shell.ipp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. // Copyright (c) 2022 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_V2_IMPL_SHELL_IPP
  6. #define BOOST_PROCESS_V2_IMPL_SHELL_IPP
  7. #include <boost/process/v2/detail/config.hpp>
  8. #include <boost/process/v2/detail/last_error.hpp>
  9. #include <boost/process/v2/detail/throw_error.hpp>
  10. #include <boost/process/v2/detail/config.hpp>
  11. #include <boost/process/v2/error.hpp>
  12. #include <boost/process/v2/shell.hpp>
  13. #if defined(BOOST_PROCESS_V2_WINDOWS)
  14. #include <shellapi.h>
  15. #else
  16. #include <wordexp.h>
  17. #endif
  18. BOOST_PROCESS_V2_BEGIN_NAMESPACE
  19. #if defined(BOOST_PROCESS_V2_WINDOWS)
  20. BOOST_PROCESS_V2_DECL const error_category& get_shell_category()
  21. {
  22. return system_category();
  23. }
  24. #else
  25. struct shell_category_t final : public error_category
  26. {
  27. shell_category_t() : error_category(0xDAF1u) {}
  28. const char* name() const noexcept
  29. {
  30. return "process.v2.utf8";
  31. }
  32. std::string message(int value) const
  33. {
  34. switch (value)
  35. {
  36. case WRDE_BADCHAR:
  37. return "Illegal occurrence of newline or one of |, &, ;, <, >, (, ), {, }.";
  38. case WRDE_BADVAL:
  39. return "An undefined shell variable was referenced, and the WRDE_UNDEF flag told us to consider this an error.";
  40. case WRDE_CMDSUB:
  41. return "Command substitution occurred, and the WRDE_NOCMD flag told us to consider this an error.";
  42. case WRDE_NOSPACE:
  43. return "Out of memory.";
  44. case WRDE_SYNTAX:
  45. return "Shell syntax error, such as unbalanced parentheses or unmatched quotes.";
  46. default:
  47. return "process.v2.wordexp error";
  48. }
  49. }
  50. };
  51. BOOST_PROCESS_V2_DECL const error_category& get_shell_category()
  52. {
  53. static shell_category_t instance;
  54. return instance;
  55. }
  56. #endif
  57. #if defined (BOOST_PROCESS_V2_WINDOWS)
  58. void shell::parse_()
  59. {
  60. argv_ = ::CommandLineToArgvW(input_.c_str(), &argc_);
  61. if (argv_ == nullptr)
  62. {
  63. error_code ec;
  64. BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
  65. throw system_error(ec, "shell::parse");
  66. }
  67. }
  68. shell::~shell()
  69. {
  70. if (argv_ != nullptr)
  71. LocalFree(argv_);
  72. }
  73. auto shell::args() const-> args_type
  74. {
  75. return input_.c_str();
  76. }
  77. #else
  78. void shell::parse_()
  79. {
  80. wordexp_t we{};
  81. auto cd = wordexp(input_.c_str(), &we, WRDE_NOCMD);
  82. if (cd != 0)
  83. detail::throw_error(error_code(cd, get_shell_category()), "shell::parse");
  84. else
  85. {
  86. argc_ = static_cast<int>(we.we_wordc);
  87. argv_ = we.we_wordv;
  88. }
  89. free_argv_ = +[](int argc, char ** argv)
  90. {
  91. wordexp_t we{
  92. .we_wordc = static_cast<std::size_t>(argc),
  93. .we_wordv = argv,
  94. .we_offs = 0
  95. };
  96. wordfree(&we);
  97. };
  98. }
  99. shell::~shell()
  100. {
  101. if (argv_ != nullptr && free_argv_ != nullptr)
  102. free_argv_(argc_, argv_);
  103. }
  104. auto shell::args() const -> args_type
  105. {
  106. if (argc() == 0)
  107. {
  108. static const char * helper = nullptr;
  109. return &helper;
  110. }
  111. else
  112. return const_cast<const char**>(argv());
  113. }
  114. #endif
  115. BOOST_PROCESS_V2_END_NAMESPACE
  116. #endif //BOOST_PROCESS_V2_IMPL_SHELL_IPP