1 // Copyright (c) 2006, 2007 Julio M. Merino Vidal
2 // Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
3 // Copyright (c) 2009 Boris Schaeling
4 // Copyright (c) 2010 Felipe Tanus, Boris Schaeling
5 // Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
6 // Copyright (c) 2016 Klemens D. Morgenstern
7 //
8 // Distributed under the Boost Software License, Version 1.0. (See accompanying
9 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
10 
11 #ifndef BOOST_PROCESS_DETAIL_ERROR_HPP
12 #define BOOST_PROCESS_DETAIL_ERROR_HPP
13 
14 #include <boost/process/detail/config.hpp>
15 #include <boost/process/detail/traits.hpp>
16 
17 
18 #if defined(BOOST_POSIX_API)
19 #include <boost/process/detail/posix/handler.hpp>
20 #elif defined(BOOST_WINDOWS_API)
21 #include <boost/process/detail/windows/handler.hpp>
22 #endif
23 
24 #include <system_error>
25 
26 #include <type_traits>
27 #include <boost/fusion/algorithm/query/find_if.hpp>
28 #include <boost/fusion/sequence/intrinsic/begin.hpp>
29 #include <boost/fusion/sequence/intrinsic/end.hpp>
30 #include <boost/fusion/container/vector/convert.hpp>
31 #include <boost/fusion/iterator/deref.hpp>
32 #include <boost/fusion/sequence/comparison/equal_to.hpp>
33 #include <boost/fusion/container/set/convert.hpp>
34 #include <boost/type_index.hpp>
35 
36 /** \file boost/process/error.hpp
37  *
38  *    Header which provides the error properties. It allows to explicitly set the error handling, the properties are:
39  *
40 \xmlonly
41 <programlisting>
42 namespace boost {
43   namespace process {
44     <emphasis>unspecified</emphasis> <globalname alt="boost::process::ignore_error">ignore_error</globalname>;
45     <emphasis>unspecified</emphasis> <globalname alt="boost::process::throw_on_error">throw_on_error</globalname>;
46     <emphasis>unspecified</emphasis> <globalname alt="boost::process::error">error</globalname>;
47     <emphasis>unspecified</emphasis> <globalname alt="boost::process::error_ref">error_ref</globalname>;
48     <emphasis>unspecified</emphasis> <globalname alt="boost::process::error_code">error_code</globalname>;
49   }
50 }
51 </programlisting>
52 \endxmlonly
53  *     For error there are two aliases: error_ref and error_code
54  */
55 
56 namespace boost { namespace process {
57 
58 namespace detail {
59 
60 struct throw_on_error_ : ::boost::process::detail::api::handler_base_ext
61 {
62     constexpr throw_on_error_() = default;
63 
64     template <class Executor>
on_errorboost::process::detail::throw_on_error_65     void on_error(Executor&, const std::error_code & ec) const
66     {
67         throw process_error(ec, "process creation failed");
68     }
69 
operator ()boost::process::detail::throw_on_error_70     const throw_on_error_ &operator()() const {return *this;}
71 };
72 
73 struct ignore_error_ : ::boost::process::detail::api::handler_base_ext
74 {
75     constexpr ignore_error_() = default;
76 };
77 
78 struct set_on_error : ::boost::process::detail::api::handler_base_ext
79 {
80     set_on_error(const set_on_error&) = default;
set_on_errorboost::process::detail::set_on_error81     explicit set_on_error(std::error_code &ec) : ec_(ec) {}
82 
83     template <class Executor>
on_errorboost::process::detail::set_on_error84     void on_error(Executor&, const std::error_code & ec) const noexcept
85     {
86         ec_ = ec;
87     }
88 
89 private:
90     std::error_code &ec_;
91 };
92 
93 struct error_
94 {
95     constexpr error_() = default;
operator ()boost::process::detail::error_96     set_on_error operator()(std::error_code &ec) const {return set_on_error(ec);}
operator =boost::process::detail::error_97     set_on_error operator= (std::error_code &ec) const {return set_on_error(ec);}
98 
99 };
100 
101 
102 template<typename T>
103 struct is_error_handler : std::false_type {};
104 
105 template<> struct is_error_handler<set_on_error>    : std::true_type {};
106 template<> struct is_error_handler<throw_on_error_> : std::true_type {};
107 template<> struct is_error_handler<ignore_error_>   : std::true_type {};
108 
109 
110 
111 template<typename Iterator, typename End>
112 struct has_error_handler_impl
113 {
114     typedef typename boost::fusion::result_of::deref<Iterator>::type ref_type;
115     typedef typename std::remove_reference<ref_type>::type res_type_;
116     typedef typename std::remove_cv<res_type_>::type res_type;
117     typedef typename is_error_handler<res_type>::type cond;
118 
119     typedef typename boost::fusion::result_of::next<Iterator>::type next_itr;
120     typedef typename has_error_handler_impl<next_itr, End>::type next;
121 
122     typedef typename boost::mpl::or_<cond, next>::type type;
123 };
124 
125 template<typename Iterator>
126 struct has_error_handler_impl<Iterator, Iterator>
127 {
128     typedef boost::mpl::false_ type;
129 };
130 
131 
132 template<typename Sequence>
133 struct has_error_handler
134 {
135     typedef typename boost::fusion::result_of::as_vector<Sequence>::type vector_type;
136 
137     typedef typename has_error_handler_impl<
138             typename boost::fusion::result_of::begin<vector_type>::type,
139             typename boost::fusion::result_of::end<  vector_type>::type
140             >::type type;
141 };
142 
143 template<typename Sequence>
144 struct has_ignore_error
145 {
146     typedef typename boost::fusion::result_of::as_set<Sequence>::type set_type;
147     typedef typename boost::fusion::result_of::has_key<set_type, ignore_error_>::type  type1;
148     typedef typename boost::fusion::result_of::has_key<set_type, ignore_error_&>::type type2;
149     typedef typename boost::fusion::result_of::has_key<set_type, const ignore_error_&>::type type3;
150     typedef typename boost::mpl::or_<type1,type2, type3>::type type;
151 };
152 
153 struct error_builder
154 {
155     std::error_code *err;
156     typedef set_on_error result_type;
get_initializerboost::process::detail::error_builder157     set_on_error get_initializer() {return set_on_error(*err);};
operator ()boost::process::detail::error_builder158     void operator()(std::error_code & ec) {err = &ec;};
159 };
160 
161 template<>
162 struct initializer_tag<std::error_code>
163 {
164     typedef error_tag type;
165 };
166 
167 
168 template<>
169 struct initializer_builder<error_tag>
170 {
171     typedef error_builder type;
172 };
173 
174 }
175 /**The ignore_error property will disable any error handling. This can be useful
176 on linux, where error handling will require a pipe.*/
177 constexpr boost::process::detail::ignore_error_ ignore_error;
178 /**The throw_on_error property will enable the exception when launching a process.
179 It is unnecessary by default, but may be used, when an additional error_code is provided.*/
180 constexpr boost::process::detail::throw_on_error_ throw_on_error;
181 /**
182 The error property will set the executor to handle any errors by setting an
183 [std::error_code](http://en.cppreference.com/w/cpp/error/error_code).
184 
185 \code{.cpp}
186 std::error_code ec;
187 system("gcc", error(ec));
188 \endcode
189 
190 The following syntax is valid:
191 
192 \code{.cpp}
193 error(ec);
194 error=ec;
195 \endcode
196 
197 The overload version is achieved by just passing an object of
198  [std::error_code](http://en.cppreference.com/w/cpp/error/error_code) to the function.
199 
200 
201  */
202 constexpr boost::process::detail::error_ error;
203 ///Alias for \xmlonly <globalname alt="boost::process::error">error</globalname> \endxmlonly .
204 constexpr boost::process::detail::error_ error_ref;
205 ///Alias for \xmlonly <globalname alt="boost::process::error">error</globalname> \endxmlonly .
206 constexpr boost::process::detail::error_ error_code;
207 
208 
209 }}
210 
211 #endif
212