File indexing completed on 2025-01-18 09:50:05
0001
0002
0003
0004
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/detail/posix/handler.hpp>
0011 #include <boost/process/detail/posix/cmd.hpp>
0012 #include <boost/algorithm/string/replace.hpp>
0013 #include <boost/process/shell.hpp>
0014 #include <boost/algorithm/string/trim.hpp>
0015 #include <boost/algorithm/string/join.hpp>
0016 #include <string>
0017 #include <vector>
0018
0019 namespace boost
0020 {
0021 namespace process
0022 {
0023 namespace detail
0024 {
0025 namespace posix
0026 {
0027
0028
0029 inline std::string build_cmd_shell(const std::string & exe, std::vector<std::string> && data)
0030 {
0031 std::string st = exe;
0032 for (auto & arg : data)
0033 {
0034 boost::replace_all(arg, "\"", "\\\"");
0035
0036 auto it = std::find(arg.begin(), arg.end(), ' ');
0037 if (it != arg.end())
0038 {
0039
0040
0041 arg.insert(arg.begin(), '"' );
0042 arg += '"';
0043 }
0044
0045 if (!st.empty())
0046 st += ' ';
0047
0048 st += arg;
0049 }
0050 return st ;
0051 }
0052
0053 inline std::vector<std::string> build_args(const std::string & data)
0054 {
0055 std::vector<std::string> st;
0056
0057 typedef std::string::const_iterator itr_t;
0058
0059
0060 auto make_entry = [](const itr_t & begin, const itr_t & end)
0061 {
0062 std::string data;
0063 if ((*begin == '"') && (*(end-1) == '"'))
0064 data.assign(begin+1, end-1);
0065 else
0066 data.assign(begin, end);
0067
0068 boost::replace_all(data, "\\\"", "\"");
0069 return data;
0070
0071 };
0072
0073 bool in_quote = false;
0074
0075 auto part_beg = data.cbegin();
0076 auto itr = data.cbegin();
0077
0078 for (; itr != data.cend(); itr++)
0079 {
0080 if (*itr == '"')
0081 in_quote ^= true;
0082
0083 if (!in_quote && (*itr == ' '))
0084 {
0085
0086
0087 if ((itr != data.cbegin()) && (*(itr -1) != ' ' ))
0088 st.push_back(make_entry(part_beg, itr));
0089
0090 part_beg = itr+1;
0091 }
0092 }
0093 if (part_beg != itr)
0094 st.emplace_back(make_entry(part_beg, itr));
0095
0096
0097 return st;
0098 }
0099
0100 template<typename Char>
0101 struct exe_cmd_init;
0102
0103 template<>
0104 struct exe_cmd_init<char> : boost::process::detail::api::handler_base_ext
0105 {
0106 exe_cmd_init(const exe_cmd_init & ) = delete;
0107 exe_cmd_init(exe_cmd_init && ) = default;
0108 exe_cmd_init(std::string && exe, std::vector<std::string> && args)
0109 : exe(std::move(exe)), args(std::move(args)) {};
0110 template <class Executor>
0111 void on_setup(Executor& exec)
0112 {
0113 if (exe.empty())
0114 {
0115 if (args.empty())
0116 exec.exe = "";
0117 else
0118 exec.exe = args.front().c_str();
0119 exec.cmd_style = true;
0120 }
0121 else
0122 exec.exe = &exe.front();
0123
0124 cmd_impl = make_cmd();
0125 exec.cmd_line = cmd_impl.data();
0126 }
0127 static exe_cmd_init exe_args(std::string && exe, std::vector<std::string> && args) {return exe_cmd_init(std::move(exe), std::move(args));}
0128 static exe_cmd_init cmd (std::string && cmd)
0129 {
0130 auto args = build_args(cmd);
0131 return exe_cmd_init({}, std::move(args));
0132 }
0133
0134 static exe_cmd_init exe_args_shell(std::string&& exe, std::vector<std::string> && args)
0135 {
0136 auto cmd = build_cmd_shell(std::move(exe), std::move(args));
0137
0138 std::vector<std::string> args_ = {"-c", std::move(cmd)};
0139 std::string sh = shell().string();
0140
0141 return exe_cmd_init(std::move(sh), std::move(args_));
0142 }
0143 static exe_cmd_init cmd_shell(std::string&& cmd)
0144 {
0145 std::vector<std::string> args = {"-c", cmd};
0146 std::string sh = shell().string();
0147
0148 return exe_cmd_init(
0149 std::move(sh),
0150 {std::move(args)});
0151 }
0152 private:
0153 inline std::vector<char*> make_cmd();
0154 std::string exe;
0155 std::vector<std::string> args;
0156 std::vector<char*> cmd_impl;
0157 };
0158
0159 std::vector<char*> exe_cmd_init<char>::make_cmd()
0160 {
0161
0162 static char empty_string[1] = "";
0163 std::vector<char*> vec;
0164 if (!exe.empty())
0165 vec.push_back(exe.empty() ? empty_string : &exe.front());
0166
0167 if (!args.empty()) {
0168 for (auto & v : args)
0169 vec.push_back(v.empty() ? empty_string : &v.front());
0170 }
0171
0172 vec.push_back(nullptr);
0173
0174 return vec;
0175 }
0176
0177
0178 }}}}
0179
0180 #endif