From 2d9a6cf1b0123e5962d5558b57f74c1faf33bf0b Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Fri, 1 Dec 2017 13:03:46 +0200 Subject: [PATCH] Improve ExternalTask::run_and_capture_output Redirect input from /dev/null and allow stderr to be captured as well. --- source/externaltask.cpp | 17 +++++++++++------ source/externaltask.h | 7 ++++--- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/source/externaltask.cpp b/source/externaltask.cpp index 257d131..e4dfdc2 100644 --- a/source/externaltask.cpp +++ b/source/externaltask.cpp @@ -16,6 +16,7 @@ ExternalTask::ExternalTask(const Arguments &a, const FS::Path &wd): work_dir(wd), process(0), exit_code(-1), + stdin_action(PASSTHROUGH), stdout_action(PASSTHROUGH), stderr_action(PASSTHROUGH), capture_pipe(0) @@ -45,7 +46,7 @@ string ExternalTask::get_command() const } } - if(!stdin_file.empty()) + if(stdin_action==REDIRECT) { cmd += " <"; cmd += stdin_file.str(); @@ -70,9 +71,11 @@ void ExternalTask::start() 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); + devnull = new IO::File("/dev/null", IO::M_RDWR); + if(stdin_action==IGNORE) + process->redirect_cin(*devnull); if(stdout_action==IGNORE) process->redirect_cout(*devnull); if(stderr_action==IGNORE) @@ -94,7 +97,7 @@ void ExternalTask::start() 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); @@ -156,6 +159,7 @@ Task::Status ExternalTask::do_wait(bool block) void ExternalTask::set_stdin(const FS::Path &f) { + stdin_action = REDIRECT; stdin_file = f; } @@ -179,11 +183,12 @@ void ExternalTask::set_stderr(StreamAction a) 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())); diff --git a/source/externaltask.h b/source/externaltask.h index 00465f3..26a6aca 100644 --- a/source/externaltask.h +++ b/source/externaltask.h @@ -31,6 +31,7 @@ private: Msp::FS::Path work_dir; Msp::Process *process; int exit_code; + StreamAction stdin_action; Msp::FS::Path stdin_file; StreamAction stdout_action; Msp::FS::Path stdout_file; @@ -70,9 +71,9 @@ public: still running, but it will always return all output. */ const std::string &get_output() const { return output; } - /** Executes a command and captures its output. Stderr is ignored, but if - the command exits with a nonzero status, an exception is thrown. */ - static std::string run_and_capture_output(const Arguments &, const Msp::FS::Path & = Msp::FS::Path()); + /** Executes a command and captures its output. If the command exits with + a nonzero status, an exception is thrown. */ + static std::string run_and_capture_output(const Arguments &, const Msp::FS::Path & = Msp::FS::Path(), bool = false); }; #endif -- 2.43.0