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
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)
10 #define BOOST_USE_WINDOWS_H
12 #include <boost/program_options.hpp>
13 #include <boost/filesystem.hpp>
14 #include <boost/algorithm/string/join.hpp>
15 #include <boost/range/iterator_range.hpp>
16 #include <boost/range/algorithm/transform.hpp>
17 #include <boost/range/algorithm_ext/push_back.hpp>
18 #include <boost/lambda/lambda.hpp>
19 #include <boost/process/environment.hpp>
25 #if defined(BOOST_POSIX_API)
26 # include <boost/lexical_cast.hpp>
27 # include <boost/iostreams/device/file_descriptor.hpp>
28 # include <boost/iostreams/stream.hpp>
30 #elif defined(BOOST_WINDOWS_API)
35 using namespace boost::program_options;
37 int main(int argc, char *argv[])
39 options_description desc;
41 ("echo-stdout", value<std::string>())
42 ("echo-stderr", value<std::string>())
43 ("echo-stdout-stderr", value<std::string>())
44 ("echo-argv", bool_switch())
45 ("exit-code", value<int>())
46 ("wait", value<int>())
47 ("is-closed-stdin", bool_switch())
48 ("is-closed-stdout", bool_switch())
49 ("is-closed-stderr", bool_switch())
50 ("is-nul-stdin", bool_switch())
51 ("is-nul-stdout", bool_switch())
52 ("is-nul-stderr", bool_switch())
53 ("loop", bool_switch())
54 ("prefix", value<std::string>())
55 ("prefix-once", value<std::string>())
56 ("pwd", bool_switch())
57 ("query", value<std::string>())
58 ("stdin-to-stdout", bool_switch())
59 #if defined(BOOST_POSIX_API)
60 ("posix-echo-one", value<std::vector<std::string> >()->multitoken())
61 ("posix-echo-two", value<std::vector<std::string> >()->multitoken());
62 #elif defined(BOOST_WINDOWS_API)
63 ("windows-print-showwindow", bool_switch())
64 ("windows-print-flags", bool_switch());
67 command_line_parser parser(argc, argv);
68 store(parser.options(desc).allow_unregistered().run(), vm);
71 if (vm.count("echo-stdout"))
73 std::cout << vm["echo-stdout"].as<std::string>() << std::endl;
75 else if (vm.count("echo-stderr"))
77 std::cerr << vm["echo-stderr"].as<std::string>() << std::endl;
79 else if (vm.count("echo-stdout-stderr"))
81 std::cout << vm["echo-stdout-stderr"].as<std::string>() << std::endl;
82 std::cerr << vm["echo-stdout-stderr"].as<std::string>() << std::endl;
84 else if (vm["echo-argv"].as<bool>())
86 std::vector<char*> args(argv+1, argv + argc);
87 for (auto & arg : args)
88 std::cout << arg << std::endl;
90 else if (vm.count("exit-code"))
92 return vm["exit-code"].as<int>();
94 else if (vm.count("wait"))
96 int sec = vm["wait"].as<int>();
97 #if defined(BOOST_POSIX_API)
99 #elif defined(BOOST_WINDOWS_API)
103 else if (vm["is-closed-stdin"].as<bool>())
107 return std::cin.eof() ? EXIT_SUCCESS : EXIT_FAILURE;
109 else if (vm["is-closed-stdout"].as<bool>())
111 std::cout << "foo" << std::endl;
112 return std::cout.bad() ? EXIT_SUCCESS : EXIT_FAILURE;
114 else if (vm["is-closed-stderr"].as<bool>())
116 std::cerr << "foo" << std::endl;
117 return std::cerr.bad() ? EXIT_SUCCESS : EXIT_FAILURE;
119 else if (vm["is-nul-stdin"].as<bool>())
121 #if defined(BOOST_POSIX_API)
123 int res = read(STDIN_FILENO, buffer, 1);
124 return res != -1 ? EXIT_SUCCESS : EXIT_FAILURE;
125 #elif defined(BOOST_WINDOWS_API)
126 HANDLE h = GetStdHandle(STD_INPUT_HANDLE);
127 if (h == INVALID_HANDLE_VALUE)
131 BOOL res = ReadFile(h, buffer, 1, &read, NULL);
133 return res ? EXIT_SUCCESS : EXIT_FAILURE;
136 else if (vm["is-nul-stdout"].as<bool>())
138 std::cout << "foo" << std::endl;
139 return std::cout.bad() ? EXIT_FAILURE : EXIT_SUCCESS;
141 else if (vm["is-nul-stderr"].as<bool>())
143 std::cerr << "foo" << std::endl;
144 return std::cerr.bad() ? EXIT_FAILURE : EXIT_SUCCESS;
146 else if (vm["loop"].as<bool>())
150 else if (vm.count("prefix"))
153 while (std::getline(std::cin, line))
154 std::cout << vm["prefix"].as<std::string>() << line << std::endl;
156 else if (vm.count("prefix-once"))
160 std::getline(std::cin, line);
162 std::cout << vm["prefix-once"].as<std::string>() << line << std::endl;
164 else if (vm["pwd"].as<bool>())
166 std::cout << boost::filesystem::current_path().string() << std::endl;
168 else if (vm.count("query"))
170 auto key = vm["query"].as<std::string>();
171 auto env = boost::this_process::environment();
174 std::cout << "************** empty environment **************" << std::endl;
176 std::cout << val.to_string() << std::endl;
178 else if (vm["stdin-to-stdout"].as<bool>())
181 while (std::cin >> std::noskipws >> ch)
182 std::cout << ch << std::flush;
184 #if defined(BOOST_POSIX_API)
185 else if (vm.count("posix-echo-one"))
187 using namespace boost::iostreams;
188 std::vector<std::string> v = vm["posix-echo-one"].as<std::vector<std::string> >();
189 int fd = boost::lexical_cast<int>(v[0]);
190 file_descriptor_sink sink(fd, close_handle);
191 stream<file_descriptor_sink> os(sink);
192 os << v[1] << std::endl;
194 else if (vm.count("posix-echo-two"))
196 using namespace boost::iostreams;
197 std::vector<std::string> v = vm["posix-echo-two"].as<std::vector<std::string> >();
198 int fd1 = boost::lexical_cast<int>(v[0]);
199 file_descriptor_sink sink1(fd1, close_handle);
200 stream<file_descriptor_sink> os1(sink1);
201 os1 << v[1] << std::endl;
202 int fd2 = boost::lexical_cast<int>(v[2]);
203 file_descriptor_sink sink2(fd2, close_handle);
204 stream<file_descriptor_sink> os2(sink2);
205 os2 << v[3] << std::endl;
207 #elif defined(BOOST_WINDOWS_API)
208 else if (vm["windows-print-showwindow"].as<bool>())
212 std::cout << si.wShowWindow << std::endl;
214 else if (vm["windows-print-flags"].as<bool>())
218 std::cout << si.dwFlags << std::endl;