]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/process/detail/posix/basic_cmd.hpp
update sources to ceph Nautilus 14.2.1
[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 cmd_impl = make_cmd();
122 exec.cmd_line = cmd_impl.data();
123 }
124 static exe_cmd_init exe_args(std::string && exe, std::vector<std::string> && args) {return exe_cmd_init(std::move(exe), std::move(args));}
125 static exe_cmd_init cmd (std::string && cmd)
126 {
127 auto args = build_args(cmd);
128 return exe_cmd_init({}, std::move(args));
129 }
130
131 static exe_cmd_init exe_args_shell(std::string&& exe, std::vector<std::string> && args)
132 {
133 auto cmd = build_cmd_shell(std::move(exe), std::move(args));
134
135 std::vector<std::string> args_ = {"-c", std::move(cmd)};
136 std::string sh = shell().string();
137
138 return exe_cmd_init(std::move(sh), std::move(args_));
139 }
140 static exe_cmd_init cmd_shell(std::string&& cmd)
141 {
142 std::vector<std::string> args = {"-c", "\"" + cmd + "\""};
143 std::string sh = shell().string();
144
145 return exe_cmd_init(
146 std::move(sh),
147 {std::move(args)});
148 }
149 private:
150 inline std::vector<char*> make_cmd();
151 std::string exe;
152 std::vector<std::string> args;
153 std::vector<char*> cmd_impl;
154 };
155
156 std::vector<char*> exe_cmd_init<char>::make_cmd()
157 {
158 std::vector<char*> vec;
159 if (!exe.empty())
160 vec.push_back(&exe.front());
161
162 if (!args.empty()) {
163 for (auto & v : args)
164 vec.push_back(&v.front());
165 }
166
167 vec.push_back(nullptr);
168
169 return vec;
170 }
171
172
173 }}}}
174
175 #endif