From 50a8a5e7959ca315e812413661a76576b7c3bbb8 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 3 Sep 2013 22:06:26 +0200 Subject: add QProcess::InputChannelMode this enables forwarding standard input from the parent process. Change-Id: I7ee72b9842acc96320d4da693b95dd15d9a7b4d4 Reviewed-by: Simon Hausmann Reviewed-by: Lars Knoll Reviewed-by: Olivier Goffart Reviewed-by: Friedemann Kleint Reviewed-by: Oliver Wolff --- src/corelib/io/qprocess.cpp | 53 ++++++++++++++++++++++++++++++++++++++-- src/corelib/io/qprocess.h | 6 +++++ src/corelib/io/qprocess_p.h | 1 + src/corelib/io/qprocess_unix.cpp | 15 ++++++------ src/corelib/io/qprocess_win.cpp | 10 +++++++- 5 files changed, 75 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp index 27a8bce3fe..7f4d7f0313 100644 --- a/src/corelib/io/qprocess.cpp +++ b/src/corelib/io/qprocess.cpp @@ -608,8 +608,8 @@ void QProcessPrivate::Channel::clear() /*! \enum QProcess::ProcessChannelMode - This enum describes the process channel modes of QProcess. Pass - one of these values to setProcessChannelMode() to set the + This enum describes the process output channel modes of QProcess. + Pass one of these values to setProcessChannelMode() to set the current read channel mode. \value SeparateChannels QProcess manages the output of the @@ -651,6 +651,26 @@ void QProcessPrivate::Channel::clear() \sa setProcessChannelMode() */ +/*! + \enum QProcess::InputChannelMode + \since 5.2 + + This enum describes the process input channel modes of QProcess. + Pass one of these values to setInputChannelMode() to set the + current write channel mode. + + \value ManagedInputChannel QProcess manages the input of the running + process. This is the default input channel mode of QProcess. + + \value ForwardedInputChannel QProcess forwards the input of the main + process onto the running process. The child process reads its standard + input from the same source as the main process. + Note that the main process must not try to read its standard input + while the child process is running. + + \sa setInputChannelMode() +*/ + /*! \enum QProcess::ProcessError @@ -779,6 +799,7 @@ QProcessPrivate::QProcessPrivate() { processChannel = QProcess::StandardOutput; processChannelMode = QProcess::SeparateChannels; + inputChannelMode = QProcess::ManagedInputChannel; processError = QProcess::UnknownError; processState = QProcess::NotRunning; pid = 0; @@ -1243,6 +1264,34 @@ void QProcess::setProcessChannelMode(ProcessChannelMode mode) d->processChannelMode = mode; } +/*! + \since 5.2 + + Returns the channel mode of the QProcess standard input channel. + + \sa setInputChannelMode(), InputChannelMode +*/ +QProcess::InputChannelMode QProcess::inputChannelMode() const +{ + Q_D(const QProcess); + return d->inputChannelMode; +} + +/*! + \since 5.2 + + Sets the channel mode of the QProcess standard intput + channel to the \a mode specified. + This mode will be used the next time start() is called. + + \sa inputChannelMode(), InputChannelMode +*/ +void QProcess::setInputChannelMode(InputChannelMode mode) +{ + Q_D(QProcess); + d->inputChannelMode = mode; +} + /*! Returns the current read channel of the QProcess. diff --git a/src/corelib/io/qprocess.h b/src/corelib/io/qprocess.h index 0984d501fd..c0b3ab945e 100644 --- a/src/corelib/io/qprocess.h +++ b/src/corelib/io/qprocess.h @@ -128,6 +128,10 @@ public: ForwardedOutputChannel, ForwardedErrorChannel }; + enum InputChannelMode { + ManagedInputChannel, + ForwardedInputChannel + }; enum ExitStatus { NormalExit, CrashExit @@ -151,6 +155,8 @@ public: void setReadChannelMode(ProcessChannelMode mode); ProcessChannelMode processChannelMode() const; void setProcessChannelMode(ProcessChannelMode mode); + InputChannelMode inputChannelMode() const; + void setInputChannelMode(InputChannelMode mode); ProcessChannel readChannel() const; void setReadChannel(ProcessChannel channel); diff --git a/src/corelib/io/qprocess_p.h b/src/corelib/io/qprocess_p.h index e96cb42f94..219bdf8200 100644 --- a/src/corelib/io/qprocess_p.h +++ b/src/corelib/io/qprocess_p.h @@ -302,6 +302,7 @@ public: QProcess::ProcessChannel processChannel; QProcess::ProcessChannelMode processChannelMode; + QProcess::InputChannelMode inputChannelMode; QProcess::ProcessError processError; QProcess::ProcessState processState; QString workingDirectory; diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp index 0e0ead5897..9868ea624a 100644 --- a/src/corelib/io/qprocess_unix.cpp +++ b/src/corelib/io/qprocess_unix.cpp @@ -807,29 +807,29 @@ pid_t QProcessPrivate::spawnChild(const char *workingDir, char **argv, char **en ? i : SPAWN_FDCLOSED; } + if (inputChannelMode == QProcess::ManagedInputChannel) + fd_map[0] = stdinChannel.pipe[0]; + else + fd_map[0] = QT_FILENO(stdin); + switch (processChannelMode) { case QProcess::ForwardedChannels: - fd_map[0] = stdinChannel.pipe[0]; fd_map[1] = QT_FILENO(stdout); fd_map[2] = QT_FILENO(stderr); break; case QProcess::ForwardedOutputChannel: - fd_map[0] = stdinChannel.pipe[0]; fd_map[1] = QT_FILENO(stdout); fd_map[2] = stderrChannel.pipe[1]; break; case QProcess::ForwardedErrorChannel: - fd_map[0] = stdinChannel.pipe[0]; fd_map[1] = stdoutChannel.pipe[1]; fd_map[2] = QT_FILENO(stderr); break; case QProcess::MergedChannels: - fd_map[0] = stdinChannel.pipe[0]; fd_map[1] = stdoutChannel.pipe[1]; fd_map[2] = stdoutChannel.pipe[1]; break; case QProcess::SeparateChannels: - fd_map[0] = stdinChannel.pipe[0]; fd_map[1] = stdoutChannel.pipe[1]; fd_map[2] = stderrChannel.pipe[1]; break; @@ -855,8 +855,9 @@ void QProcessPrivate::execChild(const char *workingDir, char **path, char **argv Q_Q(QProcess); - // copy the stdin socket (without closing on exec) - qt_safe_dup2(stdinChannel.pipe[0], fileno(stdin), 0); + // copy the stdin socket if asked to (without closing on exec) + if (inputChannelMode != QProcess::ForwardedInputChannel) + qt_safe_dup2(stdinChannel.pipe[0], fileno(stdin), 0); // copy the stdout and stderr if asked to if (processChannelMode != QProcess::ForwardedChannels) { diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp index f545386f56..291ea319ec 100644 --- a/src/corelib/io/qprocess_win.cpp +++ b/src/corelib/io/qprocess_win.cpp @@ -156,7 +156,15 @@ bool QProcessPrivate::createChannel(Channel &channel) if (channel.type == Channel::Normal) { // we're piping this channel to our own process if (&channel == &stdinChannel) { - qt_create_pipe(channel.pipe, true); + if (inputChannelMode != QProcess::ForwardedInputChannel) { + qt_create_pipe(channel.pipe, true); + } else { + channel.pipe[1] = INVALID_Q_PIPE; + HANDLE hStdReadChannel = GetStdHandle(STD_INPUT_HANDLE); + HANDLE hCurrentProcess = GetCurrentProcess(); + DuplicateHandle(hCurrentProcess, hStdReadChannel, hCurrentProcess, + &channel.pipe[0], 0, TRUE, DUPLICATE_SAME_ACCESS); + } } else { QWindowsPipeReader *pipeReader = 0; if (&channel == &stdoutChannel) { -- cgit v1.2.3