]> git.tdb.fi Git - builder.git/blobdiff - source/externaltask.cpp
Additional MSVC fixes
[builder.git] / source / externaltask.cpp
index 3cc8eca394572aa4b1af9b5a621fdae8c6b97238..16d1df096dd4a23eee3f60b2e54a8cf289de9884 100644 (file)
@@ -1,11 +1,9 @@
 #include <cstdlib>
-#include <unistd.h>
-#include <sys/wait.h>
 #include <msp/fs/dir.h>
 #include <msp/io/console.h>
 #include <msp/io/file.h>
 #include <msp/io/print.h>
-#include <msp/time/units.h>
+#include <msp/time/timedelta.h>
 #include "externaltask.h"
 
 using namespace std;
@@ -16,8 +14,9 @@ ExternalTask::ExternalTask(const Arguments &a, const FS::Path &wd):
        work_dir(wd),
        process(0),
        exit_code(-1),
-       stdout_dest(PASSTHROUGH),
-       stderr_dest(PASSTHROUGH),
+       stdin_action(PASSTHROUGH),
+       stdout_action(PASSTHROUGH),
+       stderr_action(PASSTHROUGH),
        capture_pipe(0)
 {
        if(argv.empty())
@@ -45,35 +44,67 @@ string ExternalTask::get_command() const
                }
        }
 
+       if(stdin_action==REDIRECT)
+       {
+               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(stdin_action==IGNORE || stdout_action==IGNORE || stderr_action==IGNORE)
        {
-               devnull = new IO::File("/dev/null", IO::M_WRITE);
-               if(stdout_dest==IGNORE)
+#ifdef _WIN32
+               devnull = new IO::File("nul", IO::M_RDWR);
+#else
+               devnull = new IO::File("/dev/null", IO::M_RDWR);
+#endif
+               if(stdin_action==IGNORE)
+                       process->redirect_cin(*devnull);
+               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_action==REDIRECT)
+       {
+               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 +114,8 @@ void ExternalTask::start()
                capture_pipe->set_mode(IO::M_READ);
 
        delete devnull;
+       delete infile;
+       delete outfile;
 }
 
 Task::Status ExternalTask::check()
@@ -97,9 +130,9 @@ Task::Status ExternalTask::wait()
 
 Task::Status ExternalTask::do_wait(bool block)
 {
-       if(process)
+       while(process)
        {
-               if(process->wait(block))
+               if(process->wait(block && !capture_pipe))
                {
                        exit_code = process->get_exit_code();
                        delete process;
@@ -107,7 +140,7 @@ Task::Status ExternalTask::do_wait(bool block)
                }
 
                // Do this after waiting to avoid a race condition
-               while(capture_pipe && IO::poll(*capture_pipe, IO::P_INPUT, Time::zero))
+               while(capture_pipe && IO::poll(*capture_pipe, IO::P_INPUT, 10*Time::msec))
                {
                        char buf[1024];
                        unsigned len = capture_pipe->read(buf, sizeof(buf));
@@ -118,7 +151,10 @@ Task::Status ExternalTask::do_wait(bool block)
                }
 
                if(process)
-                       return RUNNING;
+               {
+                       if(!block)
+                               return RUNNING;
+               }
                else
                        signal_finished.emit(!exit_code);
        }
@@ -126,21 +162,38 @@ 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_action = REDIRECT;
+       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)
+string ExternalTask::run_and_capture_output(const Arguments &argv, const FS::Path &wd, bool capture_stderr)
 {
        ExternalTask task(argv, wd);
+       task.stdin_action = IGNORE;
        task.set_stdout(CAPTURE);
-       task.set_stderr(IGNORE);
+       task.set_stderr(capture_stderr ? CAPTURE : IGNORE);
        task.start();
        if(task.wait()!=SUCCESS)
                throw runtime_error(format("%s failed", argv.front()));