aboutsummaryrefslogtreecommitdiff
path: root/butl/process-run.txx
diff options
context:
space:
mode:
Diffstat (limited to 'butl/process-run.txx')
-rw-r--r--butl/process-run.txx216
1 files changed, 216 insertions, 0 deletions
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 <cassert>
+#include <utility> // 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 <typename C,
+ typename I,
+ typename O,
+ typename E,
+ typename... A,
+ typename std::size_t... index>
+ process
+ process_start (std::index_sequence<index...>,
+ 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<I> (in)));
+ int out_i (process_stdout (std::forward<O> (out)));
+ int err_i (process_stderr (std::forward<E> (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 <typename C,
+ typename I,
+ typename O,
+ typename E,
+ typename... A>
+ 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<A...> (),
+ cmdc,
+ std::forward<I> (in),
+ std::forward<O> (out),
+ std::forward<E> (err),
+ cwd,
+ pp,
+ std::forward<A> (args)...);
+ }
+
+ template <typename I,
+ typename O,
+ typename E,
+ typename P,
+ typename... A>
+ 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<I> (in),
+ std::forward<O> (out),
+ std::forward<E> (err),
+ cwd,
+ process::path_search (p, true),
+ std::forward<A> (args)...);
+ }
+
+ template <typename C,
+ typename I,
+ typename O,
+ typename E,
+ typename P,
+ typename... A>
+ 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<I> (in),
+ std::forward<O> (out),
+ std::forward<E> (err),
+ cwd,
+ process::path_search (p, true),
+ std::forward<A> (args)...);
+ }
+
+ template <typename C,
+ typename I,
+ typename O,
+ typename E,
+ typename... A>
+ 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<I> (in),
+ std::forward<O> (out),
+ std::forward<E> (err),
+ cwd,
+ pp,
+ std::forward<A> (args)...));
+
+ pr.wait ();
+ return *pr.exit;
+ }
+
+ template <typename I,
+ typename O,
+ typename E,
+ typename P,
+ typename... A>
+ 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<I> (in),
+ std::forward<O> (out),
+ std::forward<E> (err),
+ cwd,
+ process::path_search (p, true),
+ std::forward<A> (args)...);
+ }
+
+ template <typename C,
+ typename I,
+ typename O,
+ typename E,
+ typename P,
+ typename... A>
+ 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<I> (in),
+ std::forward<O> (out),
+ std::forward<E> (err),
+ cwd,
+ process::path_search (p, true),
+ std::forward<A> (args)...);
+ }
+}