00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include "oprocctrl.h"
00032
00033
00034 #include <opie2/oprocess.h>
00035
00036
00037
00038 #include <qapplication.h>
00039 #include <qdir.h>
00040 #include <qmap.h>
00041 #include <qsocketnotifier.h>
00042 #include <qtextstream.h>
00043
00044
00045 #include <errno.h>
00046 #include <fcntl.h>
00047 #include <pwd.h>
00048 #include <stdlib.h>
00049 #include <signal.h>
00050 #include <stdio.h>
00051 #include <string.h>
00052 #include <sys/time.h>
00053 #include <sys/types.h>
00054 #include <sys/stat.h>
00055 #include <sys/socket.h>
00056 #include <unistd.h>
00057 #ifdef HAVE_SYS_SELECT_H
00058 #include <sys/select.h>
00059 #endif
00060 #ifdef HAVE_INITGROUPS
00061 #include <grp.h>
00062 #endif
00063
00064 using namespace Opie::Core::Internal;
00065
00066 namespace Opie {
00067 namespace Core {
00068 namespace Internal {
00069 class OProcessPrivate
00070 {
00071 public:
00072 OProcessPrivate() : useShell( false )
00073 { }
00074
00075 bool useShell;
00076 QMap<QString, QString> env;
00077 QString wd;
00078 QCString shell;
00079 };
00080 }
00081
00082 OProcess::OProcess( QObject *parent, const char *name )
00083 : QObject( parent, name )
00084 {
00085 init ( );
00086 }
00087
00088 OProcess::OProcess( const QString &arg0, QObject *parent, const char *name )
00089 : QObject( parent, name )
00090 {
00091 init ( );
00092 *this << arg0;
00093 }
00094
00095 OProcess::OProcess( const QStringList &args, QObject *parent, const char *name )
00096 : QObject( parent, name )
00097 {
00098 init ( );
00099 *this << args;
00100 }
00101
00102 void OProcess::init ( )
00103 {
00104 run_mode = NotifyOnExit;
00105 runs = false;
00106 pid_ = 0;
00107 status = 0;
00108 keepPrivs = false;
00109 innot = 0;
00110 outnot = 0;
00111 errnot = 0;
00112 communication = NoCommunication;
00113 input_data = 0;
00114 input_sent = 0;
00115 input_total = 0;
00116 d = 0;
00117
00118 if ( 0 == OProcessController::theOProcessController )
00119 {
00120 ( void ) new OProcessController();
00121 CHECK_PTR( OProcessController::theOProcessController );
00122 }
00123
00124 OProcessController::theOProcessController->addOProcess( this );
00125 out[ 0 ] = out[ 1 ] = -1;
00126 in[ 0 ] = in[ 1 ] = -1;
00127 err[ 0 ] = err[ 1 ] = -1;
00128 }
00129
00130 void OProcess::setEnvironment( const QString &name, const QString &value )
00131 {
00132 if ( !d )
00133 d = new OProcessPrivate;
00134 d->env.insert( name, value );
00135 }
00136
00137 void OProcess::setWorkingDirectory( const QString &dir )
00138 {
00139 if ( !d )
00140 d = new OProcessPrivate;
00141 d->wd = dir;
00142 }
00143
00144 void OProcess::setupEnvironment()
00145 {
00146 if ( d )
00147 {
00148 QMap<QString, QString>::Iterator it;
00149 for ( it = d->env.begin(); it != d->env.end(); ++it )
00150 setenv( QFile::encodeName( it.key() ).data(),
00151 QFile::encodeName( it.data() ).data(), 1 );
00152 if ( !d->wd.isEmpty() )
00153 chdir( QFile::encodeName( d->wd ).data() );
00154 }
00155 }
00156
00157 void OProcess::setRunPrivileged( bool keepPrivileges )
00158 {
00159 keepPrivs = keepPrivileges;
00160 }
00161
00162 bool OProcess::runPrivileged() const
00163 {
00164 return keepPrivs;
00165 }
00166
00167 OProcess::~OProcess()
00168 {
00169
00170
00171
00172
00173
00174 OProcessController::theOProcessController->removeOProcess( this );
00175
00176
00177
00178 if ( runs && ( run_mode != DontCare ) )
00179 kill( SIGKILL );
00180
00181
00182 closeStdin();
00183 closeStdout();
00184 closeStderr();
00185
00186
00187 delete d;
00188 }
00189
00190 void OProcess::detach()
00191 {
00192 OProcessController::theOProcessController->removeOProcess( this );
00193
00194 runs = false;
00195 pid_ = 0;
00196
00197
00198 closeStdin();
00199 closeStdout();
00200 closeStderr();
00201 }
00202
00203 bool OProcess::setExecutable( const QString& proc )
00204 {
00205 if ( runs )
00206 return false;
00207
00208 if ( proc.isEmpty() )
00209 return false;
00210
00211 if ( !arguments.isEmpty() )
00212 arguments.remove( arguments.begin() );
00213 arguments.prepend( QFile::encodeName( proc ) );
00214
00215 return true;
00216 }
00217
00218 OProcess &OProcess::operator<<( const QStringList& args )
00219 {
00220 QStringList::ConstIterator it = args.begin();
00221 for ( ; it != args.end() ; ++it )
00222 arguments.append( QFile::encodeName( *it ) );
00223 return *this;
00224 }
00225
00226 OProcess &OProcess::operator<<( const QCString& arg )
00227 {
00228 return operator<< ( arg.data() );
00229 }
00230
00231 OProcess &OProcess::operator<<( const char* arg )
00232 {
00233 arguments.append( arg );
00234 return *this;
00235 }
00236
00237 OProcess &OProcess::operator<<( const QString& arg )
00238 {
00239 arguments.append( QFile::encodeName( arg ) );
00240 return *this;
00241 }
00242
00243 void OProcess::clearArguments()
00244 {
00245 arguments.clear();
00246 }
00247
00248 bool OProcess::start( RunMode runmode, Communication comm )
00249 {
00250 uint i;
00251 uint n = arguments.count();
00252 char **arglist;
00253
00254 if ( runs || ( 0 == n ) )
00255 {
00256 return false;
00257
00258 }
00259 run_mode = runmode;
00260 status = 0;
00261
00262 QCString shellCmd;
00263 if ( d && d->useShell )
00264 {
00265 if ( d->shell.isEmpty() )
00266 {
00267 qWarning( "Could not find a valid shell" );
00268 return false;
00269 }
00270
00271 arglist = static_cast<char **>( malloc( ( 4 ) * sizeof( char * ) ) );
00272 for ( i = 0; i < n; i++ )
00273 {
00274 shellCmd += arguments[ i ];
00275 shellCmd += " ";
00276 }
00277
00278 arglist[ 0 ] = d->shell.data();
00279 arglist[ 1 ] = ( char * ) "-c";
00280 arglist[ 2 ] = shellCmd.data();
00281 arglist[ 3 ] = 0;
00282 }
00283 else
00284 {
00285 arglist = static_cast<char **>( malloc( ( n + 1 ) * sizeof( char * ) ) );
00286 for ( i = 0; i < n; i++ )
00287 arglist[ i ] = arguments[ i ].data();
00288 arglist[ n ] = 0;
00289 }
00290
00291 if ( !setupCommunication( comm ) )
00292 qWarning( "Could not setup Communication!" );
00293
00294
00295
00296 uid_t uid = getuid();
00297 gid_t gid = getgid();
00298 #ifdef HAVE_INITGROUPS
00299
00300 struct passwd *pw = getpwuid( uid );
00301 #endif
00302
00303 int fd[ 2 ];
00304 if ( 0 > pipe( fd ) )
00305 {
00306 fd[ 0 ] = fd[ 1 ] = 0;
00307 }
00308
00309 runs = true;
00310
00311 QApplication::flushX();
00312
00313
00314
00315 pid_ = fork();
00316
00317 if ( 0 == pid_ )
00318 {
00319 if ( fd[ 0 ] )
00320 close( fd[ 0 ] );
00321 if ( !runPrivileged() )
00322 {
00323 setgid( gid );
00324 #if defined( HAVE_INITGROUPS)
00325
00326 if ( pw )
00327 initgroups( pw->pw_name, pw->pw_gid );
00328 #endif
00329
00330 setuid( uid );
00331 }
00332
00333 if ( !commSetupDoneC() )
00334 qWarning( "Could not finish comm setup in child!" );
00335
00336 setupEnvironment();
00337
00338
00339 if ( run_mode == DontCare )
00340 setpgid( 0, 0 );
00341
00342 struct sigaction act;
00343 sigemptyset( &( act.sa_mask ) );
00344 sigaddset( &( act.sa_mask ), SIGPIPE );
00345 act.sa_handler = SIG_DFL;
00346 act.sa_flags = 0;
00347 sigaction( SIGPIPE, &act, 0L );
00348
00349
00350
00351 if ( fd[ 1 ] )
00352 fcntl( fd[ 1 ], F_SETFD, FD_CLOEXEC );
00353 execvp( arglist[ 0 ], arglist );
00354 char resultByte = 1;
00355 if ( fd[ 1 ] )
00356 write( fd[ 1 ], &resultByte, 1 );
00357 _exit( -1 );
00358 }
00359 else if ( -1 == pid_ )
00360 {
00361
00362
00363 runs = false;
00364 free( arglist );
00365 return false;
00366 }
00367 else
00368 {
00369 if ( fd[ 1 ] )
00370 close( fd[ 1 ] );
00371
00372
00373
00374 input_data = 0;
00375
00376
00377 if ( fd[ 0 ] )
00378 for ( ;; )
00379 {
00380 char resultByte;
00381 int n = ::read( fd[ 0 ], &resultByte, 1 );
00382 if ( n == 1 )
00383 {
00384
00385 runs = false;
00386 close( fd[ 0 ] );
00387 free( arglist );
00388 pid_ = 0;
00389 return false;
00390 }
00391 if ( n == -1 )
00392 {
00393 if ( ( errno == ECHILD ) || ( errno == EINTR ) )
00394 continue;
00395 }
00396 break;
00397 }
00398 if ( fd[ 0 ] )
00399 close( fd[ 0 ] );
00400
00401 if ( !commSetupDoneP() )
00402 qWarning( "Could not finish comm setup in parent!" );
00403
00404 if ( run_mode == Block )
00405 {
00406 commClose();
00407
00408
00409
00410 while ( runs )
00411 {
00412 OProcessController::theOProcessController->
00413 slotDoHousekeeping( 0 );
00414 }
00415 runs = FALSE;
00416 emit processExited( this );
00417 }
00418 }
00419 free( arglist );
00420 return true;
00421 }
00422
00423
00424
00425 bool OProcess::kill( int signo )
00426 {
00427 bool rv = false;
00428
00429 if ( 0 != pid_ )
00430 rv = ( -1 != ::kill( pid_, signo ) );
00431
00432 return rv;
00433 }
00434
00435 bool OProcess::isRunning() const
00436 {
00437 return runs;
00438 }
00439
00440 pid_t OProcess::pid() const
00441 {
00442 return pid_;
00443 }
00444
00445 bool OProcess::normalExit() const
00446 {
00447 int _status = status;
00448 return ( pid_ != 0 ) && ( !runs ) && ( WIFEXITED( ( _status ) ) );
00449 }
00450
00451 int OProcess::exitStatus() const
00452 {
00453 int _status = status;
00454 return WEXITSTATUS( ( _status ) );
00455 }
00456
00457 bool OProcess::writeStdin( const char *buffer, int buflen )
00458 {
00459 bool rv;
00460
00461
00462
00463
00464 if ( 0 != input_data )
00465 return false;
00466
00467 if ( runs && ( communication & Stdin ) )
00468 {
00469 input_data = buffer;
00470 input_sent = 0;
00471 input_total = buflen;
00472 slotSendData( 0 );
00473 innot->setEnabled( true );
00474 rv = true;
00475 }
00476 else
00477 rv = false;
00478 return rv;
00479 }
00480
00481 void OProcess::flushStdin ( )
00482 {
00483 if ( !input_data || ( input_sent == input_total ) )
00484 return ;
00485
00486 int d1, d2;
00487
00488 do
00489 {
00490 d1 = input_total - input_sent;
00491 slotSendData ( 0 );
00492 d2 = input_total - input_sent;
00493 }
00494 while ( d2 <= d1 );
00495 }
00496
00497 void OProcess::suspend()
00498 {
00499 if ( ( communication & Stdout ) && outnot )
00500 outnot->setEnabled( false );
00501 }
00502
00503 void OProcess::resume()
00504 {
00505 if ( ( communication & Stdout ) && outnot )
00506 outnot->setEnabled( true );
00507 }
00508
00509 bool OProcess::closeStdin()
00510 {
00511 bool rv;
00512
00513 if ( communication & Stdin )
00514 {
00515 communication = ( Communication ) ( communication & ~Stdin );
00516 delete innot;
00517 innot = 0;
00518 close( in[ 1 ] );
00519 rv = true;
00520 }
00521 else
00522 rv = false;
00523 return rv;
00524 }
00525
00526 bool OProcess::closeStdout()
00527 {
00528 bool rv;
00529
00530 if ( communication & Stdout )
00531 {
00532 communication = ( Communication ) ( communication & ~Stdout );
00533 delete outnot;
00534 outnot = 0;
00535 close( out[ 0 ] );
00536 rv = true;
00537 }
00538 else
00539 rv = false;
00540 return rv;
00541 }
00542
00543 bool OProcess::closeStderr()
00544 {
00545 bool rv;
00546
00547 if ( communication & Stderr )
00548 {
00549 communication = static_cast<Communication>( communication & ~Stderr );
00550 delete errnot;
00551 errnot = 0;
00552 close( err[ 0 ] );
00553 rv = true;
00554 }
00555 else
00556 rv = false;
00557 return rv;
00558 }
00559
00560 void OProcess::slotChildOutput( int fdno )
00561 {
00562 if ( !childOutput( fdno ) )
00563 closeStdout();
00564 }
00565
00566 void OProcess::slotChildError( int fdno )
00567 {
00568 if ( !childError( fdno ) )
00569 closeStderr();
00570 }
00571
00572 void OProcess::slotSendData( int )
00573 {
00574 if ( input_sent == input_total )
00575 {
00576 innot->setEnabled( false );
00577 input_data = 0;
00578 emit wroteStdin( this );
00579 }
00580 else
00581 input_sent += ::write( in[ 1 ], input_data + input_sent, input_total - input_sent );
00582 }
00583
00584 void OProcess::processHasExited( int state )
00585 {
00586 if ( runs )
00587 {
00588 runs = false;
00589 status = state;
00590
00591 commClose();
00592
00593
00594 if ( DontCare != run_mode )
00595 {
00596 emit processExited( this );
00597 }
00598 }
00599 }
00600
00601 int OProcess::childOutput( int fdno )
00602 {
00603 if ( communication & NoRead )
00604 {
00605 int len = -1;
00606 emit receivedStdout( fdno, len );
00607 errno = 0;
00608 return len;
00609 }
00610 else
00611 {
00612 char buffer[ 1024 ];
00613 int len;
00614
00615 len = ::read( fdno, buffer, 1024 );
00616
00617 if ( 0 < len )
00618 {
00619 emit receivedStdout( this, buffer, len );
00620 }
00621 return len;
00622 }
00623 }
00624
00625 int OProcess::childError( int fdno )
00626 {
00627 char buffer[ 1024 ];
00628 int len;
00629
00630 len = ::read( fdno, buffer, 1024 );
00631
00632 if ( 0 < len )
00633 emit receivedStderr( this, buffer, len );
00634 return len;
00635 }
00636
00637 int OProcess::setupCommunication( Communication comm )
00638 {
00639 int ok;
00640
00641 communication = comm;
00642
00643 ok = 1;
00644 if ( comm & Stdin )
00645 ok &= socketpair( AF_UNIX, SOCK_STREAM, 0, in ) >= 0;
00646
00647 if ( comm & Stdout )
00648 ok &= socketpair( AF_UNIX, SOCK_STREAM, 0, out ) >= 0;
00649
00650 if ( comm & Stderr )
00651 ok &= socketpair( AF_UNIX, SOCK_STREAM, 0, err ) >= 0;
00652
00653 return ok;
00654 }
00655
00656 int OProcess::commSetupDoneP()
00657 {
00658 int ok = 1;
00659
00660 if ( communication != NoCommunication )
00661 {
00662 if ( communication & Stdin )
00663 close( in[ 0 ] );
00664 if ( communication & Stdout )
00665 close( out[ 1 ] );
00666 if ( communication & Stderr )
00667 close( err[ 1 ] );
00668
00669
00670
00671 if ( run_mode == Block )
00672 return ok;
00673
00674 if ( communication & Stdin )
00675 {
00676
00677 innot = new QSocketNotifier( in[ 1 ], QSocketNotifier::Write, this );
00678 CHECK_PTR( innot );
00679 innot->setEnabled( false );
00680 QObject::connect( innot, SIGNAL( activated(int) ),
00681 this, SLOT( slotSendData(int) ) );
00682 }
00683
00684 if ( communication & Stdout )
00685 {
00686
00687 outnot = new QSocketNotifier( out[ 0 ], QSocketNotifier::Read, this );
00688 CHECK_PTR( outnot );
00689 QObject::connect( outnot, SIGNAL( activated(int) ),
00690 this, SLOT( slotChildOutput(int) ) );
00691 if ( communication & NoRead )
00692 suspend();
00693 }
00694
00695 if ( communication & Stderr )
00696 {
00697
00698 errnot = new QSocketNotifier( err[ 0 ], QSocketNotifier::Read, this );
00699 CHECK_PTR( errnot );
00700 QObject::connect( errnot, SIGNAL( activated(int) ),
00701 this, SLOT( slotChildError(int) ) );
00702 }
00703 }
00704 return ok;
00705 }
00706
00707 int OProcess::commSetupDoneC()
00708 {
00709 int ok = 1;
00710 struct linger so;
00711 memset( &so, 0, sizeof( so ) );
00712
00713 if ( communication & Stdin )
00714 close( in[ 1 ] );
00715 if ( communication & Stdout )
00716 close( out[ 0 ] );
00717 if ( communication & Stderr )
00718 close( err[ 0 ] );
00719
00720 if ( communication & Stdin )
00721 ok &= dup2( in[ 0 ], STDIN_FILENO ) != -1;
00722 else
00723 {
00724 int null_fd = open( "/dev/null", O_RDONLY );
00725 ok &= dup2( null_fd, STDIN_FILENO ) != -1;
00726 close( null_fd );
00727 }
00728 if ( communication & Stdout )
00729 {
00730 ok &= dup2( out[ 1 ], STDOUT_FILENO ) != -1;
00731 ok &= !setsockopt( out[ 1 ], SOL_SOCKET, SO_LINGER, ( char* ) & so, sizeof( so ) );
00732 }
00733 else
00734 {
00735 int null_fd = open( "/dev/null", O_WRONLY );
00736 ok &= dup2( null_fd, STDOUT_FILENO ) != -1;
00737 close( null_fd );
00738 }
00739 if ( communication & Stderr )
00740 {
00741 ok &= dup2( err[ 1 ], STDERR_FILENO ) != -1;
00742 ok &= !setsockopt( err[ 1 ], SOL_SOCKET, SO_LINGER, reinterpret_cast<char *>( &so ), sizeof( so ) );
00743 }
00744 else
00745 {
00746 int null_fd = open( "/dev/null", O_WRONLY );
00747 ok &= dup2( null_fd, STDERR_FILENO ) != -1;
00748 close( null_fd );
00749 }
00750 return ok;
00751 }
00752
00753 void OProcess::commClose()
00754 {
00755 if ( NoCommunication != communication )
00756 {
00757 bool b_in = ( communication & Stdin );
00758 bool b_out = ( communication & Stdout );
00759 bool b_err = ( communication & Stderr );
00760 if ( b_in )
00761 delete innot;
00762
00763 if ( b_out || b_err )
00764 {
00765
00766
00767
00768
00769
00770
00771
00772 int fds_ready = 1;
00773 fd_set rfds;
00774
00775 int max_fd = 0;
00776 if ( b_out )
00777 {
00778 fcntl( out[ 0 ], F_SETFL, O_NONBLOCK );
00779 if ( out[ 0 ] > max_fd )
00780 max_fd = out[ 0 ];
00781 delete outnot;
00782 outnot = 0;
00783 }
00784 if ( b_err )
00785 {
00786 fcntl( err[ 0 ], F_SETFL, O_NONBLOCK );
00787 if ( err[ 0 ] > max_fd )
00788 max_fd = err[ 0 ];
00789 delete errnot;
00790 errnot = 0;
00791 }
00792
00793
00794 while ( b_out || b_err )
00795 {
00796
00797
00798
00799
00800
00801 struct timeval timeout;
00802 timeout.tv_sec = 0;
00803 timeout.tv_usec = 0;
00804 struct timeval *p_timeout = runs ? 0 : &timeout;
00805
00806 FD_ZERO( &rfds );
00807 if ( b_out )
00808 FD_SET( out[ 0 ], &rfds );
00809
00810 if ( b_err )
00811 FD_SET( err[ 0 ], &rfds );
00812
00813 fds_ready = select( max_fd + 1, &rfds, 0, 0, p_timeout );
00814 if ( fds_ready <= 0 )
00815 break;
00816
00817 if ( b_out && FD_ISSET( out[ 0 ], &rfds ) )
00818 {
00819 int ret = 1;
00820 while ( ret > 0 )
00821 ret = childOutput( out[ 0 ] );
00822 if ( ( ret == -1 && errno != EAGAIN ) || ret == 0 )
00823 b_out = false;
00824 }
00825
00826 if ( b_err && FD_ISSET( err[ 0 ], &rfds ) )
00827 {
00828 int ret = 1;
00829 while ( ret > 0 )
00830 ret = childError( err[ 0 ] );
00831 if ( ( ret == -1 && errno != EAGAIN ) || ret == 0 )
00832 b_err = false;
00833 }
00834 }
00835 }
00836
00837 if ( b_in )
00838 {
00839 communication = ( Communication ) ( communication & ~Stdin );
00840 close( in[ 1 ] );
00841 }
00842 if ( b_out )
00843 {
00844 communication = ( Communication ) ( communication & ~Stdout );
00845 close( out[ 0 ] );
00846 }
00847 if ( b_err )
00848 {
00849 communication = ( Communication ) ( communication & ~Stderr );
00850 close( err[ 0 ] );
00851 }
00852 }
00853 }
00854
00855 void OProcess::setUseShell( bool useShell, const char *shell )
00856 {
00857 if ( !d )
00858 d = new OProcessPrivate;
00859 d->useShell = useShell;
00860 d->shell = shell;
00861 if ( d->shell.isEmpty() )
00862 d->shell = searchShell();
00863 }
00864
00865 QString OProcess::quote( const QString &arg )
00866 {
00867 QString res = arg;
00868 res.replace( QRegExp( QString::fromLatin1( "\'" ) ),
00869 QString::fromLatin1( "'\"'\"'" ) );
00870 res.prepend( '\'' );
00871 res.append( '\'' );
00872 return res;
00873 }
00874
00875 QCString OProcess::searchShell()
00876 {
00877 QCString tmpShell = QCString( getenv( "SHELL" ) ).stripWhiteSpace();
00878 if ( !isExecutable( tmpShell ) )
00879 {
00880 tmpShell = "/bin/sh";
00881 }
00882
00883 return tmpShell;
00884 }
00885
00886 bool OProcess::isExecutable( const QCString &filename )
00887 {
00888 struct stat fileinfo;
00889
00890 if ( filename.isEmpty() )
00891 return false;
00892
00893
00894
00895 if ( -1 == stat( filename.data(), &fileinfo ) )
00896 return false;
00897
00898
00899
00900 if ( ( S_ISDIR( fileinfo.st_mode ) ) ||
00901 ( S_ISCHR( fileinfo.st_mode ) ) ||
00902 ( S_ISBLK( fileinfo.st_mode ) ) ||
00903 #ifdef S_ISSOCK
00904
00905 ( S_ISSOCK( fileinfo.st_mode ) ) ||
00906 #endif
00907 ( S_ISFIFO( fileinfo.st_mode ) ) ||
00908 ( S_ISDIR( fileinfo.st_mode ) ) )
00909 {
00910 return false;
00911 }
00912
00913
00914 if ( access( filename.data(), X_OK ) != 0 )
00915 return false;
00916
00917
00918 return true;
00919 }
00920
00921 int OProcess::processPID( const QString& process )
00922 {
00923 QString line;
00924 QDir d = QDir( "/proc" );
00925 QStringList dirs = d.entryList( QDir::Dirs );
00926 QStringList::Iterator it;
00927 for ( it = dirs.begin(); it != dirs.end(); ++it )
00928 {
00929
00930 QFile file( "/proc/"+*it+"/cmdline" );
00931 file.open( IO_ReadOnly );
00932 if ( !file.isOpen() ) continue;
00933 QTextStream t( &file );
00934 line = t.readLine();
00935
00936 if ( line.contains( process ) ) break;
00937 }
00938 if ( line.contains( process ) )
00939 {
00940
00941 return (*it).toInt();
00942 }
00943 else
00944 {
00945
00946 return 0;
00947 }
00948 }
00949
00950 }
00951 }