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