basic_cmd.hpp 5.3 KB

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