basic_cmd.hpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  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
  26. {
  27. boost::replace_all(st, "\"", "\\\"");
  28. auto it = std::find(st.begin(), st.end(), ' ');
  29. if (it != st.end())//contains spaces.
  30. {
  31. st.insert(st.begin(), '"');
  32. st += '"';
  33. }
  34. }
  35. for (auto & arg : data)
  36. {
  37. boost::replace_all(arg, "\"", "\\\"");
  38. auto it = std::find(arg.begin(), arg.end(), ' ');//contains space?
  39. if (it != arg.end())//ok, contains spaces.
  40. {
  41. //the first one is put directly onto the output,
  42. //because then I don't have to copy the whole string
  43. arg.insert(arg.begin(), '"');
  44. arg += '"'; //thats the post one.
  45. }
  46. if (!st.empty())//first one does not need a preceeding space
  47. st += ' ';
  48. st += arg;
  49. }
  50. return st;
  51. }
  52. inline std::wstring build_args(const std::wstring & exe, std::vector<std::wstring> && data)
  53. {
  54. std::wstring st = exe;
  55. //put in quotes if it has spaces
  56. {
  57. boost::replace_all(st, L"\"", L"\\\"");
  58. auto it = std::find(st.begin(), st.end(), L' ');
  59. if (it != st.end())//contains spaces.
  60. {
  61. st.insert(st.begin(), L'"');
  62. st += L'"';
  63. }
  64. }
  65. for (auto & arg : data)
  66. {
  67. boost::replace_all(arg, L"\"", L"\\\"");
  68. auto it = std::find(arg.begin(), arg.end(), L' ');//contains space?
  69. if (it != arg.end())//ok, contains spaces.
  70. {
  71. //the first one is put directly onto the output,
  72. //because then I don't have to copy the whole string
  73. arg.insert(arg.begin(), L'"');
  74. arg += L'"'; //thats the post one.
  75. }
  76. if (!st.empty())//first one does not need a preceeding space
  77. st += L' ';
  78. st += arg;
  79. }
  80. return st;
  81. }
  82. template<typename Char>
  83. struct exe_cmd_init : handler_base_ext
  84. {
  85. using value_type = Char;
  86. using string_type = std::basic_string<value_type>;
  87. static const char* c_arg(char) { return "/c";}
  88. static const wchar_t* c_arg(wchar_t) { return L"/c";}
  89. exe_cmd_init(const string_type & exe, bool cmd_only = false)
  90. : exe(exe), args({}), cmd_only(cmd_only) {};
  91. exe_cmd_init(string_type && exe, bool cmd_only = false)
  92. : exe(std::move(exe)), args({}), cmd_only(cmd_only) {};
  93. exe_cmd_init(string_type && exe, std::vector<string_type> && args)
  94. : exe(std::move(exe)), args(build_args(this->exe, std::move(args))), cmd_only(false) {};
  95. template <class Executor>
  96. void on_setup(Executor& exec) const
  97. {
  98. if (cmd_only && args.empty())
  99. exec.cmd_line = exe.c_str();
  100. else
  101. {
  102. exec.exe = exe.c_str();
  103. exec.cmd_line = args.c_str();
  104. }
  105. }
  106. static exe_cmd_init<Char> exe_args(string_type && exe, std::vector<string_type> && args)
  107. {
  108. return exe_cmd_init<Char>(std::move(exe), std::move(args));
  109. }
  110. static exe_cmd_init<Char> cmd(string_type&& cmd)
  111. {
  112. return exe_cmd_init<Char>(std::move(cmd), true);
  113. }
  114. static exe_cmd_init<Char> exe_args_shell(string_type && exe, std::vector<string_type> && args)
  115. {
  116. std::vector<string_type> args_ = {c_arg(Char()), std::move(exe)};
  117. args_.insert(args_.end(), std::make_move_iterator(args.begin()), std::make_move_iterator(args.end()));
  118. string_type sh = get_shell(Char());
  119. return exe_cmd_init<Char>(std::move(sh), std::move(args_));
  120. }
  121. static std:: string get_shell(char) {return shell(). string(codecvt()); }
  122. static std::wstring get_shell(wchar_t) {return shell().wstring(codecvt());}
  123. static exe_cmd_init<Char> cmd_shell(string_type&& cmd)
  124. {
  125. std::vector<string_type> args = {c_arg(Char()), std::move(cmd)};
  126. string_type sh = get_shell(Char());
  127. return exe_cmd_init<Char>(
  128. std::move(sh),
  129. std::move(args));
  130. }
  131. private:
  132. string_type exe;
  133. string_type args;
  134. bool cmd_only;
  135. };
  136. }
  137. }
  138. }
  139. }
  140. #endif /* INCLUDE_BOOST_PROCESS_WINDOWS_ARGS_HPP_ */