From e2d759fce9ff5e5886064ec693af54fe598773ff Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 23 Jul 2015 14:47:09 +0200 Subject: Add support for process redirection to existing fd, piping --- butl/process.cxx | 64 ++++++++++++++++++++++++++++++++------------------------ 1 file changed, 37 insertions(+), 27 deletions(-) (limited to 'butl/process.cxx') diff --git a/butl/process.cxx b/butl/process.cxx index 35ca26d..a456217 100644 --- a/butl/process.cxx +++ b/butl/process.cxx @@ -16,6 +16,8 @@ # include // _O_TEXT #endif +#include + using namespace std; namespace butl @@ -23,15 +25,15 @@ namespace butl #ifndef _WIN32 process:: - process (char const* args[], bool in, bool err, bool out) + process (char const* args[], int in, int out, int err) { - int out_fd[2]; - int in_efd[2]; - int in_ofd[2]; + int out_fd[2] = {in, 0}; + int in_ofd[2] = {0, out}; + int in_efd[2] = {0, err}; - if ((in && pipe (out_fd) == -1) || - (err && pipe (in_efd) == -1) || - (out && pipe (in_ofd) == -1)) + if ((in == -1 && pipe (out_fd) == -1) || + (out == -1 && pipe (in_ofd) == -1) || + (err == -1 && pipe (in_efd) == -1)) throw process_error (errno, false); id = fork (); @@ -44,31 +46,31 @@ namespace butl // Child. If requested, close the write end of the pipe and duplicate // the read end to stdin. Then close the original read end descriptor. // - if (in) + if (in != STDIN_FILENO) { - if (close (out_fd[1]) == -1 || - dup2 (out_fd[0], STDIN_FILENO) == -1 || - close (out_fd[0]) == -1) + if ((in == -1 && close (out_fd[1]) == -1) || + dup2 (out_fd[0], STDIN_FILENO) == -1 || + (in == -1 && close (out_fd[0]) == -1)) throw process_error (errno, true); } - // Do the same for the stderr if requested. + // Do the same for the stdout if requested. // - if (err) + if (out != STDOUT_FILENO) { - if (close (in_efd[0]) == -1 || - dup2 (in_efd[1], STDERR_FILENO) == -1 || - close (in_efd[1]) == -1) + if ((out == -1 && close (in_ofd[0]) == -1) || + dup2 (in_ofd[1], STDOUT_FILENO) == -1 || + (out == -1 && close (in_ofd[1]) == -1)) throw process_error (errno, true); } - // Do the same for the stdout if requested. + // Do the same for the stderr if requested. // - if (out) + if (err != STDERR_FILENO) { - if (close (in_ofd[0]) == -1 || - dup2 (in_ofd[1], STDOUT_FILENO) == -1 || - close (in_ofd[1]) == -1) + if ((err == -1 && close (in_efd[0]) == -1) || + dup2 (in_efd[1], STDERR_FILENO) == -1 || + (err == -1 && close (in_efd[1]) == -1)) throw process_error (errno, true); } @@ -79,15 +81,23 @@ namespace butl { // Parent. Close the other ends of the pipes. // - if ((in && close (out_fd[0]) == -1) || - (err && close (in_efd[1]) == -1) || - (out && close (in_ofd[1]) == -1)) + if ((in == -1 && close (out_fd[0]) == -1) || + (out == -1 && close (in_ofd[1]) == -1) || + (err == -1 && close (in_efd[1]) == -1)) throw process_error (errno, false); } - this->out_fd = in ? out_fd[1] : 0; - this->in_efd = err ? in_efd[0] : 0; - this->in_ofd = out ? in_ofd[0] : 0; + this->out_fd = in == -1 ? out_fd[1] : -1; + this->in_ofd = out == -1 ? in_ofd[0] : -1; + this->in_efd = err == -1 ? in_efd[0] : -1; + } + + process:: + process (char const* args[], process& in, int out, int err) + : process (args, in.in_ofd, out, err) + { + assert (in.in_ofd != -1); // Should be a pipe. + close (in.in_ofd); // Close it on our side. } bool process:: -- cgit v1.1