]> git.tdb.fi Git - builder.git/commitdiff
Support redirecting ExternalTask's stdin/stdout from/to a file
authorMikko Rasa <tdb@tdb.fi>
Thu, 9 Oct 2014 17:42:57 +0000 (20:42 +0300)
committerMikko Rasa <tdb@tdb.fi>
Thu, 9 Oct 2014 17:42:57 +0000 (20:42 +0300)
source/externaltask.cpp
source/externaltask.h

index 3cc8eca394572aa4b1af9b5a621fdae8c6b97238..257d1318fb22a42d31a5e2ed04e95424cb0a80ae 100644 (file)
@@ -16,8 +16,8 @@ ExternalTask::ExternalTask(const Arguments &a, const FS::Path &wd):
        work_dir(wd),
        process(0),
        exit_code(-1),
-       stdout_dest(PASSTHROUGH),
-       stderr_dest(PASSTHROUGH),
+       stdout_action(PASSTHROUGH),
+       stderr_action(PASSTHROUGH),
        capture_pipe(0)
 {
        if(argv.empty())
@@ -45,35 +45,61 @@ string ExternalTask::get_command() const
                }
        }
 
+       if(!stdin_file.empty())
+       {
+               cmd += " <";
+               cmd += stdin_file.str();
+       }
+
+       if(stdout_action==REDIRECT)
+       {
+               cmd += " >";
+               cmd += stdout_file.str();
+       }
+
        return cmd;
 }
 
 void ExternalTask::start()
 {
        IO::File *devnull = 0;
+       IO::File *infile = 0;
+       IO::File *outfile = 0;
 
        prepare();
 
        process = new Process;
 
-       if(stdout_dest==IGNORE || stderr_dest==IGNORE)
+       if(stdout_action==IGNORE || stderr_action==IGNORE)
        {
                devnull = new IO::File("/dev/null", IO::M_WRITE);
-               if(stdout_dest==IGNORE)
+               if(stdout_action==IGNORE)
                        process->redirect_cout(*devnull);
-               if(stderr_dest==IGNORE)
+               if(stderr_action==IGNORE)
                        process->redirect_cerr(*devnull);
        }
 
-       if(stdout_dest==CAPTURE || stderr_dest==CAPTURE)
+       if(stdout_action==REDIRECT)
+       {
+               outfile = new IO::File((work_dir/stdout_file).str(), IO::M_WRITE);
+               process->redirect_cout(*outfile);
+       }
+
+       if(stdout_action==CAPTURE || stderr_action==CAPTURE)
        {
                capture_pipe = new IO::Pipe;
-               if(stdout_dest==CAPTURE)
+               if(stdout_action==CAPTURE)
                        process->redirect_cout(*capture_pipe);
-               if(stderr_dest==CAPTURE)
+               if(stderr_action==CAPTURE)
                        process->redirect_cerr(*capture_pipe);
        }
 
+       if(!stdin_file.empty())
+       {
+               infile = new IO::File((work_dir/stdin_file).str());
+               process->redirect_cin(*infile);
+       }
+
        if(!work_dir.empty())
                process->set_working_directory(work_dir);
 
@@ -83,6 +109,8 @@ void ExternalTask::start()
                capture_pipe->set_mode(IO::M_READ);
 
        delete devnull;
+       delete infile;
+       delete outfile;
 }
 
 Task::Status ExternalTask::check()
@@ -126,14 +154,29 @@ Task::Status ExternalTask::do_wait(bool block)
        return exit_code ? ERROR : SUCCESS;
 }
 
-void ExternalTask::set_stdout(Destination d)
+void ExternalTask::set_stdin(const FS::Path &f)
+{
+       stdin_file = f;
+}
+
+void ExternalTask::set_stdout(StreamAction a)
+{
+       if(a==REDIRECT)
+               throw invalid_argument("ExternalTask::set_stdout");
+       stdout_action = a;
+}
+
+void ExternalTask::set_stdout(const FS::Path &f)
 {
-       stdout_dest = d;
+       stdout_action = REDIRECT;
+       stdout_file = f;
 }
 
-void ExternalTask::set_stderr(Destination d)
+void ExternalTask::set_stderr(StreamAction a)
 {
-       stderr_dest = d;
+       if(a==REDIRECT)
+               throw invalid_argument("ExternalTask::set_stdout");
+       stderr_action = a;
 }
 
 string ExternalTask::run_and_capture_output(const Arguments &argv, const FS::Path &wd)
index 992df5c692a4c7bf8dfd6e6a208d2c64f15afdc0..00465f3af4f3ba501952f1a7bf29ce149d04865a 100644 (file)
@@ -16,10 +16,11 @@ be captured.
 class ExternalTask: public Task
 {
 public:
-       enum Destination
+       enum StreamAction
        {
                PASSTHROUGH,  //< Do not touch the stream
                CAPTURE,      //< Capture the stream
+               REDIRECT,     //< Redirect the stream to/from a file
                IGNORE        //< Redirect the stream to oblivion
        };
 
@@ -30,8 +31,10 @@ private:
        Msp::FS::Path work_dir;
        Msp::Process *process;
        int exit_code;
-       Destination stdout_dest;
-       Destination stderr_dest;
+       Msp::FS::Path stdin_file;
+       StreamAction stdout_action;
+       Msp::FS::Path stdout_file;
+       StreamAction stderr_action;
        Msp::IO::Pipe *capture_pipe;
        std::string output;
 
@@ -51,11 +54,17 @@ private:
        Status do_wait(bool);
 
 public:
+       /// Redirect stdin from a file.  Has no effect after the task is started.
+       void set_stdin(const Msp::FS::Path &);
+
        /// Sets destination for stdout.  Has no effect after the task is started.
-       void set_stdout(Destination);
+       void set_stdout(StreamAction);
+
+       /// Redirect stdout to a file.  Has no effect after the task is started.
+       void set_stdout(const Msp::FS::Path &);
 
        /// Sets destination for stderr.  Has no effect after the task is started.
-       void set_stderr(Destination);
+       void set_stderr(StreamAction);
 
        /** Returns captured output, if any.  This may be called while the task is
        still running, but it will always return all output. */