summaryrefslogtreecommitdiff
path: root/core/launcher/qprocess_unix.cpp
Unidiff
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
@@ -134,7 +134,7 @@ public:
134 odebug << "QProc: Constructor for pid " << pid << " and QProcess " << process << "" << oendl; 134 odebug << "QProc: Constructor for pid " << pid << " and QProcess " << process << "" << oendl;
135#endif 135#endif
136 socketStdin = 0; 136 socketStdin = 0;
137 socketStdout = 0; 137 socketStdout = 0;
138 socketStderr = 0; 138 socketStderr = 0;
139 } 139 }
140 ~QProc() 140 ~QProc()
@@ -143,21 +143,21 @@ public:
143 odebug << "QProc: Destructor for pid " << pid << " and QProcess " << process << "" << oendl; 143 odebug << "QProc: Destructor for pid " << pid << " and QProcess " << process << "" << oendl;
144#endif 144#endif
145 if ( process != 0 ) { 145 if ( process != 0 ) {
146 if ( process->d->notifierStdin ) 146 if ( process->d->notifierStdin )
147 process->d->notifierStdin->setEnabled( FALSE ); 147 process->d->notifierStdin->setEnabled( FALSE );
148 if ( process->d->notifierStdout ) 148 if ( process->d->notifierStdout )
149 process->d->notifierStdout->setEnabled( FALSE ); 149 process->d->notifierStdout->setEnabled( FALSE );
150 if ( process->d->notifierStderr ) 150 if ( process->d->notifierStderr )
151 process->d->notifierStderr->setEnabled( FALSE ); 151 process->d->notifierStderr->setEnabled( FALSE );
152 process->d->proc = 0; 152 process->d->proc = 0;
153 } 153 }
154 if( socketStdin != 0 ) 154 if( socketStdin != 0 )
155 ::close( socketStdin ); 155 ::close( socketStdin );
156 // ### close these sockets even on parent exit or is it better only on 156 // ### close these sockets even on parent exit or is it better only on
157 // sigchld (but what do I have to do with them on exit then)? 157 // sigchld (but what do I have to do with them on exit then)?
158 if( socketStdout != 0 ) 158 if( socketStdout != 0 )
159 ::close( socketStdout ); 159 ::close( socketStdout );
160 if( socketStderr != 0 ) 160 if( socketStderr != 0 )
161 ::close( socketStderr ); 161 ::close( socketStderr );
162 } 162 }
163 163
@@ -209,15 +209,15 @@ QProcessManager::QProcessManager()
209 // event reporting. 209 // event reporting.
210 if ( ::socketpair( AF_UNIX, SOCK_STREAM, 0, sigchldFd ) ) { 210 if ( ::socketpair( AF_UNIX, SOCK_STREAM, 0, sigchldFd ) ) {
211 sigchldFd[0] = 0; 211 sigchldFd[0] = 0;
212 sigchldFd[1] = 0; 212 sigchldFd[1] = 0;
213 } else { 213 } else {
214#if defined(QT_QPROCESS_DEBUG) 214#if defined(QT_QPROCESS_DEBUG)
215 odebug << "QProcessManager: install socket notifier (" << sigchldFd[1] << ")" << oendl; 215 odebug << "QProcessManager: install socket notifier (" << sigchldFd[1] << ")" << oendl;
216#endif 216#endif
217 QSocketNotifier *sn = new QSocketNotifier( sigchldFd[1], 217 QSocketNotifier *sn = new QSocketNotifier( sigchldFd[1],
218 QSocketNotifier::Read, this ); 218 QSocketNotifier::Read, this );
219 connect( sn, SIGNAL(activated(int)), 219 connect( sn, SIGNAL(activated(int)),
220 this, SLOT(sigchldHnd(int)) ); 220 this, SLOT(sigchldHnd(int)) );
221 sn->setEnabled( TRUE ); 221 sn->setEnabled( TRUE );
222 } 222 }
223 223
@@ -242,8 +242,8 @@ QProcessManager::QProcessManager()
242#endif 242#endif
243 /* 243 /*
244 Using qt_C_sigpipeHnd rather than SIG_IGN is a workaround 244 Using qt_C_sigpipeHnd rather than SIG_IGN is a workaround
245 for a strange problem where GNU tar (called by backuprestore) 245 for a strange problem where GNU tar (called by backuprestore)
246 would hang on filesystem-full. Strangely, the qt_C_sigpipeHnd 246 would hang on filesystem-full. Strangely, the qt_C_sigpipeHnd
247 is never even called, yet this avoids the hang. 247 is never even called, yet this avoids the hang.
248 */ 248 */
249 act.sa_handler = qt_C_sigpipeHnd; 249 act.sa_handler = qt_C_sigpipeHnd;
@@ -260,7 +260,7 @@ QProcessManager::~QProcessManager()
260 260
261 if ( sigchldFd[0] != 0 ) 261 if ( sigchldFd[0] != 0 )
262 ::close( sigchldFd[0] ); 262 ::close( sigchldFd[0] );
263 if ( sigchldFd[1] != 0 ) 263 if ( sigchldFd[1] != 0 )
264 ::close( sigchldFd[1] ); 264 ::close( sigchldFd[1] );
265 265
266 // restore SIGCHLD handler 266 // restore SIGCHLD handler
@@ -298,5 +298,5 @@ void QProcessManager::cleanup()
298{ 298{
299 if ( procList->count() == 0 ) { 299 if ( procList->count() == 0 ) {
300 QTimer::singleShot( 0, this, SLOT(removeMe()) ); 300 QTimer::singleShot( 0, this, SLOT(removeMe()) );
301 } 301 }
302} 302}
@@ -305,7 +305,7 @@ void QProcessManager::removeMe()
305{ 305{
306 if ( procList->count() == 0 ) { 306 if ( procList->count() == 0 ) {
307 qprocess_cleanup_procmanager.remove( &QProcessPrivate::procManager ); 307 qprocess_cleanup_procmanager.remove( &QProcessPrivate::procManager );
308 QProcessPrivate::procManager = 0; 308 QProcessPrivate::procManager = 0;
309 delete this; 309 delete this;
310 } 310 }
311} 311}
@@ -323,51 +323,51 @@ void QProcessManager::sigchldHnd( int fd )
323 proc = procList->first(); 323 proc = procList->first();
324 while ( proc != 0 ) { 324 while ( proc != 0 ) {
325 removeProc = FALSE; 325 removeProc = FALSE;
326 process = proc->process; 326 process = proc->process;
327 QProcess *process_exit_notify=0; 327 QProcess *process_exit_notify=0;
328 if ( process != 0 ) { 328 if ( process != 0 ) {
329 if ( !process->isRunning() ) { 329 if ( !process->isRunning() ) {
330#if defined(QT_QPROCESS_DEBUG) 330#if defined(QT_QPROCESS_DEBUG)
331 odebug << "QProcessManager::sigchldHnd() (PID: " << proc->pid << "): process exited (QProcess available)" << oendl; 331 odebug << "QProcessManager::sigchldHnd() (PID: " << proc->pid << "): process exited (QProcess available)" << oendl;
332#endif 332#endif
333 // read pending data 333 // read pending data
334 int nbytes = 0; 334 int nbytes = 0;
335 if ( ::ioctl(proc->socketStdout, FIONREAD, (char*)&nbytes)==0 && nbytes>0 ) { 335 if ( ::ioctl(proc->socketStdout, FIONREAD, (char*)&nbytes)==0 && nbytes>0 ) {
336#if defined(QT_QPROCESS_DEBUG) 336#if defined(QT_QPROCESS_DEBUG)
337 odebug << "QProcessManager::sigchldHnd() (PID: " << proc->pid << "): reading " << nbytes << " bytes of pending data on stdout" << oendl; 337 odebug << "QProcessManager::sigchldHnd() (PID: " << proc->pid << "): reading " << nbytes << " bytes of pending data on stdout" << oendl;
338#endif 338#endif
339 process->socketRead( proc->socketStdout ); 339 process->socketRead( proc->socketStdout );
340 } 340 }
341 nbytes = 0; 341 nbytes = 0;
342 if ( ::ioctl(proc->socketStderr, FIONREAD, (char*)&nbytes)==0 && nbytes>0 ) { 342 if ( ::ioctl(proc->socketStderr, FIONREAD, (char*)&nbytes)==0 && nbytes>0 ) {
343#if defined(QT_QPROCESS_DEBUG) 343#if defined(QT_QPROCESS_DEBUG)
344 odebug << "QProcessManager::sigchldHnd() (PID: " << proc->pid << "): reading " << nbytes << " bytes of pending data on stderr" << oendl; 344 odebug << "QProcessManager::sigchldHnd() (PID: " << proc->pid << "): reading " << nbytes << " bytes of pending data on stderr" << oendl;
345#endif 345#endif
346 process->socketRead( proc->socketStderr ); 346 process->socketRead( proc->socketStderr );
347 } 347 }
348 348
349 if ( process->notifyOnExit ) 349 if ( process->notifyOnExit )
350 process_exit_notify = process; 350 process_exit_notify = process;
351 351
352 removeProc = TRUE; 352 removeProc = TRUE;
353 } 353 }
354 } else { 354 } else {
355 int status; 355 int status;
356 if ( ::waitpid( proc->pid, &status, WNOHANG ) == proc->pid ) { 356 if ( ::waitpid( proc->pid, &status, WNOHANG ) == proc->pid ) {
357#if defined(QT_QPROCESS_DEBUG) 357#if defined(QT_QPROCESS_DEBUG)
358 odebug << "QProcessManager::sigchldHnd() (PID: " << proc->pid << "): process exited (QProcess not available)" << oendl; 358 odebug << "QProcessManager::sigchldHnd() (PID: " << proc->pid << "): process exited (QProcess not available)" << oendl;
359#endif 359#endif
360 removeProc = TRUE; 360 removeProc = TRUE;
361 } 361 }
362 } 362 }
363 if ( removeProc ) { 363 if ( removeProc ) {
364 QProc *oldproc = proc; 364 QProc *oldproc = proc;
365 proc = procList->next(); 365 proc = procList->next();
366 remove( oldproc ); 366 remove( oldproc );
367 } else { 367 } else {
368 proc = procList->next(); 368 proc = procList->next();
369 } 369 }
370 if ( process_exit_notify ) 370 if ( process_exit_notify )
371 emit process_exit_notify->processExited(); 371 emit process_exit_notify->processExited();
372 } 372 }
373} 373}
@@ -407,13 +407,13 @@ QProcessPrivate::~QProcessPrivate()
407 407
408 if ( proc != 0 ) { 408 if ( proc != 0 ) {
409 if ( proc->socketStdin != 0 ) { 409 if ( proc->socketStdin != 0 ) {
410 ::close( proc->socketStdin ); 410 ::close( proc->socketStdin );
411 proc->socketStdin = 0; 411 proc->socketStdin = 0;
412 } 412 }
413 proc->process = 0; 413 proc->process = 0;
414 } 414 }
415 415
416 while ( !stdinBuf.isEmpty() ) { 416 while ( !stdinBuf.isEmpty() ) {
417 delete stdinBuf.dequeue(); 417 delete stdinBuf.dequeue();
418 } 418 }
419 delete notifierStdin; 419 delete notifierStdin;
@@ -430,16 +430,16 @@ void QProcessPrivate::closeOpenSocketsForChild()
430{ 430{
431 if ( procManager != 0 ) { 431 if ( procManager != 0 ) {
432 if ( procManager->sigchldFd[0] != 0 ) 432 if ( procManager->sigchldFd[0] != 0 )
433 ::close( procManager->sigchldFd[0] ); 433 ::close( procManager->sigchldFd[0] );
434 if ( procManager->sigchldFd[1] != 0 ) 434 if ( procManager->sigchldFd[1] != 0 )
435 ::close( procManager->sigchldFd[1] ); 435 ::close( procManager->sigchldFd[1] );
436 436
437 // close also the sockets from other QProcess instances 437 // close also the sockets from other QProcess instances
438 QProc *proc; 438 QProc *proc;
439 for ( proc=procManager->procList->first(); proc!=0; proc=procManager->procList->next() ) { 439 for ( proc=procManager->procList->first(); proc!=0; proc=procManager->procList->next() ) {
440 ::close( proc->socketStdin ); 440 ::close( proc->socketStdin );
441 ::close( proc->socketStdout ); 441 ::close( proc->socketStdout );
442 ::close( proc->socketStderr ); 442 ::close( proc->socketStderr );
443 } 443 }
444 } 444 }
445} 445}
@@ -449,6 +449,6 @@ void QProcessPrivate::newProc( pid_t pid, QProcess *process )
449 proc = new QProc( pid, process ); 449 proc = new QProc( pid, process );
450 if ( procManager == 0 ) { 450 if ( procManager == 0 ) {
451 procManager = new QProcessManager; 451 procManager = new QProcessManager;
452 qprocess_cleanup_procmanager.add( &procManager ); 452 qprocess_cleanup_procmanager.add( &procManager );
453 } 453 }
454 // the QProcessManager takes care of deleting the QProc instances 454 // the QProcessManager takes care of deleting the QProc instances
@@ -464,7 +464,7 @@ QT_SIGNAL_RETTYPE qt_C_sigchldHnd( QT_SIGNAL_ARGS )
464{ 464{
465 if ( QProcessPrivate::procManager == 0 ) 465 if ( QProcessPrivate::procManager == 0 )
466 return; 466 return;
467 if ( QProcessPrivate::procManager->sigchldFd[0] == 0 ) 467 if ( QProcessPrivate::procManager->sigchldFd[0] == 0 )
468 return; 468 return;
469 469
470 char a = 1; 470 char a = 1;
@@ -509,7 +509,7 @@ QByteArray* QProcess::bufStdout()
509{ 509{
510 if ( d->proc && d->proc->socketStdout ) { 510 if ( d->proc && d->proc->socketStdout ) {
511 // ### can this cause a blocking behaviour (maybe do a ioctl() to see 511 // ### can this cause a blocking behaviour (maybe do a ioctl() to see
512 // if data is available)? 512 // if data is available)?
513 socketRead( d->proc->socketStdout ); 513 socketRead( d->proc->socketStdout );
514 } 514 }
515 return &d->bufStdout; 515 return &d->bufStdout;
@@ -519,7 +519,7 @@ QByteArray* QProcess::bufStderr()
519{ 519{
520 if ( d->proc && d->proc->socketStderr ) { 520 if ( d->proc && d->proc->socketStderr ) {
521 // ### can this cause a blocking behaviour (maybe do a ioctl() to see 521 // ### can this cause a blocking behaviour (maybe do a ioctl() to see
522 // if data is available)? 522 // if data is available)?
523 socketRead( d->proc->socketStderr ); 523 socketRead( d->proc->socketStderr );
524 } 524 }
525 return &d->bufStderr; 525 return &d->bufStderr;
@@ -530,9 +530,9 @@ void QProcess::consumeBufStdout( int consume )
530 uint n = d->bufStdout.size(); 530 uint n = d->bufStdout.size();
531 if ( consume==-1 || (uint)consume >= n ) { 531 if ( consume==-1 || (uint)consume >= n ) {
532 d->bufStdout.resize( 0 ); 532 d->bufStdout.resize( 0 );
533 } else { 533 } else {
534 QByteArray tmp( n - consume ); 534 QByteArray tmp( n - consume );
535 memcpy( tmp.data(), d->bufStdout.data()+consume, n-consume ); 535 memcpy( tmp.data(), d->bufStdout.data()+consume, n-consume );
536 d->bufStdout = tmp; 536 d->bufStdout = tmp;
537 } 537 }
538} 538}
@@ -542,9 +542,9 @@ void QProcess::consumeBufStderr( int consume )
542 uint n = d->bufStderr.size(); 542 uint n = d->bufStderr.size();
543 if ( consume==-1 || (uint)consume >= n ) { 543 if ( consume==-1 || (uint)consume >= n ) {
544 d->bufStderr.resize( 0 ); 544 d->bufStderr.resize( 0 );
545 } else { 545 } else {
546 QByteArray tmp( n - consume ); 546 QByteArray tmp( n - consume );
547 memcpy( tmp.data(), d->bufStderr.data()+consume, n-consume ); 547 memcpy( tmp.data(), d->bufStderr.data()+consume, n-consume );
548 d->bufStderr = tmp; 548 d->bufStderr = tmp;
549 } 549 }
550} 550}
@@ -609,11 +609,11 @@ bool QProcess::start( QStringList *env )
609 // open sockets for piping 609 // open sockets for piping
610 if ( (comms & Stdin) && ::socketpair( AF_UNIX, SOCK_STREAM, 0, sStdin ) == -1 ) { 610 if ( (comms & Stdin) && ::socketpair( AF_UNIX, SOCK_STREAM, 0, sStdin ) == -1 ) {
611 return FALSE; 611 return FALSE;
612 } 612 }
613 if ( (comms & Stderr) && ::socketpair( AF_UNIX, SOCK_STREAM, 0, sStderr ) == -1 ) { 613 if ( (comms & Stderr) && ::socketpair( AF_UNIX, SOCK_STREAM, 0, sStderr ) == -1 ) {
614 return FALSE; 614 return FALSE;
615 } 615 }
616 if ( (comms & Stdout) && ::socketpair( AF_UNIX, SOCK_STREAM, 0, sStdout ) == -1 ) { 616 if ( (comms & Stdout) && ::socketpair( AF_UNIX, SOCK_STREAM, 0, sStdout ) == -1 ) {
617 return FALSE; 617 return FALSE;
618 } 618 }
619 619
@@ -622,7 +622,7 @@ bool QProcess::start( QStringList *env )
622 int fd[2]; 622 int fd[2];
623 if ( pipe( fd ) < 0 ) { 623 if ( pipe( fd ) < 0 ) {
624 // non critical error, go on 624 // non critical error, go on
625 fd[0] = 0; 625 fd[0] = 0;
626 fd[1] = 0; 626 fd[1] = 0;
627 } 627 }
628 628
@@ -632,10 +632,10 @@ bool QProcess::start( QStringList *env )
632 int i = 0; 632 int i = 0;
633 for ( QStringList::Iterator it = _arguments.begin(); it != _arguments.end(); ++it ) { 633 for ( QStringList::Iterator it = _arguments.begin(); it != _arguments.end(); ++it ) {
634 arglistQ[i] = (*it).local8Bit(); 634 arglistQ[i] = (*it).local8Bit();
635 arglist[i] = arglistQ[i]; 635 arglist[i] = arglistQ[i];
636#if defined(QT_QPROCESS_DEBUG) 636#if defined(QT_QPROCESS_DEBUG)
637 odebug << "QProcess::start(): arg " << i << " = " << arglist[i] << "" << oendl; 637 odebug << "QProcess::start(): arg " << i << " = " << arglist[i] << "" << oendl;
638#endif 638#endif
639 i++; 639 i++;
640 } 640 }
641 arglist[i] = 0; 641 arglist[i] = 0;
@@ -644,6 +644,6 @@ bool QProcess::start( QStringList *env )
644 // in case the process exits quickly. 644 // in case the process exits quickly.
645 if ( d->procManager == 0 ) { 645 if ( d->procManager == 0 ) {
646 d->procManager = new QProcessManager; 646 d->procManager = new QProcessManager;
647 qprocess_cleanup_procmanager.add( &d->procManager ); 647 qprocess_cleanup_procmanager.add( &d->procManager );
648 } 648 }
649 649
@@ -652,110 +652,110 @@ bool QProcess::start( QStringList *env )
652 pid_t pid = fork(); 652 pid_t pid = fork();
653 if ( pid == 0 ) { 653 if ( pid == 0 ) {
654 // child 654 // child
655 d->closeOpenSocketsForChild(); 655 d->closeOpenSocketsForChild();
656 if ( comms & Stdin ) { 656 if ( comms & Stdin ) {
657 ::close( sStdin[1] ); 657 ::close( sStdin[1] );
658 ::dup2( sStdin[0], STDIN_FILENO ); 658 ::dup2( sStdin[0], STDIN_FILENO );
659 } 659 }
660 if ( comms & Stdout ) { 660 if ( comms & Stdout ) {
661 ::close( sStdout[0] ); 661 ::close( sStdout[0] );
662 ::dup2( sStdout[1], STDOUT_FILENO ); 662 ::dup2( sStdout[1], STDOUT_FILENO );
663 } 663 }
664 if ( comms & Stderr ) { 664 if ( comms & Stderr ) {
665 ::close( sStderr[0] ); 665 ::close( sStderr[0] );
666 ::dup2( sStderr[1], STDERR_FILENO ); 666 ::dup2( sStderr[1], STDERR_FILENO );
667 } 667 }
668 if ( comms & DupStderr ) { 668 if ( comms & DupStderr ) {
669 ::dup2( STDOUT_FILENO, STDERR_FILENO ); 669 ::dup2( STDOUT_FILENO, STDERR_FILENO );
670 } 670 }
671#ifndef QT_NO_DIR 671#ifndef QT_NO_DIR
672 ::chdir( workingDir.absPath().latin1() ); 672 ::chdir( workingDir.absPath().latin1() );
673#endif 673#endif
674 if ( fd[0] ) 674 if ( fd[0] )
675 ::close( fd[0] ); 675 ::close( fd[0] );
676 if ( fd[1] ) 676 if ( fd[1] )
677 ::fcntl( fd[1], F_SETFD, FD_CLOEXEC ); // close on exec shows sucess 677 ::fcntl( fd[1], F_SETFD, FD_CLOEXEC ); // close on exec shows sucess
678 678
679 if ( env == 0 ) { // inherit environment and start process 679 if ( env == 0 ) { // inherit environment and start process
680 ::execvp( arglist[0], (char*const*)arglist ); // ### cast not nice 680 ::execvp( arglist[0], (char*const*)arglist ); // ### cast not nice
681 } else { // start process with environment settins as specified in env 681 } else { // start process with environment settins as specified in env
682 // construct the environment for exec 682 // construct the environment for exec
683 int numEntries = env->count(); 683 int numEntries = env->count();
684 bool setLibraryPath = 684 bool setLibraryPath =
685 env->grep( QRegExp( "^LD_LIBRARY_PATH=" ) ).isEmpty() && 685 env->grep( QRegExp( "^LD_LIBRARY_PATH=" ) ).isEmpty() &&
686 getenv( "LD_LIBRARY_PATH" ) != 0; 686 getenv( "LD_LIBRARY_PATH" ) != 0;
687 if ( setLibraryPath ) 687 if ( setLibraryPath )
688 numEntries++; 688 numEntries++;
689 QCString *envlistQ = new QCString[ numEntries + 1 ]; 689 QCString *envlistQ = new QCString[ numEntries + 1 ];
690 const char** envlist = new const char*[ numEntries + 1 ]; 690 const char** envlist = new const char*[ numEntries + 1 ];
691 int i = 0; 691 int i = 0;
692 if ( setLibraryPath ) { 692 if ( setLibraryPath ) {
693 envlistQ[i] = QString( "LD_LIBRARY_PATH=%1" ).arg( getenv( "LD_LIBRARY_PATH" ) ).local8Bit(); 693 envlistQ[i] = QString( "LD_LIBRARY_PATH=%1" ).arg( getenv( "LD_LIBRARY_PATH" ) ).local8Bit();
694 envlist[i] = envlistQ[i]; 694 envlist[i] = envlistQ[i];
695 i++; 695 i++;
696 } 696 }
697 for ( QStringList::Iterator it = env->begin(); it != env->end(); ++it ) { 697 for ( QStringList::Iterator it = env->begin(); it != env->end(); ++it ) {
698 envlistQ[i] = (*it).local8Bit(); 698 envlistQ[i] = (*it).local8Bit();
699 envlist[i] = envlistQ[i]; 699 envlist[i] = envlistQ[i];
700 i++; 700 i++;
701 } 701 }
702 envlist[i] = 0; 702 envlist[i] = 0;
703 703
704 // look for the executable in the search path 704 // look for the executable in the search path
705 if ( _arguments.count()>0 && getenv("PATH")!=0 ) { 705 if ( _arguments.count()>0 && getenv("PATH")!=0 ) {
706 QString command = _arguments[0]; 706 QString command = _arguments[0];
707 if ( !command.contains( '/' ) ) { 707 if ( !command.contains( '/' ) ) {
708 QStringList pathList = QStringList::split( ':', getenv( "PATH" ) ); 708 QStringList pathList = QStringList::split( ':', getenv( "PATH" ) );
709 for (QStringList::Iterator it = pathList.begin(); it != pathList.end(); ++it ) { 709 for (QStringList::Iterator it = pathList.begin(); it != pathList.end(); ++it ) {
710 QString dir = *it; 710 QString dir = *it;
711#ifdef Q_OS_MACX 711#ifdef Q_OS_MACX
712 if(QFile::exists(dir + "/" + command + ".app")) //look in a bundle 712 if(QFile::exists(dir + "/" + command + ".app")) //look in a bundle
713 dir += "/" + command + ".app/Contents/MacOS"; 713 dir += "/" + command + ".app/Contents/MacOS";
714#endif 714#endif
715#ifndef QT_NO_DIR 715#ifndef QT_NO_DIR
716 QFileInfo fileInfo( dir, command ); 716 QFileInfo fileInfo( dir, command );
717#else 717#else
718 QFileInfo fileInfo( dir + "/" + command ); 718 QFileInfo fileInfo( dir + "/" + command );
719#endif 719#endif
720 if ( fileInfo.isExecutable() ) { 720 if ( fileInfo.isExecutable() ) {
721 arglistQ[0] = fileInfo.filePath().local8Bit(); 721 arglistQ[0] = fileInfo.filePath().local8Bit();
722 arglist[0] = arglistQ[0]; 722 arglist[0] = arglistQ[0];
723 break; 723 break;
724 } 724 }
725 } 725 }
726 } 726 }
727 } 727 }
728 ::execve( arglist[0], (char*const*)arglist, (char*const*)envlist ); // ### casts not nice 728 ::execve( arglist[0], (char*const*)arglist, (char*const*)envlist ); // ### casts not nice
729 } 729 }
730 if ( fd[1] ) { 730 if ( fd[1] ) {
731 char buf = 0; 731 char buf = 0;
732 ::write( fd[1], &buf, 1 ); 732 ::write( fd[1], &buf, 1 );
733 ::close( fd[1] ); 733 ::close( fd[1] );
734 } 734 }
735 ::exit( -1 ); 735 ::exit( -1 );
736 } else if ( pid == -1 ) { 736 } else if ( pid == -1 ) {
737 // error forking 737 // error forking
738 goto error; 738 goto error;
739 } 739 }
740 740
741 // test if exec was successful 741 // test if exec was successful
742 if ( fd[1] ) 742 if ( fd[1] )
743 ::close( fd[1] ); 743 ::close( fd[1] );
744 if ( fd[0] ) { 744 if ( fd[0] ) {
745 char buf; 745 char buf;
746 for ( ;; ) { 746 for ( ;; ) {
747 int n = ::read( fd[0], &buf, 1 ); 747 int n = ::read( fd[0], &buf, 1 );
748 if ( n==1 ) { 748 if ( n==1 ) {
749 // socket was not closed => error 749 // socket was not closed => error
750 d->proc = 0; 750 d->proc = 0;
751 goto error; 751 goto error;
752 } else if ( n==-1 ) { 752 } else if ( n==-1 ) {
753 if ( errno==EAGAIN || errno==EINTR ) 753 if ( errno==EAGAIN || errno==EINTR )
754 // try it again 754 // try it again
755 continue; 755 continue;
756 } 756 }
757 break; 757 break;
758 } 758 }
759 ::close( fd[0] ); 759 ::close( fd[0] );
760 } 760 }
761 761
@@ -763,31 +763,31 @@ bool QProcess::start( QStringList *env )
763 763
764 if ( comms & Stdin ) { 764 if ( comms & Stdin ) {
765 ::close( sStdin[0] ); 765 ::close( sStdin[0] );
766 d->proc->socketStdin = sStdin[1]; 766 d->proc->socketStdin = sStdin[1];
767 d->notifierStdin = new QSocketNotifier( sStdin[1], QSocketNotifier::Write ); 767 d->notifierStdin = new QSocketNotifier( sStdin[1], QSocketNotifier::Write );
768 connect( d->notifierStdin, SIGNAL(activated(int)), 768 connect( d->notifierStdin, SIGNAL(activated(int)),
769 this, SLOT(socketWrite(int)) ); 769 this, SLOT(socketWrite(int)) );
770 // setup notifiers for the sockets 770 // setup notifiers for the sockets
771 if ( !d->stdinBuf.isEmpty() ) { 771 if ( !d->stdinBuf.isEmpty() ) {
772 d->notifierStdin->setEnabled( TRUE ); 772 d->notifierStdin->setEnabled( TRUE );
773 } 773 }
774 } 774 }
775 if ( comms & Stdout ) { 775 if ( comms & Stdout ) {
776 ::close( sStdout[1] ); 776 ::close( sStdout[1] );
777 d->proc->socketStdout = sStdout[0]; 777 d->proc->socketStdout = sStdout[0];
778 d->notifierStdout = new QSocketNotifier( sStdout[0], QSocketNotifier::Read ); 778 d->notifierStdout = new QSocketNotifier( sStdout[0], QSocketNotifier::Read );
779 connect( d->notifierStdout, SIGNAL(activated(int)), 779 connect( d->notifierStdout, SIGNAL(activated(int)),
780 this, SLOT(socketRead(int)) ); 780 this, SLOT(socketRead(int)) );
781 if ( ioRedirection ) 781 if ( ioRedirection )
782 d->notifierStdout->setEnabled( TRUE ); 782 d->notifierStdout->setEnabled( TRUE );
783 } 783 }
784 if ( comms & Stderr ) { 784 if ( comms & Stderr ) {
785 ::close( sStderr[1] ); 785 ::close( sStderr[1] );
786 d->proc->socketStderr = sStderr[0]; 786 d->proc->socketStderr = sStderr[0];
787 d->notifierStderr = new QSocketNotifier( sStderr[0], QSocketNotifier::Read ); 787 d->notifierStderr = new QSocketNotifier( sStderr[0], QSocketNotifier::Read );
788 connect( d->notifierStderr, SIGNAL(activated(int)), 788 connect( d->notifierStderr, SIGNAL(activated(int)),
789 this, SLOT(socketRead(int)) ); 789 this, SLOT(socketRead(int)) );
790 if ( ioRedirection ) 790 if ( ioRedirection )
791 d->notifierStderr->setEnabled( TRUE ); 791 d->notifierStderr->setEnabled( TRUE );
792 } 792 }
793 793
@@ -802,16 +802,16 @@ error:
802#endif 802#endif
803 if ( d->procManager ) 803 if ( d->procManager )
804 d->procManager->cleanup(); 804 d->procManager->cleanup();
805 if ( comms & Stdin ) { 805 if ( comms & Stdin ) {
806 ::close( sStdin[1] ); 806 ::close( sStdin[1] );
807 ::close( sStdin[0] ); 807 ::close( sStdin[0] );
808 } 808 }
809 if ( comms & Stdout ) { 809 if ( comms & Stdout ) {
810 ::close( sStdout[0] ); 810 ::close( sStdout[0] );
811 ::close( sStdout[1] ); 811 ::close( sStdout[1] );
812 } 812 }
813 if ( comms & Stderr ) { 813 if ( comms & Stderr ) {
814 ::close( sStderr[0] ); 814 ::close( sStderr[0] );
815 ::close( sStderr[1] ); 815 ::close( sStderr[1] );
816 } 816 }
817 ::close( fd[0] ); 817 ::close( fd[0] );
@@ -836,5 +836,5 @@ void QProcess::tryTerminate() const
836{ 836{
837 if ( d->proc != 0 ) 837 if ( d->proc != 0 )
838 ::kill( d->proc->pid, SIGTERM ); 838 ::kill( d->proc->pid, SIGTERM );
839} 839}
840 840
@@ -866,5 +866,5 @@ void QProcess::kill() const
866{ 866{
867 if ( d->proc != 0 ) 867 if ( d->proc != 0 )
868 ::kill( d->proc->pid, SIGKILL ); 868 ::kill( d->proc->pid, SIGKILL );
869} 869}
870 870
@@ -880,22 +880,22 @@ bool QProcess::isRunning() const
880 odebug << "QProcess::isRunning(): FALSE (already computed)" << oendl; 880 odebug << "QProcess::isRunning(): FALSE (already computed)" << oendl;
881#endif 881#endif
882 return FALSE; 882 return FALSE;
883 } 883 }
884 if ( d->proc == 0 ) 884 if ( d->proc == 0 )
885 return FALSE; 885 return FALSE;
886 int status; 886 int status;
887 if ( ::waitpid( d->proc->pid, &status, WNOHANG ) == d->proc->pid ) 887 if ( ::waitpid( d->proc->pid, &status, WNOHANG ) == d->proc->pid )
888 { 888 {
889 // compute the exit values 889 // compute the exit values
890 QProcess *that = (QProcess*)this; // mutable 890 QProcess *that = (QProcess*)this; // mutable
891 that->exitNormal = WIFEXITED( status ) != 0; 891 that->exitNormal = WIFEXITED( status ) != 0;
892 if ( exitNormal ) { 892 if ( exitNormal ) {
893 that->exitStat = (char)WEXITSTATUS( status ); 893 that->exitStat = (char)WEXITSTATUS( status );
894 } 894 }
895 d->exitValuesCalculated = TRUE; 895 d->exitValuesCalculated = TRUE;
896#if defined(QT_QPROCESS_DEBUG) 896#if defined(QT_QPROCESS_DEBUG)
897 odebug << "QProcess::isRunning() (PID: " << d->proc->pid << "): FALSE" << oendl; 897 odebug << "QProcess::isRunning() (PID: " << d->proc->pid << "): FALSE" << oendl;
898#endif 898#endif
899 return FALSE; 899 return FALSE;
900 } 900 }
901#if defined(QT_QPROCESS_DEBUG) 901#if defined(QT_QPROCESS_DEBUG)
@@ -924,5 +924,5 @@ void QProcess::writeToStdin( const QByteArray& buf )
924 d->stdinBuf.enqueue( new QByteArray(buf) ); 924 d->stdinBuf.enqueue( new QByteArray(buf) );
925 if ( d->notifierStdin != 0 ) 925 if ( d->notifierStdin != 0 )
926 d->notifierStdin->setEnabled( TRUE ); 926 d->notifierStdin->setEnabled( TRUE );
927} 927}
928 928
@@ -939,18 +939,18 @@ void QProcess::closeStdin()
939{ 939{
940 if ( d->proc == 0 ) 940 if ( d->proc == 0 )
941 return; 941 return;
942 if ( d->proc->socketStdin !=0 ) { 942 if ( d->proc->socketStdin !=0 ) {
943 while ( !d->stdinBuf.isEmpty() ) { 943 while ( !d->stdinBuf.isEmpty() ) {
944 delete d->stdinBuf.dequeue(); 944 delete d->stdinBuf.dequeue();
945 } 945 }
946 delete d->notifierStdin; 946 delete d->notifierStdin;
947 d->notifierStdin = 0; 947 d->notifierStdin = 0;
948 if ( ::close( d->proc->socketStdin ) != 0 ) { 948 if ( ::close( d->proc->socketStdin ) != 0 ) {
949 owarn << "Could not close stdin of child process" << oendl; 949 owarn << "Could not close stdin of child process" << oendl;
950 } 950 }
951#if defined(QT_QPROCESS_DEBUG) 951#if defined(QT_QPROCESS_DEBUG)
952 odebug << "QProcess::closeStdin(): stdin (" << d->proc->socketStdin << ") closed" << oendl; 952 odebug << "QProcess::closeStdin(): stdin (" << d->proc->socketStdin << ") closed" << oendl;
953#endif 953#endif
954 d->proc->socketStdin = 0; 954 d->proc->socketStdin = 0;
955 } 955 }
956} 956}
@@ -964,8 +964,8 @@ void QProcess::socketRead( int fd )
964{ 964{
965 if ( d->socketReadCalled ) { 965 if ( d->socketReadCalled ) {
966 // the slots that are connected to the readyRead...() signals might 966 // the slots that are connected to the readyRead...() signals might
967 // trigger a recursive call of socketRead(). Avoid this since you get a 967 // trigger a recursive call of socketRead(). Avoid this since you get a
968 // blocking read otherwise. 968 // blocking read otherwise.
969 return; 969 return;
970 } 970 }
971#if defined(QT_QPROCESS_DEBUG) 971#if defined(QT_QPROCESS_DEBUG)
@@ -973,5 +973,5 @@ void QProcess::socketRead( int fd )
973#endif 973#endif
974 if ( fd == 0 ) 974 if ( fd == 0 )
975 return; 975 return;
976 const int bufsize = 4096; 976 const int bufsize = 4096;
977 QByteArray *buffer = 0; 977 QByteArray *buffer = 0;
@@ -979,10 +979,10 @@ void QProcess::socketRead( int fd )
979 int n; 979 int n;
980 if ( fd == d->proc->socketStdout ) { 980 if ( fd == d->proc->socketStdout ) {
981 buffer = &d->bufStdout; 981 buffer = &d->bufStdout;
982 } else if ( fd == d->proc->socketStderr ) { 982 } else if ( fd == d->proc->socketStderr ) {
983 buffer = &d->bufStderr; 983 buffer = &d->bufStderr;
984 } else { 984 } else {
985 // this case should never happen, but just to be safe 985 // this case should never happen, but just to be safe
986 return; 986 return;
987 } 987 }
988 988
@@ -992,40 +992,40 @@ void QProcess::socketRead( int fd )
992 n = ::read( fd, buffer->data()+oldSize, bufsize ); 992 n = ::read( fd, buffer->data()+oldSize, bufsize );
993 if ( n > 0 ) 993 if ( n > 0 )
994 buffer->resize( oldSize + n ); 994 buffer->resize( oldSize + n );
995 else 995 else
996 buffer->resize( oldSize ); 996 buffer->resize( oldSize );
997 // eof or error? 997 // eof or error?
998 if ( n == 0 || n == -1 ) { 998 if ( n == 0 || n == -1 ) {
999 if ( fd == d->proc->socketStdout ) { 999 if ( fd == d->proc->socketStdout ) {
1000#if defined(QT_QPROCESS_DEBUG) 1000#if defined(QT_QPROCESS_DEBUG)
1001 odebug << "QProcess::socketRead(): stdout (" << fd << ") closed" << oendl; 1001 odebug << "QProcess::socketRead(): stdout (" << fd << ") closed" << oendl;
1002#endif 1002#endif
1003 d->notifierStdout->setEnabled( FALSE ); 1003 d->notifierStdout->setEnabled( FALSE );
1004 delete d->notifierStdout; 1004 delete d->notifierStdout;
1005 d->notifierStdout = 0; 1005 d->notifierStdout = 0;
1006 ::close( d->proc->socketStdout ); 1006 ::close( d->proc->socketStdout );
1007 d->proc->socketStdout = 0; 1007 d->proc->socketStdout = 0;
1008 return; 1008 return;
1009 } else if ( fd == d->proc->socketStderr ) { 1009 } else if ( fd == d->proc->socketStderr ) {
1010#if defined(QT_QPROCESS_DEBUG) 1010#if defined(QT_QPROCESS_DEBUG)
1011 odebug << "QProcess::socketRead(): stderr (" << fd << ") closed" << oendl; 1011 odebug << "QProcess::socketRead(): stderr (" << fd << ") closed" << oendl;
1012#endif 1012#endif
1013 d->notifierStderr->setEnabled( FALSE ); 1013 d->notifierStderr->setEnabled( FALSE );
1014 delete d->notifierStderr; 1014 delete d->notifierStderr;
1015 d->notifierStderr = 0; 1015 d->notifierStderr = 0;
1016 ::close( d->proc->socketStderr ); 1016 ::close( d->proc->socketStderr );
1017 d->proc->socketStderr = 0; 1017 d->proc->socketStderr = 0;
1018 return; 1018 return;
1019 } 1019 }
1020 } 1020 }
1021 // read all data that is available 1021 // read all data that is available
1022 while ( n == bufsize ) { 1022 while ( n == bufsize ) {
1023 oldSize = buffer->size(); 1023 oldSize = buffer->size();
1024 buffer->resize( oldSize + bufsize ); 1024 buffer->resize( oldSize + bufsize );
1025 n = ::read( fd, buffer->data()+oldSize, bufsize ); 1025 n = ::read( fd, buffer->data()+oldSize, bufsize );
1026 if ( n > 0 ) 1026 if ( n > 0 )
1027 buffer->resize( oldSize + n ); 1027 buffer->resize( oldSize + n );
1028 else 1028 else
1029 buffer->resize( oldSize ); 1029 buffer->resize( oldSize );
1030 } 1030 }
1031 1031
@@ -1033,14 +1033,14 @@ void QProcess::socketRead( int fd )
1033 if ( fd == d->proc->socketStdout ) { 1033 if ( fd == d->proc->socketStdout ) {
1034#if defined(QT_QPROCESS_DEBUG) 1034#if defined(QT_QPROCESS_DEBUG)
1035 qDebug( "QProcess::socketRead(): %d bytes read from stdout (%d)", 1035 odebug << "QProcess::socketRead(): " << buffer->size()-oldSize << "bytes read from stdout ("
1036 buffer->size()-oldSize, fd ); 1036 << fd << ")" << oendl;
1037#endif 1037#endif
1038 emit readyReadStdout(); 1038 emit readyReadStdout();
1039 } else if ( fd == d->proc->socketStderr ) { 1039 } else if ( fd == d->proc->socketStderr ) {
1040#if defined(QT_QPROCESS_DEBUG) 1040#if defined(QT_QPROCESS_DEBUG)
1041 qDebug( "QProcess::socketRead(): %d bytes read from stderr (%d)", 1041 odebug << "QProcess::socketRead(): " << buffer->size()-oldSize << " bytes read from stderr ("
1042 buffer->size()-oldSize, fd ); 1042 << fd << ")" << oendl;
1043#endif 1043#endif
1044 emit readyReadStderr(); 1044 emit readyReadStderr();
1045 } 1045 }
1046 d->socketReadCalled = FALSE; 1046 d->socketReadCalled = FALSE;
@@ -1055,8 +1055,8 @@ void QProcess::socketWrite( int fd )
1055{ 1055{
1056 if ( fd != d->proc->socketStdin || d->proc->socketStdin == 0 ) 1056 if ( fd != d->proc->socketStdin || d->proc->socketStdin == 0 )
1057 return; 1057 return;
1058 if ( d->stdinBuf.isEmpty() ) { 1058 if ( d->stdinBuf.isEmpty() ) {
1059 d->notifierStdin->setEnabled( FALSE ); 1059 d->notifierStdin->setEnabled( FALSE );
1060 return; 1060 return;
1061 } 1061 }
1062#if defined(QT_QPROCESS_DEBUG) 1062#if defined(QT_QPROCESS_DEBUG)
@@ -1064,14 +1064,14 @@ void QProcess::socketWrite( int fd )
1064#endif 1064#endif
1065 ssize_t ret = ::write( fd, 1065 ssize_t ret = ::write( fd,
1066 d->stdinBuf.head()->data() + d->stdinBufRead, 1066 d->stdinBuf.head()->data() + d->stdinBufRead,
1067 d->stdinBuf.head()->size() - d->stdinBufRead ); 1067 d->stdinBuf.head()->size() - d->stdinBufRead );
1068 if ( ret > 0 ) 1068 if ( ret > 0 )
1069 d->stdinBufRead += ret; 1069 d->stdinBufRead += ret;
1070 if ( d->stdinBufRead == (ssize_t)d->stdinBuf.head()->size() ) { 1070 if ( d->stdinBufRead == (ssize_t)d->stdinBuf.head()->size() ) {
1071 d->stdinBufRead = 0; 1071 d->stdinBufRead = 0;
1072 delete d->stdinBuf.dequeue(); 1072 delete d->stdinBuf.dequeue();
1073 if ( wroteToStdinConnected && d->stdinBuf.isEmpty() ) 1073 if ( wroteToStdinConnected && d->stdinBuf.isEmpty() )
1074 emit wroteToStdin(); 1074 emit wroteToStdin();
1075 socketWrite( fd ); 1075 socketWrite( fd );
1076 } 1076 }
1077} 1077}
@@ -1106,13 +1106,13 @@ void QProcess::setIoRedirection( bool value )
1106 ioRedirection = value; 1106 ioRedirection = value;
1107 if ( ioRedirection ) { 1107 if ( ioRedirection ) {
1108 if ( d->notifierStdout ) 1108 if ( d->notifierStdout )
1109 d->notifierStdout->setEnabled( TRUE ); 1109 d->notifierStdout->setEnabled( TRUE );
1110 if ( d->notifierStderr ) 1110 if ( d->notifierStderr )
1111 d->notifierStderr->setEnabled( TRUE ); 1111 d->notifierStderr->setEnabled( TRUE );
1112 } else { 1112 } else {
1113 if ( d->notifierStdout ) 1113 if ( d->notifierStdout )
1114 d->notifierStdout->setEnabled( FALSE ); 1114 d->notifierStdout->setEnabled( FALSE );
1115 if ( d->notifierStderr ) 1115 if ( d->notifierStderr )
1116 d->notifierStderr->setEnabled( FALSE ); 1116 d->notifierStderr->setEnabled( FALSE );
1117 } 1117 }
1118} 1118}
@@ -1153,5 +1153,5 @@ QProcess::PID QProcess::processIdentifier()
1153{ 1153{
1154 if ( d->proc == 0 ) 1154 if ( d->proc == 0 )
1155 return -1; 1155 return -1;
1156 return d->proc->pid; 1156 return d->proc->pid;
1157} 1157}
@@ -1160,5 +1160,5 @@ int QProcess::priority() const
1160{ 1160{
1161 if ( d->proc ) 1161 if ( d->proc )
1162 return getpriority(PRIO_PROCESS,d->proc->pid); 1162 return getpriority(PRIO_PROCESS,d->proc->pid);
1163 return 0; 1163 return 0;
1164} 1164}
@@ -1167,5 +1167,5 @@ void QProcess::setPriority(int p)
1167{ 1167{
1168 if ( d->proc ) 1168 if ( d->proc )
1169 setpriority(PRIO_PROCESS,d->proc->pid,p); 1169 setpriority(PRIO_PROCESS,d->proc->pid,p);
1170} 1170}
1171 1171