#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;
work_dir(wd),
process(0),
exit_code(-1),
+ stdin_action(PASSTHROUGH),
stdout_action(PASSTHROUGH),
stderr_action(PASSTHROUGH),
capture_pipe(0)
string ExternalTask::get_command() const
{
string cmd;
- for(vector<string>::const_iterator i=argv.begin(); i!=argv.end(); ++i)
+ for(const string &a: argv)
{
- if(i!=argv.begin())
+ if(!cmd.empty())
cmd += ' ';
- for(string::const_iterator j=i->begin(); j!=i->end(); ++j)
+ for(char c: a)
{
- if(*j=='"' || *j=='\'' || *j==' ' || *j=='\\' || *j=='&')
+ if(c=='"' || c=='\'' || c==' ' || c=='\\' || c=='&')
cmd += '\\';
- cmd += *j;
+ cmd += c;
}
}
- if(!stdin_file.empty())
+ if(stdin_action==REDIRECT)
{
cmd += " <";
cmd += stdin_file.str();
process = new Process;
- if(stdout_action==IGNORE || stderr_action==IGNORE)
+ if(stdin_action==IGNORE || stdout_action==IGNORE || stderr_action==IGNORE)
{
- devnull = new IO::File("/dev/null", IO::M_WRITE);
+#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_action==IGNORE)
process->redirect_cerr(*capture_pipe);
}
- if(!stdin_file.empty())
+ if(stdin_action==REDIRECT)
{
infile = new IO::File((work_dir/stdin_file).str());
process->redirect_cin(*infile);
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;
}
// 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));
}
if(process)
- return RUNNING;
+ {
+ if(!block)
+ return RUNNING;
+ }
else
signal_finished.emit(!exit_code);
}
void ExternalTask::set_stdin(const FS::Path &f)
{
+ stdin_action = REDIRECT;
stdin_file = f;
}
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()));