File indexing completed on 2025-12-13 10:03:35
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/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(), ' ');
0039 if (it != arg.end())
0040 {
0041
0042
0043 arg.insert(arg.begin(), '"' );
0044 arg += '"';
0045 }
0046
0047 if (!st.empty())
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
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
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())
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
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