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> |
9 | #include <qscopedvaluerollback.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 | |
23 | QT_BEGIN_NAMESPACE |
24 | |
25 | /*! |
26 | \class QProcessEnvironment |
27 | \inmodule QtCore |
28 | |
29 | \brief The QProcessEnvironment class holds the environment variables that |
30 | can be passed to a program. |
31 | |
32 | \ingroup io |
33 | \ingroup misc |
34 | \ingroup shared |
35 | \reentrant |
36 | \since 4.6 |
37 | |
38 | A process's environment is composed of a set of key=value pairs known as |
39 | environment variables. The QProcessEnvironment class wraps that concept |
40 | and allows easy manipulation of those variables. It's meant to be used |
41 | along with QProcess, to set the environment for child processes. It |
42 | cannot be used to change the current process's environment. |
43 | |
44 | The environment of the calling process can be obtained using |
45 | QProcessEnvironment::systemEnvironment(). |
46 | |
47 | On Unix systems, the variable names are case-sensitive. Note that the |
48 | Unix environment allows both variable names and contents to contain arbitrary |
49 | binary data (except for the NUL character). QProcessEnvironment will preserve |
50 | such variables, but does not support manipulating variables whose names or |
51 | values cannot be encoded by the current locale settings (see |
52 | QString::toLocal8Bit). |
53 | |
54 | On Windows, the variable names are case-insensitive, but case-preserving. |
55 | QProcessEnvironment behaves accordingly. |
56 | |
57 | \sa QProcess, QProcess::systemEnvironment(), QProcess::setProcessEnvironment() |
58 | */ |
59 | |
60 | QStringList QProcessEnvironmentPrivate::toList() const |
61 | { |
62 | QStringList result; |
63 | result.reserve(asize: vars.size()); |
64 | for (auto it = vars.cbegin(), end = vars.cend(); it != end; ++it) |
65 | result << nameToString(name: it.key()) + u'=' + valueToString(value: it.value()); |
66 | return result; |
67 | } |
68 | |
69 | QProcessEnvironment QProcessEnvironmentPrivate::fromList(const QStringList &list) |
70 | { |
71 | QProcessEnvironment env; |
72 | QStringList::ConstIterator it = list.constBegin(), |
73 | end = list.constEnd(); |
74 | for ( ; it != end; ++it) { |
75 | const qsizetype pos = it->indexOf(c: u'=', from: 1); |
76 | if (pos < 1) |
77 | continue; |
78 | |
79 | QString value = it->mid(position: pos + 1); |
80 | QString name = *it; |
81 | name.truncate(pos); |
82 | env.insert(name, value); |
83 | } |
84 | return env; |
85 | } |
86 | |
87 | QStringList QProcessEnvironmentPrivate::keys() const |
88 | { |
89 | QStringList result; |
90 | result.reserve(asize: vars.size()); |
91 | auto it = vars.constBegin(); |
92 | const auto end = vars.constEnd(); |
93 | for ( ; it != end; ++it) |
94 | result << nameToString(name: it.key()); |
95 | return result; |
96 | } |
97 | |
98 | void QProcessEnvironmentPrivate::insert(const QProcessEnvironmentPrivate &other) |
99 | { |
100 | auto it = other.vars.constBegin(); |
101 | const auto end = other.vars.constEnd(); |
102 | for ( ; it != end; ++it) |
103 | vars.insert(key: it.key(), value: 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(key: nit.key(), value: nit.value()); |
111 | #endif |
112 | } |
113 | |
114 | /*! |
115 | \enum QProcessEnvironment::Initialization |
116 | |
117 | This enum contains a token that is used to disambiguate constructors. |
118 | |
119 | \value InheritFromParent A QProcessEnvironment will be created that, when |
120 | set on a QProcess, causes it to inherit variables from its parent. |
121 | |
122 | \since 6.3 |
123 | */ |
124 | |
125 | /*! |
126 | Creates a new QProcessEnvironment object. This constructor creates an |
127 | empty environment. If set on a QProcess, this will cause the current |
128 | environment variables to be removed (except for PATH and SystemRoot |
129 | on Windows). |
130 | */ |
131 | QProcessEnvironment::QProcessEnvironment() : d(new QProcessEnvironmentPrivate) { } |
132 | |
133 | /*! |
134 | Creates an object that when set on QProcess will cause it to be executed with |
135 | environment variables inherited from its parent process. |
136 | |
137 | \note The created object does not store any environment variables by itself, |
138 | it just indicates to QProcess to arrange for inheriting the environment at the |
139 | time when the new process is started. Adding any environment variables to |
140 | the created object will disable inheritance of the environment and result in |
141 | an environment containing only the added environment variables. |
142 | |
143 | If a modified version of the parent environment is wanted, start with the |
144 | return value of \c systemEnvironment() and modify that (but note that changes to |
145 | the parent process's environment after that is created won't be reflected |
146 | in the modified environment). |
147 | |
148 | \sa inheritsFromParent(), systemEnvironment() |
149 | \since 6.3 |
150 | */ |
151 | QProcessEnvironment::QProcessEnvironment(QProcessEnvironment::Initialization) noexcept { } |
152 | |
153 | /*! |
154 | Frees the resources associated with this QProcessEnvironment object. |
155 | */ |
156 | QProcessEnvironment::~QProcessEnvironment() |
157 | { |
158 | } |
159 | |
160 | /*! |
161 | Creates a QProcessEnvironment object that is a copy of \a other. |
162 | */ |
163 | QProcessEnvironment::QProcessEnvironment(const QProcessEnvironment &other) |
164 | : d(other.d) |
165 | { |
166 | } |
167 | |
168 | /*! |
169 | Copies the contents of the \a other QProcessEnvironment object into this |
170 | one. |
171 | */ |
172 | QProcessEnvironment &QProcessEnvironment::operator=(const QProcessEnvironment &other) |
173 | { |
174 | d = other.d; |
175 | return *this; |
176 | } |
177 | |
178 | /*! |
179 | \fn void QProcessEnvironment::swap(QProcessEnvironment &other) |
180 | \since 5.0 |
181 | |
182 | Swaps this process environment instance with \a other. This |
183 | function is very fast and never fails. |
184 | */ |
185 | |
186 | /*! |
187 | \fn bool QProcessEnvironment::operator !=(const QProcessEnvironment &other) const |
188 | |
189 | Returns \c true if this and the \a other QProcessEnvironment objects are different. |
190 | |
191 | \sa operator==() |
192 | */ |
193 | |
194 | /*! |
195 | Returns \c true if this and the \a other QProcessEnvironment objects are equal. |
196 | |
197 | Two QProcessEnvironment objects are considered equal if they have the same |
198 | set of key=value pairs. The comparison of keys is done case-sensitive on |
199 | platforms where the environment is case-sensitive. |
200 | |
201 | \sa operator!=(), contains() |
202 | */ |
203 | bool QProcessEnvironment::operator==(const QProcessEnvironment &other) const |
204 | { |
205 | if (d == other.d) |
206 | return true; |
207 | |
208 | return d && other.d && d->vars == other.d->vars; |
209 | } |
210 | |
211 | /*! |
212 | Returns \c true if this QProcessEnvironment object is empty: that is |
213 | there are no key=value pairs set. |
214 | |
215 | This method also returns \c true for objects that were constructed using |
216 | \c{QProcessEnvironment::InheritFromParent}. |
217 | |
218 | \sa clear(), systemEnvironment(), insert(), inheritsFromParent() |
219 | */ |
220 | bool QProcessEnvironment::isEmpty() const |
221 | { |
222 | // Needs no locking, as no hash nodes are accessed |
223 | return d ? d->vars.isEmpty() : true; |
224 | } |
225 | |
226 | /*! |
227 | Returns \c true if this QProcessEnvironment was constructed using |
228 | \c{QProcessEnvironment::InheritFromParent}. |
229 | |
230 | \since 6.3 |
231 | \sa isEmpty() |
232 | */ |
233 | bool QProcessEnvironment::inheritsFromParent() const |
234 | { |
235 | return !d; |
236 | } |
237 | |
238 | /*! |
239 | Removes all key=value pairs from this QProcessEnvironment object, making |
240 | it empty. |
241 | |
242 | If the environment was constructed using \c{QProcessEnvironment::InheritFromParent} |
243 | it remains unchanged. |
244 | |
245 | \sa isEmpty(), systemEnvironment() |
246 | */ |
247 | void QProcessEnvironment::clear() |
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 | |
255 | /*! |
256 | Returns \c true if the environment variable of name \a name is found in |
257 | this QProcessEnvironment object. |
258 | |
259 | |
260 | \sa insert(), value() |
261 | */ |
262 | bool QProcessEnvironment::contains(const QString &name) const |
263 | { |
264 | if (!d) |
265 | return false; |
266 | return d->vars.contains(key: d->prepareName(name)); |
267 | } |
268 | |
269 | /*! |
270 | Inserts the environment variable of name \a name and contents \a value |
271 | into this QProcessEnvironment object. If that variable already existed, |
272 | it is replaced by the new value. |
273 | |
274 | On most systems, inserting a variable with no contents will have the |
275 | same effect for applications as if the variable had not been set at all. |
276 | However, to guarantee that there are no incompatibilities, to remove a |
277 | variable, please use the remove() function. |
278 | |
279 | \sa contains(), remove(), value() |
280 | */ |
281 | void QProcessEnvironment::insert(const QString &name, const QString &value) |
282 | { |
283 | // our re-impl of detach() detaches from null |
284 | d.detach(); // detach before prepareName() |
285 | d->vars.insert(key: d->prepareName(name), value: d->prepareValue(value)); |
286 | } |
287 | |
288 | /*! |
289 | Removes the environment variable identified by \a name from this |
290 | QProcessEnvironment object. If that variable did not exist before, |
291 | nothing happens. |
292 | |
293 | |
294 | \sa contains(), insert(), value() |
295 | */ |
296 | void QProcessEnvironment::remove(const QString &name) |
297 | { |
298 | if (d.constData()) { |
299 | QProcessEnvironmentPrivate *p = d.data(); |
300 | p->vars.remove(key: p->prepareName(name)); |
301 | } |
302 | } |
303 | |
304 | /*! |
305 | Searches this QProcessEnvironment object for a variable identified by |
306 | \a name and returns its value. If the variable is not found in this object, |
307 | then \a defaultValue is returned instead. |
308 | |
309 | \sa contains(), insert(), remove() |
310 | */ |
311 | QString QProcessEnvironment::value(const QString &name, const QString &defaultValue) const |
312 | { |
313 | if (!d) |
314 | return defaultValue; |
315 | |
316 | const auto it = d->vars.constFind(key: d->prepareName(name)); |
317 | if (it == d->vars.constEnd()) |
318 | return defaultValue; |
319 | |
320 | return d->valueToString(value: it.value()); |
321 | } |
322 | |
323 | /*! |
324 | Converts this QProcessEnvironment object into a list of strings, one for |
325 | each environment variable that is set. The environment variable's name |
326 | and its value are separated by an equal character ('='). |
327 | |
328 | The QStringList contents returned by this function are suitable for |
329 | presentation. |
330 | Use with the QProcess::setEnvironment function is not recommended due to |
331 | potential encoding problems under Unix, and worse performance. |
332 | |
333 | \sa systemEnvironment(), QProcess::systemEnvironment(), |
334 | QProcess::setProcessEnvironment() |
335 | */ |
336 | QStringList QProcessEnvironment::toStringList() const |
337 | { |
338 | if (!d) |
339 | return QStringList(); |
340 | return d->toList(); |
341 | } |
342 | |
343 | /*! |
344 | \since 4.8 |
345 | |
346 | Returns a list containing all the variable names in this QProcessEnvironment |
347 | object. |
348 | |
349 | The returned list is empty for objects constructed using |
350 | \c{QProcessEnvironment::InheritFromParent}. |
351 | */ |
352 | QStringList QProcessEnvironment::keys() const |
353 | { |
354 | if (!d) |
355 | return QStringList(); |
356 | return d->keys(); |
357 | } |
358 | |
359 | /*! |
360 | \overload |
361 | \since 4.8 |
362 | |
363 | Inserts the contents of \a e in this QProcessEnvironment object. Variables in |
364 | this object that also exist in \a e will be overwritten. |
365 | */ |
366 | void QProcessEnvironment::insert(const QProcessEnvironment &e) |
367 | { |
368 | if (!e.d) |
369 | return; |
370 | |
371 | // our re-impl of detach() detaches from null |
372 | d->insert(other: *e.d); |
373 | } |
374 | |
375 | #if QT_CONFIG(process) |
376 | |
377 | void 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 | |
399 | /*! |
400 | \class QProcess |
401 | \inmodule QtCore |
402 | |
403 | \brief The QProcess class is used to start external programs and |
404 | to communicate with them. |
405 | |
406 | \ingroup io |
407 | |
408 | \reentrant |
409 | |
410 | \section1 Running a Process |
411 | |
412 | To start a process, pass the name and command line arguments of |
413 | the program you want to run as arguments to start(). Arguments |
414 | are supplied as individual strings in a QStringList. |
415 | |
416 | Alternatively, you can set the program to run with setProgram() |
417 | and setArguments(), and then call start() or open(). |
418 | |
419 | For example, the following code snippet runs the analog clock |
420 | example in the Fusion style on X11 platforms by passing strings |
421 | containing "-style" and "fusion" as two items in the list of |
422 | arguments: |
423 | |
424 | \snippet qprocess/qprocess-simpleexecution.cpp 0 |
425 | \dots |
426 | \snippet qprocess/qprocess-simpleexecution.cpp 1 |
427 | \snippet qprocess/qprocess-simpleexecution.cpp 2 |
428 | |
429 | QProcess then enters the \l Starting state, and when the program |
430 | has started, QProcess enters the \l Running state and emits |
431 | started(). |
432 | |
433 | QProcess allows you to treat a process as a sequential I/O |
434 | device. You can write to and read from the process just as you |
435 | would access a network connection using QTcpSocket. You can then |
436 | write to the process's standard input by calling write(), and |
437 | read the standard output by calling read(), readLine(), and |
438 | getChar(). Because it inherits QIODevice, QProcess can also be |
439 | used as an input source for QXmlReader, or for generating data to |
440 | be uploaded using QNetworkAccessManager. |
441 | |
442 | When the process exits, QProcess reenters the \l NotRunning state |
443 | (the initial state), and emits finished(). |
444 | |
445 | The finished() signal provides the exit code and exit status of |
446 | the process as arguments, and you can also call exitCode() to |
447 | obtain the exit code of the last process that finished, and |
448 | exitStatus() to obtain its exit status. If an error occurs at |
449 | any point in time, QProcess will emit the errorOccurred() signal. |
450 | You can also call error() to find the type of error that occurred |
451 | last, and state() to find the current process state. |
452 | |
453 | \note QProcess is not supported on VxWorks, iOS, tvOS, or watchOS. |
454 | |
455 | \section1 Finding the Executable |
456 | |
457 | The program to be run can be set either by calling setProgram() or directly |
458 | in the start() call. The effect of calling start() with the program name |
459 | and arguments is equivalent to calling setProgram() and setArguments() |
460 | before that function and then calling the overload without those |
461 | parameters. |
462 | |
463 | QProcess interprets the program name in one of three different ways, |
464 | similar to how Unix shells and the Windows command interpreter operate in |
465 | their own command-lines: |
466 | |
467 | \list |
468 | \li If the program name is an absolute path, then that is the exact |
469 | executable that will be launched and QProcess performs no searching. |
470 | |
471 | \li If the program name is a relative path with more than one path |
472 | component (that is, it contains at least one slash), the starting |
473 | directory where that relative path is searched is OS-dependent: on |
474 | Windows, it's the parent process' current working dir, while on Unix it's |
475 | the one set with setWorkingDirectory(). |
476 | |
477 | \li If the program name is a plain file name with no slashes, the |
478 | behavior is operating-system dependent. On Unix systems, QProcess will |
479 | search the \c PATH environment variable; on Windows, the search is |
480 | performed by the OS and will first the parent process' current directory |
481 | before the \c PATH environment variable (see the documentation for |
482 | \l{CreateProcess} for the full list). |
483 | \endlist |
484 | |
485 | To avoid platform-dependent behavior or any issues with how the current |
486 | application was launched, it is advisable to always pass an absolute path |
487 | to the executable to be launched. For auxiliary binaries shipped with the |
488 | application, one can construct such a path starting with |
489 | QCoreApplication::applicationDirPath(). Similarly, to explicitly run an |
490 | executable that is to be found relative to the directory set with |
491 | setWorkingDirectory(), use a program path starting with "./" or "../" as |
492 | the case may be. |
493 | |
494 | On Windows, the ".exe" suffix is not required for most uses, except those |
495 | outlined in the \l{CreateProcess} documentation. Additionally, QProcess |
496 | will convert the Unix-style forward slashes to Windows path backslashes for |
497 | the program name. This allows code using QProcess to be written in a |
498 | cross-platform manner, as shown in the examples above. |
499 | |
500 | QProcess does not support directly executing Unix shell or Windows command |
501 | interpreter built-in functions, such as \c{cmd.exe}'s \c dir command or the |
502 | Bourne shell's \c export. On Unix, even though many shell built-ins are |
503 | also provided as separate executables, their behavior may differ from those |
504 | implemented as built-ins. To run those commands, one should explicitly |
505 | execute the interpreter with suitable options. For Unix systems, launch |
506 | "/bin/sh" with two arguments: "-c" and a string with the command-line to be |
507 | run. For Windows, due to the non-standard way \c{cmd.exe} parses its |
508 | command-line, use setNativeArguments() (for example, "/c dir d:"). |
509 | |
510 | \section1 Environment variables |
511 | |
512 | The QProcess API offers methods to manipulate the environment variables |
513 | that the child process will see. By default, the child process will have a |
514 | copy of the current process environment variables that exist at the time |
515 | the start() function is called. This means that any modifications performed |
516 | using qputenv() prior to that call will be reflected in the child process' |
517 | environment. Note that QProcess makes no attempt to prevent race conditions |
518 | with qputenv() happening in other threads, so it is recommended to avoid |
519 | qputenv() after the application's initial start up. |
520 | |
521 | The environment for a specific child can be modified using the |
522 | processEnvironment() and setProcessEnvironment() functions, which use the |
523 | \l QProcessEnvironment class. By default, processEnvironment() will return |
524 | an object for which QProcessEnvironment::inheritsFromParent() is true. |
525 | Setting an environment that does not inherit from the parent will cause |
526 | QProcess to use exactly that environment for the child when it is started. |
527 | |
528 | The normal scenario starts from the current environment by calling |
529 | QProcessEnvironment::systemEnvironment() and then proceeds to adding, |
530 | changing, or removing specific variables. The resulting variable roster can |
531 | then be applied to a QProcess with setProcessEnvironment(). |
532 | |
533 | It is possible to remove all variables from the environment or to start |
534 | from an empty environment, using the QProcessEnvironment() default |
535 | constructor. This is not advisable outside of controlled and |
536 | system-specific conditions, as there may be system variables that are set |
537 | in the current process environment and are required for proper execution |
538 | of the child process. |
539 | |
540 | On Windows, QProcess will copy the current process' \c "PATH" and \c |
541 | "SystemRoot" environment variables if they were unset. It is not possible |
542 | to unset them completely, but it is possible to set them to empty values. |
543 | Setting \c "PATH" to empty on Windows will likely cause the child process |
544 | to fail to start. |
545 | |
546 | \section1 Communicating via Channels |
547 | |
548 | Processes have two predefined output channels: The standard |
549 | output channel (\c stdout) supplies regular console output, and |
550 | the standard error channel (\c stderr) usually supplies the |
551 | errors that are printed by the process. These channels represent |
552 | two separate streams of data. You can toggle between them by |
553 | calling setReadChannel(). QProcess emits readyRead() when data is |
554 | available on the current read channel. It also emits |
555 | readyReadStandardOutput() when new standard output data is |
556 | available, and when new standard error data is available, |
557 | readyReadStandardError() is emitted. Instead of calling read(), |
558 | readLine(), or getChar(), you can explicitly read all data from |
559 | either of the two channels by calling readAllStandardOutput() or |
560 | readAllStandardError(). |
561 | |
562 | The terminology for the channels can be misleading. Be aware that |
563 | the process's output channels correspond to QProcess's |
564 | \e read channels, whereas the process's input channels correspond |
565 | to QProcess's \e write channels. This is because what we read |
566 | using QProcess is the process's output, and what we write becomes |
567 | the process's input. |
568 | |
569 | QProcess can merge the two output channels, so that standard |
570 | output and standard error data from the running process both use |
571 | the standard output channel. Call setProcessChannelMode() with |
572 | MergedChannels before starting the process to activate |
573 | this feature. You also have the option of forwarding the output of |
574 | the running process to the calling, main process, by passing |
575 | ForwardedChannels as the argument. It is also possible to forward |
576 | only one of the output channels - typically one would use |
577 | ForwardedErrorChannel, but ForwardedOutputChannel also exists. |
578 | Note that using channel forwarding is typically a bad idea in GUI |
579 | applications - you should present errors graphically instead. |
580 | |
581 | Certain processes need special environment settings in order to |
582 | operate. You can set environment variables for your process by |
583 | calling setProcessEnvironment(). To set a working directory, call |
584 | setWorkingDirectory(). By default, processes are run in the |
585 | current working directory of the calling process. |
586 | |
587 | The positioning and the screen Z-order of windows belonging to |
588 | GUI applications started with QProcess are controlled by |
589 | the underlying windowing system. For Qt 5 applications, the |
590 | positioning can be specified using the \c{-qwindowgeometry} |
591 | command line option; X11 applications generally accept a |
592 | \c{-geometry} command line option. |
593 | |
594 | \section1 Synchronous Process API |
595 | |
596 | QProcess provides a set of functions which allow it to be used |
597 | without an event loop, by suspending the calling thread until |
598 | certain signals are emitted: |
599 | |
600 | \list |
601 | \li waitForStarted() blocks until the process has started. |
602 | |
603 | \li waitForReadyRead() blocks until new data is |
604 | available for reading on the current read channel. |
605 | |
606 | \li waitForBytesWritten() blocks until one payload of |
607 | data has been written to the process. |
608 | |
609 | \li waitForFinished() blocks until the process has finished. |
610 | \endlist |
611 | |
612 | Calling these functions from the main thread (the thread that |
613 | calls QApplication::exec()) may cause your user interface to |
614 | freeze. |
615 | |
616 | The following example runs \c gzip to compress the string "Qt |
617 | rocks!", without an event loop: |
618 | |
619 | \snippet process/process.cpp 0 |
620 | |
621 | \sa QBuffer, QFile, QTcpSocket |
622 | */ |
623 | |
624 | /*! |
625 | \enum QProcess::ProcessChannel |
626 | |
627 | This enum describes the process channels used by the running process. |
628 | Pass one of these values to setReadChannel() to set the |
629 | current read channel of QProcess. |
630 | |
631 | \value StandardOutput The standard output (stdout) of the running |
632 | process. |
633 | |
634 | \value StandardError The standard error (stderr) of the running |
635 | process. |
636 | |
637 | \sa setReadChannel() |
638 | */ |
639 | |
640 | /*! |
641 | \enum QProcess::ProcessChannelMode |
642 | |
643 | This enum describes the process output channel modes of QProcess. |
644 | Pass one of these values to setProcessChannelMode() to set the |
645 | current read channel mode. |
646 | |
647 | \value SeparateChannels QProcess manages the output of the |
648 | running process, keeping standard output and standard error data |
649 | in separate internal buffers. You can select the QProcess's |
650 | current read channel by calling setReadChannel(). This is the |
651 | default channel mode of QProcess. |
652 | |
653 | \value MergedChannels QProcess merges the output of the running |
654 | process into the standard output channel (\c stdout). The |
655 | standard error channel (\c stderr) will not receive any data. The |
656 | standard output and standard error data of the running process |
657 | are interleaved. For detached processes, the merged output of the |
658 | running process is forwarded onto the main process. |
659 | |
660 | \value ForwardedChannels QProcess forwards the output of the |
661 | running process onto the main process. Anything the child process |
662 | writes to its standard output and standard error will be written |
663 | to the standard output and standard error of the main process. |
664 | |
665 | \value ForwardedErrorChannel QProcess manages the standard output |
666 | of the running process, but forwards its standard error onto the |
667 | main process. This reflects the typical use of command line tools |
668 | as filters, where the standard output is redirected to another |
669 | process or a file, while standard error is printed to the console |
670 | for diagnostic purposes. |
671 | (This value was introduced in Qt 5.2.) |
672 | |
673 | \value ForwardedOutputChannel Complementary to ForwardedErrorChannel. |
674 | (This value was introduced in Qt 5.2.) |
675 | |
676 | \note Windows intentionally suppresses output from GUI-only |
677 | applications to inherited consoles. |
678 | This does \e not apply to output redirected to files or pipes. |
679 | To forward the output of GUI-only applications on the console |
680 | nonetheless, you must use SeparateChannels and do the forwarding |
681 | yourself by reading the output and writing it to the appropriate |
682 | output channels. |
683 | |
684 | \sa setProcessChannelMode() |
685 | */ |
686 | |
687 | /*! |
688 | \enum QProcess::InputChannelMode |
689 | \since 5.2 |
690 | |
691 | This enum describes the process input channel modes of QProcess. |
692 | Pass one of these values to setInputChannelMode() to set the |
693 | current write channel mode. |
694 | |
695 | \value ManagedInputChannel QProcess manages the input of the running |
696 | process. This is the default input channel mode of QProcess. |
697 | |
698 | \value ForwardedInputChannel QProcess forwards the input of the main |
699 | process onto the running process. The child process reads its standard |
700 | input from the same source as the main process. |
701 | Note that the main process must not try to read its standard input |
702 | while the child process is running. |
703 | |
704 | \sa setInputChannelMode() |
705 | */ |
706 | |
707 | /*! |
708 | \enum QProcess::ProcessError |
709 | |
710 | This enum describes the different types of errors that are |
711 | reported by QProcess. |
712 | |
713 | \value FailedToStart The process failed to start. Either the |
714 | invoked program is missing, or you may have insufficient |
715 | permissions or resources to invoke the program. |
716 | |
717 | \value Crashed The process crashed some time after starting |
718 | successfully. |
719 | |
720 | \value Timedout The last waitFor...() function timed out. The |
721 | state of QProcess is unchanged, and you can try calling |
722 | waitFor...() again. |
723 | |
724 | \value WriteError An error occurred when attempting to write to the |
725 | process. For example, the process may not be running, or it may |
726 | have closed its input channel. |
727 | |
728 | \value ReadError An error occurred when attempting to read from |
729 | the process. For example, the process may not be running. |
730 | |
731 | \value UnknownError An unknown error occurred. This is the default |
732 | return value of error(). |
733 | |
734 | \sa error() |
735 | */ |
736 | |
737 | /*! |
738 | \enum QProcess::ProcessState |
739 | |
740 | This enum describes the different states of QProcess. |
741 | |
742 | \value NotRunning The process is not running. |
743 | |
744 | \value Starting The process is starting, but the program has not |
745 | yet been invoked. |
746 | |
747 | \value Running The process is running and is ready for reading and |
748 | writing. |
749 | |
750 | \sa state() |
751 | */ |
752 | |
753 | /*! |
754 | \enum QProcess::ExitStatus |
755 | |
756 | This enum describes the different exit statuses of QProcess. |
757 | |
758 | \value NormalExit The process exited normally. |
759 | |
760 | \value CrashExit The process crashed. |
761 | |
762 | \sa exitStatus() |
763 | */ |
764 | |
765 | /*! |
766 | \typedef QProcess::CreateProcessArgumentModifier |
767 | \note This typedef is only available on desktop Windows. |
768 | |
769 | On Windows, QProcess uses the Win32 API function \c CreateProcess to |
770 | start child processes. While QProcess provides a comfortable way to start |
771 | processes without worrying about platform |
772 | details, it is in some cases desirable to fine-tune the parameters that are |
773 | passed to \c CreateProcess. This is done by defining a |
774 | \c CreateProcessArgumentModifier function and passing it to |
775 | \c setCreateProcessArgumentsModifier. |
776 | |
777 | A \c CreateProcessArgumentModifier function takes one parameter: a pointer |
778 | to a \c CreateProcessArguments struct. The members of this struct will be |
779 | passed to \c CreateProcess after the \c CreateProcessArgumentModifier |
780 | function is called. |
781 | |
782 | The following example demonstrates how to pass custom flags to |
783 | \c CreateProcess. |
784 | When starting a console process B from a console process A, QProcess will |
785 | reuse the console window of process A for process B by default. In this |
786 | example, a new console window with a custom color scheme is created for the |
787 | child process B instead. |
788 | |
789 | \snippet qprocess/qprocess-createprocessargumentsmodifier.cpp 0 |
790 | |
791 | \sa QProcess::CreateProcessArguments |
792 | \sa setCreateProcessArgumentsModifier() |
793 | */ |
794 | |
795 | /*! |
796 | \class QProcess::CreateProcessArguments |
797 | \inmodule QtCore |
798 | \note This struct is only available on the Windows platform. |
799 | |
800 | This struct is a representation of all parameters of the Windows API |
801 | function \c CreateProcess. It is used as parameter for |
802 | \c CreateProcessArgumentModifier functions. |
803 | |
804 | \sa QProcess::CreateProcessArgumentModifier |
805 | */ |
806 | |
807 | /*! |
808 | \class QProcess::UnixProcessParameters |
809 | \inmodule QtCore |
810 | \note This struct is only available on Unix platforms |
811 | \since 6.6 |
812 | |
813 | This struct can be used to pass extra, Unix-specific configuration for the |
814 | child process using QProcess::setUnixProcessParameters(). |
815 | |
816 | Its members are: |
817 | \list |
818 | \li UnixProcessParameters::flags Flags, see QProcess::UnixProcessFlags |
819 | \li UnixProcessParameters::lowestFileDescriptorToClose The lowest file |
820 | descriptor to close. |
821 | \endlist |
822 | |
823 | When the QProcess::UnixProcessFlags::CloseFileDescriptors flag is set in |
824 | the \c flags field, QProcess closes the application's open file descriptors |
825 | before executing the child process. The descriptors 0, 1, and 2 (that is, |
826 | \c stdin, \c stdout, and \c stderr) are left alone, along with the ones |
827 | numbered lower than the value of the \c lowestFileDescriptorToClose field. |
828 | |
829 | All of the settings above can also be manually achieved by calling the |
830 | respective POSIX function from a handler set with |
831 | QProcess::setChildProcessModifier(). This structure allows QProcess to deal |
832 | with any platform-specific differences, benefit from certain optimizations, |
833 | and reduces code duplication. Moreover, if any of those functions fail, |
834 | QProcess will enter QProcess::FailedToStart state, while the child process |
835 | modifier callback is not allowed to fail. |
836 | |
837 | \sa QProcess::setUnixProcessParameters(), QProcess::setChildProcessModifier() |
838 | */ |
839 | |
840 | /*! |
841 | \enum QProcess::UnixProcessFlag |
842 | \since 6.6 |
843 | |
844 | These flags can be used in the \c flags field of \l UnixProcessParameters. |
845 | |
846 | \value CloseFileDescriptors Close all file descriptors above the threshold |
847 | defined by \c lowestFileDescriptorToClose, preventing any currently |
848 | open descriptor in the parent process from accidentally leaking to the |
849 | child. The \c stdin, \c stdout, and \c stderr file descriptors are |
850 | never closed. |
851 | |
852 | \value IgnoreSigPipe Always sets the \c SIGPIPE signal to ignored |
853 | (\c SIG_IGN), even if the \c ResetSignalHandlers flag was set. By |
854 | default, if the child attempts to write to its standard output or |
855 | standard error after the respective channel was closed with |
856 | QProcess::closeReadChannel(), it would get the \c SIGPIPE signal and |
857 | terminate immediately; with this flag, the write operation fails |
858 | without a signal and the child may continue executing. |
859 | |
860 | \value ResetSignalHandlers Resets all Unix signal handlers back to their |
861 | default state (that is, pass \c SIG_DFL to \c{signal(2)}). This flag |
862 | is useful to ensure any ignored (\c SIG_IGN) signal does not affect |
863 | the child's behavior. |
864 | |
865 | \value UseVFork Requests that QProcess use \c{vfork(2)} to start the child |
866 | process. Use this flag to indicate that the callback function set |
867 | with setChildProcessModifier() is safe to execute in the child side of |
868 | a \c{vfork(2)}; that is, the callback does not modify any non-local |
869 | variables (directly or through any function it calls), nor attempts |
870 | to communicate with the parent process. It is implementation-defined |
871 | if QProcess will actually use \c{vfork(2)} and if \c{vfork(2)} is |
872 | different from standard \c{fork(2)}. |
873 | |
874 | \sa setUnixProcessParameters(), unixProcessParameters() |
875 | */ |
876 | |
877 | /*! |
878 | \fn void QProcess::errorOccurred(QProcess::ProcessError error) |
879 | \since 5.6 |
880 | |
881 | This signal is emitted when an error occurs with the process. The |
882 | specified \a error describes the type of error that occurred. |
883 | */ |
884 | |
885 | /*! |
886 | \fn void QProcess::started() |
887 | |
888 | This signal is emitted by QProcess when the process has started, |
889 | and state() returns \l Running. |
890 | */ |
891 | |
892 | /*! |
893 | \fn void QProcess::stateChanged(QProcess::ProcessState newState) |
894 | |
895 | This signal is emitted whenever the state of QProcess changes. The |
896 | \a newState argument is the state QProcess changed to. |
897 | */ |
898 | |
899 | /*! |
900 | \fn void QProcess::finished(int exitCode, QProcess::ExitStatus exitStatus) |
901 | |
902 | This signal is emitted when the process finishes. \a exitCode is the exit |
903 | code of the process (only valid for normal exits), and \a exitStatus is |
904 | the exit status. |
905 | After the process has finished, the buffers in QProcess are still intact. |
906 | You can still read any data that the process may have written before it |
907 | finished. |
908 | |
909 | \sa exitStatus() |
910 | */ |
911 | |
912 | /*! |
913 | \fn void QProcess::readyReadStandardOutput() |
914 | |
915 | This signal is emitted when the process has made new data |
916 | available through its standard output channel (\c stdout). It is |
917 | emitted regardless of the current \l{readChannel()}{read channel}. |
918 | |
919 | \sa readAllStandardOutput(), readChannel() |
920 | */ |
921 | |
922 | /*! |
923 | \fn void QProcess::readyReadStandardError() |
924 | |
925 | This signal is emitted when the process has made new data |
926 | available through its standard error channel (\c stderr). It is |
927 | emitted regardless of the current \l{readChannel()}{read |
928 | channel}. |
929 | |
930 | \sa readAllStandardError(), readChannel() |
931 | */ |
932 | |
933 | /*! |
934 | \internal |
935 | */ |
936 | QProcessPrivate::QProcessPrivate() |
937 | { |
938 | readBufferChunkSize = QRINGBUFFER_CHUNKSIZE; |
939 | #ifndef Q_OS_WIN |
940 | writeBufferChunkSize = QRINGBUFFER_CHUNKSIZE; |
941 | #endif |
942 | } |
943 | |
944 | /*! |
945 | \internal |
946 | */ |
947 | QProcessPrivate::~QProcessPrivate() |
948 | { |
949 | if (stdinChannel.process) |
950 | stdinChannel.process->stdoutChannel.clear(); |
951 | if (stdoutChannel.process) |
952 | stdoutChannel.process->stdinChannel.clear(); |
953 | } |
954 | |
955 | /*! |
956 | \internal |
957 | */ |
958 | void QProcessPrivate::setError(QProcess::ProcessError error, const QString &description) |
959 | { |
960 | processError = error; |
961 | if (description.isEmpty()) { |
962 | switch (error) { |
963 | case QProcess::FailedToStart: |
964 | errorString = QProcess::tr(s: "Process failed to start" ); |
965 | break; |
966 | case QProcess::Crashed: |
967 | errorString = QProcess::tr(s: "Process crashed" ); |
968 | break; |
969 | case QProcess::Timedout: |
970 | errorString = QProcess::tr(s: "Process operation timed out" ); |
971 | break; |
972 | case QProcess::ReadError: |
973 | errorString = QProcess::tr(s: "Error reading from process" ); |
974 | break; |
975 | case QProcess::WriteError: |
976 | errorString = QProcess::tr(s: "Error writing to process" ); |
977 | break; |
978 | case QProcess::UnknownError: |
979 | errorString.clear(); |
980 | break; |
981 | } |
982 | } else { |
983 | errorString = description; |
984 | } |
985 | } |
986 | |
987 | /*! |
988 | \internal |
989 | */ |
990 | void QProcessPrivate::setErrorAndEmit(QProcess::ProcessError error, const QString &description) |
991 | { |
992 | Q_Q(QProcess); |
993 | Q_ASSERT(error != QProcess::UnknownError); |
994 | setError(error, description); |
995 | emit q->errorOccurred(error: QProcess::ProcessError(processError)); |
996 | } |
997 | |
998 | /*! |
999 | \internal |
1000 | */ |
1001 | bool QProcessPrivate::openChannels() |
1002 | { |
1003 | // stdin channel. |
1004 | if (inputChannelMode == QProcess::ForwardedInputChannel) { |
1005 | if (stdinChannel.type != Channel::Normal) |
1006 | qWarning(msg: "QProcess::openChannels: Inconsistent stdin channel configuration" ); |
1007 | } else if (!openChannel(channel&: stdinChannel)) { |
1008 | return false; |
1009 | } |
1010 | |
1011 | // stdout channel. |
1012 | if (processChannelMode == QProcess::ForwardedChannels |
1013 | || processChannelMode == QProcess::ForwardedOutputChannel) { |
1014 | if (stdoutChannel.type != Channel::Normal) |
1015 | qWarning(msg: "QProcess::openChannels: Inconsistent stdout channel configuration" ); |
1016 | } else if (!openChannel(channel&: stdoutChannel)) { |
1017 | return false; |
1018 | } |
1019 | |
1020 | // stderr channel. |
1021 | if (processChannelMode == QProcess::ForwardedChannels |
1022 | || processChannelMode == QProcess::ForwardedErrorChannel |
1023 | || processChannelMode == QProcess::MergedChannels) { |
1024 | if (stderrChannel.type != Channel::Normal) |
1025 | qWarning(msg: "QProcess::openChannels: Inconsistent stderr channel configuration" ); |
1026 | } else if (!openChannel(channel&: stderrChannel)) { |
1027 | return false; |
1028 | } |
1029 | |
1030 | return true; |
1031 | } |
1032 | |
1033 | /*! |
1034 | \internal |
1035 | */ |
1036 | void QProcessPrivate::closeChannels() |
1037 | { |
1038 | closeChannel(channel: &stdoutChannel); |
1039 | closeChannel(channel: &stderrChannel); |
1040 | closeChannel(channel: &stdinChannel); |
1041 | } |
1042 | |
1043 | /*! |
1044 | \internal |
1045 | */ |
1046 | bool QProcessPrivate::openChannelsForDetached() |
1047 | { |
1048 | // stdin channel. |
1049 | bool needToOpen = (stdinChannel.type == Channel::Redirect |
1050 | || stdinChannel.type == Channel::PipeSink); |
1051 | if (stdinChannel.type != Channel::Normal |
1052 | && (!needToOpen |
1053 | || inputChannelMode == QProcess::ForwardedInputChannel)) { |
1054 | qWarning(msg: "QProcess::openChannelsForDetached: Inconsistent stdin channel configuration" ); |
1055 | } |
1056 | if (needToOpen && !openChannel(channel&: stdinChannel)) |
1057 | return false; |
1058 | |
1059 | // stdout channel. |
1060 | needToOpen = (stdoutChannel.type == Channel::Redirect |
1061 | || stdoutChannel.type == Channel::PipeSource); |
1062 | if (stdoutChannel.type != Channel::Normal |
1063 | && (!needToOpen |
1064 | || processChannelMode == QProcess::ForwardedChannels |
1065 | || processChannelMode == QProcess::ForwardedOutputChannel)) { |
1066 | qWarning(msg: "QProcess::openChannelsForDetached: Inconsistent stdout channel configuration" ); |
1067 | } |
1068 | if (needToOpen && !openChannel(channel&: stdoutChannel)) |
1069 | return false; |
1070 | |
1071 | // stderr channel. |
1072 | needToOpen = (stderrChannel.type == Channel::Redirect); |
1073 | if (stderrChannel.type != Channel::Normal |
1074 | && (!needToOpen |
1075 | || processChannelMode == QProcess::ForwardedChannels |
1076 | || processChannelMode == QProcess::ForwardedErrorChannel |
1077 | || processChannelMode == QProcess::MergedChannels)) { |
1078 | qWarning(msg: "QProcess::openChannelsForDetached: Inconsistent stderr channel configuration" ); |
1079 | } |
1080 | if (needToOpen && !openChannel(channel&: stderrChannel)) |
1081 | return false; |
1082 | |
1083 | return true; |
1084 | } |
1085 | |
1086 | /*! |
1087 | \internal |
1088 | Returns \c true if we emitted readyRead(). |
1089 | */ |
1090 | bool QProcessPrivate::tryReadFromChannel(Channel *channel) |
1091 | { |
1092 | Q_Q(QProcess); |
1093 | if (channel->pipe[0] == INVALID_Q_PIPE) |
1094 | return false; |
1095 | |
1096 | qint64 available = bytesAvailableInChannel(channel); |
1097 | if (available == 0) |
1098 | available = 1; // always try to read at least one byte |
1099 | |
1100 | QProcess::ProcessChannel channelIdx = (channel == &stdoutChannel |
1101 | ? QProcess::StandardOutput |
1102 | : QProcess::StandardError); |
1103 | Q_ASSERT(readBuffers.size() > int(channelIdx)); |
1104 | QRingBuffer &readBuffer = readBuffers[int(channelIdx)]; |
1105 | char *ptr = readBuffer.reserve(bytes: available); |
1106 | qint64 readBytes = readFromChannel(channel, data: ptr, maxlen: available); |
1107 | if (readBytes <= 0) |
1108 | readBuffer.chop(bytes: available); |
1109 | if (readBytes == -2) { |
1110 | // EWOULDBLOCK |
1111 | return false; |
1112 | } |
1113 | if (readBytes == -1) { |
1114 | setErrorAndEmit(error: QProcess::ReadError); |
1115 | #if defined QPROCESS_DEBUG |
1116 | qDebug("QProcessPrivate::tryReadFromChannel(%d), failed to read from the process" , |
1117 | int(channel - &stdinChannel)); |
1118 | #endif |
1119 | return false; |
1120 | } |
1121 | if (readBytes == 0) { |
1122 | // EOF |
1123 | closeChannel(channel); |
1124 | #if defined QPROCESS_DEBUG |
1125 | qDebug("QProcessPrivate::tryReadFromChannel(%d), 0 bytes available" , |
1126 | int(channel - &stdinChannel)); |
1127 | #endif |
1128 | return false; |
1129 | } |
1130 | #if defined QPROCESS_DEBUG |
1131 | qDebug("QProcessPrivate::tryReadFromChannel(%d), read %lld bytes from the process' output" , |
1132 | int(channel - &stdinChannel), readBytes); |
1133 | #endif |
1134 | |
1135 | if (channel->closed) { |
1136 | readBuffer.chop(bytes: readBytes); |
1137 | return false; |
1138 | } |
1139 | |
1140 | readBuffer.chop(bytes: available - readBytes); |
1141 | |
1142 | bool didRead = false; |
1143 | if (currentReadChannel == channelIdx) { |
1144 | didRead = true; |
1145 | if (!emittedReadyRead) { |
1146 | QScopedValueRollback<bool> guard(emittedReadyRead, true); |
1147 | emit q->readyRead(); |
1148 | } |
1149 | } |
1150 | emit q->channelReadyRead(channel: int(channelIdx)); |
1151 | if (channelIdx == QProcess::StandardOutput) |
1152 | emit q->readyReadStandardOutput(QProcess::QPrivateSignal()); |
1153 | else |
1154 | emit q->readyReadStandardError(QProcess::QPrivateSignal()); |
1155 | return didRead; |
1156 | } |
1157 | |
1158 | /*! |
1159 | \internal |
1160 | */ |
1161 | bool QProcessPrivate::_q_canReadStandardOutput() |
1162 | { |
1163 | return tryReadFromChannel(channel: &stdoutChannel); |
1164 | } |
1165 | |
1166 | /*! |
1167 | \internal |
1168 | */ |
1169 | bool QProcessPrivate::_q_canReadStandardError() |
1170 | { |
1171 | return tryReadFromChannel(channel: &stderrChannel); |
1172 | } |
1173 | |
1174 | /*! |
1175 | \internal |
1176 | */ |
1177 | void QProcessPrivate::_q_processDied() |
1178 | { |
1179 | #if defined QPROCESS_DEBUG |
1180 | qDebug("QProcessPrivate::_q_processDied()" ); |
1181 | #endif |
1182 | |
1183 | // in case there is data in the pipeline and this slot by chance |
1184 | // got called before the read notifications, call these functions |
1185 | // so the data is made available before we announce death. |
1186 | #ifdef Q_OS_WIN |
1187 | drainOutputPipes(); |
1188 | #else |
1189 | _q_canReadStandardOutput(); |
1190 | _q_canReadStandardError(); |
1191 | #endif |
1192 | |
1193 | // Slots connected to signals emitted by the functions called above |
1194 | // might call waitFor*(), which would synchronously reap the process. |
1195 | // So check the state to avoid trying to reap a second time. |
1196 | if (processState != QProcess::NotRunning) |
1197 | processFinished(); |
1198 | } |
1199 | |
1200 | /*! |
1201 | \internal |
1202 | */ |
1203 | void QProcessPrivate::processFinished() |
1204 | { |
1205 | Q_Q(QProcess); |
1206 | #if defined QPROCESS_DEBUG |
1207 | qDebug("QProcessPrivate::processFinished()" ); |
1208 | #endif |
1209 | |
1210 | #ifdef Q_OS_UNIX |
1211 | waitForDeadChild(); |
1212 | #else |
1213 | findExitCode(); |
1214 | #endif |
1215 | |
1216 | cleanup(); |
1217 | |
1218 | if (exitStatus == QProcess::CrashExit) |
1219 | setErrorAndEmit(error: QProcess::Crashed); |
1220 | |
1221 | // we received EOF now: |
1222 | emit q->readChannelFinished(); |
1223 | // in the future: |
1224 | //emit q->standardOutputClosed(); |
1225 | //emit q->standardErrorClosed(); |
1226 | |
1227 | emit q->finished(exitCode, exitStatus: QProcess::ExitStatus(exitStatus)); |
1228 | |
1229 | #if defined QPROCESS_DEBUG |
1230 | qDebug("QProcessPrivate::processFinished(): process is dead" ); |
1231 | #endif |
1232 | } |
1233 | |
1234 | /*! |
1235 | \internal |
1236 | */ |
1237 | bool QProcessPrivate::_q_startupNotification() |
1238 | { |
1239 | Q_Q(QProcess); |
1240 | #if defined QPROCESS_DEBUG |
1241 | qDebug("QProcessPrivate::startupNotification()" ); |
1242 | #endif |
1243 | |
1244 | QString errorMessage; |
1245 | if (processStarted(errorMessage: &errorMessage)) { |
1246 | q->setProcessState(QProcess::Running); |
1247 | emit q->started(QProcess::QPrivateSignal()); |
1248 | return true; |
1249 | } |
1250 | |
1251 | q->setProcessState(QProcess::NotRunning); |
1252 | setErrorAndEmit(error: QProcess::FailedToStart, description: errorMessage); |
1253 | #ifdef Q_OS_UNIX |
1254 | waitForDeadChild(); |
1255 | #endif |
1256 | cleanup(); |
1257 | return false; |
1258 | } |
1259 | |
1260 | /*! |
1261 | \internal |
1262 | */ |
1263 | void QProcessPrivate::closeWriteChannel() |
1264 | { |
1265 | #if defined QPROCESS_DEBUG |
1266 | qDebug("QProcessPrivate::closeWriteChannel()" ); |
1267 | #endif |
1268 | |
1269 | closeChannel(channel: &stdinChannel); |
1270 | } |
1271 | |
1272 | /*! |
1273 | Constructs a QProcess object with the given \a parent. |
1274 | */ |
1275 | QProcess::QProcess(QObject *parent) |
1276 | : QIODevice(*new QProcessPrivate, parent) |
1277 | { |
1278 | #if defined QPROCESS_DEBUG |
1279 | qDebug("QProcess::QProcess(%p)" , parent); |
1280 | #endif |
1281 | } |
1282 | |
1283 | /*! |
1284 | Destructs the QProcess object, i.e., killing the process. |
1285 | |
1286 | Note that this function will not return until the process is |
1287 | terminated. |
1288 | */ |
1289 | QProcess::~QProcess() |
1290 | { |
1291 | Q_D(QProcess); |
1292 | if (d->processState != NotRunning) { |
1293 | qWarning().nospace() |
1294 | << "QProcess: Destroyed while process (" << QDir::toNativeSeparators(pathName: program()) << ") is still running." ; |
1295 | kill(); |
1296 | waitForFinished(); |
1297 | } |
1298 | d->cleanup(); |
1299 | } |
1300 | |
1301 | /*! |
1302 | \since 4.2 |
1303 | |
1304 | Returns the channel mode of the QProcess standard output and |
1305 | standard error channels. |
1306 | |
1307 | \sa setProcessChannelMode(), ProcessChannelMode, setReadChannel() |
1308 | */ |
1309 | QProcess::ProcessChannelMode QProcess::processChannelMode() const |
1310 | { |
1311 | Q_D(const QProcess); |
1312 | return ProcessChannelMode(d->processChannelMode); |
1313 | } |
1314 | |
1315 | /*! |
1316 | \since 4.2 |
1317 | |
1318 | Sets the channel mode of the QProcess standard output and standard |
1319 | error channels to the \a mode specified. |
1320 | This mode will be used the next time start() is called. For example: |
1321 | |
1322 | \snippet code/src_corelib_io_qprocess.cpp 0 |
1323 | |
1324 | \sa processChannelMode(), ProcessChannelMode, setReadChannel() |
1325 | */ |
1326 | void QProcess::setProcessChannelMode(ProcessChannelMode mode) |
1327 | { |
1328 | Q_D(QProcess); |
1329 | d->processChannelMode = mode; |
1330 | } |
1331 | |
1332 | /*! |
1333 | \since 5.2 |
1334 | |
1335 | Returns the channel mode of the QProcess standard input channel. |
1336 | |
1337 | \sa setInputChannelMode(), InputChannelMode |
1338 | */ |
1339 | QProcess::InputChannelMode QProcess::inputChannelMode() const |
1340 | { |
1341 | Q_D(const QProcess); |
1342 | return InputChannelMode(d->inputChannelMode); |
1343 | } |
1344 | |
1345 | /*! |
1346 | \since 5.2 |
1347 | |
1348 | Sets the channel mode of the QProcess standard input |
1349 | channel to the \a mode specified. |
1350 | This mode will be used the next time start() is called. |
1351 | |
1352 | \sa inputChannelMode(), InputChannelMode |
1353 | */ |
1354 | void QProcess::setInputChannelMode(InputChannelMode mode) |
1355 | { |
1356 | Q_D(QProcess); |
1357 | d->inputChannelMode = mode; |
1358 | } |
1359 | |
1360 | /*! |
1361 | Returns the current read channel of the QProcess. |
1362 | |
1363 | \sa setReadChannel() |
1364 | */ |
1365 | QProcess::ProcessChannel QProcess::readChannel() const |
1366 | { |
1367 | Q_D(const QProcess); |
1368 | return ProcessChannel(d->currentReadChannel); |
1369 | } |
1370 | |
1371 | /*! |
1372 | Sets the current read channel of the QProcess to the given \a |
1373 | channel. The current input channel is used by the functions |
1374 | read(), readAll(), readLine(), and getChar(). It also determines |
1375 | which channel triggers QProcess to emit readyRead(). |
1376 | |
1377 | \sa readChannel() |
1378 | */ |
1379 | void QProcess::setReadChannel(ProcessChannel channel) |
1380 | { |
1381 | QIODevice::setCurrentReadChannel(int(channel)); |
1382 | } |
1383 | |
1384 | /*! |
1385 | Closes the read channel \a channel. After calling this function, |
1386 | QProcess will no longer receive data on the channel. Any data that |
1387 | has already been received is still available for reading. |
1388 | |
1389 | Call this function to save memory, if you are not interested in |
1390 | the output of the process. |
1391 | |
1392 | \sa closeWriteChannel(), setReadChannel() |
1393 | */ |
1394 | void QProcess::closeReadChannel(ProcessChannel channel) |
1395 | { |
1396 | Q_D(QProcess); |
1397 | |
1398 | if (channel == StandardOutput) |
1399 | d->stdoutChannel.closed = true; |
1400 | else |
1401 | d->stderrChannel.closed = true; |
1402 | } |
1403 | |
1404 | /*! |
1405 | Schedules the write channel of QProcess to be closed. The channel |
1406 | will close once all data has been written to the process. After |
1407 | calling this function, any attempts to write to the process will |
1408 | fail. |
1409 | |
1410 | Closing the write channel is necessary for programs that read |
1411 | input data until the channel has been closed. For example, the |
1412 | program "more" is used to display text data in a console on both |
1413 | Unix and Windows. But it will not display the text data until |
1414 | QProcess's write channel has been closed. Example: |
1415 | |
1416 | \snippet code/src_corelib_io_qprocess.cpp 1 |
1417 | |
1418 | The write channel is implicitly opened when start() is called. |
1419 | |
1420 | \sa closeReadChannel() |
1421 | */ |
1422 | void QProcess::closeWriteChannel() |
1423 | { |
1424 | Q_D(QProcess); |
1425 | d->stdinChannel.closed = true; // closing |
1426 | if (bytesToWrite() == 0) |
1427 | d->closeWriteChannel(); |
1428 | } |
1429 | |
1430 | /*! |
1431 | \since 4.2 |
1432 | |
1433 | Redirects the process' standard input to the file indicated by \a |
1434 | fileName. When an input redirection is in place, the QProcess |
1435 | object will be in read-only mode (calling write() will result in |
1436 | error). |
1437 | |
1438 | To make the process read EOF right away, pass nullDevice() here. |
1439 | This is cleaner than using closeWriteChannel() before writing any |
1440 | data, because it can be set up prior to starting the process. |
1441 | |
1442 | If the file \a fileName does not exist at the moment start() is |
1443 | called or is not readable, starting the process will fail. |
1444 | |
1445 | Calling setStandardInputFile() after the process has started has no |
1446 | effect. |
1447 | |
1448 | \sa setStandardOutputFile(), setStandardErrorFile(), |
1449 | setStandardOutputProcess() |
1450 | */ |
1451 | void QProcess::setStandardInputFile(const QString &fileName) |
1452 | { |
1453 | Q_D(QProcess); |
1454 | d->stdinChannel = fileName; |
1455 | } |
1456 | |
1457 | /*! |
1458 | \since 4.2 |
1459 | |
1460 | Redirects the process' standard output to the file \a |
1461 | fileName. When the redirection is in place, the standard output |
1462 | read channel is closed: reading from it using read() will always |
1463 | fail, as will readAllStandardOutput(). |
1464 | |
1465 | To discard all standard output from the process, pass nullDevice() |
1466 | here. This is more efficient than simply never reading the standard |
1467 | output, as no QProcess buffers are filled. |
1468 | |
1469 | If the file \a fileName doesn't exist at the moment start() is |
1470 | called, it will be created. If it cannot be created, the starting |
1471 | will fail. |
1472 | |
1473 | If the file exists and \a mode is QIODevice::Truncate, the file |
1474 | will be truncated. Otherwise (if \a mode is QIODevice::Append), |
1475 | the file will be appended to. |
1476 | |
1477 | Calling setStandardOutputFile() after the process has started has |
1478 | no effect. |
1479 | |
1480 | If \a fileName is an empty string, it stops redirecting the standard |
1481 | output. This is useful for restoring the standard output after redirection. |
1482 | |
1483 | \sa setStandardInputFile(), setStandardErrorFile(), |
1484 | setStandardOutputProcess() |
1485 | */ |
1486 | void QProcess::setStandardOutputFile(const QString &fileName, OpenMode mode) |
1487 | { |
1488 | Q_ASSERT(mode == Append || mode == Truncate); |
1489 | Q_D(QProcess); |
1490 | |
1491 | d->stdoutChannel = fileName; |
1492 | d->stdoutChannel.append = mode == Append; |
1493 | } |
1494 | |
1495 | /*! |
1496 | \since 4.2 |
1497 | |
1498 | Redirects the process' standard error to the file \a |
1499 | fileName. When the redirection is in place, the standard error |
1500 | read channel is closed: reading from it using read() will always |
1501 | fail, as will readAllStandardError(). The file will be appended to |
1502 | if \a mode is Append, otherwise, it will be truncated. |
1503 | |
1504 | See setStandardOutputFile() for more information on how the file |
1505 | is opened. |
1506 | |
1507 | Note: if setProcessChannelMode() was called with an argument of |
1508 | QProcess::MergedChannels, this function has no effect. |
1509 | |
1510 | \sa setStandardInputFile(), setStandardOutputFile(), |
1511 | setStandardOutputProcess() |
1512 | */ |
1513 | void QProcess::setStandardErrorFile(const QString &fileName, OpenMode mode) |
1514 | { |
1515 | Q_ASSERT(mode == Append || mode == Truncate); |
1516 | Q_D(QProcess); |
1517 | |
1518 | d->stderrChannel = fileName; |
1519 | d->stderrChannel.append = mode == Append; |
1520 | } |
1521 | |
1522 | /*! |
1523 | \since 4.2 |
1524 | |
1525 | Pipes the standard output stream of this process to the \a |
1526 | destination process' standard input. |
1527 | |
1528 | The following shell command: |
1529 | \snippet code/src_corelib_io_qprocess.cpp 2 |
1530 | |
1531 | Can be accomplished with QProcess with the following code: |
1532 | \snippet code/src_corelib_io_qprocess.cpp 3 |
1533 | */ |
1534 | void QProcess::setStandardOutputProcess(QProcess *destination) |
1535 | { |
1536 | QProcessPrivate *dfrom = d_func(); |
1537 | QProcessPrivate *dto = destination->d_func(); |
1538 | dfrom->stdoutChannel.pipeTo(other: dto); |
1539 | dto->stdinChannel.pipeFrom(other: dfrom); |
1540 | } |
1541 | |
1542 | #if defined(Q_OS_WIN) || defined(Q_QDOC) |
1543 | |
1544 | /*! |
1545 | \since 4.7 |
1546 | |
1547 | Returns the additional native command line arguments for the program. |
1548 | |
1549 | \note This function is available only on the Windows platform. |
1550 | |
1551 | \sa setNativeArguments() |
1552 | */ |
1553 | QString QProcess::nativeArguments() const |
1554 | { |
1555 | Q_D(const QProcess); |
1556 | return d->nativeArguments; |
1557 | } |
1558 | |
1559 | /*! |
1560 | \since 4.7 |
1561 | \overload |
1562 | |
1563 | Sets additional native command line \a arguments for the program. |
1564 | |
1565 | On operating systems where the system API for passing command line |
1566 | \a arguments to a subprocess natively uses a single string, one can |
1567 | conceive command lines which cannot be passed via QProcess's portable |
1568 | list-based API. In such cases this function must be used to set a |
1569 | string which is \e appended to the string composed from the usual |
1570 | argument list, with a delimiting space. |
1571 | |
1572 | \note This function is available only on the Windows platform. |
1573 | |
1574 | \sa nativeArguments() |
1575 | */ |
1576 | void QProcess::setNativeArguments(const QString &arguments) |
1577 | { |
1578 | Q_D(QProcess); |
1579 | d->nativeArguments = arguments; |
1580 | } |
1581 | |
1582 | /*! |
1583 | \since 5.7 |
1584 | |
1585 | Returns a previously set \c CreateProcess modifier function. |
1586 | |
1587 | \note This function is available only on the Windows platform. |
1588 | |
1589 | \sa setCreateProcessArgumentsModifier() |
1590 | \sa QProcess::CreateProcessArgumentModifier |
1591 | */ |
1592 | QProcess::CreateProcessArgumentModifier QProcess::createProcessArgumentsModifier() const |
1593 | { |
1594 | Q_D(const QProcess); |
1595 | return d->modifyCreateProcessArgs; |
1596 | } |
1597 | |
1598 | /*! |
1599 | \since 5.7 |
1600 | |
1601 | Sets the \a modifier for the \c CreateProcess Win32 API call. |
1602 | Pass \c QProcess::CreateProcessArgumentModifier() to remove a previously set one. |
1603 | |
1604 | \note This function is available only on the Windows platform and requires |
1605 | C++11. |
1606 | |
1607 | \sa QProcess::CreateProcessArgumentModifier, setChildProcessModifier() |
1608 | */ |
1609 | void QProcess::setCreateProcessArgumentsModifier(CreateProcessArgumentModifier modifier) |
1610 | { |
1611 | Q_D(QProcess); |
1612 | d->modifyCreateProcessArgs = modifier; |
1613 | } |
1614 | |
1615 | #endif |
1616 | |
1617 | #if defined(Q_OS_UNIX) || defined(Q_QDOC) |
1618 | /*! |
1619 | \since 6.0 |
1620 | |
1621 | Returns the modifier function previously set by calling |
1622 | setChildProcessModifier(). |
1623 | |
1624 | \note This function is only available on Unix platforms. |
1625 | |
1626 | \sa setChildProcessModifier(), unixProcessParameters() |
1627 | */ |
1628 | std::function<void(void)> QProcess::childProcessModifier() const |
1629 | { |
1630 | Q_D(const QProcess); |
1631 | return d->unixExtras ? d->unixExtras->childProcessModifier : std::function<void(void)>(); |
1632 | } |
1633 | |
1634 | /*! |
1635 | \since 6.0 |
1636 | |
1637 | Sets the \a modifier function for the child process, for Unix systems |
1638 | (including \macos; for Windows, see setCreateProcessArgumentsModifier()). |
1639 | The function contained by the \a modifier argument will be invoked in the |
1640 | child process after \c{fork()} or \c{vfork()} is completed and QProcess has |
1641 | set up the standard file descriptors for the child process, but before |
1642 | \c{execve()}, inside start(). |
1643 | |
1644 | The following shows an example of setting up a child process to run without |
1645 | privileges: |
1646 | |
1647 | \snippet code/src_corelib_io_qprocess.cpp 4 |
1648 | |
1649 | If the modifier function needs to exit the process, remember to use |
1650 | \c{_exit()}, not \c{exit()}. |
1651 | |
1652 | Certain properties of the child process, such as closing all extraneous |
1653 | file descriptors or disconnecting from the controlling TTY, can be more |
1654 | readily achieved by using setUnixProcessParameters(), which can detect |
1655 | failure and report a \l{QProcess::}{FailedToStart} condition. The modifier |
1656 | is useful to change certain uncommon properties of the child process, such |
1657 | as setting up additional file descriptors. If both a child process modifier |
1658 | and Unix process parameters are set, the modifier is run before these |
1659 | parameters are applied. |
1660 | |
1661 | \note In multithreaded applications, this function must be careful not to |
1662 | call any functions that may lock mutexes that may have been in use in |
1663 | other threads (in general, using only functions defined by POSIX as |
1664 | "async-signal-safe" is advised). Most of the Qt API is unsafe inside this |
1665 | callback, including qDebug(), and may lead to deadlocks. |
1666 | |
1667 | \note If the UnixProcessParameters::UseVFork flag is set via |
1668 | setUnixProcessParameters(), QProcess may use \c{vfork()} semantics to |
1669 | start the child process, so this function must obey even stricter |
1670 | constraints. First, because it is still sharing memory with the parent |
1671 | process, it must not write to any non-local variable and must obey proper |
1672 | ordering semantics when reading from them, to avoid data races. Second, |
1673 | even more library functions may misbehave; therefore, this function should |
1674 | only make use of low-level system calls, such as \c{read()}, |
1675 | \c{write()}, \c{setsid()}, \c{nice()}, and similar. |
1676 | |
1677 | \sa childProcessModifier(), setUnixProcessParameters() |
1678 | */ |
1679 | void QProcess::setChildProcessModifier(const std::function<void(void)> &modifier) |
1680 | { |
1681 | Q_D(QProcess); |
1682 | if (!d->unixExtras) |
1683 | d->unixExtras.reset(p: new QProcessPrivate::UnixExtras); |
1684 | d->unixExtras->childProcessModifier = modifier; |
1685 | } |
1686 | |
1687 | /*! |
1688 | \since 6.6 |
1689 | Returns the \l UnixProcessParameters object describing extra flags and |
1690 | settings that will be applied to the child process on Unix systems. The |
1691 | default settings correspond to a default-constructed UnixProcessParameters. |
1692 | |
1693 | \note This function is only available on Unix platforms. |
1694 | |
1695 | \sa childProcessModifier() |
1696 | */ |
1697 | auto QProcess::unixProcessParameters() const noexcept -> UnixProcessParameters |
1698 | { |
1699 | Q_D(const QProcess); |
1700 | return d->unixExtras ? d->unixExtras->processParameters : UnixProcessParameters{}; |
1701 | } |
1702 | |
1703 | /*! |
1704 | \since 6.6 |
1705 | Sets the extra settings and parameters for the child process on Unix |
1706 | systems to be \a params. This function can be used to ask QProcess to |
1707 | modify the child process before launching the target executable. |
1708 | |
1709 | This function can be used to change certain properties of the child |
1710 | process, such as closing all extraneous file descriptors, changing the nice |
1711 | level of the child, or disconnecting from the controlling TTY. For more |
1712 | fine-grained control of the child process or to modify it in other ways, |
1713 | use the setChildProcessModifier() function. If both a child process |
1714 | modifier and Unix process parameters are set, the modifier is run before |
1715 | these parameters are applied. |
1716 | |
1717 | \note This function is only available on Unix platforms. |
1718 | |
1719 | \sa unixProcessParameters(), setChildProcessModifier() |
1720 | */ |
1721 | void QProcess::setUnixProcessParameters(const UnixProcessParameters ¶ms) |
1722 | { |
1723 | Q_D(QProcess); |
1724 | if (!d->unixExtras) |
1725 | d->unixExtras.reset(p: new QProcessPrivate::UnixExtras); |
1726 | d->unixExtras->processParameters = params; |
1727 | } |
1728 | |
1729 | /*! |
1730 | \since 6.6 |
1731 | \overload |
1732 | |
1733 | Sets the extra settings for the child process on Unix systems to \a |
1734 | flagsOnly. This is the same as the overload with just the \c flags field |
1735 | set. |
1736 | \note This function is only available on Unix platforms. |
1737 | |
1738 | \sa unixProcessParameters(), setChildProcessModifier() |
1739 | */ |
1740 | void QProcess::setUnixProcessParameters(UnixProcessFlags flagsOnly) |
1741 | { |
1742 | Q_D(QProcess); |
1743 | if (!d->unixExtras) |
1744 | d->unixExtras.reset(p: new QProcessPrivate::UnixExtras); |
1745 | d->unixExtras->processParameters = { .flags: flagsOnly }; |
1746 | } |
1747 | #endif |
1748 | |
1749 | /*! |
1750 | If QProcess has been assigned a working directory, this function returns |
1751 | the working directory that the QProcess will enter before the program has |
1752 | started. Otherwise, (i.e., no directory has been assigned,) an empty |
1753 | string is returned, and QProcess will use the application's current |
1754 | working directory instead. |
1755 | |
1756 | \sa setWorkingDirectory() |
1757 | */ |
1758 | QString QProcess::workingDirectory() const |
1759 | { |
1760 | Q_D(const QProcess); |
1761 | return d->workingDirectory; |
1762 | } |
1763 | |
1764 | /*! |
1765 | Sets the working directory to \a dir. QProcess will start the |
1766 | process in this directory. The default behavior is to start the |
1767 | process in the working directory of the calling process. |
1768 | |
1769 | \sa workingDirectory(), start() |
1770 | */ |
1771 | void QProcess::setWorkingDirectory(const QString &dir) |
1772 | { |
1773 | Q_D(QProcess); |
1774 | d->workingDirectory = dir; |
1775 | } |
1776 | |
1777 | /*! |
1778 | \since 5.3 |
1779 | |
1780 | Returns the native process identifier for the running process, if |
1781 | available. If no process is currently running, \c 0 is returned. |
1782 | */ |
1783 | qint64 QProcess::processId() const |
1784 | { |
1785 | Q_D(const QProcess); |
1786 | #ifdef Q_OS_WIN |
1787 | return d->pid ? d->pid->dwProcessId : 0; |
1788 | #else |
1789 | return d->pid; |
1790 | #endif |
1791 | } |
1792 | |
1793 | /*! |
1794 | Closes all communication with the process and kills it. After calling this |
1795 | function, QProcess will no longer emit readyRead(), and data can no |
1796 | longer be read or written. |
1797 | */ |
1798 | void QProcess::close() |
1799 | { |
1800 | Q_D(QProcess); |
1801 | emit aboutToClose(); |
1802 | while (waitForBytesWritten(msecs: -1)) |
1803 | ; |
1804 | kill(); |
1805 | waitForFinished(msecs: -1); |
1806 | d->setWriteChannelCount(0); |
1807 | QIODevice::close(); |
1808 | } |
1809 | |
1810 | /*! \reimp |
1811 | */ |
1812 | bool QProcess::isSequential() const |
1813 | { |
1814 | return true; |
1815 | } |
1816 | |
1817 | /*! \reimp |
1818 | */ |
1819 | qint64 QProcess::bytesToWrite() const |
1820 | { |
1821 | #ifdef Q_OS_WIN |
1822 | return d_func()->pipeWriterBytesToWrite(); |
1823 | #else |
1824 | return QIODevice::bytesToWrite(); |
1825 | #endif |
1826 | } |
1827 | |
1828 | /*! |
1829 | Returns the type of error that occurred last. |
1830 | |
1831 | \sa state() |
1832 | */ |
1833 | QProcess::ProcessError QProcess::error() const |
1834 | { |
1835 | Q_D(const QProcess); |
1836 | return ProcessError(d->processError); |
1837 | } |
1838 | |
1839 | /*! |
1840 | Returns the current state of the process. |
1841 | |
1842 | \sa stateChanged(), error() |
1843 | */ |
1844 | QProcess::ProcessState QProcess::state() const |
1845 | { |
1846 | Q_D(const QProcess); |
1847 | return ProcessState(d->processState); |
1848 | } |
1849 | |
1850 | /*! |
1851 | \deprecated |
1852 | Sets the environment that QProcess will pass to the child process. |
1853 | The parameter \a environment is a list of key=value pairs. |
1854 | |
1855 | For example, the following code adds the environment variable \c{TMPDIR}: |
1856 | |
1857 | \snippet qprocess-environment/main.cpp 0 |
1858 | |
1859 | \note This function is less efficient than the setProcessEnvironment() |
1860 | function. |
1861 | |
1862 | \sa environment(), setProcessEnvironment(), systemEnvironment() |
1863 | */ |
1864 | void QProcess::setEnvironment(const QStringList &environment) |
1865 | { |
1866 | setProcessEnvironment(QProcessEnvironmentPrivate::fromList(list: environment)); |
1867 | } |
1868 | |
1869 | /*! |
1870 | \deprecated |
1871 | Returns the environment that QProcess will pass to its child |
1872 | process, or an empty QStringList if no environment has been set |
1873 | using setEnvironment(). If no environment has been set, the |
1874 | environment of the calling process will be used. |
1875 | |
1876 | \sa processEnvironment(), setEnvironment(), systemEnvironment() |
1877 | */ |
1878 | QStringList QProcess::environment() const |
1879 | { |
1880 | Q_D(const QProcess); |
1881 | return d->environment.toStringList(); |
1882 | } |
1883 | |
1884 | /*! |
1885 | \since 4.6 |
1886 | Sets the \a environment that QProcess will pass to the child process. |
1887 | |
1888 | For example, the following code adds the environment variable \c{TMPDIR}: |
1889 | |
1890 | \snippet qprocess-environment/main.cpp 1 |
1891 | |
1892 | Note how, on Windows, environment variable names are case-insensitive. |
1893 | |
1894 | \sa processEnvironment(), QProcessEnvironment::systemEnvironment(), |
1895 | {Environment variables} |
1896 | */ |
1897 | void QProcess::setProcessEnvironment(const QProcessEnvironment &environment) |
1898 | { |
1899 | Q_D(QProcess); |
1900 | d->environment = environment; |
1901 | } |
1902 | |
1903 | /*! |
1904 | \since 4.6 |
1905 | Returns the environment that QProcess will pass to its child process. If no |
1906 | environment has been set using setProcessEnvironment(), this method returns |
1907 | an object indicating the environment will be inherited from the parent. |
1908 | |
1909 | \sa setProcessEnvironment(), QProcessEnvironment::inheritsFromParent(), |
1910 | {Environment variables} |
1911 | */ |
1912 | QProcessEnvironment QProcess::processEnvironment() const |
1913 | { |
1914 | Q_D(const QProcess); |
1915 | return d->environment; |
1916 | } |
1917 | |
1918 | /*! |
1919 | Blocks until the process has started and the started() signal has |
1920 | been emitted, or until \a msecs milliseconds have passed. |
1921 | |
1922 | Returns \c true if the process was started successfully; otherwise |
1923 | returns \c false (if the operation timed out or if an error |
1924 | occurred). |
1925 | |
1926 | This function can operate without an event loop. It is |
1927 | useful when writing non-GUI applications and when performing |
1928 | I/O operations in a non-GUI thread. |
1929 | |
1930 | \warning Calling this function from the main (GUI) thread |
1931 | might cause your user interface to freeze. |
1932 | |
1933 | If msecs is -1, this function will not time out. |
1934 | |
1935 | \note On some UNIX operating systems, this function may return true but |
1936 | the process may later report a QProcess::FailedToStart error. |
1937 | |
1938 | \sa started(), waitForReadyRead(), waitForBytesWritten(), waitForFinished() |
1939 | */ |
1940 | bool QProcess::waitForStarted(int msecs) |
1941 | { |
1942 | Q_D(QProcess); |
1943 | if (d->processState == QProcess::Starting) |
1944 | return d->waitForStarted(deadline: QDeadlineTimer(msecs)); |
1945 | |
1946 | return d->processState == QProcess::Running; |
1947 | } |
1948 | |
1949 | /*! \reimp |
1950 | */ |
1951 | bool QProcess::waitForReadyRead(int msecs) |
1952 | { |
1953 | Q_D(QProcess); |
1954 | |
1955 | if (d->processState == QProcess::NotRunning) |
1956 | return false; |
1957 | if (d->currentReadChannel == QProcess::StandardOutput && d->stdoutChannel.closed) |
1958 | return false; |
1959 | if (d->currentReadChannel == QProcess::StandardError && d->stderrChannel.closed) |
1960 | return false; |
1961 | |
1962 | QDeadlineTimer deadline(msecs); |
1963 | if (d->processState == QProcess::Starting) { |
1964 | bool started = d->waitForStarted(deadline); |
1965 | if (!started) |
1966 | return false; |
1967 | } |
1968 | |
1969 | return d->waitForReadyRead(deadline); |
1970 | } |
1971 | |
1972 | /*! \reimp |
1973 | */ |
1974 | bool QProcess::waitForBytesWritten(int msecs) |
1975 | { |
1976 | Q_D(QProcess); |
1977 | if (d->processState == QProcess::NotRunning) |
1978 | return false; |
1979 | |
1980 | QDeadlineTimer deadline(msecs); |
1981 | if (d->processState == QProcess::Starting) { |
1982 | bool started = d->waitForStarted(deadline); |
1983 | if (!started) |
1984 | return false; |
1985 | } |
1986 | |
1987 | return d->waitForBytesWritten(deadline); |
1988 | } |
1989 | |
1990 | /*! |
1991 | Blocks until the process has finished and the finished() signal |
1992 | has been emitted, or until \a msecs milliseconds have passed. |
1993 | |
1994 | Returns \c true if the process finished; otherwise returns \c false (if |
1995 | the operation timed out, if an error occurred, or if this QProcess |
1996 | is already finished). |
1997 | |
1998 | This function can operate without an event loop. It is |
1999 | useful when writing non-GUI applications and when performing |
2000 | I/O operations in a non-GUI thread. |
2001 | |
2002 | \warning Calling this function from the main (GUI) thread |
2003 | might cause your user interface to freeze. |
2004 | |
2005 | If msecs is -1, this function will not time out. |
2006 | |
2007 | \sa finished(), waitForStarted(), waitForReadyRead(), waitForBytesWritten() |
2008 | */ |
2009 | bool QProcess::waitForFinished(int msecs) |
2010 | { |
2011 | Q_D(QProcess); |
2012 | if (d->processState == QProcess::NotRunning) |
2013 | return false; |
2014 | |
2015 | QDeadlineTimer deadline(msecs); |
2016 | if (d->processState == QProcess::Starting) { |
2017 | bool started = d->waitForStarted(deadline); |
2018 | if (!started) |
2019 | return false; |
2020 | } |
2021 | |
2022 | return d->waitForFinished(deadline); |
2023 | } |
2024 | |
2025 | /*! |
2026 | Sets the current state of the QProcess to the \a state specified. |
2027 | |
2028 | \sa state() |
2029 | */ |
2030 | void QProcess::setProcessState(ProcessState state) |
2031 | { |
2032 | Q_D(QProcess); |
2033 | if (d->processState == state) |
2034 | return; |
2035 | d->processState = state; |
2036 | emit stateChanged(state, QPrivateSignal()); |
2037 | } |
2038 | |
2039 | #if QT_VERSION < QT_VERSION_CHECK(7,0,0) |
2040 | /*! |
2041 | \internal |
2042 | */ |
2043 | auto QProcess::setupChildProcess() -> Use_setChildProcessModifier_Instead |
2044 | { |
2045 | Q_UNREACHABLE_RETURN({}); |
2046 | } |
2047 | #endif |
2048 | |
2049 | /*! \reimp |
2050 | */ |
2051 | qint64 QProcess::readData(char *data, qint64 maxlen) |
2052 | { |
2053 | Q_D(QProcess); |
2054 | Q_UNUSED(data); |
2055 | if (!maxlen) |
2056 | return 0; |
2057 | if (d->processState == QProcess::NotRunning) |
2058 | return -1; // EOF |
2059 | return 0; |
2060 | } |
2061 | |
2062 | /*! |
2063 | Regardless of the current read channel, this function returns all |
2064 | data available from the standard output of the process as a |
2065 | QByteArray. |
2066 | |
2067 | \sa readyReadStandardOutput(), readAllStandardError(), readChannel(), setReadChannel() |
2068 | */ |
2069 | QByteArray QProcess::readAllStandardOutput() |
2070 | { |
2071 | ProcessChannel tmp = readChannel(); |
2072 | setReadChannel(StandardOutput); |
2073 | QByteArray data = readAll(); |
2074 | setReadChannel(tmp); |
2075 | return data; |
2076 | } |
2077 | |
2078 | /*! |
2079 | Regardless of the current read channel, this function returns all |
2080 | data available from the standard error of the process as a |
2081 | QByteArray. |
2082 | |
2083 | \sa readyReadStandardError(), readAllStandardOutput(), readChannel(), setReadChannel() |
2084 | */ |
2085 | QByteArray QProcess::readAllStandardError() |
2086 | { |
2087 | Q_D(QProcess); |
2088 | QByteArray data; |
2089 | if (d->processChannelMode == MergedChannels) { |
2090 | qWarning(msg: "QProcess::readAllStandardError: Called with MergedChannels" ); |
2091 | } else { |
2092 | ProcessChannel tmp = readChannel(); |
2093 | setReadChannel(StandardError); |
2094 | data = readAll(); |
2095 | setReadChannel(tmp); |
2096 | } |
2097 | return data; |
2098 | } |
2099 | |
2100 | /*! |
2101 | Starts the given \a program in a new process, passing the command line |
2102 | arguments in \a arguments. See setProgram() for information about how |
2103 | QProcess searches for the executable to be run. |
2104 | |
2105 | The QProcess object will immediately enter the Starting state. If the |
2106 | process starts successfully, QProcess will emit started(); otherwise, |
2107 | errorOccurred() will be emitted. |
2108 | |
2109 | \note Processes are started asynchronously, which means the started() |
2110 | and errorOccurred() signals may be delayed. Call waitForStarted() to make |
2111 | sure the process has started (or has failed to start) and those signals |
2112 | have been emitted. |
2113 | |
2114 | \note No further splitting of the arguments is performed. |
2115 | |
2116 | \b{Windows:} The arguments are quoted and joined into a command line |
2117 | that is compatible with the \c CommandLineToArgvW() Windows function. |
2118 | For programs that have different command line quoting requirements, |
2119 | you need to use setNativeArguments(). One notable program that does |
2120 | not follow the \c CommandLineToArgvW() rules is cmd.exe and, by |
2121 | consequence, all batch scripts. |
2122 | |
2123 | The OpenMode is set to \a mode. |
2124 | |
2125 | If the QProcess object is already running a process, a warning may be |
2126 | printed at the console, and the existing process will continue running |
2127 | unaffected. |
2128 | |
2129 | \sa processId(), started(), waitForStarted(), setNativeArguments() |
2130 | */ |
2131 | void QProcess::start(const QString &program, const QStringList &arguments, OpenMode mode) |
2132 | { |
2133 | Q_D(QProcess); |
2134 | if (d->processState != NotRunning) { |
2135 | qWarning(msg: "QProcess::start: Process is already running" ); |
2136 | return; |
2137 | } |
2138 | if (program.isEmpty()) { |
2139 | d->setErrorAndEmit(error: QProcess::FailedToStart, description: tr(s: "No program defined" )); |
2140 | return; |
2141 | } |
2142 | |
2143 | d->program = program; |
2144 | d->arguments = arguments; |
2145 | |
2146 | d->start(mode); |
2147 | } |
2148 | |
2149 | /*! |
2150 | \since 5.1 |
2151 | \overload |
2152 | |
2153 | Starts the program set by setProgram() with arguments set by setArguments(). |
2154 | The OpenMode is set to \a mode. |
2155 | |
2156 | \sa open(), setProgram(), setArguments() |
2157 | */ |
2158 | void QProcess::start(OpenMode mode) |
2159 | { |
2160 | Q_D(QProcess); |
2161 | if (d->processState != NotRunning) { |
2162 | qWarning(msg: "QProcess::start: Process is already running" ); |
2163 | return; |
2164 | } |
2165 | if (d->program.isEmpty()) { |
2166 | d->setErrorAndEmit(error: QProcess::FailedToStart, description: tr(s: "No program defined" )); |
2167 | return; |
2168 | } |
2169 | |
2170 | d->start(mode); |
2171 | } |
2172 | |
2173 | /*! |
2174 | \since 6.0 |
2175 | |
2176 | Starts the command \a command in a new process. |
2177 | The OpenMode is set to \a mode. |
2178 | |
2179 | \a command is a single string of text containing both the program name |
2180 | and its arguments. The arguments are separated by one or more spaces. |
2181 | For example: |
2182 | |
2183 | \snippet code/src_corelib_io_qprocess.cpp 5 |
2184 | |
2185 | Arguments containing spaces must be quoted to be correctly supplied to |
2186 | the new process. For example: |
2187 | |
2188 | \snippet code/src_corelib_io_qprocess.cpp 6 |
2189 | |
2190 | Literal quotes in the \a command string are represented by triple quotes. |
2191 | For example: |
2192 | |
2193 | \snippet code/src_corelib_io_qprocess.cpp 7 |
2194 | |
2195 | After the \a command string has been split and unquoted, this function |
2196 | behaves like start(). |
2197 | |
2198 | On operating systems where the system API for passing command line |
2199 | arguments to a subprocess natively uses a single string (Windows), one can |
2200 | conceive command lines which cannot be passed via QProcess's portable |
2201 | list-based API. In these rare cases you need to use setProgram() and |
2202 | setNativeArguments() instead of this function. |
2203 | |
2204 | \sa splitCommand() |
2205 | \sa start() |
2206 | */ |
2207 | void QProcess::startCommand(const QString &command, OpenMode mode) |
2208 | { |
2209 | QStringList args = splitCommand(command); |
2210 | const QString program = args.takeFirst(); |
2211 | start(program, arguments: args, mode); |
2212 | } |
2213 | |
2214 | /*! |
2215 | \since 5.10 |
2216 | |
2217 | Starts the program set by setProgram() with arguments set by setArguments() |
2218 | in a new process, and detaches from it. Returns \c true on success; |
2219 | otherwise returns \c false. If the calling process exits, the |
2220 | detached process will continue to run unaffected. |
2221 | |
2222 | \b{Unix:} The started process will run in its own session and act |
2223 | like a daemon. |
2224 | |
2225 | The process will be started in the directory set by setWorkingDirectory(). |
2226 | If workingDirectory() is empty, the working directory is inherited |
2227 | from the calling process. |
2228 | |
2229 | If the function is successful then *\a pid is set to the process identifier |
2230 | of the started process; otherwise, it's set to -1. Note that the child |
2231 | process may exit and the PID may become invalid without notice. |
2232 | Furthermore, after the child process exits, the same PID may be recycled |
2233 | and used by a completely different process. User code should be careful |
2234 | when using this variable, especially if one intends to forcibly terminate |
2235 | the process by operating system means. |
2236 | |
2237 | Only the following property setters are supported by startDetached(): |
2238 | \list |
2239 | \li setArguments() |
2240 | \li setCreateProcessArgumentsModifier() |
2241 | \li setNativeArguments() |
2242 | \li setProcessEnvironment() |
2243 | \li setProgram() |
2244 | \li setStandardErrorFile() |
2245 | \li setStandardInputFile() |
2246 | \li setStandardOutputFile() |
2247 | \li setProcessChannelMode(QProcess::MergedChannels) |
2248 | \li setStandardOutputProcess() |
2249 | \li setWorkingDirectory() |
2250 | \endlist |
2251 | All other properties of the QProcess object are ignored. |
2252 | |
2253 | \note The called process inherits the console window of the calling |
2254 | process. To suppress console output, redirect standard/error output to |
2255 | QProcess::nullDevice(). |
2256 | |
2257 | \sa start() |
2258 | \sa startDetached(const QString &program, const QStringList &arguments, |
2259 | const QString &workingDirectory, qint64 *pid) |
2260 | */ |
2261 | bool QProcess::startDetached(qint64 *pid) |
2262 | { |
2263 | Q_D(QProcess); |
2264 | if (d->processState != NotRunning) { |
2265 | qWarning(msg: "QProcess::startDetached: Process is already running" ); |
2266 | return false; |
2267 | } |
2268 | if (d->program.isEmpty()) { |
2269 | d->setErrorAndEmit(error: QProcess::FailedToStart, description: tr(s: "No program defined" )); |
2270 | return false; |
2271 | } |
2272 | return d->startDetached(pPid: pid); |
2273 | } |
2274 | |
2275 | /*! |
2276 | Starts the program set by setProgram() with arguments set by setArguments(). |
2277 | The OpenMode is set to \a mode. |
2278 | |
2279 | This method is an alias for start(), and exists only to fully implement |
2280 | the interface defined by QIODevice. |
2281 | |
2282 | Returns \c true if the program has been started. |
2283 | |
2284 | \sa start(), setProgram(), setArguments() |
2285 | */ |
2286 | bool QProcess::open(OpenMode mode) |
2287 | { |
2288 | Q_D(QProcess); |
2289 | if (d->processState != NotRunning) { |
2290 | qWarning(msg: "QProcess::start: Process is already running" ); |
2291 | return false; |
2292 | } |
2293 | if (d->program.isEmpty()) { |
2294 | qWarning(msg: "QProcess::start: program not set" ); |
2295 | return false; |
2296 | } |
2297 | |
2298 | d->start(mode); |
2299 | return true; |
2300 | } |
2301 | |
2302 | void QProcessPrivate::start(QIODevice::OpenMode mode) |
2303 | { |
2304 | Q_Q(QProcess); |
2305 | #if defined QPROCESS_DEBUG |
2306 | qDebug() << "QProcess::start(" << program << ',' << arguments << ',' << mode << ')'; |
2307 | #endif |
2308 | |
2309 | if (stdinChannel.type != QProcessPrivate::Channel::Normal) |
2310 | mode &= ~QIODevice::WriteOnly; // not open for writing |
2311 | if (stdoutChannel.type != QProcessPrivate::Channel::Normal && |
2312 | (stderrChannel.type != QProcessPrivate::Channel::Normal || |
2313 | processChannelMode == QProcess::MergedChannels)) |
2314 | mode &= ~QIODevice::ReadOnly; // not open for reading |
2315 | if (mode == 0) |
2316 | mode = QIODevice::Unbuffered; |
2317 | if ((mode & QIODevice::ReadOnly) == 0) { |
2318 | if (stdoutChannel.type == QProcessPrivate::Channel::Normal) |
2319 | q->setStandardOutputFile(fileName: q->nullDevice()); |
2320 | if (stderrChannel.type == QProcessPrivate::Channel::Normal |
2321 | && processChannelMode != QProcess::MergedChannels) |
2322 | q->setStandardErrorFile(fileName: q->nullDevice()); |
2323 | } |
2324 | |
2325 | q->QIODevice::open(mode); |
2326 | |
2327 | if (q->isReadable() && processChannelMode != QProcess::MergedChannels) |
2328 | setReadChannelCount(2); |
2329 | |
2330 | stdinChannel.closed = false; |
2331 | stdoutChannel.closed = false; |
2332 | stderrChannel.closed = false; |
2333 | |
2334 | exitCode = 0; |
2335 | exitStatus = QProcess::NormalExit; |
2336 | processError = QProcess::UnknownError; |
2337 | errorString.clear(); |
2338 | startProcess(); |
2339 | } |
2340 | |
2341 | /*! |
2342 | \since 5.15 |
2343 | |
2344 | Splits the string \a command into a list of tokens, and returns |
2345 | the list. |
2346 | |
2347 | Tokens with spaces can be surrounded by double quotes; three |
2348 | consecutive double quotes represent the quote character itself. |
2349 | */ |
2350 | QStringList QProcess::splitCommand(QStringView command) |
2351 | { |
2352 | QStringList args; |
2353 | QString tmp; |
2354 | int quoteCount = 0; |
2355 | bool inQuote = false; |
2356 | |
2357 | // handle quoting. tokens can be surrounded by double quotes |
2358 | // "hello world". three consecutive double quotes represent |
2359 | // the quote character itself. |
2360 | for (int i = 0; i < command.size(); ++i) { |
2361 | if (command.at(n: i) == u'"') { |
2362 | ++quoteCount; |
2363 | if (quoteCount == 3) { |
2364 | // third consecutive quote |
2365 | quoteCount = 0; |
2366 | tmp += command.at(n: i); |
2367 | } |
2368 | continue; |
2369 | } |
2370 | if (quoteCount) { |
2371 | if (quoteCount == 1) |
2372 | inQuote = !inQuote; |
2373 | quoteCount = 0; |
2374 | } |
2375 | if (!inQuote && command.at(n: i).isSpace()) { |
2376 | if (!tmp.isEmpty()) { |
2377 | args += tmp; |
2378 | tmp.clear(); |
2379 | } |
2380 | } else { |
2381 | tmp += command.at(n: i); |
2382 | } |
2383 | } |
2384 | if (!tmp.isEmpty()) |
2385 | args += tmp; |
2386 | |
2387 | return args; |
2388 | } |
2389 | |
2390 | /*! |
2391 | \since 5.0 |
2392 | |
2393 | Returns the program the process was last started with. |
2394 | |
2395 | \sa start() |
2396 | */ |
2397 | QString QProcess::program() const |
2398 | { |
2399 | Q_D(const QProcess); |
2400 | return d->program; |
2401 | } |
2402 | |
2403 | /*! |
2404 | \since 5.1 |
2405 | |
2406 | Set the \a program to use when starting the process. |
2407 | This function must be called before start(). |
2408 | |
2409 | If \a program is an absolute path, it specifies the exact executable that |
2410 | will be launched. Relative paths will be resolved in a platform-specific |
2411 | manner, which includes searching the \c PATH environment variable (see |
2412 | \l{Finding the Executable} for details). |
2413 | |
2414 | \sa start(), setArguments(), program(), QStandardPaths::findExecutable() |
2415 | */ |
2416 | void QProcess::setProgram(const QString &program) |
2417 | { |
2418 | Q_D(QProcess); |
2419 | if (d->processState != NotRunning) { |
2420 | qWarning(msg: "QProcess::setProgram: Process is already running" ); |
2421 | return; |
2422 | } |
2423 | d->program = program; |
2424 | } |
2425 | |
2426 | /*! |
2427 | \since 5.0 |
2428 | |
2429 | Returns the command line arguments the process was last started with. |
2430 | |
2431 | \sa start() |
2432 | */ |
2433 | QStringList QProcess::arguments() const |
2434 | { |
2435 | Q_D(const QProcess); |
2436 | return d->arguments; |
2437 | } |
2438 | |
2439 | /*! |
2440 | \since 5.1 |
2441 | |
2442 | Set the \a arguments to pass to the called program when starting the process. |
2443 | This function must be called before start(). |
2444 | |
2445 | \sa start(), setProgram(), arguments() |
2446 | */ |
2447 | void QProcess::setArguments(const QStringList &arguments) |
2448 | { |
2449 | Q_D(QProcess); |
2450 | if (d->processState != NotRunning) { |
2451 | qWarning(msg: "QProcess::setProgram: Process is already running" ); |
2452 | return; |
2453 | } |
2454 | d->arguments = arguments; |
2455 | } |
2456 | |
2457 | /*! |
2458 | Attempts to terminate the process. |
2459 | |
2460 | The process may not exit as a result of calling this function (it is given |
2461 | the chance to prompt the user for any unsaved files, etc). |
2462 | |
2463 | On Windows, terminate() posts a WM_CLOSE message to all top-level windows |
2464 | of the process and then to the main thread of the process itself. On Unix |
2465 | and \macos the \c SIGTERM signal is sent. |
2466 | |
2467 | Console applications on Windows that do not run an event loop, or whose |
2468 | event loop does not handle the WM_CLOSE message, can only be terminated by |
2469 | calling kill(). |
2470 | |
2471 | \sa kill() |
2472 | */ |
2473 | void QProcess::terminate() |
2474 | { |
2475 | Q_D(QProcess); |
2476 | d->terminateProcess(); |
2477 | } |
2478 | |
2479 | /*! |
2480 | Kills the current process, causing it to exit immediately. |
2481 | |
2482 | On Windows, kill() uses TerminateProcess, and on Unix and \macos, the |
2483 | SIGKILL signal is sent to the process. |
2484 | |
2485 | \sa terminate() |
2486 | */ |
2487 | void QProcess::kill() |
2488 | { |
2489 | Q_D(QProcess); |
2490 | d->killProcess(); |
2491 | } |
2492 | |
2493 | /*! |
2494 | Returns the exit code of the last process that finished. |
2495 | |
2496 | This value is not valid unless exitStatus() returns NormalExit. |
2497 | */ |
2498 | int QProcess::exitCode() const |
2499 | { |
2500 | Q_D(const QProcess); |
2501 | return d->exitCode; |
2502 | } |
2503 | |
2504 | /*! |
2505 | \since 4.1 |
2506 | |
2507 | Returns the exit status of the last process that finished. |
2508 | |
2509 | On Windows, if the process was terminated with TerminateProcess() from |
2510 | another application, this function will still return NormalExit |
2511 | unless the exit code is less than 0. |
2512 | */ |
2513 | QProcess::ExitStatus QProcess::exitStatus() const |
2514 | { |
2515 | Q_D(const QProcess); |
2516 | return ExitStatus(d->exitStatus); |
2517 | } |
2518 | |
2519 | /*! |
2520 | Starts the program \a program with the arguments \a arguments in a |
2521 | new process, waits for it to finish, and then returns the exit |
2522 | code of the process. Any data the new process writes to the |
2523 | console is forwarded to the calling process. |
2524 | |
2525 | The environment and working directory are inherited from the calling |
2526 | process. |
2527 | |
2528 | Argument handling is identical to the respective start() overload. |
2529 | |
2530 | If the process cannot be started, -2 is returned. If the process |
2531 | crashes, -1 is returned. Otherwise, the process' exit code is |
2532 | returned. |
2533 | |
2534 | \sa start() |
2535 | */ |
2536 | int QProcess::execute(const QString &program, const QStringList &arguments) |
2537 | { |
2538 | QProcess process; |
2539 | process.setProcessChannelMode(ForwardedChannels); |
2540 | process.start(program, arguments); |
2541 | if (!process.waitForFinished(msecs: -1) || process.error() == FailedToStart) |
2542 | return -2; |
2543 | return process.exitStatus() == QProcess::NormalExit ? process.exitCode() : -1; |
2544 | } |
2545 | |
2546 | /*! |
2547 | \overload startDetached() |
2548 | |
2549 | Starts the program \a program with the arguments \a arguments in a |
2550 | new process, and detaches from it. Returns \c true on success; |
2551 | otherwise returns \c false. If the calling process exits, the |
2552 | detached process will continue to run unaffected. |
2553 | |
2554 | Argument handling is identical to the respective start() overload. |
2555 | |
2556 | The process will be started in the directory \a workingDirectory. |
2557 | If \a workingDirectory is empty, the working directory is inherited |
2558 | from the calling process. |
2559 | |
2560 | If the function is successful then *\a pid is set to the process |
2561 | identifier of the started process. |
2562 | |
2563 | \sa start() |
2564 | */ |
2565 | bool QProcess::startDetached(const QString &program, |
2566 | const QStringList &arguments, |
2567 | const QString &workingDirectory, |
2568 | qint64 *pid) |
2569 | { |
2570 | QProcess process; |
2571 | process.setProgram(program); |
2572 | process.setArguments(arguments); |
2573 | process.setWorkingDirectory(workingDirectory); |
2574 | return process.startDetached(pid); |
2575 | } |
2576 | |
2577 | /*! |
2578 | \since 4.1 |
2579 | |
2580 | Returns the environment of the calling process as a list of |
2581 | key=value pairs. Example: |
2582 | |
2583 | \snippet code/src_corelib_io_qprocess.cpp 8 |
2584 | |
2585 | This function does not cache the system environment. Therefore, it's |
2586 | possible to obtain an updated version of the environment if low-level C |
2587 | library functions like \tt setenv or \tt putenv have been called. |
2588 | |
2589 | However, note that repeated calls to this function will recreate the |
2590 | list of environment variables, which is a non-trivial operation. |
2591 | |
2592 | \note For new code, it is recommended to use QProcessEnvironment::systemEnvironment() |
2593 | |
2594 | \sa QProcessEnvironment::systemEnvironment(), setProcessEnvironment() |
2595 | */ |
2596 | QStringList QProcess::systemEnvironment() |
2597 | { |
2598 | return QProcessEnvironment::systemEnvironment().toStringList(); |
2599 | } |
2600 | |
2601 | /*! |
2602 | \fn QProcessEnvironment QProcessEnvironment::systemEnvironment() |
2603 | |
2604 | \since 4.6 |
2605 | |
2606 | \brief The systemEnvironment function returns the environment of |
2607 | the calling process. |
2608 | |
2609 | It is returned as a QProcessEnvironment. This function does not |
2610 | cache the system environment. Therefore, it's possible to obtain |
2611 | an updated version of the environment if low-level C library |
2612 | functions like \tt setenv or \tt putenv have been called. |
2613 | |
2614 | However, note that repeated calls to this function will recreate the |
2615 | QProcessEnvironment object, which is a non-trivial operation. |
2616 | |
2617 | \sa QProcess::systemEnvironment() |
2618 | */ |
2619 | |
2620 | /*! |
2621 | \since 5.2 |
2622 | |
2623 | \brief The null device of the operating system. |
2624 | |
2625 | The returned file path uses native directory separators. |
2626 | |
2627 | \sa QProcess::setStandardInputFile(), QProcess::setStandardOutputFile(), |
2628 | QProcess::setStandardErrorFile() |
2629 | */ |
2630 | QString QProcess::nullDevice() |
2631 | { |
2632 | #ifdef Q_OS_WIN |
2633 | return QStringLiteral("\\\\.\\NUL" ); |
2634 | #elif defined(_PATH_DEVNULL) |
2635 | return QStringLiteral(_PATH_DEVNULL); |
2636 | #else |
2637 | return QStringLiteral("/dev/null" ); |
2638 | #endif |
2639 | } |
2640 | |
2641 | #endif // QT_CONFIG(process) |
2642 | |
2643 | QT_END_NAMESPACE |
2644 | |
2645 | #include "moc_qprocess.cpp" |
2646 | |