1 /*
2     SPDX-FileCopyrightText: 2009 Nokia Corporation and /or its subsidiary(-ies).
3     Contact: Qt Software Information (qt-info@nokia.com)
4 
5     This file is part of the QtCore module of the Qt Toolkit.
6 
7     $QT_BEGIN_LICENSE:LGPL$
8     Commercial Usage
9     Licensees holding valid Qt Commercial licenses may use this file in
10     accordance with the Qt Commercial License Agreement provided with the
11     Software or, alternatively, in accordance with the terms contained in
12     a written agreement between you and Nokia.
13 
14     GNU Lesser General Public License Usage
15     Alternatively, this file may be used under the terms of the GNU Lesser
16     General Public License version 2.1 as published by the Free Software
17     Foundation and appearing in the file LICENSE.LGPL included in the
18     packaging of this file.  Please review the following information to
19     ensure the GNU Lesser General Public License version 2.1 requirements
20     will be met: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
21 
22     In addition, as a special exception, Nokia gives you certain
23     additional rights. These rights are described in the Nokia Qt LGPL
24     Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
25     package.
26 
27     GNU General Public License Usage
28     Alternatively, this file may be used under the terms of the GNU
29     General Public License version 3.0 as published by the Free Software
30     Foundation and appearing in the file LICENSE.GPL included in the
31     packaging of this file.  Please review the following information to
32     ensure the GNU General Public License version 3.0 requirements will be
33     met: https://www.gnu.org/licenses/gpl-3.0.html.
34 
35     If you are unsure which license is appropriate for your use, please
36     contact the sales department at qt-sales@nokia.com.
37     $QT_END_LICENSE$
38 
39 */
40 
41 #ifndef K3B_QPROCESS_P_H
42 #define K3B_QPROCESS_P_H
43 
44 //
45 //  W A R N I N G
46 //  -------------
47 //
48 // This file is not part of the Qt API.  It exists purely as an
49 // implementation detail.  This header file may change from version to
50 // version without notice, or even be removed.
51 //
52 // We mean it.
53 //
54 
55 #include "k3bqprocess.h"
56 #include <QStringList>
57 //#include "private/qringbuffer_p.h"
58 #include "qringbuffer_p.h"
59 //#include "private/qiodevice_p.h"
60 
61 #ifdef Q_OS_WIN
62 #include "QtCore/qt_windows.h"
63 typedef HANDLE Q_PIPE;
64 #define INVALID_Q_PIPE INVALID_HANDLE_VALUE
65 #else
66 typedef int Q_PIPE;
67 #define INVALID_Q_PIPE -1
68 #endif
69 
70 #ifndef QT_NO_PROCESS
71 
72 //QT_BEGIN_NAMESPACE
73 class QSocketNotifier;
74 class QWindowsPipeWriter;
75 class QWinEventNotifier;
76 class QTimer;
77 
78 
79 class K3bQProcessPrivate
80 {
81 public:
Q_DECLARE_PUBLIC(K3bQProcess)82     Q_DECLARE_PUBLIC(K3bQProcess)
83     K3bQProcess* q_ptr;
84 
85     struct Channel {
86         enum ProcessChannelType {
87             Normal = 0,
88             PipeSource = 1,
89             PipeSink = 2,
90             Redirect = 3
91             // if you add "= 4" here, increase the number of bits below
92         };
93 
94         Channel() : process(0), notifier(0), type(Normal), closed(false), append(false)
95         {
96             pipe[0] = INVALID_Q_PIPE;
97             pipe[1] = INVALID_Q_PIPE;
98         }
99 
100         void clear();
101 
102         Channel &operator=(const QString &fileName)
103         {
104             clear();
105             file = fileName;
106             type = fileName.isEmpty() ? Normal : Redirect;
107             return *this;
108         }
109 
110         void pipeTo(K3bQProcessPrivate *other)
111         {
112             clear();
113             process = other;
114             type = PipeSource;
115         }
116 
117         void pipeFrom(K3bQProcessPrivate *other)
118         {
119             clear();
120             process = other;
121             type = PipeSink;
122         }
123 
124         QString file;
125         K3bQProcessPrivate *process;
126         QSocketNotifier *notifier;
127         Q_PIPE pipe[2];
128 
129         unsigned type : 2;
130         bool closed : 1;
131         bool append : 1;
132     };
133 
134     K3bQProcessPrivate();
135     virtual ~K3bQProcessPrivate();
136 
137     // private slots
138     bool _q_canReadStandardOutput();
139     bool _q_canReadStandardError();
140     bool _q_canWrite();
141     bool _q_startupNotification();
142     bool _q_processDied();
143     bool _q_notifyProcessDied();
144     void _q_notified();
145 
146     ::QProcess::ProcessChannel processChannel;
147     ::QProcess::ProcessChannelMode processChannelMode;
148     K3bQProcess::ProcessFlags processFlags;
149     ::QProcess::ProcessError processError;
150     ::QProcess::ProcessState processState;
151     QString workingDirectory;
152     Q_PID pid;
153     int sequenceNumber;
154 
155     bool dying;
156     bool emittedReadyRead;
157     bool emittedBytesWritten;
158 
159     Channel stdinChannel;
160     Channel stdoutChannel;
161     Channel stderrChannel;
162     bool createChannel(Channel &channel);
163     void closeWriteChannel();
164 
165     QString program;
166     QStringList arguments;
167     QStringList environment;
168 
169     QRingBuffer outputReadBuffer;
170     QRingBuffer errorReadBuffer;
171     QRingBuffer writeBuffer;
172 
173     Q_PIPE childStartedPipe[2];
174     Q_PIPE deathPipe[2];
175     void destroyPipe(Q_PIPE pipe[2]);
176 
177     QSocketNotifier *startupSocketNotifier;
178     QSocketNotifier *deathNotifier;
179 
180     // the wonderful windows notifier
181     QTimer *notifier;
182     QWindowsPipeWriter *pipeWriter;
183     QWinEventNotifier *processFinishedNotifier;
184 
185     void startProcess();
186 #ifdef Q_OS_UNIX
187     void execChild(const char *workingDirectory, char **path, char **argv, char **envp);
188 #endif
189     bool processStarted();
190     void terminateProcess();
191     void killProcess();
192     void findExitCode();
193 #ifdef Q_OS_UNIX
194     bool waitForDeadChild();
195 #endif
196 #ifdef Q_OS_WIN
197     void flushPipeWriter();
198     qint64 pipeWriterBytesToWrite() const;
199 #endif
200 
201     static bool startDetached(const QString &program, const QStringList &arguments, const QString &workingDirectory = QString(),
202                               qint64 *pid = 0);
203 
204     int exitCode;
205     ::QProcess::ExitStatus exitStatus;
206     bool crashed;
207 #ifdef Q_OS_UNIX
208     int serial;
209 #endif
210 
211     bool isReadyWrite;
212 
213     bool waitForStarted(int msecs = 30000);
214     bool waitForReadyRead(int msecs = 30000);
215     bool waitForBytesWritten(int msecs = 30000);
216     bool waitForFinished(int msecs = 30000);
217     bool waitForWrite(int msecs = 30000);
218 
219     qint64 bytesAvailableFromStdout() const;
220     qint64 bytesAvailableFromStderr() const;
221     qint64 readFromStdout(char *data, qint64 maxlen);
222     qint64 readFromStderr(char *data, qint64 maxlen);
223     qint64 writeToStdin(const char *data, qint64 maxlen);
224 
225     qint64 readData( char *data, qint64 len, QProcess::ProcessChannel channel );
226 
227     void cleanup();
228 #ifdef Q_OS_UNIX
229     static void initializeProcessManager();
230 #endif
231 };
232 
233 //QT_END_NAMESPACE
234 
235 #endif // QT_NO_PROCESS
236 
237 #endif // QPROCESS_P_H
238