basic_cmd.hpp 5.5 KB

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