00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #if defined QPROCESS_DEBUG
00027 #include <qdebug.h>
00028 #include <qstring.h>
00029 #include <ctype.h>
00030
00031
00032
00033
00034
00035 static QByteArray qt_prettyDebug(const char *data, int len, int maxSize)
00036 {
00037 if (!data) return "(null)";
00038 QByteArray out;
00039 for (int i = 0; i < len && i < maxSize; ++i) {
00040 char c = data[i];
00041 if (isprint(c)) {
00042 out += c;
00043 } else switch (c) {
00044 case '\n': out += "\\n"; break;
00045 case '\r': out += "\\r"; break;
00046 case '\t': out += "\\t"; break;
00047 default:
00048 char buf[5];
00049 qsnprintf(buf, sizeof(buf), "\\%3o", c);
00050 buf[4] = '\0';
00051 out += QString::fromLatin1(buf);
00052 }
00053 }
00054
00055 if (len < maxSize)
00056 out += "...";
00057
00058 return out;
00059 }
00060 #endif
00061
00062 #include "qprocess.h"
00063 #include "qprocess_p.h"
00064
00065 #include <qbytearray.h>
00066 #include <qdatetime.h>
00067 #include <qcoreapplication.h>
00068 #include <qsocketnotifier.h>
00069 #include <qtimer.h>
00070
00071 #ifdef Q_WS_WIN
00072 #include <private/qwineventnotifier_p.h>
00073 #endif
00074
00075 #ifndef QT_NO_PROCESS
00076
00353 QProcessPrivate::QProcessPrivate()
00354 {
00355 processChannel = QProcess::StandardOutput;
00356 processChannelMode = QProcess::SeparateChannels;
00357 processError = QProcess::UnknownError;
00358 processState = QProcess::NotRunning;
00359 pid = 0;
00360 sequenceNumber = 0;
00361 exitCode = 0;
00362 exitStatus = QProcess::NormalExit;
00363 startupSocketNotifier = 0;
00364 deathNotifier = 0;
00365 notifier = 0;
00366 pipeWriter = 0;
00367 childStartedPipe[0] = INVALID_Q_PIPE;
00368 childStartedPipe[1] = INVALID_Q_PIPE;
00369 deathPipe[0] = INVALID_Q_PIPE;
00370 deathPipe[1] = INVALID_Q_PIPE;
00371 exitCode = 0;
00372 crashed = false;
00373 emittedReadyRead = false;
00374 emittedBytesWritten = false;
00375 #ifdef Q_WS_WIN
00376 pipeWriter = 0;
00377 processFinishedNotifier = 0;
00378 #endif // Q_WS_WIN
00379 #ifdef Q_OS_UNIX
00380 serial = 0;
00381 #endif
00382 }
00383
00386 QProcessPrivate::~QProcessPrivate()
00387 {
00388 if (stdinChannel.process)
00389 stdinChannel.process->stdoutChannel.clear();
00390 if (stdoutChannel.process)
00391 stdoutChannel.process->stdinChannel.clear();
00392 }
00393
00396 void QProcessPrivate::cleanup()
00397 {
00398 processState = QProcess::NotRunning;
00399 #ifdef Q_OS_WIN
00400 if (pid) {
00401 CloseHandle(pid->hThread);
00402 CloseHandle(pid->hProcess);
00403 delete pid;
00404 pid = 0;
00405 }
00406 if (processFinishedNotifier) {
00407 processFinishedNotifier->setEnabled(false);
00408 delete processFinishedNotifier;
00409 processFinishedNotifier = 0;
00410 }
00411
00412 #endif
00413 pid = 0;
00414 sequenceNumber = 0;
00415
00416 if (stdoutChannel.notifier) {
00417 stdoutChannel.notifier->setEnabled(false);
00418 delete stdoutChannel.notifier;
00419 stdoutChannel.notifier = 0;
00420 }
00421 if (stderrChannel.notifier) {
00422 stderrChannel.notifier->setEnabled(false);
00423 delete stderrChannel.notifier;
00424 stderrChannel.notifier = 0;
00425 }
00426 if (stdinChannel.notifier) {
00427 stdinChannel.notifier->setEnabled(false);
00428 delete stdinChannel.notifier;
00429 stdinChannel.notifier = 0;
00430 }
00431 if (startupSocketNotifier) {
00432 startupSocketNotifier->setEnabled(false);
00433 delete startupSocketNotifier;
00434 startupSocketNotifier = 0;
00435 }
00436 if (deathNotifier) {
00437 deathNotifier->setEnabled(false);
00438 delete deathNotifier;
00439 deathNotifier = 0;
00440 }
00441 if (notifier) {
00442 delete notifier;
00443 notifier = 0;
00444 }
00445 destroyPipe(stdoutChannel.pipe);
00446 destroyPipe(stderrChannel.pipe);
00447 destroyPipe(stdinChannel.pipe);
00448 destroyPipe(childStartedPipe);
00449 destroyPipe(deathPipe);
00450 #ifdef Q_OS_UNIX
00451 serial = 0;
00452 #endif
00453 }
00454
00457 bool QProcessPrivate::_q_canReadStandardOutput()
00458 {
00459 Q_Q(QProcess);
00460 qint64 available = bytesAvailableFromStdout();
00461 if (available == 0) {
00462 if (stdoutChannel.notifier)
00463 stdoutChannel.notifier->setEnabled(false);
00464 destroyPipe(stdoutChannel.pipe);
00465 #if defined QPROCESS_DEBUG
00466 qDebug("QProcessPrivate::canReadStandardOutput(), 0 bytes available");
00467 #endif
00468 return false;
00469 }
00470
00471 char *ptr = outputReadBuffer.reserve(available);
00472 qint64 readBytes = readFromStdout(ptr, available);
00473 if (readBytes == -1) {
00474 processError = QProcess::ReadError;
00475 q->setErrorString(QT_TRANSLATE_NOOP(QProcess, QLatin1String("Error reading from process")));
00476 emit q->error(processError);
00477 #if defined QPROCESS_DEBUG
00478 qDebug("QProcessPrivate::canReadStandardOutput(), failed to read from the process");
00479 #endif
00480 return false;
00481 }
00482 #if defined QPROCESS_DEBUG
00483 qDebug("QProcessPrivate::canReadStandardOutput(), read %d bytes from the process' output",
00484 int(readBytes));
00485 #endif
00486
00487 if (stdoutChannel.closed) {
00488 outputReadBuffer.chop(readBytes);
00489 return false;
00490 }
00491
00492 outputReadBuffer.chop(available - readBytes);
00493
00494 bool didRead = false;
00495 if (readBytes == 0) {
00496 if (stdoutChannel.notifier)
00497 stdoutChannel.notifier->setEnabled(false);
00498 } else if (processChannel == QProcess::StandardOutput) {
00499 didRead = true;
00500 if (!emittedReadyRead) {
00501 emittedReadyRead = true;
00502 emit q->readyRead();
00503 emittedReadyRead = false;
00504 }
00505 }
00506 emit q->readyReadStandardOutput();
00507 return didRead;
00508 }
00509
00512 bool QProcessPrivate::_q_canReadStandardError()
00513 {
00514 Q_Q(QProcess);
00515 qint64 available = bytesAvailableFromStderr();
00516 if (available == 0) {
00517 if (stderrChannel.notifier)
00518 stderrChannel.notifier->setEnabled(false);
00519 destroyPipe(stderrChannel.pipe);
00520 return false;
00521 }
00522
00523 char *ptr = errorReadBuffer.reserve(available);
00524 qint64 readBytes = readFromStderr(ptr, available);
00525 if (readBytes == -1) {
00526 processError = QProcess::ReadError;
00527 q->setErrorString(QT_TRANSLATE_NOOP(QProcess, QLatin1String("Error reading from process")));
00528 emit q->error(processError);
00529 return false;
00530 }
00531 if (stderrChannel.closed) {
00532 errorReadBuffer.chop(readBytes);
00533 return false;
00534 }
00535
00536 errorReadBuffer.chop(available - readBytes);
00537
00538 bool didRead = false;
00539 if (readBytes == 0) {
00540 if (stderrChannel.notifier)
00541 stderrChannel.notifier->setEnabled(false);
00542 } else if (processChannel == QProcess::StandardError) {
00543 didRead = true;
00544 if (!emittedReadyRead) {
00545 emittedReadyRead = true;
00546 emit q->readyRead();
00547 emittedReadyRead = false;
00548 }
00549 }
00550 emit q->readyReadStandardError();
00551 return didRead;
00552 }
00553
00556 bool QProcessPrivate::_q_canWrite()
00557 {
00558 Q_Q(QProcess);
00559 if (stdinChannel.notifier)
00560 stdinChannel.notifier->setEnabled(false);
00561
00562 if (writeBuffer.isEmpty()) {
00563 #if defined QPROCESS_DEBUG
00564 qDebug("QProcessPrivate::canWrite(), not writing anything (empty write buffer).");
00565 #endif
00566 return false;
00567 }
00568
00569 qint64 written = writeToStdin(writeBuffer.readPointer(),
00570 writeBuffer.nextDataBlockSize());
00571 if (written < 0) {
00572 destroyPipe(stdinChannel.pipe);
00573 processError = QProcess::WriteError;
00574 q->setErrorString(QT_TRANSLATE_NOOP(QProcess, QLatin1String("Error writing to process")));
00575 #if defined QPROCESS_DEBUG
00576 qDebug("QProcessPrivate::canWrite(), failed to write (%s)", strerror(errno));
00577 #endif
00578 emit q->error(processError);
00579 return false;
00580 }
00581
00582 #if defined QPROCESS_DEBUG
00583 qDebug("QProcessPrivate::canWrite(), wrote %d bytes to the process input", int(written));
00584 #endif
00585
00586 writeBuffer.free(written);
00587 if (!emittedBytesWritten) {
00588 emittedBytesWritten = true;
00589 emit q->bytesWritten(written);
00590 emittedBytesWritten = false;
00591 }
00592 if (stdinChannel.notifier && !writeBuffer.isEmpty())
00593 stdinChannel.notifier->setEnabled(true);
00594 if (writeBuffer.isEmpty() && stdinChannel.closed)
00595 closeWriteChannel();
00596 return true;
00597 }
00598
00601 bool QProcessPrivate::_q_processDied()
00602 {
00603 Q_Q(QProcess);
00604 #if defined QPROCESS_DEBUG
00605 qDebug("QProcessPrivate::_q_processDied()");
00606 #endif
00607 #ifdef Q_OS_UNIX
00608 if (!waitForDeadChild())
00609 return false;
00610 #endif
00611 #ifdef Q_OS_WIN
00612 if (processFinishedNotifier)
00613 processFinishedNotifier->setEnabled(false);
00614 #endif
00615
00616
00617
00618
00619 if (processState == QProcess::Starting) {
00620 if (!_q_startupNotification())
00621 return true;
00622 }
00623
00624
00625
00626
00627 _q_canReadStandardOutput();
00628 _q_canReadStandardError();
00629
00630 findExitCode();
00631
00632 if (crashed) {
00633 exitStatus = QProcess::CrashExit;
00634 processError = QProcess::Crashed;
00635 q->setErrorString(QT_TRANSLATE_NOOP(QProcess, QLatin1String("Process crashed")));
00636 emit q->error(processError);
00637 }
00638
00639 cleanup();
00640
00641 processState = QProcess::NotRunning;
00642 emit q->stateChanged(processState);
00643 emit q->finished(exitCode);
00644 emit q->finished(exitCode, exitStatus);
00645 #if defined QPROCESS_DEBUG
00646 qDebug("QProcessPrivate::_q_processDied() process is dead");
00647 #endif
00648 return true;
00649 }
00650
00653 bool QProcessPrivate::_q_startupNotification()
00654 {
00655 Q_Q(QProcess);
00656 #if defined QPROCESS_DEBUG
00657 qDebug("QProcessPrivate::startupNotification()");
00658 #endif
00659
00660 if (startupSocketNotifier)
00661 startupSocketNotifier->setEnabled(false);
00662 if (processStarted()) {
00663 processState = QProcess::Running;
00664 emit q->started();
00665 return true;
00666 }
00667
00668 processState = QProcess::NotRunning;
00669 processError = QProcess::FailedToStart;
00670 emit q->error(processError);
00671 #ifdef Q_OS_UNIX
00672
00673 waitForDeadChild();
00674 findExitCode();
00675 #endif
00676 cleanup();
00677 return false;
00678 }
00679
00682 void QProcessPrivate::closeWriteChannel()
00683 {
00684 #if defined QPROCESS_DEBUG
00685 qDebug("QProcessPrivate::closeWriteChannel()");
00686 #endif
00687 if (stdinChannel.notifier) {
00688 stdinChannel.notifier->setEnabled(false);
00689 delete stdinChannel.notifier;
00690 stdinChannel.notifier = 0;
00691 }
00692 #ifdef Q_OS_WIN
00693
00694
00695 flushPipeWriter();
00696 #endif
00697 destroyPipe(stdinChannel.pipe);
00698 }
00699
00703 QProcess::QProcess(QObject *parent)
00704 : QIODevice(*new QProcessPrivate, parent)
00705 {
00706 #if defined QPROCESS_DEBUG
00707 qDebug("QProcess::QProcess(%p)", parent);
00708 #endif
00709 }
00710
00717 QProcess::~QProcess()
00718 {
00719 Q_D(QProcess);
00720 if (d->processState != NotRunning) {
00721 qWarning("QProcess: Destroyed while process is still running.");
00722 kill();
00723 waitForFinished();
00724 }
00725 #ifdef Q_OS_UNIX
00726
00727 d->findExitCode();
00728 #endif
00729 d->cleanup();
00730 }
00731
00739 QProcess::ProcessChannelMode QProcess::readChannelMode() const
00740 {
00741 return processChannelMode();
00742 }
00743
00751 void QProcess::setReadChannelMode(ProcessChannelMode mode)
00752 {
00753 setProcessChannelMode(mode);
00754 }
00755
00764 QProcess::ProcessChannelMode QProcess::processChannelMode() const
00765 {
00766 Q_D(const QProcess);
00767 return d->processChannelMode;
00768 }
00769
00790 void QProcess::setProcessChannelMode(ProcessChannelMode mode)
00791 {
00792 Q_D(QProcess);
00793 d->processChannelMode = mode;
00794 }
00795
00801 QProcess::ProcessChannel QProcess::readChannel() const
00802 {
00803 Q_D(const QProcess);
00804 return d->processChannel;
00805 }
00806
00817 void QProcess::setReadChannel(ProcessChannel channel)
00818 {
00819 Q_D(QProcess);
00820 if (d->processChannel != channel)
00821 d->buffer.clear();
00822 d->processChannel = channel;
00823 }
00824
00835 void QProcess::closeReadChannel(ProcessChannel channel)
00836 {
00837 Q_D(QProcess);
00838
00839 if (channel == StandardOutput)
00840 d->stdoutChannel.closed = true;
00841 else
00842 d->stderrChannel.closed = true;
00843 }
00844
00869 void QProcess::closeWriteChannel()
00870 {
00871 Q_D(QProcess);
00872 d->stdinChannel.closed = true;
00873 if (d->writeBuffer.isEmpty())
00874 d->closeWriteChannel();
00875 }
00876
00894 void QProcess::setStandardInputFile(const QString &fileName)
00895 {
00896 Q_D(QProcess);
00897 d->stdinChannel = fileName;
00898 }
00899
00922 void QProcess::setStandardOutputFile(const QString &fileName, OpenMode mode)
00923 {
00924 Q_ASSERT(mode == Append || mode == Truncate);
00925 Q_D(QProcess);
00926
00927 d->stdoutChannel = fileName;
00928 d->stdoutChannel.append = mode == Append;
00929 }
00930
00949 void QProcess::setStandardErrorFile(const QString &fileName, OpenMode mode)
00950 {
00951 Q_ASSERT(mode == Append || mode == Truncate);
00952 Q_D(QProcess);
00953
00954 d->stderrChannel = fileName;
00955 d->stderrChannel.append = mode == Append;
00956 }
00957
00980 void QProcess::setStandardOutputProcess(QProcess *destination)
00981 {
00982 QProcessPrivate *dfrom = d_func();
00983 QProcessPrivate *dto = destination->d_func();
00984 dfrom->stdoutChannel.pipeTo(dto);
00985 dto->stdinChannel.pipeFrom(dfrom);
00986 }
00987
00994 QString QProcess::workingDirectory() const
00995 {
00996 Q_D(const QProcess);
00997 return d->workingDirectory;
00998 }
00999
01007 void QProcess::setWorkingDirectory(const QString &dir)
01008 {
01009 Q_D(QProcess);
01010 d->workingDirectory = dir;
01011 }
01012
01017 Q_PID QProcess::pid() const
01018 {
01019 Q_D(const QProcess);
01020 return d->pid;
01021 }
01022
01029 bool QProcess::canReadLine() const
01030 {
01031 Q_D(const QProcess);
01032 const QRingBuffer *readBuffer = (d->processChannel == QProcess::StandardError)
01033 ? &d->errorReadBuffer
01034 : &d->outputReadBuffer;
01035 return readBuffer->canReadLine() || QIODevice::canReadLine();
01036 }
01037
01043 void QProcess::close()
01044 {
01045 emit aboutToClose();
01046 while (waitForBytesWritten(-1))
01047 ;
01048 kill();
01049 waitForFinished(-1);
01050 setOpenMode(QIODevice::NotOpen);
01051 }
01052
01058 bool QProcess::atEnd() const
01059 {
01060 Q_D(const QProcess);
01061 const QRingBuffer *readBuffer = (d->processChannel == QProcess::StandardError)
01062 ? &d->errorReadBuffer
01063 : &d->outputReadBuffer;
01064 return QIODevice::atEnd() && (!isOpen() || readBuffer->isEmpty());
01065 }
01066
01069 bool QProcess::isSequential() const
01070 {
01071 return true;
01072 }
01073
01076 qint64 QProcess::bytesAvailable() const
01077 {
01078 Q_D(const QProcess);
01079 const QRingBuffer *readBuffer = (d->processChannel == QProcess::StandardError)
01080 ? &d->errorReadBuffer
01081 : &d->outputReadBuffer;
01082 #if defined QPROCESS_DEBUG
01083 qDebug("QProcess::bytesAvailable() == %i (%s)", readBuffer->size(),
01084 (d->processChannel == QProcess::StandardError) ? "stderr" : "stdout");
01085 #endif
01086 return readBuffer->size() + QIODevice::bytesAvailable();
01087 }
01088
01091 qint64 QProcess::bytesToWrite() const
01092 {
01093 Q_D(const QProcess);
01094 return d->writeBuffer.size();
01095 }
01096
01102 QProcess::ProcessError QProcess::error() const
01103 {
01104 Q_D(const QProcess);
01105 return d->processError;
01106 }
01107
01113 QProcess::ProcessState QProcess::state() const
01114 {
01115 Q_D(const QProcess);
01116 return d->processState;
01117 }
01118
01132 void QProcess::setEnvironment(const QStringList &environment)
01133 {
01134 Q_D(QProcess);
01135 d->environment = environment;
01136 }
01137
01146 QStringList QProcess::environment() const
01147 {
01148 Q_D(const QProcess);
01149 return d->environment;
01150 }
01151
01171 bool QProcess::waitForStarted(int msecs)
01172 {
01173 Q_D(QProcess);
01174 if (d->processState == QProcess::Starting) {
01175 if (!d->waitForStarted(msecs))
01176 return false;
01177 d->processState = QProcess::Running;
01178 emit started();
01179 }
01180 return d->processState == QProcess::Running;
01181 }
01182
01185 bool QProcess::waitForReadyRead(int msecs)
01186 {
01187 Q_D(QProcess);
01188
01189 if (d->processState == QProcess::NotRunning)
01190 return false;
01191 if (d->processChannel == QProcess::StandardOutput && d->stdoutChannel.closed)
01192 return false;
01193 if (d->processChannel == QProcess::StandardError && d->stderrChannel.closed)
01194 return false;
01195 return d->waitForReadyRead(msecs);
01196 }
01197
01200 bool QProcess::waitForBytesWritten(int msecs)
01201 {
01202 Q_D(QProcess);
01203 if (d->processState == QProcess::NotRunning)
01204 return false;
01205 if (d->processState == QProcess::Starting) {
01206 QTime stopWatch;
01207 stopWatch.start();
01208 bool started = waitForStarted(msecs);
01209 if (!started)
01210 return false;
01211 if (msecs != -1)
01212 msecs -= stopWatch.elapsed();
01213 }
01214
01215 return d->waitForBytesWritten(msecs);
01216 }
01217
01236 bool QProcess::waitForFinished(int msecs)
01237 {
01238 Q_D(QProcess);
01239 if (d->processState == QProcess::NotRunning)
01240 return false;
01241 if (d->processState == QProcess::Starting) {
01242 QTime stopWatch;
01243 stopWatch.start();
01244 bool started = waitForStarted(msecs);
01245 if (!started)
01246 return false;
01247 if (msecs != -1)
01248 msecs -= stopWatch.elapsed();
01249 }
01250
01251 return d->waitForFinished(msecs);
01252 }
01253
01259 void QProcess::setProcessState(ProcessState state)
01260 {
01261 Q_D(QProcess);
01262 d->processState = state;
01263 }
01264
01299 void QProcess::setupChildProcess()
01300 {
01301 }
01302
01305 qint64 QProcess::readData(char *data, qint64 maxlen)
01306 {
01307 Q_D(QProcess);
01308 QRingBuffer *readBuffer = (d->processChannel == QProcess::StandardError)
01309 ? &d->errorReadBuffer
01310 : &d->outputReadBuffer;
01311
01312 if (maxlen == 1) {
01313 int c = readBuffer->getChar();
01314 if (c == -1) {
01315 #if defined QPROCESS_DEBUG
01316 qDebug("QProcess::readData(%p \"%s\", %d) == -1",
01317 data, qt_prettyDebug(data, 1, maxlen).constData(), 1);
01318 #endif
01319 return -1;
01320 }
01321 *data = (char) c;
01322 #if defined QPROCESS_DEBUG
01323 qDebug("QProcess::readData(%p \"%s\", %d) == 1",
01324 data, qt_prettyDebug(data, 1, maxlen).constData(), 1);
01325 #endif
01326 return 1;
01327 }
01328
01329 qint64 bytesToRead = qint64(qMin(readBuffer->size(), (int)maxlen));
01330 qint64 readSoFar = 0;
01331 while (readSoFar < bytesToRead) {
01332 const char *ptr = readBuffer->readPointer();
01333 int bytesToReadFromThisBlock = qMin<qint64>(bytesToRead - readSoFar,
01334 readBuffer->nextDataBlockSize());
01335 memcpy(data + readSoFar, ptr, bytesToReadFromThisBlock);
01336 readSoFar += bytesToReadFromThisBlock;
01337 readBuffer->free(bytesToReadFromThisBlock);
01338 }
01339
01340 #if defined QPROCESS_DEBUG
01341 qDebug("QProcess::readData(%p \"%s\", %lld) == %lld",
01342 data, qt_prettyDebug(data, readSoFar, 16).constData(), maxlen, readSoFar);
01343 #endif
01344 return readSoFar;
01345 }
01346
01349 qint64 QProcess::writeData(const char *data, qint64 len)
01350 {
01351 Q_D(QProcess);
01352
01353 if (d->stdinChannel.closed) {
01354 #if defined QPROCESS_DEBUG
01355 qDebug("QProcess::writeData(%p \"%s\", %lld) == 0 (write channel closing)",
01356 data, qt_prettyDebug(data, len, 16).constData(), len);
01357 #endif
01358 return 0;
01359 }
01360
01361 if (len == 1) {
01362 d->writeBuffer.putChar(*data);
01363 if (d->stdinChannel.notifier)
01364 d->stdinChannel.notifier->setEnabled(true);
01365 #if defined QPROCESS_DEBUG
01366 qDebug("QProcess::writeData(%p \"%s\", %lld) == 1 (written to buffer)",
01367 data, qt_prettyDebug(data, len, 16).constData(), len);
01368 #endif
01369 return 1;
01370 }
01371
01372 char *dest = d->writeBuffer.reserve(len);
01373 memcpy(dest, data, len);
01374 if (d->stdinChannel.notifier)
01375 d->stdinChannel.notifier->setEnabled(true);
01376 #if defined QPROCESS_DEBUG
01377 qDebug("QProcess::writeData(%p \"%s\", %lld) == %lld (written to buffer)",
01378 data, qt_prettyDebug(data, len, 16).constData(), len, len);
01379 #endif
01380 return len;
01381 }
01382
01390 QByteArray QProcess::readAllStandardOutput()
01391 {
01392 ProcessChannel tmp = readChannel();
01393 setReadChannel(StandardOutput);
01394 QByteArray data = readAll();
01395 setReadChannel(tmp);
01396 return data;
01397 }
01398
01406 QByteArray QProcess::readAllStandardError()
01407 {
01408 ProcessChannel tmp = readChannel();
01409 setReadChannel(StandardError);
01410 QByteArray data = readAll();
01411 setReadChannel(tmp);
01412 return data;
01413 }
01414
01431 void QProcess::start(const QString &program, const QStringList &arguments, OpenMode mode)
01432 {
01433 Q_D(QProcess);
01434 if (d->processState != NotRunning) {
01435 qWarning("QProcess::start: Process is already running");
01436 return;
01437 }
01438
01439 #if defined QPROCESS_DEBUG
01440 qDebug() << "QProcess::start(" << program << "," << arguments << "," << mode << ")";
01441 #endif
01442
01443 d->outputReadBuffer.clear();
01444 d->errorReadBuffer.clear();
01445
01446 if (d->stdinChannel.type != QProcessPrivate::Channel::Normal)
01447 mode &= ~WriteOnly;
01448 if (d->stdoutChannel.type != QProcessPrivate::Channel::Normal &&
01449 (d->stderrChannel.type != QProcessPrivate::Channel::Normal ||
01450 d->processChannelMode == MergedChannels))
01451 mode &= ~ReadOnly;
01452 if (mode == 0)
01453 mode = Unbuffered;
01454 setOpenMode(mode);
01455
01456 d->stdinChannel.closed = false;
01457 d->stdoutChannel.closed = false;
01458 d->stderrChannel.closed = false;
01459
01460 d->program = program;
01461 d->arguments = arguments;
01462
01463 d->exitCode = 0;
01464 d->exitStatus = NormalExit;
01465 d->processError = QProcess::UnknownError;
01466 d->errorString.clear();
01467 d->startProcess();
01468 }
01469
01470
01471 static QStringList parseCombinedArgString(const QString &program)
01472 {
01473 QStringList args;
01474 QString tmp;
01475 int quoteCount = 0;
01476 bool inQuote = false;
01477
01478
01479
01480
01481 for (int i = 0; i < program.size(); ++i) {
01482 if (program.at(i) == QLatin1Char('"')) {
01483 ++quoteCount;
01484 if (quoteCount == 3) {
01485
01486 quoteCount = 0;
01487 tmp += program.at(i);
01488 }
01489 continue;
01490 }
01491 if (quoteCount) {
01492 if (quoteCount == 1)
01493 inQuote = !inQuote;
01494 quoteCount = 0;
01495 }
01496 if (!inQuote && program.at(i).isSpace()) {
01497 if (!tmp.isEmpty()) {
01498 args += tmp;
01499 tmp.clear();
01500 }
01501 } else {
01502 tmp += program.at(i);
01503 }
01504 }
01505 if (!tmp.isEmpty())
01506 args += tmp;
01507
01508 return args;
01509 }
01510
01546 void QProcess::start(const QString &program, OpenMode mode)
01547 {
01548 QStringList args = parseCombinedArgString(program);
01549
01550 QString prog = args.first();
01551 args.removeFirst();
01552
01553 start(prog, args, mode);
01554 }
01555
01567 void QProcess::terminate()
01568 {
01569 Q_D(QProcess);
01570 d->terminateProcess();
01571 }
01572
01581 void QProcess::kill()
01582 {
01583 Q_D(QProcess);
01584 d->killProcess();
01585 }
01586
01590 int QProcess::exitCode() const
01591 {
01592 Q_D(const QProcess);
01593 return d->exitCode;
01594 }
01595
01605 QProcess::ExitStatus QProcess::exitStatus() const
01606 {
01607 Q_D(const QProcess);
01608 return d->exitStatus;
01609 }
01610
01622 int QProcess::execute(const QString &program, const QStringList &arguments)
01623 {
01624 QProcess process;
01625 process.setReadChannelMode(ForwardedChannels);
01626 process.start(program, arguments);
01627 process.waitForFinished(-1);
01628 return process.exitCode();
01629 }
01630
01638 int QProcess::execute(const QString &program)
01639 {
01640 QProcess process;
01641 process.setReadChannelMode(ForwardedChannels);
01642 process.start(program);
01643 process.waitForFinished(-1);
01644 return process.exitCode();
01645 }
01646
01659 bool QProcess::startDetached(const QString &program, const QStringList &arguments)
01660 {
01661 return QProcessPrivate::startDetached(program, arguments);
01662 }
01663
01674 bool QProcess::startDetached(const QString &program)
01675 {
01676 QStringList args = parseCombinedArgString(program);
01677
01678 QString prog = args.first();
01679 args.removeFirst();
01680
01681 return QProcessPrivate::startDetached(prog, args);
01682 }
01683
01684 #ifdef Q_OS_MAC
01685 # include <crt_externs.h>
01686 # define environ (*_NSGetEnviron())
01687 #elif !defined(Q_OS_WIN)
01688 extern char **environ;
01689 #endif
01690
01705 QStringList QProcess::systemEnvironment()
01706 {
01707 QStringList tmp;
01708 char *entry = 0;
01709 int count = 0;
01710 while ((entry = environ[count++]))
01711 tmp << QString::fromLocal8Bit(entry);
01712 return tmp;
01713 }
01714
01726 #include "moc_qprocess.cpp"
01727
01728 #endif // QT_NO_PROCESS