summaryrefslogtreecommitdiff
path: root/core/launcher/qprocess.cpp
Unidiff
Diffstat (limited to 'core/launcher/qprocess.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--core/launcher/qprocess.cpp639
1 files changed, 639 insertions, 0 deletions
diff --git a/core/launcher/qprocess.cpp b/core/launcher/qprocess.cpp
new file mode 100644
index 0000000..97bd539
--- a/dev/null
+++ b/core/launcher/qprocess.cpp
@@ -0,0 +1,639 @@
1/**********************************************************************
2** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
3**
4** This file is part of the Qtopia Environment.
5**
6** This file may be distributed and/or modified under the terms of the
7** GNU General Public License version 2 as published by the Free Software
8** Foundation and appearing in the file LICENSE.GPL included in the
9** packaging of this file.
10**
11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13**
14** See http://www.trolltech.com/gpl/ for GPL licensing information.
15**
16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you.
18**
19**********************************************************************/
20
21#include <stdio.h>
22#include <stdlib.h>
23
24#include "qprocess.h"
25
26#ifndef QT_NO_PROCESS
27
28#include "qapplication.h"
29
30
31//#define QT_QPROCESS_DEBUG
32
33
34/*!
35 \class QProcess qprocess.h
36
37 \brief The QProcess class is used to start external programs and to
38 communicate with them.
39
40 This is a temporary class. This will be replaced by Qt 3's QProcess class.
41
42 \ingroup qtopiaemb
43*/
44
45/*!
46 \enum QProcess::Communication
47
48 This enum type defines the communication channels connected to the
49 process.
50
51 \value Stdin Data can be written to the process's standard input.
52
53 \value Stdout Data can be read from the process's standard output.
54
55 \value Stderr Data can be read from the process's standard error.
56
57 \value DupStderr Duplicates standard error to standard output for new
58 processes; i.e. everything that the process writes to standard error, is
59 reported by QProcess on standard output instead. This is especially useful if
60 your application requires that the output on standard output and standard
61 error is read in the same order as the process output it. Please note that
62 this is a binary flag, so if you want to activate this together with standard
63 input, output and error redirection (the default), you have to specify
64 \c{Stdin|Stdout|Stderr|DupStderr} for the setCommunication() call.
65
66 \sa setCommunication() communication()
67*/
68
69/*!
70 Constructs a QProcess object. The \a parent and \a name parameters are passed
71 to the QObject constructor.
72
73 \sa setArguments() addArgument() start()
74*/
75QProcess::QProcess( QObject *parent, const char *name )
76 : QObject( parent, name ), ioRedirection( FALSE ), notifyOnExit( FALSE ),
77 wroteToStdinConnected( FALSE ),
78 readStdoutCalled( FALSE ), readStderrCalled( FALSE ),
79 comms( Stdin|Stdout|Stderr )
80{
81 init();
82}
83
84/*!
85 Constructs a QProcess with \a arg0 as the command to be executed. The
86 \a parent and \a name parameters are passed to the QObject constructor.
87
88 The process is not started. You must call start() or launch()
89 to start the process.
90
91 \sa setArguments() addArgument() start()
92*/
93QProcess::QProcess( const QString& arg0, QObject *parent, const char *name )
94 : QObject( parent, name ), ioRedirection( FALSE ), notifyOnExit( FALSE ),
95 wroteToStdinConnected( FALSE ),
96 readStdoutCalled( FALSE ), readStderrCalled( FALSE ),
97 comms( Stdin|Stdout|Stderr )
98{
99 init();
100 addArgument( arg0 );
101}
102
103/*!
104 Constructs a QProcess with \a args as the arguments of the process. The first
105 element in the list is the command to be executed. The other elements in the
106 list are the arguments to this command. The \a parent and \a name
107 parameters are passed to the QObject constructor.
108
109 The process is not started. You must call start() or launch()
110 to start the process.
111
112 \sa setArguments() addArgument() start()
113*/
114QProcess::QProcess( const QStringList& args, QObject *parent, const char *name )
115 : QObject( parent, name ), ioRedirection( FALSE ), notifyOnExit( FALSE ),
116 wroteToStdinConnected( FALSE ),
117 readStdoutCalled( FALSE ), readStderrCalled( FALSE ),
118 comms( Stdin|Stdout|Stderr )
119{
120 init();
121 setArguments( args );
122}
123
124
125/*!
126 Returns the list of arguments that are set for the process. Arguments can be
127 specified with the constructor or with the functions setArguments() and
128 addArgument().
129
130 \sa setArguments() addArgument()
131*/
132QStringList QProcess::arguments() const
133{
134 return _arguments;
135}
136
137/*!
138 Clears the list of arguments that are set for the process.
139
140 \sa setArguments() addArgument()
141*/
142void QProcess::clearArguments()
143{
144 _arguments.clear();
145}
146
147/*!
148 Sets \a args as the arguments for the process. The first element in the list
149 is the command to be executed. The other elements in the list are the
150 arguments to the command. Any previous arguments are deleted.
151
152 \sa arguments() addArgument()
153*/
154void QProcess::setArguments( const QStringList& args )
155{
156 _arguments = args;
157}
158
159/*!
160 Adds \a arg to the end of the list of arguments.
161
162 The first element in the list of arguments is the command to be
163 executed; the following elements are the arguments to the command.
164
165 \sa arguments() setArguments()
166*/
167void QProcess::addArgument( const QString& arg )
168{
169 _arguments.append( arg );
170}
171
172#ifndef QT_NO_DIR
173/*!
174 Returns the working directory that was set with
175 setWorkingDirectory(), or the current directory if none has been
176 set.
177
178 \sa setWorkingDirectory() QDir::current()
179*/
180QDir QProcess::workingDirectory() const
181{
182 return workingDir;
183}
184
185/*!
186 Sets \a dir as the working directory for a process. This does not affect
187 running processes; only processes that are started afterwards are affected.
188
189 Setting the working directory is especially useful for processes that try to
190 access files with relative filenames.
191
192 \sa workingDirectory() start()
193*/
194void QProcess::setWorkingDirectory( const QDir& dir )
195{
196 workingDir = dir;
197}
198#endif //QT_NO_DIR
199
200/*!
201 Returns the communication required with the process.
202
203 \sa setCommunication()
204*/
205int QProcess::communication() const
206{
207 return comms;
208}
209
210/*!
211 Sets \a commFlags as the communication required with the process.
212
213 \a commFlags is a bitwise OR between the flags defined in \c Communication.
214
215 The default is \c{Stdin|Stdout|Stderr}.
216
217 \sa communication()
218*/
219void QProcess::setCommunication( int commFlags )
220{
221 comms = commFlags;
222}
223
224/*!
225 Returns TRUE if the process has exited normally; otherwise returns
226 FALSE. This implies that this function returns FALSE if the process
227 is still running.
228
229 \sa isRunning() exitStatus() processExited()
230*/
231bool QProcess::normalExit() const
232{
233 // isRunning() has the side effect that it determines the exit status!
234 if ( isRunning() )
235 return FALSE;
236 else
237 return exitNormal;
238}
239
240/*!
241 Returns the exit status of the process or 0 if the process is still
242 running. This function returns immediately and does not wait until
243 the process is finished.
244
245 If normalExit() is FALSE (e.g. if the program was killed or
246 crashed), this function returns 0, so you should check the return
247 value of normalExit() before relying on this value.
248
249 \sa normalExit() processExited()
250*/
251int QProcess::exitStatus() const
252{
253 // isRunning() has the side effect that it determines the exit status!
254 if ( isRunning() )
255 return 0;
256 else
257 return exitStat;
258}
259
260
261/*!
262 Reads the data that the process has written to standard output. When
263 new data is written to standard output, the class emits the signal
264 readyReadStdout().
265
266 If there is no data to read, this function returns a QByteArray of
267 size 0: it does not wait until there is something to read.
268
269 \sa readyReadStdout() readLineStdout() readStderr() writeToStdin()
270*/
271QByteArray QProcess::readStdout()
272{
273 if ( readStdoutCalled ) {
274 return QByteArray();
275 }
276 readStdoutCalled = TRUE;
277
278 QByteArray buf = bufStdout()->copy();
279 consumeBufStdout( -1 ); // consume everything
280
281 readStdoutCalled = FALSE;
282 return buf;
283}
284
285/*!
286 Reads the data that the process has written to standard error. When
287 new data is written to standard error, the class emits the signal
288 readyReadStderr().
289
290 If there is no data to read, this function returns a QByteArray of
291 size 0: it does not wait until there is something to read.
292
293 \sa readyReadStderr() readLineStderr() readStdout() writeToStdin()
294*/
295QByteArray QProcess::readStderr()
296{
297 if ( readStderrCalled ) {
298 return QByteArray();
299 }
300 readStderrCalled = TRUE;
301
302 QByteArray buf = bufStderr()->copy();
303 consumeBufStderr( -1 ); // consume everything
304
305 readStderrCalled = FALSE;
306 return buf;
307}
308
309/*!
310 Returns TRUE if it's possible to read an entire line of text from
311 standard output at this time; otherwise returns FALSE.
312
313 \sa readLineStdout() canReadLineStderr()
314*/
315bool QProcess::canReadLineStdout() const
316{
317 QProcess *that = (QProcess*)this;
318 return that->scanNewline( TRUE, 0 );
319}
320
321/*!
322 Returns TRUE if it's possible to read an entire line of text from
323 standard error at this time; otherwise returns FALSE.
324
325 \sa readLineStderr() canReadLineStdout()
326*/
327bool QProcess::canReadLineStderr() const
328{
329 QProcess *that = (QProcess*)this;
330 return that->scanNewline( FALSE, 0 );
331}
332
333/*!
334 Reads a line of text from standard output, excluding any trailing newline or
335 carriage return characters, and returns it. Returns QString::null if
336 canReadLineStdout() returns FALSE.
337
338 \sa canReadLineStdout() readyReadStdout() readStdout() readLineStderr()
339*/
340QString QProcess::readLineStdout()
341{
342 QByteArray a;
343 QString s;
344 if ( scanNewline( TRUE, &a ) ) {
345 if ( a.isEmpty() )
346 s = "";
347 else
348 s = QString( a );
349 }
350 return s;
351}
352
353/*!
354 Reads a line of text from standard error, excluding any trailing newline or
355 carriage return characters and returns it. Returns QString::null if
356 canReadLineStderr() returns FALSE.
357
358 \sa canReadLineStderr() readyReadStderr() readStderr() readLineStdout()
359*/
360QString QProcess::readLineStderr()
361{
362 QByteArray a;
363 QString s;
364 if ( scanNewline( FALSE, &a ) ) {
365 if ( a.isEmpty() )
366 s = "";
367 else
368 s = QString( a );
369 }
370 return s;
371}
372
373/*!
374 This private function scans for any occurrence of \n or \r\n in the
375 buffer \e buf. It stores the text in the byte array \a store if it is
376 non-null.
377*/
378bool QProcess::scanNewline( bool stdOut, QByteArray *store )
379{
380 QByteArray *buf;
381 if ( stdOut )
382 buf = bufStdout();
383 else
384 buf = bufStderr();
385 uint n = buf->size();
386 uint i;
387 for ( i=0; i<n; i++ ) {
388 if ( buf->at(i) == '\n' ) {
389 break;
390 }
391 }
392 if ( i >= n )
393 return FALSE;
394
395 if ( store ) {
396 uint lineLength = i;
397 if ( lineLength>0 && buf->at(lineLength-1) == '\r' )
398 lineLength--; // (if there are two \r, let one stay)
399 store->resize( lineLength );
400 memcpy( store->data(), buf->data(), lineLength );
401 if ( stdOut )
402 consumeBufStdout( i+1 );
403 else
404 consumeBufStderr( i+1 );
405 }
406 return TRUE;
407}
408
409/*!
410 \fn void QProcess::launchFinished()
411
412 This signal is emitted when the process was started with launch().
413 If the start was successful, this signal is emitted after all the
414 data has been written to standard input. If the start failed, then
415 this signal is emitted immediately.
416
417 \sa launch() QObject::deleteLater()
418*/
419
420/*!
421 Runs the process and writes the data \a buf to the process's standard input.
422 If all the data is written to standard input, standard input is
423 closed. The command is searched for in the path for executable programs;
424 you can also use an absolute path in the command itself.
425
426 If \a env is null, then the process is started with the same environment as
427 the starting process. If \a env is non-null, then the values in the
428 stringlist are interpreted as environment setttings of the form \c
429 {key=value} and the process is started with these environment settings. For
430 convenience, there is a small exception to this rule under Unix: if \a env
431 does not contain any settings for the environment variable \c
432 LD_LIBRARY_PATH, then this variable is inherited from the starting process.
433
434 Returns TRUE if the process could be started; otherwise returns FALSE.
435
436 Note that you should not use the slots writeToStdin() and closeStdin() on
437 processes started with launch(), since the result is not well-defined. If you
438 need these slots, use start() instead.
439
440 The process may or may not read the \a buf data sent to its standard
441 input.
442
443 You can call this function even when a process that was started with
444 this instance is still running. Be aware that if you do this the
445 standard input of the process that was launched first will be
446 closed, with any pending data being deleted, and the process will be
447 left to run out of your control. Similarly, if the process could not
448 be started the standard input will be closed and the pending data
449 deleted. (On operating systems that have zombie processes, Qt will
450 also wait() on the old process.)
451
452 The object emits the signal launchFinished() when this function
453 call is finished. If the start was successful, this signal is
454 emitted after all the data has been written to standard input. If
455 the start failed, then this signal is emitted immediately.
456
457 \sa start() launchFinished();
458*/
459bool QProcess::launch( const QByteArray& buf, QStringList *env )
460{
461 if ( start( env ) ) {
462 if ( !buf.isEmpty() ) {
463 connect( this, SIGNAL(wroteToStdin()),
464 this, SLOT(closeStdinLaunch()) );
465 writeToStdin( buf );
466 } else {
467 closeStdin();
468 emit launchFinished();
469 }
470 return TRUE;
471 } else {
472 emit launchFinished();
473 return FALSE;
474 }
475}
476
477/*! \overload
478
479 The data \a buf is written to standard input with writeToStdin()
480 using the QString::local8Bit() representation of the strings.
481*/
482bool QProcess::launch( const QString& buf, QStringList *env )
483{
484 if ( start( env ) ) {
485 if ( !buf.isEmpty() ) {
486 connect( this, SIGNAL(wroteToStdin()),
487 this, SLOT(closeStdinLaunch()) );
488 writeToStdin( buf );
489 } else {
490 closeStdin();
491 emit launchFinished();
492 }
493 return TRUE;
494 } else {
495 emit launchFinished();
496 return FALSE;
497 }
498}
499
500/*!
501 This private slot is used by the launch() functions to close standard input.
502*/
503void QProcess::closeStdinLaunch()
504{
505 disconnect( this, SIGNAL(wroteToStdin()),
506 this, SLOT(closeStdinLaunch()) );
507 closeStdin();
508 emit launchFinished();
509}
510
511
512/*!
513 \fn void QProcess::readyReadStdout()
514
515 This signal is emitted when the process has written data to standard output.
516 You can read the data with readStdout().
517
518 Note that this signal is only emitted when there is new data and not
519 when there is old, but unread data. In the slot connected to this signal, you
520 should always read everything that is available at that moment to make sure
521 that you don't lose any data.
522
523 \sa readStdout() readLineStdout() readyReadStderr()
524*/
525/*!
526 \fn void QProcess::readyReadStderr()
527
528 This signal is emitted when the process has written data to standard error.
529 You can read the data with readStderr().
530
531 Note that this signal is only emitted when there is new data and not
532 when there is old, but unread data. In the slot connected to this signal, you
533 should always read everything that is available at that moment to make sure
534 that you don't lose any data.
535
536 \sa readStderr() readLineStderr() readyReadStdout()
537*/
538/*!
539 \fn void QProcess::processExited()
540
541 This signal is emitted when the process has exited.
542
543 \sa isRunning() normalExit() exitStatus() start() launch()
544*/
545/*!
546 \fn void QProcess::wroteToStdin()
547
548 This signal is emitted if the data sent to standard input (via
549 writeToStdin()) was actually written to the process. This does not
550 imply that the process really read the data, since this class only detects
551 when it was able to write the data to the operating system. But it is now
552 safe to close standard input without losing pending data.
553
554 \sa writeToStdin() closeStdin()
555*/
556
557
558/*! \overload
559
560 The string \a buf is handled as text using
561 the QString::local8Bit() representation.
562*/
563void QProcess::writeToStdin( const QString& buf )
564{
565 QByteArray tmp = buf.local8Bit();
566 tmp.resize( buf.length() );
567 writeToStdin( tmp );
568}
569
570
571/*
572 * Under Windows the implementation is not so nice: it is not that easy to
573 * detect when one of the signals should be emitted; therefore there are some
574 * timers that query the information.
575 * To keep it a little efficient, use the timers only when they are needed.
576 * They are needed, if you are interested in the signals. So use
577 * connectNotify() and disconnectNotify() to keep track of your interest.
578 */
579/*! \reimp
580*/
581void QProcess::connectNotify( const char * signal )
582{
583#if defined(QT_QPROCESS_DEBUG)
584 qDebug( "QProcess::connectNotify(): signal %s has been connected", signal );
585#endif
586 if ( !ioRedirection )
587 if ( qstrcmp( signal, SIGNAL(readyReadStdout()) )==0 ||
588 qstrcmp( signal, SIGNAL(readyReadStderr()) )==0
589 ) {
590#if defined(QT_QPROCESS_DEBUG)
591 qDebug( "QProcess::connectNotify(): set ioRedirection to TRUE" );
592#endif
593 setIoRedirection( TRUE );
594 return;
595 }
596 if ( !notifyOnExit && qstrcmp( signal, SIGNAL(processExited()) )==0 ) {
597#if defined(QT_QPROCESS_DEBUG)
598 qDebug( "QProcess::connectNotify(): set notifyOnExit to TRUE" );
599#endif
600 setNotifyOnExit( TRUE );
601 return;
602 }
603 if ( !wroteToStdinConnected && qstrcmp( signal, SIGNAL(wroteToStdin()) )==0 ) {
604#if defined(QT_QPROCESS_DEBUG)
605 qDebug( "QProcess::connectNotify(): set wroteToStdinConnected to TRUE" );
606#endif
607 setWroteStdinConnected( TRUE );
608 return;
609 }
610}
611
612/*! \reimp
613*/
614void QProcess::disconnectNotify( const char * )
615{
616 if ( ioRedirection &&
617 receivers( SIGNAL(readyReadStdout()) ) ==0 &&
618 receivers( SIGNAL(readyReadStderr()) ) ==0
619 ) {
620#if defined(QT_QPROCESS_DEBUG)
621 qDebug( "QProcess::disconnectNotify(): set ioRedirection to FALSE" );
622#endif
623 setIoRedirection( FALSE );
624 }
625 if ( notifyOnExit && receivers( SIGNAL(processExited()) ) == 0 ) {
626#if defined(QT_QPROCESS_DEBUG)
627 qDebug( "QProcess::disconnectNotify(): set notifyOnExit to FALSE" );
628#endif
629 setNotifyOnExit( FALSE );
630 }
631 if ( wroteToStdinConnected && receivers( SIGNAL(wroteToStdin()) ) == 0 ) {
632#if defined(QT_QPROCESS_DEBUG)
633 qDebug( "QProcess::disconnectNotify(): set wroteToStdinConnected to FALSE" );
634#endif
635 setWroteStdinConnected( FALSE );
636 }
637}
638
639#endif // QT_NO_PROCESS