00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #if defined(connect)
00023 #undef connect
00024 #endif
00025
00026 #include "qprocess.h"
00027
00028
00029 #include <opie2/odebug.h>
00030 using namespace Opie::Core;
00031
00032
00033 #ifndef QT_NO_PROCESS
00034 #include <qapplication.h>
00035 #include <qqueue.h>
00036 #include <qlist.h>
00037 #include <qsocketnotifier.h>
00038 #include <qtimer.h>
00039 #include <qregexp.h>
00040
00041 #include "qcleanuphandler_p.h"
00042
00043
00044 #include <stdlib.h>
00045 #include <unistd.h>
00046 #include <signal.h>
00047 #include <sys/socket.h>
00048 #include <sys/ioctl.h>
00049 #include <sys/wait.h>
00050 #include <sys/fcntl.h>
00051 #include <errno.h>
00052 #ifdef Q_OS_MACX
00053 #include <sys/time.h>
00054 #endif
00055 #include <sys/resource.h>
00056
00057 #ifdef __MIPSEL__
00058 # ifndef SOCK_DGRAM
00059 # define SOCK_DGRAM 1
00060 # endif
00061 # ifndef SOCK_STREAM
00062 # define SOCK_STREAM 2
00063 # endif
00064 #endif
00065
00066
00067
00068
00069 #ifdef Q_C_CALLBACKS
00070 extern "C" {
00071 #endif // Q_C_CALLBACKS
00072
00073 #define QT_SIGNAL_RETTYPE void
00074 #define QT_SIGNAL_ARGS int
00075 #define QT_SIGNAL_IGNORE SIG_IGN
00076
00077 QT_SIGNAL_RETTYPE qt_C_sigchldHnd(QT_SIGNAL_ARGS);
00078 QT_SIGNAL_RETTYPE qt_C_sigpipeHnd(QT_SIGNAL_ARGS);
00079
00080 #ifdef Q_C_CALLBACKS
00081 }
00082 #endif // Q_C_CALLBACKS
00083
00084
00085 class QProc;
00086 class QProcessManager;
00087 class QProcessPrivate
00088 {
00089 public:
00090 QProcessPrivate();
00091 ~QProcessPrivate();
00092
00093 void closeOpenSocketsForChild();
00094 void newProc( pid_t pid, QProcess *process );
00095
00096 QByteArray bufStdout;
00097 QByteArray bufStderr;
00098
00099 QQueue<QByteArray> stdinBuf;
00100
00101 QSocketNotifier *notifierStdin;
00102 QSocketNotifier *notifierStdout;
00103 QSocketNotifier *notifierStderr;
00104
00105 ssize_t stdinBufRead;
00106 QProc *proc;
00107
00108 bool exitValuesCalculated;
00109 bool socketReadCalled;
00110
00111 static QProcessManager *procManager;
00112 };
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128 class QProc
00129 {
00130 public:
00131 QProc( pid_t p, QProcess *proc=0 ) : pid(p), process(proc)
00132 {
00133 #if defined(QT_QPROCESS_DEBUG)
00134 odebug << "QProc: Constructor for pid " << pid << " and QProcess " << process << "" << oendl;
00135 #endif
00136 socketStdin = 0;
00137 socketStdout = 0;
00138 socketStderr = 0;
00139 }
00140 ~QProc()
00141 {
00142 #if defined(QT_QPROCESS_DEBUG)
00143 odebug << "QProc: Destructor for pid " << pid << " and QProcess " << process << "" << oendl;
00144 #endif
00145 if ( process != 0 ) {
00146 if ( process->d->notifierStdin )
00147 process->d->notifierStdin->setEnabled( FALSE );
00148 if ( process->d->notifierStdout )
00149 process->d->notifierStdout->setEnabled( FALSE );
00150 if ( process->d->notifierStderr )
00151 process->d->notifierStderr->setEnabled( FALSE );
00152 process->d->proc = 0;
00153 }
00154 if( socketStdin != 0 )
00155 ::close( socketStdin );
00156
00157
00158 if( socketStdout != 0 )
00159 ::close( socketStdout );
00160 if( socketStderr != 0 )
00161 ::close( socketStderr );
00162 }
00163
00164 pid_t pid;
00165 int socketStdin;
00166 int socketStdout;
00167 int socketStderr;
00168 QProcess *process;
00169 };
00170
00171
00172
00173
00174
00175
00176 class QProcessManager : public QObject
00177 {
00178 Q_OBJECT
00179
00180 public:
00181 QProcessManager();
00182 ~QProcessManager();
00183
00184 void append( QProc *p );
00185 void remove( QProc *p );
00186
00187 void cleanup();
00188
00189 public slots:
00190 void removeMe();
00191 void sigchldHnd( int );
00192
00193 public:
00194 struct sigaction oldactChld;
00195 struct sigaction oldactPipe;
00196 QList<QProc> *procList;
00197 int sigchldFd[2];
00198 };
00199
00200 QCleanupHandler<QProcessManager> qprocess_cleanup_procmanager;
00201
00202 QProcessManager::QProcessManager()
00203 {
00204 procList = new QList<QProc>;
00205 procList->setAutoDelete( TRUE );
00206
00207
00208
00209
00210 if ( ::socketpair( AF_UNIX, SOCK_STREAM, 0, sigchldFd ) ) {
00211 sigchldFd[0] = 0;
00212 sigchldFd[1] = 0;
00213 } else {
00214 #if defined(QT_QPROCESS_DEBUG)
00215 odebug << "QProcessManager: install socket notifier (" << sigchldFd[1] << ")" << oendl;
00216 #endif
00217 QSocketNotifier *sn = new QSocketNotifier( sigchldFd[1],
00218 QSocketNotifier::Read, this );
00219 connect( sn, SIGNAL(activated(int)),
00220 this, SLOT(sigchldHnd(int)) );
00221 sn->setEnabled( TRUE );
00222 }
00223
00224
00225 struct sigaction act;
00226
00227 #if defined(QT_QPROCESS_DEBUG)
00228 odebug << "QProcessManager: install a SIGCHLD handler" << oendl;
00229 #endif
00230 act.sa_handler = qt_C_sigchldHnd;
00231 sigemptyset( &(act.sa_mask) );
00232 sigaddset( &(act.sa_mask), SIGCHLD );
00233 act.sa_flags = SA_NOCLDSTOP;
00234 #if defined(SA_RESTART)
00235 act.sa_flags |= SA_RESTART;
00236 #endif
00237 if ( sigaction( SIGCHLD, &act, &oldactChld ) != 0 )
00238 owarn << "Error installing SIGCHLD handler" << oendl;
00239
00240 #if defined(QT_QPROCESS_DEBUG)
00241 odebug << "QProcessManager: install a SIGPIPE handler (SIG_IGN)" << oendl;
00242 #endif
00243
00244
00245
00246
00247
00248
00249 act.sa_handler = qt_C_sigpipeHnd;
00250 sigemptyset( &(act.sa_mask) );
00251 sigaddset( &(act.sa_mask), SIGPIPE );
00252 act.sa_flags = 0;
00253 if ( sigaction( SIGPIPE, &act, &oldactPipe ) != 0 )
00254 owarn << "Error installing SIGPIPE handler" << oendl;
00255 }
00256
00257 QProcessManager::~QProcessManager()
00258 {
00259 delete procList;
00260
00261 if ( sigchldFd[0] != 0 )
00262 ::close( sigchldFd[0] );
00263 if ( sigchldFd[1] != 0 )
00264 ::close( sigchldFd[1] );
00265
00266
00267 #if defined(QT_QPROCESS_DEBUG)
00268 odebug << "QProcessManager: restore old sigchild handler" << oendl;
00269 #endif
00270 if ( sigaction( SIGCHLD, &oldactChld, 0 ) != 0 )
00271 owarn << "Error restoring SIGCHLD handler" << oendl;
00272
00273 #if defined(QT_QPROCESS_DEBUG)
00274 odebug << "QProcessManager: restore old sigpipe handler" << oendl;
00275 #endif
00276 if ( sigaction( SIGPIPE, &oldactPipe, 0 ) != 0 )
00277 owarn << "Error restoring SIGPIPE handler" << oendl;
00278 }
00279
00280 void QProcessManager::append( QProc *p )
00281 {
00282 procList->append( p );
00283 #if defined(QT_QPROCESS_DEBUG)
00284 odebug << "QProcessManager: append process (procList.count(): " << procList->count() << ")" << oendl;
00285 #endif
00286 }
00287
00288 void QProcessManager::remove( QProc *p )
00289 {
00290 procList->remove( p );
00291 #if defined(QT_QPROCESS_DEBUG)
00292 odebug << "QProcessManager: remove process (procList.count(): " << procList->count() << ")" << oendl;
00293 #endif
00294 cleanup();
00295 }
00296
00297 void QProcessManager::cleanup()
00298 {
00299 if ( procList->count() == 0 ) {
00300 QTimer::singleShot( 0, this, SLOT(removeMe()) );
00301 }
00302 }
00303
00304 void QProcessManager::removeMe()
00305 {
00306 if ( procList->count() == 0 ) {
00307 qprocess_cleanup_procmanager.remove( &QProcessPrivate::procManager );
00308 QProcessPrivate::procManager = 0;
00309 delete this;
00310 }
00311 }
00312
00313 void QProcessManager::sigchldHnd( int fd )
00314 {
00315 char tmp;
00316 ::read( fd, &tmp, sizeof(tmp) );
00317 #if defined(QT_QPROCESS_DEBUG)
00318 odebug << "QProcessManager::sigchldHnd()" << oendl;
00319 #endif
00320 QProc *proc;
00321 QProcess *process;
00322 bool removeProc;
00323 proc = procList->first();
00324 while ( proc != 0 ) {
00325 removeProc = FALSE;
00326 process = proc->process;
00327 QProcess *process_exit_notify=0;
00328 if ( process != 0 ) {
00329 if ( !process->isRunning() ) {
00330 #if defined(QT_QPROCESS_DEBUG)
00331 odebug << "QProcessManager::sigchldHnd() (PID: " << proc->pid << "): process exited (QProcess available)" << oendl;
00332 #endif
00333
00334 int nbytes = 0;
00335 if ( ::ioctl(proc->socketStdout, FIONREAD, (char*)&nbytes)==0 && nbytes>0 ) {
00336 #if defined(QT_QPROCESS_DEBUG)
00337 odebug << "QProcessManager::sigchldHnd() (PID: " << proc->pid << "): reading " << nbytes << " bytes of pending data on stdout" << oendl;
00338 #endif
00339 process->socketRead( proc->socketStdout );
00340 }
00341 nbytes = 0;
00342 if ( ::ioctl(proc->socketStderr, FIONREAD, (char*)&nbytes)==0 && nbytes>0 ) {
00343 #if defined(QT_QPROCESS_DEBUG)
00344 odebug << "QProcessManager::sigchldHnd() (PID: " << proc->pid << "): reading " << nbytes << " bytes of pending data on stderr" << oendl;
00345 #endif
00346 process->socketRead( proc->socketStderr );
00347 }
00348
00349 if ( process->notifyOnExit )
00350 process_exit_notify = process;
00351
00352 removeProc = TRUE;
00353 }
00354 } else {
00355 int status;
00356 if ( ::waitpid( proc->pid, &status, WNOHANG ) == proc->pid ) {
00357 #if defined(QT_QPROCESS_DEBUG)
00358 odebug << "QProcessManager::sigchldHnd() (PID: " << proc->pid << "): process exited (QProcess not available)" << oendl;
00359 #endif
00360 removeProc = TRUE;
00361 }
00362 }
00363 if ( removeProc ) {
00364 QProc *oldproc = proc;
00365 proc = procList->next();
00366 remove( oldproc );
00367 } else {
00368 proc = procList->next();
00369 }
00370 if ( process_exit_notify )
00371 emit process_exit_notify->processExited();
00372 }
00373 }
00374
00375 #include "qprocess_unix.moc"
00376
00377
00378
00379
00380
00381
00382
00383 QProcessManager *QProcessPrivate::procManager = 0;
00384
00385 QProcessPrivate::QProcessPrivate()
00386 {
00387 #if defined(QT_QPROCESS_DEBUG)
00388 odebug << "QProcessPrivate: Constructor" << oendl;
00389 #endif
00390 stdinBufRead = 0;
00391
00392 notifierStdin = 0;
00393 notifierStdout = 0;
00394 notifierStderr = 0;
00395
00396 exitValuesCalculated = FALSE;
00397 socketReadCalled = FALSE;
00398
00399 proc = 0;
00400 }
00401
00402 QProcessPrivate::~QProcessPrivate()
00403 {
00404 #if defined(QT_QPROCESS_DEBUG)
00405 odebug << "QProcessPrivate: Destructor" << oendl;
00406 #endif
00407
00408 if ( proc != 0 ) {
00409 if ( proc->socketStdin != 0 ) {
00410 ::close( proc->socketStdin );
00411 proc->socketStdin = 0;
00412 }
00413 proc->process = 0;
00414 }
00415
00416 while ( !stdinBuf.isEmpty() ) {
00417 delete stdinBuf.dequeue();
00418 }
00419 delete notifierStdin;
00420 delete notifierStdout;
00421 delete notifierStderr;
00422 }
00423
00424
00425
00426
00427
00428
00429 void QProcessPrivate::closeOpenSocketsForChild()
00430 {
00431 if ( procManager != 0 ) {
00432 if ( procManager->sigchldFd[0] != 0 )
00433 ::close( procManager->sigchldFd[0] );
00434 if ( procManager->sigchldFd[1] != 0 )
00435 ::close( procManager->sigchldFd[1] );
00436
00437
00438 QProc *proc;
00439 for ( proc=procManager->procList->first(); proc!=0; proc=procManager->procList->next() ) {
00440 ::close( proc->socketStdin );
00441 ::close( proc->socketStdout );
00442 ::close( proc->socketStderr );
00443 }
00444 }
00445 }
00446
00447 void QProcessPrivate::newProc( pid_t pid, QProcess *process )
00448 {
00449 proc = new QProc( pid, process );
00450 if ( procManager == 0 ) {
00451 procManager = new QProcessManager;
00452 qprocess_cleanup_procmanager.add( &procManager );
00453 }
00454
00455 procManager->append( proc );
00456 }
00457
00458
00459
00460
00461
00462
00463 QT_SIGNAL_RETTYPE qt_C_sigchldHnd( QT_SIGNAL_ARGS )
00464 {
00465 if ( QProcessPrivate::procManager == 0 )
00466 return;
00467 if ( QProcessPrivate::procManager->sigchldFd[0] == 0 )
00468 return;
00469
00470 char a = 1;
00471 ::write( QProcessPrivate::procManager->sigchldFd[0], &a, sizeof(a) );
00472 }
00473 QT_SIGNAL_RETTYPE qt_C_sigpipeHnd( QT_SIGNAL_ARGS )
00474 {
00475
00476 }
00477
00478
00479
00480
00481
00482
00483
00487 void QProcess::init()
00488 {
00489 d = new QProcessPrivate();
00490 exitStat = 0;
00491 exitNormal = FALSE;
00492 }
00493
00498 void QProcess::reset()
00499 {
00500 delete d;
00501 d = new QProcessPrivate();
00502 exitStat = 0;
00503 exitNormal = FALSE;
00504 d->bufStdout.resize( 0 );
00505 d->bufStderr.resize( 0 );
00506 }
00507
00508 QByteArray* QProcess::bufStdout()
00509 {
00510 if ( d->proc && d->proc->socketStdout ) {
00511
00512
00513 socketRead( d->proc->socketStdout );
00514 }
00515 return &d->bufStdout;
00516 }
00517
00518 QByteArray* QProcess::bufStderr()
00519 {
00520 if ( d->proc && d->proc->socketStderr ) {
00521
00522
00523 socketRead( d->proc->socketStderr );
00524 }
00525 return &d->bufStderr;
00526 }
00527
00528 void QProcess::consumeBufStdout( int consume )
00529 {
00530 uint n = d->bufStdout.size();
00531 if ( consume==-1 || (uint)consume >= n ) {
00532 d->bufStdout.resize( 0 );
00533 } else {
00534 QByteArray tmp( n - consume );
00535 memcpy( tmp.data(), d->bufStdout.data()+consume, n-consume );
00536 d->bufStdout = tmp;
00537 }
00538 }
00539
00540 void QProcess::consumeBufStderr( int consume )
00541 {
00542 uint n = d->bufStderr.size();
00543 if ( consume==-1 || (uint)consume >= n ) {
00544 d->bufStderr.resize( 0 );
00545 } else {
00546 QByteArray tmp( n - consume );
00547 memcpy( tmp.data(), d->bufStderr.data()+consume, n-consume );
00548 d->bufStderr = tmp;
00549 }
00550 }
00551
00563 QProcess::~QProcess()
00564 {
00565 delete d;
00566 }
00567
00598 bool QProcess::start( QStringList *env )
00599 {
00600 #if defined(QT_QPROCESS_DEBUG)
00601 odebug << "QProcess::start()" << oendl;
00602 #endif
00603 reset();
00604
00605 int sStdin[2];
00606 int sStdout[2];
00607 int sStderr[2];
00608
00609
00610 if ( (comms & Stdin) && ::socketpair( AF_UNIX, SOCK_STREAM, 0, sStdin ) == -1 ) {
00611 return FALSE;
00612 }
00613 if ( (comms & Stderr) && ::socketpair( AF_UNIX, SOCK_STREAM, 0, sStderr ) == -1 ) {
00614 return FALSE;
00615 }
00616 if ( (comms & Stdout) && ::socketpair( AF_UNIX, SOCK_STREAM, 0, sStdout ) == -1 ) {
00617 return FALSE;
00618 }
00619
00620
00621
00622 int fd[2];
00623 if ( pipe( fd ) < 0 ) {
00624
00625 fd[0] = 0;
00626 fd[1] = 0;
00627 }
00628
00629
00630 QCString *arglistQ = new QCString[ _arguments.count() + 1 ];
00631 const char** arglist = new const char*[ _arguments.count() + 1 ];
00632 int i = 0;
00633 for ( QStringList::Iterator it = _arguments.begin(); it != _arguments.end(); ++it ) {
00634 arglistQ[i] = (*it).local8Bit();
00635 arglist[i] = arglistQ[i];
00636 #if defined(QT_QPROCESS_DEBUG)
00637 odebug << "QProcess::start(): arg " << i << " = " << arglist[i] << "" << oendl;
00638 #endif
00639 i++;
00640 }
00641 arglist[i] = 0;
00642
00643
00644
00645 if ( d->procManager == 0 ) {
00646 d->procManager = new QProcessManager;
00647 qprocess_cleanup_procmanager.add( &d->procManager );
00648 }
00649
00650
00651 QApplication::flushX();
00652 pid_t pid = fork();
00653 if ( pid == 0 ) {
00654
00655 d->closeOpenSocketsForChild();
00656 if ( comms & Stdin ) {
00657 ::close( sStdin[1] );
00658 ::dup2( sStdin[0], STDIN_FILENO );
00659 }
00660 if ( comms & Stdout ) {
00661 ::close( sStdout[0] );
00662 ::dup2( sStdout[1], STDOUT_FILENO );
00663 }
00664 if ( comms & Stderr ) {
00665 ::close( sStderr[0] );
00666 ::dup2( sStderr[1], STDERR_FILENO );
00667 }
00668 if ( comms & DupStderr ) {
00669 ::dup2( STDOUT_FILENO, STDERR_FILENO );
00670 }
00671 #ifndef QT_NO_DIR
00672 ::chdir( workingDir.absPath().latin1() );
00673 #endif
00674 if ( fd[0] )
00675 ::close( fd[0] );
00676 if ( fd[1] )
00677 ::fcntl( fd[1], F_SETFD, FD_CLOEXEC );
00678
00679 if ( env == 0 ) {
00680 ::execvp( arglist[0], (char*const*)arglist );
00681 } else {
00682
00683 int numEntries = env->count();
00684 bool setLibraryPath =
00685 env->grep( QRegExp( "^LD_LIBRARY_PATH=" ) ).isEmpty() &&
00686 getenv( "LD_LIBRARY_PATH" ) != 0;
00687 if ( setLibraryPath )
00688 numEntries++;
00689 QCString *envlistQ = new QCString[ numEntries + 1 ];
00690 const char** envlist = new const char*[ numEntries + 1 ];
00691 int i = 0;
00692 if ( setLibraryPath ) {
00693 envlistQ[i] = QString( "LD_LIBRARY_PATH=%1" ).arg( getenv( "LD_LIBRARY_PATH" ) ).local8Bit();
00694 envlist[i] = envlistQ[i];
00695 i++;
00696 }
00697 for ( QStringList::Iterator it = env->begin(); it != env->end(); ++it ) {
00698 envlistQ[i] = (*it).local8Bit();
00699 envlist[i] = envlistQ[i];
00700 i++;
00701 }
00702 envlist[i] = 0;
00703
00704
00705 if ( _arguments.count()>0 && getenv("PATH")!=0 ) {
00706 QString command = _arguments[0];
00707 if ( !command.contains( '/' ) ) {
00708 QStringList pathList = QStringList::split( ':', getenv( "PATH" ) );
00709 for (QStringList::Iterator it = pathList.begin(); it != pathList.end(); ++it ) {
00710 QString dir = *it;
00711 #ifdef Q_OS_MACX
00712 if(QFile::exists(dir + "/" + command + ".app"))
00713 dir += "/" + command + ".app/Contents/MacOS";
00714 #endif
00715 #ifndef QT_NO_DIR
00716 QFileInfo fileInfo( dir, command );
00717 #else
00718 QFileInfo fileInfo( dir + "/" + command );
00719 #endif
00720 if ( fileInfo.isExecutable() ) {
00721 arglistQ[0] = fileInfo.filePath().local8Bit();
00722 arglist[0] = arglistQ[0];
00723 break;
00724 }
00725 }
00726 }
00727 }
00728 ::execve( arglist[0], (char*const*)arglist, (char*const*)envlist );
00729 }
00730 if ( fd[1] ) {
00731 char buf = 0;
00732 ::write( fd[1], &buf, 1 );
00733 ::close( fd[1] );
00734 }
00735 ::exit( -1 );
00736 } else if ( pid == -1 ) {
00737
00738 goto error;
00739 }
00740
00741
00742 if ( fd[1] )
00743 ::close( fd[1] );
00744 if ( fd[0] ) {
00745 char buf;
00746 for ( ;; ) {
00747 int n = ::read( fd[0], &buf, 1 );
00748 if ( n==1 ) {
00749
00750 d->proc = 0;
00751 goto error;
00752 } else if ( n==-1 ) {
00753 if ( errno==EAGAIN || errno==EINTR )
00754
00755 continue;
00756 }
00757 break;
00758 }
00759 ::close( fd[0] );
00760 }
00761
00762 d->newProc( pid, this );
00763
00764 if ( comms & Stdin ) {
00765 ::close( sStdin[0] );
00766 d->proc->socketStdin = sStdin[1];
00767 d->notifierStdin = new QSocketNotifier( sStdin[1], QSocketNotifier::Write );
00768 connect( d->notifierStdin, SIGNAL(activated(int)),
00769 this, SLOT(socketWrite(int)) );
00770
00771 if ( !d->stdinBuf.isEmpty() ) {
00772 d->notifierStdin->setEnabled( TRUE );
00773 }
00774 }
00775 if ( comms & Stdout ) {
00776 ::close( sStdout[1] );
00777 d->proc->socketStdout = sStdout[0];
00778 d->notifierStdout = new QSocketNotifier( sStdout[0], QSocketNotifier::Read );
00779 connect( d->notifierStdout, SIGNAL(activated(int)),
00780 this, SLOT(socketRead(int)) );
00781 if ( ioRedirection )
00782 d->notifierStdout->setEnabled( TRUE );
00783 }
00784 if ( comms & Stderr ) {
00785 ::close( sStderr[1] );
00786 d->proc->socketStderr = sStderr[0];
00787 d->notifierStderr = new QSocketNotifier( sStderr[0], QSocketNotifier::Read );
00788 connect( d->notifierStderr, SIGNAL(activated(int)),
00789 this, SLOT(socketRead(int)) );
00790 if ( ioRedirection )
00791 d->notifierStderr->setEnabled( TRUE );
00792 }
00793
00794
00795 delete[] arglistQ;
00796 delete[] arglist;
00797 return TRUE;
00798
00799 error:
00800 #if defined(QT_QPROCESS_DEBUG)
00801 odebug << "QProcess::start(): error starting process" << oendl;
00802 #endif
00803 if ( d->procManager )
00804 d->procManager->cleanup();
00805 if ( comms & Stdin ) {
00806 ::close( sStdin[1] );
00807 ::close( sStdin[0] );
00808 }
00809 if ( comms & Stdout ) {
00810 ::close( sStdout[0] );
00811 ::close( sStdout[1] );
00812 }
00813 if ( comms & Stderr ) {
00814 ::close( sStderr[0] );
00815 ::close( sStderr[1] );
00816 }
00817 ::close( fd[0] );
00818 ::close( fd[1] );
00819 delete[] arglistQ;
00820 delete[] arglist;
00821 return FALSE;
00822 }
00823
00824
00835 void QProcess::tryTerminate() const
00836 {
00837 if ( d->proc != 0 )
00838 ::kill( d->proc->pid, SIGTERM );
00839 }
00840
00865 void QProcess::kill() const
00866 {
00867 if ( d->proc != 0 )
00868 ::kill( d->proc->pid, SIGKILL );
00869 }
00870
00876 bool QProcess::isRunning() const
00877 {
00878 if ( d->exitValuesCalculated ) {
00879 #if defined(QT_QPROCESS_DEBUG)
00880 odebug << "QProcess::isRunning(): FALSE (already computed)" << oendl;
00881 #endif
00882 return FALSE;
00883 }
00884 if ( d->proc == 0 )
00885 return FALSE;
00886 int status;
00887 if ( ::waitpid( d->proc->pid, &status, WNOHANG ) == d->proc->pid )
00888 {
00889
00890 QProcess *that = (QProcess*)this;
00891 that->exitNormal = WIFEXITED( status ) != 0;
00892 if ( exitNormal ) {
00893 that->exitStat = (char)WEXITSTATUS( status );
00894 }
00895 d->exitValuesCalculated = TRUE;
00896 #if defined(QT_QPROCESS_DEBUG)
00897 odebug << "QProcess::isRunning() (PID: " << d->proc->pid << "): FALSE" << oendl;
00898 #endif
00899 return FALSE;
00900 }
00901 #if defined(QT_QPROCESS_DEBUG)
00902 odebug << "QProcess::isRunning() (PID: " << d->proc->pid << "): TRUE" << oendl;
00903 #endif
00904 return TRUE;
00905 }
00906
00919 void QProcess::writeToStdin( const QByteArray& buf )
00920 {
00921 #if defined(QT_QPROCESS_DEBUG)
00922
00923 #endif
00924 d->stdinBuf.enqueue( new QByteArray(buf) );
00925 if ( d->notifierStdin != 0 )
00926 d->notifierStdin->setEnabled( TRUE );
00927 }
00928
00929
00938 void QProcess::closeStdin()
00939 {
00940 if ( d->proc == 0 )
00941 return;
00942 if ( d->proc->socketStdin !=0 ) {
00943 while ( !d->stdinBuf.isEmpty() ) {
00944 delete d->stdinBuf.dequeue();
00945 }
00946 delete d->notifierStdin;
00947 d->notifierStdin = 0;
00948 if ( ::close( d->proc->socketStdin ) != 0 ) {
00949 owarn << "Could not close stdin of child process" << oendl;
00950 }
00951 #if defined(QT_QPROCESS_DEBUG)
00952 odebug << "QProcess::closeStdin(): stdin (" << d->proc->socketStdin << ") closed" << oendl;
00953 #endif
00954 d->proc->socketStdin = 0;
00955 }
00956 }
00957
00958
00959
00960
00961
00962
00963 void QProcess::socketRead( int fd )
00964 {
00965 if ( d->socketReadCalled ) {
00966
00967
00968
00969 return;
00970 }
00971 #if defined(QT_QPROCESS_DEBUG)
00972 odebug << "QProcess::socketRead(): " << fd << "" << oendl;
00973 #endif
00974 if ( fd == 0 )
00975 return;
00976 const int bufsize = 4096;
00977 QByteArray *buffer = 0;
00978 uint oldSize;
00979 int n;
00980 if ( fd == d->proc->socketStdout ) {
00981 buffer = &d->bufStdout;
00982 } else if ( fd == d->proc->socketStderr ) {
00983 buffer = &d->bufStderr;
00984 } else {
00985
00986 return;
00987 }
00988
00989
00990 oldSize = buffer->size();
00991 buffer->resize( oldSize + bufsize );
00992 n = ::read( fd, buffer->data()+oldSize, bufsize );
00993 if ( n > 0 )
00994 buffer->resize( oldSize + n );
00995 else
00996 buffer->resize( oldSize );
00997
00998 if ( n == 0 || n == -1 ) {
00999 if ( fd == d->proc->socketStdout ) {
01000 #if defined(QT_QPROCESS_DEBUG)
01001 odebug << "QProcess::socketRead(): stdout (" << fd << ") closed" << oendl;
01002 #endif
01003 d->notifierStdout->setEnabled( FALSE );
01004 delete d->notifierStdout;
01005 d->notifierStdout = 0;
01006 ::close( d->proc->socketStdout );
01007 d->proc->socketStdout = 0;
01008 return;
01009 } else if ( fd == d->proc->socketStderr ) {
01010 #if defined(QT_QPROCESS_DEBUG)
01011 odebug << "QProcess::socketRead(): stderr (" << fd << ") closed" << oendl;
01012 #endif
01013 d->notifierStderr->setEnabled( FALSE );
01014 delete d->notifierStderr;
01015 d->notifierStderr = 0;
01016 ::close( d->proc->socketStderr );
01017 d->proc->socketStderr = 0;
01018 return;
01019 }
01020 }
01021
01022 while ( n == bufsize ) {
01023 oldSize = buffer->size();
01024 buffer->resize( oldSize + bufsize );
01025 n = ::read( fd, buffer->data()+oldSize, bufsize );
01026 if ( n > 0 )
01027 buffer->resize( oldSize + n );
01028 else
01029 buffer->resize( oldSize );
01030 }
01031
01032 d->socketReadCalled = TRUE;
01033 if ( fd == d->proc->socketStdout ) {
01034 #if defined(QT_QPROCESS_DEBUG)
01035 odebug << "QProcess::socketRead(): " << buffer->size()-oldSize << "bytes read from stdout ("
01036 << fd << ")" << oendl;
01037 #endif
01038 emit readyReadStdout();
01039 } else if ( fd == d->proc->socketStderr ) {
01040 #if defined(QT_QPROCESS_DEBUG)
01041 odebug << "QProcess::socketRead(): " << buffer->size()-oldSize << " bytes read from stderr ("
01042 << fd << ")" << oendl;
01043 #endif
01044 emit readyReadStderr();
01045 }
01046 d->socketReadCalled = FALSE;
01047 }
01048
01049
01050
01051
01052
01053
01054 void QProcess::socketWrite( int fd )
01055 {
01056 if ( fd != d->proc->socketStdin || d->proc->socketStdin == 0 )
01057 return;
01058 if ( d->stdinBuf.isEmpty() ) {
01059 d->notifierStdin->setEnabled( FALSE );
01060 return;
01061 }
01062 #if defined(QT_QPROCESS_DEBUG)
01063 odebug << "QProcess::socketWrite(): write to stdin (" << fd << ")" << oendl;
01064 #endif
01065 ssize_t ret = ::write( fd,
01066 d->stdinBuf.head()->data() + d->stdinBufRead,
01067 d->stdinBuf.head()->size() - d->stdinBufRead );
01068 if ( ret > 0 )
01069 d->stdinBufRead += ret;
01070 if ( d->stdinBufRead == (ssize_t)d->stdinBuf.head()->size() ) {
01071 d->stdinBufRead = 0;
01072 delete d->stdinBuf.dequeue();
01073 if ( wroteToStdinConnected && d->stdinBuf.isEmpty() )
01074 emit wroteToStdin();
01075 socketWrite( fd );
01076 }
01077 }
01078
01086 void QProcess::flushStdin()
01087 {
01088 socketWrite( d->proc->socketStdin );
01089 }
01090
01091
01092
01093
01094
01095 void QProcess::timeout()
01096 {
01097 }
01098
01099
01100
01101
01102
01103
01104 void QProcess::setIoRedirection( bool value )
01105 {
01106 ioRedirection = value;
01107 if ( ioRedirection ) {
01108 if ( d->notifierStdout )
01109 d->notifierStdout->setEnabled( TRUE );
01110 if ( d->notifierStderr )
01111 d->notifierStderr->setEnabled( TRUE );
01112 } else {
01113 if ( d->notifierStdout )
01114 d->notifierStdout->setEnabled( FALSE );
01115 if ( d->notifierStderr )
01116 d->notifierStderr->setEnabled( FALSE );
01117 }
01118 }
01119
01120
01121
01122
01123
01124
01125 void QProcess::setNotifyOnExit( bool value )
01126 {
01127 notifyOnExit = value;
01128 }
01129
01130
01131
01132
01133
01134 void QProcess::setWroteStdinConnected( bool value )
01135 {
01136 wroteToStdinConnected = value;
01137 }
01138
01152 QProcess::PID QProcess::processIdentifier()
01153 {
01154 if ( d->proc == 0 )
01155 return -1;
01156 return d->proc->pid;
01157 }
01158
01159 int QProcess::priority() const
01160 {
01161 if ( d->proc )
01162 return getpriority(PRIO_PROCESS,d->proc->pid);
01163 return 0;
01164 }
01165
01166 void QProcess::setPriority(int p)
01167 {
01168 if ( d->proc )
01169 setpriority(PRIO_PROCESS,d->proc->pid,p);
01170 }
01171
01172
01173 #endif // QT_NO_PROCESS