1 /*
2     SPDX-FileCopyrightText: 2009 Nokia Corporation and /or its subsidiary(-ies).
3     Contact: Qt Software Information (qt-info@nokia.com)
4 
5     This file is part of the QtCore module of the Qt Toolkit.
6 
7     $QT_BEGIN_LICENSE:LGPL$
8     Commercial Usage
9     Licensees holding valid Qt Commercial licenses may use this file in
10     accordance with the Qt Commercial License Agreement provided with the
11     Software or, alternatively, in accordance with the terms contained in
12     a written agreement between you and Nokia.
13 
14     GNU Lesser General Public License Usage
15     Alternatively, this file may be used under the terms of the GNU Lesser
16     General Public License version 2.1 as published by the Free Software
17     Foundation and appearing in the file LICENSE.LGPL included in the
18     packaging of this file.  Please review the following information to
19     ensure the GNU Lesser General Public License version 2.1 requirements
20     will be met: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
21 
22     In addition, as a special exception, Nokia gives you certain
23     additional rights. These rights are described in the Nokia Qt LGPL
24     Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
25     package.
26 
27     GNU General Public License Usage
28     Alternatively, this file may be used under the terms of the GNU
29     General Public License version 3.0 as published by the Free Software
30     Foundation and appearing in the file LICENSE.GPL included in the
31     packaging of this file.  Please review the following information to
32     ensure the GNU General Public License version 3.0 requirements will be
33     met: https://www.gnu.org/licenses/gpl-3.0.html.
34 
35     If you are unsure which license is appropriate for your use, please
36     contact the sales department at qt-sales@nokia.com.
37     $QT_END_LICENSE$
38 
39 */
40 
41 //#define QPROCESS_DEBUG
42 #include <QElapsedTimer>
43 #if defined QPROCESS_DEBUG
44 #include <qdebug.h>
45 #include <QString>
46 #include <ctype.h>
47 #if !defined(Q_OS_WINCE)
48 #include <errno.h>
49 #endif
50 
51 //QT_BEGIN_NAMESPACE
52 /*
53     Returns a human readable representation of the first \a len
54     characters in \a data.
55 */
qt_prettyDebug(const char * data,int len,int maxSize)56 static QByteArray qt_prettyDebug(const char *data, int len, int maxSize)
57 {
58     if (!data) return "(null)";
59     QByteArray out;
60     for (int i = 0; i < len && i < maxSize; ++i) {
61         char c = data[i];
62         if (isprint(c)) {
63             out += c;
64         } else switch (c) {
65         case '\n': out += "\\n"; break;
66         case '\r': out += "\\r"; break;
67         case '\t': out += "\\t"; break;
68         default:
69             char buf[5];
70             qsnprintf(buf, sizeof(buf), "\\%3o", c);
71             buf[4] = '\0';
72             out += QByteArray(buf);
73         }
74     }
75 
76     if (len < maxSize)
77         out += "...";
78 
79     return out;
80 }
81 
82 //QT_END_NAMESPACE
83 
84 #endif
85 
86 #include "k3bqprocess.h"
87 #include "k3bqprocess_p.h"
88 
89 #include <QByteArray>
90 #include <QDateTime>
91 #include <qcoreapplication.h>
92 #include <qsocketnotifier.h>
93 #include <QTimer>
94 
95 #ifdef Q_WS_WIN
96 #include <private/qwineventnotifier_p.h>
97 #endif
98 
99 #ifndef QT_NO_PROCESS
100 
101 //QT_BEGIN_NAMESPACE
102 
clear()103 void K3bQProcessPrivate::Channel::clear()
104 {
105     switch (type) {
106     case PipeSource:
107         Q_ASSERT(process);
108         process->stdinChannel.type = Normal;
109         process->stdinChannel.process = 0;
110         break;
111     case PipeSink:
112         Q_ASSERT(process);
113         process->stdoutChannel.type = Normal;
114         process->stdoutChannel.process = 0;
115         break;
116     }
117 
118     type = Normal;
119     file.clear();
120     process = 0;
121 }
122 
123 /*!
124     \class QProcess
125 
126     \brief The QProcess class is used to start external programs and
127     to communicate with them.
128 
129     \ingroup io
130     \ingroup misc
131     \mainclass
132     \reentrant
133 
134     To start a process, pass the name and command line arguments of
135     the program you want to run as arguments to start(). For example:
136 
137     \snippet doc/src/snippets/qprocess/qprocess-simpleexecution.cpp 0
138     \dots
139     \snippet doc/src/snippets/qprocess/qprocess-simpleexecution.cpp 1
140     \snippet doc/src/snippets/qprocess/qprocess-simpleexecution.cpp 2
141 
142     QProcess then enters the \l Starting state, and when the program
143     has started, QProcess enters the \l Running state and emits
144     started().
145 
146     QProcess allows you to treat a process as a sequential I/O
147     device. You can write to and read from the process just as you
148     would access a network connection using QTcpSocket. You can then
149     write to the process's standard input by calling write(), and
150     read the standard output by calling read(), readLine(), and
151     getChar(). Because it inherits QIODevice, QProcess can also be
152     used as an input source for QXmlReader, or for generating data to
153     be uploaded using QFtp.
154 
155     \note On Windows CE, reading and writing to a process is not supported.
156 
157     When the process exits, QProcess reenters the \l NotRunning state
158     (the initial state), and emits finished().
159 
160     The finished() signal provides the exit code and exit status of
161     the process as arguments, and you can also call exitCode() to
162     obtain the exit code of the last process that finished, and
163     exitStatus() to obtain its exit status. If an error occurs at
164     any point in time, QProcess will emit the error() signal. You
165     can also call error() to find the type of error that occurred
166     last, and state() to find the current process state.
167 
168     \section1 Communicating via Channels
169 
170     Processes have two predefined output channels: The standard
171     output channel (\c stdout) supplies regular console output, and
172     the standard error channel (\c stderr) usually supplies the
173     errors that are printed by the process. These channels represent
174     two separate streams of data. You can toggle between them by
175     calling setReadChannel(). QProcess emits readyRead() when data is
176     available on the current read channel. It also emits
177     readyReadStandardOutput() when new standard output data is
178     available, and when new standard error data is available,
179     readyReadStandardError() is emitted. Instead of calling read(),
180     readLine(), or getChar(), you can explicitly read all data from
181     either of the two channels by calling readAllStandardOutput() or
182     readAllStandardError().
183 
184     The terminology for the channels can be misleading. Be aware that
185     the process's output channels correspond to QProcess's
186     \e read channels, whereas the process's input channels correspond
187     to QProcess's \e write channels. This is because what we read
188     using QProcess is the process's output, and what we write becomes
189     the process's input.
190 
191     QProcess can merge the two output channels, so that standard
192     output and standard error data from the running process both use
193     the standard output channel. Call setProcessChannelMode() with
194     MergedChannels before starting the process to activate
195     this feature. You also have the option of forwarding the output of
196     the running process to the calling, main process, by passing
197     ForwardedChannels as the argument.
198 
199     Certain processes need special environment settings in order to
200     operate. You can set environment variables for your process by
201     calling setEnvironment(). To set a working directory, call
202     setWorkingDirectory(). By default, processes are run in the
203     current working directory of the calling process.
204 
205     \section1 Synchronous Process API
206 
207     QProcess provides a set of functions which allow it to be used
208     without an event loop, by suspending the calling thread until
209     certain signals are emitted:
210 
211     \list
212     \o waitForStarted() blocks until the process has started.
213 
214     \o waitForReadyRead() blocks until new data is
215     available for reading on the current read channel.
216 
217     \o waitForBytesWritten() blocks until one payload of
218     data has been written to the process.
219 
220     \o waitForFinished() blocks until the process has finished.
221     \endlist
222 
223     Calling these functions from the main thread (the thread that
224     calls QApplication::exec()) may cause your user interface to
225     freeze.
226 
227     The following example runs \c gzip to compress the string "Qt
228     rocks!", without an event loop:
229 
230     \snippet doc/src/snippets/process/process.cpp 0
231 
232     \section1 Notes for Windows Users
233 
234     Some Windows commands (for example, \c dir) are not provided by
235     separate applications, but by the command interpreter itself.
236     If you attempt to use QProcess to execute these commands directly,
237     it won't work. One possible solution is to execute the command
238     interpreter itself (\c{cmd.exe} on some Windows systems), and ask
239     the interpreter to execute the desired command.
240 
241     \sa QBuffer, QFile, QTcpSocket
242 */
243 
244 /*!
245     \enum QProcess::ProcessChannel
246 
247     This enum describes the process channels used by the running process.
248     Pass one of these values to setReadChannel() to set the
249     current read channel of QProcess.
250 
251     \value StandardOutput The standard output (stdout) of the running
252            process.
253 
254     \value StandardError The standard error (stderr) of the running
255            process.
256 
257     \sa setReadChannel()
258 */
259 
260 /*!
261     \enum QProcess::ProcessChannelMode
262 
263     This enum describes the process channel modes of QProcess. Pass
264     one of these values to setProcessChannelMode() to set the
265     current read channel mode.
266 
267     \value SeparateChannels QProcess manages the output of the
268     running process, keeping standard output and standard error data
269     in separate internal buffers. You can select the QProcess's
270     current read channel by calling setReadChannel(). This is the
271     default channel mode of QProcess.
272 
273     \value MergedChannels QProcess merges the output of the running
274     process into the standard output channel (\c stdout). The
275     standard error channel (\c stderr) will not receive any data. The
276     standard output and standard error data of the running process
277     are interleaved.
278 
279     \value ForwardedChannels QProcess forwards the output of the
280     running process onto the main process. Anything the child process
281     writes to its standard output and standard error will be written
282     to the standard output and standard error of the main process.
283 
284     \sa setReadChannelMode()
285 */
286 
287 /*!
288     \enum QProcess::ProcessError
289 
290     This enum describes the different types of errors that are
291     reported by QProcess.
292 
293     \value FailedToStart The process failed to start. Either the
294     invoked program is missing, or you may have insufficient
295     permissions to invoke the program.
296 
297     \value Crashed The process crashed some time after starting
298     successfully.
299 
300     \value Timedout The last waitFor...() function timed out. The
301     state of QProcess is unchanged, and you can try calling
302     waitFor...() again.
303 
304     \value WriteError An error occurred when attempting to write to the
305     process. For example, the process may not be running, or it may
306     have closed its input channel.
307 
308     \value ReadError An error occurred when attempting to read from
309     the process. For example, the process may not be running.
310 
311     \value UnknownError An unknown error occurred. This is the default
312     return value of error().
313 
314     \sa error()
315 */
316 
317 /*!
318     \enum QProcess::ProcessState
319 
320     This enum describes the different states of QProcess.
321 
322     \value NotRunning The process is not running.
323 
324     \value Starting The process is starting, but the program has not
325     yet been invoked.
326 
327     \value Running The process is running and is ready for reading and
328     writing.
329 
330     \sa state()
331 */
332 
333 /*!
334     \enum QProcess::ExitStatus
335 
336     This enum describes the different exit statuses of QProcess.
337 
338     \value NormalExit The process exited normally.
339 
340     \value CrashExit The process crashed.
341 
342     \sa exitStatus()
343 */
344 
345 /*!
346     \fn void QProcess::error(QProcess::ProcessError error)
347 
348     This signal is emitted when an error occurs with the process. The
349     specified \a error describes the type of error that occurred.
350 */
351 
352 /*!
353     \fn void QProcess::started()
354 
355     This signal is emitted by QProcess when the process has started,
356     and state() returns \l Running.
357 */
358 
359 /*!
360     \fn void QProcess::stateChanged(QProcess::ProcessState newState)
361 
362     This signal is emitted whenever the state of QProcess changes. The
363     \a newState argument is the state QProcess changed to.
364 */
365 
366 /*!
367     \fn void QProcess::finished(int exitCode)
368     \obsolete
369     \overload
370 
371     Use finished(int exitCode, QProcess::ExitStatus status) instead.
372 */
373 
374 /*!
375     \fn void QProcess::finished(int exitCode, QProcess::ExitStatus exitStatus)
376 
377     This signal is emitted when the process finishes. \a exitCode is the exit
378     code of the process, and \a exitStatus is the exit status.  After the
379     process has finished, the buffers in QProcess are still intact. You can
380     still read any data that the process may have written before it finished.
381 
382     \sa exitStatus()
383 */
384 
385 /*!
386     \fn void QProcess::readyReadStandardOutput()
387 
388     This signal is emitted when the process has made new data
389     available through its standard output channel (\c stdout). It is
390     emitted regardless of the current \l{readChannel()}{read channel}.
391 
392     \sa readAllStandardOutput(), readChannel()
393 */
394 
395 /*!
396     \fn void QProcess::readyReadStandardError()
397 
398     This signal is emitted when the process has made new data
399     available through its standard error channel (\c stderr). It is
400     emitted regardless of the current \l{readChannel()}{read
401     channel}.
402 
403     \sa readAllStandardError(), readChannel()
404 */
405 
406 /*! \internal
407 */
K3bQProcessPrivate()408 K3bQProcessPrivate::K3bQProcessPrivate()
409 {
410     processChannel = ::QProcess::StandardOutput;
411     processChannelMode = ::QProcess::SeparateChannels;
412     processError = ::QProcess::UnknownError;
413     processState = ::QProcess::NotRunning;
414     pid = 0;
415     sequenceNumber = 0;
416     exitCode = 0;
417     exitStatus = ::QProcess::NormalExit;
418     startupSocketNotifier = 0;
419     deathNotifier = 0;
420     notifier = 0;
421     pipeWriter = 0;
422     childStartedPipe[0] = INVALID_Q_PIPE;
423     childStartedPipe[1] = INVALID_Q_PIPE;
424     deathPipe[0] = INVALID_Q_PIPE;
425     deathPipe[1] = INVALID_Q_PIPE;
426     exitCode = 0;
427     crashed = false;
428     dying = false;
429     emittedReadyRead = false;
430     emittedBytesWritten = false;
431 #ifdef Q_WS_WIN
432     pipeWriter = 0;
433     processFinishedNotifier = 0;
434 #endif // Q_WS_WIN
435 #ifdef Q_OS_UNIX
436     serial = 0;
437 #endif
438 }
439 
440 /*! \internal
441 */
~K3bQProcessPrivate()442 K3bQProcessPrivate::~K3bQProcessPrivate()
443 {
444     if (stdinChannel.process)
445         stdinChannel.process->stdoutChannel.clear();
446     if (stdoutChannel.process)
447         stdoutChannel.process->stdinChannel.clear();
448 }
449 
450 /*! \internal
451 */
452 
453 void qDeleteInEventHandler(QObject *o);
454 
cleanup()455 void K3bQProcessPrivate::cleanup()
456 {
457     q_func()->setProcessState(::QProcess::NotRunning);
458 #ifdef Q_OS_WIN
459     if (pid) {
460         CloseHandle(pid->hThread);
461         CloseHandle(pid->hProcess);
462         delete pid;
463         pid = 0;
464     }
465     if (processFinishedNotifier) {
466         processFinishedNotifier->setEnabled(false);
467         qDeleteInEventHandler(processFinishedNotifier);
468         processFinishedNotifier = 0;
469     }
470 
471 #endif
472     pid = 0;
473     sequenceNumber = 0;
474     dying = false;
475 
476     if (stdoutChannel.notifier) {
477         stdoutChannel.notifier->setEnabled(false);
478         delete stdoutChannel.notifier;
479         stdoutChannel.notifier = 0;
480     }
481     if (stderrChannel.notifier) {
482         stderrChannel.notifier->setEnabled(false);
483         delete stderrChannel.notifier;
484         stderrChannel.notifier = 0;
485     }
486     if (stdinChannel.notifier) {
487         stdinChannel.notifier->setEnabled(false);
488         delete stdinChannel.notifier;
489         stdinChannel.notifier = 0;
490     }
491     if (startupSocketNotifier) {
492         startupSocketNotifier->setEnabled(false);
493         delete startupSocketNotifier;
494         startupSocketNotifier = 0;
495     }
496     if (deathNotifier) {
497         deathNotifier->setEnabled(false);
498         delete deathNotifier;
499         deathNotifier = 0;
500     }
501     if (notifier) {
502         delete notifier;
503         notifier = 0;
504     }
505     destroyPipe(stdoutChannel.pipe);
506     destroyPipe(stderrChannel.pipe);
507     destroyPipe(stdinChannel.pipe);
508     destroyPipe(childStartedPipe);
509     destroyPipe(deathPipe);
510 #ifdef Q_OS_UNIX
511     serial = 0;
512 #endif
513 }
514 
515 /*! \internal
516 */
_q_canReadStandardOutput()517 bool K3bQProcessPrivate::_q_canReadStandardOutput()
518 {
519     Q_Q(K3bQProcess);
520     qint64 available = bytesAvailableFromStdout();
521     if (available == 0) {
522         if (stdoutChannel.notifier)
523             stdoutChannel.notifier->setEnabled(false);
524         destroyPipe(stdoutChannel.pipe);
525 #if defined QPROCESS_DEBUG
526         qDebug("K3bQProcessPrivate::canReadStandardOutput(), 0 bytes available");
527 #endif
528         return false;
529     }
530 
531     if (!(processFlags & K3bQProcess::RawStdout)) {
532         char *ptr = outputReadBuffer.reserve(available);
533         qint64 readBytes = readFromStdout(ptr, available);
534         if (readBytes == -1) {
535             processError = ::QProcess::ReadError;
536             q->setErrorString(K3bQProcess::tr("Error reading from process"));
537             emit q->error(processError);
538 #if defined QPROCESS_DEBUG
539             qDebug("K3bQProcessPrivate::canReadStandardOutput(), failed to read from the process");
540 #endif
541             return false;
542         }
543 #if defined QPROCESS_DEBUG
544         qDebug("K3bQProcessPrivate::canReadStandardOutput(), read %d bytes from the process' output",
545                int(readBytes));
546 #endif
547 
548         if (stdoutChannel.closed) {
549             outputReadBuffer.chop(readBytes);
550             return false;
551         }
552 
553         outputReadBuffer.chop(available - readBytes);
554 
555         bool didRead = false;
556         if (readBytes == 0) {
557             if (stdoutChannel.notifier)
558                 stdoutChannel.notifier->setEnabled(false);
559         } else if (processChannel == ::QProcess::StandardOutput) {
560             didRead = true;
561             if (!emittedReadyRead) {
562                 emittedReadyRead = true;
563                 emit q->readyRead();
564                 emittedReadyRead = false;
565             }
566         }
567         emit q->readyReadStandardOutput();
568         return didRead;
569     }
570     else {
571         if (!emittedReadyRead) {
572             emittedReadyRead = true;
573             emit q->readyRead();
574             emittedReadyRead = false;
575         }
576         emit q->readyReadStandardOutput();
577         return true;
578     }
579 }
580 
581 /*! \internal
582 */
_q_canReadStandardError()583 bool K3bQProcessPrivate::_q_canReadStandardError()
584 {
585     Q_Q(K3bQProcess);
586     qint64 available = bytesAvailableFromStderr();
587     if (available == 0) {
588         if (stderrChannel.notifier)
589             stderrChannel.notifier->setEnabled(false);
590         destroyPipe(stderrChannel.pipe);
591         return false;
592     }
593 
594     char *ptr = errorReadBuffer.reserve(available);
595     qint64 readBytes = readFromStderr(ptr, available);
596     if (readBytes == -1) {
597         processError = ::QProcess::ReadError;
598         q->setErrorString(K3bQProcess::tr("Error reading from process"));
599         emit q->error(processError);
600         return false;
601     }
602     if (stderrChannel.closed) {
603         errorReadBuffer.chop(readBytes);
604         return false;
605     }
606 
607     errorReadBuffer.chop(available - readBytes);
608 
609     bool didRead = false;
610     if (readBytes == 0) {
611         if (stderrChannel.notifier)
612             stderrChannel.notifier->setEnabled(false);
613     } else if (processChannel == ::QProcess::StandardError) {
614         didRead = true;
615         if (!emittedReadyRead) {
616             emittedReadyRead = true;
617             emit q->readyRead();
618             emittedReadyRead = false;
619         }
620     }
621     emit q->readyReadStandardError();
622     return didRead;
623 }
624 
625 /*! \internal
626 */
_q_canWrite()627 bool K3bQProcessPrivate::_q_canWrite()
628 {
629     Q_Q(K3bQProcess);
630     if (processFlags & K3bQProcess::RawStdin) {
631         if (stdinChannel.notifier)
632             stdinChannel.notifier->setEnabled(false);
633         isReadyWrite = true;
634         emit q->readyWrite();
635     }
636     else {
637         if (stdinChannel.notifier)
638             stdinChannel.notifier->setEnabled(false);
639 
640         if (writeBuffer.isEmpty()) {
641 #if defined QPROCESS_DEBUG
642             qDebug("K3bQProcessPrivate::canWrite(), not writing anything (empty write buffer).");
643 #endif
644             return false;
645         }
646 
647         qint64 written = writeToStdin(writeBuffer.readPointer(),
648                                       writeBuffer.nextDataBlockSize());
649         if (written < 0) {
650             destroyPipe(stdinChannel.pipe);
651             processError = ::QProcess::WriteError;
652             q->setErrorString(K3bQProcess::tr("Error writing to process"));
653 #if defined(QPROCESS_DEBUG) && !defined(Q_OS_WINCE)
654             qDebug("K3bQProcessPrivate::canWrite(), failed to write (%s)", strerror(errno));
655 #endif
656             emit q->error(processError);
657             return false;
658         }
659 
660 #if defined QPROCESS_DEBUG
661         qDebug("K3bQProcessPrivate::canWrite(), wrote %d bytes to the process input", int(written));
662 #endif
663 
664         writeBuffer.free(written);
665         if (!emittedBytesWritten) {
666             emittedBytesWritten = true;
667             emit q->bytesWritten(written);
668             emittedBytesWritten = false;
669         }
670         if (stdinChannel.notifier && !writeBuffer.isEmpty())
671             stdinChannel.notifier->setEnabled(true);
672         if (writeBuffer.isEmpty() && stdinChannel.closed)
673             closeWriteChannel();
674     }
675     return true;
676 }
677 
678 /*! \internal
679 */
_q_processDied()680 bool K3bQProcessPrivate::_q_processDied()
681 {
682 #if defined QPROCESS_DEBUG
683     qDebug("K3bQProcessPrivate::_q_processDied()");
684 #endif
685 #ifdef Q_OS_UNIX
686     if (!waitForDeadChild())
687         return false;
688 #endif
689 #ifdef Q_OS_WIN
690     if (processFinishedNotifier)
691         processFinishedNotifier->setEnabled(false);
692 #endif
693 
694     // the process may have died before it got a chance to report that it was
695     // either running or stopped, so we will call _q_startupNotification() and
696     // give it a chance to emit started() or error(FailedToStart).
697     if (processState == ::QProcess::Starting) {
698         if (!_q_startupNotification())
699             return true;
700     }
701 
702     return _q_notifyProcessDied();
703 }
704 
_q_notifyProcessDied()705 bool K3bQProcessPrivate::_q_notifyProcessDied()
706 {
707     Q_Q(K3bQProcess);
708 #if defined QPROCESS_DEBUG
709     qDebug("K3bQProcessPrivate::_q_notifyProcessDied()");
710 #endif
711 
712     if ( processFlags&K3bQProcess::RawStdout ) {
713         qint64 bytes = bytesAvailableFromStdout();
714 #if defined QPROCESS_DEBUG
715         qDebug() << "bytesAvailableFromStdout:" << bytes;
716 #endif
717         // wait for all data to be read
718         if ( bytes > 0 ) {
719             QMetaObject::invokeMethod( q, "_q_notifyProcessDied", Qt::QueuedConnection );
720             return false;
721         }
722     }
723 
724     if (dying) {
725         // at this point we know the process is dead. prevent
726         // reentering this slot recursively by calling waitForFinished()
727         // or opening a dialog inside slots connected to the readyRead
728         // signals emitted below.
729         return true;
730     }
731     dying = true;
732 
733     // in case there is data in the pipe line and this slot by chance
734     // got called before the read notifications, call these two slots
735     // so the data is made available before the process dies.
736     if ( !processFlags.testFlag( K3bQProcess::RawStdout ) ) {
737         _q_canReadStandardOutput();
738     }
739     _q_canReadStandardError();
740     findExitCode();
741 
742     if (crashed) {
743         exitStatus = ::QProcess::CrashExit;
744         processError = ::QProcess::Crashed;
745         q->setErrorString(K3bQProcess::tr("Process crashed"));
746         emit q->error(processError);
747     }
748 
749     bool wasRunning = (processState == ::QProcess::Running);
750 
751     cleanup();
752 
753     if (wasRunning) {
754         // we received EOF now:
755         emit q->readChannelFinished();
756         // in the future:
757         //emit q->standardOutputClosed();
758         //emit q->standardErrorClosed();
759 
760         emit q->finished(exitCode);
761         emit q->finished(exitCode, exitStatus);
762     }
763 #if defined QPROCESS_DEBUG
764     qDebug("K3bQProcessPrivate::_q_notifyProcessDied() process is dead");
765 #endif
766     return true;
767 }
768 
769 /*! \internal
770 */
_q_startupNotification()771 bool K3bQProcessPrivate::_q_startupNotification()
772 {
773     Q_Q(K3bQProcess);
774 #if defined QPROCESS_DEBUG
775     qDebug("K3bQProcessPrivate::startupNotification()");
776 #endif
777 
778     if (startupSocketNotifier)
779         startupSocketNotifier->setEnabled(false);
780     if (processStarted()) {
781         q->setProcessState(::QProcess::Running);
782         emit q->started();
783         return true;
784     }
785 
786     q->setProcessState(::QProcess::NotRunning);
787     processError = ::QProcess::FailedToStart;
788     emit q->error(processError);
789 #ifdef Q_OS_UNIX
790     // make sure the process manager removes this entry
791     waitForDeadChild();
792     findExitCode();
793 #endif
794     cleanup();
795     return false;
796 }
797 
798 /*! \internal
799 */
closeWriteChannel()800 void K3bQProcessPrivate::closeWriteChannel()
801 {
802 #if defined QPROCESS_DEBUG
803     qDebug("K3bQProcessPrivate::closeWriteChannel()");
804 #endif
805     if (stdinChannel.notifier) {
806         stdinChannel.notifier->setEnabled(false);
807         if (stdinChannel.notifier) {
808             delete stdinChannel.notifier;
809             stdinChannel.notifier = 0;
810         }
811     }
812 #ifdef Q_OS_WIN
813     // ### Find a better fix, feeding the process little by little
814     // instead.
815     flushPipeWriter();
816 #endif
817     destroyPipe(stdinChannel.pipe);
818 }
819 
readData(char * data,qint64 maxlen,QProcess::ProcessChannel channel)820 qint64 K3bQProcessPrivate::readData( char *data, qint64 maxlen, QProcess::ProcessChannel channel )
821 {
822     if (processFlags&K3bQProcess::RawStdout &&
823         channel == ::QProcess::StandardOutput) {
824         return readFromStdout(data, maxlen);
825     }
826     else {
827         QRingBuffer *readBuffer = (channel == ::QProcess::StandardError)
828                                   ? &errorReadBuffer
829                                   : &outputReadBuffer;
830 
831         if (maxlen == 1 && !readBuffer->isEmpty()) {
832             int c = readBuffer->getChar();
833             if (c == -1) {
834 #if defined QPROCESS_DEBUG
835                 qDebug("QProcess::readData(%p \"%s\", %d) == -1",
836                        data, qt_prettyDebug(data, 1, maxlen).constData(), 1);
837 #endif
838                 return -1;
839             }
840             *data = (char) c;
841 #if defined QPROCESS_DEBUG
842             qDebug("QProcess::readData(%p \"%s\", %d) == 1",
843                    data, qt_prettyDebug(data, 1, maxlen).constData(), 1);
844 #endif
845             return 1;
846         }
847 
848         qint64 bytesToRead = qint64(qMin(readBuffer->size(), (int)maxlen));
849         qint64 readSoFar = 0;
850         while (readSoFar < bytesToRead) {
851             const char *ptr = readBuffer->readPointer();
852             int bytesToReadFromThisBlock = qMin<qint64>(bytesToRead - readSoFar,
853                                                         readBuffer->nextDataBlockSize());
854             memcpy(data + readSoFar, ptr, bytesToReadFromThisBlock);
855             readSoFar += bytesToReadFromThisBlock;
856             readBuffer->free(bytesToReadFromThisBlock);
857         }
858 
859 #if defined QPROCESS_DEBUG
860         qDebug("QProcess::readData(%p \"%s\", %lld) == %lld",
861                data, qt_prettyDebug(data, readSoFar, 16).constData(), maxlen, readSoFar);
862 #endif
863         if (!readSoFar && processState == ::QProcess::NotRunning)
864             return -1;              // EOF
865         return readSoFar;
866     }
867 }
868 
869 /*!
870     Constructs a QProcess object with the given \a parent.
871 */
K3bQProcess(QObject * parent)872 K3bQProcess::K3bQProcess(QObject *parent)
873     : QIODevice(parent),
874       d_ptr( new K3bQProcessPrivate )
875 {
876     d_ptr->q_ptr = this;
877 //#if defined QPROCESS_DEBUG
878     qDebug("K3bQProcess::QProcess(%p)", parent);
879 //#endif
880 }
881 
882 /*!
883     Destructs the QProcess object, i.e., killing the process.
884 
885     Note that this function will not return until the process is
886     terminated.
887 */
~K3bQProcess()888 K3bQProcess::~K3bQProcess()
889 {
890     Q_D(K3bQProcess);
891     if (d->processState != ::QProcess::NotRunning) {
892         qWarning("QProcess: Destroyed while process is still running.");
893         kill();
894         waitForFinished();
895     }
896 #ifdef Q_OS_UNIX
897     // make sure the process manager removes this entry
898     d->findExitCode();
899 #endif
900     d->cleanup();
901     delete d;
902 }
903 
flags() const904 K3bQProcess::ProcessFlags K3bQProcess::flags() const
905 {
906     Q_D(const K3bQProcess);
907     return d->processFlags;
908 }
909 
setFlags(K3bQProcess::ProcessFlags flags)910 void K3bQProcess::setFlags( K3bQProcess::ProcessFlags flags )
911 {
912     Q_D(K3bQProcess);
913     d->processFlags = flags;
914 }
915 
916 /*!
917     \obsolete
918     Returns the read channel mode of the QProcess. This function is
919     equivalent to processChannelMode()
920 
921     \sa processChannelMode()
922 */
readChannelMode() const923 ::QProcess::ProcessChannelMode K3bQProcess::readChannelMode() const
924 {
925     return processChannelMode();
926 }
927 
928 /*!
929     \obsolete
930 
931     Use setProcessChannelMode(\a mode) instead.
932 
933     \sa setProcessChannelMode()
934 */
setReadChannelMode(::QProcess::ProcessChannelMode mode)935 void K3bQProcess::setReadChannelMode(::QProcess::ProcessChannelMode mode)
936 {
937     setProcessChannelMode(mode);
938 }
939 
940 /*!
941     \since 4.2
942 
943     Returns the channel mode of the QProcess standard output and
944     standard error channels.
945 
946     \sa setReadChannelMode(), ProcessChannelMode, setReadChannel()
947 */
processChannelMode() const948 ::QProcess::ProcessChannelMode K3bQProcess::processChannelMode() const
949 {
950     Q_D(const K3bQProcess);
951     return d->processChannelMode;
952 }
953 
954 /*!
955     \since 4.2
956 
957     Sets the channel mode of the QProcess standard output and standard
958     error channels to the \a mode specified.
959     This mode will be used the next time start() is called. For example:
960 
961     \snippet doc/src/snippets/code/src_corelib_io_qprocess.cpp 0
962 
963     \sa readChannelMode(), ProcessChannelMode, setReadChannel()
964 */
setProcessChannelMode(::QProcess::ProcessChannelMode mode)965 void K3bQProcess::setProcessChannelMode(::QProcess::ProcessChannelMode mode)
966 {
967     Q_D(K3bQProcess);
968     d->processChannelMode = mode;
969 }
970 
971 /*!
972     Returns the current read channel of the QProcess.
973 
974     \sa setReadChannel()
975 */
readChannel() const976 QProcess::ProcessChannel K3bQProcess::readChannel() const
977 {
978     Q_D(const K3bQProcess);
979     return d->processChannel;
980 }
981 
982 /*!
983     Sets the current read channel of the QProcess to the given \a
984     channel. The current input channel is used by the functions
985     read(), readAll(), readLine(), and getChar(). It also determines
986     which channel triggers QProcess to emit readyRead().
987 
988     \sa readChannel()
989 */
setReadChannel(::QProcess::ProcessChannel channel)990 void K3bQProcess::setReadChannel(::QProcess::ProcessChannel channel)
991 {
992     Q_D(K3bQProcess);
993 //     if (d->processChannel != channel) {
994 //         QByteArray buf = d->buffer.readAll();
995 //         if (d->processChannel == QProcess::StandardOutput) {
996 //             for (int i = buf.size() - 1; i >= 0; --i)
997 //                 d->outputReadBuffer.ungetChar(buf.at(i));
998 //         } else {
999 //             for (int i = buf.size() - 1; i >= 0; --i)
1000 //                 d->errorReadBuffer.ungetChar(buf.at(i));
1001 //         }
1002 //     }
1003     d->processChannel = channel;
1004 }
1005 
1006 /*!
1007     Closes the read channel \a channel. After calling this function,
1008     QProcess will no longer receive data on the channel. Any data that
1009     has already been received is still available for reading.
1010 
1011     Call this function to save memory, if you are not interested in
1012     the output of the process.
1013 
1014     \sa closeWriteChannel(), setReadChannel()
1015 */
closeReadChannel(::QProcess::ProcessChannel channel)1016 void K3bQProcess::closeReadChannel(::QProcess::ProcessChannel channel)
1017 {
1018     Q_D(K3bQProcess);
1019 
1020     if (channel == ::QProcess::StandardOutput) {
1021         d->stdoutChannel.closed = true;
1022         if ( d->processFlags&RawStdout )
1023             d->destroyPipe(d->stdoutChannel.pipe);
1024     }
1025     else
1026         d->stderrChannel.closed = true;
1027 }
1028 
1029 /*!
1030     Schedules the write channel of QProcess to be closed. The channel
1031     will close once all data has been written to the process. After
1032     calling this function, any attempts to write to the process will
1033     fail.
1034 
1035     Closing the write channel is necessary for programs that read
1036     input data until the channel has been closed. For example, the
1037     program "more" is used to display text data in a console on both
1038     Unix and Windows. But it will not display the text data until
1039     QProcess's write channel has been closed. Example:
1040 
1041     \snippet doc/src/snippets/code/src_corelib_io_qprocess.cpp 1
1042 
1043     The write channel is implicitly opened when start() is called.
1044 
1045     \sa closeReadChannel()
1046 */
closeWriteChannel()1047 void K3bQProcess::closeWriteChannel()
1048 {
1049     Q_D(K3bQProcess);
1050     d->stdinChannel.closed = true; // closing
1051     if (d->writeBuffer.isEmpty())
1052         d->closeWriteChannel();
1053 }
1054 
1055 /*!
1056     \since 4.2
1057 
1058     Redirects the process' standard input to the file indicated by \a
1059     fileName. When an input redirection is in place, the QProcess
1060     object will be in read-only mode (calling write() will result in
1061     error).
1062 
1063     If the file \a fileName does not exist at the moment start() is
1064     called or is not readable, starting the process will fail.
1065 
1066     Calling setStandardInputFile() after the process has started has no
1067     effect.
1068 
1069     \sa setStandardOutputFile(), setStandardErrorFile(),
1070         setStandardOutputProcess()
1071 */
setStandardInputFile(const QString & fileName)1072 void K3bQProcess::setStandardInputFile(const QString &fileName)
1073 {
1074     Q_D(K3bQProcess);
1075     d->stdinChannel = fileName;
1076 }
1077 
1078 /*!
1079     \since 4.2
1080 
1081     Redirects the process' standard output to the file \a
1082     fileName. When the redirection is in place, the standard output
1083     read channel is closed: reading from it using read() will always
1084     fail, as will readAllStandardOutput().
1085 
1086     If the file \a fileName doesn't exist at the moment start() is
1087     called, it will be created. If it cannot be created, the starting
1088     will fail.
1089 
1090     If the file exists and \a mode is QIODevice::Truncate, the file
1091     will be truncated. Otherwise (if \a mode is QIODevice::Append),
1092     the file will be appended to.
1093 
1094     Calling setStandardOutputFile() after the process has started has
1095     no effect.
1096 
1097     \sa setStandardInputFile(), setStandardErrorFile(),
1098         setStandardOutputProcess()
1099 */
setStandardOutputFile(const QString & fileName,OpenMode mode)1100 void K3bQProcess::setStandardOutputFile(const QString &fileName, OpenMode mode)
1101 {
1102     Q_ASSERT(mode == Append || mode == Truncate);
1103     Q_D(K3bQProcess);
1104 
1105     d->stdoutChannel = fileName;
1106     d->stdoutChannel.append = mode == Append;
1107 }
1108 
1109 /*!
1110     \since 4.2
1111 
1112     Redirects the process' standard error to the file \a
1113     fileName. When the redirection is in place, the standard error
1114     read channel is closed: reading from it using read() will always
1115     fail, as will readAllStandardError(). The file will be appended to
1116     if \a mode is Append, otherwise, it will be truncated.
1117 
1118     See setStandardOutputFile() for more information on how the file
1119     is opened.
1120 
1121     Note: if setProcessChannelMode() was called with an argument of
1122     QProcess::MergedChannels, this function has no effect.
1123 
1124     \sa setStandardInputFile(), setStandardOutputFile(),
1125         setStandardOutputProcess()
1126 */
setStandardErrorFile(const QString & fileName,OpenMode mode)1127 void K3bQProcess::setStandardErrorFile(const QString &fileName, OpenMode mode)
1128 {
1129     Q_ASSERT(mode == Append || mode == Truncate);
1130     Q_D(K3bQProcess);
1131 
1132     d->stderrChannel = fileName;
1133     d->stderrChannel.append = mode == Append;
1134 }
1135 
1136 /*!
1137     \since 4.2
1138 
1139     Pipes the standard output stream of this process to the \a
1140     destination process' standard input.
1141 
1142     The following shell command:
1143     \snippet doc/src/snippets/code/src_corelib_io_qprocess.cpp 2
1144 
1145     Can be accomplished with QProcesses with the following code:
1146     \snippet doc/src/snippets/code/src_corelib_io_qprocess.cpp 3
1147 */
setStandardOutputProcess(K3bQProcess * destination)1148 void K3bQProcess::setStandardOutputProcess(K3bQProcess *destination)
1149 {
1150     K3bQProcessPrivate *dfrom = d_func();
1151     K3bQProcessPrivate *dto = destination->d_func();
1152     dfrom->stdoutChannel.pipeTo(dto);
1153     dto->stdinChannel.pipeFrom(dfrom);
1154 }
1155 
1156 /*!
1157     If QProcess has been assigned a working directory, this function returns
1158     the working directory that the QProcess will enter before the program has
1159     started. Otherwise, (i.e., no directory has been assigned,) an empty
1160     string is returned, and QProcess will use the application's current
1161     working directory instead.
1162 
1163     \sa setWorkingDirectory()
1164 */
workingDirectory() const1165 QString K3bQProcess::workingDirectory() const
1166 {
1167     Q_D(const K3bQProcess);
1168     return d->workingDirectory;
1169 }
1170 
1171 /*!
1172     Sets the working directory to \a dir. QProcess will start the
1173     process in this directory. The default behavior is to start the
1174     process in the working directory of the calling process.
1175 
1176     \sa workingDirectory(), start()
1177 */
setWorkingDirectory(const QString & dir)1178 void K3bQProcess::setWorkingDirectory(const QString &dir)
1179 {
1180     Q_D(K3bQProcess);
1181     d->workingDirectory = dir;
1182 }
1183 
1184 /*!
1185     Returns the native process identifier for the running process, if
1186     available.  If no process is currently running, 0 is returned.
1187 */
pid() const1188 Q_PID K3bQProcess::pid() const
1189 {
1190     Q_D(const K3bQProcess);
1191     return d->pid;
1192 }
1193 
1194 /*! \reimp
1195 
1196     This function operates on the current read channel.
1197 
1198     \sa readChannel(), setReadChannel()
1199 */
canReadLine() const1200 bool K3bQProcess::canReadLine() const
1201 {
1202     Q_D(const K3bQProcess);
1203     const QRingBuffer *readBuffer = (d->processChannel == ::QProcess::StandardError)
1204                                     ? &d->errorReadBuffer
1205                                     : &d->outputReadBuffer;
1206     return readBuffer->canReadLine() || QIODevice::canReadLine();
1207 }
1208 
1209 /*!
1210     Closes all communication with the process and kills it. After calling this
1211     function, QProcess will no longer emit readyRead(), and data can no
1212     longer be read or written.
1213 */
close()1214 void K3bQProcess::close()
1215 {
1216     emit aboutToClose();
1217     while (waitForBytesWritten(-1))
1218         ;
1219     kill();
1220     waitForFinished(-1);
1221     QIODevice::close();
1222 }
1223 
1224 /*! \reimp
1225 
1226    Returns true if the process is not running, and no more data is available
1227    for reading; otherwise returns false.
1228 */
atEnd() const1229 bool K3bQProcess::atEnd() const
1230 {
1231     Q_D(const K3bQProcess);
1232     const QRingBuffer *readBuffer = (d->processChannel == ::QProcess::StandardError)
1233                                     ? &d->errorReadBuffer
1234                                     : &d->outputReadBuffer;
1235     return QIODevice::atEnd() && (!isOpen() || readBuffer->isEmpty());
1236 }
1237 
1238 /*! \reimp
1239 */
isSequential() const1240 bool K3bQProcess::isSequential() const
1241 {
1242     return true;
1243 }
1244 
1245 /*! \reimp
1246 */
bytesAvailable() const1247 qint64 K3bQProcess::bytesAvailable() const
1248 {
1249     Q_D(const K3bQProcess);
1250     const QRingBuffer *readBuffer = (d->processChannel == ::QProcess::StandardError)
1251                                     ? &d->errorReadBuffer
1252                                     : &d->outputReadBuffer;
1253 #if defined QPROCESS_DEBUG
1254     qDebug("QProcess::bytesAvailable() == %i (%s)", readBuffer->size(),
1255            (d->processChannel == ::QProcess::StandardError) ? "stderr" : "stdout");
1256 #endif
1257     return readBuffer->size() + QIODevice::bytesAvailable();
1258 }
1259 
1260 /*! \reimp
1261 */
bytesToWrite() const1262 qint64 K3bQProcess::bytesToWrite() const
1263 {
1264     Q_D(const K3bQProcess);
1265     qint64 size = d->writeBuffer.size();
1266 #ifdef Q_OS_WIN
1267     size += d->pipeWriterBytesToWrite();
1268 #endif
1269     return size;
1270 }
1271 
1272 /*!
1273     Returns the type of error that occurred last.
1274 
1275     \sa state()
1276 */
error() const1277 ::QProcess::ProcessError K3bQProcess::error() const
1278 {
1279     Q_D(const K3bQProcess);
1280     return d->processError;
1281 }
1282 
1283 /*!
1284     Returns the current state of the process.
1285 
1286     \sa stateChanged(), error()
1287 */
state() const1288 ::QProcess::ProcessState K3bQProcess::state() const
1289 {
1290     Q_D(const K3bQProcess);
1291     return d->processState;
1292 }
1293 
1294 /*!
1295     Sets the environment that QProcess will use when starting a process to the
1296     \a environment specified which consists of a list of key=value pairs.
1297 
1298     For example, the following code adds the \c{C:\\BIN} directory to the list of
1299     executable paths (\c{PATHS}) on Windows:
1300 
1301     \snippet doc/src/snippets/qprocess-environment/main.cpp 0
1302 
1303     \sa environment(), systemEnvironment()
1304 */
setEnvironment(const QStringList & environment)1305 void K3bQProcess::setEnvironment(const QStringList &environment)
1306 {
1307     Q_D(K3bQProcess);
1308     d->environment = environment;
1309 }
1310 
1311 /*!
1312     Returns the environment that QProcess will use when starting a
1313     process, or an empty QStringList if no environment has been set
1314     using setEnvironment(). If no environment has been set, the
1315     environment of the calling process will be used.
1316 
1317     \note The environment settings are ignored on Windows CE,
1318     as there is no concept of an environment.
1319 
1320     \sa setEnvironment(), systemEnvironment()
1321 */
environment() const1322 QStringList K3bQProcess::environment() const
1323 {
1324     Q_D(const K3bQProcess);
1325     return d->environment;
1326 }
1327 
1328 /*!
1329     Blocks until the process has started and the started() signal has
1330     been emitted, or until \a msecs milliseconds have passed.
1331 
1332     Returns true if the process was started successfully; otherwise
1333     returns false (if the operation timed out or if an error
1334     occurred).
1335 
1336     This function can operate without an event loop. It is
1337     useful when writing non-GUI applications and when performing
1338     I/O operations in a non-GUI thread.
1339 
1340     \warning Calling this function from the main (GUI) thread
1341     might cause your user interface to freeze.
1342 
1343     If msecs is -1, this function will not time out.
1344 
1345     \sa started(), waitForReadyRead(), waitForBytesWritten(), waitForFinished()
1346 */
waitForStarted(int msecs)1347 bool K3bQProcess::waitForStarted(int msecs)
1348 {
1349     Q_D(K3bQProcess);
1350     if (d->processState == ::QProcess::Starting) {
1351         if (!d->waitForStarted(msecs))
1352             return false;
1353         setProcessState(::QProcess::Running);
1354         emit started();
1355     }
1356     return d->processState == ::QProcess::Running;
1357 }
1358 
1359 /*! \reimp
1360 */
waitForReadyRead(int msecs)1361 bool K3bQProcess::waitForReadyRead(int msecs)
1362 {
1363     Q_D(K3bQProcess);
1364 
1365     if (d->processState == ::QProcess::NotRunning)
1366         return false;
1367     if (d->processChannel == ::QProcess::StandardOutput && d->stdoutChannel.closed)
1368         return false;
1369     if (d->processChannel == ::QProcess::StandardError && d->stderrChannel.closed)
1370         return false;
1371     return d->waitForReadyRead(msecs);
1372 }
1373 
1374 /*! \reimp
1375 */
waitForBytesWritten(int msecs)1376 bool K3bQProcess::waitForBytesWritten(int msecs)
1377 {
1378     Q_D(K3bQProcess);
1379     if (d->processState == ::QProcess::NotRunning)
1380         return false;
1381     if (d->processState == ::QProcess::Starting) {
1382         QElapsedTimer stopWatch;
1383         stopWatch.start();
1384         bool started = waitForStarted(msecs);
1385         if (!started)
1386             return false;
1387         if (msecs != -1)
1388             msecs -= stopWatch.elapsed();
1389     }
1390 
1391     return d->waitForBytesWritten(msecs);
1392 }
1393 
1394 /*!
1395     Blocks until the process has finished and the finished() signal
1396     has been emitted, or until \a msecs milliseconds have passed.
1397 
1398     Returns true if the process finished; otherwise returns false (if
1399     the operation timed out or if an error occurred).
1400 
1401     This function can operate without an event loop. It is
1402     useful when writing non-GUI applications and when performing
1403     I/O operations in a non-GUI thread.
1404 
1405     \warning Calling this function from the main (GUI) thread
1406     might cause your user interface to freeze.
1407 
1408     If msecs is -1, this function will not time out.
1409 
1410     \sa finished(), waitForStarted(), waitForReadyRead(), waitForBytesWritten()
1411 */
waitForFinished(int msecs)1412 bool K3bQProcess::waitForFinished(int msecs)
1413 {
1414     Q_D(K3bQProcess);
1415     if (d->processState == ::QProcess::NotRunning)
1416         return false;
1417     if (d->processState == ::QProcess::Starting) {
1418         QElapsedTimer stopWatch;
1419         stopWatch.start();
1420         bool started = waitForStarted(msecs);
1421         if (!started)
1422             return false;
1423         if (msecs != -1)
1424             msecs -= stopWatch.elapsed();
1425     }
1426 
1427     return d->waitForFinished(msecs);
1428 }
1429 
1430 /*!
1431     Sets the current state of the QProcess to the \a state specified.
1432 
1433     \sa state()
1434 */
setProcessState(::QProcess::ProcessState state)1435 void K3bQProcess::setProcessState(::QProcess::ProcessState state)
1436 {
1437     Q_D(K3bQProcess);
1438     if (d->processState == state)
1439         return;
1440     d->processState = state;
1441     emit stateChanged(state);
1442 }
1443 
1444 /*!
1445   This function is called in the child process context just before the
1446     program is executed on Unix or Mac OS X (i.e., after \e fork(), but before
1447     \e execve()). Reimplement this function to do last minute initialization
1448     of the child process. Example:
1449 
1450     \snippet doc/src/snippets/code/src_corelib_io_qprocess.cpp 4
1451 
1452     You cannot exit the process (by calling exit(), for instance) from
1453     this function. If you need to stop the program before it starts
1454     execution, your workaround is to emit finished() and then call
1455     exit().
1456 
1457     \warning This function is called by QProcess on Unix and Mac OS X
1458     only. On Windows, it is not called.
1459 */
setupChildProcess()1460 void K3bQProcess::setupChildProcess()
1461 {
1462 }
1463 
1464 /*! \reimp
1465 */
readData(char * data,qint64 maxlen)1466 qint64 K3bQProcess::readData(char *data, qint64 maxlen)
1467 {
1468     Q_D(K3bQProcess);
1469     return d->readData( data, maxlen, d->processChannel );
1470 }
1471 
1472 /*! \reimp
1473 */
writeData(const char * data,qint64 len)1474 qint64 K3bQProcess::writeData(const char *data, qint64 len)
1475 {
1476     Q_D(K3bQProcess);
1477 
1478 #if defined(Q_OS_WINCE)
1479     Q_UNUSED(data);
1480     Q_UNUSED(len);
1481     d->processError = ::QProcess::WriteError;
1482     setErrorString(tr("Error writing to process"));
1483     emit error(d->processError);
1484     return -1;
1485 #endif
1486 
1487     if (d->stdinChannel.closed) {
1488 #if defined QPROCESS_DEBUG
1489     qDebug("QProcess::writeData(%p \"%s\", %lld) == 0 (write channel closing)",
1490            data, qt_prettyDebug(data, len, 16).constData(), len);
1491 #endif
1492         return 0;
1493     }
1494 
1495     if (d->processFlags & K3bQProcess::RawStdin) {
1496         d->waitForBytesWritten();
1497         qint64 r = d->writeToStdin(data, len);
1498         if ( r > 0 )
1499             emit bytesWritten(r);
1500         return r;
1501     }
1502     else {
1503         if (len == 1) {
1504             d->writeBuffer.putChar(*data);
1505             if (d->stdinChannel.notifier)
1506                 d->stdinChannel.notifier->setEnabled(true);
1507 #if defined QPROCESS_DEBUG
1508             qDebug("QProcess::writeData(%p \"%s\", %lld) == 1 (written to buffer)",
1509                    data, qt_prettyDebug(data, len, 16).constData(), len);
1510 #endif
1511             return 1;
1512         }
1513 
1514         char *dest = d->writeBuffer.reserve(len);
1515         memcpy(dest, data, len);
1516         if (d->stdinChannel.notifier)
1517             d->stdinChannel.notifier->setEnabled(true);
1518 #if defined QPROCESS_DEBUG
1519         qDebug("QProcess::writeData(%p \"%s\", %lld) == %lld (written to buffer)",
1520                data, qt_prettyDebug(data, len, 16).constData(), len, len);
1521 #endif
1522         return len;
1523     }
1524 }
1525 
1526 /*!
1527     Regardless of the current read channel, this function returns all
1528     data available from the standard output of the process as a
1529     QByteArray.
1530 
1531     \sa readyReadStandardOutput(), readAllStandardError(), readChannel(), setReadChannel()
1532 */
readAllStandardOutput()1533 QByteArray K3bQProcess::readAllStandardOutput()
1534 {
1535     Q_D(K3bQProcess);
1536     if (!(d->processFlags&RawStdout)) {
1537         ::QProcess::ProcessChannel tmp = readChannel();
1538         setReadChannel(::QProcess::StandardOutput);
1539         QByteArray data = readAll();
1540         setReadChannel(tmp);
1541         return data;
1542     }
1543     else {
1544         return QByteArray();
1545     }
1546 }
1547 
1548 /*!
1549     Regardless of the current read channel, this function returns all
1550     data available from the standard error of the process as a
1551     QByteArray.
1552 
1553     \sa readyReadStandardError(), readAllStandardOutput(), readChannel(), setReadChannel()
1554 */
readAllStandardError()1555 QByteArray K3bQProcess::readAllStandardError()
1556 {
1557     Q_D(K3bQProcess);
1558     if (d->processFlags&RawStdout) {
1559         //
1560         // HACK: this is an ugly hack to get around the following problem:
1561         // K3b uses QProcess from different threads. This is no problem unless
1562         // the read channel is changed here while the other thread tries to read
1563         // from stdout. It will then result in two reads from stderr instead
1564         // (this one and the other thread which originally wanted to read from
1565         // stdout).
1566         // The "solution" atm is to reimplement QIODevice::readAll here, ignoring its
1567         // buffer (no real problem since K3b::Process is always opened Unbuffered)
1568         //
1569         QByteArray tmp;
1570         tmp.resize(int(d->errorReadBuffer.size()));
1571         qint64 readBytes = d->readData(tmp.data(), tmp.size(), QProcess::StandardError);
1572         tmp.resize(readBytes < 0 ? 0 : int(readBytes));
1573         return tmp;
1574     }
1575     else {
1576         ::QProcess::ProcessChannel tmp = readChannel();
1577         setReadChannel(::QProcess::StandardError);
1578         QByteArray data = readAll();
1579         setReadChannel(tmp);
1580         return data;
1581     }
1582 }
1583 
1584 /*!
1585     Starts the program \a program in a new process, passing the
1586     command line arguments in \a arguments. The OpenMode is set to \a
1587     mode. QProcess will immediately enter the Starting state. If the
1588     process starts successfully, QProcess will emit started();
1589     otherwise, error() will be emitted.
1590 
1591     Note that arguments that contain spaces are not passed to the
1592     process as separate arguments.
1593 
1594     \bold{Windows:} Arguments that contain spaces are wrapped in quotes.
1595 
1596     \note Processes are started asynchronously, which means the started()
1597     and error() signals may be delayed. Call waitForStarted() to make
1598     sure the process has started (or has failed to start) and those signals
1599     have been emitted.
1600 
1601     \sa pid(), started(), waitForStarted()
1602 */
start(const QString & program,const QStringList & arguments,OpenMode mode)1603 void K3bQProcess::start(const QString &program, const QStringList &arguments, OpenMode mode)
1604 {
1605     Q_D(K3bQProcess);
1606     if (d->processState != ::QProcess::NotRunning) {
1607         qWarning("QProcess::start: Process is already running");
1608         return;
1609     }
1610 
1611 #if defined QPROCESS_DEBUG
1612     qDebug() << "QProcess::start(" << program << "," << arguments << "," << mode << ")";
1613 #endif
1614 
1615     d->outputReadBuffer.clear();
1616     d->errorReadBuffer.clear();
1617 
1618     d->isReadyWrite = false;
1619 
1620     if (d->stdinChannel.type != K3bQProcessPrivate::Channel::Normal)
1621         mode &= ~WriteOnly;     // not open for writing
1622     if (d->stdoutChannel.type != K3bQProcessPrivate::Channel::Normal &&
1623         (d->stderrChannel.type != K3bQProcessPrivate::Channel::Normal ||
1624          d->processChannelMode == ::QProcess::MergedChannels))
1625         mode &= ~ReadOnly;      // not open for reading
1626     if (mode == 0)
1627         mode = Unbuffered;
1628     QIODevice::open(mode);
1629 
1630     d->stdinChannel.closed = false;
1631     d->stdoutChannel.closed = false;
1632     d->stderrChannel.closed = false;
1633 
1634     d->program = program;
1635     d->arguments = arguments;
1636 
1637     d->exitCode = 0;
1638     d->exitStatus = ::QProcess::NormalExit;
1639     d->processError = ::QProcess::UnknownError;
1640     setErrorString( QString() );
1641     d->startProcess();
1642 }
1643 
1644 
parseCombinedArgString(const QString & program)1645 static QStringList parseCombinedArgString(const QString &program)
1646 {
1647     QStringList args;
1648     QString tmp;
1649     int quoteCount = 0;
1650     bool inQuote = false;
1651 
1652     // handle quoting. tokens can be surrounded by double quotes
1653     // "hello world". three consecutive double quotes represent
1654     // the quote character itself.
1655     for (int i = 0; i < program.size(); ++i) {
1656         if (program.at(i) == QLatin1Char('"')) {
1657             ++quoteCount;
1658             if (quoteCount == 3) {
1659                 // third consecutive quote
1660                 quoteCount = 0;
1661                 tmp += program.at(i);
1662             }
1663             continue;
1664         }
1665         if (quoteCount) {
1666             if (quoteCount == 1)
1667                 inQuote = !inQuote;
1668             quoteCount = 0;
1669         }
1670         if (!inQuote && program.at(i).isSpace()) {
1671             if (!tmp.isEmpty()) {
1672                 args += tmp;
1673                 tmp.clear();
1674             }
1675         } else {
1676             tmp += program.at(i);
1677         }
1678     }
1679     if (!tmp.isEmpty())
1680         args += tmp;
1681 
1682     return args;
1683 }
1684 
1685 /*!
1686     \overload
1687 
1688     Starts the program \a program in a new process. \a program is a
1689     single string of text containing both the program name and its
1690     arguments. The arguments are separated by one or more
1691     spaces. For example:
1692 
1693     \snippet doc/src/snippets/code/src_corelib_io_qprocess.cpp 5
1694 
1695     The \a program string can also contain quotes, to ensure that arguments
1696     containing spaces are correctly supplied to the new process. For example:
1697 
1698     \snippet doc/src/snippets/code/src_corelib_io_qprocess.cpp 6
1699 
1700     Note that, on Windows, quotes need to be both escaped and quoted.
1701     For example, the above code would be specified in the following
1702     way to ensure that \c{"My Documents"} is used as the argument to
1703     the \c dir executable:
1704 
1705     \snippet doc/src/snippets/code/src_corelib_io_qprocess.cpp 7
1706 
1707     The OpenMode is set to \a mode.
1708 */
start(const QString & program,OpenMode mode)1709 void K3bQProcess::start(const QString &program, OpenMode mode)
1710 {
1711     QStringList args = parseCombinedArgString(program);
1712 
1713     QString prog = args.first();
1714     args.removeFirst();
1715 
1716     start(prog, args, mode);
1717 }
1718 
1719 /*!
1720     Attempts to terminate the process.
1721 
1722     The process may not exit as a result of calling this function (it is given
1723     the chance to prompt the user for any unsaved files, etc).
1724 
1725     On Windows, terminate() posts a WM_CLOSE message to all toplevel windows
1726     of the process and then to the main thread of the process itself. On Unix
1727     and Mac OS X the SIGTERM signal is sent.
1728 
1729     Console applications on Windows that do not run an event loop, or whose
1730     event loop does not handle the WM_CLOSE message, can only be terminated by
1731     calling kill().
1732 
1733     \sa kill()
1734 */
terminate()1735 void K3bQProcess::terminate()
1736 {
1737     Q_D(K3bQProcess);
1738     d->terminateProcess();
1739 }
1740 
1741 /*!
1742     Kills the current process, causing it to exit immediately.
1743 
1744     On Windows, kill() uses TerminateProcess, and on Unix and Mac OS X, the
1745     SIGKILL signal is sent to the process.
1746 
1747     \sa terminate()
1748 */
kill()1749 void K3bQProcess::kill()
1750 {
1751     Q_D(K3bQProcess);
1752     d->killProcess();
1753 }
1754 
1755 /*!
1756     Returns the exit code of the last process that finished.
1757 */
exitCode() const1758 int K3bQProcess::exitCode() const
1759 {
1760     Q_D(const K3bQProcess);
1761     return d->exitCode;
1762 }
1763 
1764 /*!
1765     \since 4.1
1766 
1767     Returns the exit status of the last process that finished.
1768 
1769     On Windows, if the process was terminated with TerminateProcess()
1770     from another application this function will still return NormalExit
1771     unless the exit code is less than 0.
1772 */
exitStatus() const1773 ::QProcess::ExitStatus K3bQProcess::exitStatus() const
1774 {
1775     Q_D(const K3bQProcess);
1776     return d->exitStatus;
1777 }
1778 
1779 /*!
1780     Starts the program \a program with the arguments \a arguments in a
1781     new process, waits for it to finish, and then returns the exit
1782     code of the process. Any data the new process writes to the
1783     console is forwarded to the calling process.
1784 
1785     The environment and working directory are inherited by the calling
1786     process.
1787 
1788     On Windows, arguments that contain spaces are wrapped in quotes.
1789 */
execute(const QString & program,const QStringList & arguments)1790 int K3bQProcess::execute(const QString &program, const QStringList &arguments)
1791 {
1792     QProcess process;
1793     process.setProcessChannelMode(::QProcess::ForwardedChannels);
1794     process.start(program, arguments);
1795     process.waitForFinished(-1);
1796     return process.exitCode();
1797 }
1798 
1799 /*!
1800     \overload
1801 
1802     Starts the program \a program in a new process. \a program is a
1803     single string of text containing both the program name and its
1804     arguments. The arguments are separated by one or more spaces.
1805 */
execute(const QString & program)1806 int K3bQProcess::execute(const QString &program)
1807 {
1808     QProcess process;
1809     process.setProcessChannelMode(::QProcess::ForwardedChannels);
1810     process.start(program);
1811     process.waitForFinished(-1);
1812     return process.exitCode();
1813 }
1814 
1815 /*!
1816     Starts the program \a program with the arguments \a arguments in a
1817     new process, and detaches from it. Returns true on success;
1818     otherwise returns false. If the calling process exits, the
1819     detached process will continue to live.
1820 
1821     Note that arguments that contain spaces are not passed to the
1822     process as separate arguments.
1823 
1824     \bold{Unix:} The started process will run in its own session and act
1825     like a daemon.
1826 
1827     \bold{Windows:} Arguments that contain spaces are wrapped in quotes.
1828     The started process will run as a regular standalone process.
1829 
1830     The process will be started in the directory \a workingDirectory.
1831 
1832     If the function is successful then *\a pid is set to the process
1833     identifier of the started process.
1834 */
startDetached(const QString & program,const QStringList & arguments,const QString & workingDirectory,qint64 * pid)1835 bool K3bQProcess::startDetached(const QString &program,
1836 			     const QStringList &arguments,
1837 			     const QString &workingDirectory,
1838                              qint64 *pid)
1839 {
1840     return K3bQProcessPrivate::startDetached(program,
1841 					  arguments,
1842 					  workingDirectory,
1843 					  pid);
1844 }
1845 
1846 /*!
1847     Starts the program \a program with the given \a arguments in a
1848     new process, and detaches from it. Returns true on success;
1849     otherwise returns false. If the calling process exits, the
1850     detached process will continue to live.
1851 
1852     Note that arguments that contain spaces are not passed to the
1853     process as separate arguments.
1854 
1855     \bold{Unix:} The started process will run in its own session and act
1856     like a daemon.
1857 
1858     \bold{Windows:} Arguments that contain spaces are wrapped in quotes.
1859     The started process will run as a regular standalone process.
1860 */
startDetached(const QString & program,const QStringList & arguments)1861 bool K3bQProcess::startDetached(const QString &program,
1862 			     const QStringList &arguments)
1863 {
1864     return K3bQProcessPrivate::startDetached(program, arguments);
1865 }
1866 
1867 /*!
1868     \overload
1869 
1870     Starts the program \a program in a new process. \a program is a
1871     single string of text containing both the program name and its
1872     arguments. The arguments are separated by one or more spaces.
1873 
1874     The \a program string can also contain quotes, to ensure that arguments
1875     containing spaces are correctly supplied to the new process.
1876 */
startDetached(const QString & program)1877 bool K3bQProcess::startDetached(const QString &program)
1878 {
1879     QStringList args = parseCombinedArgString(program);
1880 
1881     QString prog = args.first();
1882     args.removeFirst();
1883 
1884     return K3bQProcessPrivate::startDetached(prog, args);
1885 }
1886 
1887 QT_BEGIN_INCLUDE_NAMESPACE
1888 #ifdef Q_OS_MAC
1889 # include <crt_externs.h>
1890 # define environ (*_NSGetEnviron())
1891 #elif defined(Q_OS_WINCE)
1892   static char *qt_wince_environ[] = { 0 };
1893 #define environ qt_wince_environ
1894 #elif !defined(Q_OS_WIN)
1895   extern char **environ;
1896 #endif
1897 QT_END_INCLUDE_NAMESPACE
1898 
1899 /*!
1900     \since 4.1
1901 
1902     Returns the environment of the calling process as a list of
1903     key=value pairs. Example:
1904 
1905     \snippet doc/src/snippets/code/src_corelib_io_qprocess.cpp 8
1906 
1907     \sa environment(), setEnvironment()
1908 */
systemEnvironment()1909 QStringList K3bQProcess::systemEnvironment()
1910 {
1911     QStringList tmp;
1912 //     char *entry = 0;
1913 //     int count = 0;
1914 //     while ((entry = environ[count++]))
1915 //         tmp << QString::fromLocal8Bit(entry);
1916     return tmp;
1917 }
1918 
isReadyWrite() const1919 bool K3bQProcess::isReadyWrite() const
1920 {
1921     Q_D(const K3bQProcess);
1922     return d->isReadyWrite;
1923 }
1924 
1925 
1926 /*!
1927     \typedef Q_PID
1928     \relates QProcess
1929 
1930     Typedef for the identifiers used to represent processes on the underlying
1931     platform. On Unix, this corresponds to \l qint64; on Windows, it
1932     corresponds to \c{_PROCESS_INFORMATION*}.
1933 
1934     \sa QProcess::pid()
1935 */
1936 
1937 
1938 //QT_END_NAMESPACE
1939 
1940 #include "moc_k3bqprocess.cpp"
1941 
1942 #endif // QT_NO_PROCESS
1943 
1944