]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/process/detail/posix/basic_cmd.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / process / detail / posix / basic_cmd.hpp
1 // Copyright (c) 2016 Klemens D. Morgenstern
2 //
3 // Distributed under the Boost Software License, Version 1.0. (See accompanying
4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5
6
7 #ifndef BOOST_PROCESS_DETAIL_POSIX_BASIC_CMD_HPP_
8 #define BOOST_PROCESS_DETAIL_POSIX_BASIC_CMD_HPP_
9
10 #include <boost/process/detail/posix/handler.hpp>
11 #include <boost/process/detail/posix/cmd.hpp>
12 #include <boost/algorithm/string/replace.hpp>
13 #include <boost/process/shell.hpp>
14 #include <boost/algorithm/string/trim.hpp>
15 #include <boost/algorithm/string/join.hpp>
16 #include <string>
17 #include <vector>
18
19 namespace boost
20 {
21 namespace process
22 {
23 namespace detail
24 {
25 namespace posix
26 {
27
28
29 inline std::string build_cmd_shell(const std::string & exe, std::vector<std::string> && data)
30 {
31 std::string st = exe;
32 for (auto & arg : data)
33 {
34 boost::replace_all(arg, "\"", "\\\"");
35
36 auto it = std::find(arg.begin(), arg.end(), ' ');//contains space?
37 if (it != arg.end())//ok, contains spaces.
38 {
39 //the first one is put directly onto the output,
40 //because then I don't have to copy the whole string
41 arg.insert(arg.begin(), '"' );
42 arg += '"'; //thats the post one.
43 }
44
45 if (!st.empty())//first one does not need a preceeding space
46 st += ' ';
47
48 st += arg;
49 }
50 return st ;
51 }
52
53 inline std::vector<std::string> build_args(const std::string & data)
54 {
55 std::vector<std::string> st;
56
57 typedef std::string::const_iterator itr_t;
58
59 //normal quotes outside can be stripped, inside ones marked as \" will be replaced.
60 auto make_entry = [](const itr_t & begin, const itr_t & end)
61 {
62 std::string data;
63 if ((*begin == '"') && (*(end-1) == '"'))
64 data.assign(begin+1, end-1);
65 else
66 data.assign(begin, end);
67
68 boost::replace_all(data, "\\\"", "\"");
69 return data;
70
71 };
72
73 bool in_quote = false;
74
75 auto part_beg = data.cbegin();
76 auto itr = data.cbegin();
77
78 for (; itr != data.cend(); itr++)
79 {
80 if (*itr == '"')
81 in_quote ^= true;
82
83 if (!in_quote && (*itr == ' '))
84 {
85 //alright, got a space
86
87 if ((itr != data.cbegin()) && (*(itr -1) != ' ' ))
88 st.push_back(make_entry(part_beg, itr));
89
90 part_beg = itr+1;
91 }
92 }
93 if (part_beg != itr)
94 st.emplace_back(make_entry(part_beg, itr));
95
96
97 return st;
98 }
99
100 template<typename Char>
101 struct exe_cmd_init;
102
103 template<>
104 struct exe_cmd_init<char> : boost::process::detail::api::handler_base_ext
105 {
106 exe_cmd_init(const exe_cmd_init & ) = delete;
107 exe_cmd_init(exe_cmd_init && ) = default;
108 exe_cmd_init(std::string && exe, std::vector<std::string> && args)
109 : exe(std::move(exe)), args(std::move(args)) {};
110 template <class Executor>
111 void on_setup(Executor& exec)
112 {
113 if (exe.empty()) //cmd style
114 {
115 exec.exe = args.front().c_str();
116 exec.cmd_style = true;
117 }
118 else
119 exec.exe = &exe.front();
120
121
122 if (!args.empty())
123 {
124 cmd_impl = make_cmd();
125 exec.cmd_line = cmd_impl.data();
126 }
127 }
128 static exe_cmd_init exe_args(std::string && exe, std::vector<std::string> && args) {return exe_cmd_init(std::move(exe), std::move(args));}
129 static exe_cmd_init cmd (std::string && cmd)
130 {
131 auto args = build_args(cmd);
132 return exe_cmd_init({}, std::move(args));
133 }
134
135 static exe_cmd_init exe_args_shell(std::string&& exe, std::vector<std::string> && args)
136 {
137 auto cmd = build_cmd_shell(std::move(exe), std::move(args));
138
139 std::vector<std::string> args_ = {"-c", std::move(cmd)};
140 std::string sh = shell().string();
141
142 return exe_cmd_init(std::move(sh), std::move(args_));
143 }
144 static exe_cmd_init cmd_shell(std::string&& cmd)
145 {
146 std::vector<std::string> args = {"-c", "\"" + cmd + "\""};
147 std::string sh = shell().string();
148
149 return exe_cmd_init(
150 std::move(sh),
151 {std::move(args)});
152 }
153 private:
154 inline std::vector<char*> make_cmd();
155 std::string exe;
156 std::vector<std::string> args;
157 std::vector<char*> cmd_impl;
158 };
159
160 std::vector<char*> exe_cmd_init<char>::make_cmd()
161 {
162 std::vector<char*> vec;
163 if (!exe.empty())
164 vec.push_back(&exe.front());
165
166 for (auto & v : args)
167 vec.push_back(&v.front());
168
169 vec.push_back(nullptr);
170
171 return vec;
172 }
173
174
175 }}}}
176
177 #endif