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_WINDOWS_BASIC_CMD_HPP_
8 #define BOOST_PROCESS_DETAIL_WINDOWS_BASIC_CMD_HPP_
9
10 #include <boost/algorithm/string/trim.hpp>
11 #include <boost/algorithm/string/replace.hpp>
12 #include <boost/process/shell.hpp>
13 #include <boost/process/detail/windows/handler.hpp>
14
15 #include <vector>
16 #include <string>
17 #include <iterator>
18
19
20 namespace boost
21 {
22 namespace process
23 {
24 namespace detail
25 {
26 namespace windows
27 {
28
build_args(const std::string & exe,std::vector<std::string> && data)29 inline std::string build_args(const std::string & exe, std::vector<std::string> && data)
30 {
31 std::string st = exe;
32
33 //put in quotes if it has spaces or double quotes
34 if(!exe.empty())
35 {
36 auto it = st.find_first_of(" \"");
37
38 if(it != st.npos)//contains spaces.
39 {
40 // double existing quotes
41 boost::replace_all(st, "\"", "\"\"");
42
43 // surround with quotes
44 st.insert(st.begin(), '"');
45 st += '"';
46 }
47 }
48
49 for (auto & arg : data)
50 {
51 if(!arg.empty())
52 {
53 auto it = arg.find_first_of(" \"");//contains space or double quotes?
54 if(it != arg.npos)//yes
55 {
56 // double existing quotes
57 boost::replace_all(arg, "\"", "\"\"");
58
59 // surround with quotes
60 arg.insert(arg.begin(), '"');
61 arg += '"';
62 }
63 }
64
65 if (!st.empty())//first one does not need a preceeding space
66 st += ' ';
67
68 st += arg;
69 }
70 return st;
71 }
72
build_args(const std::wstring & exe,std::vector<std::wstring> && data)73 inline std::wstring build_args(const std::wstring & exe, std::vector<std::wstring> && data)
74 {
75 std::wstring st = exe;
76
77 //put in quotes if it has spaces or double quotes
78 if(!exe.empty())
79 {
80 auto it = st.find_first_of(L" \"");
81
82 if(it != st.npos)//contains spaces or double quotes.
83 {
84 // double existing quotes
85 boost::replace_all(st, L"\"", L"\"\"");
86
87 // surround with quotes
88 st.insert(st.begin(), L'"');
89 st += L'"';
90 }
91 }
92
93 for(auto & arg : data)
94 {
95 if(!arg.empty())
96 {
97 auto it = arg.find_first_of(L" \"");//contains space or double quotes?
98 if(it != arg.npos)//yes
99 {
100 // double existing quotes
101 boost::replace_all(arg, L"\"", L"\"\"");
102
103 // surround with quotes
104 arg.insert(arg.begin(), L'"');
105 arg += '"';
106 }
107 }
108
109 if (!st.empty())//first one does not need a preceeding space
110 st += L' ';
111
112 st += arg;
113 }
114 return st;
115 }
116
117 template<typename Char>
118 struct exe_cmd_init : handler_base_ext
119 {
120 using value_type = Char;
121 using string_type = std::basic_string<value_type>;
122
c_argboost::process::detail::windows::exe_cmd_init123 static const char* c_arg(char) { return "/c";}
c_argboost::process::detail::windows::exe_cmd_init124 static const wchar_t* c_arg(wchar_t) { return L"/c";}
125
exe_cmd_initboost::process::detail::windows::exe_cmd_init126 exe_cmd_init(const string_type & exe, bool cmd_only = false)
127 : exe(exe), args({}), cmd_only(cmd_only) {};
exe_cmd_initboost::process::detail::windows::exe_cmd_init128 exe_cmd_init(string_type && exe, bool cmd_only = false)
129 : exe(std::move(exe)), args({}), cmd_only(cmd_only) {};
130
exe_cmd_initboost::process::detail::windows::exe_cmd_init131 exe_cmd_init(string_type && exe, std::vector<string_type> && args)
132 : exe(std::move(exe)), args(build_args(this->exe, std::move(args))), cmd_only(false) {};
133 template <class Executor>
on_setupboost::process::detail::windows::exe_cmd_init134 void on_setup(Executor& exec) const
135 {
136
137 if (cmd_only && args.empty())
138 exec.cmd_line = exe.c_str();
139 else
140 {
141 exec.exe = exe.c_str();
142 exec.cmd_line = args.c_str();
143 }
144 }
exe_argsboost::process::detail::windows::exe_cmd_init145 static exe_cmd_init<Char> exe_args(string_type && exe, std::vector<string_type> && args)
146 {
147 return exe_cmd_init<Char>(std::move(exe), std::move(args));
148 }
cmdboost::process::detail::windows::exe_cmd_init149 static exe_cmd_init<Char> cmd(string_type&& cmd)
150 {
151 return exe_cmd_init<Char>(std::move(cmd), true);
152 }
exe_args_shellboost::process::detail::windows::exe_cmd_init153 static exe_cmd_init<Char> exe_args_shell(string_type && exe, std::vector<string_type> && args)
154 {
155 std::vector<string_type> args_ = {c_arg(Char()), std::move(exe)};
156 args_.insert(args_.end(), std::make_move_iterator(args.begin()), std::make_move_iterator(args.end()));
157 string_type sh = get_shell(Char());
158
159 return exe_cmd_init<Char>(std::move(sh), std::move(args_));
160 }
161
get_shellboost::process::detail::windows::exe_cmd_init162 static std:: string get_shell(char) {return shell(). string(codecvt()); }
get_shellboost::process::detail::windows::exe_cmd_init163 static std::wstring get_shell(wchar_t) {return shell().wstring(codecvt());}
164
cmd_shellboost::process::detail::windows::exe_cmd_init165 static exe_cmd_init<Char> cmd_shell(string_type&& cmd)
166 {
167 std::vector<string_type> args = {c_arg(Char()), std::move(cmd)};
168 string_type sh = get_shell(Char());
169
170 return exe_cmd_init<Char>(
171 std::move(sh),
172 std::move(args));
173 }
174 private:
175 string_type exe;
176 string_type args;
177 bool cmd_only;
178 };
179
180 }
181
182
183
184 }
185 }
186 }
187
188
189
190 #endif /* INCLUDE_BOOST_PROCESS_WINDOWS_ARGS_HPP_ */
191