aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2019-09-13 17:57:00 (GMT)
committerKaren Arutyunov <karen@codesynthesis.com>2019-09-27 14:08:05 (GMT)
commit3fa1b103014bab51f8f257e1e12f27f7e498f42e (patch)
tree4958c20dead025ffa0305dd0c99041382bda16a8
parentc4292d57e2e67dfcdac9004f8edb229976f6669a (diff)
Add support for builtin escaping to command running API
-rw-r--r--libbutl/command.cxx12
-rw-r--r--libbutl/command.mxx5
-rw-r--r--tests/command/testscript10
3 files changed, 26 insertions, 1 deletions
diff --git a/libbutl/command.cxx b/libbutl/command.cxx
index a344790..1126bb0 100644
--- a/libbutl/command.cxx
+++ b/libbutl/command.cxx
@@ -272,11 +272,21 @@ namespace butl
}
else // Execute the program.
{
+ // Strip the potential leading `^`, indicating that this is an external
+ // program rather than a builtin. Consider only simple paths and don't
+ // end up with an empty path.
+ //
+ const char* p (prog.size () > 1 &&
+ prog[0] == '^' &&
+ path::traits_type::find_separator (prog) == string::npos
+ ? prog.c_str () + 1
+ : prog.c_str ());
+
// Prepare the process environment.
//
// Note: cwd passed to process_env() may not be a temporary object.
//
- process_env pe (prog, cwd, env ? env->vars : nullptr);
+ process_env pe (p, cwd, env ? env->vars : nullptr);
// Finally, run the process.
//
diff --git a/libbutl/command.mxx b/libbutl/command.mxx
index 0e6617b..8423f59 100644
--- a/libbutl/command.mxx
+++ b/libbutl/command.mxx
@@ -37,6 +37,11 @@ LIBBUTL_MODEXPORT namespace butl
// error, ios::failure on the underlying OS error, process_error on the
// process running error and std::system_error on the builtin running error.
//
+ // To run a system utility rather than a builtin prefix its name with `^`,
+ // for example:
+ //
+ // ^cat --squeeze-blank file
+ //
// The process environment path is unused and must point to the empty
// process path.
//
diff --git a/tests/command/testscript b/tests/command/testscript
index db9bb5c..12ddd79 100644
--- a/tests/command/testscript
+++ b/tests/command/testscript
@@ -184,4 +184,14 @@ end
{
$* -p 'echo abc >a' >'echo abc >a' &a
}
+
+ : escape
+ :
+ : Note that the sed builtin doesn't support multiple scripts.
+ :
+ if ($cxx.target.class != 'windows')
+ {
+ echo 'abc' >=f;
+ $* '^sed -e s/a/b/ -e s/c/b/ f' >'bbb'
+ }
}