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

source code of qtbase/src/corelib/io/qprocess.h