From 550b5257aba507bcce98f6832b8905769a14955d Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 10 Apr 2017 13:19:19 +0200 Subject: Add process_run()/process_start() higher-level API on top of class process --- butl/process-run.txx | 216 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 216 insertions(+) create mode 100644 butl/process-run.txx (limited to 'butl/process-run.txx') diff --git a/butl/process-run.txx b/butl/process-run.txx new file mode 100644 index 0000000..013be4c --- /dev/null +++ b/butl/process-run.txx @@ -0,0 +1,216 @@ +// file : butl/process-run.txx -*- C++ -*- +// copyright : Copyright (c) 2014-2017 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#include +#include // move(), forward(), index_sequence + +namespace butl +{ + inline int process_stdin (int v) {assert (v >= 0); return v;} + inline int process_stdout (int v) {assert (v >= 0); return v;} + inline int process_stderr (int v) {assert (v >= 0); return v;} + + inline int + process_stdin (const auto_fd& v) {assert (v.get () >= 0); return v.get ();} + + inline int + process_stdout (const auto_fd& v) {assert (v.get () >= 0); return v.get ();} + + inline int + process_stderr (const auto_fd& v) {assert (v.get () >= 0); return v.get ();} + + process + process_start (const dir_path& cwd, + const process_path& pp, + const char* cmd[], + int in, + int out, + int err); + + template + process + process_start (std::index_sequence, + const C& cmdc, + I&& in, + O&& out, + E&& err, + const dir_path& cwd, + const process_path& pp, + A&&... args) + { + // Map stdin/stdout/stderr arguments to their integer values, as expected + // by the process constructor. + // + int in_i (process_stdin (std::forward (in))); + int out_i (process_stdout (std::forward (out))); + int err_i (process_stderr (std::forward (err))); + + // Construct the command line array. + // + const std::size_t args_size (sizeof... (args)); + + std::string storage[args_size]; + const char* cmd[args_size + 2] = { + pp.recall_string (), + process_arg_as (args, storage[index])..., + nullptr}; + + // The last argument can be NULL (used to handle zero A... pack). + // + cmdc (cmd, args_size + 2); + + // @@ Do we need to make sure certain fd's are closed before calling + // wait()? Is this only the case with pipes? Needs thinking. + + return process_start (cwd, pp, cmd, in_i, out_i, err_i); + } + + template + inline process + process_start (const C& cmdc, + I&& in, + O&& out, + E&& err, + const dir_path& cwd, + const process_path& pp, + A&&... args) + { + return process_start (std::index_sequence_for (), + cmdc, + std::forward (in), + std::forward (out), + std::forward (err), + cwd, + pp, + std::forward (args)...); + } + + template + inline process + process_start (I&& in, + O&& out, + E&& err, + const dir_path& cwd, + const P& p, + A&&... args) + { + return process_start ([] (const char* [], std::size_t) {}, + std::forward (in), + std::forward (out), + std::forward (err), + cwd, + process::path_search (p, true), + std::forward (args)...); + } + + template + inline process + process_start (const C& cmdc, + I&& in, + O&& out, + E&& err, + const dir_path& cwd, + const P& p, + A&&... args) + { + return process_start (cmdc, + std::forward (in), + std::forward (out), + std::forward (err), + cwd, + process::path_search (p, true), + std::forward (args)...); + } + + template + inline process_exit + process_run (const C& cmdc, + I&& in, + O&& out, + E&& err, + const dir_path& cwd, + const process_path& pp, + A&&... args) + { + process pr ( + process_start (cmdc, + std::forward (in), + std::forward (out), + std::forward (err), + cwd, + pp, + std::forward (args)...)); + + pr.wait (); + return *pr.exit; + } + + template + inline process_exit + process_run (I&& in, + O&& out, + E&& err, + const dir_path& cwd, + const P& p, + A&&... args) + { + return process_run ([] (const char* [], std::size_t) {}, + std::forward (in), + std::forward (out), + std::forward (err), + cwd, + process::path_search (p, true), + std::forward (args)...); + } + + template + inline process_exit + process_run (const C& cmdc, + I&& in, + O&& out, + E&& err, + const dir_path& cwd, + const P& p, + A&&... args) + { + return process_run (cmdc, + std::forward (in), + std::forward (out), + std::forward (err), + cwd, + process::path_search (p, true), + std::forward (args)...); + } +} -- cgit v1.1