Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-13 10:03:35

0001 // Copyright (c) 2016 Klemens D. Morgenstern
0002 //
0003 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0004 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0005 
0006 
0007 #ifndef BOOST_PROCESS_DETAIL_POSIX_BASIC_CMD_HPP_
0008 #define BOOST_PROCESS_DETAIL_POSIX_BASIC_CMD_HPP_
0009 
0010 #include <boost/process/v1/detail/config.hpp>
0011 #include <boost/process/v1/detail/posix/handler.hpp>
0012 #include <boost/process/v1/detail/posix/cmd.hpp>
0013 #include <boost/algorithm/string/replace.hpp>
0014 #include <boost/process/v1/shell.hpp>
0015 #include <boost/algorithm/string/trim.hpp>
0016 #include <boost/algorithm/string/join.hpp>
0017 #include <string>
0018 #include <vector>
0019 
0020 namespace boost
0021 {
0022 namespace process
0023 {
0024 BOOST_PROCESS_V1_INLINE namespace v1
0025 {
0026 namespace detail
0027 {
0028 namespace posix
0029 {
0030 
0031 inline std::string build_cmd_shell(const std::string & exe, std::vector<std::string> && data)
0032 {
0033     std::string st = exe;
0034     for (auto & arg : data)
0035     {
0036         boost::replace_all(arg, "\"", "\\\"");
0037 
0038         auto it = std::find(arg.begin(), arg.end(), ' ');//contains space?
0039         if (it != arg.end())//ok, contains spaces.
0040         {
0041             //the first one is put directly onto the output,
0042             //because then I don't have to copy the whole string
0043             arg.insert(arg.begin(), '"' );
0044             arg += '"'; //that is the post one.
0045         }
0046 
0047         if (!st.empty())//first one does not need a preceding space
0048             st += ' ';
0049 
0050         st += arg;
0051     }
0052     return  st ;
0053 }
0054 
0055 inline std::vector<std::string>  build_args(const std::string & data)
0056 {
0057     std::vector<std::string>  st;
0058     
0059     typedef std::string::const_iterator itr_t;
0060 
0061     //normal quotes outside can be stripped, inside ones marked as \" will be replaced.
0062     auto make_entry = [](const itr_t & begin, const itr_t & end)
0063     {
0064         std::string data;
0065         if ((*begin == '"') && (*(end-1) == '"'))
0066             data.assign(begin+1, end-1);
0067         else
0068             data.assign(begin, end);
0069 
0070         boost::replace_all(data, "\\\"", "\"");
0071         return data;
0072 
0073     };
0074 
0075     bool in_quote = false;
0076 
0077     auto part_beg = data.cbegin();
0078     auto itr = data.cbegin();
0079 
0080     for (; itr != data.cend(); itr++)
0081     {
0082         if (*itr == '"')
0083             in_quote ^= true;
0084 
0085         if (!in_quote && (*itr == ' '))
0086         {
0087             //alright, got a space
0088 
0089             if ((itr != data.cbegin()) && (*(itr -1) != ' ' ))
0090                 st.push_back(make_entry(part_beg, itr));
0091 
0092             part_beg = itr+1;
0093         }
0094     }
0095     if (part_beg != itr)
0096         st.emplace_back(make_entry(part_beg, itr));
0097 
0098 
0099     return st;
0100 }
0101 
0102 template<typename Char>
0103 struct exe_cmd_init;
0104 
0105 template<>
0106 struct exe_cmd_init<char> : boost::process::v1::detail::api::handler_base_ext
0107 {
0108     exe_cmd_init(const exe_cmd_init & ) = delete;
0109     exe_cmd_init(exe_cmd_init && ) = default;
0110     exe_cmd_init(std::string && exe, std::vector<std::string> && args)
0111             : exe(std::move(exe)), args(std::move(args)) {};
0112     template <class Executor>
0113     void on_setup(Executor& exec) 
0114     {
0115         if (exe.empty()) //cmd style
0116         {
0117             if (args.empty())
0118                 exec.exe = "";
0119             else
0120                 exec.exe = args.front().c_str();    
0121             exec.cmd_style = true;
0122         }
0123         else
0124             exec.exe = &exe.front();
0125 
0126         cmd_impl = make_cmd();
0127         exec.cmd_line = cmd_impl.data();
0128     }
0129     static exe_cmd_init exe_args(std::string && exe, std::vector<std::string> && args) {return exe_cmd_init(std::move(exe), std::move(args));}
0130     static exe_cmd_init cmd     (std::string && cmd)
0131     {
0132         auto args = build_args(cmd);
0133         return exe_cmd_init({}, std::move(args));
0134     }
0135 
0136     static exe_cmd_init exe_args_shell(std::string&& exe, std::vector<std::string> && args)
0137     {
0138         auto cmd = build_cmd_shell(std::move(exe), std::move(args));
0139 
0140         std::vector<std::string> args_ = {"-c", std::move(cmd)};
0141         std::string sh = shell().string();
0142 
0143         return exe_cmd_init(std::move(sh), std::move(args_));
0144     }
0145     static exe_cmd_init cmd_shell(std::string&& cmd)
0146     {
0147         std::vector<std::string> args = {"-c", cmd};
0148         std::string sh = shell().string();
0149 
0150         return exe_cmd_init(
0151                 std::move(sh),
0152                 {std::move(args)});
0153     }
0154 private:
0155     inline std::vector<char*> make_cmd();
0156     std::string exe;
0157     std::vector<std::string> args;
0158     std::vector<char*> cmd_impl;
0159 };
0160 
0161 std::vector<char*> exe_cmd_init<char>::make_cmd()
0162 {
0163     // any string must be writable.
0164     static char empty_string[1] = "";
0165     std::vector<char*> vec;
0166     if (!exe.empty())
0167         vec.push_back(exe.empty() ? empty_string : &exe.front());
0168 
0169     if (!args.empty()) {
0170         for (auto & v : args)
0171             vec.push_back(v.empty() ? empty_string : &v.front());
0172     }
0173 
0174     vec.push_back(nullptr);
0175 
0176     return vec;
0177 }
0178 
0179 
0180 }}}}}
0181 
0182 #endif