File indexing completed on 2024-05-12 04:51:18

0001 /*
0002     SPDX-FileCopyrightText: 2009 Nokia Corporation and /or its subsidiary(-ies).
0003     Contact: Qt Software Information (qt-info@nokia.com)
0004 
0005     This file is part of the QtCore module of the Qt Toolkit.
0006 
0007     $QT_BEGIN_LICENSE:LGPL$
0008     Commercial Usage
0009     Licensees holding valid Qt Commercial licenses may use this file in
0010     accordance with the Qt Commercial License Agreement provided with the
0011     Software or, alternatively, in accordance with the terms contained in
0012     a written agreement between you and Nokia.
0013 
0014     GNU Lesser General Public License Usage
0015     Alternatively, this file may be used under the terms of the GNU Lesser
0016     General Public License version 2.1 as published by the Free Software
0017     Foundation and appearing in the file LICENSE.LGPL included in the
0018     packaging of this file.  Please review the following information to
0019     ensure the GNU Lesser General Public License version 2.1 requirements
0020     will be met: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
0021 
0022     In addition, as a special exception, Nokia gives you certain
0023     additional rights. These rights are described in the Nokia Qt LGPL
0024     Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
0025     package.
0026 
0027     GNU General Public License Usage
0028     Alternatively, this file may be used under the terms of the GNU
0029     General Public License version 3.0 as published by the Free Software
0030     Foundation and appearing in the file LICENSE.GPL included in the
0031     packaging of this file.  Please review the following information to
0032     ensure the GNU General Public License version 3.0 requirements will be
0033     met: https://www.gnu.org/licenses/gpl-3.0.html.
0034 
0035     If you are unsure which license is appropriate for your use, please
0036     contact the sales department at qt-sales@nokia.com.
0037     $QT_END_LICENSE$
0038 
0039 */
0040 
0041 //#define QPROCESS_DEBUG
0042 #include <QElapsedTimer>
0043 #if defined QPROCESS_DEBUG
0044 #include <qdebug.h>
0045 #include <QString>
0046 #include <ctype.h>
0047 #if !defined(Q_OS_WINCE)
0048 #include <errno.h>
0049 #endif
0050 
0051 //QT_BEGIN_NAMESPACE
0052 /*
0053     Returns a human readable representation of the first \a len
0054     characters in \a data.
0055 */
0056 static QByteArray qt_prettyDebug(const char *data, int len, int maxSize)
0057 {
0058     if (!data) return "(null)";
0059     QByteArray out;
0060     for (int i = 0; i < len && i < maxSize; ++i) {
0061         char c = data[i];
0062         if (isprint(c)) {
0063             out += c;
0064         } else switch (c) {
0065         case '\n': out += "\\n"; break;
0066         case '\r': out += "\\r"; break;
0067         case '\t': out += "\\t"; break;
0068         default:
0069             char buf[5];
0070             qsnprintf(buf, sizeof(buf), "\\%3o", c);
0071             buf[4] = '\0';
0072             out += QByteArray(buf);
0073         }
0074     }
0075 
0076     if (len < maxSize)
0077         out += "...";
0078 
0079     return out;
0080 }
0081 
0082 //QT_END_NAMESPACE
0083 
0084 #endif
0085 
0086 #include "k3bqprocess.h"
0087 #include "k3bqprocess_p.h"
0088 
0089 #include <QByteArray>
0090 #include <QDateTime>
0091 #include <qcoreapplication.h>
0092 #include <qsocketnotifier.h>
0093 #include <QTimer>
0094 
0095 #ifdef Q_WS_WIN
0096 #include <private/qwineventnotifier_p.h>
0097 #endif
0098 
0099 #ifndef QT_NO_PROCESS
0100 
0101 //QT_BEGIN_NAMESPACE
0102 
0103 void K3bQProcessPrivate::Channel::clear()
0104 {
0105     switch (type) {
0106     case PipeSource:
0107         Q_ASSERT(process);
0108         process->stdinChannel.type = Normal;
0109         process->stdinChannel.process = 0;
0110         break;
0111     case PipeSink:
0112         Q_ASSERT(process);
0113         process->stdoutChannel.type = Normal;
0114         process->stdoutChannel.process = 0;
0115         break;
0116     }
0117 
0118     type = Normal;
0119     file.clear();
0120     process = 0;
0121 }
0122 
0123 /*!
0124     \class QProcess
0125 
0126     \brief The QProcess class is used to start external programs and
0127     to communicate with them.
0128 
0129     \ingroup io
0130     \ingroup misc
0131     \mainclass
0132     \reentrant
0133 
0134     To start a process, pass the name and command line arguments of
0135     the program you want to run as arguments to start(). For example:
0136 
0137     \snippet doc/src/snippets/qprocess/qprocess-simpleexecution.cpp 0
0138     \dots
0139     \snippet doc/src/snippets/qprocess/qprocess-simpleexecution.cpp 1
0140     \snippet doc/src/snippets/qprocess/qprocess-simpleexecution.cpp 2
0141 
0142     QProcess then enters the \l Starting state, and when the program
0143     has started, QProcess enters the \l Running state and emits
0144     started().
0145 
0146     QProcess allows you to treat a process as a sequential I/O
0147     device. You can write to and read from the process just as you
0148     would access a network connection using QTcpSocket. You can then
0149     write to the process's standard input by calling write(), and
0150     read the standard output by calling read(), readLine(), and
0151     getChar(). Because it inherits QIODevice, QProcess can also be
0152     used as an input source for QXmlReader, or for generating data to
0153     be uploaded using QFtp.
0154 
0155     \note On Windows CE, reading and writing to a process is not supported.
0156 
0157     When the process exits, QProcess reenters the \l NotRunning state
0158     (the initial state), and emits finished().
0159 
0160     The finished() signal provides the exit code and exit status of
0161     the process as arguments, and you can also call exitCode() to
0162     obtain the exit code of the last process that finished, and
0163     exitStatus() to obtain its exit status. If an error occurs at
0164     any point in time, QProcess will emit the error() signal. You
0165     can also call error() to find the type of error that occurred
0166     last, and state() to find the current process state.
0167 
0168     \section1 Communicating via Channels
0169 
0170     Processes have two predefined output channels: The standard
0171     output channel (\c stdout) supplies regular console output, and
0172     the standard error channel (\c stderr) usually supplies the
0173     errors that are printed by the process. These channels represent
0174     two separate streams of data. You can toggle between them by
0175     calling setReadChannel(). QProcess emits readyRead() when data is
0176     available on the current read channel. It also emits
0177     readyReadStandardOutput() when new standard output data is
0178     available, and when new standard error data is available,
0179     readyReadStandardError() is emitted. Instead of calling read(),
0180     readLine(), or getChar(), you can explicitly read all data from
0181     either of the two channels by calling readAllStandardOutput() or
0182     readAllStandardError().
0183 
0184     The terminology for the channels can be misleading. Be aware that
0185     the process's output channels correspond to QProcess's
0186     \e read channels, whereas the process's input channels correspond
0187     to QProcess's \e write channels. This is because what we read
0188     using QProcess is the process's output, and what we write becomes
0189     the process's input.
0190 
0191     QProcess can merge the two output channels, so that standard
0192     output and standard error data from the running process both use
0193     the standard output channel. Call setProcessChannelMode() with
0194     MergedChannels before starting the process to activate
0195     this feature. You also have the option of forwarding the output of
0196     the running process to the calling, main process, by passing
0197     ForwardedChannels as the argument.
0198 
0199     Certain processes need special environment settings in order to
0200     operate. You can set environment variables for your process by
0201     calling setEnvironment(). To set a working directory, call
0202     setWorkingDirectory(). By default, processes are run in the
0203     current working directory of the calling process.
0204 
0205     \section1 Synchronous Process API
0206 
0207     QProcess provides a set of functions which allow it to be used
0208     without an event loop, by suspending the calling thread until
0209     certain signals are emitted:
0210 
0211     \list
0212     \o waitForStarted() blocks until the process has started.
0213 
0214     \o waitForReadyRead() blocks until new data is
0215     available for reading on the current read channel.
0216 
0217     \o waitForBytesWritten() blocks until one payload of
0218     data has been written to the process.
0219 
0220     \o waitForFinished() blocks until the process has finished.
0221     \endlist
0222 
0223     Calling these functions from the main thread (the thread that
0224     calls QApplication::exec()) may cause your user interface to
0225     freeze.
0226 
0227     The following example runs \c gzip to compress the string "Qt
0228     rocks!", without an event loop:
0229 
0230     \snippet doc/src/snippets/process/process.cpp 0
0231 
0232     \section1 Notes for Windows Users
0233 
0234     Some Windows commands (for example, \c dir) are not provided by
0235     separate applications, but by the command interpreter itself.
0236     If you attempt to use QProcess to execute these commands directly,
0237     it won't work. One possible solution is to execute the command
0238     interpreter itself (\c{cmd.exe} on some Windows systems), and ask
0239     the interpreter to execute the desired command.
0240 
0241     \sa QBuffer, QFile, QTcpSocket
0242 */
0243 
0244 /*!
0245     \enum QProcess::ProcessChannel
0246 
0247     This enum describes the process channels used by the running process.
0248     Pass one of these values to setReadChannel() to set the
0249     current read channel of QProcess.
0250 
0251     \value StandardOutput The standard output (stdout) of the running
0252            process.
0253 
0254     \value StandardError The standard error (stderr) of the running
0255            process.
0256 
0257     \sa setReadChannel()
0258 */
0259 
0260 /*!
0261     \enum QProcess::ProcessChannelMode
0262 
0263     This enum describes the process channel modes of QProcess. Pass
0264     one of these values to setProcessChannelMode() to set the
0265     current read channel mode.
0266 
0267     \value SeparateChannels QProcess manages the output of the
0268     running process, keeping standard output and standard error data
0269     in separate internal buffers. You can select the QProcess's
0270     current read channel by calling setReadChannel(). This is the
0271     default channel mode of QProcess.
0272 
0273     \value MergedChannels QProcess merges the output of the running
0274     process into the standard output channel (\c stdout). The
0275     standard error channel (\c stderr) will not receive any data. The
0276     standard output and standard error data of the running process
0277     are interleaved.
0278 
0279     \value ForwardedChannels QProcess forwards the output of the
0280     running process onto the main process. Anything the child process
0281     writes to its standard output and standard error will be written
0282     to the standard output and standard error of the main process.
0283 
0284     \sa setReadChannelMode()
0285 */
0286 
0287 /*!
0288     \enum QProcess::ProcessError
0289 
0290     This enum describes the different types of errors that are
0291     reported by QProcess.
0292 
0293     \value FailedToStart The process failed to start. Either the
0294     invoked program is missing, or you may have insufficient
0295     permissions to invoke the program.
0296 
0297     \value Crashed The process crashed some time after starting
0298     successfully.
0299 
0300     \value Timedout The last waitFor...() function timed out. The
0301     state of QProcess is unchanged, and you can try calling
0302     waitFor...() again.
0303 
0304     \value WriteError An error occurred when attempting to write to the
0305     process. For example, the process may not be running, or it may
0306     have closed its input channel.
0307 
0308     \value ReadError An error occurred when attempting to read from
0309     the process. For example, the process may not be running.
0310 
0311     \value UnknownError An unknown error occurred. This is the default
0312     return value of error().
0313 
0314     \sa error()
0315 */
0316 
0317 /*!
0318     \enum QProcess::ProcessState
0319 
0320     This enum describes the different states of QProcess.
0321 
0322     \value NotRunning The process is not running.
0323 
0324     \value Starting The process is starting, but the program has not
0325     yet been invoked.
0326 
0327     \value Running The process is running and is ready for reading and
0328     writing.
0329 
0330     \sa state()
0331 */
0332 
0333 /*!
0334     \enum QProcess::ExitStatus
0335 
0336     This enum describes the different exit statuses of QProcess.
0337 
0338     \value NormalExit The process exited normally.
0339 
0340     \value CrashExit The process crashed.
0341 
0342     \sa exitStatus()
0343 */
0344 
0345 /*!
0346     \fn void QProcess::error(QProcess::ProcessError error)
0347 
0348     This signal is emitted when an error occurs with the process. The
0349     specified \a error describes the type of error that occurred.
0350 */
0351 
0352 /*!
0353     \fn void QProcess::started()
0354 
0355     This signal is emitted by QProcess when the process has started,
0356     and state() returns \l Running.
0357 */
0358 
0359 /*!
0360     \fn void QProcess::stateChanged(QProcess::ProcessState newState)
0361 
0362     This signal is emitted whenever the state of QProcess changes. The
0363     \a newState argument is the state QProcess changed to.
0364 */
0365 
0366 /*!
0367     \fn void QProcess::finished(int exitCode)
0368     \obsolete
0369     \overload
0370 
0371     Use finished(int exitCode, QProcess::ExitStatus status) instead.
0372 */
0373 
0374 /*!
0375     \fn void QProcess::finished(int exitCode, QProcess::ExitStatus exitStatus)
0376 
0377     This signal is emitted when the process finishes. \a exitCode is the exit
0378     code of the process, and \a exitStatus is the exit status.  After the
0379     process has finished, the buffers in QProcess are still intact. You can
0380     still read any data that the process may have written before it finished.
0381 
0382     \sa exitStatus()
0383 */
0384 
0385 /*!
0386     \fn void QProcess::readyReadStandardOutput()
0387 
0388     This signal is emitted when the process has made new data
0389     available through its standard output channel (\c stdout). It is
0390     emitted regardless of the current \l{readChannel()}{read channel}.
0391 
0392     \sa readAllStandardOutput(), readChannel()
0393 */
0394 
0395 /*!
0396     \fn void QProcess::readyReadStandardError()
0397 
0398     This signal is emitted when the process has made new data
0399     available through its standard error channel (\c stderr). It is
0400     emitted regardless of the current \l{readChannel()}{read
0401     channel}.
0402 
0403     \sa readAllStandardError(), readChannel()
0404 */
0405 
0406 /*! \internal
0407 */
0408 K3bQProcessPrivate::K3bQProcessPrivate()
0409 {
0410     processChannel = ::QProcess::StandardOutput;
0411     processChannelMode = ::QProcess::SeparateChannels;
0412     processError = ::QProcess::UnknownError;
0413     processState = ::QProcess::NotRunning;
0414     pid = 0;
0415     sequenceNumber = 0;
0416     exitCode = 0;
0417     exitStatus = ::QProcess::NormalExit;
0418     startupSocketNotifier = 0;
0419     deathNotifier = 0;
0420     notifier = 0;
0421     pipeWriter = 0;
0422     childStartedPipe[0] = INVALID_Q_PIPE;
0423     childStartedPipe[1] = INVALID_Q_PIPE;
0424     deathPipe[0] = INVALID_Q_PIPE;
0425     deathPipe[1] = INVALID_Q_PIPE;
0426     exitCode = 0;
0427     crashed = false;
0428     dying = false;
0429     emittedReadyRead = false;
0430     emittedBytesWritten = false;
0431 #ifdef Q_WS_WIN
0432     pipeWriter = 0;
0433     processFinishedNotifier = 0;
0434 #endif // Q_WS_WIN
0435 #ifdef Q_OS_UNIX
0436     serial = 0;
0437 #endif
0438 }
0439 
0440 /*! \internal
0441 */
0442 K3bQProcessPrivate::~K3bQProcessPrivate()
0443 {
0444     if (stdinChannel.process)
0445         stdinChannel.process->stdoutChannel.clear();
0446     if (stdoutChannel.process)
0447         stdoutChannel.process->stdinChannel.clear();
0448 }
0449 
0450 /*! \internal
0451 */
0452 
0453 void qDeleteInEventHandler(QObject *o);
0454 
0455 void K3bQProcessPrivate::cleanup()
0456 {
0457     q_func()->setProcessState(::QProcess::NotRunning);
0458 #ifdef Q_OS_WIN
0459     if (pid) {
0460         CloseHandle(pid->hThread);
0461         CloseHandle(pid->hProcess);
0462         delete pid;
0463         pid = 0;
0464     }
0465     if (processFinishedNotifier) {
0466         processFinishedNotifier->setEnabled(false);
0467         qDeleteInEventHandler(processFinishedNotifier);
0468         processFinishedNotifier = 0;
0469     }
0470 
0471 #endif
0472     pid = 0;
0473     sequenceNumber = 0;
0474     dying = false;
0475 
0476     if (stdoutChannel.notifier) {
0477         stdoutChannel.notifier->setEnabled(false);
0478         delete stdoutChannel.notifier;
0479         stdoutChannel.notifier = 0;
0480     }
0481     if (stderrChannel.notifier) {
0482         stderrChannel.notifier->setEnabled(false);
0483         delete stderrChannel.notifier;
0484         stderrChannel.notifier = 0;
0485     }
0486     if (stdinChannel.notifier) {
0487         stdinChannel.notifier->setEnabled(false);
0488         delete stdinChannel.notifier;
0489         stdinChannel.notifier = 0;
0490     }
0491     if (startupSocketNotifier) {
0492         startupSocketNotifier->setEnabled(false);
0493         delete startupSocketNotifier;
0494         startupSocketNotifier = 0;
0495     }
0496     if (deathNotifier) {
0497         deathNotifier->setEnabled(false);
0498         delete deathNotifier;
0499         deathNotifier = 0;
0500     }
0501     if (notifier) {
0502         delete notifier;
0503         notifier = 0;
0504     }
0505     destroyPipe(stdoutChannel.pipe);
0506     destroyPipe(stderrChannel.pipe);
0507     destroyPipe(stdinChannel.pipe);
0508     destroyPipe(childStartedPipe);
0509     destroyPipe(deathPipe);
0510 #ifdef Q_OS_UNIX
0511     serial = 0;
0512 #endif
0513 }
0514 
0515 /*! \internal
0516 */
0517 bool K3bQProcessPrivate::_q_canReadStandardOutput()
0518 {
0519     Q_Q(K3bQProcess);
0520     qint64 available = bytesAvailableFromStdout();
0521     if (available == 0) {
0522         if (stdoutChannel.notifier)
0523             stdoutChannel.notifier->setEnabled(false);
0524         destroyPipe(stdoutChannel.pipe);
0525 #if defined QPROCESS_DEBUG
0526         qDebug("K3bQProcessPrivate::canReadStandardOutput(), 0 bytes available");
0527 #endif
0528         return false;
0529     }
0530 
0531     if (!(processFlags & K3bQProcess::RawStdout)) {
0532         char *ptr = outputReadBuffer.reserve(available);
0533         qint64 readBytes = readFromStdout(ptr, available);
0534         if (readBytes == -1) {
0535             processError = ::QProcess::ReadError;
0536             q->setErrorString(K3bQProcess::tr("Error reading from process"));
0537             emit q->error(processError);
0538 #if defined QPROCESS_DEBUG
0539             qDebug("K3bQProcessPrivate::canReadStandardOutput(), failed to read from the process");
0540 #endif
0541             return false;
0542         }
0543 #if defined QPROCESS_DEBUG
0544         qDebug("K3bQProcessPrivate::canReadStandardOutput(), read %d bytes from the process' output",
0545                int(readBytes));
0546 #endif
0547 
0548         if (stdoutChannel.closed) {
0549             outputReadBuffer.chop(readBytes);
0550             return false;
0551         }
0552 
0553         outputReadBuffer.chop(available - readBytes);
0554 
0555         bool didRead = false;
0556         if (readBytes == 0) {
0557             if (stdoutChannel.notifier)
0558                 stdoutChannel.notifier->setEnabled(false);
0559         } else if (processChannel == ::QProcess::StandardOutput) {
0560             didRead = true;
0561             if (!emittedReadyRead) {
0562                 emittedReadyRead = true;
0563                 emit q->readyRead();
0564                 emittedReadyRead = false;
0565             }
0566         }
0567         emit q->readyReadStandardOutput();
0568         return didRead;
0569     }
0570     else {
0571         if (!emittedReadyRead) {
0572             emittedReadyRead = true;
0573             emit q->readyRead();
0574             emittedReadyRead = false;
0575         }
0576         emit q->readyReadStandardOutput();
0577         return true;
0578     }
0579 }
0580 
0581 /*! \internal
0582 */
0583 bool K3bQProcessPrivate::_q_canReadStandardError()
0584 {
0585     Q_Q(K3bQProcess);
0586     qint64 available = bytesAvailableFromStderr();
0587     if (available == 0) {
0588         if (stderrChannel.notifier)
0589             stderrChannel.notifier->setEnabled(false);
0590         destroyPipe(stderrChannel.pipe);
0591         return false;
0592     }
0593 
0594     char *ptr = errorReadBuffer.reserve(available);
0595     qint64 readBytes = readFromStderr(ptr, available);
0596     if (readBytes == -1) {
0597         processError = ::QProcess::ReadError;
0598         q->setErrorString(K3bQProcess::tr("Error reading from process"));
0599         emit q->error(processError);
0600         return false;
0601     }
0602     if (stderrChannel.closed) {
0603         errorReadBuffer.chop(readBytes);
0604         return false;
0605     }
0606 
0607     errorReadBuffer.chop(available - readBytes);
0608 
0609     bool didRead = false;
0610     if (readBytes == 0) {
0611         if (stderrChannel.notifier)
0612             stderrChannel.notifier->setEnabled(false);
0613     } else if (processChannel == ::QProcess::StandardError) {
0614         didRead = true;
0615         if (!emittedReadyRead) {
0616             emittedReadyRead = true;
0617             emit q->readyRead();
0618             emittedReadyRead = false;
0619         }
0620     }
0621     emit q->readyReadStandardError();
0622     return didRead;
0623 }
0624 
0625 /*! \internal
0626 */
0627 bool K3bQProcessPrivate::_q_canWrite()
0628 {
0629     Q_Q(K3bQProcess);
0630     if (processFlags & K3bQProcess::RawStdin) {
0631         if (stdinChannel.notifier)
0632             stdinChannel.notifier->setEnabled(false);
0633         isReadyWrite = true;
0634         emit q->readyWrite();
0635     }
0636     else {
0637         if (stdinChannel.notifier)
0638             stdinChannel.notifier->setEnabled(false);
0639 
0640         if (writeBuffer.isEmpty()) {
0641 #if defined QPROCESS_DEBUG
0642             qDebug("K3bQProcessPrivate::canWrite(), not writing anything (empty write buffer).");
0643 #endif
0644             return false;
0645         }
0646 
0647         qint64 written = writeToStdin(writeBuffer.readPointer(),
0648                                       writeBuffer.nextDataBlockSize());
0649         if (written < 0) {
0650             destroyPipe(stdinChannel.pipe);
0651             processError = ::QProcess::WriteError;
0652             q->setErrorString(K3bQProcess::tr("Error writing to process"));
0653 #if defined(QPROCESS_DEBUG) && !defined(Q_OS_WINCE)
0654             qDebug("K3bQProcessPrivate::canWrite(), failed to write (%s)", strerror(errno));
0655 #endif
0656             emit q->error(processError);
0657             return false;
0658         }
0659 
0660 #if defined QPROCESS_DEBUG
0661         qDebug("K3bQProcessPrivate::canWrite(), wrote %d bytes to the process input", int(written));
0662 #endif
0663 
0664         writeBuffer.free(written);
0665         if (!emittedBytesWritten) {
0666             emittedBytesWritten = true;
0667             emit q->bytesWritten(written);
0668             emittedBytesWritten = false;
0669         }
0670         if (stdinChannel.notifier && !writeBuffer.isEmpty())
0671             stdinChannel.notifier->setEnabled(true);
0672         if (writeBuffer.isEmpty() && stdinChannel.closed)
0673             closeWriteChannel();
0674     }
0675     return true;
0676 }
0677 
0678 /*! \internal
0679 */
0680 bool K3bQProcessPrivate::_q_processDied()
0681 {
0682 #if defined QPROCESS_DEBUG
0683     qDebug("K3bQProcessPrivate::_q_processDied()");
0684 #endif
0685 #ifdef Q_OS_UNIX
0686     if (!waitForDeadChild())
0687         return false;
0688 #endif
0689 #ifdef Q_OS_WIN
0690     if (processFinishedNotifier)
0691         processFinishedNotifier->setEnabled(false);
0692 #endif
0693 
0694     // the process may have died before it got a chance to report that it was
0695     // either running or stopped, so we will call _q_startupNotification() and
0696     // give it a chance to emit started() or error(FailedToStart).
0697     if (processState == ::QProcess::Starting) {
0698         if (!_q_startupNotification())
0699             return true;
0700     }
0701 
0702     return _q_notifyProcessDied();
0703 }
0704 
0705 bool K3bQProcessPrivate::_q_notifyProcessDied()
0706 {
0707     Q_Q(K3bQProcess);
0708 #if defined QPROCESS_DEBUG
0709     qDebug("K3bQProcessPrivate::_q_notifyProcessDied()");
0710 #endif
0711 
0712     if ( processFlags&K3bQProcess::RawStdout ) {
0713         qint64 bytes = bytesAvailableFromStdout();
0714 #if defined QPROCESS_DEBUG
0715         qDebug() << "bytesAvailableFromStdout:" << bytes;
0716 #endif
0717         // wait for all data to be read
0718         if ( bytes > 0 ) {
0719             QMetaObject::invokeMethod( q, "_q_notifyProcessDied", Qt::QueuedConnection );
0720             return false;
0721         }
0722     }
0723 
0724     if (dying) {
0725         // at this point we know the process is dead. prevent
0726         // reentering this slot recursively by calling waitForFinished()
0727         // or opening a dialog inside slots connected to the readyRead
0728         // signals emitted below.
0729         return true;
0730     }
0731     dying = true;
0732 
0733     // in case there is data in the pipe line and this slot by chance
0734     // got called before the read notifications, call these two slots
0735     // so the data is made available before the process dies.
0736     if ( !processFlags.testFlag( K3bQProcess::RawStdout ) ) {
0737         _q_canReadStandardOutput();
0738     }
0739     _q_canReadStandardError();
0740     findExitCode();
0741 
0742     if (crashed) {
0743         exitStatus = ::QProcess::CrashExit;
0744         processError = ::QProcess::Crashed;
0745         q->setErrorString(K3bQProcess::tr("Process crashed"));
0746         emit q->error(processError);
0747     }
0748 
0749     bool wasRunning = (processState == ::QProcess::Running);
0750 
0751     cleanup();
0752 
0753     if (wasRunning) {
0754         // we received EOF now:
0755         emit q->readChannelFinished();
0756         // in the future:
0757         //emit q->standardOutputClosed();
0758         //emit q->standardErrorClosed();
0759 
0760         emit q->finished(exitCode);
0761         emit q->finished(exitCode, exitStatus);
0762     }
0763 #if defined QPROCESS_DEBUG
0764     qDebug("K3bQProcessPrivate::_q_notifyProcessDied() process is dead");
0765 #endif
0766     return true;
0767 }
0768 
0769 /*! \internal
0770 */
0771 bool K3bQProcessPrivate::_q_startupNotification()
0772 {
0773     Q_Q(K3bQProcess);
0774 #if defined QPROCESS_DEBUG
0775     qDebug("K3bQProcessPrivate::startupNotification()");
0776 #endif
0777 
0778     if (startupSocketNotifier)
0779         startupSocketNotifier->setEnabled(false);
0780     if (processStarted()) {
0781         q->setProcessState(::QProcess::Running);
0782         emit q->started();
0783         return true;
0784     }
0785 
0786     q->setProcessState(::QProcess::NotRunning);
0787     processError = ::QProcess::FailedToStart;
0788     emit q->error(processError);
0789 #ifdef Q_OS_UNIX
0790     // make sure the process manager removes this entry
0791     waitForDeadChild();
0792     findExitCode();
0793 #endif
0794     cleanup();
0795     return false;
0796 }
0797 
0798 /*! \internal
0799 */
0800 void K3bQProcessPrivate::closeWriteChannel()
0801 {
0802 #if defined QPROCESS_DEBUG
0803     qDebug("K3bQProcessPrivate::closeWriteChannel()");
0804 #endif
0805     if (stdinChannel.notifier) {
0806         stdinChannel.notifier->setEnabled(false);
0807         if (stdinChannel.notifier) {
0808             delete stdinChannel.notifier;
0809             stdinChannel.notifier = 0;
0810         }
0811     }
0812 #ifdef Q_OS_WIN
0813     // ### Find a better fix, feeding the process little by little
0814     // instead.
0815     flushPipeWriter();
0816 #endif
0817     destroyPipe(stdinChannel.pipe);
0818 }
0819 
0820 qint64 K3bQProcessPrivate::readData( char *data, qint64 maxlen, QProcess::ProcessChannel channel )
0821 {
0822     if (processFlags&K3bQProcess::RawStdout &&
0823         channel == ::QProcess::StandardOutput) {
0824         return readFromStdout(data, maxlen);
0825     }
0826     else {
0827         QRingBuffer *readBuffer = (channel == ::QProcess::StandardError)
0828                                   ? &errorReadBuffer
0829                                   : &outputReadBuffer;
0830 
0831         if (maxlen == 1 && !readBuffer->isEmpty()) {
0832             int c = readBuffer->getChar();
0833             if (c == -1) {
0834 #if defined QPROCESS_DEBUG
0835                 qDebug("QProcess::readData(%p \"%s\", %d) == -1",
0836                        data, qt_prettyDebug(data, 1, maxlen).constData(), 1);
0837 #endif
0838                 return -1;
0839             }
0840             *data = (char) c;
0841 #if defined QPROCESS_DEBUG
0842             qDebug("QProcess::readData(%p \"%s\", %d) == 1",
0843                    data, qt_prettyDebug(data, 1, maxlen).constData(), 1);
0844 #endif
0845             return 1;
0846         }
0847 
0848         qint64 bytesToRead = qint64(qMin(readBuffer->size(), (int)maxlen));
0849         qint64 readSoFar = 0;
0850         while (readSoFar < bytesToRead) {
0851             const char *ptr = readBuffer->readPointer();
0852             int bytesToReadFromThisBlock = qMin<qint64>(bytesToRead - readSoFar,
0853                                                         readBuffer->nextDataBlockSize());
0854             memcpy(data + readSoFar, ptr, bytesToReadFromThisBlock);
0855             readSoFar += bytesToReadFromThisBlock;
0856             readBuffer->free(bytesToReadFromThisBlock);
0857         }
0858 
0859 #if defined QPROCESS_DEBUG
0860         qDebug("QProcess::readData(%p \"%s\", %lld) == %lld",
0861                data, qt_prettyDebug(data, readSoFar, 16).constData(), maxlen, readSoFar);
0862 #endif
0863         if (!readSoFar && processState == ::QProcess::NotRunning)
0864             return -1;              // EOF
0865         return readSoFar;
0866     }
0867 }
0868 
0869 /*!
0870     Constructs a QProcess object with the given \a parent.
0871 */
0872 K3bQProcess::K3bQProcess(QObject *parent)
0873     : QIODevice(parent),
0874       d_ptr( new K3bQProcessPrivate )
0875 {
0876     d_ptr->q_ptr = this;
0877 //#if defined QPROCESS_DEBUG
0878     qDebug("K3bQProcess::QProcess(%p)", parent);
0879 //#endif
0880 }
0881 
0882 /*!
0883     Destructs the QProcess object, i.e., killing the process.
0884 
0885     Note that this function will not return until the process is
0886     terminated.
0887 */
0888 K3bQProcess::~K3bQProcess()
0889 {
0890     Q_D(K3bQProcess);
0891     if (d->processState != ::QProcess::NotRunning) {
0892         qWarning("QProcess: Destroyed while process is still running.");
0893         kill();
0894         waitForFinished();
0895     }
0896 #ifdef Q_OS_UNIX
0897     // make sure the process manager removes this entry
0898     d->findExitCode();
0899 #endif
0900     d->cleanup();
0901     delete d;
0902 }
0903 
0904 K3bQProcess::ProcessFlags K3bQProcess::flags() const
0905 {
0906     Q_D(const K3bQProcess);
0907     return d->processFlags;
0908 }
0909 
0910 void K3bQProcess::setFlags( K3bQProcess::ProcessFlags flags )
0911 {
0912     Q_D(K3bQProcess);
0913     d->processFlags = flags;
0914 }
0915 
0916 /*!
0917     \obsolete
0918     Returns the read channel mode of the QProcess. This function is
0919     equivalent to processChannelMode()
0920 
0921     \sa processChannelMode()
0922 */
0923 ::QProcess::ProcessChannelMode K3bQProcess::readChannelMode() const
0924 {
0925     return processChannelMode();
0926 }
0927 
0928 /*!
0929     \obsolete
0930 
0931     Use setProcessChannelMode(\a mode) instead.
0932 
0933     \sa setProcessChannelMode()
0934 */
0935 void K3bQProcess::setReadChannelMode(::QProcess::ProcessChannelMode mode)
0936 {
0937     setProcessChannelMode(mode);
0938 }
0939 
0940 /*!
0941     \since 4.2
0942 
0943     Returns the channel mode of the QProcess standard output and
0944     standard error channels.
0945 
0946     \sa setReadChannelMode(), ProcessChannelMode, setReadChannel()
0947 */
0948 ::QProcess::ProcessChannelMode K3bQProcess::processChannelMode() const
0949 {
0950     Q_D(const K3bQProcess);
0951     return d->processChannelMode;
0952 }
0953 
0954 /*!
0955     \since 4.2
0956 
0957     Sets the channel mode of the QProcess standard output and standard
0958     error channels to the \a mode specified.
0959     This mode will be used the next time start() is called. For example:
0960 
0961     \snippet doc/src/snippets/code/src_corelib_io_qprocess.cpp 0
0962 
0963     \sa readChannelMode(), ProcessChannelMode, setReadChannel()
0964 */
0965 void K3bQProcess::setProcessChannelMode(::QProcess::ProcessChannelMode mode)
0966 {
0967     Q_D(K3bQProcess);
0968     d->processChannelMode = mode;
0969 }
0970 
0971 /*!
0972     Returns the current read channel of the QProcess.
0973 
0974     \sa setReadChannel()
0975 */
0976 QProcess::ProcessChannel K3bQProcess::readChannel() const
0977 {
0978     Q_D(const K3bQProcess);
0979     return d->processChannel;
0980 }
0981 
0982 /*!
0983     Sets the current read channel of the QProcess to the given \a
0984     channel. The current input channel is used by the functions
0985     read(), readAll(), readLine(), and getChar(). It also determines
0986     which channel triggers QProcess to emit readyRead().
0987 
0988     \sa readChannel()
0989 */
0990 void K3bQProcess::setReadChannel(::QProcess::ProcessChannel channel)
0991 {
0992     Q_D(K3bQProcess);
0993 //     if (d->processChannel != channel) {
0994 //         QByteArray buf = d->buffer.readAll();
0995 //         if (d->processChannel == QProcess::StandardOutput) {
0996 //             for (int i = buf.size() - 1; i >= 0; --i)
0997 //                 d->outputReadBuffer.ungetChar(buf.at(i));
0998 //         } else {
0999 //             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 */
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 */
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 */
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 */
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 */
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 */
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 */
1165 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 */
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 */
1188 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 */
1200 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 */
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 */
1229 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 */
1240 bool K3bQProcess::isSequential() const
1241 {
1242     return true;
1243 }
1244 
1245 /*! \reimp
1246 */
1247 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 */
1262 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 */
1277 ::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 */
1288 ::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 */
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 */
1322 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 */
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 */
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 */
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 */
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 */
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 */
1460 void K3bQProcess::setupChildProcess()
1461 {
1462 }
1463 
1464 /*! \reimp
1465 */
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 */
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 */
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 */
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 */
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 
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 */
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 */
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 */
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 */
1758 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 */
1773 ::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, and detaches from it. Returns true on success;
1782     otherwise returns false. If the calling process exits, the
1783     detached process will continue to live.
1784 
1785     Note that arguments that contain spaces are not passed to the
1786     process as separate arguments.
1787 
1788     \bold{Unix:} The started process will run in its own session and act
1789     like a daemon.
1790 
1791     \bold{Windows:} Arguments that contain spaces are wrapped in quotes.
1792     The started process will run as a regular standalone process.
1793 
1794     The process will be started in the directory \a workingDirectory.
1795 
1796     If the function is successful then *\a pid is set to the process
1797     identifier of the started process.
1798 */
1799 bool K3bQProcess::startDetached(const QString &program,
1800                  const QStringList &arguments,
1801                  const QString &workingDirectory,
1802                              qint64 *pid)
1803 {
1804     return K3bQProcessPrivate::startDetached(program,
1805                       arguments,
1806                       workingDirectory,
1807                       pid);
1808 }
1809 
1810 /*!
1811     Starts the program \a program with the given \a arguments in a
1812     new process, and detaches from it. Returns true on success;
1813     otherwise returns false. If the calling process exits, the
1814     detached process will continue to live.
1815 
1816     Note that arguments that contain spaces are not passed to the
1817     process as separate arguments.
1818 
1819     \bold{Unix:} The started process will run in its own session and act
1820     like a daemon.
1821 
1822     \bold{Windows:} Arguments that contain spaces are wrapped in quotes.
1823     The started process will run as a regular standalone process.
1824 */
1825 bool K3bQProcess::startDetached(const QString &program,
1826                  const QStringList &arguments)
1827 {
1828     return K3bQProcessPrivate::startDetached(program, arguments);
1829 }
1830 
1831 /*!
1832     \overload
1833 
1834     Starts the program \a program in a new process. \a program is a
1835     single string of text containing both the program name and its
1836     arguments. The arguments are separated by one or more spaces.
1837 
1838     The \a program string can also contain quotes, to ensure that arguments
1839     containing spaces are correctly supplied to the new process.
1840 */
1841 bool K3bQProcess::startDetached(const QString &program)
1842 {
1843     QStringList args = parseCombinedArgString(program);
1844 
1845     QString prog = args.first();
1846     args.removeFirst();
1847 
1848     return K3bQProcessPrivate::startDetached(prog, args);
1849 }
1850 
1851 QT_BEGIN_INCLUDE_NAMESPACE
1852 #ifdef Q_OS_MAC
1853 # include <crt_externs.h>
1854 # define environ (*_NSGetEnviron())
1855 #elif defined(Q_OS_WINCE)
1856   static char *qt_wince_environ[] = { 0 };
1857 #define environ qt_wince_environ
1858 #elif !defined(Q_OS_WIN)
1859   extern char **environ;
1860 #endif
1861 QT_END_INCLUDE_NAMESPACE
1862 
1863 /*!
1864     \since 4.1
1865 
1866     Returns the environment of the calling process as a list of
1867     key=value pairs. Example:
1868 
1869     \snippet doc/src/snippets/code/src_corelib_io_qprocess.cpp 8
1870 
1871     \sa environment(), setEnvironment()
1872 */
1873 QStringList K3bQProcess::systemEnvironment()
1874 {
1875     QStringList tmp;
1876 //     char *entry = 0;
1877 //     int count = 0;
1878 //     while ((entry = environ[count++]))
1879 //         tmp << QString::fromLocal8Bit(entry);
1880     return tmp;
1881 }
1882 
1883 bool K3bQProcess::isReadyWrite() const
1884 {
1885     Q_D(const K3bQProcess);
1886     return d->isReadyWrite;
1887 }
1888 
1889 
1890 /*!
1891     \typedef Q_PID
1892     \relates QProcess
1893 
1894     Typedef for the identifiers used to represent processes on the underlying
1895     platform. On Unix, this corresponds to \l qint64; on Windows, it
1896     corresponds to \c{_PROCESS_INFORMATION*}.
1897 
1898     \sa QProcess::pid()
1899 */
1900 
1901 
1902 //QT_END_NAMESPACE
1903 
1904 #include "moc_k3bqprocess.cpp"
1905 
1906 #endif // QT_NO_PROCESS
1907