basic_cmd.hpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  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. if (!st.empty())//first one does not need a preceeding space
  53. st += ' ';
  54. st += arg;
  55. }
  56. return st;
  57. }
  58. inline std::wstring build_args(const std::wstring & exe, std::vector<std::wstring> && data)
  59. {
  60. std::wstring st = exe;
  61. //put in quotes if it has spaces or double quotes
  62. if(!exe.empty())
  63. {
  64. auto it = st.find_first_of(L" \"");
  65. if(it != st.npos)//contains spaces or double quotes.
  66. {
  67. // double existing quotes
  68. boost::replace_all(st, L"\"", L"\"\"");
  69. // surround with quotes
  70. st.insert(st.begin(), L'"');
  71. st += L'"';
  72. }
  73. }
  74. for(auto & arg : data)
  75. {
  76. if(!arg.empty())
  77. {
  78. auto it = arg.find_first_of(L" \"");//contains space or double quotes?
  79. if(it != arg.npos)//yes
  80. {
  81. // double existing quotes
  82. boost::replace_all(arg, L"\"", L"\"\"");
  83. // surround with quotes
  84. arg.insert(arg.begin(), L'"');
  85. arg += '"';
  86. }
  87. }
  88. if (!st.empty())//first one does not need a preceeding space
  89. st += L' ';
  90. st += arg;
  91. }
  92. return st;
  93. }
  94. template<typename Char>
  95. struct exe_cmd_init : handler_base_ext
  96. {
  97. using value_type = Char;
  98. using string_type = std::basic_string<value_type>;
  99. static const char* c_arg(char) { return "/c";}
  100. static const wchar_t* c_arg(wchar_t) { return L"/c";}
  101. exe_cmd_init(const string_type & exe, bool cmd_only = false)
  102. : exe(exe), args({}), cmd_only(cmd_only) {};
  103. exe_cmd_init(string_type && exe, bool cmd_only = false)
  104. : exe(std::move(exe)), args({}), cmd_only(cmd_only) {};
  105. exe_cmd_init(string_type && exe, std::vector<string_type> && args)
  106. : exe(std::move(exe)), args(build_args(this->exe, std::move(args))), cmd_only(false) {};
  107. template <class Executor>
  108. void on_setup(Executor& exec) const
  109. {
  110. if (cmd_only && args.empty())
  111. exec.cmd_line = exe.c_str();
  112. else
  113. {
  114. exec.exe = exe.c_str();
  115. exec.cmd_line = args.c_str();
  116. }
  117. }
  118. static exe_cmd_init<Char> exe_args(string_type && exe, std::vector<string_type> && args)
  119. {
  120. return exe_cmd_init<Char>(std::move(exe), std::move(args));
  121. }
  122. static exe_cmd_init<Char> cmd(string_type&& cmd)
  123. {
  124. return exe_cmd_init<Char>(std::move(cmd), true);
  125. }
  126. static exe_cmd_init<Char> exe_args_shell(string_type && exe, std::vector<string_type> && args)
  127. {
  128. std::vector<string_type> args_ = {c_arg(Char()), std::move(exe)};
  129. args_.insert(args_.end(), std::make_move_iterator(args.begin()), std::make_move_iterator(args.end()));
  130. string_type sh = get_shell(Char());
  131. return exe_cmd_init<Char>(std::move(sh), std::move(args_));
  132. }
  133. static std:: string get_shell(char) {return shell(). string(codecvt()); }
  134. static std::wstring get_shell(wchar_t) {return shell().wstring(codecvt());}
  135. static exe_cmd_init<Char> cmd_shell(string_type&& cmd)
  136. {
  137. std::vector<string_type> args = {c_arg(Char()), std::move(cmd)};
  138. string_type sh = get_shell(Char());
  139. return exe_cmd_init<Char>(
  140. std::move(sh),
  141. std::move(args));
  142. }
  143. private:
  144. string_type exe;
  145. string_type args;
  146. bool cmd_only;
  147. };
  148. }
  149. }
  150. }
  151. }
  152. #endif /* INCLUDE_BOOST_PROCESS_WINDOWS_ARGS_HPP_ */