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())
}
}
+ 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);
capture_pipe->set_mode(IO::M_READ);
delete devnull;
+ delete infile;
+ delete outfile;
}
Task::Status ExternalTask::check()
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)
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
};
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;
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. */