Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:50:14

0001 // Copyright (c) 2016 Klemens D. Morgenstern
0002 //
0003 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0004 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0005 
0006 #ifndef BOOST_PROCESS_IO_HPP_
0007 #define BOOST_PROCESS_IO_HPP_
0008 
0009 #include <iosfwd>
0010 #include <cstdio>
0011 #include <functional>
0012 #include <utility>
0013 #include <boost/process/detail/config.hpp>
0014 #include <boost/process/pipe.hpp>
0015 
0016 #include <future>
0017 
0018 #if defined(BOOST_POSIX_API)
0019 #include <boost/process/detail/posix/asio_fwd.hpp>
0020 #include <boost/process/detail/posix/close_in.hpp>
0021 #include <boost/process/detail/posix/close_out.hpp>
0022 #include <boost/process/detail/posix/null_in.hpp>
0023 #include <boost/process/detail/posix/null_out.hpp>
0024 #include <boost/process/detail/posix/file_in.hpp>
0025 #include <boost/process/detail/posix/file_out.hpp>
0026 #include <boost/process/detail/posix/pipe_in.hpp>
0027 #include <boost/process/detail/posix/pipe_out.hpp>
0028 #elif defined(BOOST_WINDOWS_API)
0029 #include <boost/process/detail/windows/asio_fwd.hpp>
0030 #include <boost/process/detail/windows/close_in.hpp>
0031 #include <boost/process/detail/windows/close_out.hpp>
0032 #include <boost/process/detail/windows/null_in.hpp>
0033 #include <boost/process/detail/windows/null_out.hpp>
0034 #include <boost/process/detail/windows/file_in.hpp>
0035 #include <boost/process/detail/windows/file_out.hpp>
0036 #include <boost/process/detail/windows/pipe_in.hpp>
0037 #include <boost/process/detail/windows/pipe_out.hpp>
0038 #endif
0039 
0040 /** \file boost/process/io.hpp
0041  *
0042  *    Header which provides the io properties. It provides the following properties:
0043  *
0044 \xmlonly
0045 <programlisting>
0046 namespace boost {
0047   namespace process {
0048     <emphasis>unspecified</emphasis> <globalname alt="boost::process::close">close</globalname>;
0049     <emphasis>unspecified</emphasis> <globalname alt="boost::process::null">null</globalname>;
0050     <emphasis>unspecified</emphasis> <globalname alt="boost::process::std_in">std_in</globalname>;
0051     <emphasis>unspecified</emphasis> <globalname alt="boost::process::std_out">std_out</globalname>;
0052     <emphasis>unspecified</emphasis> <globalname alt="boost::process::std_err">std_err</globalname>;
0053   }
0054 }
0055 </programlisting>
0056 \endxmlonly
0057 
0058 \par File I/O
0059 
0060 The library allows full redirection of streams to files as shown below.
0061 
0062 \code{.cpp}
0063 boost::process::filesystem::path log    = "my_log_file.txt";
0064 boost::process::filesystem::path input  = "input.txt";
0065 boost::process::filesystem::path output = "output.txt";
0066 system("my_prog", std_out>output, std_in<input, std_err>log);
0067 \endcode
0068 
0069 \par Synchronous Pipe I/O
0070 
0071 Another way is to communicate through pipes.
0072 
0073 \code{.cpp}
0074 pstream str;
0075 child c("my_prog", std_out > str);
0076 
0077 int i;
0078 str >> i;
0079 \endcode
0080 
0081 Note that the pipe may also be used between several processes, like this:
0082 
0083 \code{.cpp}
0084 pipe p;
0085 child c1("nm", "a.out", std_out>p);
0086 child c2("c++filt", std_in<p);
0087 \endcode
0088 
0089 \par Asynchronous I/O
0090 
0091 Utilizing `boost.asio` asynchronous I/O is provided.
0092 
0093 \code
0094 boost::asio::io_context ios;
0095 std::future<std::string> output;
0096 system("ls", std_out > output, ios);
0097 
0098 auto res = fut.get();
0099 \endcode
0100 
0101 \note `boost/process/async.hpp` must also be included for this to work.
0102 
0103 \par Closing
0104 
0105 Stream can be closed, so nothing can be read or written.
0106 
0107 \code{.cpp}
0108 system("foo", std_in.close());
0109 \endcode
0110 
0111 \par Null
0112 
0113 Streams can be redirected to null, which means, that written date will be
0114 discarded and read data will only contain `EOF`.
0115 
0116 \code{.cpp}
0117 system("b2", std_out > null);
0118 \endcode
0119 
0120  *
0121  */
0122 
0123 namespace boost { namespace process { namespace detail {
0124 
0125 
0126 template<typename T> using is_streambuf    = typename std::is_same<T, boost::asio::streambuf>::type;
0127 template<typename T> using is_const_buffer =
0128         std::integral_constant<bool,
0129             std::is_same<   boost::asio::const_buffer, T>::value |
0130             std::is_base_of<boost::asio::const_buffer, T>::value
0131         >;
0132 template<typename T> using is_mutable_buffer =
0133         std::integral_constant<bool,
0134             std::is_same<   boost::asio::mutable_buffer, T>::value |
0135             std::is_base_of<boost::asio::mutable_buffer, T>::value
0136         >;
0137 
0138 
0139 struct null_t  {constexpr null_t() = default;};
0140 struct close_t;
0141 
0142 template<class>
0143 struct std_in_
0144 {
0145     constexpr std_in_() = default;
0146 
0147     api::close_in close() const {return api::close_in(); }
0148     api::close_in operator=(const close_t &) const {return api::close_in();}
0149     api::close_in operator<(const close_t &) const {return api::close_in();}
0150 
0151     api::null_in null() const {return api::null_in();}
0152     api::null_in operator=(const null_t &) const {return api::null_in();}
0153     api::null_in operator<(const null_t &) const {return api::null_in();}
0154 
0155     api::file_in operator=(const boost::process::filesystem::path &p) const {return p;}
0156     api::file_in operator=(const std::string & p)            const {return p;}
0157     api::file_in operator=(const std::wstring &p)            const {return p;}
0158     api::file_in operator=(const char * p)                   const {return p;}
0159     api::file_in operator=(const wchar_t * p)                const {return p;}
0160 
0161     api::file_in operator<(const boost::process::filesystem::path &p) const {return p;}
0162     api::file_in operator<(const std::string &p)             const {return p;}
0163     api::file_in operator<(const std::wstring &p)            const {return p;}
0164     api::file_in operator<(const char*p)                     const {return p;}
0165     api::file_in operator<(const wchar_t * p)                const {return p;}
0166 
0167     api::file_in operator=(FILE * f)                         const {return f;}
0168     api::file_in operator<(FILE * f)                         const {return f;}
0169 
0170     template<typename Char, typename Traits> api::pipe_in operator=(basic_pipe<Char, Traits> & p)      const {return p;}
0171     template<typename Char, typename Traits> api::pipe_in operator<(basic_pipe<Char, Traits> & p)      const {return p;}
0172     template<typename Char, typename Traits> api::pipe_in operator=(basic_opstream<Char, Traits> & p)  const {return p.pipe();}
0173     template<typename Char, typename Traits> api::pipe_in operator<(basic_opstream<Char, Traits> & p)  const {return p.pipe();}
0174     template<typename Char, typename Traits> api::pipe_in operator=(basic_pstream <Char, Traits> & p)  const {return p.pipe();}
0175     template<typename Char, typename Traits> api::pipe_in operator<(basic_pstream <Char, Traits> & p)  const {return p.pipe();}
0176 
0177     api::async_pipe_in operator=(async_pipe & p) const {return p;}
0178     api::async_pipe_in operator<(async_pipe & p) const {return p;}
0179 
0180     template<typename T, typename = typename std::enable_if<
0181             is_const_buffer<T>::value || is_mutable_buffer<T>::value
0182             >::type>
0183     api::async_in_buffer<const T> operator=(const T & buf) const {return buf;}
0184     template<typename T, typename = typename std::enable_if<is_streambuf<T>::value>::type >
0185     api::async_in_buffer<T>       operator=(T       & buf) const {return buf;}
0186 
0187     template<typename T, typename = typename std::enable_if<
0188             is_const_buffer<T>::value || is_mutable_buffer<T>::value
0189             >::type>
0190     api::async_in_buffer<const T> operator<(const T & buf) const {return buf;}
0191     template<typename T, typename = typename std::enable_if<is_streambuf<T>::value>::type >
0192     api::async_in_buffer<T>       operator<(T       & buf) const {return buf;}
0193 
0194 };
0195 
0196 //-1 == empty.
0197 //1 == stdout
0198 //2 == stderr
0199 template<int p1, int p2 = -1>
0200 struct std_out_
0201 {
0202     constexpr std_out_() = default;
0203 
0204     api::close_out<p1,p2> close() const {return api::close_out<p1,p2>(); }
0205     api::close_out<p1,p2> operator=(const close_t &) const {return api::close_out<p1,p2>();}
0206     api::close_out<p1,p2> operator>(const close_t &) const {return api::close_out<p1,p2>();}
0207 
0208     api::null_out<p1,p2> null() const {return api::null_out<p1,p2>();}
0209     api::null_out<p1,p2> operator=(const null_t &) const {return api::null_out<p1,p2>();}
0210     api::null_out<p1,p2> operator>(const null_t &) const {return api::null_out<p1,p2>();}
0211 
0212     api::file_out<p1,p2> operator=(const boost::process::filesystem::path &p) const {return api::file_out<p1,p2>(p);}
0213     api::file_out<p1,p2> operator=(const std::string &p)             const {return api::file_out<p1,p2>(p);}
0214     api::file_out<p1,p2> operator=(const std::wstring &p)            const {return api::file_out<p1,p2>(p);}
0215     api::file_out<p1,p2> operator=(const char * p)                   const {return api::file_out<p1,p2>(p);}
0216     api::file_out<p1,p2> operator=(const wchar_t * p)                const {return api::file_out<p1,p2>(p);}
0217 
0218     api::file_out<p1,p2> operator>(const boost::process::filesystem::path &p) const {return api::file_out<p1,p2>(p);}
0219     api::file_out<p1,p2> operator>(const std::string &p)             const {return api::file_out<p1,p2>(p);}
0220     api::file_out<p1,p2> operator>(const std::wstring &p)            const {return api::file_out<p1,p2>(p);}
0221     api::file_out<p1,p2> operator>(const char * p)                   const {return api::file_out<p1,p2>(p);}
0222     api::file_out<p1,p2> operator>(const wchar_t * p)                const {return api::file_out<p1,p2>(p);}
0223 
0224     api::file_out<p1,p2> operator=(FILE * f)  const {return f;}
0225     api::file_out<p1,p2> operator>(FILE * f)  const {return f;}
0226 
0227     template<typename Char, typename Traits> api::pipe_out<p1,p2> operator=(basic_pipe<Char, Traits> & p)      const {return p;}
0228     template<typename Char, typename Traits> api::pipe_out<p1,p2> operator>(basic_pipe<Char, Traits> & p)      const {return p;}
0229     template<typename Char, typename Traits> api::pipe_out<p1,p2> operator=(basic_ipstream<Char, Traits> & p)  const {return p.pipe();}
0230     template<typename Char, typename Traits> api::pipe_out<p1,p2> operator>(basic_ipstream<Char, Traits> & p)  const {return p.pipe();}
0231     template<typename Char, typename Traits> api::pipe_out<p1,p2> operator=(basic_pstream <Char, Traits> & p)  const {return p.pipe();}
0232     template<typename Char, typename Traits> api::pipe_out<p1,p2> operator>(basic_pstream <Char, Traits> & p)  const {return p.pipe();}
0233 
0234     api::async_pipe_out<p1, p2> operator=(async_pipe & p) const {return p;}
0235     api::async_pipe_out<p1, p2> operator>(async_pipe & p) const {return p;}
0236 
0237     api::async_out_buffer<p1, p2, const asio::mutable_buffer>     operator=(const asio::mutable_buffer & buf)     const {return buf;}
0238     api::async_out_buffer<p1, p2, const asio::mutable_buffers_1> operator=(const asio::mutable_buffers_1 & buf) const {return buf;}
0239     api::async_out_buffer<p1, p2, asio::streambuf>               operator=(asio::streambuf & os)                   const {return os ;}
0240 
0241     api::async_out_buffer<p1, p2, const asio::mutable_buffer>     operator>(const asio::mutable_buffer & buf)     const {return buf;}
0242     api::async_out_buffer<p1, p2, const asio::mutable_buffers_1> operator>(const asio::mutable_buffers_1 & buf) const {return buf;}
0243     api::async_out_buffer<p1, p2, asio::streambuf>               operator>(asio::streambuf & os)                   const {return os ;}
0244 
0245     api::async_out_future<p1,p2, std::string>       operator=(std::future<std::string> & fut)       const { return fut;}
0246     api::async_out_future<p1,p2, std::string>       operator>(std::future<std::string> & fut)       const { return fut;}
0247     api::async_out_future<p1,p2, std::vector<char>> operator=(std::future<std::vector<char>> & fut) const { return fut;}
0248     api::async_out_future<p1,p2, std::vector<char>> operator>(std::future<std::vector<char>> & fut) const { return fut;}
0249 
0250     template<int pin, typename = typename std::enable_if<
0251             (((p1 == 1) && (pin == 2)) ||
0252              ((p1 == 2) && (pin == 1)))
0253              && (p2 == -1)>::type>
0254     constexpr std_out_<1, 2> operator& (const std_out_<pin>&) const
0255     {
0256         return std_out_<1, 2> ();
0257     }
0258 
0259 };
0260 
0261 struct close_t
0262 {
0263     constexpr close_t() = default;
0264     template<int T, int U>
0265     api::close_out<T,U> operator()(std_out_<T,U>) {return api::close_out<T,U>();}
0266 };
0267 
0268 
0269 
0270 }
0271 ///This constant is a utility to allow syntax like `std_out > close` for closing I/O streams.
0272 constexpr boost::process::detail::close_t close;
0273 ///This constant is a utility to redirect streams to the null-device.
0274 constexpr boost::process::detail::null_t  null;
0275 
0276 /**
0277 This property allows to set the input stream for the child process.
0278 
0279 \section stdin_details Details
0280 
0281 \subsection stdin_file File Input
0282 
0283 The file I/O simple redirects the stream to a file, for which the possible types are
0284 
0285  - `boost::process::filesystem::path`
0286  - `std::basic_string<char_type>`
0287  - `const char_type*`
0288  - `FILE*`
0289 
0290 with `char_type` being either `char` or `wchar_t`.
0291 
0292 FILE* is explicitly added, so the process can easily redirect the output stream
0293 of the child to another output stream of the process. That is:
0294 
0295 \code{.cpp}
0296 system("ls", std_in < stdin);
0297 \endcode
0298 
0299 \warning If the launching and the child process use the input, this leads to undefined behaviour.
0300 
0301 A syntax like `system("ls", std_out > std::cerr)` is not possible, due to the C++
0302 implementation not providing access to the handle.
0303 
0304 The valid expressions for this property are
0305 
0306 \code{.cpp}
0307 std_in < file;
0308 std_in = file;
0309 \endcode
0310 
0311 \subsection stdin_pipe Pipe Input
0312 
0313 As explained in the corresponding section, the boost.process library provides a
0314 @ref boost::process::async_pipe "async_pipe" class which can be
0315 used to communicate with child processes.
0316 
0317 \note Technically the @ref boost::process::async_pipe "async_pipe"
0318 works synchronous here, since no asio implementation is used by the library here.
0319 The async-operation will then however not end if the process is finished, since
0320 the pipe remains open. You can use the async_close function with on_exit to fix that.
0321 
0322 Valid expressions with pipes are these:
0323 
0324 \code{.cpp}
0325 std_in < pipe;
0326 std_in = pipe;
0327 \endcode
0328 
0329 Where the valid types for `pipe` are the following:
0330 
0331  - `basic_pipe`
0332  - `async_pipe`
0333  - `basic_opstream`
0334  - `basic_pstream`
0335 
0336 Note that the pipe may also be used between several processes, like this:
0337 
0338 \code{.cpp}
0339 pipe p;
0340 child c1("nm", "a.out", std_out>p);
0341 child c2("c++filt", std_in<p);
0342 \endcode
0343 
0344 \subsection stdin_async_pipe Asynchronous Pipe Input
0345 
0346 Asynchronous Pipe I/O classifies communication which has automatically handling
0347 of the asynchronous operations by the process library. This means, that a pipe will be
0348 constructed, the async_read/-write will be automatically started, and that the
0349 end of the child process will also close the pipe.
0350 
0351 Valid types for pipe I/O are the following:
0352 
0353  - `boost::asio::const_buffer`   \xmlonly <footnote><para> Constructed with <code>boost::asio::buffer</code></para></footnote> \endxmlonly
0354  - `boost::asio::mutable_buffer` \xmlonly <footnote><para> Constructed with <code>boost::asio::buffer</code></para></footnote> \endxmlonly
0355  - `boost::asio::streambuf`
0356 
0357 Valid expressions with pipes are these:
0358 
0359 \code{.cpp}
0360 std_in < buffer;
0361 std_in = buffer;
0362 std_out > buffer;
0363 std_out = buffer;
0364 std_err > buffer;
0365 std_err = buffer;
0366 (std_out & std_err) > buffer;
0367 (std_out & std_err) = buffer;
0368 \endcode
0369 
0370 \note  It is also possible to get a future for std_in, by chaining another `std::future<void>` onto it,
0371 so you can wait for the input to be completed. It looks like this:
0372 \code{.cpp}
0373 std::future<void> fut;
0374 boost::asio::io_context ios;
0375 std::string data;
0376 child c("prog", std_in < buffer(data) >  fut, ios);
0377 fut.get();
0378 \endcode
0379 
0380 
0381 \note `boost::asio::buffer` is also available in the `boost::process` namespace.
0382 
0383 \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.
0384 
0385 
0386 \subsection stdin_close Close
0387 
0388 The input stream can be closed, so it cannot be read from. This will lead to an error when attempted.
0389 
0390 This can be achieved by the following syntax.
0391 
0392 \code{.cpp}
0393 std_in < close;
0394 std_in = close;
0395 std_in.close();
0396 \endcode
0397 
0398 \subsection stdin_null Null
0399 
0400 The input stream can be redirected to read from the null-device, which means that only `EOF` is read.
0401 
0402 The syntax to achieve that has the following variants:
0403 
0404 \code{.cpp}
0405 std_in < null;
0406 std_in = null;
0407 std_in.null();
0408 \endcode
0409 
0410 */
0411 
0412 constexpr boost::process::detail::std_in_<void>   std_in;
0413 
0414 /**
0415 This property allows to set the output stream for the child process.
0416 
0417 \note The Semantic is the same as for \xmlonly <globalname alt="boost::process::std_err">std_err</globalname> \endxmlonly
0418 
0419 \note `std_err` and `std_out` can be combined into one stream, with the `operator &`, i.e. `std_out & std_err`.
0420 
0421 \section stdout_details Details
0422 
0423 \subsection stdout_file File Input
0424 
0425 The file I/O simple redirects the stream to a file, for which the possible types are
0426 
0427  - `boost::process::filesystem::path`
0428  - `std::basic_string<char_type>`
0429  - `const char_type*`
0430  - `FILE*`
0431 
0432 with `char_type` being either `char` or `wchar_t`.
0433 
0434 FILE* is explicitly added, so the process can easily redirect the output stream
0435 of the child to another output stream of the process. That is:
0436 
0437 \code{.cpp}
0438 system("ls", std_out < stdin);
0439 \endcode
0440 
0441 \warning If the launching and the child process use the input, this leads to undefined behaviour.
0442 
0443 A syntax like `system("ls", std_out > std::cerr)` is not possible, due to the C++
0444 implementation not providing access to the handle.
0445 
0446 The valid expressions for this property are
0447 
0448 \code{.cpp}
0449 std_out < file;
0450 std_out = file;
0451 \endcode
0452 
0453 \subsection stdout_pipe Pipe Output
0454 
0455 As explained in the corresponding section, the boost.process library provides a
0456 @ref boost::process::async_pipe "async_pipe" class which can be
0457 used to communicate with child processes.
0458 
0459 \note Technically the @ref boost::process::async_pipe "async_pipe"
0460 works like a synchronous pipe here, since no asio implementation is used by the library here.
0461 The asynchronous operation will then however not end if the process is finished, since
0462 the pipe remains open. You can use the async_close function with on_exit to fix that.
0463 
0464 Valid expressions with pipes are these:
0465 
0466 \code{.cpp}
0467 std_out > pipe;
0468 std_out = pipe;
0469 \endcode
0470 
0471 Where the valid types for `pipe` are the following:
0472 
0473  - `basic_pipe`
0474  - `async_pipe`
0475  - `basic_ipstream`
0476  - `basic_pstream`
0477 
0478 Note that the pipe may also be used between several processes, like this:
0479 
0480 \code{.cpp}
0481 pipe p;
0482 child c1("nm", "a.out", std_out>p);
0483 child c2("c++filt", std_in<p);
0484 \endcode
0485 
0486 \subsection stdout_async_pipe Asynchronous Pipe Output
0487 
0488 Asynchronous Pipe I/O classifies communication which has automatically handling
0489 of the async operations by the process library. This means, that a pipe will be
0490 constructed, the async_read/-write will be automatically started, and that the
0491 end of the child process will also close the pipe.
0492 
0493 Valid types for pipe I/O are the following:
0494 
0495  - `boost::asio::mutable_buffer` \xmlonly <footnote><para> Constructed with <code>boost::asio::buffer</code></para></footnote> \endxmlonly
0496  - `boost::asio::streambuf`
0497  - `std::future<std::vector<char>>`
0498  - `std::future<std::string>`
0499 
0500 Valid expressions with pipes are these:
0501 
0502 \code{.cpp}
0503 std_out > buffer;
0504 std_out = buffer;
0505 std_err > buffer;
0506 std_err = buffer;
0507 (std_out & std_err) > buffer;
0508 (std_out & std_err) = buffer;
0509 \endcode
0510 
0511 \note `boost::asio::buffer` is also available in the `boost::process` namespace.
0512 
0513 \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.
0514 
0515 
0516 \subsection stdout_close Close
0517 
0518 The out stream can be closed, so it cannot be write from.
0519 This will lead to an error when attempted.
0520 
0521 This can be achieved by the following syntax.
0522 
0523 \code{.cpp}
0524 std_out > close;
0525 std_out = close;
0526 std_out.close();
0527 \endcode
0528 
0529 \subsection stdout_null Null
0530 
0531 The output stream can be redirected to write to the null-device,
0532 which means that all output is discarded.
0533 
0534 The syntax to achieve that has the following variants:
0535 
0536 \code{.cpp}
0537 std_out > null;
0538 std_out = null;
0539 std_out.null();
0540 \endcode
0541 
0542 */
0543 
0544 constexpr boost::process::detail::std_out_<1> std_out;
0545 /**This property allows setting the `stderr` stream. The semantic and syntax is the same as for
0546  * \xmlonly <globalname alt="boost::process::std_out">std_out</globalname> \endxmlonly .
0547  */
0548 constexpr boost::process::detail::std_out_<2> std_err;
0549 
0550 }}
0551 #endif /* INCLUDE_BOOST_PROCESS_IO_HPP_ */