sparring_partner.cpp 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. // Copyright (c) 2006, 2007 Julio M. Merino Vidal
  2. // Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
  3. // Copyright (c) 2009 Boris Schaeling
  4. // Copyright (c) 2010 Felipe Tanus, Boris Schaeling
  5. // Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
  6. //
  7. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  9. #define BOOST_USE_WINDOWS_H
  10. #include <boost/program_options.hpp>
  11. #include <boost/filesystem.hpp>
  12. #include <boost/algorithm/string/join.hpp>
  13. #include <boost/range/iterator_range.hpp>
  14. #include <boost/range/algorithm/transform.hpp>
  15. #include <boost/range/algorithm_ext/push_back.hpp>
  16. #include <boost/lambda/lambda.hpp>
  17. #include <boost/process/environment.hpp>
  18. #include <boost/process/handles.hpp>
  19. #include <vector>
  20. #include <string>
  21. #include <iterator>
  22. #include <iostream>
  23. #include <cstdlib>
  24. #if defined(BOOST_POSIX_API)
  25. # include <boost/lexical_cast.hpp>
  26. # include <boost/iostreams/device/file_descriptor.hpp>
  27. # include <boost/iostreams/stream.hpp>
  28. # include <unistd.h>
  29. #elif defined(BOOST_WINDOWS_API)
  30. # include <windows.h>
  31. #endif
  32. using namespace boost::program_options;
  33. int main(int argc, char *argv[])
  34. {
  35. options_description desc;
  36. desc.add_options()
  37. ("echo-stdout", value<std::string>())
  38. ("echo-stderr", value<std::string>())
  39. ("echo-stdout-stderr", value<std::string>())
  40. ("echo-argv", bool_switch())
  41. ("exit-code", value<int>())
  42. ("wait", value<int>())
  43. ("is-closed-stdin", bool_switch())
  44. ("is-closed-stdout", bool_switch())
  45. ("is-closed-stderr", bool_switch())
  46. ("is-nul-stdin", bool_switch())
  47. ("is-nul-stdout", bool_switch())
  48. ("is-nul-stderr", bool_switch())
  49. ("loop", bool_switch())
  50. ("abort", bool_switch())
  51. ("prefix", value<std::string>())
  52. ("prefix-once", value<std::string>())
  53. ("pwd", bool_switch())
  54. ("query", value<std::string>())
  55. ("stdin-to-stdout", bool_switch())
  56. ("has-handle", value<std::uintptr_t>())
  57. #if defined(BOOST_POSIX_API)
  58. ("posix-echo-one", value<std::vector<std::string> >()->multitoken())
  59. ("posix-echo-two", value<std::vector<std::string> >()->multitoken());
  60. #elif defined(BOOST_WINDOWS_API)
  61. ("windows-print-showwindow", bool_switch())
  62. ("windows-print-flags", bool_switch());
  63. #endif
  64. variables_map vm;
  65. command_line_parser parser(argc, argv);
  66. store(parser.options(desc).allow_unregistered().run(), vm);
  67. notify(vm);
  68. if (vm.count("echo-stdout"))
  69. {
  70. std::cout << vm["echo-stdout"].as<std::string>() << std::endl;
  71. }
  72. else if (vm.count("echo-stderr"))
  73. {
  74. std::cerr << vm["echo-stderr"].as<std::string>() << std::endl;
  75. }
  76. else if (vm.count("echo-stdout-stderr"))
  77. {
  78. std::cout << vm["echo-stdout-stderr"].as<std::string>() << std::endl;
  79. std::cerr << vm["echo-stdout-stderr"].as<std::string>() << std::endl;
  80. }
  81. else if (vm["echo-argv"].as<bool>())
  82. {
  83. std::vector<char*> args(argv+1, argv + argc);
  84. for (auto & arg : args)
  85. std::cout << arg << std::endl;
  86. }
  87. else if (vm.count("exit-code"))
  88. {
  89. return vm["exit-code"].as<int>();
  90. }
  91. else if (vm.count("wait"))
  92. {
  93. int sec = vm["wait"].as<int>();
  94. #if defined(BOOST_POSIX_API)
  95. sleep(sec);
  96. #elif defined(BOOST_WINDOWS_API)
  97. Sleep(sec * 1000);
  98. #endif
  99. }
  100. else if (vm["is-closed-stdin"].as<bool>())
  101. {
  102. std::string s;
  103. std::cin >> s;
  104. return std::cin.eof() ? EXIT_SUCCESS : EXIT_FAILURE;
  105. }
  106. else if (vm["is-closed-stdout"].as<bool>())
  107. {
  108. std::cout << "foo" << std::endl;
  109. return std::cout.bad() ? EXIT_SUCCESS : EXIT_FAILURE;
  110. }
  111. else if (vm["is-closed-stderr"].as<bool>())
  112. {
  113. std::cerr << "foo" << std::endl;
  114. return std::cerr.bad() ? EXIT_SUCCESS : EXIT_FAILURE;
  115. }
  116. else if (vm["is-nul-stdin"].as<bool>())
  117. {
  118. #if defined(BOOST_POSIX_API)
  119. char buffer[1];
  120. int res = read(STDIN_FILENO, buffer, 1);
  121. return res != -1 ? EXIT_SUCCESS : EXIT_FAILURE;
  122. #elif defined(BOOST_WINDOWS_API)
  123. HANDLE h = GetStdHandle(STD_INPUT_HANDLE);
  124. if (h == INVALID_HANDLE_VALUE)
  125. return EXIT_FAILURE;
  126. char buffer[1];
  127. DWORD read;
  128. BOOL res = ReadFile(h, buffer, 1, &read, NULL);
  129. CloseHandle(h);
  130. return res ? EXIT_SUCCESS : EXIT_FAILURE;
  131. #endif
  132. }
  133. else if (vm["is-nul-stdout"].as<bool>())
  134. {
  135. std::cout << "foo" << std::endl;
  136. return std::cout.bad() ? EXIT_FAILURE : EXIT_SUCCESS;
  137. }
  138. else if (vm["is-nul-stderr"].as<bool>())
  139. {
  140. std::cerr << "foo" << std::endl;
  141. return std::cerr.bad() ? EXIT_FAILURE : EXIT_SUCCESS;
  142. }
  143. else if (vm["loop"].as<bool>())
  144. {
  145. while (true);
  146. }
  147. else if (vm["abort"].as<bool>())
  148. {
  149. std::abort();
  150. }
  151. else if (vm.count("prefix"))
  152. {
  153. std::string line;
  154. while (std::getline(std::cin, line))
  155. std::cout << vm["prefix"].as<std::string>() << line << std::endl;
  156. }
  157. else if (vm.count("prefix-once"))
  158. {
  159. std::string line;
  160. std::getline(std::cin, line);
  161. std::cout << vm["prefix-once"].as<std::string>() << line << std::endl;
  162. }
  163. else if (vm["pwd"].as<bool>())
  164. {
  165. std::cout << boost::filesystem::current_path().string() << std::endl;
  166. }
  167. else if (vm.count("query"))
  168. {
  169. auto key = vm["query"].as<std::string>();
  170. auto env = boost::this_process::environment();
  171. auto val = env[key];
  172. if (val.empty())
  173. std::cout << "************** empty environment **************" << std::endl;
  174. else
  175. std::cout << val.to_string() << std::endl;
  176. }
  177. else if (vm["stdin-to-stdout"].as<bool>())
  178. {
  179. char ch;
  180. while (std::cin >> std::noskipws >> ch)
  181. std::cout << ch << std::flush;
  182. }
  183. #if defined(BOOST_POSIX_API)
  184. else if (vm.count("posix-echo-one"))
  185. {
  186. using namespace boost::iostreams;
  187. std::vector<std::string> v = vm["posix-echo-one"].as<std::vector<std::string> >();
  188. int fd = boost::lexical_cast<int>(v[0]);
  189. file_descriptor_sink sink(fd, close_handle);
  190. stream<file_descriptor_sink> os(sink);
  191. os << v[1] << std::endl;
  192. }
  193. else if (vm.count("posix-echo-two"))
  194. {
  195. using namespace boost::iostreams;
  196. std::vector<std::string> v = vm["posix-echo-two"].as<std::vector<std::string> >();
  197. int fd1 = boost::lexical_cast<int>(v[0]);
  198. file_descriptor_sink sink1(fd1, close_handle);
  199. stream<file_descriptor_sink> os1(sink1);
  200. os1 << v[1] << std::endl;
  201. int fd2 = boost::lexical_cast<int>(v[2]);
  202. file_descriptor_sink sink2(fd2, close_handle);
  203. stream<file_descriptor_sink> os2(sink2);
  204. os2 << v[3] << std::endl;
  205. }
  206. #elif defined(BOOST_WINDOWS_API)
  207. else if (vm["windows-print-showwindow"].as<bool>())
  208. {
  209. STARTUPINFO si;
  210. GetStartupInfo(&si);
  211. std::cout << si.wShowWindow << std::endl;
  212. }
  213. else if (vm["windows-print-flags"].as<bool>())
  214. {
  215. STARTUPINFO si;
  216. GetStartupInfo(&si);
  217. std::cout << si.dwFlags << std::endl;
  218. }
  219. #endif
  220. else if (vm.count("has-handle"))
  221. {
  222. #if defined(BOOST_WINDOWS_API)
  223. const auto handle = reinterpret_cast<boost::this_process::native_handle_type>(vm["has-handle"].as<std::uintptr_t>());
  224. #else
  225. const auto handle = static_cast<boost::this_process::native_handle_type>(vm["has-handle"].as<std::uintptr_t>());
  226. #endif
  227. auto all_handles = boost::this_process::get_handles();
  228. return (std::find(all_handles.begin(), all_handles.end(), handle) != all_handles.end()) ? EXIT_SUCCESS : EXIT_FAILURE;
  229. }
  230. return EXIT_SUCCESS;
  231. }