1
/****************************************************************************
2
** $Id: jprocess_unix.cpp,v 1.13 2004/06/07 07:30:04 justin Exp $
4
** Implementation of QProcess class for Unix
8
** Copyright (C) 1992-2003 Trolltech AS. All rights reserved.
10
** This file is part of the kernel module of the Qt GUI Toolkit.
12
** This file may be distributed under the terms of the Q Public License
13
** as defined by Trolltech AS of Norway and appearing in the file
14
** LICENSE.QPL included in the packaging of this file.
16
** This file may be distributed and/or modified under the terms of the
17
** GNU General Public License version 2 as published by the Free Software
18
** Foundation and appearing in the file LICENSE.GPL included in the
19
** packaging of this file.
21
** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
22
** licenses may use this file in accordance with the Qt Commercial License
23
** Agreement provided with the Software.
25
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
26
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
28
** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
29
** information about Qt Commercial License Agreements.
30
** See http://www.trolltech.com/qpl/ for QPL licensing information.
31
** See http://www.trolltech.com/gpl/ for GPL licensing information.
33
** Contact info@trolltech.com if any conditions of this licensing are
36
**********************************************************************/
38
#include "qplatformdefs.h"
40
// Solaris redefines connect -> __xnet_connect with _XOPEN_SOURCE_EXTENDED.
45
//#include "qprocess.h"
50
#include "qapplication.h"
51
#include "qptrqueue.h"
53
#include "qsocketnotifier.h"
55
#include "qcleanuphandler.h"
57
#include "qguardedptr.h"
59
// table to hold callbacks -- Justin
62
void (*childStarting)(JProcess *);
66
static QPtrList<JP_CALLBACK> jp_callback_list;
68
static JP_CALLBACK *findCallback(JProcess *p)
70
QPtrListIterator<JP_CALLBACK> it(jp_callback_list);
71
for(JP_CALLBACK *cb; (cb = it.current()); ++it) {
78
static void setCallback(void (*childStarting)(JProcess *), JProcess *p)
80
JP_CALLBACK *cb = findCallback(p);
85
jp_callback_list.append(cb);
87
cb->childStarting = childStarting;
91
jp_callback_list.removeRef(cb);
97
static void callCallback(JProcess *p)
99
JP_CALLBACK *cb = findCallback(p);
101
cb->childStarting(p);
110
# define SOCK_DGRAM 1
113
# define SOCK_STREAM 2
117
//#define QT_QPROCESS_DEBUG
119
// Don't need this -- Justin
123
#endif // Q_C_CALLBACKS
125
QT_SIGNAL_RETTYPE qt_C_sigchldHnd(QT_SIGNAL_ARGS);
129
#endif // Q_C_CALLBACKS
133
class JProcessManager;
134
class JProcessPrivate
140
void closeOpenSocketsForChild();
141
void newProc( pid_t pid, JProcess *process );
143
QByteArray bufStdout;
144
QByteArray bufStderr;
146
QPtrQueue<QByteArray> stdinBuf;
148
QSocketNotifier *notifierStdin;
149
QSocketNotifier *notifierStdout;
150
QSocketNotifier *notifierStderr;
152
ssize_t stdinBufRead;
155
bool exitValuesCalculated;
156
bool socketReadCalled;
158
static JProcessManager *procManager;
161
/***********************************************************************
165
**********************************************************************/
167
The class QProcess does not necessarily map exactly to the running
168
child processes: if the process is finished, the QProcess class may still be
169
there; furthermore a user can use QProcess to start more than one process.
171
The helper-class QProc has the semantics that one instance of this class maps
172
directly to a running child process.
177
JProc( pid_t p, JProcess *proc=0 ) : pid(p), process(proc)
179
#if defined(QT_QPROCESS_DEBUG)
180
qDebug( "QProc: Constructor for pid %d and QProcess %p", pid, process );
188
#if defined(QT_QPROCESS_DEBUG)
189
qDebug( "QProc: Destructor for pid %d and QProcess %p", pid, process );
191
if ( process != 0 ) {
192
if ( process->d->notifierStdin )
193
process->d->notifierStdin->setEnabled( FALSE );
194
if ( process->d->notifierStdout )
195
process->d->notifierStdout->setEnabled( FALSE );
196
if ( process->d->notifierStderr )
197
process->d->notifierStderr->setEnabled( FALSE );
198
process->d->proc = 0;
200
if( socketStdin != 0 )
201
::close( socketStdin );
202
// ### close these sockets even on parent exit or is it better only on
203
// sigchld (but what do I have to do with them on exit then)?
204
if( socketStdout != 0 )
205
::close( socketStdout );
206
if( socketStderr != 0 )
207
::close( socketStderr );
217
/***********************************************************************
221
**********************************************************************/
222
class JProcessManager : public QObject
230
void append( JProc *p );
231
void remove( JProc *p );
237
void sigchldHnd( int );
240
struct sigaction oldactChld;
241
struct sigaction oldactPipe;
242
QPtrList<JProc> *procList;
246
void cleanupProcesses();
253
static QCleanupHandler<JProcessManager> qprocess_cleanup_procmanager;
256
#define BAILOUT close(tmpSocket);close(socketFD[1]);return -1;
257
int qnx6SocketPairReplacement (int socketFD[2]) {
259
tmpSocket = socket (AF_INET, SOCK_STREAM, 0);
262
socketFD[1] = socket(AF_INET, SOCK_STREAM, 0);
263
if (socketFD[1] == -1) { BAILOUT };
266
memset(&ipAddr, 0, sizeof(ipAddr));
267
ipAddr.sin_family = AF_INET;
268
ipAddr.sin_addr.s_addr = INADDR_ANY;
270
int socketOptions = 1;
271
setsockopt(tmpSocket, SOL_SOCKET, SO_REUSEADDR, &socketOptions, sizeof(int));
274
for (int socketIP = 2000; (socketIP < 2500) && !(found); socketIP++) {
275
ipAddr.sin_port = htons(socketIP);
276
if (bind(tmpSocket, (struct sockaddr *)&ipAddr, sizeof(ipAddr)))
280
if (listen(tmpSocket, 5)) { BAILOUT };
282
// Select non-blocking mode
283
int originalFlags = fcntl(socketFD[1], F_GETFL, 0);
284
fcntl(socketFD[1], F_SETFL, originalFlags | O_NONBLOCK);
286
// Request connection
287
if (connect(socketFD[1], (struct sockaddr*)&ipAddr, sizeof(ipAddr)))
288
if (errno != EINPROGRESS) { BAILOUT };
291
socketFD[0] = accept(tmpSocket, (struct sockaddr *)NULL, (size_t *)NULL);
292
if(socketFD[0] == -1) { BAILOUT };
297
// Restore original flags , ie return to blocking
298
fcntl(socketFD[1], F_SETFL, originalFlags);
304
JProcessManager::JProcessManager() : sn(0)
306
procList = new QPtrList<JProc>;
307
procList->setAutoDelete( TRUE );
309
// really lame workaround -- Justin
310
pollTimer = new QTimer(this);
311
connect(pollTimer, SIGNAL(timeout()), SLOT(cleanupProcesses()));
313
// The SIGCHLD handler writes to a socket to tell the manager that
314
// something happened. This is done to get the processing in sync with the
317
if ( ::socketpair( AF_UNIX, SOCK_STREAM, 0, sigchldFd ) ) {
319
if ( qnx6SocketPairReplacement (sigchldFd) ) {
324
#if defined(QT_QPROCESS_DEBUG)
325
qDebug( "QProcessManager: install socket notifier (%d)", sigchldFd[1] );
327
sn = new QSocketNotifier( sigchldFd[1],
328
QSocketNotifier::Read, this );
329
connect( sn, SIGNAL(activated(int)),
330
this, SLOT(sigchldHnd(int)) );
331
sn->setEnabled( TRUE );
334
// install a SIGCHLD handler and ignore SIGPIPE
335
struct sigaction act;
337
// NO SIGCHLD -- Justin
339
#if defined(QT_QPROCESS_DEBUG)
340
qDebug( "QProcessManager: install a SIGCHLD handler" );
342
act.sa_handler = qt_C_sigchldHnd;
343
sigemptyset( &(act.sa_mask) );
344
sigaddset( &(act.sa_mask), SIGCHLD );
345
act.sa_flags = SA_NOCLDSTOP;
346
#if defined(SA_RESTART)
347
act.sa_flags |= SA_RESTART;
349
if ( sigaction( SIGCHLD, &act, &oldactChld ) != 0 )
350
qWarning( "Error installing SIGCHLD handler" );
353
// obtain current handler
354
if ( sigaction( SIGPIPE, NULL, &act ) == 0 ) {
356
if(act.sa_handler == QT_SIGNAL_IGNORE) {
360
#if defined(QT_QPROCESS_DEBUG)
361
qDebug( "QProcessManager: install a SIGPIPE handler (SIG_IGN)" );
363
act.sa_handler = QT_SIGNAL_IGNORE;
364
sigemptyset( &(act.sa_mask) );
365
sigaddset( &(act.sa_mask), SIGPIPE );
367
if ( sigaction( SIGPIPE, &act, &oldactPipe ) != 0 )
368
qWarning( "Error installing SIGPIPE handler" );
372
pollTimer->start(100);
375
JProcessManager::~JProcessManager()
379
if ( sigchldFd[0] != 0 )
380
::close( sigchldFd[0] );
381
if ( sigchldFd[1] != 0 )
382
::close( sigchldFd[1] );
384
// NO SIGCHLD -- Justin
386
// restore SIGCHLD handler
387
#if defined(QT_QPROCESS_DEBUG)
388
qDebug( "QProcessManager: restore old sigchild handler" );
390
if ( sigaction( SIGCHLD, &oldactChld, 0 ) != 0 )
391
qWarning( "Error restoring SIGCHLD handler" );
394
// NO SIGPIPE restore (we might trash the one from QProcess)
396
#if defined(QT_QPROCESS_DEBUG)
397
qDebug( "QProcessManager: restore old sigpipe handler" );
399
if ( sigaction( SIGPIPE, &oldactPipe, 0 ) != 0 )
400
qWarning( "Error restoring SIGPIPE handler" );
404
void JProcessManager::append( JProc *p )
406
procList->append( p );
407
#if defined(QT_QPROCESS_DEBUG)
408
qDebug( "QProcessManager: append process (procList.count(): %d)", procList->count() );
412
void JProcessManager::remove( JProc *p )
414
procList->remove( p );
415
#if defined(QT_QPROCESS_DEBUG)
416
qDebug( "QProcessManager: remove process (procList.count(): %d)", procList->count() );
421
void JProcessManager::cleanup()
423
if ( procList->count() == 0 ) {
424
QTimer::singleShot( 0, this, SLOT(removeMe()) );
428
void JProcessManager::removeMe()
430
if ( procList->count() == 0 ) {
431
qprocess_cleanup_procmanager.remove( &JProcessPrivate::procManager );
432
JProcessPrivate::procManager = 0;
437
void JProcessManager::sigchldHnd( int fd )
439
// Disable the socket notifier to make sure that this function is not
440
// called recursively -- this can happen, if you enter the event loop in
441
// the slot connected to the processExited() signal (e.g. by showing a
442
// modal dialog) and there are more than one process which exited in the
445
sn->setEnabled( FALSE );
448
::read( fd, &tmp, sizeof(tmp) );
449
#if defined(QT_QPROCESS_DEBUG)
450
qDebug( "QProcessManager::sigchldHnd()" );
455
proc = procList->first();
456
while ( proc != 0 ) {
458
process = proc->process;
459
if ( process != 0 ) {
460
if ( !process->isRunning() ) {
461
#if defined(QT_QPROCESS_DEBUG)
462
qDebug( "QProcessManager::sigchldHnd() (PID: %d): process exited (QProcess available)", proc->pid );
465
Apparently, there is not consistency among different
466
operating systems on how to use FIONREAD.
468
FreeBSD, Linux and Solaris all expect the 3rd
469
argument to ioctl() to be an int, which is normally
470
32-bit even on 64-bit machines.
472
IRIX, on the other hand, expects a size_t, which is
473
64-bit on 64-bit machines.
475
So, the solution is to use size_t initialized to
476
zero to make sure all bits are set to zero,
477
preventing underflow with the FreeBSD/Linux/Solaris
482
if ( ::ioctl(proc->socketStdout, FIONREAD, (char*)&nbytes)==0 && nbytes>0 ) {
483
#if defined(QT_QPROCESS_DEBUG)
484
qDebug( "QProcessManager::sigchldHnd() (PID: %d): reading %d bytes of pending data on stdout", proc->pid, nbytes );
486
process->socketRead( proc->socketStdout );
489
if ( ::ioctl(proc->socketStderr, FIONREAD, (char*)&nbytes)==0 && nbytes>0 ) {
490
#if defined(QT_QPROCESS_DEBUG)
491
qDebug( "QProcessManager::sigchldHnd() (PID: %d): reading %d bytes of pending data on stderr", proc->pid, nbytes );
493
process->socketRead( proc->socketStderr );
496
if ( process->notifyOnExit )
497
emit process->processExited();
503
if ( ::waitpid( proc->pid, &status, WNOHANG ) == proc->pid ) {
504
#if defined(QT_QPROCESS_DEBUG)
505
qDebug( "QProcessManager::sigchldHnd() (PID: %d): process exited (QProcess not available)", proc->pid );
511
JProc *oldproc = proc;
512
proc = procList->next();
515
proc = procList->next();
519
sn->setEnabled( TRUE );
522
void JProcessManager::cleanupProcesses()
524
if ( JProcessPrivate::procManager == 0 )
526
if ( JProcessPrivate::procManager->sigchldFd[0] == 0 )
530
::write( JProcessPrivate::procManager->sigchldFd[0], &a, sizeof(a) );
533
#include "jprocess_unix.moc"
536
/***********************************************************************
540
**********************************************************************/
541
JProcessManager *JProcessPrivate::procManager = 0;
543
JProcessPrivate::JProcessPrivate()
545
#if defined(QT_QPROCESS_DEBUG)
546
qDebug( "QProcessPrivate: Constructor" );
554
exitValuesCalculated = FALSE;
555
socketReadCalled = FALSE;
560
JProcessPrivate::~JProcessPrivate()
562
#if defined(QT_QPROCESS_DEBUG)
563
qDebug( "QProcessPrivate: Destructor" );
567
if ( proc->socketStdin != 0 ) {
568
::close( proc->socketStdin );
569
proc->socketStdin = 0;
574
while ( !stdinBuf.isEmpty() ) {
575
delete stdinBuf.dequeue();
577
delete notifierStdin;
578
delete notifierStdout;
579
delete notifierStderr;
583
Closes all open sockets in the child process that are not needed by the child
584
process. Otherwise one child may have an open socket on standard input, etc.
587
void JProcessPrivate::closeOpenSocketsForChild()
589
if ( procManager != 0 ) {
590
if ( procManager->sigchldFd[0] != 0 )
591
::close( procManager->sigchldFd[0] );
592
if ( procManager->sigchldFd[1] != 0 )
593
::close( procManager->sigchldFd[1] );
595
// close also the sockets from other QProcess instances
596
for ( JProc *p=procManager->procList->first(); p!=0; p=procManager->procList->next() ) {
597
::close( p->socketStdin );
598
::close( p->socketStdout );
599
::close( p->socketStderr );
604
void JProcessPrivate::newProc( pid_t pid, JProcess *process )
606
proc = new JProc( pid, process );
607
if ( procManager == 0 ) {
608
procManager = new JProcessManager;
609
qprocess_cleanup_procmanager.add( &procManager );
611
// the QProcessManager takes care of deleting the QProc instances
612
procManager->append( proc );
615
/***********************************************************************
617
* sigchld handler callback
619
**********************************************************************/
620
// Don't need this -- Justin
621
/*QT_SIGNAL_RETTYPE qt_C_sigchldHnd( QT_SIGNAL_ARGS )
623
if ( JProcessPrivate::procManager == 0 )
625
if ( JProcessPrivate::procManager->sigchldFd[0] == 0 )
629
::write( JProcessPrivate::procManager->sigchldFd[0], &a, sizeof(a) );
632
/***********************************************************************
636
**********************************************************************/
638
This private class does basic initialization.
640
void JProcess::init()
642
d = new JProcessPrivate();
648
This private class resets the process variables, etc. so that it can be used
649
for another process to start.
651
void JProcess::reset()
654
d = new JProcessPrivate();
657
d->bufStdout.resize( 0 );
658
d->bufStderr.resize( 0 );
661
QByteArray* JProcess::bufStdout()
663
if ( d->proc && d->proc->socketStdout ) {
665
Apparently, there is not consistency among different
666
operating systems on how to use FIONREAD.
668
FreeBSD, Linux and Solaris all expect the 3rd argument to
669
ioctl() to be an int, which is normally 32-bit even on
672
IRIX, on the other hand, expects a size_t, which is 64-bit
675
So, the solution is to use size_t initialized to zero to
676
make sure all bits are set to zero, preventing underflow
677
with the FreeBSD/Linux/Solaris ioctls.
680
if ( ::ioctl(d->proc->socketStdout, FIONREAD, (char*)&nbytes)==0 && nbytes>0 )
681
socketRead( d->proc->socketStdout );
683
return &d->bufStdout;
686
QByteArray* JProcess::bufStderr()
688
if ( d->proc && d->proc->socketStderr ) {
690
Apparently, there is not consistency among different
691
operating systems on how to use FIONREAD.
693
FreeBSD, Linux and Solaris all expect the 3rd argument to
694
ioctl() to be an int, which is normally 32-bit even on
697
IRIX, on the other hand, expects a size_t, which is 64-bit
700
So, the solution is to use size_t initialized to zero to
701
make sure all bits are set to zero, preventing underflow
702
with the FreeBSD/Linux/Solaris ioctls.
705
if ( ::ioctl(d->proc->socketStderr, FIONREAD, (char*)&nbytes)==0 && nbytes>0 )
706
socketRead( d->proc->socketStderr );
708
return &d->bufStderr;
711
void JProcess::consumeBufStdout( int consume )
713
uint n = d->bufStdout.size();
714
if ( consume==-1 || (uint)consume >= n ) {
715
d->bufStdout.resize( 0 );
717
QByteArray tmp( n - consume );
718
memcpy( tmp.data(), d->bufStdout.data()+consume, n-consume );
723
void JProcess::consumeBufStderr( int consume )
725
uint n = d->bufStderr.size();
726
if ( consume==-1 || (uint)consume >= n ) {
727
d->bufStderr.resize( 0 );
729
QByteArray tmp( n - consume );
730
memcpy( tmp.data(), d->bufStderr.data()+consume, n-consume );
736
Destroys the instance.
738
If the process is running, it is <b>not</b> terminated! The
739
standard input, standard output and standard error of the process
742
You can connect the destroyed() signal to the kill() slot, if you
743
want the process to be terminated automatically when the instance
746
\sa tryTerminate() kill()
748
JProcess::~JProcess()
750
setCallback(0, this);
755
Tries to run a process for the command and arguments that were
756
specified with setArguments(), addArgument() or that were
757
specified in the constructor. The command is searched for in the
758
path for executable programs; you can also use an absolute path in
761
If \a env is null, then the process is started with the same
762
environment as the starting process. If \a env is non-null, then
763
the values in the stringlist are interpreted as environment
764
setttings of the form \c {key=value} and the process is started in
765
these environment settings. For convenience, there is a small
766
exception to this rule: under Unix, if \a env does not contain any
767
settings for the environment variable \c LD_LIBRARY_PATH, then
768
this variable is inherited from the starting process; under
769
Windows the same applies for the environment variable \c PATH.
771
Returns TRUE if the process could be started; otherwise returns
774
You can write data to the process's standard input with
775
writeToStdin(). You can close standard input with closeStdin() and
776
you can terminate the process with tryTerminate(), or with kill().
778
You can call this function even if you've used this instance to
779
create a another process which is still running. In such cases,
780
QProcess closes the old process's standard input and deletes
781
pending data, i.e., you lose all control over the old process, but
782
the old process is not terminated. This applies also if the
783
process could not be started. (On operating systems that have
784
zombie processes, Qt will also wait() on the old process.)
786
\sa launch() closeStdin()
788
bool JProcess::start( QStringList *env )
790
#if defined(QT_QPROCESS_DEBUG)
791
qDebug( "QProcess::start()" );
799
// open sockets for piping
801
if ( (comms & Stdin) && ::socketpair( AF_UNIX, SOCK_STREAM, 0, sStdin ) == -1 ) {
803
if ( (comms & Stdin) && qnx6SocketPairReplacement(sStdin) == -1 ) {
808
if ( (comms & Stderr) && ::socketpair( AF_UNIX, SOCK_STREAM, 0, sStderr ) == -1 ) {
810
if ( (comms & Stderr) && qnx6SocketPairReplacement(sStderr) == -1 ) {
815
if ( (comms & Stdout) && ::socketpair( AF_UNIX, SOCK_STREAM, 0, sStdout ) == -1 ) {
817
if ( (comms & Stdout) && qnx6SocketPairReplacement(sStdout) == -1 ) {
822
// the following pipe is only used to determine if the process could be
825
if ( pipe( fd ) < 0 ) {
826
// non critical error, go on
831
// construct the arguments for exec
832
QCString *arglistQ = new QCString[ _arguments.count() + 1 ];
833
const char** arglist = new const char*[ _arguments.count() + 1 ];
835
for ( QStringList::Iterator it = _arguments.begin(); it != _arguments.end(); ++it ) {
836
arglistQ[i] = (*it).local8Bit();
837
arglist[i] = arglistQ[i];
838
#if defined(QT_QPROCESS_DEBUG)
839
qDebug( "QProcess::start(): arg %d = %s", i, arglist[i] );
845
// Must make sure signal handlers are installed before exec'ing
846
// in case the process exits quickly.
847
if ( d->procManager == 0 ) {
848
d->procManager = new JProcessManager;
849
qprocess_cleanup_procmanager.add( &d->procManager );
853
QApplication::flushX();
858
d->closeOpenSocketsForChild();
859
if ( comms & Stdin ) {
860
::close( sStdin[1] );
861
::dup2( sStdin[0], STDIN_FILENO );
863
if ( comms & Stdout ) {
864
::close( sStdout[0] );
865
::dup2( sStdout[1], STDOUT_FILENO );
867
if ( comms & Stderr ) {
868
::close( sStderr[0] );
869
::dup2( sStderr[1], STDERR_FILENO );
871
if ( comms & DupStderr ) {
872
::dup2( STDOUT_FILENO, STDERR_FILENO );
875
::chdir( workingDir.absPath().latin1() );
880
::fcntl( fd[1], F_SETFD, FD_CLOEXEC ); // close on exec shows sucess
882
if ( env == 0 ) { // inherit environment and start process
883
QString command = _arguments[0];
884
#if defined(Q_OS_MACX) //look in a bundle
885
const QString mac_bundle_suffix = ".app/Contents/MacOS/";
886
if(!QFile::exists(command) && QFile::exists(command + mac_bundle_suffix)) {
887
QString exec = command;
888
int lslash = command.findRev('/');
890
exec = command.mid(lslash+1);
891
QFileInfo fileInfo( command + mac_bundle_suffix + exec );
892
if ( fileInfo.isExecutable() )
893
command = fileInfo.absFilePath().local8Bit();
897
::execvp( command, (char*const*)arglist ); // ### cast not nice
899
::execvp( command, (char const*const*)arglist ); // ### cast not nice
901
} else { // start process with environment settins as specified in env
902
// construct the environment for exec
903
int numEntries = env->count();
904
#if defined(Q_OS_MACX)
905
QString ld_library_path("DYLD_LIBRARY_PATH");
907
QString ld_library_path("LD_LIBRARY_PATH");
909
bool setLibraryPath =
910
env->grep( QRegExp( "^" + ld_library_path + "=" ) ).empty() &&
911
getenv( ld_library_path ) != 0;
912
if ( setLibraryPath )
914
QCString *envlistQ = new QCString[ numEntries + 1 ];
915
const char** envlist = new const char*[ numEntries + 1 ];
917
if ( setLibraryPath ) {
918
envlistQ[i] = QString( ld_library_path + "=%1" ).arg( getenv( ld_library_path ) ).local8Bit();
919
envlist[i] = envlistQ[i];
922
for ( QStringList::Iterator it = env->begin(); it != env->end(); ++it ) {
923
envlistQ[i] = (*it).local8Bit();
924
envlist[i] = envlistQ[i];
929
// look for the executable in the search path
930
if ( _arguments.count()>0 && getenv("PATH")!=0 ) {
931
QString command = _arguments[0];
932
if ( !command.contains( '/' ) ) {
933
QStringList pathList = QStringList::split( ':', getenv( "PATH" ) );
934
for (QStringList::Iterator it = pathList.begin(); it != pathList.end(); ++it ) {
936
#if defined(Q_OS_MACX) //look in a bundle
937
if(!QFile::exists(dir + "/" + command) && QFile::exists(dir + "/" + command + ".app"))
938
dir += "/" + command + ".app/Contents/MacOS";
941
QFileInfo fileInfo( dir, command );
943
QFileInfo fileInfo( dir + "/" + command );
945
if ( fileInfo.isExecutable() ) {
946
#if defined(Q_OS_MACX)
947
arglistQ[0] = fileInfo.absFilePath().local8Bit();
949
arglistQ[0] = fileInfo.filePath().local8Bit();
951
arglist[0] = arglistQ[0];
957
#if defined(Q_OS_MACX)
958
if(!QFile::exists(arglist[0])) {
959
QString command = arglist[0];
960
const QString mac_bundle_suffix = ".app/Contents/MacOS/";
961
if(QFile::exists(command + mac_bundle_suffix)) {
962
QString exec = command;
963
int lslash = command.findRev('/');
965
exec = command.mid(lslash+1);
966
QFileInfo fileInfo( command + mac_bundle_suffix + exec );
967
if ( fileInfo.isExecutable() ) {
968
arglistQ[0] = fileInfo.absFilePath().local8Bit();
969
arglist[0] = arglistQ[0];
975
::execve( arglist[0], (char*const*)arglist, (char*const*)envlist ); // ### casts not nice
977
::execve( arglist[0], (char const*const*)arglist,(char const*const*)envlist ); // ### casts not nice
982
::write( fd[1], &buf, 1 );
986
} else if ( pid == -1 ) {
991
// test if exec was successful
997
int n = ::read( fd[0], &buf, 1 );
999
// socket was not closed => error
1000
::waitpid( pid, 0, WNOHANG );
1003
} else if ( n==-1 ) {
1004
if ( errno==EAGAIN || errno==EINTR )
1013
d->newProc( pid, this );
1015
if ( comms & Stdin ) {
1016
::close( sStdin[0] );
1017
d->proc->socketStdin = sStdin[1];
1019
// Select non-blocking mode
1020
int originalFlags = fcntl(d->proc->socketStdin, F_GETFL, 0);
1021
fcntl(d->proc->socketStdin, F_SETFL, originalFlags | O_NONBLOCK);
1023
d->notifierStdin = new QSocketNotifier( sStdin[1], QSocketNotifier::Write );
1024
connect( d->notifierStdin, SIGNAL(activated(int)),
1025
this, SLOT(socketWrite(int)) );
1026
// setup notifiers for the sockets
1027
if ( !d->stdinBuf.isEmpty() ) {
1028
d->notifierStdin->setEnabled( TRUE );
1031
if ( comms & Stdout ) {
1032
::close( sStdout[1] );
1033
d->proc->socketStdout = sStdout[0];
1034
d->notifierStdout = new QSocketNotifier( sStdout[0], QSocketNotifier::Read );
1035
connect( d->notifierStdout, SIGNAL(activated(int)),
1036
this, SLOT(socketRead(int)) );
1037
if ( ioRedirection )
1038
d->notifierStdout->setEnabled( TRUE );
1040
if ( comms & Stderr ) {
1041
::close( sStderr[1] );
1042
d->proc->socketStderr = sStderr[0];
1043
d->notifierStderr = new QSocketNotifier( sStderr[0], QSocketNotifier::Read );
1044
connect( d->notifierStderr, SIGNAL(activated(int)),
1045
this, SLOT(socketRead(int)) );
1046
if ( ioRedirection )
1047
d->notifierStderr->setEnabled( TRUE );
1050
// cleanup and return
1056
#if defined(QT_QPROCESS_DEBUG)
1057
qDebug( "QProcess::start(): error starting process" );
1059
if ( d->procManager )
1060
d->procManager->cleanup();
1061
if ( comms & Stdin ) {
1062
::close( sStdin[1] );
1063
::close( sStdin[0] );
1065
if ( comms & Stdout ) {
1066
::close( sStdout[0] );
1067
::close( sStdout[1] );
1069
if ( comms & Stderr ) {
1070
::close( sStderr[0] );
1071
::close( sStderr[1] );
1082
Asks the process to terminate. Processes can ignore this if they
1083
wish. If you want to be certain that the process really
1084
terminates, you can use kill() instead.
1086
The slot returns immediately: it does not wait until the process
1087
has finished. When the process terminates, the processExited()
1090
\sa kill() processExited()
1092
void JProcess::tryTerminate() const
1095
::kill( d->proc->pid, SIGTERM );
1099
Terminates the process. This is not a safe way to end a process
1100
since the process will not be able to do any cleanup.
1101
tryTerminate() is safer, but processes can ignore a
1104
The nice way to end a process and to be sure that it is finished,
1105
is to do something like this:
1107
process->tryTerminate();
1108
QTimer::singleShot( 5000, process, SLOT( kill() ) );
1111
This tries to terminate the process the nice way. If the process
1112
is still running after 5 seconds, it terminates the process the
1113
hard way. The timeout should be chosen depending on the time the
1114
process needs to do all its cleanup: use a higher value if the
1115
process is likely to do a lot of computation or I/O on cleanup.
1117
The slot returns immediately: it does not wait until the process
1118
has finished. When the process terminates, the processExited()
1121
\sa tryTerminate() processExited()
1123
void JProcess::kill() const
1126
::kill( d->proc->pid, SIGKILL );
1130
Returns TRUE if the process is running; otherwise returns FALSE.
1132
\sa normalExit() exitStatus() processExited()
1134
bool JProcess::isRunning() const
1136
if ( d->exitValuesCalculated ) {
1137
#if defined(QT_QPROCESS_DEBUG)
1138
qDebug( "QProcess::isRunning(): FALSE (already computed)" );
1145
if ( ::waitpid( d->proc->pid, &status, WNOHANG ) == d->proc->pid )
1147
// compute the exit values
1148
JProcess *that = (JProcess*)this; // mutable
1149
that->exitNormal = WIFEXITED( status ) != 0;
1151
that->exitStat = (char)WEXITSTATUS( status );
1153
d->exitValuesCalculated = TRUE;
1155
// On heavy processing, the socket notifier for the sigchild might not
1156
// have found time to fire yet.
1157
if ( d->procManager ) {
1161
FD_SET( d->procManager->sigchldFd[1], &fds );
1164
while ( ::select( d->procManager->sigchldFd[1]+1, &fds, 0, 0, &tv ) > 0 )
1165
d->procManager->sigchldHnd( d->procManager->sigchldFd[1] );
1168
#if defined(QT_QPROCESS_DEBUG)
1169
qDebug( "QProcess::isRunning() (PID: %d): FALSE", d->proc->pid );
1173
#if defined(QT_QPROCESS_DEBUG)
1174
qDebug( "QProcess::isRunning() (PID: %d): TRUE", d->proc->pid );
1180
Returns TRUE if it's possible to read an entire line of text from
1181
standard output at this time; otherwise returns FALSE.
1183
\sa readLineStdout() canReadLineStderr()
1185
bool JProcess::canReadLineStdout() const
1187
if ( !d->proc || !d->proc->socketStdout )
1188
return !d->bufStdout.isEmpty();
1190
JProcess *that = (JProcess*)this;
1191
return that->scanNewline( TRUE, 0 );
1195
Returns TRUE if it's possible to read an entire line of text from
1196
standard error at this time; otherwise returns FALSE.
1198
\sa readLineStderr() canReadLineStdout()
1200
bool JProcess::canReadLineStderr() const
1202
if ( !d->proc || !d->proc->socketStderr )
1203
return !d->bufStderr.isEmpty();
1205
JProcess *that = (JProcess*)this;
1206
return that->scanNewline( FALSE, 0 );
1210
Writes the data \a buf to the process's standard input. The
1211
process may or may not read this data.
1213
This function returns immediately; the QProcess class might write
1214
the data at a later point (you must enter the event loop for this
1215
to occur). When all the data is written to the process, the signal
1216
wroteToStdin() is emitted. This does not mean that the process
1217
actually read the data, since this class only detects when it was
1218
able to write the data to the operating system.
1220
\sa wroteToStdin() closeStdin() readStdout() readStderr()
1222
void JProcess::writeToStdin( const QByteArray& buf )
1224
#if defined(QT_QPROCESS_DEBUG)
1225
// qDebug( "QProcess::writeToStdin(): write to stdin (%d)", d->socketStdin );
1227
d->stdinBuf.enqueue( new QByteArray(buf) );
1228
if ( d->notifierStdin != 0 )
1229
d->notifierStdin->setEnabled( TRUE );
1234
Closes the process's standard input.
1236
This function also deletes any pending data that has not been
1237
written to standard input.
1241
void JProcess::closeStdin()
1245
if ( d->proc->socketStdin !=0 ) {
1246
while ( !d->stdinBuf.isEmpty() ) {
1247
delete d->stdinBuf.dequeue();
1249
delete d->notifierStdin;
1250
d->notifierStdin = 0;
1251
if ( ::close( d->proc->socketStdin ) != 0 ) {
1252
qWarning( "Could not close stdin of child process" );
1254
#if defined(QT_QPROCESS_DEBUG)
1255
qDebug( "QProcess::closeStdin(): stdin (%d) closed", d->proc->socketStdin );
1257
d->proc->socketStdin = 0;
1263
This private slot is called when the process has outputted data to either
1264
standard output or standard error.
1266
void JProcess::socketRead( int fd )
1268
if ( d->socketReadCalled ) {
1269
// the slots that are connected to the readyRead...() signals might
1270
// trigger a recursive call of socketRead(). Avoid this since you get a
1271
// blocking read otherwise.
1275
#if defined(QT_QPROCESS_DEBUG)
1276
qDebug( "QProcess::socketRead(): %d", fd );
1280
const int bufsize = 4096;
1281
QByteArray *buffer = 0;
1284
if ( fd == d->proc->socketStdout ) {
1285
buffer = &d->bufStdout;
1286
} else if ( fd == d->proc->socketStderr ) {
1287
buffer = &d->bufStderr;
1289
// this case should never happen, but just to be safe
1293
// try to read data first (if it fails, the filedescriptor was closed)
1294
oldSize = buffer->size();
1295
buffer->resize( oldSize + bufsize );
1296
n = ::read( fd, buffer->data()+oldSize, bufsize );
1298
buffer->resize( oldSize + n );
1300
buffer->resize( oldSize );
1302
if ( n == 0 || n == -1 ) {
1303
if ( fd == d->proc->socketStdout ) {
1304
#if defined(QT_QPROCESS_DEBUG)
1305
qDebug( "QProcess::socketRead(): stdout (%d) closed", fd );
1307
d->notifierStdout->setEnabled( FALSE );
1308
delete d->notifierStdout;
1309
d->notifierStdout = 0;
1310
::close( d->proc->socketStdout );
1311
d->proc->socketStdout = 0;
1313
} else if ( fd == d->proc->socketStderr ) {
1314
#if defined(QT_QPROCESS_DEBUG)
1315
qDebug( "QProcess::socketRead(): stderr (%d) closed", fd );
1317
d->notifierStderr->setEnabled( FALSE );
1318
delete d->notifierStderr;
1319
d->notifierStderr = 0;
1320
::close( d->proc->socketStderr );
1321
d->proc->socketStderr = 0;
1332
while ( ::select( fd+1, &fds, 0, 0, &tv ) > 0 ) {
1333
// prepare for the next round
1337
oldSize = buffer->size();
1338
buffer->resize( oldSize + bufsize );
1339
n = ::read( fd, buffer->data()+oldSize, bufsize );
1341
buffer->resize( oldSize + n );
1343
buffer->resize( oldSize );
1348
d->socketReadCalled = TRUE;
1349
if ( fd == d->proc->socketStdout ) {
1350
#if defined(QT_QPROCESS_DEBUG)
1351
qDebug( "QProcess::socketRead(): %d bytes read from stdout (%d)",
1352
buffer->size()-oldSize, fd );
1354
emit readyReadStdout();
1355
} else if ( fd == d->proc->socketStderr ) {
1356
#if defined(QT_QPROCESS_DEBUG)
1357
qDebug( "QProcess::socketRead(): %d bytes read from stderr (%d)",
1358
buffer->size()-oldSize, fd );
1360
emit readyReadStderr();
1362
d->socketReadCalled = FALSE;
1367
This private slot is called when the process tries to read data from standard
1370
void JProcess::socketWrite( int fd )
1372
while ( fd == d->proc->socketStdin && d->proc->socketStdin != 0 ) {
1373
if ( d->stdinBuf.isEmpty() ) {
1374
d->notifierStdin->setEnabled( FALSE );
1377
ssize_t ret = ::write( fd,
1378
d->stdinBuf.head()->data() + d->stdinBufRead,
1379
d->stdinBuf.head()->size() - d->stdinBufRead );
1380
#if defined(QT_QPROCESS_DEBUG)
1381
qDebug( "QProcess::socketWrite(): wrote %d bytes to stdin (%d)", ret, fd );
1385
d->stdinBufRead += ret;
1386
if ( d->stdinBufRead == (ssize_t)d->stdinBuf.head()->size() ) {
1387
d->stdinBufRead = 0;
1388
delete d->stdinBuf.dequeue();
1389
if ( wroteToStdinConnected && d->stdinBuf.isEmpty() )
1390
emit wroteToStdin();
1397
Flushes standard input. This is useful if you want to use QProcess in a
1400
This function should probably go into the public API.
1402
void JProcess::flushStdin()
1404
socketWrite( d->proc->socketStdin );
1408
This private slot is only used under Windows (but moc does not know about #if
1411
void JProcess::timeout()
1417
This private function is used by connectNotify() and disconnectNotify() to
1418
change the value of ioRedirection (and related behaviour)
1420
void JProcess::setIoRedirection( bool value )
1422
ioRedirection = value;
1423
if ( ioRedirection ) {
1424
if ( d->notifierStdout )
1425
d->notifierStdout->setEnabled( TRUE );
1426
if ( d->notifierStderr )
1427
d->notifierStderr->setEnabled( TRUE );
1429
if ( d->notifierStdout )
1430
d->notifierStdout->setEnabled( FALSE );
1431
if ( d->notifierStderr )
1432
d->notifierStderr->setEnabled( FALSE );
1437
This private function is used by connectNotify() and
1438
disconnectNotify() to change the value of notifyOnExit (and related
1441
void JProcess::setNotifyOnExit( bool value )
1443
notifyOnExit = value;
1447
This private function is used by connectNotify() and disconnectNotify() to
1448
change the value of wroteToStdinConnected (and related behaviour)
1450
void JProcess::setWroteStdinConnected( bool value )
1452
wroteToStdinConnected = value;
1455
/*! \enum QProcess::PID
1459
Returns platform dependent information about the process. This can
1460
be used together with platform specific system calls.
1462
Under Unix the return value is the PID of the process, or -1 if no
1463
process is belongs to this object.
1465
Under Windows it is a pointer to the \c PROCESS_INFORMATION
1466
struct, or 0 if no process is belongs to this object.
1468
Use of this function's return value is likely to be non-portable.
1470
JProcess::PID JProcess::processIdentifier()
1474
return d->proc->pid;
1477
void JProcess::setChildStartingHandler(void (*childStarting)(JProcess *))
1479
setCallback(childStarting, this);
1482
#endif // QT_NO_PROCESS