Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

qprocess.cpp

Go to the documentation of this file.
00001 /**********************************************************************
00002 ** Copyright (C) 2000-2002 Trolltech AS.  All rights reserved.
00003 **
00004 ** This file is part of the Qtopia Environment.
00005 **
00006 ** This file may be distributed and/or modified under the terms of the
00007 ** GNU General Public License version 2 as published by the Free Software
00008 ** Foundation and appearing in the file LICENSE.GPL included in the
00009 ** packaging of this file.
00010 **
00011 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00012 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00013 **
00014 ** See http://www.trolltech.com/gpl/ for GPL licensing information.
00015 **
00016 ** Contact info@trolltech.com if any conditions of this licensing are
00017 ** not clear to you.
00018 **
00019 **********************************************************************/
00020 
00021 #include <stdio.h>
00022 #include <stdlib.h>
00023 
00024 #include "qprocess.h"
00025 
00026 #ifndef QT_NO_PROCESS
00027 
00028 #include "qapplication.h"
00029 
00030 
00031 //#define QT_QPROCESS_DEBUG
00032 
00033 
00075 QProcess::QProcess( QObject *parent, const char *name )
00076     : QObject( parent, name ), ioRedirection( FALSE ), notifyOnExit( FALSE ),
00077     wroteToStdinConnected( FALSE ),
00078     readStdoutCalled( FALSE ), readStderrCalled( FALSE ),
00079     comms( Stdin|Stdout|Stderr )
00080 {
00081     init();
00082 }
00083 
00093 QProcess::QProcess( const QString& arg0, QObject *parent, const char *name )
00094     : QObject( parent, name ), ioRedirection( FALSE ), notifyOnExit( FALSE ),
00095     wroteToStdinConnected( FALSE ),
00096     readStdoutCalled( FALSE ), readStderrCalled( FALSE ),
00097     comms( Stdin|Stdout|Stderr )
00098 {
00099     init();
00100     addArgument( arg0 );
00101 }
00102 
00114 QProcess::QProcess( const QStringList& args, QObject *parent, const char *name )
00115     : QObject( parent, name ), ioRedirection( FALSE ), notifyOnExit( FALSE ),
00116     wroteToStdinConnected( FALSE ),
00117     readStdoutCalled( FALSE ), readStderrCalled( FALSE ),
00118     comms( Stdin|Stdout|Stderr )
00119 {
00120     init();
00121     setArguments( args );
00122 }
00123 
00124 
00132 QStringList QProcess::arguments() const
00133 {
00134     return _arguments;
00135 }
00136 
00142 void QProcess::clearArguments()
00143 {
00144     _arguments.clear();
00145 }
00146 
00154 void QProcess::setArguments( const QStringList& args )
00155 {
00156     _arguments = args;
00157 }
00158 
00167 void QProcess::addArgument( const QString& arg )
00168 {
00169     _arguments.append( arg );
00170 }
00171 
00172 #ifndef QT_NO_DIR
00173 
00180 QDir QProcess::workingDirectory() const
00181 {
00182     return workingDir;
00183 }
00184 
00194 void QProcess::setWorkingDirectory( const QDir& dir )
00195 {
00196     workingDir = dir;
00197 }
00198 #endif //QT_NO_DIR
00199 
00205 int QProcess::communication() const
00206 {
00207     return comms;
00208 }
00209 
00219 void QProcess::setCommunication( int commFlags )
00220 {
00221     comms = commFlags;
00222 }
00223 
00231 bool QProcess::normalExit() const
00232 {
00233     // isRunning() has the side effect that it determines the exit status!
00234     if ( isRunning() )
00235         return FALSE;
00236     else
00237         return exitNormal;
00238 }
00239 
00251 int QProcess::exitStatus() const
00252 {
00253     // isRunning() has the side effect that it determines the exit status!
00254     if ( isRunning() )
00255         return 0;
00256     else
00257         return exitStat;
00258 }
00259 
00260 
00271 QByteArray QProcess::readStdout()
00272 {
00273     if ( readStdoutCalled ) {
00274         return QByteArray();
00275     }
00276     readStdoutCalled = TRUE;
00277 
00278     QByteArray buf = bufStdout()->copy();
00279     consumeBufStdout( -1 ); // consume everything
00280 
00281     readStdoutCalled = FALSE;
00282     return buf;
00283 }
00284 
00295 QByteArray QProcess::readStderr()
00296 {
00297     if ( readStderrCalled ) {
00298         return QByteArray();
00299     }
00300     readStderrCalled = TRUE;
00301 
00302     QByteArray buf = bufStderr()->copy();
00303     consumeBufStderr( -1 ); // consume everything
00304 
00305     readStderrCalled = FALSE;
00306     return buf;
00307 }
00308 
00315 bool QProcess::canReadLineStdout() const
00316 {
00317     QProcess *that = (QProcess*)this;
00318     return that->scanNewline( TRUE, 0 );
00319 }
00320 
00327 bool QProcess::canReadLineStderr() const
00328 {
00329     QProcess *that = (QProcess*)this;
00330     return that->scanNewline( FALSE, 0 );
00331 }
00332 
00340 QString QProcess::readLineStdout()
00341 {
00342     QByteArray a;
00343     QString s;
00344     if ( scanNewline( TRUE, &a ) ) {
00345         if ( a.isEmpty() )
00346             s = "";
00347         else
00348             s = QString( a );
00349     }
00350     return s;
00351 }
00352 
00360 QString QProcess::readLineStderr()
00361 {
00362     QByteArray a;
00363     QString s;
00364     if ( scanNewline( FALSE, &a ) ) {
00365         if ( a.isEmpty() )
00366             s = "";
00367         else
00368             s = QString( a );
00369     }
00370     return s;
00371 }
00372 
00378 bool QProcess::scanNewline( bool stdOut, QByteArray *store )
00379 {
00380     QByteArray *buf;
00381     if ( stdOut )
00382         buf = bufStdout();
00383     else
00384         buf = bufStderr();
00385     uint n = buf->size();
00386     uint i;
00387     for ( i=0; i<n; i++ ) {
00388         if ( buf->at(i) == '\n' ) {
00389             break;
00390         }
00391     }
00392     if ( i >= n )
00393         return FALSE;
00394 
00395     if ( store ) {
00396         uint lineLength = i;
00397         if ( lineLength>0 && buf->at(lineLength-1) == '\r' )
00398             lineLength--; // (if there are two \r, let one stay)
00399         store->resize( lineLength );
00400         memcpy( store->data(), buf->data(), lineLength );
00401         if ( stdOut )
00402             consumeBufStdout( i+1 );
00403         else
00404             consumeBufStderr( i+1 );
00405     }
00406     return TRUE;
00407 }
00408 
00459 bool QProcess::launch( const QByteArray& buf, QStringList *env )
00460 {
00461     if ( start( env ) ) {
00462         if ( !buf.isEmpty() ) {
00463             connect( this, SIGNAL(wroteToStdin()),
00464                     this, SLOT(closeStdinLaunch()) );
00465             writeToStdin( buf );
00466         } else {
00467             closeStdin();
00468             emit launchFinished();
00469         }
00470         return TRUE;
00471     } else {
00472         emit launchFinished();
00473         return FALSE;
00474     }
00475 }
00476 
00482 bool QProcess::launch( const QString& buf, QStringList *env )
00483 {
00484     if ( start( env ) ) {
00485         if ( !buf.isEmpty() ) {
00486             connect( this, SIGNAL(wroteToStdin()),
00487                     this, SLOT(closeStdinLaunch()) );
00488             writeToStdin( buf );
00489         } else {
00490             closeStdin();
00491             emit launchFinished();
00492         }
00493         return TRUE;
00494     } else {
00495         emit launchFinished();
00496         return FALSE;
00497     }
00498 }
00499 
00503 void QProcess::closeStdinLaunch()
00504 {
00505     disconnect( this, SIGNAL(wroteToStdin()),
00506             this, SLOT(closeStdinLaunch()) );
00507     closeStdin();
00508     emit launchFinished();
00509 }
00510 
00511 
00563 void QProcess::writeToStdin( const QString& buf )
00564 {
00565     QByteArray tmp = buf.local8Bit();
00566     tmp.resize( buf.length() );
00567     writeToStdin( tmp );
00568 }
00569 
00570 
00571 /*
00572  * Under Windows the implementation is not so nice: it is not that easy to
00573  * detect when one of the signals should be emitted; therefore there are some
00574  * timers that query the information.
00575  * To keep it a little efficient, use the timers only when they are needed.
00576  * They are needed, if you are interested in the signals. So use
00577  * connectNotify() and disconnectNotify() to keep track of your interest.
00578  */
00581 void QProcess::connectNotify( const char * signal )
00582 {
00583 #if defined(QT_QPROCESS_DEBUG)
00584     odebug << "QProcess::connectNotify(): signal " << signal << " has been connected" << oendl; 
00585 #endif
00586     if ( !ioRedirection )
00587         if ( qstrcmp( signal, SIGNAL(readyReadStdout()) )==0 ||
00588                 qstrcmp( signal, SIGNAL(readyReadStderr()) )==0
00589            ) {
00590 #if defined(QT_QPROCESS_DEBUG)
00591             odebug << "QProcess::connectNotify(): set ioRedirection to TRUE" << oendl; 
00592 #endif
00593             setIoRedirection( TRUE );
00594             return;
00595         }
00596     if ( !notifyOnExit && qstrcmp( signal, SIGNAL(processExited()) )==0 ) {
00597 #if defined(QT_QPROCESS_DEBUG)
00598         odebug << "QProcess::connectNotify(): set notifyOnExit to TRUE" << oendl; 
00599 #endif
00600         setNotifyOnExit( TRUE );
00601         return;
00602     }
00603     if ( !wroteToStdinConnected && qstrcmp( signal, SIGNAL(wroteToStdin()) )==0 ) {
00604 #if defined(QT_QPROCESS_DEBUG)
00605         odebug << "QProcess::connectNotify(): set wroteToStdinConnected to TRUE" << oendl; 
00606 #endif
00607         setWroteStdinConnected( TRUE );
00608         return;
00609     }
00610 }
00611 
00614 void QProcess::disconnectNotify( const char * )
00615 {
00616     if ( ioRedirection &&
00617             receivers( SIGNAL(readyReadStdout()) ) ==0 &&
00618             receivers( SIGNAL(readyReadStderr()) ) ==0
00619             ) {
00620 #if defined(QT_QPROCESS_DEBUG)
00621         odebug << "QProcess::disconnectNotify(): set ioRedirection to FALSE" << oendl; 
00622 #endif
00623         setIoRedirection( FALSE );
00624     }
00625     if ( notifyOnExit && receivers( SIGNAL(processExited()) ) == 0 ) {
00626 #if defined(QT_QPROCESS_DEBUG)
00627         odebug << "QProcess::disconnectNotify(): set notifyOnExit to FALSE" << oendl; 
00628 #endif
00629         setNotifyOnExit( FALSE );
00630     }
00631     if ( wroteToStdinConnected && receivers( SIGNAL(wroteToStdin()) ) == 0 ) {
00632 #if defined(QT_QPROCESS_DEBUG)
00633         odebug << "QProcess::disconnectNotify(): set wroteToStdinConnected to FALSE" << oendl; 
00634 #endif
00635         setWroteStdinConnected( FALSE );
00636     }
00637 }
00638 
00639 #endif // QT_NO_PROCESS

Generated on Sat Nov 5 16:15:31 2005 for OPIE by  doxygen 1.4.2