aboutsummaryrefslogtreecommitdiff
path: root/libbutl
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2020-04-06 16:19:38 +0200
committerKaren Arutyunov <karen@codesynthesis.com>2020-04-07 15:08:30 +0300
commitca0fa738650ab546b1422e0b2dbfdc89ba8eb5a3 (patch)
tree5e9fe6a4d8b419ab8fd94cc0614d76d2a7376028 /libbutl
parent5fba51e990e7111c7dc125c1115ac7b5de4025be (diff)
Add ability to print process_env environment
Diffstat (limited to 'libbutl')
-rw-r--r--libbutl/process-io.cxx106
-rw-r--r--libbutl/process-io.mxx24
-rw-r--r--libbutl/process.mxx11
3 files changed, 140 insertions, 1 deletions
diff --git a/libbutl/process-io.cxx b/libbutl/process-io.cxx
new file mode 100644
index 0000000..c29bbc0
--- /dev/null
+++ b/libbutl/process-io.cxx
@@ -0,0 +1,106 @@
+// file : libbutl/process-io.cxx -*- C++ -*-
+// license : MIT; see accompanying LICENSE file
+
+#ifndef __cpp_modules_ts
+#include <libbutl/process-io.mxx>
+#endif
+
+// C includes.
+
+#ifndef __cpp_lib_modules_ts
+#include <ostream>
+
+#include <cstring> // strchr()
+#endif
+
+// Other includes.
+
+#ifdef __cpp_modules_ts
+module butl.process_io;
+
+// Only imports additional to interface.
+#ifdef __clang__
+#ifdef __cpp_lib_modules_ts
+import std.core;
+import std.io;
+#endif
+import butl.process;
+#endif
+
+import butl.path-io;
+#else
+#include <libbutl/path-io.mxx>
+#endif
+
+using namespace std;
+
+namespace butl
+{
+ // process_env
+ //
+ ostream&
+ operator<< (ostream& o, const process_env& env)
+ {
+ bool first (true);
+ const dir_path* cwd (env.cwd);
+
+ if (cwd != nullptr && !cwd->empty ())
+ {
+ if (cwd->string ().find (' ') != string::npos)
+ o << "PWD=\"" << *cwd << '"';
+ else
+ o << "PWD=" << *cwd;
+
+ first = false;
+ }
+
+ if (env.vars != nullptr)
+ {
+ for (const char* const* ev (env.vars); *ev != nullptr; ++ev)
+ {
+ if (first)
+ first = false;
+ else
+ o << ' ';
+
+ const char* v (*ev);
+
+ // If there is no `=` in the string, then this is just a name
+ // (variable unset) and we print it as the empty string assignment.
+ //
+ const char* eq (strchr (v, '='));
+
+ // If there is the space character in the string, then we quote the
+ // variable value, unless this is the variable name that contains the
+ // space character in which case we quote the whole (potentially
+ // broken) assignment.
+ //
+ const char* sp (strchr (v, ' '));
+
+ if (eq != nullptr) // Variable assignment?
+ {
+ if (sp == nullptr) // No space?
+ {
+ o << v;
+ }
+ else if (eq < sp) // Space in the value?
+ {
+ o.write (v, eq - v + 1); // Name and '='.
+ o << '"' << eq + 1 << '"'; // Quoted value.
+ }
+ else // Space in the name.
+ o << '"' << v << '"';
+ }
+ else // Variable unset.
+ {
+ if (sp == nullptr) // No space?
+ o << v << '=';
+ else // Space in the name.
+ o << '"' << v << "=\"";
+ }
+ }
+ }
+
+ return o;
+ }
+}
diff --git a/libbutl/process-io.mxx b/libbutl/process-io.mxx
index 5471846..d07a212 100644
--- a/libbutl/process-io.mxx
+++ b/libbutl/process-io.mxx
@@ -40,4 +40,28 @@ LIBBUTL_MODEXPORT namespace butl
process::print (o, a.argv, a.argc);
return o;
}
+
+ // Print the environment variables and the current working directory (if
+ // specified) in a POSIX shell command line notation. The process path
+ // itself is not printed. For example:
+ //
+ // LC_ALL=C
+ //
+ // If an environment variable is in the `name` rather than in the
+ // `name=value` form, then it is considered unset. Since there is no POSIX
+ // way to unset a variable on the command line, this information is printed
+ // as `name=` (ambiguous with assigning an empty value but the two cases are
+ // normally handled in the same way). For example:
+ //
+ // PATH= LC_ALL=C
+ //
+ // Note that since there is no POSIX way to change the current working
+ // directory of a command to be executed, this information is printed in a
+ // pseudo-notation by assigning to PWD (which, according POSIX, would result
+ // in the undefined behavior of the cwd utility). For example:
+ //
+ // PWD=/tmp LC_ALL=C
+ //
+ LIBBUTL_SYMEXPORT std::ostream&
+ operator<< (std::ostream&, const process_env&);
}
diff --git a/libbutl/process.mxx b/libbutl/process.mxx
index 1f378c4..b8c6054 100644
--- a/libbutl/process.mxx
+++ b/libbutl/process.mxx
@@ -494,7 +494,6 @@ LIBBUTL_MODEXPORT namespace butl
quote_argument (const char*, std::string& buffer);
#endif
-
public:
id_type
id () const;
@@ -548,6 +547,16 @@ LIBBUTL_MODEXPORT namespace butl
const dir_path* cwd = nullptr;
const char* const* vars = nullptr;
+ // Return true if there is an "environment", that is, either the current
+ // working directory or environment variables.
+ //
+ bool
+ env () const
+ {
+ return (cwd != nullptr && !cwd->empty ()) ||
+ (vars != nullptr && *vars != nullptr);
+ }
+
process_env (const process_path& p,
const dir_path& c = dir_path (),
const char* const* v = nullptr)