File indexing completed on 2024-05-12 04:51:19

0001 /*
0002     SPDX-FileCopyrightText: 2009 Nokia Corporation and /or its subsidiary(-ies).
0003     Contact: Qt Software Information (qt-info@nokia.com)
0004 
0005     This file is part of the QtCore module of the Qt Toolkit.
0006 
0007     $QT_BEGIN_LICENSE:LGPL$
0008     Commercial Usage
0009     Licensees holding valid Qt Commercial licenses may use this file in
0010     accordance with the Qt Commercial License Agreement provided with the
0011     Software or, alternatively, in accordance with the terms contained in
0012     a written agreement between you and Nokia.
0013 
0014     GNU Lesser General Public License Usage
0015     Alternatively, this file may be used under the terms of the GNU Lesser
0016     General Public License version 2.1 as published by the Free Software
0017     Foundation and appearing in the file LICENSE.LGPL included in the
0018     packaging of this file.  Please review the following information to
0019     ensure the GNU Lesser General Public License version 2.1 requirements
0020     will be met: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
0021 
0022     In addition, as a special exception, Nokia gives you certain
0023     additional rights. These rights are described in the Nokia Qt LGPL
0024     Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
0025     package.
0026 
0027     GNU General Public License Usage
0028     Alternatively, this file may be used under the terms of the GNU
0029     General Public License version 3.0 as published by the Free Software
0030     Foundation and appearing in the file LICENSE.GPL included in the
0031     packaging of this file.  Please review the following information to
0032     ensure the GNU General Public License version 3.0 requirements will be
0033     met: https://www.gnu.org/licenses/gpl-3.0.html.
0034 
0035     If you are unsure which license is appropriate for your use, please
0036     contact the sales department at qt-sales@nokia.com.
0037     $QT_END_LICENSE$
0038 
0039 */
0040 
0041 #ifndef K3B_QPROCESS_P_H
0042 #define K3B_QPROCESS_P_H
0043 
0044 //
0045 //  W A R N I N G
0046 //  -------------
0047 //
0048 // This file is not part of the Qt API.  It exists purely as an
0049 // implementation detail.  This header file may change from version to
0050 // version without notice, or even be removed.
0051 //
0052 // We mean it.
0053 //
0054 
0055 #include "k3bqprocess.h"
0056 #include <QStringList>
0057 //#include "private/qringbuffer_p.h"
0058 #include "qringbuffer_p.h"
0059 //#include "private/qiodevice_p.h"
0060 
0061 #ifdef Q_OS_WIN
0062 #include "QtCore/qt_windows.h"
0063 typedef HANDLE Q_PIPE;
0064 #define INVALID_Q_PIPE INVALID_HANDLE_VALUE
0065 #else
0066 typedef int Q_PIPE;
0067 #define INVALID_Q_PIPE -1
0068 #endif
0069 
0070 #ifndef QT_NO_PROCESS
0071 
0072 //QT_BEGIN_NAMESPACE
0073 class QSocketNotifier;
0074 class QWindowsPipeWriter;
0075 class QWinEventNotifier;
0076 class QTimer;
0077 
0078 
0079 class K3bQProcessPrivate
0080 {
0081 public:
0082     Q_DECLARE_PUBLIC(K3bQProcess)
0083     K3bQProcess* q_ptr;
0084 
0085     struct Channel {
0086         enum ProcessChannelType {
0087             Normal = 0,
0088             PipeSource = 1,
0089             PipeSink = 2,
0090             Redirect = 3
0091             // if you add "= 4" here, increase the number of bits below
0092         };
0093 
0094         Channel() : process(0), notifier(0), type(Normal), closed(false), append(false)
0095         {
0096             pipe[0] = INVALID_Q_PIPE;
0097             pipe[1] = INVALID_Q_PIPE;
0098         }
0099 
0100         void clear();
0101 
0102         Channel &operator=(const QString &fileName)
0103         {
0104             clear();
0105             file = fileName;
0106             type = fileName.isEmpty() ? Normal : Redirect;
0107             return *this;
0108         }
0109 
0110         void pipeTo(K3bQProcessPrivate *other)
0111         {
0112             clear();
0113             process = other;
0114             type = PipeSource;
0115         }
0116 
0117         void pipeFrom(K3bQProcessPrivate *other)
0118         {
0119             clear();
0120             process = other;
0121             type = PipeSink;
0122         }
0123 
0124         QString file;
0125         K3bQProcessPrivate *process;
0126         QSocketNotifier *notifier;
0127         Q_PIPE pipe[2];
0128 
0129         unsigned type : 2;
0130         bool closed : 1;
0131         bool append : 1;
0132     };
0133 
0134     K3bQProcessPrivate();
0135     virtual ~K3bQProcessPrivate();
0136 
0137     // private slots
0138     bool _q_canReadStandardOutput();
0139     bool _q_canReadStandardError();
0140     bool _q_canWrite();
0141     bool _q_startupNotification();
0142     bool _q_processDied();
0143     bool _q_notifyProcessDied();
0144     void _q_notified();
0145 
0146     ::QProcess::ProcessChannel processChannel;
0147     ::QProcess::ProcessChannelMode processChannelMode;
0148     K3bQProcess::ProcessFlags processFlags;
0149     ::QProcess::ProcessError processError;
0150     ::QProcess::ProcessState processState;
0151     QString workingDirectory;
0152     Q_PID pid;
0153     int sequenceNumber;
0154 
0155     bool dying;
0156     bool emittedReadyRead;
0157     bool emittedBytesWritten;
0158 
0159     Channel stdinChannel;
0160     Channel stdoutChannel;
0161     Channel stderrChannel;
0162     bool createChannel(Channel &channel);
0163     void closeWriteChannel();
0164 
0165     QString program;
0166     QStringList arguments;
0167     QStringList environment;
0168 
0169     QRingBuffer outputReadBuffer;
0170     QRingBuffer errorReadBuffer;
0171     QRingBuffer writeBuffer;
0172 
0173     Q_PIPE childStartedPipe[2];
0174     Q_PIPE deathPipe[2];
0175     void destroyPipe(Q_PIPE pipe[2]);
0176 
0177     QSocketNotifier *startupSocketNotifier;
0178     QSocketNotifier *deathNotifier;
0179 
0180     // the wonderful windows notifier
0181     QTimer *notifier;
0182     QWindowsPipeWriter *pipeWriter;
0183     QWinEventNotifier *processFinishedNotifier;
0184 
0185     void startProcess();
0186 #ifdef Q_OS_UNIX
0187     void execChild(const char *workingDirectory, char **path, char **argv, char **envp);
0188 #endif
0189     bool processStarted();
0190     void terminateProcess();
0191     void killProcess();
0192     void findExitCode();
0193 #ifdef Q_OS_UNIX
0194     bool waitForDeadChild();
0195 #endif
0196 #ifdef Q_OS_WIN
0197     void flushPipeWriter();
0198     qint64 pipeWriterBytesToWrite() const;
0199 #endif
0200 
0201     static bool startDetached(const QString &program, const QStringList &arguments, const QString &workingDirectory = QString(),
0202                               qint64 *pid = 0);
0203 
0204     int exitCode;
0205     ::QProcess::ExitStatus exitStatus;
0206     bool crashed;
0207 #ifdef Q_OS_UNIX
0208     int serial;
0209 #endif
0210 
0211     bool isReadyWrite;
0212 
0213     bool waitForStarted(int msecs = 30000);
0214     bool waitForReadyRead(int msecs = 30000);
0215     bool waitForBytesWritten(int msecs = 30000);
0216     bool waitForFinished(int msecs = 30000);
0217     bool waitForWrite(int msecs = 30000);
0218 
0219     qint64 bytesAvailableFromStdout() const;
0220     qint64 bytesAvailableFromStderr() const;
0221     qint64 readFromStdout(char *data, qint64 maxlen);
0222     qint64 readFromStderr(char *data, qint64 maxlen);
0223     qint64 writeToStdin(const char *data, qint64 maxlen);
0224 
0225     qint64 readData( char *data, qint64 len, QProcess::ProcessChannel channel );
0226 
0227     void cleanup();
0228 #ifdef Q_OS_UNIX
0229     static void initializeProcessManager();
0230 #endif
0231 };
0232 
0233 //QT_END_NAMESPACE
0234 
0235 #endif // QT_NO_PROCESS
0236 
0237 #endif // QPROCESS_P_H