Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qprocess.cpp
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// Copyright (C) 2022 Intel Corporation.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
5//#define QPROCESS_DEBUG
6
7#include <qdebug.h>
8#include <qdir.h>
10
11#include "qprocess.h"
12#include "qprocess_p.h"
13
14#include <qbytearray.h>
15#include <qdeadlinetimer.h>
16#include <qcoreapplication.h>
17#include <qtimer.h>
18
19#if __has_include(<paths.h>)
20#include <paths.h>
21#endif
22
24
61{
63 result.reserve(vars.size());
64 for (auto it = vars.cbegin(), end = vars.cend(); it != end; ++it)
65 result << nameToString(it.key()) + u'=' + valueToString(it.value());
66 return result;
67}
68
70{
73 end = list.constEnd();
74 for ( ; it != end; ++it) {
75 const qsizetype pos = it->indexOf(u'=', 1);
76 if (pos < 1)
77 continue;
78
79 QString value = it->mid(pos + 1);
80 QString name = *it;
81 name.truncate(pos);
82 env.insert(name, value);
83 }
84 return env;
85}
86
88{
90 result.reserve(vars.size());
91 auto it = vars.constBegin();
92 const auto end = vars.constEnd();
93 for ( ; it != end; ++it)
94 result << nameToString(it.key());
95 return result;
96}
97
99{
100 auto it = other.vars.constBegin();
101 const auto end = other.vars.constEnd();
102 for ( ; it != end; ++it)
103 vars.insert(it.key(), it.value());
104
105#ifdef Q_OS_UNIX
106 const OrderedNameMapMutexLocker locker(this, &other);
107 auto nit = other.nameMap.constBegin();
108 const auto nend = other.nameMap.constEnd();
109 for ( ; nit != nend; ++nit)
110 nameMap.insert(nit.key(), nit.value());
111#endif
112}
113
132
152
157{
158}
159
164 : d(other.d)
165{
166}
167
173{
174 d = other.d;
175 return *this;
176}
177
204{
205 if (d == other.d)
206 return true;
207
208 return d && other.d && d->vars == other.d->vars;
209}
210
221{
222 // Needs no locking, as no hash nodes are accessed
223 return d ? d->vars.isEmpty() : true;
224}
225
234{
235 return !d;
236}
237
248{
249 if (d.constData())
250 d->vars.clear();
251 // Unix: Don't clear d->nameMap, as the environment is likely to be
252 // re-populated with the same keys again.
253}
254
263{
264 if (!d)
265 return false;
266 return d->vars.contains(d->prepareName(name));
267}
268
282{
283 // our re-impl of detach() detaches from null
284 d.detach(); // detach before prepareName()
286}
287
297{
298 if (d.constData()) {
300 p->vars.remove(p->prepareName(name));
301 }
302}
303
311QString QProcessEnvironment::value(const QString &name, const QString &defaultValue) const
312{
313 if (!d)
314 return defaultValue;
315
316 const auto it = d->vars.constFind(d->prepareName(name));
317 if (it == d->vars.constEnd())
318 return defaultValue;
319
320 return d->valueToString(it.value());
321}
322
337{
338 if (!d)
339 return QStringList();
340 return d->toList();
341}
342
353{
354 if (!d)
355 return QStringList();
356 return d->keys();
357}
358
367{
368 if (!e.d)
369 return;
370
371 // our re-impl of detach() detaches from null
372 d->insert(*e.d);
373}
374
375#if QT_CONFIG(process)
376
377void QProcessPrivate::Channel::clear()
378{
379 switch (type) {
380 case PipeSource:
381 Q_ASSERT(process);
382 process->stdinChannel.type = Normal;
383 process->stdinChannel.process = nullptr;
384 break;
385 case PipeSink:
386 Q_ASSERT(process);
387 process->stdoutChannel.type = Normal;
388 process->stdoutChannel.process = nullptr;
389 break;
390 default:
391 break;
392 }
393
394 type = Normal;
395 file.clear();
396 process = nullptr;
397}
398
958QProcessPrivate::QProcessPrivate()
959{
960 readBufferChunkSize = QRINGBUFFER_CHUNKSIZE;
961#ifndef Q_OS_WIN
962 writeBufferChunkSize = QRINGBUFFER_CHUNKSIZE;
963#endif
964}
965
969QProcessPrivate::~QProcessPrivate()
970{
971 if (stdinChannel.process)
972 stdinChannel.process->stdoutChannel.clear();
973 if (stdoutChannel.process)
974 stdoutChannel.process->stdinChannel.clear();
975}
976
980void QProcessPrivate::setError(QProcess::ProcessError error, const QString &description)
981{
982 processError = error;
983 if (description.isEmpty()) {
984 switch (error) {
985 case QProcess::FailedToStart:
986 errorString = QProcess::tr("Process failed to start");
987 break;
988 case QProcess::Crashed:
989 errorString = QProcess::tr("Process crashed");
990 break;
991 case QProcess::Timedout:
992 errorString = QProcess::tr("Process operation timed out");
993 break;
994 case QProcess::ReadError:
995 errorString = QProcess::tr("Error reading from process");
996 break;
997 case QProcess::WriteError:
998 errorString = QProcess::tr("Error writing to process");
999 break;
1000 case QProcess::UnknownError:
1002 break;
1003 }
1004 } else {
1005 errorString = description;
1006 }
1007}
1008
1012void QProcessPrivate::setErrorAndEmit(QProcess::ProcessError error, const QString &description)
1013{
1014 Q_Q(QProcess);
1015 Q_ASSERT(error != QProcess::UnknownError);
1016 setError(error, description);
1017 emit q->errorOccurred(QProcess::ProcessError(processError));
1018}
1019
1023bool QProcessPrivate::openChannels()
1024{
1025 // stdin channel.
1026 if (inputChannelMode == QProcess::ForwardedInputChannel) {
1027 if (stdinChannel.type != Channel::Normal)
1028 qWarning("QProcess::openChannels: Inconsistent stdin channel configuration");
1029 } else if (!openChannel(stdinChannel)) {
1030 return false;
1031 }
1032
1033 // stdout channel.
1034 if (processChannelMode == QProcess::ForwardedChannels
1035 || processChannelMode == QProcess::ForwardedOutputChannel) {
1036 if (stdoutChannel.type != Channel::Normal)
1037 qWarning("QProcess::openChannels: Inconsistent stdout channel configuration");
1038 } else if (!openChannel(stdoutChannel)) {
1039 return false;
1040 }
1041
1042 // stderr channel.
1043 if (processChannelMode == QProcess::ForwardedChannels
1044 || processChannelMode == QProcess::ForwardedErrorChannel
1045 || processChannelMode == QProcess::MergedChannels) {
1046 if (stderrChannel.type != Channel::Normal)
1047 qWarning("QProcess::openChannels: Inconsistent stderr channel configuration");
1048 } else if (!openChannel(stderrChannel)) {
1049 return false;
1050 }
1051
1052 return true;
1053}
1054
1058void QProcessPrivate::closeChannels()
1059{
1060 closeChannel(&stdoutChannel);
1061 closeChannel(&stderrChannel);
1062 closeChannel(&stdinChannel);
1063}
1064
1068bool QProcessPrivate::openChannelsForDetached()
1069{
1070 // stdin channel.
1071 bool needToOpen = (stdinChannel.type == Channel::Redirect
1072 || stdinChannel.type == Channel::PipeSink);
1073 if (stdinChannel.type != Channel::Normal
1074 && (!needToOpen
1075 || inputChannelMode == QProcess::ForwardedInputChannel)) {
1076 qWarning("QProcess::openChannelsForDetached: Inconsistent stdin channel configuration");
1077 }
1078 if (needToOpen && !openChannel(stdinChannel))
1079 return false;
1080
1081 // stdout channel.
1082 needToOpen = (stdoutChannel.type == Channel::Redirect
1083 || stdoutChannel.type == Channel::PipeSource);
1084 if (stdoutChannel.type != Channel::Normal
1085 && (!needToOpen
1086 || processChannelMode == QProcess::ForwardedChannels
1087 || processChannelMode == QProcess::ForwardedOutputChannel)) {
1088 qWarning("QProcess::openChannelsForDetached: Inconsistent stdout channel configuration");
1089 }
1090 if (needToOpen && !openChannel(stdoutChannel))
1091 return false;
1092
1093 // stderr channel.
1094 needToOpen = (stderrChannel.type == Channel::Redirect);
1095 if (stderrChannel.type != Channel::Normal
1096 && (!needToOpen
1097 || processChannelMode == QProcess::ForwardedChannels
1098 || processChannelMode == QProcess::ForwardedErrorChannel
1099 || processChannelMode == QProcess::MergedChannels)) {
1100 qWarning("QProcess::openChannelsForDetached: Inconsistent stderr channel configuration");
1101 }
1102 if (needToOpen && !openChannel(stderrChannel))
1103 return false;
1104
1105 return true;
1106}
1107
1112bool QProcessPrivate::tryReadFromChannel(Channel *channel)
1113{
1114 Q_Q(QProcess);
1115 if (channel->pipe[0] == INVALID_Q_PIPE)
1116 return false;
1117
1118 qint64 available = bytesAvailableInChannel(channel);
1119 if (available == 0)
1120 available = 1; // always try to read at least one byte
1121
1122 QProcess::ProcessChannel channelIdx = (channel == &stdoutChannel
1123 ? QProcess::StandardOutput
1124 : QProcess::StandardError);
1125 Q_ASSERT(readBuffers.size() > int(channelIdx));
1126 QRingBuffer &readBuffer = readBuffers[int(channelIdx)];
1127 char *ptr = readBuffer.reserve(available);
1128 qint64 readBytes = readFromChannel(channel, ptr, available);
1129 if (readBytes <= 0)
1130 readBuffer.chop(available);
1131 if (readBytes == -2) {
1132 // EWOULDBLOCK
1133 return false;
1134 }
1135 if (readBytes == -1) {
1136 setErrorAndEmit(QProcess::ReadError);
1137#if defined QPROCESS_DEBUG
1138 qDebug("QProcessPrivate::tryReadFromChannel(%d), failed to read from the process",
1139 int(channel - &stdinChannel));
1140#endif
1141 return false;
1142 }
1143 if (readBytes == 0) {
1144 // EOF
1145 closeChannel(channel);
1146#if defined QPROCESS_DEBUG
1147 qDebug("QProcessPrivate::tryReadFromChannel(%d), 0 bytes available",
1148 int(channel - &stdinChannel));
1149#endif
1150 return false;
1151 }
1152#if defined QPROCESS_DEBUG
1153 qDebug("QProcessPrivate::tryReadFromChannel(%d), read %lld bytes from the process' output",
1154 int(channel - &stdinChannel), readBytes);
1155#endif
1156
1157 if (channel->closed) {
1158 readBuffer.chop(readBytes);
1159 return false;
1160 }
1161
1162 readBuffer.chop(available - readBytes);
1163
1164 bool didRead = false;
1165 if (currentReadChannel == channelIdx) {
1166 didRead = true;
1167 if (!emittedReadyRead) {
1168 QScopedValueRollback<bool> guard(emittedReadyRead, true);
1169 emit q->readyRead();
1170 }
1171 }
1172 emit q->channelReadyRead(int(channelIdx));
1173 if (channelIdx == QProcess::StandardOutput)
1174 emit q->readyReadStandardOutput(QProcess::QPrivateSignal());
1175 else
1176 emit q->readyReadStandardError(QProcess::QPrivateSignal());
1177 return didRead;
1178}
1179
1183bool QProcessPrivate::_q_canReadStandardOutput()
1184{
1185 return tryReadFromChannel(&stdoutChannel);
1186}
1187
1191bool QProcessPrivate::_q_canReadStandardError()
1192{
1193 return tryReadFromChannel(&stderrChannel);
1194}
1195
1199void QProcessPrivate::_q_processDied()
1200{
1201#if defined QPROCESS_DEBUG
1202 qDebug("QProcessPrivate::_q_processDied()");
1203#endif
1204
1205 // in case there is data in the pipeline and this slot by chance
1206 // got called before the read notifications, call these functions
1207 // so the data is made available before we announce death.
1208#ifdef Q_OS_WIN
1209 drainOutputPipes();
1210#else
1211 _q_canReadStandardOutput();
1212 _q_canReadStandardError();
1213#endif
1214
1215 // Slots connected to signals emitted by the functions called above
1216 // might call waitFor*(), which would synchronously reap the process.
1217 // So check the state to avoid trying to reap a second time.
1218 if (processState != QProcess::NotRunning)
1219 processFinished();
1220}
1221
1225void QProcessPrivate::processFinished()
1226{
1227 Q_Q(QProcess);
1228#if defined QPROCESS_DEBUG
1229 qDebug("QProcessPrivate::processFinished()");
1230#endif
1231
1232#ifdef Q_OS_UNIX
1233 waitForDeadChild();
1234#else
1235 findExitCode();
1236#endif
1237
1238 cleanup();
1239
1240 if (exitStatus == QProcess::CrashExit)
1241 setErrorAndEmit(QProcess::Crashed);
1242
1243 // we received EOF now:
1244 emit q->readChannelFinished();
1245 // in the future:
1246 //emit q->standardOutputClosed();
1247 //emit q->standardErrorClosed();
1248
1249 emit q->finished(exitCode, QProcess::ExitStatus(exitStatus));
1250
1251#if defined QPROCESS_DEBUG
1252 qDebug("QProcessPrivate::processFinished(): process is dead");
1253#endif
1254}
1255
1259bool QProcessPrivate::_q_startupNotification()
1260{
1261 Q_Q(QProcess);
1262#if defined QPROCESS_DEBUG
1263 qDebug("QProcessPrivate::startupNotification()");
1264#endif
1265
1267 if (processStarted(&errorMessage)) {
1268 q->setProcessState(QProcess::Running);
1269 emit q->started(QProcess::QPrivateSignal());
1270 return true;
1271 }
1272
1273 q->setProcessState(QProcess::NotRunning);
1274 setErrorAndEmit(QProcess::FailedToStart, errorMessage);
1275#ifdef Q_OS_UNIX
1276 waitForDeadChild();
1277#endif
1278 cleanup();
1279 return false;
1280}
1281
1285void QProcessPrivate::closeWriteChannel()
1286{
1287#if defined QPROCESS_DEBUG
1288 qDebug("QProcessPrivate::closeWriteChannel()");
1289#endif
1290
1291 closeChannel(&stdinChannel);
1292}
1293
1297QProcess::QProcess(QObject *parent)
1298 : QIODevice(*new QProcessPrivate, parent)
1299{
1300#if defined QPROCESS_DEBUG
1301 qDebug("QProcess::QProcess(%p)", parent);
1302#endif
1303}
1304
1311QProcess::~QProcess()
1312{
1313 Q_D(QProcess);
1314 if (d->processState != NotRunning) {
1315 qWarning().nospace()
1316 << "QProcess: Destroyed while process (" << QDir::toNativeSeparators(program()) << ") is still running.";
1317 kill();
1319 }
1320 d->cleanup();
1321}
1322
1331QProcess::ProcessChannelMode QProcess::processChannelMode() const
1332{
1333 Q_D(const QProcess);
1334 return ProcessChannelMode(d->processChannelMode);
1335}
1336
1348void QProcess::setProcessChannelMode(ProcessChannelMode mode)
1349{
1350 Q_D(QProcess);
1351 d->processChannelMode = mode;
1352}
1353
1361QProcess::InputChannelMode QProcess::inputChannelMode() const
1362{
1363 Q_D(const QProcess);
1364 return InputChannelMode(d->inputChannelMode);
1365}
1366
1376void QProcess::setInputChannelMode(InputChannelMode mode)
1377{
1378 Q_D(QProcess);
1379 d->inputChannelMode = mode;
1380}
1381
1387QProcess::ProcessChannel QProcess::readChannel() const
1388{
1389 Q_D(const QProcess);
1390 return ProcessChannel(d->currentReadChannel);
1391}
1392
1401void QProcess::setReadChannel(ProcessChannel channel)
1402{
1404}
1405
1416void QProcess::closeReadChannel(ProcessChannel channel)
1417{
1418 Q_D(QProcess);
1419
1420 if (channel == StandardOutput)
1421 d->stdoutChannel.closed = true;
1422 else
1423 d->stderrChannel.closed = true;
1424}
1425
1444void QProcess::closeWriteChannel()
1445{
1446 Q_D(QProcess);
1447 d->stdinChannel.closed = true; // closing
1448 if (bytesToWrite() == 0)
1449 d->closeWriteChannel();
1450}
1451
1473void QProcess::setStandardInputFile(const QString &fileName)
1474{
1475 Q_D(QProcess);
1476 d->stdinChannel = fileName;
1477}
1478
1508void QProcess::setStandardOutputFile(const QString &fileName, OpenMode mode)
1509{
1510 Q_ASSERT(mode == Append || mode == Truncate);
1511 Q_D(QProcess);
1512
1513 d->stdoutChannel = fileName;
1514 d->stdoutChannel.append = mode == Append;
1515}
1516
1535void QProcess::setStandardErrorFile(const QString &fileName, OpenMode mode)
1536{
1537 Q_ASSERT(mode == Append || mode == Truncate);
1538 Q_D(QProcess);
1539
1540 d->stderrChannel = fileName;
1541 d->stderrChannel.append = mode == Append;
1542}
1543
1556void QProcess::setStandardOutputProcess(QProcess *destination)
1557{
1558 QProcessPrivate *dfrom = d_func();
1559 QProcessPrivate *dto = destination->d_func();
1560 dfrom->stdoutChannel.pipeTo(dto);
1561 dto->stdinChannel.pipeFrom(dfrom);
1562}
1563
1564#if defined(Q_OS_WIN) || defined(Q_QDOC)
1565
1575QString QProcess::nativeArguments() const
1576{
1577 Q_D(const QProcess);
1578 return d->nativeArguments;
1579}
1580
1598void QProcess::setNativeArguments(const QString &arguments)
1599{
1600 Q_D(QProcess);
1601 d->nativeArguments = arguments;
1602}
1603
1614QProcess::CreateProcessArgumentModifier QProcess::createProcessArgumentsModifier() const
1615{
1616 Q_D(const QProcess);
1617 return d->modifyCreateProcessArgs;
1618}
1619
1631void QProcess::setCreateProcessArgumentsModifier(CreateProcessArgumentModifier modifier)
1632{
1633 Q_D(QProcess);
1634 d->modifyCreateProcessArgs = modifier;
1635}
1636
1637#endif
1638
1639#if defined(Q_OS_UNIX) || defined(Q_QDOC)
1650std::function<void(void)> QProcess::childProcessModifier() const
1651{
1652 Q_D(const QProcess);
1653 return d->unixExtras ? d->unixExtras->childProcessModifier : std::function<void(void)>();
1654}
1655
1703void QProcess::setChildProcessModifier(const std::function<void(void)> &modifier)
1704{
1705 Q_D(QProcess);
1706 if (!d->unixExtras)
1707 d->unixExtras.reset(new QProcessPrivate::UnixExtras);
1708 d->unixExtras->childProcessModifier = modifier;
1709}
1710
1761auto QProcess::unixProcessParameters() const noexcept -> UnixProcessParameters
1762{
1763 Q_D(const QProcess);
1764 return d->unixExtras ? d->unixExtras->processParameters : UnixProcessParameters{};
1765}
1766
1785void QProcess::setUnixProcessParameters(const UnixProcessParameters &params)
1786{
1787 Q_D(QProcess);
1788 if (!d->unixExtras)
1789 d->unixExtras.reset(new QProcessPrivate::UnixExtras);
1790 d->unixExtras->processParameters = params;
1791}
1792
1804void QProcess::setUnixProcessParameters(UnixProcessFlags flagsOnly)
1805{
1806 Q_D(QProcess);
1807 if (!d->unixExtras)
1808 d->unixExtras.reset(new QProcessPrivate::UnixExtras);
1809 d->unixExtras->processParameters = { flagsOnly };
1810}
1811#endif
1812
1822QString QProcess::workingDirectory() const
1823{
1824 Q_D(const QProcess);
1825 return d->workingDirectory;
1826}
1827
1835void QProcess::setWorkingDirectory(const QString &dir)
1836{
1837 Q_D(QProcess);
1838 d->workingDirectory = dir;
1839}
1840
1847qint64 QProcess::processId() const
1848{
1849 Q_D(const QProcess);
1850#ifdef Q_OS_WIN
1851 return d->pid ? d->pid->dwProcessId : 0;
1852#else
1853 return d->pid;
1854#endif
1855}
1856
1862void QProcess::close()
1863{
1864 Q_D(QProcess);
1865 emit aboutToClose();
1866 while (waitForBytesWritten(-1))
1867 ;
1868 kill();
1869 waitForFinished(-1);
1870 d->setWriteChannelCount(0);
1872}
1873
1876bool QProcess::isSequential() const
1877{
1878 return true;
1879}
1880
1883qint64 QProcess::bytesToWrite() const
1884{
1885#ifdef Q_OS_WIN
1886 return d_func()->pipeWriterBytesToWrite();
1887#else
1888 return QIODevice::bytesToWrite();
1889#endif
1890}
1891
1897QProcess::ProcessError QProcess::error() const
1898{
1899 Q_D(const QProcess);
1900 return ProcessError(d->processError);
1901}
1902
1908QProcess::ProcessState QProcess::state() const
1909{
1910 Q_D(const QProcess);
1911 return ProcessState(d->processState);
1912}
1913
1928void QProcess::setEnvironment(const QStringList &environment)
1929{
1930 setProcessEnvironment(QProcessEnvironmentPrivate::fromList(environment));
1931}
1932
1942QStringList QProcess::environment() const
1943{
1944 Q_D(const QProcess);
1945 return d->environment.toStringList();
1946}
1947
1961void QProcess::setProcessEnvironment(const QProcessEnvironment &environment)
1962{
1963 Q_D(QProcess);
1964 d->environment = environment;
1965}
1966
1976QProcessEnvironment QProcess::processEnvironment() const
1977{
1978 Q_D(const QProcess);
1979 return d->environment;
1980}
1981
2004bool QProcess::waitForStarted(int msecs)
2005{
2006 Q_D(QProcess);
2007 if (d->processState == QProcess::Starting)
2008 return d->waitForStarted(QDeadlineTimer(msecs));
2009
2010 return d->processState == QProcess::Running;
2011}
2012
2015bool QProcess::waitForReadyRead(int msecs)
2016{
2017 Q_D(QProcess);
2018
2019 if (d->processState == QProcess::NotRunning)
2020 return false;
2021 if (d->currentReadChannel == QProcess::StandardOutput && d->stdoutChannel.closed)
2022 return false;
2023 if (d->currentReadChannel == QProcess::StandardError && d->stderrChannel.closed)
2024 return false;
2025
2026 QDeadlineTimer deadline(msecs);
2027 if (d->processState == QProcess::Starting) {
2028 bool started = d->waitForStarted(deadline);
2029 if (!started)
2030 return false;
2031 }
2032
2033 return d->waitForReadyRead(deadline);
2034}
2035
2038bool QProcess::waitForBytesWritten(int msecs)
2039{
2040 Q_D(QProcess);
2041 if (d->processState == QProcess::NotRunning)
2042 return false;
2043
2044 QDeadlineTimer deadline(msecs);
2045 if (d->processState == QProcess::Starting) {
2046 bool started = d->waitForStarted(deadline);
2047 if (!started)
2048 return false;
2049 }
2050
2051 return d->waitForBytesWritten(deadline);
2052}
2053
2073bool QProcess::waitForFinished(int msecs)
2074{
2075 Q_D(QProcess);
2076 if (d->processState == QProcess::NotRunning)
2077 return false;
2078
2079 QDeadlineTimer deadline(msecs);
2080 if (d->processState == QProcess::Starting) {
2081 bool started = d->waitForStarted(deadline);
2082 if (!started)
2083 return false;
2084 }
2085
2086 return d->waitForFinished(deadline);
2087}
2088
2094void QProcess::setProcessState(ProcessState state)
2095{
2096 Q_D(QProcess);
2097 if (d->processState == state)
2098 return;
2099 d->processState = state;
2100 emit stateChanged(state, QPrivateSignal());
2101}
2102
2103#if QT_VERSION < QT_VERSION_CHECK(7,0,0)
2107auto QProcess::setupChildProcess() -> Use_setChildProcessModifier_Instead
2108{
2109 Q_UNREACHABLE_RETURN({});
2110}
2111#endif
2112
2115qint64 QProcess::readData(char *data, qint64 maxlen)
2116{
2117 Q_D(QProcess);
2118 Q_UNUSED(data);
2119 if (!maxlen)
2120 return 0;
2121 if (d->processState == QProcess::NotRunning)
2122 return -1; // EOF
2123 return 0;
2124}
2125
2133QByteArray QProcess::readAllStandardOutput()
2134{
2135 ProcessChannel tmp = readChannel();
2136 setReadChannel(StandardOutput);
2137 QByteArray data = readAll();
2138 setReadChannel(tmp);
2139 return data;
2140}
2141
2149QByteArray QProcess::readAllStandardError()
2150{
2151 Q_D(QProcess);
2153 if (d->processChannelMode == MergedChannels) {
2154 qWarning("QProcess::readAllStandardError: Called with MergedChannels");
2155 } else {
2156 ProcessChannel tmp = readChannel();
2157 setReadChannel(StandardError);
2158 data = readAll();
2159 setReadChannel(tmp);
2160 }
2161 return data;
2162}
2163
2195void QProcess::start(const QString &program, const QStringList &arguments, OpenMode mode)
2196{
2197 Q_D(QProcess);
2198 if (d->processState != NotRunning) {
2199 qWarning("QProcess::start: Process is already running");
2200 return;
2201 }
2202 if (program.isEmpty()) {
2203 d->setErrorAndEmit(QProcess::FailedToStart, tr("No program defined"));
2204 return;
2205 }
2206
2207 d->program = program;
2208 d->arguments = arguments;
2209
2210 d->start(mode);
2211}
2212
2222void QProcess::start(OpenMode mode)
2223{
2224 Q_D(QProcess);
2225 if (d->processState != NotRunning) {
2226 qWarning("QProcess::start: Process is already running");
2227 return;
2228 }
2229 if (d->program.isEmpty()) {
2230 d->setErrorAndEmit(QProcess::FailedToStart, tr("No program defined"));
2231 return;
2232 }
2233
2234 d->start(mode);
2235}
2236
2271void QProcess::startCommand(const QString &command, OpenMode mode)
2272{
2273 QStringList args = splitCommand(command);
2274 const QString program = args.takeFirst();
2276}
2277
2325bool QProcess::startDetached(qint64 *pid)
2326{
2327 Q_D(QProcess);
2328 if (d->processState != NotRunning) {
2329 qWarning("QProcess::startDetached: Process is already running");
2330 return false;
2331 }
2332 if (d->program.isEmpty()) {
2333 d->setErrorAndEmit(QProcess::FailedToStart, tr("No program defined"));
2334 return false;
2335 }
2336 return d->startDetached(pid);
2337}
2338
2350bool QProcess::open(OpenMode mode)
2351{
2352 Q_D(QProcess);
2353 if (d->processState != NotRunning) {
2354 qWarning("QProcess::start: Process is already running");
2355 return false;
2356 }
2357 if (d->program.isEmpty()) {
2358 qWarning("QProcess::start: program not set");
2359 return false;
2360 }
2361
2362 d->start(mode);
2363 return true;
2364}
2365
2366void QProcessPrivate::start(QIODevice::OpenMode mode)
2367{
2368 Q_Q(QProcess);
2369#if defined QPROCESS_DEBUG
2370 qDebug() << "QProcess::start(" << program << ',' << arguments << ',' << mode << ')';
2371#endif
2372
2373 if (stdinChannel.type != QProcessPrivate::Channel::Normal)
2374 mode &= ~QIODevice::WriteOnly; // not open for writing
2375 if (stdoutChannel.type != QProcessPrivate::Channel::Normal &&
2376 (stderrChannel.type != QProcessPrivate::Channel::Normal ||
2377 processChannelMode == QProcess::MergedChannels))
2378 mode &= ~QIODevice::ReadOnly; // not open for reading
2379 if (mode == 0)
2381 if ((mode & QIODevice::ReadOnly) == 0) {
2382 if (stdoutChannel.type == QProcessPrivate::Channel::Normal)
2383 q->setStandardOutputFile(q->nullDevice());
2384 if (stderrChannel.type == QProcessPrivate::Channel::Normal
2385 && processChannelMode != QProcess::MergedChannels)
2386 q->setStandardErrorFile(q->nullDevice());
2387 }
2388
2389 q->QIODevice::open(mode);
2390
2391 if (q->isReadable() && processChannelMode != QProcess::MergedChannels)
2392 setReadChannelCount(2);
2393
2394 stdinChannel.closed = false;
2395 stdoutChannel.closed = false;
2396 stderrChannel.closed = false;
2397
2398 exitCode = 0;
2399 exitStatus = QProcess::NormalExit;
2400 processError = QProcess::UnknownError;
2402 startProcess();
2403}
2404
2414QStringList QProcess::splitCommand(QStringView command)
2415{
2417 QString tmp;
2418 int quoteCount = 0;
2419 bool inQuote = false;
2420
2421 // handle quoting. tokens can be surrounded by double quotes
2422 // "hello world". three consecutive double quotes represent
2423 // the quote character itself.
2424 for (int i = 0; i < command.size(); ++i) {
2425 if (command.at(i) == u'"') {
2426 ++quoteCount;
2427 if (quoteCount == 3) {
2428 // third consecutive quote
2429 quoteCount = 0;
2430 tmp += command.at(i);
2431 }
2432 continue;
2433 }
2434 if (quoteCount) {
2435 if (quoteCount == 1)
2436 inQuote = !inQuote;
2437 quoteCount = 0;
2438 }
2439 if (!inQuote && command.at(i).isSpace()) {
2440 if (!tmp.isEmpty()) {
2441 args += tmp;
2442 tmp.clear();
2443 }
2444 } else {
2445 tmp += command.at(i);
2446 }
2447 }
2448 if (!tmp.isEmpty())
2449 args += tmp;
2450
2451 return args;
2452}
2453
2461QString QProcess::program() const
2462{
2463 Q_D(const QProcess);
2464 return d->program;
2465}
2466
2480void QProcess::setProgram(const QString &program)
2481{
2482 Q_D(QProcess);
2483 if (d->processState != NotRunning) {
2484 qWarning("QProcess::setProgram: Process is already running");
2485 return;
2486 }
2487 d->program = program;
2488}
2489
2497QStringList QProcess::arguments() const
2498{
2499 Q_D(const QProcess);
2500 return d->arguments;
2501}
2502
2511void QProcess::setArguments(const QStringList &arguments)
2512{
2513 Q_D(QProcess);
2514 if (d->processState != NotRunning) {
2515 qWarning("QProcess::setProgram: Process is already running");
2516 return;
2517 }
2518 d->arguments = arguments;
2519}
2520
2537void QProcess::terminate()
2538{
2539 Q_D(QProcess);
2540 d->terminateProcess();
2541}
2542
2551void QProcess::kill()
2552{
2553 Q_D(QProcess);
2554 d->killProcess();
2555}
2556
2562int QProcess::exitCode() const
2563{
2564 Q_D(const QProcess);
2565 return d->exitCode;
2566}
2567
2577QProcess::ExitStatus QProcess::exitStatus() const
2578{
2579 Q_D(const QProcess);
2580 return ExitStatus(d->exitStatus);
2581}
2582
2600int QProcess::execute(const QString &program, const QStringList &arguments)
2601{
2602 QProcess process;
2603 process.setProcessChannelMode(ForwardedChannels);
2604 process.start(program, arguments);
2605 if (!process.waitForFinished(-1) || process.error() == FailedToStart)
2606 return -2;
2607 return process.exitStatus() == QProcess::NormalExit ? process.exitCode() : -1;
2608}
2609
2629bool QProcess::startDetached(const QString &program,
2630 const QStringList &arguments,
2631 const QString &workingDirectory,
2632 qint64 *pid)
2633{
2634 QProcess process;
2635 process.setProgram(program);
2636 process.setArguments(arguments);
2637 process.setWorkingDirectory(workingDirectory);
2638 return process.startDetached(pid);
2639}
2640
2660QStringList QProcess::systemEnvironment()
2661{
2663}
2664
2694QString QProcess::nullDevice()
2695{
2696#ifdef Q_OS_WIN
2697 return QStringLiteral("\\\\.\\NUL");
2698#elif defined(_PATH_DEVNULL)
2699 return QStringLiteral(_PATH_DEVNULL);
2700#else
2701 return QStringLiteral("/dev/null");
2702#endif
2703}
2704
2705#endif // QT_CONFIG(process)
2706
2708
2709#include "moc_qprocess.cpp"
IOBluetoothL2CAPChannel * channel
\inmodule QtCore
Definition qbytearray.h:57
constexpr bool isSpace() const noexcept
Returns true if the character is a separator character (Separator_* categories or certain code points...
Definition qchar.h:466
\inmodule QtCore
static QString toNativeSeparators(const QString &pathName)
Definition qdir.cpp:929
\inmodule QtCore \reentrant
Definition qiodevice.h:34
virtual qint64 bytesToWrite() const
For buffered devices, this function returns the number of bytes waiting to be written.
virtual void close()
First emits aboutToClose(), then closes the device and sets its OpenMode to NotOpen.
void setCurrentReadChannel(int channel)
value_type takeFirst()
Definition qlist.h:549
const_iterator constBegin() const noexcept
Definition qlist.h:615
const_iterator constEnd() const noexcept
Definition qlist.h:616
const_iterator ConstIterator
Definition qlist.h:251
iterator insert(const Key &key, const T &value)
Definition qmap.h:687
bool contains(const Key &key) const
Definition qmap.h:340
const_iterator cend() const
Definition qmap.h:604
size_type remove(const Key &key)
Definition qmap.h:299
const_iterator cbegin() const
Definition qmap.h:600
const_iterator constFind(const Key &key) const
Definition qmap.h:654
void clear()
Definition qmap.h:288
bool isEmpty() const
Definition qmap.h:268
const_iterator constBegin() const
Definition qmap.h:599
size_type size() const
Definition qmap.h:266
const_iterator constEnd() const
Definition qmap.h:603
\inmodule QtCore
Definition qobject.h:90
Value prepareValue(const QString &value) const
Definition qprocess_p.h:143
static QProcessEnvironment fromList(const QStringList &list)
Definition qprocess.cpp:69
Key prepareName(const QString &name) const
Definition qprocess_p.h:126
QString valueToString(const Value &value) const
Definition qprocess_p.h:144
void insert(const QProcessEnvironmentPrivate &other)
Definition qprocess.cpp:98
QString nameToString(const Key &name) const
Definition qprocess_p.h:134
QStringList keys() const
Definition qprocess.cpp:87
QStringList toList() const
Definition qprocess.cpp:60
\inmodule QtCore
Definition qprocess.h:31
QProcessEnvironment & operator=(const QProcessEnvironment &other)
Copies the contents of the other QProcessEnvironment object into this one.
Definition qprocess.cpp:172
QString value(const QString &name, const QString &defaultValue=QString()) const
Searches this QProcessEnvironment object for a variable identified by name and returns its value.
Definition qprocess.cpp:311
void remove(const QString &name)
Removes the environment variable identified by name from this QProcessEnvironment object.
Definition qprocess.cpp:296
QStringList toStringList() const
Converts this QProcessEnvironment object into a list of strings, one for each environment variable th...
Definition qprocess.cpp:336
void insert(const QString &name, const QString &value)
Inserts the environment variable of name name and contents value into this QProcessEnvironment object...
Definition qprocess.cpp:281
bool isEmpty() const
Returns true if this QProcessEnvironment object is empty: that is there are no key=value pairs set.
Definition qprocess.cpp:220
bool inheritsFromParent() const
Returns true if this QProcessEnvironment was constructed using {QProcessEnvironment::InheritFromParen...
Definition qprocess.cpp:233
bool contains(const QString &name) const
Returns true if the environment variable of name name is found in this QProcessEnvironment object.
Definition qprocess.cpp:262
QProcessEnvironment()
Creates a new QProcessEnvironment object.
Definition qprocess.cpp:131
QStringList keys() const
Definition qprocess.cpp:352
void clear()
Removes all key=value pairs from this QProcessEnvironment object, making it empty.
Definition qprocess.cpp:247
Initialization
This enum contains a token that is used to disambiguate constructors.
Definition qprocess.h:33
bool operator==(const QProcessEnvironment &other) const
Returns true if this and the other QProcessEnvironment objects are equal.
Definition qprocess.cpp:203
~QProcessEnvironment()
Frees the resources associated with this QProcessEnvironment object.
Definition qprocess.cpp:156
static QProcessEnvironment systemEnvironment()
void detach()
If the shared data object's reference count is greater than 1, this function creates a deep copy of t...
Definition qshareddata.h:40
const T * constData() const noexcept
Returns a const pointer to the shared data object.
Definition qshareddata.h:51
T * data()
Returns a pointer to the shared data object.
Definition qshareddata.h:47
\inmodule QtCore
\inmodule QtCore
Definition qstringview.h:76
constexpr qsizetype size() const noexcept
Returns the size of this string view, in UTF-16 code units (that is, surrogate pairs count as two for...
constexpr QChar at(qsizetype n) const noexcept
Returns the character at position n in this string view.
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
void clear()
Clears the contents of the string and makes it null.
Definition qstring.h:1107
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:1083
double e
QSet< QString >::iterator it
QList< QVariant > arguments
else opt state
[0]
Combined button and popup list for selecting options.
Q_MULTIMEDIA_EXPORT QString errorString(HRESULT hr)
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char * destination
DBusConnection const char DBusError * error
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define qDebug
[1]
Definition qlogging.h:160
#define qWarning
Definition qlogging.h:162
static ControlElement< T > * ptr(QWidget *widget)
GLenum mode
GLuint GLuint end
GLenum type
GLuint program
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLuint start
GLuint name
void ** params
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
GLuint64EXT * result
[6]
GLfloat GLfloat p
[1]
GLbitfield GLuint readBuffer
#define INVALID_Q_PIPE
Definition qprocess_p.h:39
static void setError(QJsonObject *response, const QString &msg)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define QRINGBUFFER_CHUNKSIZE
#define QStringLiteral(str)
void startProcess()
Definition main.cpp:6
#define tr(X)
#define emit
#define Q_UNUSED(x)
ptrdiff_t qsizetype
Definition qtypes.h:70
long long qint64
Definition qtypes.h:55
static QString errorMessage(QUrlPrivate::ErrorCode errorCode, const QString &errorSource, qsizetype errorPosition)
Definition qurl.cpp:3503
QList< int > list
[14]
future waitForFinished()
QFile file
[0]
QDeadlineTimer deadline(30s)
QSharedPointer< T > other(t)
[5]
QString dir
[11]
QJSValueList args
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent