summaryrefslogtreecommitdiff
path: root/core/launcher/qprocess_unix.cpp
Side-by-side diff
Diffstat (limited to 'core/launcher/qprocess_unix.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--core/launcher/qprocess_unix.cpp646
1 files changed, 323 insertions, 323 deletions
diff --git a/core/launcher/qprocess_unix.cpp b/core/launcher/qprocess_unix.cpp
index 56e1b1d..97c0460 100644
--- a/core/launcher/qprocess_unix.cpp
+++ b/core/launcher/qprocess_unix.cpp
@@ -124,50 +124,50 @@ public:
The helper-class QProc has the semantics that one instance of this class maps
directly to a running child process.
*/
class QProc
{
public:
QProc( pid_t p, QProcess *proc=0 ) : pid(p), process(proc)
{
#if defined(QT_QPROCESS_DEBUG)
odebug << "QProc: Constructor for pid " << pid << " and QProcess " << process << "" << oendl;
#endif
- socketStdin = 0;
- socketStdout = 0;
- socketStderr = 0;
+ socketStdin = 0;
+ socketStdout = 0;
+ socketStderr = 0;
}
~QProc()
{
#if defined(QT_QPROCESS_DEBUG)
odebug << "QProc: Destructor for pid " << pid << " and QProcess " << process << "" << oendl;
#endif
- if ( process != 0 ) {
- if ( process->d->notifierStdin )
- process->d->notifierStdin->setEnabled( FALSE );
- if ( process->d->notifierStdout )
- process->d->notifierStdout->setEnabled( FALSE );
- if ( process->d->notifierStderr )
- process->d->notifierStderr->setEnabled( FALSE );
- process->d->proc = 0;
- }
- if( socketStdin != 0 )
- ::close( socketStdin );
- // ### close these sockets even on parent exit or is it better only on
- // sigchld (but what do I have to do with them on exit then)?
- if( socketStdout != 0 )
- ::close( socketStdout );
- if( socketStderr != 0 )
- ::close( socketStderr );
+ if ( process != 0 ) {
+ if ( process->d->notifierStdin )
+ process->d->notifierStdin->setEnabled( FALSE );
+ if ( process->d->notifierStdout )
+ process->d->notifierStdout->setEnabled( FALSE );
+ if ( process->d->notifierStderr )
+ process->d->notifierStderr->setEnabled( FALSE );
+ process->d->proc = 0;
+ }
+ if( socketStdin != 0 )
+ ::close( socketStdin );
+ // ### close these sockets even on parent exit or is it better only on
+ // sigchld (but what do I have to do with them on exit then)?
+ if( socketStdout != 0 )
+ ::close( socketStdout );
+ if( socketStderr != 0 )
+ ::close( socketStderr );
}
pid_t pid;
int socketStdin;
int socketStdout;
int socketStderr;
QProcess *process;
};
/***********************************************************************
*
* QProcessManager
@@ -199,78 +199,78 @@ public:
QCleanupHandler<QProcessManager> qprocess_cleanup_procmanager;
QProcessManager::QProcessManager()
{
procList = new QList<QProc>;
procList->setAutoDelete( TRUE );
// The SIGCHLD handler writes to a socket to tell the manager that
// something happened. This is done to get the processing in sync with the
// event reporting.
if ( ::socketpair( AF_UNIX, SOCK_STREAM, 0, sigchldFd ) ) {
- sigchldFd[0] = 0;
- sigchldFd[1] = 0;
+ sigchldFd[0] = 0;
+ sigchldFd[1] = 0;
} else {
#if defined(QT_QPROCESS_DEBUG)
odebug << "QProcessManager: install socket notifier (" << sigchldFd[1] << ")" << oendl;
#endif
- QSocketNotifier *sn = new QSocketNotifier( sigchldFd[1],
- QSocketNotifier::Read, this );
- connect( sn, SIGNAL(activated(int)),
- this, SLOT(sigchldHnd(int)) );
- sn->setEnabled( TRUE );
+ QSocketNotifier *sn = new QSocketNotifier( sigchldFd[1],
+ QSocketNotifier::Read, this );
+ connect( sn, SIGNAL(activated(int)),
+ this, SLOT(sigchldHnd(int)) );
+ sn->setEnabled( TRUE );
}
// install a SIGCHLD handler and ignore SIGPIPE
struct sigaction act;
#if defined(QT_QPROCESS_DEBUG)
odebug << "QProcessManager: install a SIGCHLD handler" << oendl;
#endif
act.sa_handler = qt_C_sigchldHnd;
sigemptyset( &(act.sa_mask) );
sigaddset( &(act.sa_mask), SIGCHLD );
act.sa_flags = SA_NOCLDSTOP;
#if defined(SA_RESTART)
act.sa_flags |= SA_RESTART;
#endif
if ( sigaction( SIGCHLD, &act, &oldactChld ) != 0 )
owarn << "Error installing SIGCHLD handler" << oendl;
#if defined(QT_QPROCESS_DEBUG)
odebug << "QProcessManager: install a SIGPIPE handler (SIG_IGN)" << oendl;
#endif
/*
- Using qt_C_sigpipeHnd rather than SIG_IGN is a workaround
- for a strange problem where GNU tar (called by backuprestore)
- would hang on filesystem-full. Strangely, the qt_C_sigpipeHnd
- is never even called, yet this avoids the hang.
+ Using qt_C_sigpipeHnd rather than SIG_IGN is a workaround
+ for a strange problem where GNU tar (called by backuprestore)
+ would hang on filesystem-full. Strangely, the qt_C_sigpipeHnd
+ is never even called, yet this avoids the hang.
*/
act.sa_handler = qt_C_sigpipeHnd;
sigemptyset( &(act.sa_mask) );
sigaddset( &(act.sa_mask), SIGPIPE );
act.sa_flags = 0;
if ( sigaction( SIGPIPE, &act, &oldactPipe ) != 0 )
owarn << "Error installing SIGPIPE handler" << oendl;
}
QProcessManager::~QProcessManager()
{
delete procList;
if ( sigchldFd[0] != 0 )
- ::close( sigchldFd[0] );
+ ::close( sigchldFd[0] );
if ( sigchldFd[1] != 0 )
- ::close( sigchldFd[1] );
+ ::close( sigchldFd[1] );
// restore SIGCHLD handler
#if defined(QT_QPROCESS_DEBUG)
odebug << "QProcessManager: restore old sigchild handler" << oendl;
#endif
if ( sigaction( SIGCHLD, &oldactChld, 0 ) != 0 )
owarn << "Error restoring SIGCHLD handler" << oendl;
#if defined(QT_QPROCESS_DEBUG)
odebug << "QProcessManager: restore old sigpipe handler" << oendl;
#endif
if ( sigaction( SIGPIPE, &oldactPipe, 0 ) != 0 )
@@ -288,96 +288,96 @@ void QProcessManager::append( QProc *p )
void QProcessManager::remove( QProc *p )
{
procList->remove( p );
#if defined(QT_QPROCESS_DEBUG)
odebug << "QProcessManager: remove process (procList.count(): " << procList->count() << ")" << oendl;
#endif
cleanup();
}
void QProcessManager::cleanup()
{
if ( procList->count() == 0 ) {
- QTimer::singleShot( 0, this, SLOT(removeMe()) );
+ QTimer::singleShot( 0, this, SLOT(removeMe()) );
}
}
void QProcessManager::removeMe()
{
if ( procList->count() == 0 ) {
- qprocess_cleanup_procmanager.remove( &QProcessPrivate::procManager );
- QProcessPrivate::procManager = 0;
- delete this;
+ qprocess_cleanup_procmanager.remove( &QProcessPrivate::procManager );
+ QProcessPrivate::procManager = 0;
+ delete this;
}
}
void QProcessManager::sigchldHnd( int fd )
{
char tmp;
::read( fd, &tmp, sizeof(tmp) );
#if defined(QT_QPROCESS_DEBUG)
odebug << "QProcessManager::sigchldHnd()" << oendl;
#endif
QProc *proc;
QProcess *process;
bool removeProc;
proc = procList->first();
while ( proc != 0 ) {
- removeProc = FALSE;
- process = proc->process;
- QProcess *process_exit_notify=0;
- if ( process != 0 ) {
- if ( !process->isRunning() ) {
+ removeProc = FALSE;
+ process = proc->process;
+ QProcess *process_exit_notify=0;
+ if ( process != 0 ) {
+ if ( !process->isRunning() ) {
#if defined(QT_QPROCESS_DEBUG)
odebug << "QProcessManager::sigchldHnd() (PID: " << proc->pid << "): process exited (QProcess available)" << oendl;
#endif
- // read pending data
- int nbytes = 0;
- if ( ::ioctl(proc->socketStdout, FIONREAD, (char*)&nbytes)==0 && nbytes>0 ) {
+ // read pending data
+ int nbytes = 0;
+ if ( ::ioctl(proc->socketStdout, FIONREAD, (char*)&nbytes)==0 && nbytes>0 ) {
#if defined(QT_QPROCESS_DEBUG)
odebug << "QProcessManager::sigchldHnd() (PID: " << proc->pid << "): reading " << nbytes << " bytes of pending data on stdout" << oendl;
#endif
- process->socketRead( proc->socketStdout );
- }
- nbytes = 0;
- if ( ::ioctl(proc->socketStderr, FIONREAD, (char*)&nbytes)==0 && nbytes>0 ) {
+ process->socketRead( proc->socketStdout );
+ }
+ nbytes = 0;
+ if ( ::ioctl(proc->socketStderr, FIONREAD, (char*)&nbytes)==0 && nbytes>0 ) {
#if defined(QT_QPROCESS_DEBUG)
odebug << "QProcessManager::sigchldHnd() (PID: " << proc->pid << "): reading " << nbytes << " bytes of pending data on stderr" << oendl;
#endif
- process->socketRead( proc->socketStderr );
- }
+ process->socketRead( proc->socketStderr );
+ }
- if ( process->notifyOnExit )
- process_exit_notify = process;
+ if ( process->notifyOnExit )
+ process_exit_notify = process;
- removeProc = TRUE;
- }
- } else {
- int status;
- if ( ::waitpid( proc->pid, &status, WNOHANG ) == proc->pid ) {
+ removeProc = TRUE;
+ }
+ } else {
+ int status;
+ if ( ::waitpid( proc->pid, &status, WNOHANG ) == proc->pid ) {
#if defined(QT_QPROCESS_DEBUG)
odebug << "QProcessManager::sigchldHnd() (PID: " << proc->pid << "): process exited (QProcess not available)" << oendl;
#endif
- removeProc = TRUE;
- }
- }
- if ( removeProc ) {
- QProc *oldproc = proc;
- proc = procList->next();
- remove( oldproc );
- } else {
- proc = procList->next();
- }
- if ( process_exit_notify )
- emit process_exit_notify->processExited();
+ removeProc = TRUE;
+ }
+ }
+ if ( removeProc ) {
+ QProc *oldproc = proc;
+ proc = procList->next();
+ remove( oldproc );
+ } else {
+ proc = procList->next();
+ }
+ if ( process_exit_notify )
+ emit process_exit_notify->processExited();
}
}
#include "qprocess_unix.moc"
/***********************************************************************
*
* QProcessPrivate
*
**********************************************************************/
QProcessManager *QProcessPrivate::procManager = 0;
@@ -397,84 +397,84 @@ QProcessPrivate::QProcessPrivate()
socketReadCalled = FALSE;
proc = 0;
}
QProcessPrivate::~QProcessPrivate()
{
#if defined(QT_QPROCESS_DEBUG)
odebug << "QProcessPrivate: Destructor" << oendl;
#endif
if ( proc != 0 ) {
- if ( proc->socketStdin != 0 ) {
- ::close( proc->socketStdin );
- proc->socketStdin = 0;
- }
- proc->process = 0;
+ if ( proc->socketStdin != 0 ) {
+ ::close( proc->socketStdin );
+ proc->socketStdin = 0;
+ }
+ proc->process = 0;
}
while ( !stdinBuf.isEmpty() ) {
- delete stdinBuf.dequeue();
+ delete stdinBuf.dequeue();
}
delete notifierStdin;
delete notifierStdout;
delete notifierStderr;
}
/*
Closes all open sockets in the child process that are not needed by the child
process. Otherwise one child may have an open socket on standard input, etc.
of another child.
*/
void QProcessPrivate::closeOpenSocketsForChild()
{
if ( procManager != 0 ) {
- if ( procManager->sigchldFd[0] != 0 )
- ::close( procManager->sigchldFd[0] );
- if ( procManager->sigchldFd[1] != 0 )
- ::close( procManager->sigchldFd[1] );
-
- // close also the sockets from other QProcess instances
- QProc *proc;
- for ( proc=procManager->procList->first(); proc!=0; proc=procManager->procList->next() ) {
- ::close( proc->socketStdin );
- ::close( proc->socketStdout );
- ::close( proc->socketStderr );
- }
+ if ( procManager->sigchldFd[0] != 0 )
+ ::close( procManager->sigchldFd[0] );
+ if ( procManager->sigchldFd[1] != 0 )
+ ::close( procManager->sigchldFd[1] );
+
+ // close also the sockets from other QProcess instances
+ QProc *proc;
+ for ( proc=procManager->procList->first(); proc!=0; proc=procManager->procList->next() ) {
+ ::close( proc->socketStdin );
+ ::close( proc->socketStdout );
+ ::close( proc->socketStderr );
+ }
}
}
void QProcessPrivate::newProc( pid_t pid, QProcess *process )
{
proc = new QProc( pid, process );
if ( procManager == 0 ) {
- procManager = new QProcessManager;
- qprocess_cleanup_procmanager.add( &procManager );
+ procManager = new QProcessManager;
+ qprocess_cleanup_procmanager.add( &procManager );
}
// the QProcessManager takes care of deleting the QProc instances
procManager->append( proc );
}
/***********************************************************************
*
* sigchld handler callback
*
**********************************************************************/
QT_SIGNAL_RETTYPE qt_C_sigchldHnd( QT_SIGNAL_ARGS )
{
if ( QProcessPrivate::procManager == 0 )
- return;
+ return;
if ( QProcessPrivate::procManager->sigchldFd[0] == 0 )
- return;
+ return;
char a = 1;
::write( QProcessPrivate::procManager->sigchldFd[0], &a, sizeof(a) );
}
QT_SIGNAL_RETTYPE qt_C_sigpipeHnd( QT_SIGNAL_ARGS )
{
// Ignore (but in a way somehow different to SIG_IGN).
}
/***********************************************************************
*
@@ -499,62 +499,62 @@ void QProcess::reset()
{
delete d;
d = new QProcessPrivate();
exitStat = 0;
exitNormal = FALSE;
d->bufStdout.resize( 0 );
d->bufStderr.resize( 0 );
}
QByteArray* QProcess::bufStdout()
{
if ( d->proc && d->proc->socketStdout ) {
- // ### can this cause a blocking behaviour (maybe do a ioctl() to see
- // if data is available)?
- socketRead( d->proc->socketStdout );
+ // ### can this cause a blocking behaviour (maybe do a ioctl() to see
+ // if data is available)?
+ socketRead( d->proc->socketStdout );
}
return &d->bufStdout;
}
QByteArray* QProcess::bufStderr()
{
if ( d->proc && d->proc->socketStderr ) {
- // ### can this cause a blocking behaviour (maybe do a ioctl() to see
- // if data is available)?
- socketRead( d->proc->socketStderr );
+ // ### can this cause a blocking behaviour (maybe do a ioctl() to see
+ // if data is available)?
+ socketRead( d->proc->socketStderr );
}
return &d->bufStderr;
}
void QProcess::consumeBufStdout( int consume )
{
uint n = d->bufStdout.size();
if ( consume==-1 || (uint)consume >= n ) {
- d->bufStdout.resize( 0 );
+ d->bufStdout.resize( 0 );
} else {
- QByteArray tmp( n - consume );
- memcpy( tmp.data(), d->bufStdout.data()+consume, n-consume );
- d->bufStdout = tmp;
+ QByteArray tmp( n - consume );
+ memcpy( tmp.data(), d->bufStdout.data()+consume, n-consume );
+ d->bufStdout = tmp;
}
}
void QProcess::consumeBufStderr( int consume )
{
uint n = d->bufStderr.size();
if ( consume==-1 || (uint)consume >= n ) {
- d->bufStderr.resize( 0 );
+ d->bufStderr.resize( 0 );
} else {
- QByteArray tmp( n - consume );
- memcpy( tmp.data(), d->bufStderr.data()+consume, n-consume );
- d->bufStderr = tmp;
+ QByteArray tmp( n - consume );
+ memcpy( tmp.data(), d->bufStderr.data()+consume, n-consume );
+ d->bufStderr = tmp;
}
}
/*!
Destroys the class.
If the process is running, it is NOT terminated! Standard input, standard
output and standard error of the process are closed.
You can connect the destroyed() signal to the kill() slot, if you want the
process to be terminated automatically when the class is destroyed.
@@ -599,252 +599,252 @@ bool QProcess::start( QStringList *env )
{
#if defined(QT_QPROCESS_DEBUG)
odebug << "QProcess::start()" << oendl;
#endif
reset();
int sStdin[2];
int sStdout[2];
int sStderr[2];
// open sockets for piping
if ( (comms & Stdin) && ::socketpair( AF_UNIX, SOCK_STREAM, 0, sStdin ) == -1 ) {
- return FALSE;
+ return FALSE;
}
if ( (comms & Stderr) && ::socketpair( AF_UNIX, SOCK_STREAM, 0, sStderr ) == -1 ) {
- return FALSE;
+ return FALSE;
}
if ( (comms & Stdout) && ::socketpair( AF_UNIX, SOCK_STREAM, 0, sStdout ) == -1 ) {
- return FALSE;
+ return FALSE;
}
// the following pipe is only used to determine if the process could be
// started
int fd[2];
if ( pipe( fd ) < 0 ) {
- // non critical error, go on
- fd[0] = 0;
- fd[1] = 0;
+ // non critical error, go on
+ fd[0] = 0;
+ fd[1] = 0;
}
// construct the arguments for exec
QCString *arglistQ = new QCString[ _arguments.count() + 1 ];
const char** arglist = new const char*[ _arguments.count() + 1 ];
int i = 0;
for ( QStringList::Iterator it = _arguments.begin(); it != _arguments.end(); ++it ) {
- arglistQ[i] = (*it).local8Bit();
- arglist[i] = arglistQ[i];
+ arglistQ[i] = (*it).local8Bit();
+ arglist[i] = arglistQ[i];
#if defined(QT_QPROCESS_DEBUG)
odebug << "QProcess::start(): arg " << i << " = " << arglist[i] << "" << oendl;
#endif
- i++;
+ i++;
}
arglist[i] = 0;
// Must make sure signal handlers are installed before exec'ing
// in case the process exits quickly.
if ( d->procManager == 0 ) {
- d->procManager = new QProcessManager;
- qprocess_cleanup_procmanager.add( &d->procManager );
+ d->procManager = new QProcessManager;
+ qprocess_cleanup_procmanager.add( &d->procManager );
}
// fork and exec
QApplication::flushX();
pid_t pid = fork();
if ( pid == 0 ) {
- // child
- d->closeOpenSocketsForChild();
- if ( comms & Stdin ) {
- ::close( sStdin[1] );
- ::dup2( sStdin[0], STDIN_FILENO );
- }
- if ( comms & Stdout ) {
- ::close( sStdout[0] );
- ::dup2( sStdout[1], STDOUT_FILENO );
- }
- if ( comms & Stderr ) {
- ::close( sStderr[0] );
- ::dup2( sStderr[1], STDERR_FILENO );
- }
- if ( comms & DupStderr ) {
- ::dup2( STDOUT_FILENO, STDERR_FILENO );
- }
+ // child
+ d->closeOpenSocketsForChild();
+ if ( comms & Stdin ) {
+ ::close( sStdin[1] );
+ ::dup2( sStdin[0], STDIN_FILENO );
+ }
+ if ( comms & Stdout ) {
+ ::close( sStdout[0] );
+ ::dup2( sStdout[1], STDOUT_FILENO );
+ }
+ if ( comms & Stderr ) {
+ ::close( sStderr[0] );
+ ::dup2( sStderr[1], STDERR_FILENO );
+ }
+ if ( comms & DupStderr ) {
+ ::dup2( STDOUT_FILENO, STDERR_FILENO );
+ }
#ifndef QT_NO_DIR
- ::chdir( workingDir.absPath().latin1() );
+ ::chdir( workingDir.absPath().latin1() );
#endif
- if ( fd[0] )
- ::close( fd[0] );
- if ( fd[1] )
- ::fcntl( fd[1], F_SETFD, FD_CLOEXEC ); // close on exec shows sucess
-
- if ( env == 0 ) { // inherit environment and start process
- ::execvp( arglist[0], (char*const*)arglist ); // ### cast not nice
- } else { // start process with environment settins as specified in env
- // construct the environment for exec
- int numEntries = env->count();
- bool setLibraryPath =
- env->grep( QRegExp( "^LD_LIBRARY_PATH=" ) ).isEmpty() &&
- getenv( "LD_LIBRARY_PATH" ) != 0;
- if ( setLibraryPath )
- numEntries++;
- QCString *envlistQ = new QCString[ numEntries + 1 ];
- const char** envlist = new const char*[ numEntries + 1 ];
- int i = 0;
- if ( setLibraryPath ) {
- envlistQ[i] = QString( "LD_LIBRARY_PATH=%1" ).arg( getenv( "LD_LIBRARY_PATH" ) ).local8Bit();
- envlist[i] = envlistQ[i];
- i++;
- }
- for ( QStringList::Iterator it = env->begin(); it != env->end(); ++it ) {
- envlistQ[i] = (*it).local8Bit();
- envlist[i] = envlistQ[i];
- i++;
- }
- envlist[i] = 0;
-
- // look for the executable in the search path
- if ( _arguments.count()>0 && getenv("PATH")!=0 ) {
- QString command = _arguments[0];
- if ( !command.contains( '/' ) ) {
- QStringList pathList = QStringList::split( ':', getenv( "PATH" ) );
- for (QStringList::Iterator it = pathList.begin(); it != pathList.end(); ++it ) {
- QString dir = *it;
+ if ( fd[0] )
+ ::close( fd[0] );
+ if ( fd[1] )
+ ::fcntl( fd[1], F_SETFD, FD_CLOEXEC ); // close on exec shows sucess
+
+ if ( env == 0 ) { // inherit environment and start process
+ ::execvp( arglist[0], (char*const*)arglist ); // ### cast not nice
+ } else { // start process with environment settins as specified in env
+ // construct the environment for exec
+ int numEntries = env->count();
+ bool setLibraryPath =
+ env->grep( QRegExp( "^LD_LIBRARY_PATH=" ) ).isEmpty() &&
+ getenv( "LD_LIBRARY_PATH" ) != 0;
+ if ( setLibraryPath )
+ numEntries++;
+ QCString *envlistQ = new QCString[ numEntries + 1 ];
+ const char** envlist = new const char*[ numEntries + 1 ];
+ int i = 0;
+ if ( setLibraryPath ) {
+ envlistQ[i] = QString( "LD_LIBRARY_PATH=%1" ).arg( getenv( "LD_LIBRARY_PATH" ) ).local8Bit();
+ envlist[i] = envlistQ[i];
+ i++;
+ }
+ for ( QStringList::Iterator it = env->begin(); it != env->end(); ++it ) {
+ envlistQ[i] = (*it).local8Bit();
+ envlist[i] = envlistQ[i];
+ i++;
+ }
+ envlist[i] = 0;
+
+ // look for the executable in the search path
+ if ( _arguments.count()>0 && getenv("PATH")!=0 ) {
+ QString command = _arguments[0];
+ if ( !command.contains( '/' ) ) {
+ QStringList pathList = QStringList::split( ':', getenv( "PATH" ) );
+ for (QStringList::Iterator it = pathList.begin(); it != pathList.end(); ++it ) {
+ QString dir = *it;
#ifdef Q_OS_MACX
- if(QFile::exists(dir + "/" + command + ".app")) //look in a bundle
- dir += "/" + command + ".app/Contents/MacOS";
+ if(QFile::exists(dir + "/" + command + ".app")) //look in a bundle
+ dir += "/" + command + ".app/Contents/MacOS";
#endif
#ifndef QT_NO_DIR
- QFileInfo fileInfo( dir, command );
+ QFileInfo fileInfo( dir, command );
#else
- QFileInfo fileInfo( dir + "/" + command );
+ QFileInfo fileInfo( dir + "/" + command );
#endif
- if ( fileInfo.isExecutable() ) {
- arglistQ[0] = fileInfo.filePath().local8Bit();
- arglist[0] = arglistQ[0];
- break;
- }
- }
- }
- }
- ::execve( arglist[0], (char*const*)arglist, (char*const*)envlist ); // ### casts not nice
- }
- if ( fd[1] ) {
- char buf = 0;
- ::write( fd[1], &buf, 1 );
- ::close( fd[1] );
- }
- ::exit( -1 );
+ if ( fileInfo.isExecutable() ) {
+ arglistQ[0] = fileInfo.filePath().local8Bit();
+ arglist[0] = arglistQ[0];
+ break;
+ }
+ }
+ }
+ }
+ ::execve( arglist[0], (char*const*)arglist, (char*const*)envlist ); // ### casts not nice
+ }
+ if ( fd[1] ) {
+ char buf = 0;
+ ::write( fd[1], &buf, 1 );
+ ::close( fd[1] );
+ }
+ ::exit( -1 );
} else if ( pid == -1 ) {
- // error forking
- goto error;
+ // error forking
+ goto error;
}
// test if exec was successful
if ( fd[1] )
- ::close( fd[1] );
+ ::close( fd[1] );
if ( fd[0] ) {
- char buf;
- for ( ;; ) {
- int n = ::read( fd[0], &buf, 1 );
- if ( n==1 ) {
- // socket was not closed => error
- d->proc = 0;
- goto error;
- } else if ( n==-1 ) {
- if ( errno==EAGAIN || errno==EINTR )
- // try it again
- continue;
- }
- break;
- }
- ::close( fd[0] );
+ char buf;
+ for ( ;; ) {
+ int n = ::read( fd[0], &buf, 1 );
+ if ( n==1 ) {
+ // socket was not closed => error
+ d->proc = 0;
+ goto error;
+ } else if ( n==-1 ) {
+ if ( errno==EAGAIN || errno==EINTR )
+ // try it again
+ continue;
+ }
+ break;
+ }
+ ::close( fd[0] );
}
d->newProc( pid, this );
if ( comms & Stdin ) {
- ::close( sStdin[0] );
- d->proc->socketStdin = sStdin[1];
- d->notifierStdin = new QSocketNotifier( sStdin[1], QSocketNotifier::Write );
- connect( d->notifierStdin, SIGNAL(activated(int)),
- this, SLOT(socketWrite(int)) );
- // setup notifiers for the sockets
- if ( !d->stdinBuf.isEmpty() ) {
- d->notifierStdin->setEnabled( TRUE );
- }
+ ::close( sStdin[0] );
+ d->proc->socketStdin = sStdin[1];
+ d->notifierStdin = new QSocketNotifier( sStdin[1], QSocketNotifier::Write );
+ connect( d->notifierStdin, SIGNAL(activated(int)),
+ this, SLOT(socketWrite(int)) );
+ // setup notifiers for the sockets
+ if ( !d->stdinBuf.isEmpty() ) {
+ d->notifierStdin->setEnabled( TRUE );
+ }
}
if ( comms & Stdout ) {
- ::close( sStdout[1] );
- d->proc->socketStdout = sStdout[0];
- d->notifierStdout = new QSocketNotifier( sStdout[0], QSocketNotifier::Read );
- connect( d->notifierStdout, SIGNAL(activated(int)),
- this, SLOT(socketRead(int)) );
- if ( ioRedirection )
- d->notifierStdout->setEnabled( TRUE );
+ ::close( sStdout[1] );
+ d->proc->socketStdout = sStdout[0];
+ d->notifierStdout = new QSocketNotifier( sStdout[0], QSocketNotifier::Read );
+ connect( d->notifierStdout, SIGNAL(activated(int)),
+ this, SLOT(socketRead(int)) );
+ if ( ioRedirection )
+ d->notifierStdout->setEnabled( TRUE );
}
if ( comms & Stderr ) {
- ::close( sStderr[1] );
- d->proc->socketStderr = sStderr[0];
- d->notifierStderr = new QSocketNotifier( sStderr[0], QSocketNotifier::Read );
- connect( d->notifierStderr, SIGNAL(activated(int)),
- this, SLOT(socketRead(int)) );
- if ( ioRedirection )
- d->notifierStderr->setEnabled( TRUE );
+ ::close( sStderr[1] );
+ d->proc->socketStderr = sStderr[0];
+ d->notifierStderr = new QSocketNotifier( sStderr[0], QSocketNotifier::Read );
+ connect( d->notifierStderr, SIGNAL(activated(int)),
+ this, SLOT(socketRead(int)) );
+ if ( ioRedirection )
+ d->notifierStderr->setEnabled( TRUE );
}
// cleanup and return
delete[] arglistQ;
delete[] arglist;
return TRUE;
error:
#if defined(QT_QPROCESS_DEBUG)
odebug << "QProcess::start(): error starting process" << oendl;
#endif
if ( d->procManager )
- d->procManager->cleanup();
+ d->procManager->cleanup();
if ( comms & Stdin ) {
- ::close( sStdin[1] );
- ::close( sStdin[0] );
+ ::close( sStdin[1] );
+ ::close( sStdin[0] );
}
if ( comms & Stdout ) {
- ::close( sStdout[0] );
- ::close( sStdout[1] );
+ ::close( sStdout[0] );
+ ::close( sStdout[1] );
}
if ( comms & Stderr ) {
- ::close( sStderr[0] );
- ::close( sStderr[1] );
+ ::close( sStderr[0] );
+ ::close( sStderr[1] );
}
::close( fd[0] );
::close( fd[1] );
delete[] arglistQ;
delete[] arglist;
return FALSE;
}
/*!
Asks the process to terminate. Processes can ignore this wish. If you want to
be sure that the process really terminates, you must use kill() instead.
The slot returns immediately: it does not wait until the process has
finished. When the process really exited, the signal processExited() is
emitted.
\sa kill() processExited()
*/
void QProcess::tryTerminate() const
{
if ( d->proc != 0 )
- ::kill( d->proc->pid, SIGTERM );
+ ::kill( d->proc->pid, SIGTERM );
}
/*!
Terminates the process. This is not a safe way to end a process since the
process will not be able to do cleanup. tryTerminate() is a safer way to do
it, but processes might ignore a tryTerminate().
The nice way to end a process and to be sure that it is finished, is doing
something like this:
\code
process->tryTerminate();
QTimer::singleShot( 5000, process, SLOT( kill() ) );
@@ -856,56 +856,56 @@ void QProcess::tryTerminate() const
cleanup: use a higher value if the process is likely to do heavy computation
on cleanup.
The slot returns immediately: it does not wait until the process has
finished. When the process really exited, the signal processExited() is
emitted.
\sa tryTerminate() processExited()
*/
void QProcess::kill() const
{
if ( d->proc != 0 )
- ::kill( d->proc->pid, SIGKILL );
+ ::kill( d->proc->pid, SIGKILL );
}
/*!
Returns TRUE if the process is running, otherwise FALSE.
\sa normalExit() exitStatus() processExited()
*/
bool QProcess::isRunning() const
{
if ( d->exitValuesCalculated ) {
#if defined(QT_QPROCESS_DEBUG)
odebug << "QProcess::isRunning(): FALSE (already computed)" << oendl;
#endif
- return FALSE;
+ return FALSE;
}
if ( d->proc == 0 )
- return FALSE;
+ return FALSE;
int status;
if ( ::waitpid( d->proc->pid, &status, WNOHANG ) == d->proc->pid )
{
- // compute the exit values
- QProcess *that = (QProcess*)this; // mutable
- that->exitNormal = WIFEXITED( status ) != 0;
- if ( exitNormal ) {
- that->exitStat = (char)WEXITSTATUS( status );
- }
- d->exitValuesCalculated = TRUE;
+ // compute the exit values
+ QProcess *that = (QProcess*)this; // mutable
+ that->exitNormal = WIFEXITED( status ) != 0;
+ if ( exitNormal ) {
+ that->exitStat = (char)WEXITSTATUS( status );
+ }
+ d->exitValuesCalculated = TRUE;
#if defined(QT_QPROCESS_DEBUG)
odebug << "QProcess::isRunning() (PID: " << d->proc->pid << "): FALSE" << oendl;
#endif
- return FALSE;
+ return FALSE;
}
#if defined(QT_QPROCESS_DEBUG)
odebug << "QProcess::isRunning() (PID: " << d->proc->pid << "): TRUE" << oendl;
#endif
return TRUE;
}
/*!
Writes the data \a buf to the standard input of the process. The process may
or may not read this data.
This function returns immediately; the QProcess class might write the data at
@@ -914,174 +914,174 @@ bool QProcess::isRunning() const
not mean that the process really read the data, since this class only detects
when it was able to write the data to the operating system.
\sa wroteToStdin() closeStdin() readStdout() readStderr()
*/
void QProcess::writeToStdin( const QByteArray& buf )
{
#if defined(QT_QPROCESS_DEBUG)
// odebug << "QProcess::writeToStdin(): write to stdin (" << d->socketStdin << ")" << oendl;
#endif
d->stdinBuf.enqueue( new QByteArray(buf) );
if ( d->notifierStdin != 0 )
- d->notifierStdin->setEnabled( TRUE );
+ d->notifierStdin->setEnabled( TRUE );
}
/*!
Closes standard input of the process.
This function also deletes pending data that is not written to standard input
yet.
\sa wroteToStdin()
*/
void QProcess::closeStdin()
{
if ( d->proc == 0 )
- return;
+ return;
if ( d->proc->socketStdin !=0 ) {
- while ( !d->stdinBuf.isEmpty() ) {
- delete d->stdinBuf.dequeue();
- }
- delete d->notifierStdin;
- d->notifierStdin = 0;
- if ( ::close( d->proc->socketStdin ) != 0 ) {
+ while ( !d->stdinBuf.isEmpty() ) {
+ delete d->stdinBuf.dequeue();
+ }
+ delete d->notifierStdin;
+ d->notifierStdin = 0;
+ if ( ::close( d->proc->socketStdin ) != 0 ) {
owarn << "Could not close stdin of child process" << oendl;
- }
+ }
#if defined(QT_QPROCESS_DEBUG)
odebug << "QProcess::closeStdin(): stdin (" << d->proc->socketStdin << ") closed" << oendl;
#endif
- d->proc->socketStdin = 0;
+ d->proc->socketStdin = 0;
}
}
/*
This private slot is called when the process has outputted data to either
standard output or standard error.
*/
void QProcess::socketRead( int fd )
{
if ( d->socketReadCalled ) {
- // the slots that are connected to the readyRead...() signals might
- // trigger a recursive call of socketRead(). Avoid this since you get a
- // blocking read otherwise.
- return;
+ // the slots that are connected to the readyRead...() signals might
+ // trigger a recursive call of socketRead(). Avoid this since you get a
+ // blocking read otherwise.
+ return;
}
#if defined(QT_QPROCESS_DEBUG)
odebug << "QProcess::socketRead(): " << fd << "" << oendl;
#endif
if ( fd == 0 )
- return;
+ return;
const int bufsize = 4096;
QByteArray *buffer = 0;
uint oldSize;
int n;
if ( fd == d->proc->socketStdout ) {
- buffer = &d->bufStdout;
+ buffer = &d->bufStdout;
} else if ( fd == d->proc->socketStderr ) {
- buffer = &d->bufStderr;
+ buffer = &d->bufStderr;
} else {
- // this case should never happen, but just to be safe
- return;
+ // this case should never happen, but just to be safe
+ return;
}
// read data
oldSize = buffer->size();
buffer->resize( oldSize + bufsize );
n = ::read( fd, buffer->data()+oldSize, bufsize );
if ( n > 0 )
- buffer->resize( oldSize + n );
+ buffer->resize( oldSize + n );
else
- buffer->resize( oldSize );
+ buffer->resize( oldSize );
// eof or error?
if ( n == 0 || n == -1 ) {
- if ( fd == d->proc->socketStdout ) {
+ if ( fd == d->proc->socketStdout ) {
#if defined(QT_QPROCESS_DEBUG)
odebug << "QProcess::socketRead(): stdout (" << fd << ") closed" << oendl;
#endif
- d->notifierStdout->setEnabled( FALSE );
- delete d->notifierStdout;
- d->notifierStdout = 0;
- ::close( d->proc->socketStdout );
- d->proc->socketStdout = 0;
- return;
- } else if ( fd == d->proc->socketStderr ) {
+ d->notifierStdout->setEnabled( FALSE );
+ delete d->notifierStdout;
+ d->notifierStdout = 0;
+ ::close( d->proc->socketStdout );
+ d->proc->socketStdout = 0;
+ return;
+ } else if ( fd == d->proc->socketStderr ) {
#if defined(QT_QPROCESS_DEBUG)
odebug << "QProcess::socketRead(): stderr (" << fd << ") closed" << oendl;
#endif
- d->notifierStderr->setEnabled( FALSE );
- delete d->notifierStderr;
- d->notifierStderr = 0;
- ::close( d->proc->socketStderr );
- d->proc->socketStderr = 0;
- return;
- }
+ d->notifierStderr->setEnabled( FALSE );
+ delete d->notifierStderr;
+ d->notifierStderr = 0;
+ ::close( d->proc->socketStderr );
+ d->proc->socketStderr = 0;
+ return;
+ }
}
// read all data that is available
while ( n == bufsize ) {
- oldSize = buffer->size();
- buffer->resize( oldSize + bufsize );
- n = ::read( fd, buffer->data()+oldSize, bufsize );
- if ( n > 0 )
- buffer->resize( oldSize + n );
- else
- buffer->resize( oldSize );
+ oldSize = buffer->size();
+ buffer->resize( oldSize + bufsize );
+ n = ::read( fd, buffer->data()+oldSize, bufsize );
+ if ( n > 0 )
+ buffer->resize( oldSize + n );
+ else
+ buffer->resize( oldSize );
}
d->socketReadCalled = TRUE;
if ( fd == d->proc->socketStdout ) {
#if defined(QT_QPROCESS_DEBUG)
- qDebug( "QProcess::socketRead(): %d bytes read from stdout (%d)",
- buffer->size()-oldSize, fd );
+ odebug << "QProcess::socketRead(): " << buffer->size()-oldSize << "bytes read from stdout ("
+ << fd << ")" << oendl;
#endif
- emit readyReadStdout();
+ emit readyReadStdout();
} else if ( fd == d->proc->socketStderr ) {
#if defined(QT_QPROCESS_DEBUG)
- qDebug( "QProcess::socketRead(): %d bytes read from stderr (%d)",
- buffer->size()-oldSize, fd );
+ odebug << "QProcess::socketRead(): " << buffer->size()-oldSize << " bytes read from stderr ("
+ << fd << ")" << oendl;
#endif
- emit readyReadStderr();
+ emit readyReadStderr();
}
d->socketReadCalled = FALSE;
}
/*
This private slot is called when the process tries to read data from standard
input.
*/
void QProcess::socketWrite( int fd )
{
if ( fd != d->proc->socketStdin || d->proc->socketStdin == 0 )
- return;
+ return;
if ( d->stdinBuf.isEmpty() ) {
- d->notifierStdin->setEnabled( FALSE );
- return;
+ d->notifierStdin->setEnabled( FALSE );
+ return;
}
#if defined(QT_QPROCESS_DEBUG)
odebug << "QProcess::socketWrite(): write to stdin (" << fd << ")" << oendl;
#endif
ssize_t ret = ::write( fd,
- d->stdinBuf.head()->data() + d->stdinBufRead,
- d->stdinBuf.head()->size() - d->stdinBufRead );
+ d->stdinBuf.head()->data() + d->stdinBufRead,
+ d->stdinBuf.head()->size() - d->stdinBufRead );
if ( ret > 0 )
- d->stdinBufRead += ret;
+ d->stdinBufRead += ret;
if ( d->stdinBufRead == (ssize_t)d->stdinBuf.head()->size() ) {
- d->stdinBufRead = 0;
- delete d->stdinBuf.dequeue();
- if ( wroteToStdinConnected && d->stdinBuf.isEmpty() )
- emit wroteToStdin();
- socketWrite( fd );
+ d->stdinBufRead = 0;
+ delete d->stdinBuf.dequeue();
+ if ( wroteToStdinConnected && d->stdinBuf.isEmpty() )
+ emit wroteToStdin();
+ socketWrite( fd );
}
}
/*!
\internal
Flushes standard input. This is useful if you want to use QProcess in a
synchronous manner.
This function should probably go into the public API.
*/
void QProcess::flushStdin()
{
@@ -1096,33 +1096,33 @@ void QProcess::timeout()
{
}
/*
This private function is used by connectNotify() and disconnectNotify() to
change the value of ioRedirection (and related behaviour)
*/
void QProcess::setIoRedirection( bool value )
{
ioRedirection = value;
if ( ioRedirection ) {
- if ( d->notifierStdout )
- d->notifierStdout->setEnabled( TRUE );
- if ( d->notifierStderr )
- d->notifierStderr->setEnabled( TRUE );
+ if ( d->notifierStdout )
+ d->notifierStdout->setEnabled( TRUE );
+ if ( d->notifierStderr )
+ d->notifierStderr->setEnabled( TRUE );
} else {
- if ( d->notifierStdout )
- d->notifierStdout->setEnabled( FALSE );
- if ( d->notifierStderr )
- d->notifierStderr->setEnabled( FALSE );
+ if ( d->notifierStdout )
+ d->notifierStdout->setEnabled( FALSE );
+ if ( d->notifierStderr )
+ d->notifierStderr->setEnabled( FALSE );
}
}
/*
This private function is used by connectNotify() and
disconnectNotify() to change the value of notifyOnExit (and related
behaviour)
*/
void QProcess::setNotifyOnExit( bool value )
{
notifyOnExit = value;
}
@@ -1143,31 +1143,31 @@ void QProcess::setWroteStdinConnected( bool value )
Returns platform dependent information about the process. This can be used
together with platform specific system calls.
Under Unix the return value is the PID of the process, or -1 if no process is
belonging to this object.
Under Windows it is a pointer to the \c PROCESS_INFORMATION struct, or 0 if
no process is belonging to this object.
*/
QProcess::PID QProcess::processIdentifier()
{
if ( d->proc == 0 )
- return -1;
+ return -1;
return d->proc->pid;
}
int QProcess::priority() const
{
if ( d->proc )
- return getpriority(PRIO_PROCESS,d->proc->pid);
+ return getpriority(PRIO_PROCESS,d->proc->pid);
return 0;
}
void QProcess::setPriority(int p)
{
if ( d->proc )
- setpriority(PRIO_PROCESS,d->proc->pid,p);
+ setpriority(PRIO_PROCESS,d->proc->pid,p);
}
#endif // QT_NO_PROCESS