1 | // Copyright (C) 2016 The Qt Company Ltd. |
2 | // Copyright (C) 2023 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 | #ifndef QPROCESS_H |
6 | #define QPROCESS_H |
7 | |
8 | #include <QtCore/qcompare.h> |
9 | #include <QtCore/qiodevice.h> |
10 | #include <QtCore/qstringlist.h> |
11 | #include <QtCore/qshareddata.h> |
12 | |
13 | #include <functional> |
14 | |
15 | QT_REQUIRE_CONFIG(processenvironment); |
16 | |
17 | #if defined(Q_OS_WIN) || defined(Q_QDOC) |
18 | struct _PROCESS_INFORMATION; |
19 | struct _SECURITY_ATTRIBUTES; |
20 | struct _STARTUPINFOW; |
21 | using Q_PROCESS_INFORMATION = _PROCESS_INFORMATION; |
22 | using Q_SECURITY_ATTRIBUTES = _SECURITY_ATTRIBUTES; |
23 | using Q_STARTUPINFO = _STARTUPINFOW; |
24 | #endif |
25 | |
26 | QT_BEGIN_NAMESPACE |
27 | |
28 | class QProcessPrivate; |
29 | class QProcessEnvironmentPrivate; |
30 | |
31 | class Q_CORE_EXPORT QProcessEnvironment |
32 | { |
33 | public: |
34 | enum Initialization { InheritFromParent }; |
35 | |
36 | QProcessEnvironment(); |
37 | QProcessEnvironment(Initialization) noexcept; |
38 | QProcessEnvironment(const QProcessEnvironment &other); |
39 | ~QProcessEnvironment(); |
40 | QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QProcessEnvironment) |
41 | QProcessEnvironment &operator=(const QProcessEnvironment &other); |
42 | |
43 | void swap(QProcessEnvironment &other) noexcept { d.swap(other&: other.d); } |
44 | |
45 | #if QT_CORE_REMOVED_SINCE(6, 8) |
46 | bool operator==(const QProcessEnvironment &other) const; |
47 | inline bool operator!=(const QProcessEnvironment &other) const |
48 | { return !operator==(other); } |
49 | #endif |
50 | |
51 | bool isEmpty() const; |
52 | [[nodiscard]] bool inheritsFromParent() const; |
53 | void clear(); |
54 | |
55 | bool contains(const QString &name) const; |
56 | void insert(const QString &name, const QString &value); |
57 | void remove(const QString &name); |
58 | QString value(const QString &name, const QString &defaultValue = QString()) const; |
59 | |
60 | QStringList toStringList() const; |
61 | |
62 | QStringList keys() const; |
63 | |
64 | void insert(const QProcessEnvironment &e); |
65 | |
66 | static QProcessEnvironment systemEnvironment(); |
67 | |
68 | private: |
69 | friend Q_CORE_EXPORT bool comparesEqual(const QProcessEnvironment &lhs, |
70 | const QProcessEnvironment &rhs); |
71 | Q_DECLARE_EQUALITY_COMPARABLE_NON_NOEXCEPT(QProcessEnvironment) |
72 | friend class QProcessPrivate; |
73 | friend class QProcessEnvironmentPrivate; |
74 | QSharedDataPointer<QProcessEnvironmentPrivate> d; |
75 | }; |
76 | |
77 | Q_DECLARE_SHARED(QProcessEnvironment) |
78 | |
79 | #if QT_CONFIG(process) |
80 | |
81 | class Q_CORE_EXPORT QProcess : public QIODevice |
82 | { |
83 | Q_OBJECT |
84 | public: |
85 | enum ProcessError { |
86 | FailedToStart, |
87 | Crashed, |
88 | Timedout, |
89 | ReadError, |
90 | WriteError, |
91 | UnknownError |
92 | }; |
93 | Q_ENUM(ProcessError) |
94 | |
95 | enum ProcessState { |
96 | NotRunning, |
97 | Starting, |
98 | Running |
99 | }; |
100 | Q_ENUM(ProcessState) |
101 | |
102 | enum ProcessChannel { |
103 | StandardOutput, |
104 | StandardError |
105 | }; |
106 | Q_ENUM(ProcessChannel) |
107 | |
108 | enum ProcessChannelMode { |
109 | SeparateChannels, |
110 | MergedChannels, |
111 | ForwardedChannels, |
112 | ForwardedOutputChannel, |
113 | ForwardedErrorChannel |
114 | }; |
115 | Q_ENUM(ProcessChannelMode) |
116 | |
117 | enum InputChannelMode { |
118 | ManagedInputChannel, |
119 | ForwardedInputChannel |
120 | }; |
121 | Q_ENUM(InputChannelMode) |
122 | |
123 | enum ExitStatus { |
124 | NormalExit, |
125 | CrashExit |
126 | }; |
127 | Q_ENUM(ExitStatus) |
128 | |
129 | explicit QProcess(QObject *parent = nullptr); |
130 | virtual ~QProcess(); |
131 | |
132 | void start(const QString &program, const QStringList &arguments = {}, OpenMode mode = ReadWrite); |
133 | void start(OpenMode mode = ReadWrite); |
134 | void startCommand(const QString &command, OpenMode mode = ReadWrite); |
135 | bool startDetached(qint64 *pid = nullptr); |
136 | bool open(OpenMode mode = ReadWrite) override; |
137 | |
138 | QString program() const; |
139 | void setProgram(const QString &program); |
140 | |
141 | QStringList arguments() const; |
142 | void setArguments(const QStringList & arguments); |
143 | |
144 | ProcessChannelMode processChannelMode() const; |
145 | void setProcessChannelMode(ProcessChannelMode mode); |
146 | InputChannelMode inputChannelMode() const; |
147 | void setInputChannelMode(InputChannelMode mode); |
148 | |
149 | ProcessChannel readChannel() const; |
150 | void setReadChannel(ProcessChannel channel); |
151 | |
152 | void closeReadChannel(ProcessChannel channel); |
153 | void closeWriteChannel(); |
154 | |
155 | void setStandardInputFile(const QString &fileName); |
156 | void setStandardOutputFile(const QString &fileName, OpenMode mode = Truncate); |
157 | void setStandardErrorFile(const QString &fileName, OpenMode mode = Truncate); |
158 | void setStandardOutputProcess(QProcess *destination); |
159 | |
160 | #if defined(Q_OS_WIN) || defined(Q_QDOC) |
161 | QString nativeArguments() const; |
162 | void setNativeArguments(const QString &arguments); |
163 | struct CreateProcessArguments |
164 | { |
165 | const wchar_t *applicationName; |
166 | wchar_t *arguments; |
167 | Q_SECURITY_ATTRIBUTES *processAttributes; |
168 | Q_SECURITY_ATTRIBUTES *threadAttributes; |
169 | bool inheritHandles; |
170 | unsigned long flags; |
171 | void *environment; |
172 | const wchar_t *currentDirectory; |
173 | Q_STARTUPINFO *startupInfo; |
174 | Q_PROCESS_INFORMATION *processInformation; |
175 | }; |
176 | typedef std::function<void(CreateProcessArguments *)> CreateProcessArgumentModifier; |
177 | CreateProcessArgumentModifier createProcessArgumentsModifier() const; |
178 | void setCreateProcessArgumentsModifier(CreateProcessArgumentModifier modifier); |
179 | #endif // Q_OS_WIN || Q_QDOC |
180 | #if defined(Q_OS_UNIX) || defined(Q_QDOC) |
181 | std::function<void(void)> childProcessModifier() const; |
182 | void setChildProcessModifier(const std::function<void(void)> &modifier); |
183 | Q_NORETURN void failChildProcessModifier(const char *description, int error = 0) noexcept; |
184 | |
185 | enum class UnixProcessFlag : quint32 { |
186 | ResetSignalHandlers = 0x0001, // like POSIX_SPAWN_SETSIGDEF |
187 | IgnoreSigPipe = 0x0002, |
188 | // some room if we want to add IgnoreSigHup or so |
189 | CloseFileDescriptors = 0x0010, |
190 | UseVFork = 0x0020, // like POSIX_SPAWN_USEVFORK |
191 | CreateNewSession = 0x0040, // like POSIX_SPAWN_SETSID |
192 | DisconnectControllingTerminal = 0x0080, |
193 | ResetIds = 0x0100, // like POSIX_SPAWN_RESETIDS |
194 | }; |
195 | Q_DECLARE_FLAGS(UnixProcessFlags, UnixProcessFlag) |
196 | struct UnixProcessParameters |
197 | { |
198 | UnixProcessFlags flags = {}; |
199 | int lowestFileDescriptorToClose = 0; |
200 | |
201 | quint32 _reserved[6] {}; |
202 | }; |
203 | UnixProcessParameters unixProcessParameters() const noexcept; |
204 | void setUnixProcessParameters(const UnixProcessParameters ¶ms); |
205 | void setUnixProcessParameters(UnixProcessFlags flagsOnly); |
206 | #endif |
207 | |
208 | QString workingDirectory() const; |
209 | void setWorkingDirectory(const QString &dir); |
210 | |
211 | void setEnvironment(const QStringList &environment); |
212 | QStringList environment() const; |
213 | void setProcessEnvironment(const QProcessEnvironment &environment); |
214 | QProcessEnvironment processEnvironment() const; |
215 | |
216 | QProcess::ProcessError error() const; |
217 | QProcess::ProcessState state() const; |
218 | |
219 | qint64 processId() const; |
220 | |
221 | bool waitForStarted(int msecs = 30000); |
222 | bool waitForReadyRead(int msecs = 30000) override; |
223 | bool waitForBytesWritten(int msecs = 30000) override; |
224 | bool waitForFinished(int msecs = 30000); |
225 | |
226 | QByteArray readAllStandardOutput(); |
227 | QByteArray readAllStandardError(); |
228 | |
229 | int exitCode() const; |
230 | QProcess::ExitStatus exitStatus() const; |
231 | |
232 | // QIODevice |
233 | qint64 bytesToWrite() const override; |
234 | bool isSequential() const override; |
235 | void close() override; |
236 | |
237 | static int execute(const QString &program, const QStringList &arguments = {}); |
238 | static bool startDetached(const QString &program, const QStringList &arguments = {}, |
239 | const QString &workingDirectory = QString(), qint64 *pid = nullptr); |
240 | |
241 | static QStringList systemEnvironment(); |
242 | |
243 | static QString nullDevice(); |
244 | |
245 | static QStringList splitCommand(QStringView command); |
246 | |
247 | public Q_SLOTS: |
248 | void terminate(); |
249 | void kill(); |
250 | |
251 | Q_SIGNALS: |
252 | void started(QPrivateSignal); |
253 | void finished(int exitCode, QProcess::ExitStatus exitStatus = NormalExit); |
254 | void errorOccurred(QProcess::ProcessError error); |
255 | void stateChanged(QProcess::ProcessState state, QPrivateSignal); |
256 | |
257 | void readyReadStandardOutput(QPrivateSignal); |
258 | void readyReadStandardError(QPrivateSignal); |
259 | |
260 | protected: |
261 | void setProcessState(ProcessState state); |
262 | |
263 | // QIODevice |
264 | qint64 readData(char *data, qint64 maxlen) override; |
265 | qint64 writeData(const char *data, qint64 len) override; |
266 | |
267 | private: |
268 | Q_DECLARE_PRIVATE(QProcess) |
269 | Q_DISABLE_COPY(QProcess) |
270 | |
271 | #if QT_VERSION < QT_VERSION_CHECK(7,0,0) |
272 | // ### Qt7: Remove this struct and the virtual function; they're here only |
273 | // to cause build errors in Qt 5 code that wasn't updated to Qt 6's |
274 | // setChildProcessModifier() |
275 | struct Use_setChildProcessModifier_Instead {}; |
276 | QT_DEPRECATED_X("Use setChildProcessModifier() instead" ) |
277 | virtual Use_setChildProcessModifier_Instead setupChildProcess(); |
278 | #endif |
279 | |
280 | Q_PRIVATE_SLOT(d_func(), bool _q_canReadStandardOutput()) |
281 | Q_PRIVATE_SLOT(d_func(), bool _q_canReadStandardError()) |
282 | #ifdef Q_OS_UNIX |
283 | Q_PRIVATE_SLOT(d_func(), bool _q_canWrite()) |
284 | #endif |
285 | Q_PRIVATE_SLOT(d_func(), bool _q_startupNotification()) |
286 | Q_PRIVATE_SLOT(d_func(), void _q_processDied()) |
287 | }; |
288 | |
289 | #ifdef Q_OS_UNIX |
290 | Q_DECLARE_OPERATORS_FOR_FLAGS(QProcess::UnixProcessFlags) |
291 | #endif |
292 | |
293 | #endif // QT_CONFIG(process) |
294 | |
295 | QT_END_NAMESPACE |
296 | |
297 | #endif // QPROCESS_H |
298 | |