?????????? ????????? - ??????????????? - /home/agenciai/public_html/cd38d8/process.zip
???????
PK oM�[���h h group.hppnu �[��� // Copyright (c) 2016 Klemens D. Morgenstern // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) /** * \file boost/process/group.hpp * * Defines a group process class. * For additional information see the platform specific implementations: * * - [windows - job object](https://msdn.microsoft.com/en-us/library/windows/desktop/ms684161.aspx) * - [posix - process group](http://pubs.opengroup.org/onlinepubs/009695399/functions/setpgid.html) * */ #ifndef BOOST_PROCESS_GROUP_HPP #define BOOST_PROCESS_GROUP_HPP #include <boost/process/detail/config.hpp> #include <boost/process/child.hpp> #include <chrono> #include <memory> #include <boost/none.hpp> #include <atomic> #if defined(BOOST_POSIX_API) #include <boost/process/detail/posix/group_handle.hpp> #include <boost/process/detail/posix/group_ref.hpp> #include <boost/process/detail/posix/wait_group.hpp> #elif defined(BOOST_WINDOWS_API) #include <boost/process/detail/windows/group_handle.hpp> #include <boost/process/detail/windows/group_ref.hpp> #include <boost/process/detail/windows/wait_group.hpp> #endif namespace boost { namespace process { namespace detail { struct group_builder; } /** * Represents a process group. * * Groups are movable but non-copyable. The destructor * automatically closes handles to the group process. * * The group will have the same interface as std::thread. * * \note If the destructor is called without a previous detach or wait, the group will be terminated. * * \attention If a default-constructed group is used before being used in a process launch, the behaviour is undefined. * * \attention Waiting for groups is currently broken on windows and will most likely result in a dead-lock. */ class group { ::boost::process::detail::api::group_handle _group_handle; bool _attached = true; public: typedef ::boost::process::detail::api::group_handle group_handle; ///Native representation of the handle. typedef group_handle::handle_t native_handle_t; explicit group(group_handle &&ch) : _group_handle(std::move(ch)) {} ///Construct the group from a native_handle explicit group(native_handle_t & handle) : _group_handle(handle) {}; group(const group&) = delete; ///Move constructor group(group && lhs) : _group_handle(std::move(lhs._group_handle)), _attached (lhs._attached) { lhs._attached = false; } ///Default constructor group() = default; group& operator=(const group&) = delete; ///Move assign group& operator=(group && lhs) { _group_handle= std::move(lhs._group_handle); _attached = lhs._attached; return *this; }; ///Detach the group void detach() {_attached = false; } /** Join the child. This just calls wait, but that way the naming is similar to std::thread */ void join() {wait();} /** Check if the child is joinable. */ bool joinable() {return _attached;} /** Destructor * * \note If the destructor is called without a previous detach or wait, the group will be terminated. * */ ~group() { std::error_code ec; if ( _attached && valid()) terminate(ec); } ///Obtain the native handle of the group. native_handle_t native_handle() const { return _group_handle.handle(); } ///Wait for the process group to exit. void wait() { boost::process::detail::api::wait(_group_handle); } ///\overload void wait() void wait(std::error_code & ec) noexcept { boost::process::detail::api::wait(_group_handle, ec); } /** Wait for the process group to exit for period of time. * \return True if all child processes exited while waiting.*/ template< class Rep, class Period > bool wait_for (const std::chrono::duration<Rep, Period>& rel_time) { return boost::process::detail::api::wait_for(_group_handle, rel_time); } /** \overload bool wait_for(const std::chrono::duration<Rep, Period>& timeout_time ) */ template< class Rep, class Period > bool wait_for (const std::chrono::duration<Rep, Period>& rel_time, std::error_code & ec) noexcept { return boost::process::detail::api::wait_for(_group_handle, rel_time, ec); } /** Wait for the process group to exit until a point in time. * \return True if all child processes exited while waiting.*/ template< class Clock, class Duration > bool wait_until(const std::chrono::time_point<Clock, Duration>& timeout_time ) { return boost::process::detail::api::wait_until(_group_handle, timeout_time); } /** \overload bool wait_until(const std::chrono::time_point<Clock, Duration>& timeout_time ) */ template< class Clock, class Duration > bool wait_until(const std::chrono::time_point<Clock, Duration>& timeout_time, std::error_code & ec) noexcept { return boost::process::detail::api::wait_until(_group_handle, timeout_time, ec); } ///Check if the group has a valid handle. bool valid() const { return _group_handle.valid(); } ///Convenience to call valid. explicit operator bool() const {return valid();} ///Terminate the process group, i.e. all processes in the group void terminate() { ::boost::process::detail::api::terminate(_group_handle); } ///\overload void terminate() void terminate(std::error_code & ec) noexcept { ::boost::process::detail::api::terminate(_group_handle, ec); } ///Assign a child process to the group void add(const child &c) { _group_handle.add(c.native_handle()); } ///\overload void assign(const child & c) void add(const child &c, std::error_code & ec) noexcept { _group_handle.add(c.native_handle(), ec); } ///Check if the child process is in the group bool has(const child &c) { return _group_handle.has(c.native_handle()); } ///\overload bool has(const child &) bool has(const child &c, std::error_code & ec) noexcept { return _group_handle.has(c.native_handle(), ec); } friend struct detail::group_builder; }; namespace detail { struct group_tag; struct group_builder { group * group_p; void operator()(group & grp) {this->group_p = &grp;}; typedef api::group_ref result_type; api::group_ref get_initializer() {return api::group_ref (group_p->_group_handle);}; }; template<> struct initializer_tag<group> { typedef group_tag type; }; template<> struct initializer_builder<group_tag> { typedef group_builder type; }; } }} #endif PK oM�[p�t�� � search_path.hppnu �[��� // Copyright (c) 2006, 2007 Julio M. Merino Vidal // Copyright (c) 2008 Ilya Sokolov, Boris Schaeling // Copyright (c) 2009 Boris Schaeling // Copyright (c) 2010 Felipe Tanus, Boris Schaeling // Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) /** * \file boost/process/search_path.hpp * * Defines a function to search for an executable in path. */ #ifndef BOOST_PROCESS_SEARCH_PATH_HPP #define BOOST_PROCESS_SEARCH_PATH_HPP #include <boost/process/detail/config.hpp> #include <boost/process/environment.hpp> #if defined(BOOST_POSIX_API) #include <boost/process/detail/posix/search_path.hpp> #elif defined(BOOST_WINDOWS_API) #include <boost/process/detail/windows/search_path.hpp> #endif namespace boost { namespace process { /** * Searches for an executable in path. * * filename must be a basename including the file extension. * It must not include any directory separators (like a slash). * On Windows the file extension may be omitted. The function * will then try the various file extensions for executables on * Windows to find filename. * * \param filename The base of the filename to find * * \param path the set of paths to search, defaults to the "PATH" environment variable. * * \returns the absolute path to the executable filename or an * empty string if filename isn't found */ inline boost::filesystem::path search_path(const boost::filesystem::path &filename, const std::vector<boost::filesystem::path> path = ::boost::this_process::path()) { return ::boost::process::detail::api::search_path(filename, path); } }} #endif PK oM�[�c��y y start_dir.hppnu �[��� // Copyright (c) 2006, 2007 Julio M. Merino Vidal // Copyright (c) 2008 Ilya Sokolov, Boris Schaeling // Copyright (c) 2009 Boris Schaeling // Copyright (c) 2010 Felipe Tanus, Boris Schaeling // Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_PROCESS_START_IN_DIR_HPP #define BOOST_PROCESS_START_IN_DIR_HPP #include <boost/process/detail/config.hpp> #include <boost/process/detail/handler.hpp> #include <boost/process/locale.hpp> #include <boost/process/detail/traits/wchar_t.hpp> #if defined (BOOST_POSIX_API) #include <boost/process/detail/posix/start_dir.hpp> #elif defined (BOOST_WINDOWS_API) #include <boost/process/detail/windows/start_dir.hpp> #endif #include <boost/process/detail/config.hpp> #include <string> #include <boost/filesystem/path.hpp> /** \file boost/process/start_dir.hpp * Header which provides the start_dir property, which allows to set the directory the process shall be started in. \xmlonly <programlisting> namespace boost { namespace process { <emphasis>unspecified</emphasis> <globalname alt="boost::process::start_dir">start_dir</globalname>; } } </programlisting> \endxmlonly */ namespace boost { namespace process { namespace detail { struct start_dir_ { constexpr start_dir_() {}; template<typename Char> api::start_dir_init<Char> operator()(const std::basic_string<Char> & st) const {return {st}; } template<typename Char> api::start_dir_init<Char> operator()(std::basic_string<Char> && s) const {return {std::move(s)}; } template<typename Char> api::start_dir_init<Char> operator()(const Char* s) const {return {s}; } api::start_dir_init<typename boost::filesystem::path::value_type> operator()(const boost::filesystem::path & st) const {return {st.native()}; } template<typename Char> api::start_dir_init<Char> operator= (const std::basic_string<Char> & st) const {return {st}; } template<typename Char> api::start_dir_init<Char> operator= (std::basic_string<Char> && s) const {return {std::move(s)}; } template<typename Char> api::start_dir_init<Char> operator= (const Char* s) const {return {s}; } api::start_dir_init<typename boost::filesystem::path::value_type> operator= (const boost::filesystem::path & st) const {return {st.native()}; } }; template<> struct is_wchar_t<api::start_dir_init<wchar_t>> : std::true_type {}; template<> struct char_converter<char, api::start_dir_init<wchar_t>> { static api::start_dir_init<char> conv(const api::start_dir_init<wchar_t> & in) { return api::start_dir_init<char>{::boost::process::detail::convert(in.str())}; } }; template<> struct char_converter<wchar_t, api::start_dir_init<char>> { static api::start_dir_init<wchar_t> conv(const api::start_dir_init<char> & in) { return api::start_dir_init<wchar_t>{::boost::process::detail::convert(in.str())}; } }; } /** To set the start dir, the `start_dir` property is provided. The valid operations are the following: \code{.cpp} start_dir=path start_dir(path) \endcode It can be used with `std::string`, `std::wstring` and `boost::filesystem::path`. */ constexpr ::boost::process::detail::start_dir_ start_dir; }} #endif PK oM�[a�{ 0 0 env.hppnu �[��� // Copyright (c) 2016 Klemens D. Morgenstern // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_PROCESS_DETAIL_ENV_HPP_ #define BOOST_PROCESS_DETAIL_ENV_HPP_ #include <boost/process/environment.hpp> #include <boost/none.hpp> #if defined(BOOST_POSIX_API) #include <boost/process/detail/posix/env_init.hpp> #elif defined(BOOST_WINDOWS_API) #include <boost/process/detail/windows/env_init.hpp> #endif /** \file boost/process/env.hpp * * This header which provides the `env` property. It allows the modification of the * environment the child process will run in, in a functional style. * * \xmlonly <programlisting> namespace boost { namespace process { <emphasis>unspecified</emphasis> <globalname alt="boost::process::env">env</globalname>; } } </programlisting> * \endxmlonly * * For additional information see the platform documentations: * * - [windows](https://msdn.microsoft.com/en-US/library/windows/desktop/ms682653.aspx) * - [posix](http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html) * */ namespace boost { namespace process { namespace detail { template<typename Char> std::size_t make_env_string_size(const std::basic_string<Char> & ch) { return ch.size() + 1; } template<typename Char> std::size_t make_env_string_size(const Char * ch) { std::size_t sz = 0; while (ch[sz] != null_char<Char>()) sz++; sz++; return sz; } template<typename Char, typename Container> inline std::basic_string<Char> make_env_string(const Container & value) { std::size_t sz = 0; for (auto & v : value) sz += make_env_string_size(v); std::basic_string<Char> s; s.reserve(sz); //+1 for ;, end doesn't have one. for (auto & val : value) (s += val) += api::env_seperator<Char>(); s.resize(s.size() -1); //remove last ';' return s; } template<typename Char> struct env_set { using string_type = std::basic_string<Char>; string_type key; string_type value; }; template<typename Char> struct env_append { using string_type = std::basic_string<Char>; string_type key; string_type value; }; template<typename Char> struct env_reset { using string_type = std::basic_string<Char>; string_type key; }; template<> struct is_wchar_t<env_set<wchar_t>> : std::true_type {}; template<> struct is_wchar_t<env_append<wchar_t>> : std::true_type {}; template<> struct is_wchar_t<env_reset<wchar_t>> : std::true_type {}; template<> struct is_wchar_t<basic_environment<wchar_t>> : std::true_type {}; template<> struct char_converter<char, env_set<wchar_t>> { static env_set<char> conv(const env_set<wchar_t> & in) { return {::boost::process::detail::convert(in.key), ::boost::process::detail::convert(in.value)}; } }; template<> struct char_converter<wchar_t, env_set<char>> { static env_set<wchar_t> conv(const env_set<char> & in) { return {::boost::process::detail::convert(in.key), ::boost::process::detail::convert(in.value)}; } }; template<> struct char_converter<char, env_append<wchar_t>> { static env_append<char> conv(const env_append<wchar_t> & in) { return {::boost::process::detail::convert(in.key), ::boost::process::detail::convert(in.value)}; } }; template<> struct char_converter<wchar_t, env_append<char>> { static env_append<wchar_t> conv(const env_append<char> & in) { return {::boost::process::detail::convert(in.key), ::boost::process::detail::convert(in.value)}; } }; template<> struct char_converter<char, env_reset<wchar_t>> { static env_reset<char> conv(const env_reset<wchar_t> & in) { return {::boost::process::detail::convert(in.key)}; } }; template<> struct char_converter<wchar_t, env_reset<char>> { static env_reset<wchar_t> conv(const env_reset<char> & in) { return {::boost::process::detail::convert(in.key)}; } }; template<typename Char> struct env_init { basic_environment<Char> env; }; template<> struct char_converter<char, env_init<wchar_t>> { static env_init<char> conv(const env_init<wchar_t> & in) { return {basic_environment<char>(in.env)}; } }; template<> struct char_converter<wchar_t, env_init<char>> { static env_init<wchar_t> conv(const env_init<char> & in) { return {basic_environment<wchar_t>(in.env)}; } }; template<> struct char_converter<char, basic_environment<wchar_t>> { static basic_environment<char> conv(const basic_environment<wchar_t> & in) { return { basic_environment<char>(in) }; } }; template<> struct char_converter<wchar_t, basic_environment<char>> { static basic_environment<wchar_t> conv(const basic_environment<char> & in) { return { basic_environment<wchar_t>(in) }; } }; template<typename Char> struct env_proxy { using string_type = std::basic_string<Char>; string_type key; env_set<Char> operator=(const string_type & value) { return {std::move(key), value}; } env_set<Char> operator=(const std::vector<string_type> & value) { return {std::move(key), make_env_string<Char>(value)}; } env_set<Char> operator=(const std::initializer_list<const Char*> & value) { return {std::move(key), make_env_string<Char>(value)}; } env_append<Char> operator+=(const string_type & value) { return {std::move(key), value}; } env_append<Char> operator+=(const std::vector<string_type> & value) { return {std::move(key), make_env_string<Char>(value)}; } env_append<Char> operator+=(const std::initializer_list<const Char*> & value) { return {std::move(key), make_env_string<Char>(value)}; } env_reset<Char> operator=(boost::none_t) { return {std::move(key)}; } }; struct env_ { constexpr env_() {}; template<typename Char> env_set<Char> operator()(const std::basic_string<Char> & key, const std::basic_string<Char> & value) const { return {key, value}; } template<typename Char> env_set<Char> operator()(const std::basic_string<Char> & key, const std::vector<std::basic_string<Char>> & value) const { return {key, make_env_string<Char>(value)}; } template<typename Char> env_set<Char> operator()(const std::basic_string<Char> & key, const std::initializer_list<Char*> & value) const { return {key, make_env_string<Char>(value)}; } template<typename Char> env_reset<Char> operator()(const std::basic_string<Char> & key, boost::none_t) { return {key}; } template<typename Char> env_proxy<Char> operator[](const std::basic_string<Char> & key) const { return {key}; } template<typename Char> env_proxy<Char> operator[](const Char* key) const { return {key}; } template<typename Char> env_init<Char> operator()(const basic_environment<Char> & env) const { return {env}; } template<typename Char> env_init<Char> operator= (const basic_environment<Char> & env) const { return {env}; } }; template<typename Char> struct env_builder { basic_environment<Char> env; env_builder() : env{basic_native_environment<Char>()} {} void operator()(const basic_environment<Char> & e) { env = e; } void operator()(env_init<Char> & ei) { env = std::move(ei.env); } void operator()(env_set<Char> & es) { env[es.key] = es.value; } void operator()(env_reset<Char> & es) { env.erase(es.key); } template<typename T> void operator()(env_append<T> & es) { env[es.key] += es.value; } typedef api::env_init<Char> result_type; api::env_init<Char> get_initializer() { return api::env_init<Char>(std::move(env)); } }; template<> struct initializer_builder<env_tag<char>> { typedef env_builder<char> type; }; template<> struct initializer_builder<env_tag<wchar_t>> { typedef env_builder<wchar_t> type; }; } /** The `env` property provides a functional way to modify the environment used by the child process. If none is passed the environment is inherited from the father process. Appending means that the environment will be interpreted as a ';' or ':' separated list as used in `PATH`. On both `posix` and `windows` the environment variables can be lists of strings, separated by ';'. This is typically used for the `PATH` variable. By default the environment will be inherited from the launching process, which is also true if environment are modified with this initializer. \section env_details Details \subsection env_operations Operations \subsubsection env_set_var Setting variables To set a variable `id` the value `value` the following syntax can be used. \code{.cpp} env[id] = value; env(id, value); \endcode `std::initializer_list` is among the allowed types, so the following syntax is also possible. \code{.cpp} env[id] = {value1, value2}; env(id, {value1, value2}); \endcode \note Creates the variable if it does not exist. The following lists contain possible value types, with `char_type` being either `char` or `wchar_t` for both `id` and `value`. \paragraph id id - `std::basic_string<char_type>` - `const char_type *` \paragraph env_set_var_value value - `std::basic_string<char_type>` - `const char_type * ` - `std::initializer_list<const char_type *>` - `std::vector<std::basic_string<char_type>>` \note Using `std::vector` or `std::initializer_list` \subsubsection env_append_var Append variables Appending means, that a variable will be interpreted as a To append a variable `id` the value `value` the following syntax can be used: \code{.cpp} env[id] += value; \endcode `std::initializer_list` is among the allowed types, so the following syntax is also possible. \code{.cpp} env[id] += {value1, value2}; \endcode \note Creates the variable if it does not exist. The following lists contain possible value types, with `char_type` being either `char` or `wchar_t` for both `id` and `value`. \paragraph env_append_var_id id - `std::basic_string<char_type>` - `const char_type *` \paragraph env_append_var_value value - `std::basic_string<char_type>` - `const char_type *` - `std::initializer_list<const char_type *>` - `std::vector<std::basic_string<char_type>>` \subsubsection env_reset Reset variables Reseting signle variables can be done in the following way: \code{.cpp} env[id] = boost::none; env(id, boost::none); \endcode \note This does not set the value empty, but removes it from the list. The following lists contain possible value types, with `char_type` being either `char` or `wchar_t`: \paragraph env_reset_var_id id - `std::basic_string<char_type>` - `const char_type *` \subsubsection env_init Initialize the environment The whole environment can be initialized from an object of type \xmlonly <classname>boost::process::environment</classname> \endxmlonly \code{.cpp} env=env; env(env); \endcode \note The passed `environment` can also be default-constructed to get an empty environment. \paragraph env_init_var_id id - `std::basic_string<char_type>` - `const char_type *` \paragraph env_init_var_value value - `boost::process::basic_environment<char_type>` \subsection env_example Example \code{.cpp} spawn("b2", env["PATH"]+="F:/boost", env["SOME_VAR"]=boost::none, env["NEW_VAR"]="VALUE"); \endcode If the overload style should be done by passing an instance of \xmlonly <classname>boost::process::environment</classname> \endxmlonly the above example would look like this. \code{.cpp} environment e = this_process::environment(); e["PATH"] += "F:/boost"; e.erase("SOME_VAR"); e["NEW_VAR"] = "VALUE"; spawn("b2", e); \endcode \warning Passing an empty environment will cause undefined behaviour. */ constexpr boost::process::detail::env_ env{}; }} #endif /* INCLUDE_BOOST_PROCESS_DETAIL_ENV_HPP_ */ PK oM�[۟� � system.hppnu �[��� // Copyright (c) 2006, 2007 Julio M. Merino Vidal // Copyright (c) 2008 Ilya Sokolov, Boris Schaeling // Copyright (c) 2009 Boris Schaeling // Copyright (c) 2010 Felipe Tanus, Boris Schaeling // Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling // Copyright (c) 2016 Klemens D. Morgenstern // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) /** * \file boost/process/system.hpp * * Defines a system function. */ #ifndef BOOST_PROCESS_SYSTEM_HPP #define BOOST_PROCESS_SYSTEM_HPP #include <boost/process/detail/config.hpp> #include <boost/process/detail/on_exit.hpp> #include <boost/process/child.hpp> #include <boost/process/detail/async_handler.hpp> #include <boost/process/detail/execute_impl.hpp> #include <boost/asio/post.hpp> #include <type_traits> #include <mutex> #include <condition_variable> #if defined(BOOST_POSIX_API) #include <boost/process/posix.hpp> #endif namespace boost { namespace process { namespace detail { struct system_impl_success_check : handler { bool succeeded = false; template<typename Exec> void on_success(Exec &) { succeeded = true; } }; template<typename IoService, typename ...Args> inline int system_impl( std::true_type, /*needs ios*/ std::true_type, /*has io_context*/ Args && ...args) { IoService & ios = ::boost::process::detail::get_io_context_var(args...); system_impl_success_check check; std::atomic_bool exited{false}; child c(std::forward<Args>(args)..., check, ::boost::process::on_exit( [&](int, const std::error_code&) { boost::asio::post(ios.get_executor(), [&]{exited.store(true);}); })); if (!c.valid() || !check.succeeded) return -1; while (!exited.load()) ios.poll(); return c.exit_code(); } template<typename IoService, typename ...Args> inline int system_impl( std::true_type, /*needs ios */ std::false_type, /*has io_context*/ Args && ...args) { IoService ios; child c(ios, std::forward<Args>(args)...); if (!c.valid()) return -1; ios.run(); if (c.running()) c.wait(); return c.exit_code(); } template<typename IoService, typename ...Args> inline int system_impl( std::false_type, /*needs ios*/ std::true_type, /*has io_context*/ Args && ...args) { child c(std::forward<Args>(args)...); if (!c.valid()) return -1; c.wait(); return c.exit_code(); } template<typename IoService, typename ...Args> inline int system_impl( std::false_type, /*has async */ std::false_type, /*has io_context*/ Args && ...args) { child c(std::forward<Args>(args)... #if defined(BOOST_POSIX_API) ,::boost::process::posix::sig.dfl() #endif ); if (!c.valid()) return -1; c.wait(); return c.exit_code(); } } /** Launches a process and waits for its exit. It works as std::system, though it allows all the properties boost.process provides. It will execute the process and wait for it's exit; then return the exit_code. \code{.cpp} int ret = system("ls"); \endcode \attention Using this function with synchronous pipes leads to many potential deadlocks. When using this function with an asynchronous properties and NOT passing an io_context object, the system function will create one and run it. When the io_context is passed to the function, the system function will check if it is active, and call the io_context::run function if not. */ template<typename ...Args> inline int system(Args && ...args) { typedef typename ::boost::process::detail::needs_io_context<Args...>::type need_ios; typedef typename ::boost::process::detail::has_io_context<Args...>::type has_ios; return ::boost::process::detail::system_impl<boost::asio::io_context>( need_ios(), has_ios(), std::forward<Args>(args)...); } }} #endif PK oM�[|� shell.hppnu �[��� // Copyright (c) 2006, 2007 Julio M. Merino Vidal // Copyright (c) 2008 Ilya Sokolov, Boris Schaeling // Copyright (c) 2009 Boris Schaeling // Copyright (c) 2010 Felipe Tanus, Boris Schaeling // Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling // Copyright (c) 2016 Klemens D. Morgenstern // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_PROCESS_SHELL_PATH_HPP #define BOOST_PROCESS_SHELL_PATH_HPP #include <boost/process/detail/config.hpp> #include <boost/process/detail/traits/wchar_t.hpp> #if defined(BOOST_POSIX_API) #include <boost/process/detail/posix/shell_path.hpp> #elif defined(BOOST_WINDOWS_API) #include <boost/process/detail/windows/shell_path.hpp> #endif /** \file boost/process/shell.hpp * * Header which provides the shell property. This provides the * property to launch a process through the system shell. * It also allows the user to obtain the shell-path via shell(). \xmlonly <programlisting> namespace boost { namespace process { <emphasis>unspecified</emphasis> <globalname alt="boost::process::shell">shell</globalname>; } } </programlisting> \endxmlonly */ namespace boost { namespace process { namespace detail { struct shell_ { constexpr shell_() {} boost::filesystem::path operator()() const { return boost::process::detail::api::shell_path(); } boost::filesystem::path operator()(std::error_code & ec) const noexcept { return boost::process::detail::api::shell_path(ec); } }; template<> struct is_wchar_t<shell_> : is_wchar_t<boost::filesystem::path> { }; } /** The shell property enables to launch a program through the shell of the system. \code{.cpp} system("gcc", shell); \endcode The shell argument goes without any expression. The operator() is overloaded, to obtain the path of the system shell. \code{.cpp} auto shell_cmd = shell(); //avoid exceptions std::error_code ec; shell_cmd = shell(ec); \endcode \attention Launching through the shell will NOT provide proper error handling, i.e. you will get an error via the return code. \attention Executing shell commands that incorporate unsanitized input from an untrusted source makes a program vulnerable to shell injection, a serious security flaw which can result in arbitrary command execution. For this reason, the use of `shell` is strongly discouraged in cases where the command string is constructed from external input: */ constexpr ::boost::process::detail::shell_ shell; }} #endif PK oM�[�:���8 �8 extend.hppnu �[��� // Copyright (c) 2016 Klemens D. Morgenstern // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_PROCESS_EXTENSIONS_HPP_ #define BOOST_PROCESS_EXTENSIONS_HPP_ #include <boost/process/detail/handler.hpp> #include <boost/process/detail/used_handles.hpp> #if defined(BOOST_WINDOWS_API) #include <boost/process/detail/windows/executor.hpp> #include <boost/process/detail/windows/async_handler.hpp> #include <boost/process/detail/windows/asio_fwd.hpp> #else #include <boost/process/detail/posix/executor.hpp> #include <boost/process/detail/posix/async_handler.hpp> #include <boost/process/detail/posix/asio_fwd.hpp> #endif /** \file boost/process/extend.hpp * * This header which provides the types and functions provided for custom extensions. * * \xmlonly Please refer to the <link linkend="boost_process.extend">tutorial</link> for more details. \endxmlonly */ namespace boost { namespace process { namespace detail { template<typename Tuple> inline asio::io_context& get_io_context(const Tuple & tup); } ///Namespace for extensions \attention This is experimental. namespace extend { #if defined(BOOST_WINDOWS_API) template<typename Char, typename Sequence> using windows_executor = ::boost::process::detail::windows::executor<Char, Sequence>; template<typename Sequence> struct posix_executor; #elif defined(BOOST_POSIX_API) template<typename Sequence> using posix_executor = ::boost::process::detail::posix::executor<Sequence>; template<typename Char, typename Sequence> struct windows_executor; #endif using ::boost::process::detail::handler; using ::boost::process::detail::api::require_io_context; using ::boost::process::detail::api::async_handler; using ::boost::process::detail::get_io_context; using ::boost::process::detail::get_last_error; using ::boost::process::detail::throw_last_error; using ::boost::process::detail::uses_handles; using ::boost::process::detail::foreach_used_handle; using ::boost::process::detail::get_used_handles; ///This handler is invoked before the process in launched, to setup parameters. The required signature is `void(Exec &)`, where `Exec` is a template parameter. constexpr boost::process::detail::make_handler_t<boost::process::detail::on_setup_> on_setup; ///This handler is invoked if an error occured. The required signature is `void(auto & exec, const std::error_code&)`, where `Exec` is a template parameter. constexpr boost::process::detail::make_handler_t<boost::process::detail::on_error_> on_error; ///This handler is invoked if launching the process has succeeded. The required signature is `void(auto & exec)`, where `Exec` is a template parameter. constexpr boost::process::detail::make_handler_t<boost::process::detail::on_success_> on_success; #if defined(BOOST_POSIX_API) || defined(BOOST_PROCESS_DOXYGEN) ///This handler is invoked if the fork failed. The required signature is `void(auto & exec)`, where `Exec` is a template parameter. \note Only available on posix. constexpr ::boost::process::detail::make_handler_t<::boost::process::detail::posix::on_fork_error_ > on_fork_error; ///This handler is invoked if the fork succeeded. The required signature is `void(Exec &)`, where `Exec` is a template parameter. \note Only available on posix. constexpr ::boost::process::detail::make_handler_t<::boost::process::detail::posix::on_exec_setup_ > on_exec_setup; ///This handler is invoked if the exec call errored. The required signature is `void(auto & exec)`, where `Exec` is a template parameter. \note Only available on posix. constexpr ::boost::process::detail::make_handler_t<::boost::process::detail::posix::on_exec_error_ > on_exec_error; #endif #if defined(BOOST_PROCESS_DOXYGEN) ///Helper function to get the last error code system-independent inline std::error_code get_last_error(); ///Helper function to get and throw the last system error. /// \throws boost::process::process_error /// \param msg A message to add to the error code. inline void throw_last_error(const std::string & msg); ///\overload void throw_last_error(const std::string & msg) inline void throw_last_error(); /** This function gets the io_context from the initializer sequence. * * \attention Yields a compile-time error if no `io_context` is provided. * \param seq The Sequence of the initializer. */ template<typename Sequence> inline asio::io_context& get_io_context(const Sequence & seq); /** This class is the base for every initializer, to be used for extensions. * * The usage is done through compile-time polymorphism, so that the required * functions can be overloaded. * * \note None of the function need to be `const`. * */ struct handler { ///This function is invoked before the process launch. \note It is not required to be const. template <class Executor> void on_setup(Executor&) const {} /** This function is invoked if an error occured while trying to launch the process. * \note It is not required to be const. */ template <class Executor> void on_error(Executor&, const std::error_code &) const {} /** This function is invoked if the process was successfully launched. * \note It is not required to be const. */ template <class Executor> void on_success(Executor&) const {} /**This function is invoked if an error occured during the call of `fork`. * \note This function will only be called on posix. */ template<typename Executor> void on_fork_error (Executor &, const std::error_code&) const {} /**This function is invoked if the call of `fork` was successful, before * calling `execve`. * \note This function will only be called on posix. * \attention It will be invoked from the new process. */ template<typename Executor> void on_exec_setup (Executor &) const {} /**This function is invoked if the call of `execve` failed. * \note This function will only be called on posix. * \attention It will be invoked from the new process. */ template<typename Executor> void on_exec_error (Executor &, const std::error_code&) const {} }; /** Inheriting the class will tell the launching process that an `io_context` is * needed. This should always be used when \ref get_io_context is used. * */ struct require_io_context {}; /** Inheriting this class will tell the launching function, that an event handler * shall be invoked when the process exits. This automatically does also inherit * \ref require_io_context. * * You must add the following function to your implementation: * \code{.cpp} template<typename Executor> std::function<void(int, const std::error_code&)> on_exit_handler(Executor & exec) { auto handler_ = this->handler; return [handler_](int exit_code, const std::error_code & ec) { handler_(static_cast<int>(exit_code), ec); }; } \endcode The callback will be obtained by calling this function on setup and it will be invoked when the process exits. * * \warning Cannot be used with \ref boost::process::spawn */ struct async_handler : handler, require_io_context { }; ///The posix executor type. /** This type represents the posix executor and can be used for overloading in a custom handler. * \note It is an alias for the implementation on posix, and a forward-declaration on windows. * * \tparam Sequence The used initializer-sequence, it is fulfills the boost.fusion [sequence](http://www.boost.org/doc/libs/master/libs/fusion/doc/html/fusion/sequence.html) concept. \xmlonly As information for extension development, here is the structure of the process launching (in pseudo-code and uml) <xi:include href="posix_pseudocode.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/> <mediaobject> <caption> <para>The sequence if when no error occurs.</para> </caption> <imageobject> <imagedata fileref="boost_process/posix_success.svg"/> </imageobject> </mediaobject> <mediaobject> <caption> <para>The sequence if the execution fails.</para> </caption> <imageobject> <imagedata fileref="boost_process/posix_exec_err.svg"/> </imageobject> </mediaobject> <mediaobject> <caption> <para>The sequence if the fork fails.</para> </caption> <imageobject> <imagedata fileref="boost_process/posix_fork_err.svg"/> </imageobject> </mediaobject> \endxmlonly \note Error handling if execve fails is done through a pipe, unless \ref ignore_error is used. */ template<typename Sequence> struct posix_executor { ///A reference to the actual initializer-sequence Sequence & seq; ///A pointer to the name of the executable. const char * exe = nullptr; ///A pointer to the argument-vector. char *const* cmd_line = nullptr; ///A pointer to the environment variables, as default it is set to [environ](http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html) char **env = ::environ; ///The pid of the process - it will be -1 before invoking [fork](http://pubs.opengroup.org/onlinepubs/009695399/functions/fork.html), and after forking either 0 for the new process or a positive value if in the current process. */ pid_t pid = -1; ///This shared-pointer holds the exit code. It's done this way, so it can be shared between an `asio::io_context` and \ref child. std::shared_ptr<std::atomic<int>> exit_status = std::make_shared<std::atomic<int>>(still_active); ///This function returns a const reference to the error state of the executor. const std::error_code & error() const; ///This function can be used to report an error to the executor. This will be handled according to the configuration of the executor, i.e. it /// might throw an exception. \note This is the required way to handle errors in initializers. void set_error(const std::error_code &ec, const std::string &msg); ///\overload void set_error(const std::error_code &ec, const std::string &msg); void set_error(const std::error_code &ec, const char* msg); }; ///The windows executor type. /** This type represents the posix executor and can be used for overloading in a custom handler. * * \note It is an alias for the implementation on posix, and a forward-declaration on windows. * \tparam Sequence The used initializer-sequence, it is fulfills the boost.fusion [sequence](http://www.boost.org/doc/libs/master/libs/fusion/doc/html/fusion/sequence.html) concept. * \tparam Char The used char-type, either `char` or `wchar_t`. * \xmlonly As information for extension development, here is the structure of the process launching (in pseudo-code and uml)<xi:include href="windows_pseudocode.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/> <mediaobject> <caption> <para>The sequence for windows process creation.</para> </caption> <imageobject> <imagedata fileref="boost_process/windows_exec.svg"/> </imageobject> </mediaobject> \endxmlonly */ template<typename Char, typename Sequence> struct windows_executor { ///A reference to the actual initializer-sequence Sequence & seq; ///A pointer to the name of the executable. It's null by default. const Char * exe = nullptr; ///A pointer to the argument-vector. Must be set by some initializer. char Char* cmd_line = nullptr; ///A pointer to the environment variables. It's null by default. char Char* env = nullptr; ///A pointer to the working directory. It's null by default. const Char * work_dir = nullptr; ///A pointer to the process-attributes of type [SECURITY_ATTRIBUTES](https://msdn.microsoft.com/en-us/library/windows/desktop/aa379560.aspx). It's null by default. ::boost::detail::winapi::LPSECURITY_ATTRIBUTES_ proc_attrs = nullptr; ///A pointer to the thread-attributes of type [SECURITY_ATTRIBUTES](https://msdn.microsoft.com/en-us/library/windows/desktop/aa379560.aspx). It' null by default. ::boost::detail::winapi::LPSECURITY_ATTRIBUTES_ thread_attrs = nullptr; ///A logical bool value setting whether handles shall be inherited or not. ::boost::detail::winapi::BOOL_ inherit_handles = false; ///The element holding the process-information after process creation. The type is [PROCESS_INFORMATION](https://msdn.microsoft.com/en-us/library/windows/desktop/ms684873.aspx) ::boost::detail::winapi::PROCESS_INFORMATION_ proc_info{nullptr, nullptr, 0,0}; ///This shared-pointer holds the exit code. It's done this way, so it can be shared between an `asio::io_context` and \ref child. std::shared_ptr<std::atomic<int>> exit_status = std::make_shared<std::atomic<int>>(still_active); ///This function returns a const reference to the error state of the executor. const std::error_code & error() const; ///This function can be used to report an error to the executor. This will be handled according to the configuration of the executor, i.e. it /// might throw an exception. \note This is the required way to handle errors in initializers. void set_error(const std::error_code &ec, const std::string &msg); ///\overload void set_error(const std::error_code &ec, const std::string &msg); void set_error(const std::error_code &ec, const char* msg); ///The creation flags of the process ::boost::detail::winapi::DWORD_ creation_flags; ///The type of the [startup-info](https://msdn.microsoft.com/en-us/library/windows/desktop/ms686331.aspx), depending on the char-type. typedef typename detail::startup_info<Char>::type startup_info_t; ///The type of the [extended startup-info](https://msdn.microsoft.com/de-de/library/windows/desktop/ms686329.aspx), depending the char-type; only defined with winapi-version equal or higher than 6. typedef typename detail::startup_info_ex<Char>::type startup_info_ex_t; ///This function switches the information, so that the extended structure is used. \note It's only defined with winapi-version equal or higher than 6. void set_startup_info_ex(); ///This element is an instance or a reference (if \ref startup_info_ex exists) to the [startup-info](https://msdn.microsoft.com/en-us/library/windows/desktop/ms686331.aspx) for the process. startup_info_t startup_info; ///This element is the instance of the [extended startup-info](https://msdn.microsoft.com/de-de/library/windows/desktop/ms686329.aspx). It is only available with a winapi-version equal or highter than 6. startup_info_ex_t startup_info_ex; }; #endif } } } #endif PK oM�[�.J�` �` environment.hppnu �[��� // Copyright (c) 2016 Klemens D. Morgenstern // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_PROCESS_ENVIRONMENT_HPP_ #define BOOST_PROCESS_ENVIRONMENT_HPP_ #include <boost/process/detail/config.hpp> #include <boost/algorithm/string/split.hpp> #include <boost/algorithm/string/case_conv.hpp> #include <boost/iterator/transform_iterator.hpp> #include <boost/filesystem/path.hpp> #if defined(BOOST_POSIX_API) #include <boost/process/detail/posix/environment.hpp> #elif defined(BOOST_WINDOWS_API) #include <boost/process/detail/windows/environment.hpp> #endif namespace boost { namespace process { namespace detail { template<typename Char, typename Environment> struct const_entry { using value_type = Char ; using pointer = const value_type * ; using string_type = std::basic_string<value_type> ; using range = boost::iterator_range<pointer> ; using environment_t = Environment ; std::vector<string_type> to_vector() const { if (_data == nullptr) return std::vector<string_type>(); std::vector<string_type> data; auto str = string_type(_data); struct splitter { bool operator()(wchar_t w) const {return w == api::env_seperator<wchar_t>();} bool operator()(char c) const {return c == api::env_seperator<char> ();} } s; boost::split(data, _data, s); return data; } string_type to_string() const { if (_data != nullptr) return string_type(_data); else return string_type(); } string_type get_name() const {return string_type(_name.begin(), _name.end());} explicit const_entry(string_type&& name, pointer data, environment_t & env_) : _name(std::move(name)), _data(data), _env(&env_) {} explicit const_entry(string_type &&name, environment_t & env) : _name(std::move(name)), _data(nullptr), _env(&env) {} const_entry(const const_entry&) = default; const_entry& operator=(const const_entry&) = default; void reload() { auto p = _env->find(_name); if (p == _env->end()) _data = nullptr; else _data = p->_data; this->_env->reload(); } bool empty() const { return _data == nullptr; } protected: string_type _name; pointer _data; environment_t * _env; }; template<typename Char, typename Environment> struct entry : const_entry<Char, Environment> { using father = const_entry<Char, Environment>; using value_type = typename father::value_type; using string_type = typename father::string_type; using pointer = typename father::pointer; using environment_t = typename father::environment_t; explicit entry(string_type&& name, pointer data, environment_t & env) : father(std::move(name), data, env) {} explicit entry(string_type &&name, environment_t & env_) : father(std::move(name), env_) {} entry(const entry&) = default; entry& operator=(const entry&) = default; void assign(const string_type &value) { this->_env->set(this->_name, value); this->reload(); } void assign(const std::vector<string_type> &value) { string_type data; for (auto &v : value) { if (&v != &value.front()) data += api::env_seperator<value_type>(); data += v; } this->_env->set(this->_name, data); this->reload(); } void assign(const std::initializer_list<string_type> &value) { string_type data; for (auto &v : value) { if (&v != &*value.begin()) data += api::env_seperator<value_type>(); data += v; } this->_env->set(this->_name, data); this->reload(); } void append(const string_type &value) { if (this->_data == nullptr) this->_env->set(this->_name, value); else { string_type st = this->_data; this->_env->set(this->_name, st + api::env_seperator<value_type>() + value); } this->reload(); } void clear() { this->_env->reset(this->_name); this->_env->reload(); this->_data = nullptr; } entry &operator=(const string_type & value) { assign(value); return *this; } entry &operator=(const std::vector<string_type> & value) { assign(value); return *this; } entry &operator=(const std::initializer_list<string_type> & value) { assign(value); return *this; } entry &operator+=(const string_type & value) { append(value); return *this; } }; template<typename Char, typename Environment> struct make_entry { make_entry(const make_entry&) = default; make_entry& operator=(const make_entry&) = default; Environment *env; make_entry(Environment & env) : env(&env) {}; entry<Char, Environment> operator()(const Char* data) const { auto p = data; while ((*p != equal_sign<Char>()) && (*p != null_char<Char>())) p++; auto name = std::basic_string<Char>(data, p); p++; //go behind equal sign return entry<Char, Environment>(std::move(name), p, *env); } }; template<typename Char, typename Environment> struct make_const_entry { make_const_entry(const make_const_entry&) = default; make_const_entry& operator=(const make_const_entry&) = default; Environment *env; make_const_entry(Environment & env) : env(&env) {}; const_entry<Char, Environment> operator()(const Char* data) const { auto p = data; while ((*p != equal_sign<Char>()) && (*p != null_char<Char>())) p++; auto name = std::basic_string<Char>(data, p); p++; //go behind equal sign return const_entry<Char, Environment>(std::move(name), p, *env); } }; } #if !defined (BOOST_PROCESS_DOXYGEN) template<typename Char, template <class> class Implementation = detail::api::basic_environment_impl> class basic_environment_impl : public Implementation<Char> { Char** _get_end() const { auto p = this->_env_impl; while (*p != nullptr) p++; return p; } public: using string_type = std::basic_string<Char>; using implementation_type = Implementation<Char>; using base_type = basic_environment_impl<Char, Implementation>; using entry_maker = detail::make_entry<Char, base_type>; using entry_type = detail::entry <Char, base_type>; using const_entry_type = detail::const_entry <Char, const base_type>; using const_entry_maker = detail::make_const_entry<Char, const base_type>; friend entry_type; friend const_entry_type; using iterator = boost::transform_iterator< entry_maker, Char**, entry_type, entry_type>; using const_iterator = boost::transform_iterator<const_entry_maker, Char**, const_entry_type, const_entry_type>; using size_type = std::size_t; iterator begin() {return iterator(this->_env_impl, entry_maker(*this));} const_iterator begin() const {return const_iterator(this->_env_impl, const_entry_maker(*this));} const_iterator cbegin() const {return const_iterator(this->_env_impl, const_entry_maker(*this));} iterator end() {return iterator(_get_end(), entry_maker(*this));} const_iterator end() const {return const_iterator(_get_end(), const_entry_maker(*this));} const_iterator cend() const {return const_iterator(_get_end(), const_entry_maker(*this));} iterator find( const string_type& key ) { auto p = this->_env_impl; auto st1 = key + ::boost::process::detail::equal_sign<Char>(); while (*p != nullptr) { if (std::equal(st1.begin(), st1.end(), *p)) break; p++; } return iterator(p, entry_maker(*this)); } const_iterator find( const string_type& key ) const { auto p = this->_env_impl; auto st1 = key + ::boost::process::detail::equal_sign<Char>(); while (*p != nullptr) { if (std::equal(st1.begin(), st1.end(), *p)) break; p++; } return const_iterator(p, const_entry_maker(*this)); } std::size_t count(const string_type & st) const { auto p = this->_env_impl; auto st1 = st + ::boost::process::detail::equal_sign<Char>(); while (*p != nullptr) { if (std::equal(st1.begin(), st1.end(), *p)) return 1u; p++; } return 0u; } void erase(const string_type & id) { implementation_type::reset(id); this->reload(); } std::pair<iterator,bool> emplace(const string_type & id, const string_type & value) { auto f = find(id); if (f == end()) { implementation_type::set(id, value); this->reload(); return std::pair<iterator, bool>(find(id), true); } else return std::pair<iterator, bool>(f, false); } using implementation_type::implementation_type; using implementation_type::operator=; using native_handle_type = typename implementation_type::native_handle_type; using implementation_type::native_handle; //copy ctor if impl is copy-constructible bool empty() { return *this->_env_impl == nullptr; } std::size_t size() const { return (_get_end() - this->_env_impl); } void clear() { std::vector<string_type> names; names.resize(size()); std::transform(cbegin(), cend(), names.begin(), [](const const_entry_type & cet){return cet.get_name();}); for (auto & nm : names) implementation_type::reset(nm); this->reload(); } entry_type at( const string_type& key ) { auto f = find(key); if (f== end()) throw std::out_of_range(key + " not found"); return *f; } const_entry_type at( const string_type& key ) const { auto f = find(key); if (f== end()) throw std::out_of_range(key + " not found"); return *f; } entry_type operator[](const string_type & key) { auto p = find(key); if (p != end()) return *p; return entry_type(string_type(key), *this); } }; #endif #if defined(BOOST_PROCESS_DOXYGEN) /**Template representation of environments. It takes a character type (`char` or `wchar_t`) * as template parameter to implement the environment */ template<typename Char> class basic_environment { public: typedef std::basic_string<Char> string_type; typedef boost::transform_iterator< entry_maker, Char**> iterator ; typedef boost::transform_iterator<const_entry_maker, Char**> const_iterator ; typedef std::size_t size_type ; iterator begin() ; ///<Returns an iterator to the beginning const_iterator begin() const ; ///<Returns an iterator to the beginning const_iterator cbegin() const ; ///<Returns an iterator to the beginning iterator end() ; ///<Returns an iterator to the end const_iterator end() const; ///<Returns an iterator to the end const_iterator cend() const; ///<Returns an iterator to the end iterator find( const string_type& key ); ///<Find a variable by its name const_iterator find( const string_type& key ) const; ///<Find a variable by its name std::size_t count(const string_type & st) const; ///<Number of variables void erase(const string_type & id); ///<Erase variable by id. ///Emplace an environment variable. std::pair<iterator,bool> emplace(const string_type & id, const string_type & value); ///Default constructor basic_environment(); ///Copy constructor. basic_environment(const basic_environment & ); ///Move constructor. basic_environment(basic_environment && ); ///Copy assignment. basic_environment& operator=(const basic_environment & ); ///Move assignment. basic_environment& operator=(basic_environment && ); typedef typename detail::implementation_type::native_handle_type native_handle; ///Check if environment has entries. bool empty(); ///Get the number of variables. std::size_t size() const; ///Clear the environment. @attention Use with care, passed environment cannot be empty. void clear(); ///Get the entry with the key. Throws if it does not exist. entry_type at( const string_type& key ); ///Get the entry with the key. Throws if it does not exist. const_entry_type at( const string_type& key ) const; ///Get the entry with the given key. It creates the entry if it doesn't exist. entry_type operator[](const string_type & key); /**Proxy class used for read access to members by [] or .at() * @attention Holds a reference to the environment it was created from. */ template<typename Char, typename Environment> struct const_entry_type { typedef Char value_type; typedef const value_type * pointer; typedef std::basic_string<value_type> string_type; typedef boost::iterator_range<pointer> range; typedef Environment environment_t; ///Split the entry by ";" or ":" and return it as a vector. Used by PATH. std::vector<string_type> to_vector() const ///Get the value as string. string_type to_string() const ///Get the name of this entry. string_type get_name() const {return string_type(_name.begin(), _name.end());} ///Copy Constructor const_entry(const const_entry&) = default; ///Move Constructor const_entry& operator=(const const_entry&) = default; ///Check if the entry is empty. bool empty() const; }; /**Proxy class used for read and write access to members by [] or .at() * @attention Holds a reference to the environment it was created from. */ template<typename Char, typename Environment> struct entry_type { typedef Char value_type; typedef const value_type * pointer; typedef std::basic_string<value_type> string_type; typedef boost::iterator_range<pointer> range; typedef Environment environment_t; ///Split the entry by ";" or ":" and return it as a vector. Used by PATH. std::vector<string_type> to_vector() const ///Get the value as string. string_type to_string() const ///Get the name of this entry. string_type get_name() const {return string_type(_name.begin(), _name.end());} ///Copy Constructor entry(const entry&) = default; ///Move Constructor entry& operator=(const entry&) = default; ///Check if the entry is empty. bool empty() const; ///Assign a string to the value void assign(const string_type &value); ///Assign a set of strings to the entry; they will be separated by ';' or ':'. void assign(const std::vector<string_type> &value); ///Append a string to the end of the entry, it will separated by ';' or ':'. void append(const string_type &value); ///Reset the value void clear(); ///Assign a string to the entry. entry &operator=(const string_type & value); ///Assign a set of strings to the entry; they will be separated by ';' or ':'. entry &operator=(const std::vector<string_type> & value); ///Append a string to the end of the entry, it will separated by ';' or ':'. entry &operator+=(const string_type & value); }; }; /**Template representation of the environment of this process. It takes a template * as template parameter to implement the environment. All instances of this class * refer to the same environment, but might not get updated if another one makes changes. */ template<typename Char> class basic_native_environment { public: typedef std::basic_string<Char> string_type; typedef boost::transform_iterator< entry_maker, Char**> iterator ; typedef boost::transform_iterator<const_entry_maker, Char**> const_iterator ; typedef std::size_t size_type ; iterator begin() ; ///<Returns an iterator to the beginning const_iterator begin() const ; ///<Returns an iterator to the beginning const_iterator cbegin() const ; ///<Returns an iterator to the beginning iterator end() ; ///<Returns an iterator to the end const_iterator end() const; ///<Returns an iterator to the end const_iterator cend() const; ///<Returns an iterator to the end iterator find( const string_type& key ); ///<Find a variable by its name const_iterator find( const string_type& key ) const; ///<Find a variable by its name std::size_t count(const string_type & st) const; ///<Number of variables void erase(const string_type & id); ///<Erase variable by id. ///Emplace an environment variable. std::pair<iterator,bool> emplace(const string_type & id, const string_type & value); ///Default constructor basic_native_environment(); ///Move constructor. basic_native_environment(basic_native_environment && ); ///Move assignment. basic_native_environment& operator=(basic_native_environment && ); typedef typename detail::implementation_type::native_handle_type native_handle; ///Check if environment has entries. bool empty(); ///Get the number of variables. std::size_t size() const; ///Get the entry with the key. Throws if it does not exist. entry_type at( const string_type& key ); ///Get the entry with the key. Throws if it does not exist. const_entry_type at( const string_type& key ) const; ///Get the entry with the given key. It creates the entry if it doesn't exist. entry_type operator[](const string_type & key); /**Proxy class used for read access to members by [] or .at() * @attention Holds a reference to the environment it was created from. */ template<typename Char, typename Environment> struct const_entry_type { typedef Char value_type; typedef const value_type * pointer; typedef std::basic_string<value_type> string_type; typedef boost::iterator_range<pointer> range; typedef Environment environment_t; ///Split the entry by ";" or ":" and return it as a vector. Used by PATH. std::vector<string_type> to_vector() const ///Get the value as string. string_type to_string() const ///Get the name of this entry. string_type get_name() const {return string_type(_name.begin(), _name.end());} ///Copy Constructor const_entry(const const_entry&) = default; ///Move Constructor const_entry& operator=(const const_entry&) = default; ///Check if the entry is empty. bool empty() const; }; /**Proxy class used for read and write access to members by [] or .at() * @attention Holds a reference to the environment it was created from. */ template<typename Char, typename Environment> struct entry_type { typedef Char value_type; typedef const value_type * pointer; typedef std::basic_string<value_type> string_type; typedef boost::iterator_range<pointer> range; typedef Environment environment_t; ///Split the entry by ";" or ":" and return it as a vector. Used by PATH. std::vector<string_type> to_vector() const ///Get the value as string. string_type to_string() const ///Get the name of this entry. string_type get_name() const {return string_type(_name.begin(), _name.end());} ///Copy Constructor entry(const entry&) = default; ///Move Constructor entry& operator=(const entry&) = default; ///Check if the entry is empty. bool empty() const; ///Assign a string to the value void assign(const string_type &value); ///Assign a set of strings to the entry; they will be separated by ';' or ':'. void assign(const std::vector<string_type> &value); ///Append a string to the end of the entry, it will separated by ';' or ':'. void append(const string_type &value); ///Reset the value void clear(); ///Assign a string to the entry. entry &operator=(const string_type & value); ///Assign a set of strings to the entry; they will be separated by ';' or ':'. entry &operator=(const std::vector<string_type> & value); ///Append a string to the end of the entry, it will separated by ';' or ':'. entry &operator+=(const string_type & value); }; }; #endif ///Definition of the environment for the current process. template<typename Char> class basic_native_environment : public basic_environment_impl<Char, detail::api::native_environment_impl> { public: using base_type = basic_environment_impl<Char, detail::api::native_environment_impl>; using base_type::base_type; using base_type::operator=; }; ///Type definition to hold a seperate environment. template<typename Char> class basic_environment : public basic_environment_impl<Char, detail::api::basic_environment_impl> { public: using base_type = basic_environment_impl<Char, detail::api::basic_environment_impl>; using base_type::base_type; using base_type::operator=; }; #if !defined(BOOST_NO_ANSI_APIS) ///Definition of the environment for the current process. typedef basic_native_environment<char> native_environment; #endif ///Definition of the environment for the current process. typedef basic_native_environment<wchar_t> wnative_environment; #if !defined(BOOST_NO_ANSI_APIS) ///Type definition to hold a seperate environment. typedef basic_environment<char> environment; #endif ///Type definition to hold a seperate environment. typedef basic_environment<wchar_t> wenvironment; } ///Namespace containing information of the calling process. namespace this_process { ///Definition of the native handle type. typedef ::boost::process::detail::api::native_handle_t native_handle_type; #if !defined(BOOST_NO_ANSI_APIS) ///Definition of the environment for this process. using ::boost::process::native_environment; #endif ///Definition of the environment for this process. using ::boost::process::wnative_environment; ///Get the process id of the current process. inline int get_id() { return ::boost::process::detail::api::get_id();} ///Get the native handle of the current process. inline native_handle_type native_handle() { return ::boost::process::detail::api::native_handle();} #if !defined(BOOST_NO_ANSI_APIS) ///Get the enviroment of the current process. inline native_environment environment() { return ::boost::process:: native_environment(); } #endif ///Get the enviroment of the current process. inline wnative_environment wenvironment() { return ::boost::process::wnative_environment(); } ///Get the path environment variable of the current process runs. inline std::vector<boost::filesystem::path> path() { #if defined(BOOST_WINDOWS_API) const ::boost::process::wnative_environment ne{}; typedef typename ::boost::process::wnative_environment::const_entry_type value_type; static constexpr auto id = L"PATH"; #else const ::boost::process::native_environment ne{}; typedef typename ::boost::process::native_environment::const_entry_type value_type; static constexpr auto id = "PATH"; #endif auto itr = std::find_if(ne.cbegin(), ne.cend(), [&](const value_type & e) {return id == ::boost::to_upper_copy(e.get_name(), ::boost::process::detail::process_locale());}); if (itr == ne.cend()) return {}; auto vec = itr->to_vector(); std::vector<boost::filesystem::path> val; val.resize(vec.size()); std::copy(vec.begin(), vec.end(), val.begin()); return val; } } } #endif /* INCLUDE_BOOST_PROCESS_DETAIL_ENVIRONMENT_HPP_ */ PK oM�[�"R � � async_system.hppnu �[��� // Copyright (c) 2006, 2007 Julio M. Merino Vidal // Copyright (c) 2008 Ilya Sokolov, Boris Schaeling // Copyright (c) 2009 Boris Schaeling // Copyright (c) 2010 Felipe Tanus, Boris Schaeling // Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling // Copyright (c) 2016 Klemens D. Morgenstern // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) /** * \file boost/process/async_system.hpp * * Defines the asynchrounous version of the system function. */ #ifndef BOOST_PROCESS_ASYNC_SYSTEM_HPP #define BOOST_PROCESS_ASYNC_SYSTEM_HPP #include <boost/process/detail/config.hpp> #include <boost/process/async.hpp> #include <boost/process/child.hpp> #include <boost/process/detail/async_handler.hpp> #include <boost/process/detail/execute_impl.hpp> #include <type_traits> #include <memory> #include <boost/asio/async_result.hpp> #include <boost/asio/post.hpp> #include <boost/system/error_code.hpp> #include <tuple> #if defined(BOOST_POSIX_API) #include <boost/process/posix.hpp> #endif namespace boost { namespace process { namespace detail { template<typename ExitHandler> struct async_system_handler : ::boost::process::detail::api::async_handler { boost::asio::io_context & ios; boost::asio::async_completion< ExitHandler, void(boost::system::error_code, int)> init; #if defined(BOOST_POSIX_API) bool errored = false; #endif template<typename ExitHandler_> async_system_handler( boost::asio::io_context & ios, ExitHandler_ && exit_handler) : ios(ios), init(exit_handler) { } template<typename Exec> void on_error(Exec&, const std::error_code & ec) { #if defined(BOOST_POSIX_API) errored = true; #endif auto & h = init.completion_handler; boost::asio::post( ios.get_executor(), [h, ec]() mutable { h(boost::system::error_code(ec.value(), boost::system::system_category()), -1); }); } BOOST_ASIO_INITFN_RESULT_TYPE(ExitHandler, void (boost::system::error_code, int)) get_result() { return init.result.get(); } template<typename Executor> std::function<void(int, const std::error_code&)> on_exit_handler(Executor&) { #if defined(BOOST_POSIX_API) if (errored) return [](int , const std::error_code &){}; #endif auto & h = init.completion_handler; return [h](int exit_code, const std::error_code & ec) mutable { h(boost::system::error_code(ec.value(), boost::system::system_category()), exit_code); }; } }; template<typename ExitHandler> struct is_error_handler<async_system_handler<ExitHandler>> : std::true_type {}; } /** This function provides an asynchronous interface to process launching. It uses the same properties and parameters as the other launching function, but is similar to the asynchronous functions in [boost.asio](http://www.boost.org/doc/libs/release/doc/html/boost_asio.html) It uses [asio::async_result](http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/async_result.html) to determine the return value (from the second parameter, `exit_handler`). \param ios A reference to an [io_context](http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference.html) \param exit_handler The exit-handler for the signature `void(boost::system::error_code, int)` \note This function does not allow custom error handling, since those are done through the `exit_handler`. */ #if defined(BOOST_PROCESS_DOXYGEN) template<typename ExitHandler, typename ...Args> inline boost::process::detail::dummy async_system(boost::asio::io_context & ios, ExitHandler && exit_handler, Args && ...args); #endif template<typename ExitHandler, typename ...Args> inline BOOST_ASIO_INITFN_RESULT_TYPE(ExitHandler, void (boost::system::error_code, int)) async_system(boost::asio::io_context & ios, ExitHandler && exit_handler, Args && ...args) { detail::async_system_handler<ExitHandler> async_h{ios, std::forward<ExitHandler>(exit_handler)}; typedef typename ::boost::process::detail::has_error_handler<boost::fusion::tuple<Args...>>::type has_err_handling; static_assert(!has_err_handling::value, "async_system cannot have custom error handling"); child(ios, std::forward<Args>(args)..., async_h ).detach(); return async_h.get_result(); } }} #endif PK oM�[cm��# # args.hppnu �[��� // Copyright (c) 2006, 2007 Julio M. Merino Vidal // Copyright (c) 2008 Ilya Sokolov, Boris Schaeling // Copyright (c) 2009 Boris Schaeling // Copyright (c) 2010 Felipe Tanus, Boris Schaeling // Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling // Copyright (c) 2016 Klemens D. Morgenstern // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_PROCESS_ARGS_HPP #define BOOST_PROCESS_ARGS_HPP /** \file boost/process/args.hpp * * This header provides the \xmlonly <globalname alt="boost::process::args">args</globalname>\endxmlonly property. It also provides the * alternative name \xmlonly <globalname alt="boost::process::argv">argv</globalname>\endxmlonly . * * \xmlonly <programlisting> namespace boost { namespace process { <emphasis>unspecified</emphasis> <globalname alt="boost::process::args">args</globalname>; <emphasis>unspecified</emphasis> <globalname alt="boost::process::argv">argv</globalname>; } } </programlisting> \endxmlonly */ #include <boost/process/detail/basic_cmd.hpp> #include <iterator> namespace boost { namespace process { namespace detail { struct args_ { template<typename T> using remove_reference_t = typename std::remove_reference<T>::type; template<typename T> using value_type = typename remove_reference_t<T>::value_type; template<typename T> using vvalue_type = value_type<value_type<T>>; template <class Range> arg_setter_<vvalue_type<Range>, true> operator()(Range &&range) const { return arg_setter_<vvalue_type<Range>, true>(std::forward<Range>(range)); } template <class Range> arg_setter_<vvalue_type<Range>, true> operator+=(Range &&range) const { return arg_setter_<vvalue_type<Range>, true>(std::forward<Range>(range)); } template <class Range> arg_setter_<vvalue_type<Range>, false> operator= (Range &&range) const { return arg_setter_<vvalue_type<Range>, false>(std::forward<Range>(range)); } template<typename Char> arg_setter_<Char, true> operator()(std::basic_string<Char> && str) const { return arg_setter_<Char, true> (str); } template<typename Char> arg_setter_<Char, true> operator+=(std::basic_string<Char> && str) const { return arg_setter_<Char, true> (str); } template<typename Char> arg_setter_<Char, false> operator= (std::basic_string<Char> && str) const { return arg_setter_<Char, false>(str); } template<typename Char> arg_setter_<Char, true> operator()(const std::basic_string<Char> & str) const { return arg_setter_<Char, true> (str); } template<typename Char> arg_setter_<Char, true> operator+=(const std::basic_string<Char> & str) const { return arg_setter_<Char, true> (str); } template<typename Char> arg_setter_<Char, false> operator= (const std::basic_string<Char> & str) const { return arg_setter_<Char, false>(str); } template<typename Char> arg_setter_<Char, true> operator()(std::basic_string<Char> & str) const { return arg_setter_<Char, true> (str); } template<typename Char> arg_setter_<Char, true> operator+=(std::basic_string<Char> & str) const { return arg_setter_<Char, true> (str); } template<typename Char> arg_setter_<Char, false> operator= (std::basic_string<Char> & str) const { return arg_setter_<Char, false>(str); } template<typename Char> arg_setter_<Char, true> operator()(const Char* str) const { return arg_setter_<Char, true> (str); } template<typename Char> arg_setter_<Char, true> operator+=(const Char* str) const { return arg_setter_<Char, true> (str); } template<typename Char> arg_setter_<Char, false> operator= (const Char* str) const { return arg_setter_<Char, false>(str); } // template<typename Char, std::size_t Size> // arg_setter_<Char, true> operator()(const Char (&str) [Size]) const // { // return arg_setter_<Char, true> (str); // } // template<typename Char, std::size_t Size> // arg_setter_<Char, true> operator+=(const Char (&str) [Size]) const // { // return arg_setter_<Char, true> (str); // } // template<typename Char, std::size_t Size> // arg_setter_<Char, false> operator= (const Char (&str) [Size]) const // { // return arg_setter_<Char, false>(str); // } arg_setter_<char, true> operator()(std::initializer_list<const char*> &&range) const { return arg_setter_<char, true>(range.begin(), range.end()); } arg_setter_<char, true> operator+=(std::initializer_list<const char*> &&range) const { return arg_setter_<char, true>(range.begin(), range.end()); } arg_setter_<char, false> operator= (std::initializer_list<const char*> &&range) const { return arg_setter_<char, false>(range.begin(), range.end()); } arg_setter_<char, true> operator()(std::initializer_list<std::string> &&range) const { return arg_setter_<char, true>(range.begin(), range.end()); } arg_setter_<char, true> operator+=(std::initializer_list<std::string> &&range) const { return arg_setter_<char, true>(range.begin(), range.end()); } arg_setter_<char, false> operator= (std::initializer_list<std::string> &&range) const { return arg_setter_<char, false>(range.begin(), range.end()); } arg_setter_<wchar_t, true> operator()(std::initializer_list<const wchar_t*> &&range) const { return arg_setter_<wchar_t, true>(range.begin(), range.end()); } arg_setter_<wchar_t, true> operator+=(std::initializer_list<const wchar_t*> &&range) const { return arg_setter_<wchar_t, true>(range.begin(), range.end()); } arg_setter_<wchar_t, false> operator= (std::initializer_list<const wchar_t*> &&range) const { return arg_setter_<wchar_t, false>(range.begin(), range.end()); } arg_setter_<wchar_t, true> operator()(std::initializer_list<std::wstring> &&range) const { return arg_setter_<wchar_t, true>(range.begin(), range.end()); } arg_setter_<wchar_t, true> operator+=(std::initializer_list<std::wstring> &&range) const { return arg_setter_<wchar_t, true>(range.begin(), range.end()); } arg_setter_<wchar_t, false> operator= (std::initializer_list<std::wstring> &&range) const { return arg_setter_<wchar_t, false>(range.begin(), range.end()); } }; } /** The `args` property allows to explicitly set arguments for the execution. The name of the executable will always be the first element in the arg-vector. \section args_details Details \subsection args_operations Operations \subsubsection args_set_var Setting values To set a the argument vector the following syntax can be used. \code{.cpp} args = value; args(value); \endcode `std::initializer_list` is among the allowed types, so the following syntax is also possible. \code{.cpp} args = {value1, value2}; args({value1, value2}); \endcode Below the possible types for `value` are listed, with `char_type` being either `char` or `wchar_t`. \paragraph args_set_var_value value - `std::basic_string<char_type>` - `const char_type * ` - `std::initializer_list<const char_type *>` - `std::vector<std::basic_string<char_type>>` Additionally any range of `std::basic_string<char_type>` can be passed. \subsubsection args_append_var Appending values To append a the argument vector the following syntax can be used. \code{.cpp} args += value; \endcode `std::initializer_list` is among the allowed types, so the following syntax is also possible. \code{.cpp} args += {value1, value2}; \endcode Below the possible types for `value` are listed, with `char_type` being either `char` or `wchar_t`. \paragraph args_append_var_value value - `std::basic_string<char_type>` - `const char_type * ` - `std::initializer_list<const char_type *>` - `std::vector<std::basic_string<char_type>>` Additionally any range of `std::basic_string<char_type>` can be passed. \subsection args_example Example The overload form is used when more than one string is passed, from the second one forward. I.e. the following expressions have the same results: \code{.cpp} spawn("gcc", "--version"); spawn("gcc", args ="--version"); spawn("gcc", args+="--version"); spawn("gcc", args ={"--version"}); spawn("gcc", args+={"--version"}); \endcode \note A string will be parsed and set in quotes if it has none and contains spaces. */ constexpr boost::process::detail::args_ args{}; ///Alias for \xmlonly <globalname alt="boost::process::args">args</globalname> \endxmlonly . constexpr boost::process::detail::args_ argv{}; }} #endif PK oM�[kXΪKI KI pipe.hppnu �[��� // Copyright (c) 2006, 2007 Julio M. Merino Vidal // Copyright (c) 2008 Ilya Sokolov, Boris Schaeling // Copyright (c) 2009 Boris Schaeling // Copyright (c) 2010 Felipe Tanus, Boris Schaeling // Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_PROCESS_PIPE_HPP #define BOOST_PROCESS_PIPE_HPP #include <boost/config.hpp> #include <boost/process/detail/config.hpp> #include <streambuf> #include <istream> #include <ostream> #include <vector> #if defined(BOOST_POSIX_API) #include <boost/process/detail/posix/basic_pipe.hpp> #elif defined(BOOST_WINDOWS_API) #include <boost/process/detail/windows/basic_pipe.hpp> #endif namespace boost { namespace process { using ::boost::process::detail::api::basic_pipe; #if defined(BOOST_PROCESS_DOXYGEN) /** Class implementation of a pipe. * */ template<class CharT, class Traits = std::char_traits<CharT>> class basic_pipe { public: typedef CharT char_type ; typedef Traits traits_type; typedef typename Traits::int_type int_type ; typedef typename Traits::pos_type pos_type ; typedef typename Traits::off_type off_type ; typedef ::boost::detail::winapi::HANDLE_ native_handle; /// Default construct the pipe. Will be opened. basic_pipe(); ///Construct a named pipe. inline explicit basic_pipe(const std::string & name); /** Copy construct the pipe. * \note Duplicated the handles. */ inline basic_pipe(const basic_pipe& p); /** Move construct the pipe. */ basic_pipe(basic_pipe&& lhs); /** Copy assign the pipe. * \note Duplicated the handles. */ inline basic_pipe& operator=(const basic_pipe& p); /** Move assign the pipe. */ basic_pipe& operator=(basic_pipe&& lhs); /** Destructor closes the handles. */ ~basic_pipe(); /** Get the native handle of the source. */ native_handle native_source() const; /** Get the native handle of the sink. */ native_handle native_sink () const; /** Assign a new value to the source */ void assign_source(native_handle h); /** Assign a new value to the sink */ void assign_sink (native_handle h); ///Write data to the pipe. int_type write(const char_type * data, int_type count); ///Read data from the pipe. int_type read(char_type * data, int_type count); ///Check if the pipe is open. bool is_open(); ///Close the pipe void close(); }; #endif typedef basic_pipe<char> pipe; typedef basic_pipe<wchar_t> wpipe; /** Implementation of the stream buffer for a pipe. */ template< class CharT, class Traits = std::char_traits<CharT> > struct basic_pipebuf : std::basic_streambuf<CharT, Traits> { typedef basic_pipe<CharT, Traits> pipe_type; typedef CharT char_type ; typedef Traits traits_type; typedef typename Traits::int_type int_type ; typedef typename Traits::pos_type pos_type ; typedef typename Traits::off_type off_type ; constexpr static int default_buffer_size = BOOST_PROCESS_PIPE_SIZE; ///Default constructor, will also construct the pipe. basic_pipebuf() : _write(default_buffer_size), _read(default_buffer_size) { this->setg(_read.data(), _read.data()+ 128, _read.data() + 128); this->setp(_write.data(), _write.data() + _write.size()); } ///Copy Constructor. basic_pipebuf(const basic_pipebuf & ) = default; ///Move Constructor basic_pipebuf(basic_pipebuf && ) = default; ///Destructor -> writes the frest of the data ~basic_pipebuf() { if (basic_pipebuf::is_open()) basic_pipebuf::overflow(Traits::eof()); } ///Move construct from a pipe. basic_pipebuf(pipe_type && p) : _pipe(std::move(p)), _write(default_buffer_size), _read(default_buffer_size) { this->setg(_read.data(), _read.data()+ 128, _read.data() + 128); this->setp(_write.data(), _write.data() + _write.size()); } ///Construct from a pipe. basic_pipebuf(const pipe_type & p) : _pipe(p), _write(default_buffer_size), _read(default_buffer_size) { this->setg(_read.data(), _read.data()+ 128, _read.data() + 128); this->setp(_write.data(), _write.data() + _write.size()); } ///Copy assign. basic_pipebuf& operator=(const basic_pipebuf & ) = delete; ///Move assign. basic_pipebuf& operator=(basic_pipebuf && ) = default; ///Move assign a pipe. basic_pipebuf& operator=(pipe_type && p) { _pipe = std::move(p); return *this; } ///Copy assign a pipe. basic_pipebuf& operator=(const pipe_type & p) { _pipe = p; return *this; } ///Writes characters to the associated output sequence from the put area int_type overflow(int_type ch = traits_type::eof()) override { if (_pipe.is_open() && (ch != traits_type::eof())) { if (this->pptr() == this->epptr()) { bool wr = this->_write_impl(); if (wr) { *this->pptr() = ch; this->pbump(1); return ch; } } else { *this->pptr() = ch; this->pbump(1); if (this->_write_impl()) return ch; } } else if (ch == traits_type::eof()) this->sync(); return traits_type::eof(); } ///Synchronizes the buffers with the associated character sequence int sync() override { return this->_write_impl() ? 0 : -1; } ///Reads characters from the associated input sequence to the get area int_type underflow() override { if (!_pipe.is_open()) return traits_type::eof(); if (this->egptr() == &_read.back()) //ok, so we're at the end of the buffer this->setg(_read.data(), _read.data()+ 10, _read.data() + 10); auto len = &_read.back() - this->egptr() ; auto res = _pipe.read( this->egptr(), static_cast<typename pipe_type::int_type>(len)); if (res == 0) return traits_type::eof(); this->setg(this->eback(), this->gptr(), this->egptr() + res); auto val = *this->gptr(); return traits_type::to_int_type(val); } ///Set the pipe of the streambuf. void pipe(pipe_type&& p) {_pipe = std::move(p); } ///Set the pipe of the streambuf. void pipe(const pipe_type& p) {_pipe = p; } ///Get a reference to the pipe. pipe_type & pipe() & {return _pipe;} ///Get a const reference to the pipe. const pipe_type &pipe() const & {return _pipe;} ///Get a rvalue reference to the pipe. Qualified as rvalue. pipe_type && pipe() && {return std::move(_pipe);} ///Check if the pipe is open bool is_open() const {return _pipe.is_open(); } ///Open a new pipe basic_pipebuf<CharT, Traits>* open() { if (is_open()) return nullptr; _pipe = pipe(); return this; } ///Open a new named pipe basic_pipebuf<CharT, Traits>* open(const std::string & name) { if (is_open()) return nullptr; _pipe = pipe(name); return this; } ///Flush the buffer & close the pipe basic_pipebuf<CharT, Traits>* close() { if (!is_open()) return nullptr; overflow(Traits::eof()); return this; } private: pipe_type _pipe; std::vector<char_type> _write; std::vector<char_type> _read; bool _write_impl() { if (!_pipe.is_open()) return false; auto base = this->pbase(); if (base == this->pptr()) return true; std::ptrdiff_t wrt = _pipe.write(base, static_cast<typename pipe_type::int_type>(this->pptr() - base)); std::ptrdiff_t diff = this->pptr() - base; if (wrt < diff) std::move(base + wrt, base + diff, base); else if (wrt == 0) //broken pipe return false; this->pbump(-wrt); return true; } }; typedef basic_pipebuf<char> pipebuf; typedef basic_pipebuf<wchar_t> wpipebuf; /** Implementation of a reading pipe stream. * */ template< class CharT, class Traits = std::char_traits<CharT> > class basic_ipstream : public std::basic_istream<CharT, Traits> { mutable basic_pipebuf<CharT, Traits> _buf; public: typedef basic_pipe<CharT, Traits> pipe_type; typedef CharT char_type ; typedef Traits traits_type; typedef typename Traits::int_type int_type ; typedef typename Traits::pos_type pos_type ; typedef typename Traits::off_type off_type ; ///Get access to the underlying stream_buf basic_pipebuf<CharT, Traits>* rdbuf() const {return &_buf;}; ///Default constructor. basic_ipstream() : std::basic_istream<CharT, Traits>(nullptr) { std::basic_istream<CharT, Traits>::rdbuf(&_buf); }; ///Copy constructor. basic_ipstream(const basic_ipstream & ) = delete; ///Move constructor. basic_ipstream(basic_ipstream && lhs) : std::basic_istream<CharT, Traits>(nullptr), _buf(std::move(lhs._buf)) { std::basic_istream<CharT, Traits>::rdbuf(&_buf); } ///Move construct from a pipe. basic_ipstream(pipe_type && p) : std::basic_istream<CharT, Traits>(nullptr), _buf(std::move(p)) { std::basic_istream<CharT, Traits>::rdbuf(&_buf); } ///Copy construct from a pipe. basic_ipstream(const pipe_type & p) : std::basic_istream<CharT, Traits>(nullptr), _buf(p) { std::basic_istream<CharT, Traits>::rdbuf(&_buf); } ///Copy assignment. basic_ipstream& operator=(const basic_ipstream & ) = delete; ///Move assignment basic_ipstream& operator=(basic_ipstream && lhs) { std::basic_istream<CharT, Traits>::operator=(std::move(lhs)); _buf = std::move(lhs._buf); std::basic_istream<CharT, Traits>::rdbuf(&_buf); return *this; }; ///Move assignment of a pipe. basic_ipstream& operator=(pipe_type && p) { _buf = std::move(p); return *this; } ///Copy assignment of a pipe. basic_ipstream& operator=(const pipe_type & p) { _buf = p; return *this; } ///Set the pipe of the streambuf. void pipe(pipe_type&& p) {_buf.pipe(std::move(p)); } ///Set the pipe of the streambuf. void pipe(const pipe_type& p) {_buf.pipe(p); } ///Get a reference to the pipe. pipe_type & pipe() & {return _buf.pipe();} ///Get a const reference to the pipe. const pipe_type &pipe() const & {return _buf.pipe();} ///Get a rvalue reference to the pipe. Qualified as rvalue. pipe_type && pipe() && {return std::move(_buf).pipe();} ///Check if the pipe is open bool is_open() const {return _buf.is_open();} ///Open a new pipe void open() { if (_buf.open() == nullptr) this->setstate(std::ios_base::failbit); else this->clear(); } ///Open a new named pipe void open(const std::string & name) { if (_buf.open() == nullptr) this->setstate(std::ios_base::failbit); else this->clear(); } ///Flush the buffer & close the pipe void close() { if (_buf.close() == nullptr) this->setstate(std::ios_base::failbit); } }; typedef basic_ipstream<char> ipstream; typedef basic_ipstream<wchar_t> wipstream; /** Implementation of a write pipe stream. * */ template< class CharT, class Traits = std::char_traits<CharT> > class basic_opstream : public std::basic_ostream<CharT, Traits> { mutable basic_pipebuf<CharT, Traits> _buf; public: typedef basic_pipe<CharT, Traits> pipe_type; typedef CharT char_type ; typedef Traits traits_type; typedef typename Traits::int_type int_type ; typedef typename Traits::pos_type pos_type ; typedef typename Traits::off_type off_type ; ///Get access to the underlying stream_buf basic_pipebuf<CharT, Traits>* rdbuf() const {return &_buf;}; ///Default constructor. basic_opstream() : std::basic_ostream<CharT, Traits>(nullptr) { std::basic_ostream<CharT, Traits>::rdbuf(&_buf); }; ///Copy constructor. basic_opstream(const basic_opstream & ) = delete; ///Move constructor. basic_opstream(basic_opstream && lhs) : std::basic_ostream<CharT, Traits>(nullptr), _buf(std::move(lhs._buf)) { std::basic_ostream<CharT, Traits>::rdbuf(&_buf); } ///Move construct from a pipe. basic_opstream(pipe_type && p) : std::basic_ostream<CharT, Traits>(nullptr), _buf(std::move(p)) { std::basic_ostream<CharT, Traits>::rdbuf(&_buf); }; ///Copy construct from a pipe. basic_opstream(const pipe_type & p) : std::basic_ostream<CharT, Traits>(nullptr), _buf(p) { std::basic_ostream<CharT, Traits>::rdbuf(&_buf); }; ///Copy assignment. basic_opstream& operator=(const basic_opstream & ) = delete; ///Move assignment basic_opstream& operator=(basic_opstream && lhs) { std::basic_ostream<CharT, Traits>::operator=(std::move(lhs)); _buf = std::move(lhs._buf); std::basic_ostream<CharT, Traits>::rdbuf(&_buf); return *this; }; ///Move assignment of a pipe. basic_opstream& operator=(pipe_type && p) { _buf = std::move(p); return *this; } ///Copy assignment of a pipe. basic_opstream& operator=(const pipe_type & p) { _buf = p; return *this; } ///Set the pipe of the streambuf. void pipe(pipe_type&& p) {_buf.pipe(std::move(p)); } ///Set the pipe of the streambuf. void pipe(const pipe_type& p) {_buf.pipe(p); } ///Get a reference to the pipe. pipe_type & pipe() & {return _buf.pipe();} ///Get a const reference to the pipe. const pipe_type &pipe() const & {return _buf.pipe();} ///Get a rvalue reference to the pipe. Qualified as rvalue. pipe_type && pipe() && {return std::move(_buf).pipe();} ///Open a new pipe void open() { if (_buf.open() == nullptr) this->setstate(std::ios_base::failbit); else this->clear(); } ///Open a new named pipe void open(const std::string & name) { if (_buf.open() == nullptr) this->setstate(std::ios_base::failbit); else this->clear(); } ///Flush the buffer & close the pipe void close() { if (_buf.close() == nullptr) this->setstate(std::ios_base::failbit); } }; typedef basic_opstream<char> opstream; typedef basic_opstream<wchar_t> wopstream; /** Implementation of a read-write pipe stream. * */ template< class CharT, class Traits = std::char_traits<CharT> > class basic_pstream : public std::basic_iostream<CharT, Traits> { mutable basic_pipebuf<CharT, Traits> _buf; public: typedef basic_pipe<CharT, Traits> pipe_type; typedef CharT char_type ; typedef Traits traits_type; typedef typename Traits::int_type int_type ; typedef typename Traits::pos_type pos_type ; typedef typename Traits::off_type off_type ; ///Get access to the underlying stream_buf basic_pipebuf<CharT, Traits>* rdbuf() const {return &_buf;}; ///Default constructor. basic_pstream() : std::basic_iostream<CharT, Traits>(nullptr) { std::basic_iostream<CharT, Traits>::rdbuf(&_buf); }; ///Copy constructor. basic_pstream(const basic_pstream & ) = delete; ///Move constructor. basic_pstream(basic_pstream && lhs) : std::basic_iostream<CharT, Traits>(nullptr), _buf(std::move(lhs._buf)) { std::basic_iostream<CharT, Traits>::rdbuf(&_buf); } ///Move construct from a pipe. basic_pstream(pipe_type && p) : std::basic_iostream<CharT, Traits>(nullptr), _buf(std::move(p)) { std::basic_iostream<CharT, Traits>::rdbuf(&_buf); }; ///Copy construct from a pipe. basic_pstream(const pipe_type & p) : std::basic_iostream<CharT, Traits>(nullptr), _buf(p) { std::basic_iostream<CharT, Traits>::rdbuf(&_buf); }; ///Copy assignment. basic_pstream& operator=(const basic_pstream & ) = delete; ///Move assignment basic_pstream& operator=(basic_pstream && lhs) { std::basic_istream<CharT, Traits>::operator=(std::move(lhs)); _buf = std::move(lhs._buf); std::basic_iostream<CharT, Traits>::rdbuf(&_buf); return *this; }; ///Move assignment of a pipe. basic_pstream& operator=(pipe_type && p) { _buf = std::move(p); return *this; } ///Copy assignment of a pipe. basic_pstream& operator=(const pipe_type & p) { _buf = p; return *this; } ///Set the pipe of the streambuf. void pipe(pipe_type&& p) {_buf.pipe(std::move(p)); } ///Set the pipe of the streambuf. void pipe(const pipe_type& p) {_buf.pipe(p); } ///Get a reference to the pipe. pipe_type & pipe() & {return _buf.pipe();} ///Get a const reference to the pipe. const pipe_type &pipe() const & {return _buf.pipe();} ///Get a rvalue reference to the pipe. Qualified as rvalue. pipe_type && pipe() && {return std::move(_buf).pipe();} ///Open a new pipe void open() { if (_buf.open() == nullptr) this->setstate(std::ios_base::failbit); else this->clear(); } ///Open a new named pipe void open(const std::string & name) { if (_buf.open() == nullptr) this->setstate(std::ios_base::failbit); else this->clear(); } ///Flush the buffer & close the pipe void close() { if (_buf.close() == nullptr) this->setstate(std::ios_base::failbit); } }; typedef basic_pstream<char> pstream; typedef basic_pstream<wchar_t> wpstream; }} #endif PK oM�[���g cmd.hppnu �[��� // Copyright (c) 2006, 2007 Julio M. Merino Vidal // Copyright (c) 2008 Ilya Sokolov, Boris Schaeling // Copyright (c) 2009 Boris Schaeling // Copyright (c) 2010 Felipe Tanus, Boris Schaeling // Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling // Copyright (c) 2016 Klemens D. Morgenstern // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_PROCESS_DETAIL_CMD_LINE_HPP #define BOOST_PROCESS_DETAIL_CMD_LINE_HPP #include <boost/winapi/config.hpp> #include <boost/process/detail/config.hpp> #include <boost/process/detail/handler_base.hpp> #include <boost/process/detail/traits/cmd_or_exe.hpp> #include <boost/process/detail/traits/wchar_t.hpp> #if defined(BOOST_POSIX_API) #include <boost/process/detail/posix/cmd.hpp> #elif defined(BOOST_WINDOWS_API) #include <boost/process/detail/windows/cmd.hpp> #endif /** \file boost/process/cmd.hpp * * This header provides the \xmlonly <globalname alt="boost::process::cmd">cmd</globalname>\endxmlonly property. * \xmlonly <programlisting> namespace boost { namespace process { <emphasis>unspecified</emphasis> <globalname alt="boost::process::cmd">cmd</globalname>; } } </programlisting> \endxmlonly */ namespace boost { namespace process { namespace detail { struct cmd_ { constexpr cmd_() = default; template<typename Char> inline api::cmd_setter_<Char> operator()(const Char *s) const { return api::cmd_setter_<Char>(s); } template<typename Char> inline api::cmd_setter_<Char> operator= (const Char *s) const { return api::cmd_setter_<Char>(s); } template<typename Char> inline api::cmd_setter_<Char> operator()(const std::basic_string<Char> &s) const { return api::cmd_setter_<Char>(s); } template<typename Char> inline api::cmd_setter_<Char> operator= (const std::basic_string<Char> &s) const { return api::cmd_setter_<Char>(s); } }; template<> struct is_wchar_t<api::cmd_setter_<wchar_t>> : std::true_type {}; template<> struct char_converter<char, api::cmd_setter_<wchar_t>> { static api::cmd_setter_<char> conv(const api::cmd_setter_<wchar_t> & in) { return { ::boost::process::detail::convert(in.str()) }; } }; template<> struct char_converter<wchar_t, api::cmd_setter_<char>> { static api::cmd_setter_<wchar_t> conv(const api::cmd_setter_<char> & in) { return { ::boost::process::detail::convert(in.str()) }; } }; } /** The cmd property allows to explicitly set commands for the execution. The overload form applies when only one string is passed to a launching function. The string will be internally parsed and split at spaces. The following expressions are valid, with `value` being either a C-String or a `std::basic_string` with `char` or `wchar_t`. \code{.cpp} cmd="value"; cmd(value); \endcode The property can only be used for assignments. */ constexpr static ::boost::process::detail::cmd_ cmd; }} #endif PK oM�[�쟐 error.hppnu �[��� // Copyright (c) 2006, 2007 Julio M. Merino Vidal // Copyright (c) 2008 Ilya Sokolov, Boris Schaeling // Copyright (c) 2009 Boris Schaeling // Copyright (c) 2010 Felipe Tanus, Boris Schaeling // Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling // Copyright (c) 2016 Klemens D. Morgenstern // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_PROCESS_DETAIL_ERROR_HPP #define BOOST_PROCESS_DETAIL_ERROR_HPP #include <boost/process/detail/config.hpp> #include <boost/process/detail/traits.hpp> #if defined(BOOST_POSIX_API) #include <boost/process/detail/posix/handler.hpp> #elif defined(BOOST_WINDOWS_API) #include <boost/process/detail/windows/handler.hpp> #endif #include <system_error> #include <type_traits> #include <boost/fusion/algorithm/query/find_if.hpp> #include <boost/fusion/sequence/intrinsic/begin.hpp> #include <boost/fusion/sequence/intrinsic/end.hpp> #include <boost/fusion/container/vector/convert.hpp> #include <boost/fusion/iterator/deref.hpp> #include <boost/fusion/sequence/comparison/equal_to.hpp> #include <boost/fusion/container/set/convert.hpp> #include <boost/type_index.hpp> /** \file boost/process/error.hpp * * Header which provides the error properties. It allows to explicitly set the error handling, the properties are: * \xmlonly <programlisting> namespace boost { namespace process { <emphasis>unspecified</emphasis> <globalname alt="boost::process::ignore_error">ignore_error</globalname>; <emphasis>unspecified</emphasis> <globalname alt="boost::process::throw_on_error">throw_on_error</globalname>; <emphasis>unspecified</emphasis> <globalname alt="boost::process::error">error</globalname>; <emphasis>unspecified</emphasis> <globalname alt="boost::process::error_ref">error_ref</globalname>; <emphasis>unspecified</emphasis> <globalname alt="boost::process::error_code">error_code</globalname>; } } </programlisting> \endxmlonly * For error there are two aliases: error_ref and error_code */ namespace boost { namespace process { namespace detail { struct throw_on_error_ : ::boost::process::detail::api::handler_base_ext { constexpr throw_on_error_() = default; template <class Executor> void on_error(Executor&, const std::error_code & ec) const { throw process_error(ec, "process creation failed"); } const throw_on_error_ &operator()() const {return *this;} }; struct ignore_error_ : ::boost::process::detail::api::handler_base_ext { constexpr ignore_error_() = default; }; struct set_on_error : ::boost::process::detail::api::handler_base_ext { set_on_error(const set_on_error&) = default; explicit set_on_error(std::error_code &ec) : ec_(ec) {} template <class Executor> void on_error(Executor&, const std::error_code & ec) const noexcept { ec_ = ec; } private: std::error_code &ec_; }; struct error_ { constexpr error_() = default; set_on_error operator()(std::error_code &ec) const {return set_on_error(ec);} set_on_error operator= (std::error_code &ec) const {return set_on_error(ec);} }; template<typename T> struct is_error_handler : std::false_type {}; template<> struct is_error_handler<set_on_error> : std::true_type {}; template<> struct is_error_handler<throw_on_error_> : std::true_type {}; template<> struct is_error_handler<ignore_error_> : std::true_type {}; template<typename Iterator, typename End> struct has_error_handler_impl { typedef typename boost::fusion::result_of::deref<Iterator>::type ref_type; typedef typename std::remove_reference<ref_type>::type res_type_; typedef typename std::remove_cv<res_type_>::type res_type; typedef typename is_error_handler<res_type>::type cond; typedef typename boost::fusion::result_of::next<Iterator>::type next_itr; typedef typename has_error_handler_impl<next_itr, End>::type next; typedef typename boost::mpl::or_<cond, next>::type type; }; template<typename Iterator> struct has_error_handler_impl<Iterator, Iterator> { typedef boost::mpl::false_ type; }; template<typename Sequence> struct has_error_handler { typedef typename boost::fusion::result_of::as_vector<Sequence>::type vector_type; typedef typename has_error_handler_impl< typename boost::fusion::result_of::begin<vector_type>::type, typename boost::fusion::result_of::end< vector_type>::type >::type type; }; template<typename Sequence> struct has_ignore_error { typedef typename boost::fusion::result_of::as_set<Sequence>::type set_type; typedef typename boost::fusion::result_of::has_key<set_type, ignore_error_>::type type1; typedef typename boost::fusion::result_of::has_key<set_type, ignore_error_&>::type type2; typedef typename boost::fusion::result_of::has_key<set_type, const ignore_error_&>::type type3; typedef typename boost::mpl::or_<type1,type2, type3>::type type; }; struct error_builder { std::error_code *err; typedef set_on_error result_type; set_on_error get_initializer() {return set_on_error(*err);}; void operator()(std::error_code & ec) {err = &ec;}; }; template<> struct initializer_tag<std::error_code> { typedef error_tag type; }; template<> struct initializer_builder<error_tag> { typedef error_builder type; }; } /**The ignore_error property will disable any error handling. This can be useful on linux, where error handling will require a pipe.*/ constexpr boost::process::detail::ignore_error_ ignore_error; /**The throw_on_error property will enable the exception when launching a process. It is unnecessary by default, but may be used, when an additional error_code is provided.*/ constexpr boost::process::detail::throw_on_error_ throw_on_error; /** The error property will set the executor to handle any errors by setting an [std::error_code](http://en.cppreference.com/w/cpp/error/error_code). \code{.cpp} std::error_code ec; system("gcc", error(ec)); \endcode The following syntax is valid: \code{.cpp} error(ec); error=ec; \endcode The overload version is achieved by just passing an object of [std::error_code](http://en.cppreference.com/w/cpp/error/error_code) to the function. */ constexpr boost::process::detail::error_ error; ///Alias for \xmlonly <globalname alt="boost::process::error">error</globalname> \endxmlonly . constexpr boost::process::detail::error_ error_ref; ///Alias for \xmlonly <globalname alt="boost::process::error">error</globalname> \endxmlonly . constexpr boost::process::detail::error_ error_code; }} #endif PK oM�[v)�� � exe.hppnu �[��� // Copyright (c) 2006, 2007 Julio M. Merino Vidal // Copyright (c) 2008 Ilya Sokolov, Boris Schaeling // Copyright (c) 2009 Boris Schaeling // Copyright (c) 2010 Felipe Tanus, Boris Schaeling // Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling // Copyright (c) 2016 Klemens D. Morgenstern // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_PROCESS_EXE_HPP #define BOOST_PROCESS_EXE_HPP #include <boost/process/detail/basic_cmd.hpp> /** \file boost/process/exe.hpp * * Header which provides the exe property. \xmlonly <programlisting> namespace boost { namespace process { <emphasis>unspecified</emphasis> <globalname alt="boost::process::exe">exe</globalname>; } } </programlisting> \endxmlonly */ namespace boost { namespace filesystem { class path; } namespace process { namespace detail { struct exe_ { template<typename = void> inline exe_setter_<typename boost::filesystem::path::value_type> operator()(const boost::filesystem::path & pth) const { return exe_setter_<typename boost::filesystem::path::value_type>(pth.native()); } template<typename = void> inline exe_setter_<typename boost::filesystem::path::value_type> operator=(const boost::filesystem::path & pth) const { return exe_setter_<typename boost::filesystem::path::value_type>(pth.native()); } template<typename Char> inline exe_setter_<Char> operator()(const Char *s) const { return exe_setter_<Char>(s); } template<typename Char> inline exe_setter_<Char> operator= (const Char *s) const { return exe_setter_<Char>(s); } template<typename Char> inline exe_setter_<Char> operator()(const std::basic_string<Char> &s) const { return exe_setter_<Char>(s); } template<typename Char> inline exe_setter_<Char> operator= (const std::basic_string<Char> &s) const { return exe_setter_<Char>(s); } }; } /** The exe property allows to explicitly set the executable. The overload form applies when to the first, when several strings are passed to a launching function. The following expressions are valid, with `value` being either a C-String or a `std::basic_string` with `char` or `wchar_t` or a `boost::filesystem::path`. \code{.cpp} exe="value"; exe(value); \endcode The property can only be used for assignments. */ constexpr boost::process::detail::exe_ exe{}; }} #endif PK oM�[ʯ�� � exception.hppnu �[��� // Copyright (c) 2016 Klemens D. Morgenstern // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_PROCESS_EXCEPTION_HPP_ #define BOOST_PROCESS_EXCEPTION_HPP_ #include <system_error> namespace boost { namespace process { ///The exception usually thrown by boost.process. /** It merely inherits [std::system_error](http://en.cppreference.com/w/cpp/error/system_error) * but can then be distinguished in the catch-block from other system errors. * */ struct process_error : std::system_error { using std::system_error::system_error; }; } } #endif /* BOOST_PROCESS_EXCEPTION_HPP_ */ PK oM�[�)��N N io.hppnu �[��� // Copyright (c) 2016 Klemens D. Morgenstern // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_PROCESS_IO_HPP_ #define BOOST_PROCESS_IO_HPP_ #include <iosfwd> #include <cstdio> #include <functional> #include <utility> #include <boost/process/detail/config.hpp> #include <boost/process/pipe.hpp> #include <future> #if defined(BOOST_POSIX_API) #include <boost/process/detail/posix/asio_fwd.hpp> #include <boost/process/detail/posix/close_in.hpp> #include <boost/process/detail/posix/close_out.hpp> #include <boost/process/detail/posix/null_in.hpp> #include <boost/process/detail/posix/null_out.hpp> #include <boost/process/detail/posix/file_in.hpp> #include <boost/process/detail/posix/file_out.hpp> #include <boost/process/detail/posix/pipe_in.hpp> #include <boost/process/detail/posix/pipe_out.hpp> #elif defined(BOOST_WINDOWS_API) #include <boost/process/detail/windows/asio_fwd.hpp> #include <boost/process/detail/windows/close_in.hpp> #include <boost/process/detail/windows/close_out.hpp> #include <boost/process/detail/windows/null_in.hpp> #include <boost/process/detail/windows/null_out.hpp> #include <boost/process/detail/windows/file_in.hpp> #include <boost/process/detail/windows/file_out.hpp> #include <boost/process/detail/windows/pipe_in.hpp> #include <boost/process/detail/windows/pipe_out.hpp> #endif /** \file boost/process/io.hpp * * Header which provides the io properties. It provides the following properties: * \xmlonly <programlisting> namespace boost { namespace process { <emphasis>unspecified</emphasis> <globalname alt="boost::process::close">close</globalname>; <emphasis>unspecified</emphasis> <globalname alt="boost::process::null">null</globalname>; <emphasis>unspecified</emphasis> <globalname alt="boost::process::std_in">std_in</globalname>; <emphasis>unspecified</emphasis> <globalname alt="boost::process::std_out">std_out</globalname>; <emphasis>unspecified</emphasis> <globalname alt="boost::process::std_err">std_err</globalname>; } } </programlisting> \endxmlonly \par File I/O The library allows full redirection of streams to files as shown below. \code{.cpp} boost::filesystem::path log = "my_log_file.txt"; boost::filesystem::path input = "input.txt"; boost::filesystem::path output = "output.txt"; system("my_prog", std_out>output, std_in<input, std_err>log); \endcode \par Synchronous Pipe I/O Another way is to communicate through pipes. \code{.cpp} pstream str; child c("my_prog", std_out > str); int i; str >> i; \endcode Note that the pipe may also be used between several processes, like this: \code{.cpp} pipe p; child c1("nm", "a.out", std_out>p); child c2("c++filt", std_in<p); \endcode \par Asynchronous I/O Utilizing `boost.asio` asynchronous I/O is provided. \code boost::asio::io_context ios; std::future<std::string> output; system("ls", std_out > output, ios); auto res = fut.get(); \endcode \note `boost/process/async.hpp` must also be included for this to work. \par Closing Stream can be closed, so nothing can be read or written. \code{.cpp} system("foo", std_in.close()); \endcode \par Null Streams can be redirected to null, which means, that written date will be discarded and read data will only contain `EOF`. \code{.cpp} system("b2", std_out > null); \endcode * */ namespace boost { namespace process { namespace detail { template<typename T> using is_streambuf = typename std::is_same<T, boost::asio::streambuf>::type; template<typename T> using is_const_buffer = std::integral_constant<bool, std::is_same< boost::asio::const_buffer, T>::value | std::is_base_of<boost::asio::const_buffer, T>::value >; template<typename T> using is_mutable_buffer = std::integral_constant<bool, std::is_same< boost::asio::mutable_buffer, T>::value | std::is_base_of<boost::asio::mutable_buffer, T>::value >; struct null_t {constexpr null_t() = default;}; struct close_t; template<class> struct std_in_ { constexpr std_in_() = default; api::close_in close() const {return api::close_in(); } api::close_in operator=(const close_t &) const {return api::close_in();} api::close_in operator<(const close_t &) const {return api::close_in();} api::null_in null() const {return api::null_in();} api::null_in operator=(const null_t &) const {return api::null_in();} api::null_in operator<(const null_t &) const {return api::null_in();} api::file_in operator=(const boost::filesystem::path &p) const {return p;} api::file_in operator=(const std::string & p) const {return p;} api::file_in operator=(const std::wstring &p) const {return p;} api::file_in operator=(const char * p) const {return p;} api::file_in operator=(const wchar_t * p) const {return p;} api::file_in operator<(const boost::filesystem::path &p) const {return p;} api::file_in operator<(const std::string &p) const {return p;} api::file_in operator<(const std::wstring &p) const {return p;} api::file_in operator<(const char*p) const {return p;} api::file_in operator<(const wchar_t * p) const {return p;} api::file_in operator=(FILE * f) const {return f;} api::file_in operator<(FILE * f) const {return f;} template<typename Char, typename Traits> api::pipe_in operator=(basic_pipe<Char, Traits> & p) const {return p;} template<typename Char, typename Traits> api::pipe_in operator<(basic_pipe<Char, Traits> & p) const {return p;} template<typename Char, typename Traits> api::pipe_in operator=(basic_opstream<Char, Traits> & p) const {return p.pipe();} template<typename Char, typename Traits> api::pipe_in operator<(basic_opstream<Char, Traits> & p) const {return p.pipe();} template<typename Char, typename Traits> api::pipe_in operator=(basic_pstream <Char, Traits> & p) const {return p.pipe();} template<typename Char, typename Traits> api::pipe_in operator<(basic_pstream <Char, Traits> & p) const {return p.pipe();} api::async_pipe_in operator=(async_pipe & p) const {return p;} api::async_pipe_in operator<(async_pipe & p) const {return p;} template<typename T, typename = typename std::enable_if< is_const_buffer<T>::value || is_mutable_buffer<T>::value >::type> api::async_in_buffer<const T> operator=(const T & buf) const {return buf;} template<typename T, typename = typename std::enable_if<is_streambuf<T>::value>::type > api::async_in_buffer<T> operator=(T & buf) const {return buf;} template<typename T, typename = typename std::enable_if< is_const_buffer<T>::value || is_mutable_buffer<T>::value >::type> api::async_in_buffer<const T> operator<(const T & buf) const {return buf;} template<typename T, typename = typename std::enable_if<is_streambuf<T>::value>::type > api::async_in_buffer<T> operator<(T & buf) const {return buf;} }; //-1 == empty. //1 == stdout //2 == stderr template<int p1, int p2 = -1> struct std_out_ { constexpr std_out_() = default; api::close_out<p1,p2> close() const {return api::close_out<p1,p2>(); } api::close_out<p1,p2> operator=(const close_t &) const {return api::close_out<p1,p2>();} api::close_out<p1,p2> operator>(const close_t &) const {return api::close_out<p1,p2>();} api::null_out<p1,p2> null() const {return api::null_out<p1,p2>();} api::null_out<p1,p2> operator=(const null_t &) const {return api::null_out<p1,p2>();} api::null_out<p1,p2> operator>(const null_t &) const {return api::null_out<p1,p2>();} api::file_out<p1,p2> operator=(const boost::filesystem::path &p) const {return api::file_out<p1,p2>(p);} api::file_out<p1,p2> operator=(const std::string &p) const {return api::file_out<p1,p2>(p);} api::file_out<p1,p2> operator=(const std::wstring &p) const {return api::file_out<p1,p2>(p);} api::file_out<p1,p2> operator=(const char * p) const {return api::file_out<p1,p2>(p);} api::file_out<p1,p2> operator=(const wchar_t * p) const {return api::file_out<p1,p2>(p);} api::file_out<p1,p2> operator>(const boost::filesystem::path &p) const {return api::file_out<p1,p2>(p);} api::file_out<p1,p2> operator>(const std::string &p) const {return api::file_out<p1,p2>(p);} api::file_out<p1,p2> operator>(const std::wstring &p) const {return api::file_out<p1,p2>(p);} api::file_out<p1,p2> operator>(const char * p) const {return api::file_out<p1,p2>(p);} api::file_out<p1,p2> operator>(const wchar_t * p) const {return api::file_out<p1,p2>(p);} api::file_out<p1,p2> operator=(FILE * f) const {return f;} api::file_out<p1,p2> operator>(FILE * f) const {return f;} template<typename Char, typename Traits> api::pipe_out<p1,p2> operator=(basic_pipe<Char, Traits> & p) const {return p;} template<typename Char, typename Traits> api::pipe_out<p1,p2> operator>(basic_pipe<Char, Traits> & p) const {return p;} template<typename Char, typename Traits> api::pipe_out<p1,p2> operator=(basic_ipstream<Char, Traits> & p) const {return p.pipe();} template<typename Char, typename Traits> api::pipe_out<p1,p2> operator>(basic_ipstream<Char, Traits> & p) const {return p.pipe();} template<typename Char, typename Traits> api::pipe_out<p1,p2> operator=(basic_pstream <Char, Traits> & p) const {return p.pipe();} template<typename Char, typename Traits> api::pipe_out<p1,p2> operator>(basic_pstream <Char, Traits> & p) const {return p.pipe();} api::async_pipe_out<p1, p2> operator=(async_pipe & p) const {return p;} api::async_pipe_out<p1, p2> operator>(async_pipe & p) const {return p;} api::async_out_buffer<p1, p2, const asio::mutable_buffer> operator=(const asio::mutable_buffer & buf) const {return buf;} api::async_out_buffer<p1, p2, const asio::mutable_buffers_1> operator=(const asio::mutable_buffers_1 & buf) const {return buf;} api::async_out_buffer<p1, p2, asio::streambuf> operator=(asio::streambuf & os) const {return os ;} api::async_out_buffer<p1, p2, const asio::mutable_buffer> operator>(const asio::mutable_buffer & buf) const {return buf;} api::async_out_buffer<p1, p2, const asio::mutable_buffers_1> operator>(const asio::mutable_buffers_1 & buf) const {return buf;} api::async_out_buffer<p1, p2, asio::streambuf> operator>(asio::streambuf & os) const {return os ;} api::async_out_future<p1,p2, std::string> operator=(std::future<std::string> & fut) const { return fut;} api::async_out_future<p1,p2, std::string> operator>(std::future<std::string> & fut) const { return fut;} api::async_out_future<p1,p2, std::vector<char>> operator=(std::future<std::vector<char>> & fut) const { return fut;} api::async_out_future<p1,p2, std::vector<char>> operator>(std::future<std::vector<char>> & fut) const { return fut;} template<int pin, typename = typename std::enable_if< (((p1 == 1) && (pin == 2)) || ((p1 == 2) && (pin == 1))) && (p2 == -1)>::type> constexpr std_out_<1, 2> operator& (const std_out_<pin>&) const { return std_out_<1, 2> (); } }; struct close_t { constexpr close_t() = default; template<int T, int U> api::close_out<T,U> operator()(std_out_<T,U>) {return api::close_out<T,U>();} }; } ///This constant is a utility to allow syntax like `std_out > close` for closing I/O streams. constexpr boost::process::detail::close_t close; ///This constant is a utility to redirect streams to the null-device. constexpr boost::process::detail::null_t null; /** This property allows to set the input stream for the child process. \section stdin_details Details \subsection stdin_file File Input The file I/O simple redirects the stream to a file, for which the possible types are - `boost::filesystem::path` - `std::basic_string<char_type>` - `const char_type*` - `FILE*` with `char_type` being either `char` or `wchar_t`. FILE* is explicitly added, so the process can easily redirect the output stream of the child to another output stream of the process. That is: \code{.cpp} system("ls", std_in < stdin); \endcode \warning If the launching and the child process use the input, this leads to undefined behaviour. A syntax like `system("ls", std_out > std::cerr)` is not possible, due to the C++ implementation not providing access to the handle. The valid expressions for this property are \code{.cpp} std_in < file; std_in = file; \endcode \subsection stdin_pipe Pipe Input As explained in the corresponding section, the boost.process library provides a @ref boost::process::async_pipe "async_pipe" class which can be used to communicate with child processes. \note Technically the @ref boost::process::async_pipe "async_pipe" works synchronous here, since no asio implementation is used by the library here. The async-operation will then however not end if the process is finished, since the pipe remains open. You can use the async_close function with on_exit to fix that. Valid expressions with pipes are these: \code{.cpp} std_in < pipe; std_in = pipe; \endcode Where the valid types for `pipe` are the following: - `basic_pipe` - `async_pipe` - `basic_opstream` - `basic_pstream` Note that the pipe may also be used between several processes, like this: \code{.cpp} pipe p; child c1("nm", "a.out", std_out>p); child c2("c++filt", std_in<p); \endcode \subsection stdin_async_pipe Asynchronous Pipe Input Asynchronous Pipe I/O classifies communication which has automatically handling of the asynchronous operations by the process library. This means, that a pipe will be constructed, the async_read/-write will be automatically started, and that the end of the child process will also close the pipe. Valid types for pipe I/O are the following: - `boost::asio::const_buffer` \xmlonly <footnote><para> Constructed with <code>boost::asio::buffer</code></para></footnote> \endxmlonly - `boost::asio::mutable_buffer` \xmlonly <footnote><para> Constructed with <code>boost::asio::buffer</code></para></footnote> \endxmlonly - `boost::asio::streambuf` Valid expressions with pipes are these: \code{.cpp} std_in < buffer; std_in = buffer; std_out > buffer; std_out = buffer; std_err > buffer; std_err = buffer; (std_out & std_err) > buffer; (std_out & std_err) = buffer; \endcode \note It is also possible to get a future for std_in, by chaining another `std::future<void>` onto it, so you can wait for the input to be completed. It looks like this: \code{.cpp} std::future<void> fut; boost::asio::io_context ios; std::string data; child c("prog", std_in < buffer(data) > fut, ios); fut.get(); \endcode \note `boost::asio::buffer` is also available in the `boost::process` namespace. \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. \subsection stdin_close Close The input stream can be closed, so it cannot be read from. This will lead to an error when attempted. This can be achieved by the following syntax. \code{.cpp} std_in < close; std_in = close; std_in.close(); \endcode \subsection stdin_null Null The input stream can be redirected to read from the null-device, which means that only `EOF` is read. The syntax to achieve that has the following variants: \code{.cpp} std_in < null; std_in = null; std_in.null(); \endcode */ constexpr boost::process::detail::std_in_<void> std_in; /** This property allows to set the output stream for the child process. \note The Semantic is the same as for \xmlonly <globalname alt="boost::process::std_err">std_err</globalname> \endxmlonly \note `std_err` and `std_out` can be combined into one stream, with the `operator &`, i.e. `std_out & std_err`. \section stdout_details Details \subsection stdout_file File Input The file I/O simple redirects the stream to a file, for which the possible types are - `boost::filesystem::path` - `std::basic_string<char_type>` - `const char_type*` - `FILE*` with `char_type` being either `char` or `wchar_t`. FILE* is explicitly added, so the process can easily redirect the output stream of the child to another output stream of the process. That is: \code{.cpp} system("ls", std_out < stdin); \endcode \warning If the launching and the child process use the input, this leads to undefined behaviour. A syntax like `system("ls", std_out > std::cerr)` is not possible, due to the C++ implementation not providing access to the handle. The valid expressions for this property are \code{.cpp} std_out < file; std_out = file; \endcode \subsection stdout_pipe Pipe Output As explained in the corresponding section, the boost.process library provides a @ref boost::process::async_pipe "async_pipe" class which can be used to communicate with child processes. \note Technically the @ref boost::process::async_pipe "async_pipe" works like a synchronous pipe here, since no asio implementation is used by the library here. The asynchronous operation will then however not end if the process is finished, since the pipe remains open. You can use the async_close function with on_exit to fix that. Valid expressions with pipes are these: \code{.cpp} std_out > pipe; std_out = pipe; \endcode Where the valid types for `pipe` are the following: - `basic_pipe` - `async_pipe` - `basic_ipstream` - `basic_pstream` Note that the pipe may also be used between several processes, like this: \code{.cpp} pipe p; child c1("nm", "a.out", std_out>p); child c2("c++filt", std_in<p); \endcode \subsection stdout_async_pipe Asynchronous Pipe Output Asynchronous Pipe I/O classifies communication which has automatically handling of the async operations by the process library. This means, that a pipe will be constructed, the async_read/-write will be automatically started, and that the end of the child process will also close the pipe. Valid types for pipe I/O are the following: - `boost::asio::mutable_buffer` \xmlonly <footnote><para> Constructed with <code>boost::asio::buffer</code></para></footnote> \endxmlonly - `boost::asio::streambuf` - `std::future<std::vector<char>>` - `std::future<std::string>` Valid expressions with pipes are these: \code{.cpp} std_out > buffer; std_out = buffer; std_err > buffer; std_err = buffer; (std_out & std_err) > buffer; (std_out & std_err) = buffer; \endcode \note `boost::asio::buffer` is also available in the `boost::process` namespace. \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. \subsection stdout_close Close The out stream can be closed, so it cannot be write from. This will lead to an error when attempted. This can be achieved by the following syntax. \code{.cpp} std_out > close; std_out = close; std_out.close(); \endcode \subsection stdout_null Null The output stream can be redirected to write to the null-device, which means that all output is discarded. The syntax to achieve that has the following variants: \code{.cpp} std_out > null; std_out = null; std_out.null(); \endcode */ constexpr boost::process::detail::std_out_<1> std_out; /**This property allows setting the `stderr` stream. The semantic and syntax is the same as for * \xmlonly <globalname alt="boost::process::std_out">std_out</globalname> \endxmlonly . */ constexpr boost::process::detail::std_out_<2> std_err; }} #endif /* INCLUDE_BOOST_PROCESS_IO_HPP_ */ PK oM�[��6�� � detail/handler_base.hppnu �[��� // Copyright (c) 2006, 2007 Julio M. Merino Vidal // Copyright (c) 2008 Ilya Sokolov, Boris Schaeling // Copyright (c) 2009 Boris Schaeling // Copyright (c) 2010 Felipe Tanus, Boris Schaeling // Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling // Copyright (c) 2016 Klemens D. Morgenstern // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_PROCESS_DETAIL_HANDLER_BASE_HPP #define BOOST_PROCESS_DETAIL_HANDLER_BASE_HPP #include <system_error> namespace boost { namespace process { namespace detail { template<template <class> class Template> struct make_handler_t { constexpr make_handler_t() {} template<typename Handler> constexpr Template<Handler> operator()(Handler handler) const {return Template<Handler>(handler);} template<typename Handler> constexpr Template<Handler> operator= (Handler handler) const {return Template<Handler>(handler);} template<typename Handler> constexpr Template<Handler> operator+=(Handler handler) const {return Template<Handler>(handler);} }; struct handler_base { using resource_type = void; template <class Executor> void on_setup(Executor&) const {} template <class Executor> void on_error(Executor&, const std::error_code &) const {} template <class Executor> void on_success(Executor&) const {} }; }}} #endif PK oM�[�̹ � detail/handler.hppnu �[��� // Copyright (c) 2016 Klemens D. Morgenstern // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_PROCESS_DETAIL_HANDLER_HPP_ #define BOOST_PROCESS_DETAIL_HANDLER_HPP_ #include <boost/process/detail/config.hpp> #if defined(BOOST_POSIX_API) #include <boost/process/detail/posix/handler.hpp> #elif defined(BOOST_WINDOWS_API) #include <boost/process/detail/windows/handler.hpp> #endif namespace boost { namespace process { namespace detail { //extended handler base. typedef api::handler_base_ext handler; template <class Handler> struct on_setup_ : handler { explicit on_setup_(Handler handler) : handler_(handler) {} template <class Executor> void on_setup(Executor &e) { handler_(e); } private: Handler handler_; }; template <class Handler> struct on_error_ : handler { explicit on_error_(Handler handler) : handler_(handler) {} template <class Executor> void on_error(Executor &e, const std::error_code &ec) { handler_(e, ec); } private: Handler handler_; }; template <class Handler> struct on_success_ : handler { explicit on_success_(Handler handler) : handler_(handler) {} template <class Executor> void on_success(Executor &e) { handler_(e); } private: Handler handler_; }; } }} #endif /* BOOST_PROCESS_DETAIL_HANDLER_HPP_ */ PK oM�["ϦY^ ^ detail/config.hppnu �[��� // Copyright (c) 2006, 2007 Julio M. Merino Vidal // Copyright (c) 2008 Ilya Sokolov, Boris Schaeling // Copyright (c) 2009 Boris Schaeling // Copyright (c) 2010 Felipe Tanus, Boris Schaeling // Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling // Copyright (c) 2016 Klemens D. Morgenstern // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) /** * \file boost/process/config.hpp * * Defines various macros. */ #ifndef BOOST_PROCESS_DETAIL_CONFIG_HPP #define BOOST_PROCESS_DETAIL_CONFIG_HPP #include <boost/config.hpp> #include <system_error> #include <boost/system/api_config.hpp> #include <boost/process/exception.hpp> #if defined(BOOST_POSIX_API) #include <errno.h> #if defined(__GLIBC__) #include <features.h> #else extern char **environ; #endif #elif defined(BOOST_WINDOWS_API) #include <boost/winapi/get_last_error.hpp> #else #error "System API not supported by boost.process" #endif namespace boost { namespace process { namespace detail { #if !defined(BOOST_PROCESS_PIPE_SIZE) #define BOOST_PROCESS_PIPE_SIZE 1024 #endif #if defined(BOOST_POSIX_API) namespace posix {namespace extensions {}} namespace api = posix; inline std::error_code get_last_error() noexcept { return std::error_code(errno, std::system_category()); } //copied from linux spec. #if (_XOPEN_SOURCE >= 500 || _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED) && !(_POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700) #define BOOST_POSIX_HAS_VFORK 1 #endif #if (_POSIX_C_SOURCE >= 199309L) #define BOOST_POSIX_HAS_SIGTIMEDWAIT 1 #endif #elif defined(BOOST_WINDOWS_API) namespace windows {namespace extensions {}} namespace api = windows; inline std::error_code get_last_error() noexcept { return std::error_code(::boost::winapi::GetLastError(), std::system_category()); } #endif inline void throw_last_error(const std::string & msg) { throw process_error(get_last_error(), msg); } inline void throw_last_error(const char * msg) { throw process_error(get_last_error(), msg); } inline void throw_last_error() { throw process_error(get_last_error()); } inline void throw_error(const std::error_code& ec) { if (ec) throw process_error(ec); } inline void throw_error(const std::error_code& ec, const char* msg) { if (ec) throw process_error(ec, msg); } template<typename Char> constexpr Char null_char(); template<> constexpr char null_char<char> (){return '\0';} template<> constexpr wchar_t null_char<wchar_t> (){return L'\0';} template<typename Char> constexpr Char equal_sign(); template<> constexpr char equal_sign<char> () {return '='; } template<> constexpr wchar_t equal_sign<wchar_t> () {return L'='; } template<typename Char> constexpr Char quote_sign(); template<> constexpr char quote_sign<char> () {return '"'; } template<> constexpr wchar_t quote_sign<wchar_t> () {return L'"'; } template<typename Char> constexpr Char space_sign(); template<> constexpr char space_sign<char> () {return ' '; } template<> constexpr wchar_t space_sign<wchar_t> () {return L' '; } }}} #endif PK oM�[�(P�� � detail/traits/group.hppnu �[��� // Copyright (c) 2016 Klemens D. Morgenstern // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_PROCESS_DETAIL_TRAITS_GROUP_HPP_ #define BOOST_PROCESS_DETAIL_TRAITS_GROUP_HPP_ #include <boost/process/detail/config.hpp> #include <boost/process/detail/traits/decl.hpp> namespace boost { namespace process { struct group; namespace detail { struct group_tag {}; template<> struct make_initializer_t<group_tag>; template<> struct initializer_tag_t<::boost::process::group> { typedef group_tag type;}; }}} #endif /* BOOST_PROCESS_DETAIL_HANDLER_HPP_ */ PK oM�[1�O; ; detail/traits/wchar_t.hppnu �[��� // Copyright (c) 2016 Klemens D. Morgenstern // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_PROCESS_DETAIL_TRAITS_WCHAR_T_HPP_ #define BOOST_PROCESS_DETAIL_TRAITS_WCHAR_T_HPP_ #include <boost/process/detail/traits/decl.hpp> #include <boost/process/detail/traits/cmd_or_exe.hpp> #include <boost/process/detail/traits/env.hpp> #include <boost/process/locale.hpp> namespace boost { namespace process { namespace detail { //template template<typename T> struct is_wchar_t : std::false_type {}; template<> struct is_wchar_t<boost::filesystem::path> : std::is_same<typename boost::filesystem::path::value_type, wchar_t> { }; template<> struct is_wchar_t<const wchar_t* > : std::true_type {}; template<> struct is_wchar_t<wchar_t* > : std::true_type {}; template<std::size_t Size> struct is_wchar_t<const wchar_t [Size]> : std::true_type {}; template<std::size_t Size> struct is_wchar_t<const wchar_t (&)[Size]> : std::true_type {}; template<> struct is_wchar_t<std::wstring> : std::true_type {}; template<> struct is_wchar_t<std::vector<std::wstring>> : std::true_type {}; template<> struct is_wchar_t<std::initializer_list<std::wstring>> : std::true_type {}; template<> struct is_wchar_t<std::vector<wchar_t *>> : std::true_type {}; template<> struct is_wchar_t<std::initializer_list<wchar_t *>> : std::true_type {}; template<typename Char, typename T> struct char_converter { static T& conv(T & in) { return in; } static T&& conv(T&& in) { return std::move(in); } static const T& conv(const T & in) { return in; } }; template<typename Char, typename T> using char_converter_t = char_converter<Char, typename std::remove_cv<typename std::remove_reference<T>::type>::type>; template<> struct char_converter<char, const wchar_t*> { static std::string conv(const wchar_t* in) { std::size_t size = 0; while (in[size] != L'\0') size++; return ::boost::process::detail::convert(in, in + size); } }; template<> struct char_converter<char, wchar_t*> { static std::string conv(wchar_t* in) { std::size_t size = 0; while (in[size] != L'\0') size++; return ::boost::process::detail::convert(in, in + size); } }; template<std::size_t Size> struct char_converter<char, wchar_t[Size]> { static std::string conv(const wchar_t(&in)[Size]) { return ::boost::process::detail::convert(in, in + Size -1); } }; template<> struct char_converter<wchar_t, const char*> { static std::wstring conv(const char* in) { std::size_t size = 0; while (in[size] != '\0') size++; return ::boost::process::detail::convert(in, in + size); } }; template<> struct char_converter<wchar_t, char*> { static std::wstring conv(char* in) { std::size_t size = 0; while (in[size] != '\0') size++; return ::boost::process::detail::convert(in, in + size); } }; template<std::size_t Size> struct char_converter<wchar_t, char[Size]> { static std::wstring conv(const char(&in)[Size]) { return ::boost::process::detail::convert(in, in + Size -1); } }; //all the containers. template<> struct char_converter<wchar_t, std::string> { static std::wstring conv(const std::string & in) { return ::boost::process::detail::convert(in); } }; template<> struct char_converter<char, std::wstring> { static std::string conv(const std::wstring & in) { return ::boost::process::detail::convert(in); } }; template<> struct char_converter<wchar_t, std::vector<std::string>> { static std::vector<std::wstring> conv(const std::vector<std::string> & in) { std::vector<std::wstring> ret(in.size()); std::transform(in.begin(), in.end(), ret.begin(), [](const std::string & st) { return convert(st); }); return ret; } }; template<> struct char_converter<wchar_t, std::initializer_list<std::string>> { static std::vector<std::wstring> conv(const std::initializer_list<std::string> & in) { std::vector<std::wstring> ret(in.size()); std::transform(in.begin(), in.end(), ret.begin(), [](const std::string & st) { return convert(st); }); return ret; } }; template<> struct char_converter<wchar_t, std::vector<char* >> { static std::vector<std::wstring> conv(const std::vector<char* > & in) { std::vector<std::wstring> ret(in.size()); std::transform(in.begin(), in.end(), ret.begin(), [](const char* st) { std::size_t sz = 0; while (st[sz] != '\0') sz++; return convert(st, st + sz); }); return ret; } }; template<> struct char_converter<wchar_t, std::initializer_list<char *>> { static std::vector<std::wstring> conv(const std::initializer_list<char * > & in) { std::vector<std::wstring> ret(in.size()); std::transform(in.begin(), in.end(), ret.begin(), [](const char* st) { std::size_t sz = 0; while (st[sz] != '\0') sz++; return convert(st, st + sz); }); return ret; } }; template<> struct char_converter<char, std::vector<std::wstring>> { static std::vector<std::string> conv(const std::vector<std::wstring> & in) { std::vector<std::string> ret(in.size()); std::transform(in.begin(), in.end(), ret.begin(), [](const std::wstring & st) { return convert(st); }); return ret; } }; template<> struct char_converter<char, std::initializer_list<std::wstring>> { static std::vector<std::string> conv(const std::initializer_list<std::wstring> & in) { std::vector<std::string> ret(in.size()); std::transform(in.begin(), in.end(), ret.begin(), [](const std::wstring & st) { return convert(st); }); return ret; } }; template<> struct char_converter<char, std::vector<wchar_t* >> { static std::vector<std::string> conv(const std::vector<wchar_t* > & in) { std::vector<std::string> ret(in.size()); std::transform(in.begin(), in.end(), ret.begin(), [](const wchar_t* st) { std::size_t sz = 0; while (st[sz] != L'\0') sz++; return convert(st, st + sz); }); return ret; } }; template<> struct char_converter<char, std::initializer_list<wchar_t * >> { static std::vector<std::string> conv(const std::initializer_list<wchar_t *> & in) { std::vector<std::string> ret(in.size()); std::transform(in.begin(), in.end(), ret.begin(), [](const wchar_t* st) { std::size_t sz = 0; while (st[sz] != L'\0') sz++; return convert(st, st + sz); }); return ret; } }; }}} #endif /* BOOST_PROCESS_DETAIL_TRAITS_WCHAR_T_HPP_ */ PK oM�[Y�y detail/traits/env.hppnu �[��� // Copyright (c) 2016 Klemens D. Morgenstern // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_PROCESS_DETAIL_TRAITS_ENV_HPP_ #define BOOST_PROCESS_DETAIL_TRAITS_ENV_HPP_ #include <boost/process/detail/traits/decl.hpp> namespace boost { namespace process { template<typename Char> class basic_environment; template<typename Char> class basic_native_environment; namespace detail { template<typename Char> struct env_tag {}; template<typename Char> struct env_set; template<typename Char> struct env_append; template<typename Char> struct env_reset; template<typename Char> struct env_init; template<typename Char> struct initializer_tag<env_set<Char>> { typedef env_tag<Char> type; }; template<typename Char> struct initializer_tag<env_append<Char>> { typedef env_tag<Char> type; }; template<typename Char> struct initializer_tag<env_reset<Char>> { typedef env_tag<Char> type;}; template<typename Char> struct initializer_tag<env_init <Char>> { typedef env_tag<Char> type;}; template<typename Char> struct initializer_tag<::boost::process::basic_environment<Char>> { typedef env_tag<Char> type; }; template<typename Char> struct initializer_tag<::boost::process::basic_native_environment<Char>> { typedef env_tag<Char> type; }; template<> struct initializer_builder<env_tag<char>>; template<> struct initializer_builder<env_tag<wchar_t>>; } }} #endif /* INCLUDE_BOOST_PROCESS_DETAIL_ENV_HPP_ */ PK oM�[���X X detail/traits/error.hppnu �[��� // Copyright (c) 2016 Klemens D. Morgenstern // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_PROCESS_DETAIL_TRAITS_ERROR_HPP_ #define BOOST_PROCESS_DETAIL_TRAITS_ERROR_HPP_ #include <boost/process/detail/config.hpp> #include <system_error> #include <boost/process/detail/traits/decl.hpp> namespace boost { namespace process { namespace detail { struct error_tag; template<> struct initializer_tag<std::error_code>; }}} #endif /* BOOST_PROCESS_DETAIL_HANDLER_HPP_ */ PK oM�[M� detail/traits/cmd_or_exe.hppnu �[��� // Copyright (c) 2016 Klemens D. Morgenstern // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_PROCESS_DETAIL_TRAITS_CMD_OR_EXE_HPP_ #define BOOST_PROCESS_DETAIL_TRAITS_CMD_OR_EXE_HPP_ #include <string> #include <vector> #include <type_traits> #include <initializer_list> #include <boost/filesystem/path.hpp> #include <boost/process/detail/traits/decl.hpp> namespace boost { namespace process { namespace detail { template<typename Char> struct cmd_or_exe_tag {}; struct shell_; template<> struct initializer_tag<const char* > { typedef cmd_or_exe_tag<char> type;}; template<> struct initializer_tag<const wchar_t* > { typedef cmd_or_exe_tag<wchar_t> type;}; template<> struct initializer_tag<char* > { typedef cmd_or_exe_tag<char> type;}; template<> struct initializer_tag<wchar_t* > { typedef cmd_or_exe_tag<wchar_t> type;}; template<std::size_t Size> struct initializer_tag<const char [Size]> { typedef cmd_or_exe_tag<char> type;}; template<std::size_t Size> struct initializer_tag<const wchar_t [Size]> { typedef cmd_or_exe_tag<wchar_t> type;}; template<std::size_t Size> struct initializer_tag<const char (&)[Size]> { typedef cmd_or_exe_tag<char> type;}; template<std::size_t Size> struct initializer_tag<const wchar_t (&)[Size]> { typedef cmd_or_exe_tag<wchar_t> type;}; template<> struct initializer_tag<std::basic_string<char >> { typedef cmd_or_exe_tag<char> type;}; template<> struct initializer_tag<std::basic_string<wchar_t >> { typedef cmd_or_exe_tag<wchar_t> type;}; template<> struct initializer_tag<std::vector<std::basic_string<char >>> { typedef cmd_or_exe_tag<char> type;}; template<> struct initializer_tag<std::vector<std::basic_string<wchar_t >>> { typedef cmd_or_exe_tag<wchar_t> type;}; template<> struct initializer_tag<std::initializer_list<std::basic_string<char >>> { typedef cmd_or_exe_tag<char> type;}; template<> struct initializer_tag<std::initializer_list<std::basic_string<wchar_t >>> { typedef cmd_or_exe_tag<wchar_t> type;}; template<> struct initializer_tag<std::vector<char *>> { typedef cmd_or_exe_tag<char> type;}; template<> struct initializer_tag<std::vector<wchar_t *>> { typedef cmd_or_exe_tag<wchar_t> type;}; template<> struct initializer_tag<std::initializer_list<char *>> { typedef cmd_or_exe_tag<char> type;}; template<> struct initializer_tag<std::initializer_list<wchar_t *>> { typedef cmd_or_exe_tag<wchar_t> type;}; template<> struct initializer_tag<std::initializer_list<const char *>> { typedef cmd_or_exe_tag<char> type;}; template<> struct initializer_tag<std::initializer_list<const wchar_t *>> { typedef cmd_or_exe_tag<wchar_t> type;}; template<> struct initializer_tag<shell_> { typedef cmd_or_exe_tag<typename boost::filesystem::path::value_type> type; }; template<> struct initializer_tag<boost::filesystem::path> { typedef cmd_or_exe_tag<typename boost::filesystem::path::value_type> type; }; template <typename Char> struct exe_setter_; template <typename Char, bool Append = false> struct arg_setter_; template <typename Char, bool Append> struct initializer_tag<arg_setter_<Char, Append>> { typedef cmd_or_exe_tag<Char> type;}; template<typename Char> struct initializer_tag<exe_setter_<Char>> { typedef cmd_or_exe_tag<Char> type;}; template<> struct initializer_builder<cmd_or_exe_tag<char>>; template<> struct initializer_builder<cmd_or_exe_tag<wchar_t>>; }}} #endif /* BOOST_PROCESS_DETAIL_STRING_TRAITS_HPP_ */ PK oM�[���� � detail/traits/decl.hppnu �[��� // Copyright (c) 2016 Klemens D. Morgenstern // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_PROCESS_DETAIL_TRAITS_DECL_HPP_ #define BOOST_PROCESS_DETAIL_TRAITS_DECL_HPP_ #include <boost/process/detail/config.hpp> #include <boost/none.hpp> #include <type_traits> #if defined(BOOST_POSIX_API) #include <boost/process/detail/posix/handler.hpp> #elif defined(BOOST_WINDOWS_API) #include <boost/process/detail/windows/handler.hpp> #endif namespace boost { namespace process { namespace detail { template<typename T> struct is_initializer : std::is_base_of<handler_base, T> {}; template<typename T> struct is_initializer<T&> : std::is_base_of<handler_base, T> {}; template<typename T> struct initializer_tag;// { typedef void type; }; //remove const template<typename T> struct initializer_tag<const T> { typedef typename initializer_tag<T>::type type; }; //remove & template<typename T> struct initializer_tag<T&> { typedef typename initializer_tag<T>::type type; }; //remove const & template<typename T> struct initializer_tag<const T&> { typedef typename initializer_tag<T>::type type; }; template<typename T> struct initializer_builder; template<typename First, typename ...Args> struct valid_argument_list; template<typename First> struct valid_argument_list<First> { constexpr static bool value = is_initializer<First>::value || !std::is_void<typename initializer_tag<First>::type>::value; typedef std::integral_constant<bool, value> type; }; template<typename First, typename ...Args> struct valid_argument_list { constexpr static bool my_value = is_initializer<First>::value || !std::is_void<typename initializer_tag<First>::type>::value; constexpr static bool value = valid_argument_list<Args...>::value && my_value; typedef std::integral_constant<bool, value> type; }; }}} #endif /* BOOST_PROCESS_DETAIL_HANDLER_HPP_ */ PK oM�[�=� � detail/traits/async.hppnu �[��� // Copyright (c) 2016 Klemens D. Morgenstern // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_PROCESS_DETAIL_TRAITS_ASYNC_HPP_ #define BOOST_PROCESS_DETAIL_TRAITS_ASYNC_HPP_ #include <boost/process/detail/config.hpp> #include <boost/process/detail/traits/decl.hpp> namespace boost { namespace asio { class io_context; }} namespace boost { namespace process { namespace detail { struct async_tag {}; template<> struct initializer_builder<async_tag>; template<> struct initializer_tag<::boost::asio::io_context> { typedef async_tag type;}; }}} #endif /* BOOST_PROCESS_DETAIL_HANDLER_HPP_ */ PK oM�[�ȵ�F F detail/execute_impl.hppnu �[��� // Copyright (c) 2006, 2007 Julio M. Merino Vidal // Copyright (c) 2008 Ilya Sokolov, Boris Schaeling // Copyright (c) 2009 Boris Schaeling // Copyright (c) 2010 Felipe Tanus, Boris Schaeling // Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling // Copyright (c) 2016 Klemens D. Morgenstern // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) /** * \file boost/process/execute.hpp * * Defines a function to execute a program. */ #ifndef BOOST_PROCESS_EXECUTE_HPP #define BOOST_PROCESS_EXECUTE_HPP #include <boost/process/detail/config.hpp> #include <boost/process/detail/traits.hpp> #if defined(BOOST_POSIX_API) #include <boost/process/detail/posix/executor.hpp> #elif defined(BOOST_WINDOWS_API) #include <boost/process/detail/windows/executor.hpp> #endif #include <boost/process/detail/basic_cmd.hpp> #include <boost/process/detail/handler.hpp> #include <boost/fusion/view.hpp> #include <boost/fusion/container.hpp> #include <boost/fusion/sequence.hpp> #include <boost/fusion/tuple.hpp> #include <boost/fusion/algorithm/transformation/filter_if.hpp> #include <boost/fusion/adapted/std_tuple.hpp> #include <boost/fusion/container/vector/convert.hpp> #include <type_traits> #include <utility> namespace boost { namespace process { class child; namespace detail { template<typename ...Args> struct has_wchar; template<typename First, typename ...Args> struct has_wchar<First, Args...> { typedef has_wchar<Args...> next; typedef typename std::remove_cv< typename std::remove_reference<First>::type>::type res_type; constexpr static bool my_value = is_wchar_t<res_type>::value; constexpr static bool value = my_value || next::value; typedef std::integral_constant<bool, value> type; }; template<typename First> struct has_wchar<First> { typedef typename std::remove_cv< typename std::remove_reference<First>::type>::type res_type; constexpr static bool value = is_wchar_t<res_type>::value; typedef std::integral_constant<bool, value> type; }; #if defined(BOOST_WINDOWS_API) //everything needs to be wchar_t #if defined(BOOST_NO_ANSI_APIS) template<bool has_wchar> struct required_char_type { typedef wchar_t type; }; #else template<bool has_wchar> struct required_char_type; template<> struct required_char_type<true> { typedef wchar_t type; }; template<> struct required_char_type<false> { typedef char type; }; #endif #elif defined(BOOST_POSIX_API) template<bool has_wchar> struct required_char_type { typedef char type; }; #endif template<typename ... Args> using required_char_type_t = typename required_char_type< has_wchar<Args...>::value>::type; template<typename Iterator, typename End, typename ...Args> struct make_builders_from_view { typedef boost::fusion::set<Args...> set; typedef typename boost::fusion::result_of::deref<Iterator>::type ref_type; typedef typename std::remove_reference<ref_type>::type res_type; typedef typename initializer_tag<res_type>::type tag; typedef typename initializer_builder<tag>::type builder_type; typedef typename boost::fusion::result_of::has_key<set, builder_type> has_key; typedef typename boost::fusion::result_of::next<Iterator>::type next_itr; typedef typename make_builders_from_view<next_itr, End>::type next; typedef typename std::conditional<has_key::value, typename make_builders_from_view<next_itr, End, Args...>::type, typename make_builders_from_view<next_itr, End, Args..., builder_type>::type >::type type; }; template<typename Iterator, typename ...Args> struct make_builders_from_view<Iterator, Iterator, Args...> { typedef boost::fusion::set<Args...> type; }; template<typename Builders> struct builder_ref { Builders &builders; builder_ref(Builders & builders) : builders(builders) {}; template<typename T> void operator()(T && value) const { typedef typename initializer_tag<typename std::remove_reference<T>::type>::type tag; typedef typename initializer_builder<tag>::type builder_type; boost::fusion::at_key<builder_type>(builders)(std::forward<T>(value)); } }; template<typename T> struct get_initializers_result { typedef typename T::result_type type; }; template<> struct get_initializers_result<boost::fusion::void_> { typedef boost::fusion::void_ type; }; template<typename ...Args> struct helper_vector { }; template<typename T, typename ...Stack> struct invoke_get_initializer_collect_keys; template<typename ...Stack> struct invoke_get_initializer_collect_keys<boost::fusion::vector<>, Stack...> { typedef helper_vector<Stack...> type; }; template<typename First, typename ...Args, typename ...Stack> struct invoke_get_initializer_collect_keys<boost::fusion::vector<First, Args...>, Stack...> { typedef typename invoke_get_initializer_collect_keys<boost::fusion::vector<Args...>, Stack..., First>::type next; typedef helper_vector<Stack...> stack_t; typedef typename std::conditional<std::is_same<boost::fusion::void_, First>::value, stack_t, next>::type type; }; template<typename Keys> struct invoke_get_initializer; template<typename ...Args> struct invoke_get_initializer<helper_vector<Args...>> { typedef boost::fusion::tuple<typename get_initializers_result<Args>::type...> result_type; template<typename Sequence> static result_type call(Sequence & seq) { return result_type(boost::fusion::at_key<Args>(seq).get_initializer()...);; } }; template<typename ...Args> inline boost::fusion::tuple<typename get_initializers_result<Args>::type...> get_initializers(boost::fusion::set<Args...> & builders) { //typedef boost::fusion::tuple<typename get_initializers_result<Args>::type...> return_type; typedef typename invoke_get_initializer_collect_keys<boost::fusion::vector<Args...>>::type keys; return invoke_get_initializer<keys>::call(builders); } template<typename Char, typename ... Args> inline child basic_execute_impl(Args && ... args) { //create a tuple from the argument list boost::fusion::tuple<typename std::remove_reference<Args>::type&...> tup(args...); auto inits = boost::fusion::filter_if< boost::process::detail::is_initializer< typename std::remove_reference< boost::mpl::_ >::type > >(tup); auto others = boost::fusion::filter_if< boost::mpl::not_< boost::process::detail::is_initializer< typename std::remove_reference< boost::mpl::_ >::type > > >(tup); // typename detail::make_builders_from_view<decltype(others)>::type builders; //typedef typename boost::fusion::result_of::as_vector<decltype(inits)>::type inits_t; typedef typename boost::fusion::result_of::as_vector<decltype(others)>::type others_t; // typedef decltype(others) others_t; typedef typename ::boost::process::detail::make_builders_from_view< typename boost::fusion::result_of::begin<others_t>::type, typename boost::fusion::result_of::end <others_t>::type>::type builder_t; builder_t builders; ::boost::process::detail::builder_ref<builder_t> builder_ref(builders); boost::fusion::for_each(others, builder_ref); auto other_inits = ::boost::process::detail::get_initializers(builders); boost::fusion::joint_view<decltype(other_inits), decltype(inits)> complete_inits(other_inits, inits); auto exec = boost::process::detail::api::make_executor<Char>(complete_inits); return exec(); } template<typename ...Args> inline child execute_impl(Args&& ... args) { typedef required_char_type_t<Args...> req_char_type; return basic_execute_impl<req_char_type>( boost::process::detail::char_converter_t<req_char_type, Args>::conv( std::forward<Args>(args))... ); } }}} #endif PK oM�[i� � detail/posix/io_context_ref.hppnu �[��� // Copyright (c) 2016 Klemens D. Morgenstern // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_PROCESS_POSIX_IO_CONTEXT_REF_HPP_ #define BOOST_PROCESS_POSIX_IO_CONTEXT_REF_HPP_ #include <boost/process/detail/posix/handler.hpp> #include <boost/process/detail/posix/async_handler.hpp> #include <boost/asio/io_context.hpp> #include <boost/fusion/algorithm/iteration/for_each.hpp> #include <boost/fusion/algorithm/transformation/filter_if.hpp> #include <boost/fusion/algorithm/transformation/transform.hpp> #include <boost/fusion/view/transform_view.hpp> #include <boost/fusion/container/vector/convert.hpp> #include <boost/process/detail/posix/sigchld_service.hpp> #include <boost/process/detail/posix/is_running.hpp> #include <functional> #include <type_traits> #include <memory> #include <vector> #include <sys/wait.h> namespace boost { namespace process { namespace detail { namespace posix { template<typename Executor> struct on_exit_handler_transformer { Executor & exec; on_exit_handler_transformer(Executor & exec) : exec(exec) {} template<typename Sig> struct result; template<typename T> struct result<on_exit_handler_transformer<Executor>(T&)> { typedef typename T::on_exit_handler_t type; }; template<typename T> auto operator()(T& t) const -> typename T::on_exit_handler_t { return t.on_exit_handler(exec); } }; template<typename Executor> struct async_handler_collector { Executor & exec; std::vector<std::function<void(int, const std::error_code & ec)>> &handlers; async_handler_collector(Executor & exec, std::vector<std::function<void(int, const std::error_code & ec)>> &handlers) : exec(exec), handlers(handlers) {} template<typename T> void operator()(T & t) const { handlers.push_back(t.on_exit_handler(exec)); } }; //Also set's up waiting for the exit, so it can close async stuff. struct io_context_ref : handler_base_ext { io_context_ref(boost::asio::io_context & ios) : ios(ios) { } boost::asio::io_context &get() {return ios;}; template <class Executor> void on_success(Executor& exec) { ios.notify_fork(boost::asio::io_context::fork_parent); //must be on the heap so I can move it into the lambda. auto asyncs = boost::fusion::filter_if< is_async_handler< typename std::remove_reference< boost::mpl::_ > ::type >>(exec.seq); //ok, check if there are actually any. if (boost::fusion::empty(asyncs)) return; std::vector<std::function<void(int, const std::error_code & ec)>> funcs; funcs.reserve(boost::fusion::size(asyncs)); boost::fusion::for_each(asyncs, async_handler_collector<Executor>(exec, funcs)); auto & es = exec.exit_status; auto wh = [funcs, es](int val, const std::error_code & ec) { es->store(val); for (auto & func : funcs) func(::boost::process::detail::posix::eval_exit_status(val), ec); }; sigchld_service.async_wait(exec.pid, std::move(wh)); } template<typename Executor> void on_setup (Executor &) const {/*ios.notify_fork(boost::asio::io_context::fork_prepare);*/} template<typename Executor> void on_exec_setup (Executor &) const {/*ios.notify_fork(boost::asio::io_context::fork_child);*/} template <class Executor> void on_error(Executor&, const std::error_code &) const {/*ios.notify_fork(boost::asio::io_context::fork_parent);*/} private: boost::asio::io_context &ios; boost::process::detail::posix::sigchld_service &sigchld_service = boost::asio::use_service<boost::process::detail::posix::sigchld_service>(ios); }; }}}} #endif /* BOOST_PROCESS_WINDOWS_IO_CONTEXT_REF_HPP_ */ PK oM�[��Q) ) detail/posix/null_out.hppnu �[��� // Copyright (c) 2006, 2007 Julio M. Merino Vidal // Copyright (c) 2008 Ilya Sokolov, Boris Schaeling // Copyright (c) 2009 Boris Schaeling // Copyright (c) 2010 Felipe Tanus, Boris Schaeling // Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling // Copyright (c) 2016 Klemens D. Morgenstern // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_PROCESS_POSIX_PIPE_OUT_HPP #define BOOST_PROCESS_POSIX_PIPE_OUT_HPP #include <boost/process/detail/posix/handler.hpp> #include <boost/process/detail/posix/file_descriptor.hpp> #include <boost/process/detail/used_handles.hpp> #include <unistd.h> #include <array> namespace boost { namespace process { namespace detail { namespace posix { template<int p1, int p2> struct null_out : handler_base_ext, ::boost::process::detail::uses_handles { file_descriptor sink{"/dev/null", file_descriptor::write}; template <typename Executor> void on_exec_setup(Executor &e) const; std::array<int, 3> get_used_handles() { const auto pp1 = p1 != -1 ? p1 : p2; const auto pp2 = p2 != -1 ? p2 : p1; return {sink.handle(), pp1, pp2}; } }; template<> template<typename Executor> void null_out<1,-1>::on_exec_setup(Executor &e) const { if (::dup2(sink.handle(), STDOUT_FILENO) == -1) e.set_error(::boost::process::detail::get_last_error(), "dup2() failed"); } template<> template<typename Executor> void null_out<2,-1>::on_exec_setup(Executor &e) const { if (::dup2(sink.handle(), STDERR_FILENO) == -1) e.set_error(::boost::process::detail::get_last_error(), "dup2() failed"); } template<> template<typename Executor> void null_out<1,2>::on_exec_setup(Executor &e) const { if (::dup2(sink.handle(), STDOUT_FILENO) == -1) e.set_error(::boost::process::detail::get_last_error(), "dup2() failed"); if (::dup2(sink.handle(), STDERR_FILENO) == -1) e.set_error(::boost::process::detail::get_last_error(), "dup2() failed"); } }}}} #endif PK oM�[Ye�� detail/posix/basic_pipe.hppnu �[��� // Copyright (c) 2006, 2007 Julio M. Merino Vidal // Copyright (c) 2008 Ilya Sokolov, Boris Schaeling // Copyright (c) 2009 Boris Schaeling // Copyright (c) 2010 Felipe Tanus, Boris Schaeling // Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_PROCESS_POSIX_PIPE_HPP #define BOOST_PROCESS_POSIX_PIPE_HPP #include <boost/filesystem.hpp> #include <boost/process/detail/posix/compare_handles.hpp> #include <system_error> #include <array> #include <unistd.h> #include <fcntl.h> #include <memory> namespace boost { namespace process { namespace detail { namespace posix { template<class CharT, class Traits = std::char_traits<CharT>> class basic_pipe { int _source = -1; int _sink = -1; public: explicit basic_pipe(int source, int sink) : _source(source), _sink(sink) {} explicit basic_pipe(int source, int sink, const std::string&) : _source(source), _sink(sink) {} typedef CharT char_type ; typedef Traits traits_type; typedef typename Traits::int_type int_type ; typedef typename Traits::pos_type pos_type ; typedef typename Traits::off_type off_type ; typedef int native_handle_type; basic_pipe() { int fds[2]; if (::pipe(fds) == -1) boost::process::detail::throw_last_error("pipe(2) failed"); _source = fds[0]; _sink = fds[1]; } inline basic_pipe(const basic_pipe& rhs); explicit inline basic_pipe(const std::string& name); basic_pipe(basic_pipe&& lhs) : _source(lhs._source), _sink(lhs._sink) { lhs._source = -1; lhs._sink = -1; } inline basic_pipe& operator=(const basic_pipe& ); basic_pipe& operator=(basic_pipe&& lhs) { _source = lhs._source; _sink = lhs._sink ; lhs._source = -1; lhs._sink = -1; return *this; } ~basic_pipe() { if (_sink != -1) ::close(_sink); if (_source != -1) ::close(_source); } native_handle_type native_source() const {return _source;} native_handle_type native_sink () const {return _sink;} void assign_source(native_handle_type h) { _source = h;} void assign_sink (native_handle_type h) { _sink = h;} int_type write(const char_type * data, int_type count) { int_type write_len; while ((write_len = ::write(_sink, data, count * sizeof(char_type))) == -1) { //Try again if interrupted auto err = errno; if (err != EINTR) ::boost::process::detail::throw_last_error(); } return write_len; } int_type read(char_type * data, int_type count) { int_type read_len; while ((read_len = ::read(_source, data, count * sizeof(char_type))) == -1) { //Try again if interrupted auto err = errno; if (err != EINTR) ::boost::process::detail::throw_last_error(); } return read_len; } bool is_open() const { return (_source != -1) || (_sink != -1); } void close() { if (_source != -1) ::close(_source); if (_sink != -1) ::close(_sink); _source = -1; _sink = -1; } }; template<class CharT, class Traits> basic_pipe<CharT, Traits>::basic_pipe(const basic_pipe & rhs) { if (rhs._source != -1) { _source = ::dup(rhs._source); if (_source == -1) ::boost::process::detail::throw_last_error("dup() failed"); } if (rhs._sink != -1) { _sink = ::dup(rhs._sink); if (_sink == -1) ::boost::process::detail::throw_last_error("dup() failed"); } } template<class CharT, class Traits> basic_pipe<CharT, Traits> &basic_pipe<CharT, Traits>::operator=(const basic_pipe & rhs) { if (rhs._source != -1) { _source = ::dup(rhs._source); if (_source == -1) ::boost::process::detail::throw_last_error("dup() failed"); } if (rhs._sink != -1) { _sink = ::dup(rhs._sink); if (_sink == -1) ::boost::process::detail::throw_last_error("dup() failed"); } return *this; } template<class CharT, class Traits> basic_pipe<CharT, Traits>::basic_pipe(const std::string & name) { auto fifo = mkfifo(name.c_str(), 0666 ); if (fifo != 0) boost::process::detail::throw_last_error("mkfifo() failed"); int read_fd = open(name.c_str(), O_RDWR); if (read_fd == -1) boost::process::detail::throw_last_error(); int write_fd = dup(read_fd); if (write_fd == -1) boost::process::detail::throw_last_error(); _sink = write_fd; _source = read_fd; ::unlink(name.c_str()); } template<class Char, class Traits> inline bool operator==(const basic_pipe<Char, Traits> & lhs, const basic_pipe<Char, Traits> & rhs) { return compare_handles(lhs.native_source(), rhs.native_source()) && compare_handles(lhs.native_sink(), rhs.native_sink()); } template<class Char, class Traits> inline bool operator!=(const basic_pipe<Char, Traits> & lhs, const basic_pipe<Char, Traits> & rhs) { return !compare_handles(lhs.native_source(), rhs.native_source()) || !compare_handles(lhs.native_sink(), rhs.native_sink()); } }}}} #endif PK oM�[SGi�� � detail/posix/search_path.hppnu �[��� // Copyright (c) 2006, 2007 Julio M. Merino Vidal // Copyright (c) 2008 Ilya Sokolov, Boris Schaeling // Copyright (c) 2009 Boris Schaeling // Copyright (c) 2010 Felipe Tanus, Boris Schaeling // Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_PROCESS_POSIX_SEARCH_PATH_HPP #define BOOST_PROCESS_POSIX_SEARCH_PATH_HPP #include <boost/process/detail/config.hpp> #include <boost/filesystem.hpp> #include <boost/tokenizer.hpp> #include <string> #include <stdexcept> #include <stdlib.h> #include <unistd.h> namespace boost { namespace process { namespace detail { namespace posix { inline boost::filesystem::path search_path( const boost::filesystem::path &filename, const std::vector<boost::filesystem::path> &path) { for (const boost::filesystem::path & pp : path) { auto p = pp / filename; boost::system::error_code ec; bool file = boost::filesystem::is_regular_file(p, ec); if (!ec && file && ::access(p.c_str(), X_OK) == 0) return p; } return ""; } }}}} #endif PK oM�[�1�� � detail/posix/async_out.hppnu �[��� // Copyright (c) 2006, 2007 Julio M. Merino Vidal // Copyright (c) 2008 Ilya Sokolov, Boris Schaeling // Copyright (c) 2009 Boris Schaeling // Copyright (c) 2010 Felipe Tanus, Boris Schaeling // Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_PROCESS_DETAIL_POSIX_ASYNC_OUT_HPP #define BOOST_PROCESS_DETAIL_POSIX_ASYNC_OUT_HPP #include <boost/process/detail/posix/handler.hpp> #include <boost/asio/posix/stream_descriptor.hpp> #include <boost/asio/read.hpp> #include <boost/process/async_pipe.hpp> #include <istream> #include <memory> #include <exception> #include <future> #include <array> #include <boost/process/detail/used_handles.hpp> namespace boost { namespace process { namespace detail { namespace posix { inline int apply_out_handles(int handle, std::integral_constant<int, 1>, std::integral_constant<int, -1>) { return ::dup2(handle, STDOUT_FILENO); } inline int apply_out_handles(int handle, std::integral_constant<int, 2>, std::integral_constant<int, -1>) { return ::dup2(handle, STDERR_FILENO); } inline int apply_out_handles(int handle, std::integral_constant<int, 1>, std::integral_constant<int, 2>) { if (::dup2(handle, STDOUT_FILENO) == -1) return -1; if (::dup2(handle, STDERR_FILENO) == -1) return -1; return 0; } template<int p1, int p2, typename Buffer> struct async_out_buffer : ::boost::process::detail::posix::handler_base_ext, ::boost::process::detail::posix::require_io_context, ::boost::process::detail::uses_handles { Buffer & buf; std::shared_ptr<boost::process::async_pipe> pipe; std::array<int, 4> get_used_handles() { const auto pp1 = p1 != -1 ? p1 : p2; const auto pp2 = p2 != -1 ? p2 : p1; if (pipe) return {pipe->native_source(), pipe->native_sink(), pp1, pp2}; else //if pipe is not constructed, limit_ds is invoked before -> this also means on_exec_setup gets invoked before. return {pp1, pp2, pp1, pp2}; } async_out_buffer(Buffer & buf) : buf(buf) { } template <typename Executor> inline void on_success(Executor &exec) { auto pipe = this->pipe; boost::asio::async_read(*pipe, buf, [pipe](const boost::system::error_code&, std::size_t){}); this->pipe = nullptr; std::move(*pipe).sink().close(); } template<typename Executor> void on_error(Executor &, const std::error_code &) const { std::move(*pipe).sink().close(); } template<typename Executor> void on_setup(Executor & exec) { pipe = std::make_shared<boost::process::async_pipe>(get_io_context(exec.seq)); } template <typename Executor> void on_exec_setup(Executor &exec) { int res = apply_out_handles(pipe->native_sink(), std::integral_constant<int, p1>(), std::integral_constant<int, p2>()); if (res == -1) exec.set_error(::boost::process::detail::get_last_error(), "dup2() failed"); ::close(pipe->native_sink()); ::close(pipe->native_source()); } }; template<int p1, int p2, typename Type> struct async_out_future : ::boost::process::detail::posix::handler_base_ext, ::boost::process::detail::posix::require_io_context { std::shared_ptr<std::promise<Type>> promise = std::make_shared<std::promise<Type>>(); std::shared_ptr<boost::asio::streambuf> buffer = std::make_shared<boost::asio::streambuf>(); std::shared_ptr<boost::process::async_pipe> pipe; async_out_future(std::future<Type> & fut) { fut = promise->get_future(); } template <typename Executor> inline void on_success(Executor &) { auto pipe_ = this->pipe; auto buffer_ = this->buffer; auto promise_ = this->promise; boost::asio::async_read(*pipe_, *buffer_, [pipe_, buffer_, promise_](const boost::system::error_code& ec, std::size_t) { if (ec && (ec.value() != ENOENT)) { std::error_code e(ec.value(), std::system_category()); promise_->set_exception(std::make_exception_ptr(process_error(e))); } else { std::istream is (buffer_.get()); Type arg; if (buffer_->size() > 0) { arg.resize(buffer_->size()); is.read(&*arg.begin(), buffer_->size()); } promise_->set_value(std::move(arg)); } }); std::move(*pipe_).sink().close(); this->pipe = nullptr; } template<typename Executor> void on_error(Executor &, const std::error_code &) const { std::move(*pipe).sink().close(); } template<typename Executor> void on_setup(Executor & exec) { pipe = std::make_shared<boost::process::async_pipe>(get_io_context(exec.seq)); } template <typename Executor> void on_exec_setup(Executor &exec) { int res = apply_out_handles(pipe->native_sink(), std::integral_constant<int, p1>(), std::integral_constant<int, p2>()); if (res == -1) exec.set_error(::boost::process::detail::get_last_error(), "dup2() failed"); ::close(pipe->native_sink()); ::close(pipe->native_source()); } }; }}}} #endif PK oM�[�z�E E detail/posix/start_dir.hppnu �[��� // Copyright (c) 2006, 2007 Julio M. Merino Vidal // Copyright (c) 2008 Ilya Sokolov, Boris Schaeling // Copyright (c) 2009 Boris Schaeling // Copyright (c) 2010 Felipe Tanus, Boris Schaeling // Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_PROCESS_DETAIL_POSIX_START_DIR_HPP #define BOOST_PROCESS_DETAIL_POSIX_START_DIR_HPP #include <boost/process/detail/posix/handler.hpp> #include <string> #include <unistd.h> namespace boost { namespace process { namespace detail { namespace posix { template<typename Char> struct start_dir_init : handler_base_ext { typedef Char value_type; typedef std::basic_string<value_type> string_type; start_dir_init(string_type s) : s_(std::move(s)) {} template <class PosixExecutor> void on_exec_setup(PosixExecutor&) const { ::chdir(s_.c_str()); } const string_type & str() const {return s_;} private: string_type s_; }; }}}} #endif PK oM�[F detail/posix/pipe_out.hppnu �[��� // Copyright (c) 2006, 2007 Julio M. Merino Vidal // Copyright (c) 2008 Ilya Sokolov, Boris Schaeling // Copyright (c) 2009 Boris Schaeling // Copyright (c) 2010 Felipe Tanus, Boris Schaeling // Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling // Copyright (c) 2016 Klemens D. Morgenstern // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_PROCESS_DETAIL_POSIX_PIPE_OUT_HPP #define BOOST_PROCESS_DETAIL_POSIX_PIPE_OUT_HPP #include <boost/process/pipe.hpp> #include <boost/process/detail/posix/handler.hpp> #include <unistd.h> namespace boost { namespace process { namespace detail { namespace posix { template<int p1, int p2> struct pipe_out : handler_base_ext { int sink; int source; //opposite end pipe_out(int sink, int source) : sink(sink), source(source) {} template<typename T> pipe_out(T & p) : sink(p.native_sink()), source(p.native_source()) { p.assign_sink(-1); } template<typename Executor> void on_error(Executor &, const std::error_code &) const { ::close(sink); } template<typename Executor> void on_success(Executor &) const { ::close(sink); } template <typename Executor> void on_exec_setup(Executor &e) const; }; template<> template<typename Executor> void pipe_out<1,-1>::on_exec_setup(Executor &e) const { if (::dup2(sink, STDOUT_FILENO) == -1) e.set_error(::boost::process::detail::get_last_error(), "dup2() failed"); if (sink != STDOUT_FILENO) ::close(sink); ::close(source); } template<> template<typename Executor> void pipe_out<2,-1>::on_exec_setup(Executor &e) const { if (::dup2(sink, STDERR_FILENO) == -1) e.set_error(::boost::process::detail::get_last_error(), "dup2() failed"); if (sink != STDOUT_FILENO) ::close(sink); ::close(source); } template<> template<typename Executor> void pipe_out<1,2>::on_exec_setup(Executor &e) const { if (::dup2(sink, STDOUT_FILENO) == -1) e.set_error(::boost::process::detail::get_last_error(), "dup2() failed"); if (::dup2(sink, STDERR_FILENO) == -1) e.set_error(::boost::process::detail::get_last_error(), "dup2() failed"); if ((sink != STDOUT_FILENO) && (sink != STDERR_FILENO)) ::close(sink); } class async_pipe; template<int p1, int p2> struct async_pipe_out : public pipe_out<p1, p2> { async_pipe &pipe; template<typename AsyncPipe> async_pipe_out(AsyncPipe & p) : pipe_out<p1, p2>(p.native_sink(), p.native_source()), pipe(p) { } template<typename Pipe, typename Executor> static void close(Pipe & pipe, Executor &) { boost::system::error_code ec; std::move(pipe).sink().close(ec); } template<typename Executor> void on_error(Executor & exec, const std::error_code &) { close(pipe, exec); } template<typename Executor> void on_success(Executor &exec) { close(pipe, exec); } }; }}}} #endif PK oM�[n�_ _ detail/posix/wait_group.hppnu �[��� // Copyright (c) 2006, 2007 Julio M. Merino Vidal // Copyright (c) 2008 Ilya Sokolov, Boris Schaeling // Copyright (c) 2009 Boris Schaeling // Copyright (c) 2010 Felipe Tanus, Boris Schaeling // Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_PROCESS_DETAIL_POSIX_WAIT_GROUP_HPP #define BOOST_PROCESS_DETAIL_POSIX_WAIT_GROUP_HPP #include <boost/process/detail/config.hpp> #include <boost/process/detail/posix/group_handle.hpp> #include <chrono> #include <system_error> #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> namespace boost { namespace process { namespace detail { namespace posix { inline void wait(const group_handle &p, std::error_code &ec) noexcept { pid_t ret; siginfo_t status; do { ret = ::waitpid(-p.grp, &status.si_status, 0); if (ret == -1) { ec = get_last_error(); return; } //ECHILD --> no child processes left. ret = ::waitid(P_PGID, p.grp, &status, WEXITED | WNOHANG); } while ((ret != -1) || (errno != ECHILD)); if (errno != ECHILD) ec = boost::process::detail::get_last_error(); else ec.clear(); } inline void wait(const group_handle &p) noexcept { std::error_code ec; wait(p, ec); boost::process::detail::throw_error(ec, "waitpid(2) failed in wait"); } template< class Clock, class Duration > inline bool wait_until( const group_handle &p, const std::chrono::time_point<Clock, Duration>& time_out, std::error_code & ec) noexcept { ::siginfo_t siginfo; bool timed_out = false; int ret; ::timespec sleep_interval; sleep_interval.tv_sec = 0; sleep_interval.tv_nsec = 100000000; while (!(timed_out = (Clock::now() > time_out))) { ret = ::waitid(P_PGID, p.grp, &siginfo, WEXITED | WSTOPPED | WNOHANG); if (ret == -1) { if ((errno == ECHILD) || (errno == ESRCH)) { ec.clear(); return true; } ec = boost::process::detail::get_last_error(); return false; } //we can wait, because unlike in the wait_for_exit, we have no race condition regarding eh exit code. ::nanosleep(&sleep_interval, nullptr); } return !timed_out; } template< class Clock, class Duration > inline bool wait_until( const group_handle &p, const std::chrono::time_point<Clock, Duration>& time_out) noexcept { std::error_code ec; bool b = wait_until(p, time_out, ec); boost::process::detail::throw_error(ec, "waitpid(2) failed in wait_until"); return b; } template< class Rep, class Period > inline bool wait_for( const group_handle &p, const std::chrono::duration<Rep, Period>& rel_time, std::error_code & ec) noexcept { return wait_until(p, std::chrono::steady_clock::now() + rel_time, ec); } template< class Rep, class Period > inline bool wait_for( const group_handle &p, const std::chrono::duration<Rep, Period>& rel_time) noexcept { std::error_code ec; bool b = wait_for(p, rel_time, ec); boost::process::detail::throw_error(ec, "waitpid(2) failed in wait_for"); return b; } }}}} #endif PK oM�[�z�� detail/posix/close_in.hppnu �[��� // Copyright (c) 2006, 2007 Julio M. Merino Vidal // Copyright (c) 2008 Ilya Sokolov, Boris Schaeling // Copyright (c) 2009 Boris Schaeling // Copyright (c) 2010 Felipe Tanus, Boris Schaeling // Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_CLOSE_IN_HPP #define BOOST_PROCESS_WINDOWS_INITIALIZERS_CLOSE_IN_HPP #include <boost/process/detail/posix/handler.hpp> #include <boost/process/detail/used_handles.hpp> namespace boost { namespace process { namespace detail { namespace posix { struct close_in : handler_base_ext, ::boost::process::detail::uses_handles { template <class Executor> void on_exec_setup(Executor &e) const { if (::close(STDIN_FILENO) == -1) e.set_error(::boost::process::detail::get_last_error(), "close() failed"); } int get_used_handles() {return STDIN_FILENO;} }; }}}} #endif PK oM�[6�Y% detail/posix/null_in.hppnu �[��� // Copyright (c) 2006, 2007 Julio M. Merino Vidal // Copyright (c) 2008 Ilya Sokolov, Boris Schaeling // Copyright (c) 2009 Boris Schaeling // Copyright (c) 2010 Felipe Tanus, Boris Schaeling // Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_PROCESS_DETAIL_POSIX_NULL_IN_HPP #define BOOST_PROCESS_DETAIL_POSIX_NULL_IN_HPP #include <boost/process/pipe.hpp> #include <boost/process/detail/posix/handler.hpp> #include <boost/process/detail/posix/file_descriptor.hpp> #include <unistd.h> #include <boost/process/detail/used_handles.hpp> #include <array> namespace boost { namespace process { namespace detail { namespace posix { struct null_in : handler_base_ext, ::boost::process::detail::uses_handles { file_descriptor source{"/dev/null", file_descriptor::read}; std::array<int, 2> get_used_handles() { return {{STDIN_FILENO, source.handle()}}; } public: template <class Executor> void on_exec_setup(Executor &e) const { if (::dup2(source.handle(), STDIN_FILENO) == -1) e.set_error(::boost::process::detail::get_last_error(), "dup2() failed"); } }; }}}} #endif PK oM�[Ҵ� detail/posix/compare_handles.hppnu �[��� // Copyright (c) 2016 Klemens D. Morgenstern // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_PROCESS_DETAIL_POSIX_COMPARE_HANDLES_HPP_ #define BOOST_PROCESS_DETAIL_POSIX_COMPARE_HANDLES_HPP_ #include <boost/process/detail/config.hpp> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> namespace boost { namespace process { namespace detail { namespace posix { inline bool compare_handles(int lhs, int rhs) { if ((lhs == -1) || (rhs == -1)) return false; if (lhs == rhs) return true; struct stat stat1, stat2; if(fstat(lhs, &stat1) < 0) ::boost::process::detail::throw_last_error("fstat() failed"); if(fstat(rhs, &stat2) < 0) ::boost::process::detail::throw_last_error("fstat() failed"); return (stat1.st_dev == stat2.st_dev) && (stat1.st_ino == stat2.st_ino); } }}}} #endif /* BOOST_PROCESS_DETAIL_POSIX_COMPARE_HANDLES_HPP_ */ PK oM�[��EG G detail/posix/pipe_in.hppnu �[��� // Copyright (c) 2006, 2007 Julio M. Merino Vidal // Copyright (c) 2008 Ilya Sokolov, Boris Schaeling // Copyright (c) 2009 Boris Schaeling // Copyright (c) 2010 Felipe Tanus, Boris Schaeling // Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_PROCESS_POSIX_PIPE_IN_HPP #define BOOST_PROCESS_POSIX_PIPE_IN_HPP #include <boost/process/pipe.hpp> #include <boost/process/detail/posix/handler.hpp> #include <unistd.h> #include <boost/process/detail/used_handles.hpp> #include <array> namespace boost { namespace process { namespace detail { namespace posix { struct pipe_in : handler_base_ext, ::boost::process::detail::uses_handles { int source; int sink; //opposite end pipe_in(int sink, int source) : source(source), sink(sink) {} std::array<int, 3> get_used_handles() { return {{STDIN_FILENO, source, sink}}; } template<typename T> pipe_in(T & p) : source(p.native_source()), sink(p.native_sink()) { p.assign_source(-1); } template<typename Executor> void on_error(Executor &, const std::error_code &) const { ::close(source); } template<typename Executor> void on_success(Executor &) const { ::close(source); } template <class Executor> void on_exec_setup(Executor &e) const { if (::dup2(source, STDIN_FILENO) == -1) e.set_error(::boost::process::detail::get_last_error(), "dup2() failed"); if (source != STDIN_FILENO) ::close(source); ::close(sink); } }; class async_pipe; struct async_pipe_in : public pipe_in { async_pipe &pipe; template<typename AsyncPipe> async_pipe_in(AsyncPipe & p) : pipe_in(p.native_sink(), p.native_source()), pipe(p) { } template<typename Pipe, typename Executor> static void close(Pipe & pipe, Executor &) { boost::system::error_code ec; std::move(pipe).source().close(ec); } template<typename Executor> void on_error(Executor & exec, const std::error_code &) { close(pipe, exec); } template<typename Executor> void on_success(Executor &exec) { close(pipe, exec); } }; }}}} #endif PK oM�[����� � detail/posix/handler.hppnu �[��� // Copyright (c) 2016 Klemens D. Morgenstern // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_PROCESS_DETAIL_POSIX_HANDLER_HPP_ #define BOOST_PROCESS_DETAIL_POSIX_HANDLER_HPP_ #include <boost/process/detail/handler_base.hpp> namespace boost { namespace process { namespace detail { namespace posix { //does not extend anything. struct handler_base_ext : handler_base { template<typename Executor> void on_fork_error (Executor &, const std::error_code&) const {} template<typename Executor> void on_exec_setup (Executor &) const {} template<typename Executor> void on_exec_error (Executor &, const std::error_code&) const {} }; template <class Handler> struct on_fork_error_ : handler_base_ext { explicit on_fork_error_(Handler handler) : handler_(handler) {} template <class Executor> void on_fork_error(Executor &e, const std::error_code &ec) const { handler_(e, ec); } private: Handler handler_; }; template <class Handler> struct on_exec_setup_ : handler_base_ext { explicit on_exec_setup_(Handler handler) : handler_(handler) {} template <class Executor> void on_exec_setup(Executor &e) const { handler_(e); } private: Handler handler_; }; template <class Handler> struct on_exec_error_ : handler_base_ext { explicit on_exec_error_(Handler handler) : handler_(handler) {} template <class Executor> void on_exec_error(Executor &e, const std::error_code &ec) const { handler_(e, ec); } private: Handler handler_; }; }}}} #endif /* BOOST_PROCESS_DETAIL_POSIX_HANDLER_HPP_ */ PK oM�[tn��&