diff options
-rw-r--r-- | libbutl/process.cxx | 55 | ||||
-rw-r--r-- | libbutl/process.mxx | 10 |
2 files changed, 44 insertions, 21 deletions
diff --git a/libbutl/process.cxx b/libbutl/process.cxx index fa2f583..c6bf7cb 100644 --- a/libbutl/process.cxx +++ b/libbutl/process.cxx @@ -1067,6 +1067,37 @@ namespace butl bool locked_ = true; }; + const char* process:: + quote_argument (const char* a, string& s) + { + // On Windows we need to protect values with spaces using quotes. + // Since there could be actual quotes in the value, we need to + // escape them. + // + bool q (*a == '\0' || strchr (a, ' ') != nullptr); + + if (!q && strchr (a, '"') == nullptr) + return a; + + s.clear (); + + if (q) + s += '"'; + + for (size_t i (0), n (strlen (a)); i != n; ++i) + { + if (a[i] != '"') + s += a[i]; + else + s += "\\\""; + } + + if (q) + s += '"'; + + return s.c_str (); + } + // Protected by process_spawn_mutex. See below for the gory details. // static map<string, bool> detect_msys_cache_; @@ -1257,35 +1288,17 @@ namespace butl // string cmd_line; { - auto append = [&cmd_line] (const string& a) + auto append = [&cmd_line, buf = string ()] (const char* a) mutable { if (!cmd_line.empty ()) cmd_line += ' '; - // On Windows we need to protect values with spaces using quotes. - // Since there could be actual quotes in the value, we need to escape - // them. - // - bool quote (a.empty () || a.find (' ') != string::npos); - - if (quote) - cmd_line += '"'; - - for (size_t i (0); i < a.size (); ++i) - { - if (a[i] == '"') - cmd_line += "\\\""; - else - cmd_line += a[i]; - } - - if (quote) - cmd_line += '"'; + cmd_line += quote_argument (a, buf); }; if (batch) { - append (*batch); + append (batch->c_str ()); append ("/c"); append (pp.effect_string ()); } diff --git a/libbutl/process.mxx b/libbutl/process.mxx index 8f9d2de..c18ae43 100644 --- a/libbutl/process.mxx +++ b/libbutl/process.mxx @@ -462,6 +462,16 @@ LIBBUTL_MODEXPORT namespace butl static void print (std::ostream&, const char* const args[], size_t n = 0); + // Quote and escape the specified command line argument. Return the + // original string if neither is necessary and a pointer to the provided + // buffer string containing the escaped version otherwise. + // +#ifdef _WIN32 + static const char* + quote_argument (const char*, std::string& buffer); +#endif + + public: id_type id () const; |