]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/process/io.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / process / io.hpp
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
6 #ifndef BOOST_PROCESS_IO_HPP_
7 #define BOOST_PROCESS_IO_HPP_
8
9 #include <iosfwd>
10 #include <cstdio>
11 #include <functional>
12 #include <utility>
13 #include <boost/process/detail/config.hpp>
14 #include <boost/process/pipe.hpp>
15
16 #include <future>
17
18 #if defined(BOOST_POSIX_API)
19 #include <boost/process/detail/posix/asio_fwd.hpp>
20 #include <boost/process/detail/posix/close_in.hpp>
21 #include <boost/process/detail/posix/close_out.hpp>
22 #include <boost/process/detail/posix/null_in.hpp>
23 #include <boost/process/detail/posix/null_out.hpp>
24 #include <boost/process/detail/posix/file_in.hpp>
25 #include <boost/process/detail/posix/file_out.hpp>
26 #include <boost/process/detail/posix/pipe_in.hpp>
27 #include <boost/process/detail/posix/pipe_out.hpp>
28 #elif defined(BOOST_WINDOWS_API)
29 #include <boost/process/detail/windows/asio_fwd.hpp>
30 #include <boost/process/detail/windows/close_in.hpp>
31 #include <boost/process/detail/windows/close_out.hpp>
32 #include <boost/process/detail/windows/null_in.hpp>
33 #include <boost/process/detail/windows/null_out.hpp>
34 #include <boost/process/detail/windows/file_in.hpp>
35 #include <boost/process/detail/windows/file_out.hpp>
36 #include <boost/process/detail/windows/pipe_in.hpp>
37 #include <boost/process/detail/windows/pipe_out.hpp>
38 #endif
39
40 /** \file boost/process/io.hpp
41 *
42 * Header which provides the io properties. It provides the following properties:
43 *
44 \xmlonly
45 <programlisting>
46 namespace boost {
47 namespace process {
48 <emphasis>unspecified</emphasis> <globalname alt="boost::process::close">close</globalname>;
49 <emphasis>unspecified</emphasis> <globalname alt="boost::process::null">null</globalname>;
50 <emphasis>unspecified</emphasis> <globalname alt="boost::process::std_in">std_in</globalname>;
51 <emphasis>unspecified</emphasis> <globalname alt="boost::process::std_out">std_out</globalname>;
52 <emphasis>unspecified</emphasis> <globalname alt="boost::process::std_err">std_err</globalname>;
53 }
54 }
55 </programlisting>
56 \endxmlonly
57
58 \par File I/O
59
60 The library allows full redirection of streams to files as shown below.
61
62 \code{.cpp}
63 boost::filesystem::path log = "my_log_file.txt";
64 boost::filesystem::path input = "input.txt";
65 boost::filesystem::path output = "output.txt";
66 system("my_prog", std_out>output, std_in<input, std_err>log);
67 \endcode
68
69 \par Synchronous Pipe I/O
70
71 Another way is to communicate through pipes.
72
73 \code{.cpp}
74 pstream str;
75 child c("my_prog", std_out > str);
76
77 int i;
78 str >> i;
79 \endcode
80
81 Note that the pipe may also be used between several processes, like this:
82
83 \code{.cpp}
84 pipe p;
85 child c1("nm", "a.out", std_out>p);
86 child c2("c++filt", std_in<p);
87 \endcode
88
89 \par Asynchronous I/O
90
91 Utilizing `boost.asio` asynchronous I/O is provided.
92
93 \code
94 boost::asio::io_context ios;
95 std::future<std::string> output;
96 system("ls", std_out > output, ios);
97
98 auto res = fut.get();
99 \endcode
100
101 \note `boost/process/async.hpp` must also be included for this to work.
102
103 \par Closing
104
105 Stream can be closed, so nothing can be read or written.
106
107 \code{.cpp}
108 system("foo", std_in.close());
109 \endcode
110
111 \par Null
112
113 Streams can be redirected to null, which means, that written date will be
114 discarded and read data will only contain `EOF`.
115
116 \code{.cpp}
117 system("b2", std_out > null);
118 \endcode
119
120 *
121 */
122
123 namespace boost { namespace process { namespace detail {
124
125
126 template<typename T> using is_streambuf = typename std::is_same<T, boost::asio::streambuf>::type;
127 template<typename T> using is_const_buffer =
128 std::integral_constant<bool,
129 std::is_same< boost::asio::const_buffer, T>::value |
130 std::is_base_of<boost::asio::const_buffer, T>::value
131 >;
132 template<typename T> using is_mutable_buffer =
133 std::integral_constant<bool,
134 std::is_same< boost::asio::mutable_buffer, T>::value |
135 std::is_base_of<boost::asio::mutable_buffer, T>::value
136 >;
137
138
139 struct null_t {constexpr null_t() {}};
140 struct close_t;
141
142 template<class>
143 struct std_in_
144 {
145 constexpr std_in_() {}
146
147 api::close_in close() const {return api::close_in(); }
148 api::close_in operator=(const close_t &) const {return api::close_in();}
149 api::close_in operator<(const close_t &) const {return api::close_in();}
150
151 api::null_in null() const {return api::null_in();}
152 api::null_in operator=(const null_t &) const {return api::null_in();}
153 api::null_in operator<(const null_t &) const {return api::null_in();}
154
155 api::file_in operator=(const boost::filesystem::path &p) const {return p;}
156 api::file_in operator=(const std::string & p) const {return p;}
157 api::file_in operator=(const std::wstring &p) const {return p;}
158 api::file_in operator=(const char * p) const {return p;}
159 api::file_in operator=(const wchar_t * p) const {return p;}
160
161 api::file_in operator<(const boost::filesystem::path &p) const {return p;}
162 api::file_in operator<(const std::string &p) const {return p;}
163 api::file_in operator<(const std::wstring &p) const {return p;}
164 api::file_in operator<(const char*p) const {return p;}
165 api::file_in operator<(const wchar_t * p) const {return p;}
166
167 api::file_in operator=(FILE * f) const {return f;}
168 api::file_in operator<(FILE * f) const {return f;}
169
170 template<typename Char, typename Traits> api::pipe_in operator=(basic_pipe<Char, Traits> & p) const {return p;}
171 template<typename Char, typename Traits> api::pipe_in operator<(basic_pipe<Char, Traits> & p) const {return p;}
172 template<typename Char, typename Traits> api::pipe_in operator=(basic_opstream<Char, Traits> & p) const {return p.pipe();}
173 template<typename Char, typename Traits> api::pipe_in operator<(basic_opstream<Char, Traits> & p) const {return p.pipe();}
174 template<typename Char, typename Traits> api::pipe_in operator=(basic_pstream <Char, Traits> & p) const {return p.pipe();}
175 template<typename Char, typename Traits> api::pipe_in operator<(basic_pstream <Char, Traits> & p) const {return p.pipe();}
176
177 api::async_pipe_in operator=(async_pipe & p) const {return p;}
178 api::async_pipe_in operator<(async_pipe & p) const {return p;}
179
180 template<typename T, typename = typename std::enable_if<
181 is_const_buffer<T>::value || is_mutable_buffer<T>::value
182 >::type>
183 api::async_in_buffer<const T> operator=(const T & buf) const {return buf;}
184 template<typename T, typename = typename std::enable_if<is_streambuf<T>::value>::type >
185 api::async_in_buffer<T> operator=(T & buf) const {return buf;}
186
187 template<typename T, typename = typename std::enable_if<
188 is_const_buffer<T>::value || is_mutable_buffer<T>::value
189 >::type>
190 api::async_in_buffer<const T> operator<(const T & buf) const {return buf;}
191 template<typename T, typename = typename std::enable_if<is_streambuf<T>::value>::type >
192 api::async_in_buffer<T> operator<(T & buf) const {return buf;}
193
194 };
195
196 //-1 == empty.
197 //1 == stdout
198 //2 == stderr
199 template<int p1, int p2 = -1>
200 struct std_out_
201 {
202 constexpr std_out_() {}
203
204 api::close_out<p1,p2> close() const {return api::close_out<p1,p2>(); }
205 api::close_out<p1,p2> operator=(const close_t &) const {return api::close_out<p1,p2>();}
206 api::close_out<p1,p2> operator>(const close_t &) const {return api::close_out<p1,p2>();}
207
208 api::null_out<p1,p2> null() const {return api::null_out<p1,p2>();}
209 api::null_out<p1,p2> operator=(const null_t &) const {return api::null_out<p1,p2>();}
210 api::null_out<p1,p2> operator>(const null_t &) const {return api::null_out<p1,p2>();}
211
212 api::file_out<p1,p2> operator=(const boost::filesystem::path &p) const {return api::file_out<p1,p2>(p);}
213 api::file_out<p1,p2> operator=(const std::string &p) const {return api::file_out<p1,p2>(p);}
214 api::file_out<p1,p2> operator=(const std::wstring &p) const {return api::file_out<p1,p2>(p);}
215 api::file_out<p1,p2> operator=(const char * p) const {return api::file_out<p1,p2>(p);}
216 api::file_out<p1,p2> operator=(const wchar_t * p) const {return api::file_out<p1,p2>(p);}
217
218 api::file_out<p1,p2> operator>(const boost::filesystem::path &p) const {return api::file_out<p1,p2>(p);}
219 api::file_out<p1,p2> operator>(const std::string &p) const {return api::file_out<p1,p2>(p);}
220 api::file_out<p1,p2> operator>(const std::wstring &p) const {return api::file_out<p1,p2>(p);}
221 api::file_out<p1,p2> operator>(const char * p) const {return api::file_out<p1,p2>(p);}
222 api::file_out<p1,p2> operator>(const wchar_t * p) const {return api::file_out<p1,p2>(p);}
223
224 api::file_out<p1,p2> operator=(FILE * f) const {return f;}
225 api::file_out<p1,p2> operator>(FILE * f) const {return f;}
226
227 template<typename Char, typename Traits> api::pipe_out<p1,p2> operator=(basic_pipe<Char, Traits> & p) const {return p;}
228 template<typename Char, typename Traits> api::pipe_out<p1,p2> operator>(basic_pipe<Char, Traits> & p) const {return p;}
229 template<typename Char, typename Traits> api::pipe_out<p1,p2> operator=(basic_ipstream<Char, Traits> & p) const {return p.pipe();}
230 template<typename Char, typename Traits> api::pipe_out<p1,p2> operator>(basic_ipstream<Char, Traits> & p) const {return p.pipe();}
231 template<typename Char, typename Traits> api::pipe_out<p1,p2> operator=(basic_pstream <Char, Traits> & p) const {return p.pipe();}
232 template<typename Char, typename Traits> api::pipe_out<p1,p2> operator>(basic_pstream <Char, Traits> & p) const {return p.pipe();}
233
234 api::async_pipe_out<p1, p2> operator=(async_pipe & p) const {return p;}
235 api::async_pipe_out<p1, p2> operator>(async_pipe & p) const {return p;}
236
237 api::async_out_buffer<p1, p2, const asio::mutable_buffer> operator=(const asio::mutable_buffer & buf) const {return buf;}
238 api::async_out_buffer<p1, p2, const asio::mutable_buffers_1> operator=(const asio::mutable_buffers_1 & buf) const {return buf;}
239 api::async_out_buffer<p1, p2, asio::streambuf> operator=(asio::streambuf & os) const {return os ;}
240
241 api::async_out_buffer<p1, p2, const asio::mutable_buffer> operator>(const asio::mutable_buffer & buf) const {return buf;}
242 api::async_out_buffer<p1, p2, const asio::mutable_buffers_1> operator>(const asio::mutable_buffers_1 & buf) const {return buf;}
243 api::async_out_buffer<p1, p2, asio::streambuf> operator>(asio::streambuf & os) const {return os ;}
244
245 api::async_out_future<p1,p2, std::string> operator=(std::future<std::string> & fut) const { return fut;}
246 api::async_out_future<p1,p2, std::string> operator>(std::future<std::string> & fut) const { return fut;}
247 api::async_out_future<p1,p2, std::vector<char>> operator=(std::future<std::vector<char>> & fut) const { return fut;}
248 api::async_out_future<p1,p2, std::vector<char>> operator>(std::future<std::vector<char>> & fut) const { return fut;}
249
250 template<int pin, typename = typename std::enable_if<
251 (((p1 == 1) && (pin == 2)) ||
252 ((p1 == 2) && (pin == 1)))
253 && (p2 == -1)>::type>
254 constexpr std_out_<1, 2> operator& (const std_out_<pin>&) const
255 {
256 return std_out_<1, 2> ();
257 }
258
259 };
260
261 struct close_t
262 {
263 constexpr close_t() {}
264 template<int T, int U>
265 api::close_out<T,U> operator()(std_out_<T,U>) {return api::close_out<T,U>();}
266 };
267
268
269
270 }
271 ///This constant is a utility to allow syntax like `std_out > close` for closing I/O streams.
272 constexpr boost::process::detail::close_t close;
273 ///This constant is a utility to redirect streams to the null-device.
274 constexpr boost::process::detail::null_t null;
275
276 /**
277 This property allows to set the input stream for the child process.
278
279 \section stdin_details Details
280
281 \subsection stdin_file File Input
282
283 The file I/O simple redirects the stream to a file, for which the possible types are
284
285 - `boost::filesystem::path`
286 - `std::basic_string<char_type>`
287 - `const char_type*`
288 - `FILE*`
289
290 with `char_type` being either `char` or `wchar_t`.
291
292 FILE* is explicitly added, so the process can easily redirect the output stream
293 of the child to another output stream of the process. That is:
294
295 \code{.cpp}
296 system("ls", std_in < stdin);
297 \endcode
298
299 \warning If the launching and the child process use the input, this leads to undefined behaviour.
300
301 A syntax like `system("ls", std_out > std::cerr)` is not possible, due to the C++
302 implementation not providing access to the handle.
303
304 The valid expressions for this property are
305
306 \code{.cpp}
307 std_in < file;
308 std_in = file;
309 \endcode
310
311 \subsection stdin_pipe Pipe Input
312
313 As explained in the corresponding section, the boost.process library provides a
314 @ref boost::process::async_pipe "async_pipe" class which can be
315 used to communicate with child processes.
316
317 \note Technically the @ref boost::process::async_pipe "async_pipe"
318 works synchronous here, since no asio implementation is used by the library here.
319 The async-operation will then however not end if the process is finished, since
320 the pipe remains open. You can use the async_close function with on_exit to fix that.
321
322 Valid expressions with pipes are these:
323
324 \code{.cpp}
325 std_in < pipe;
326 std_in = pipe;
327 \endcode
328
329 Where the valid types for `pipe` are the following:
330
331 - `basic_pipe`
332 - `async_pipe`
333 - `basic_opstream`
334 - `basic_pstream`
335
336 Note that the pipe may also be used between several processes, like this:
337
338 \code{.cpp}
339 pipe p;
340 child c1("nm", "a.out", std_out>p);
341 child c2("c++filt", std_in<p);
342 \endcode
343
344 \subsection stdin_async_pipe Asynchronous Pipe Input
345
346 Asynchronous Pipe I/O classifies communication which has automatically handling
347 of the asynchronous operations by the process library. This means, that a pipe will be
348 constructed, the async_read/-write will be automatically started, and that the
349 end of the child process will also close the pipe.
350
351 Valid types for pipe I/O are the following:
352
353 - `boost::asio::const_buffer` \xmlonly <footnote><para> Constructed with <code>boost::asio::buffer</code></para></footnote> \endxmlonly
354 - `boost::asio::mutable_buffer` \xmlonly <footnote><para> Constructed with <code>boost::asio::buffer</code></para></footnote> \endxmlonly
355 - `boost::asio::streambuf`
356
357 Valid expressions with pipes are these:
358
359 \code{.cpp}
360 std_in < buffer;
361 std_in = buffer;
362 std_out > buffer;
363 std_out = buffer;
364 std_err > buffer;
365 std_err = buffer;
366 (std_out & std_err) > buffer;
367 (std_out & std_err) = buffer;
368 \endcode
369
370 \note It is also possible to get a future for std_in, by chaining another `std::future<void>` onto it,
371 so you can wait for the input to be completed. It looks like this:
372 \code{.cpp}
373 std::future<void> fut;
374 boost::asio::io_context ios;
375 std::string data;
376 child c("prog", std_in < buffer(data) > fut, ios);
377 fut.get();
378 \endcode
379
380
381 \note `boost::asio::buffer` is also available in the `boost::process` namespace.
382
383 \warning This feature requires `boost/process/async.hpp` to be included and a reference to `boost::asio::io_context` to be passed to the launching function.
384
385
386 \subsection stdin_close Close
387
388 The input stream can be closed, so it cannot be read from. This will lead to an error when attempted.
389
390 This can be achieved by the following syntax.
391
392 \code{.cpp}
393 std_in < close;
394 std_in = close;
395 std_in.close();
396 \endcode
397
398 \subsection stdin_null Null
399
400 The input stream can be redirected to read from the null-device, which means that only `EOF` is read.
401
402 The syntax to achieve that has the following variants:
403
404 \code{.cpp}
405 std_in < null;
406 std_in = null;
407 std_in.null();
408 \endcode
409
410 */
411
412 constexpr boost::process::detail::std_in_<void> std_in;
413
414 /**
415 This property allows to set the output stream for the child process.
416
417 \note The Semantic is the same as for \xmlonly <globalname alt="boost::process::std_err">std_err</globalname> \endxmlonly
418
419 \note `std_err` and `std_out` can be combined into one stream, with the `operator &`, i.e. `std_out & std_err`.
420
421 \section stdout_details Details
422
423 \subsection stdout_file File Input
424
425 The file I/O simple redirects the stream to a file, for which the possible types are
426
427 - `boost::filesystem::path`
428 - `std::basic_string<char_type>`
429 - `const char_type*`
430 - `FILE*`
431
432 with `char_type` being either `char` or `wchar_t`.
433
434 FILE* is explicitly added, so the process can easily redirect the output stream
435 of the child to another output stream of the process. That is:
436
437 \code{.cpp}
438 system("ls", std_out < stdin);
439 \endcode
440
441 \warning If the launching and the child process use the input, this leads to undefined behaviour.
442
443 A syntax like `system("ls", std_out > std::cerr)` is not possible, due to the C++
444 implementation not providing access to the handle.
445
446 The valid expressions for this property are
447
448 \code{.cpp}
449 std_out < file;
450 std_out = file;
451 \endcode
452
453 \subsection stdout_pipe Pipe Output
454
455 As explained in the corresponding section, the boost.process library provides a
456 @ref boost::process::async_pipe "async_pipe" class which can be
457 used to communicate with child processes.
458
459 \note Technically the @ref boost::process::async_pipe "async_pipe"
460 works like a synchronous pipe here, since no asio implementation is used by the library here.
461 The asynchronous operation will then however not end if the process is finished, since
462 the pipe remains open. You can use the async_close function with on_exit to fix that.
463
464 Valid expressions with pipes are these:
465
466 \code{.cpp}
467 std_out > pipe;
468 std_out = pipe;
469 \endcode
470
471 Where the valid types for `pipe` are the following:
472
473 - `basic_pipe`
474 - `async_pipe`
475 - `basic_ipstream`
476 - `basic_pstream`
477
478 Note that the pipe may also be used between several processes, like this:
479
480 \code{.cpp}
481 pipe p;
482 child c1("nm", "a.out", std_out>p);
483 child c2("c++filt", std_in<p);
484 \endcode
485
486 \subsection stdout_async_pipe Asynchronous Pipe Output
487
488 Asynchronous Pipe I/O classifies communication which has automatically handling
489 of the async operations by the process library. This means, that a pipe will be
490 constructed, the async_read/-write will be automatically started, and that the
491 end of the child process will also close the pipe.
492
493 Valid types for pipe I/O are the following:
494
495 - `boost::asio::mutable_buffer` \xmlonly <footnote><para> Constructed with <code>boost::asio::buffer</code></para></footnote> \endxmlonly
496 - `boost::asio::streambuf`
497 - `std::future<std::vector<char>>`
498 - `std::future<std::string>`
499
500 Valid expressions with pipes are these:
501
502 \code{.cpp}
503 std_out > buffer;
504 std_out = buffer;
505 std_err > buffer;
506 std_err = buffer;
507 (std_out & std_err) > buffer;
508 (std_out & std_err) = buffer;
509 \endcode
510
511 \note `boost::asio::buffer` is also available in the `boost::process` namespace.
512
513 \warning This feature requires `boost/process/async.hpp` to be included and a reference to `boost::asio::io_context` to be passed to the launching function.
514
515
516 \subsection stdout_close Close
517
518 The out stream can be closed, so it cannot be write from.
519 This will lead to an error when attempted.
520
521 This can be achieved by the following syntax.
522
523 \code{.cpp}
524 std_out > close;
525 std_out = close;
526 std_out.close();
527 \endcode
528
529 \subsection stdout_null Null
530
531 The output stream can be redirected to write to the null-device,
532 which means that all output is discarded.
533
534 The syntax to achieve that has the following variants:
535
536 \code{.cpp}
537 std_out > null;
538 std_out = null;
539 std_out.null();
540 \endcode
541
542 */
543
544 constexpr boost::process::detail::std_out_<1> std_out;
545 /**This property allows setting the `stderr` stream. The semantic and syntax is the same as for
546 * \xmlonly <globalname alt="boost::process::std_out">std_out</globalname> \endxmlonly .
547 */
548 constexpr boost::process::detail::std_out_<2> std_err;
549
550 }}
551 #endif /* INCLUDE_BOOST_PROCESS_IO_HPP_ */