X-Git-Url: http://code.vuplus.com/gitweb/?a=blobdiff_plain;f=lib%2Fbase%2Fconsole.cpp;h=6dc21d2ecf99be30a191b3e16d6a7b6c501546e5;hb=654bb0a0f8583b7cbc47b32f7e9b6921dffc4e03;hp=a29772d8fac00a54d3453a67b2239f8fb9f5eea0;hpb=1c4d458b5df83facce7cf71b39ab247eb1447491;p=vuplus_dvbapp diff --git a/lib/base/console.cpp b/lib/base/console.cpp index a29772d..6dc21d2 100644 --- a/lib/base/console.cpp +++ b/lib/base/console.cpp @@ -7,8 +7,9 @@ #include #include #include +#include -int bidirpipe(int pfd[], const char *cmd , const char * const argv[]) +int bidirpipe(int pfd[], const char *cmd , const char * const argv[], const char *cwd ) { int pfdin[2]; /* from child to parent */ int pfdout[2]; /* from parent to child */ @@ -37,6 +38,9 @@ int bidirpipe(int pfd[], const char *cmd , const char * const argv[]) for (unsigned int i=3; i < 90; ++i ) close(i); + if (cwd) + chdir(cwd); + execvp(cmd, (char * const *)argv); /* the vfork will actually suspend the parent thread until execvp is called. thus it's ok to use the shared arg/cmdline pointers here. */ _exit(0); @@ -55,7 +59,10 @@ eConsoleAppContainer::eConsoleAppContainer() :pid(-1), killstate(0), in(0), out(0), err(0) { for (int i=0; i < 3; ++i) + { fd[i]=-1; + filefd[i]=-1; + } } static char brakets[][2] = { @@ -79,6 +86,20 @@ static char *find_bracket(char ch) return NULL; } +int eConsoleAppContainer::setCWD( const char *path ) +{ + struct stat dir_stat; + + if (stat(path, &dir_stat) == -1) + return -1; + + if (!S_ISDIR(dir_stat.st_mode)) + return -2; + + m_cwd = path; + return 0; +} + int eConsoleAppContainer::execute( const char *cmd ) { int cnt=0, slen=strlen(cmd); @@ -157,13 +178,15 @@ int eConsoleAppContainer::execute(const char *cmdline, const char * const argv[] killstate=0; // get one read ,one write and the err pipe to the prog.. - pid = bidirpipe(fd, cmdline, argv); + pid = bidirpipe(fd, cmdline, argv, m_cwd.length() ? m_cwd.c_str() : 0); if ( pid == -1 ) return -3; // eDebug("pipe in = %d, out = %d, err = %d", fd[0], fd[1], fd[2]); + ::fcntl(fd[1], F_SETFL, O_NONBLOCK); + ::fcntl(fd[2], F_SETFL, O_NONBLOCK); in = new eSocketNotifier(eApp, fd[0], eSocketNotifier::Read|eSocketNotifier::Priority|eSocketNotifier::Hungup ); out = new eSocketNotifier(eApp, fd[1], eSocketNotifier::Write, false); err = new eSocketNotifier(eApp, fd[2], eSocketNotifier::Read|eSocketNotifier::Priority ); @@ -224,6 +247,12 @@ void eConsoleAppContainer::kill() delete out; delete err; in=out=err=0; + + for (int i=0; i < 3; ++i) + { + if ( filefd[i] > 0 ) + close(filefd[i]); + } } void eConsoleAppContainer::sendCtrlC() @@ -278,18 +307,20 @@ void eConsoleAppContainer::readyRead(int what) if (what & (eSocketNotifier::Priority|eSocketNotifier::Read)) { // eDebug("what = %d"); - char buf[2048]; + char buf[2049]; int rd; - while((rd = read(fd[0], buf, 2047)) > 0) + while((rd = read(fd[0], buf, 2048)) > 0) { -/* for ( int i = 0; i < rd; i++ ) - eDebug("%d = %c (%02x)", i, buf[i], buf[i] );*/ buf[rd]=0; /*emit*/ dataAvail(buf); + stdoutAvail(buf); + if ( filefd[1] > 0 ) + ::write(filefd[1], buf, rd); if (!hungup) break; } } + readyErrRead(eSocketNotifier::Priority|eSocketNotifier::Read); /* be sure to flush all data which might be already written */ if (hungup) { eDebug("child has terminated"); @@ -316,18 +347,37 @@ void eConsoleAppContainer::readyErrRead(int what) if (what & (eSocketNotifier::Priority|eSocketNotifier::Read)) { // eDebug("what = %d"); - char buf[2048]; + char buf[2049]; int rd; - while((rd = read(fd[2], buf, 2047)) > 0) + while((rd = read(fd[2], buf, 2048)) > 0) { /* for ( int i = 0; i < rd; i++ ) eDebug("%d = %c (%02x)", i, buf[i], buf[i] );*/ buf[rd]=0; /*emit*/ dataAvail(buf); + stderrAvail(buf); } } } +void eConsoleAppContainer::dumpToFile( PyObject *py_filename ) +{ + char *filename = PyString_AsString(py_filename); + filefd[1] = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0644); + eDebug("eConsoleAppContainer::dumpToFile open(%s, O_WRONLY|O_CREAT|O_TRUNC, 0644)=%i", filename, filefd[1]); +} + +void eConsoleAppContainer::readFromFile( PyObject *py_filename ) +{ + char *filename = PyString_AsString(py_filename); + char readbuf[32*1024]; + filefd[0] = open(filename, O_RDONLY); + int rsize = read(filefd[0], readbuf, 32*1024); + eDebug("eConsoleAppContainer::readFromFile open(%s, O_RDONLY)=%i, read: %i", filename, filefd[0], rsize); + if ( filefd[0] > 0 && rsize > 0 ) + write(readbuf, rsize); +} + void eConsoleAppContainer::write( const char *data, int len ) { char *tmp = new char[len]; @@ -351,20 +401,40 @@ void eConsoleAppContainer::readyWrite(int what) { if (what&eSocketNotifier::Write && outbuf.size() ) { - queue_data d = outbuf.front(); - outbuf.pop(); - if ( ::write( fd[1], d.data, d.len ) != d.len ) - { - /* emit */ dataSent(-1); -// eDebug("writeError"); - } + queue_data &d = outbuf.front(); + int wr = ::write( fd[1], d.data+d.dataSent, d.len-d.dataSent ); + if (wr < 0) + eDebug("eConsoleAppContainer write failed (%m)"); else + d.dataSent += wr; + if (d.dataSent == d.len) { + outbuf.pop(); + delete [] d.data; + if ( filefd[0] == -1 ) /* emit */ dataSent(0); -// eDebug("write ok"); } - delete [] d.data; } if ( !outbuf.size() ) - out->stop(); + { + if ( filefd[0] > 0 ) + { + char readbuf[32*1024]; + int rsize = read(filefd[0], readbuf, 32*1024); + if ( rsize > 0 ) + write(readbuf, rsize); + else + { + close(filefd[0]); + filefd[0] = -1; + ::close(fd[1]); + eDebug("readFromFile done - closing eConsoleAppContainer stdin pipe"); + fd[1]=-1; + dataSent(0); + out->stop(); + } + } + else + out->stop(); + } }