1*11be35a1SLionel Sambuc //
2*11be35a1SLionel Sambuc // Automated Testing Framework (atf)
3*11be35a1SLionel Sambuc //
4*11be35a1SLionel Sambuc // Copyright (c) 2008 The NetBSD Foundation, Inc.
5*11be35a1SLionel Sambuc // All rights reserved.
6*11be35a1SLionel Sambuc //
7*11be35a1SLionel Sambuc // Redistribution and use in source and binary forms, with or without
8*11be35a1SLionel Sambuc // modification, are permitted provided that the following conditions
9*11be35a1SLionel Sambuc // are met:
10*11be35a1SLionel Sambuc // 1. Redistributions of source code must retain the above copyright
11*11be35a1SLionel Sambuc // notice, this list of conditions and the following disclaimer.
12*11be35a1SLionel Sambuc // 2. Redistributions in binary form must reproduce the above copyright
13*11be35a1SLionel Sambuc // notice, this list of conditions and the following disclaimer in the
14*11be35a1SLionel Sambuc // documentation and/or other materials provided with the distribution.
15*11be35a1SLionel Sambuc //
16*11be35a1SLionel Sambuc // THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
17*11be35a1SLionel Sambuc // CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
18*11be35a1SLionel Sambuc // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19*11be35a1SLionel Sambuc // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20*11be35a1SLionel Sambuc // IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
21*11be35a1SLionel Sambuc // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22*11be35a1SLionel Sambuc // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23*11be35a1SLionel Sambuc // GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24*11be35a1SLionel Sambuc // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25*11be35a1SLionel Sambuc // IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26*11be35a1SLionel Sambuc // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27*11be35a1SLionel Sambuc // IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*11be35a1SLionel Sambuc //
29*11be35a1SLionel Sambuc
30*11be35a1SLionel Sambuc #if !defined(_ATF_CXX_PROCESS_HPP_)
31*11be35a1SLionel Sambuc #define _ATF_CXX_PROCESS_HPP_
32*11be35a1SLionel Sambuc
33*11be35a1SLionel Sambuc extern "C" {
34*11be35a1SLionel Sambuc #include <sys/types.h>
35*11be35a1SLionel Sambuc
36*11be35a1SLionel Sambuc #include "../../atf-c/error.h"
37*11be35a1SLionel Sambuc
38*11be35a1SLionel Sambuc #include "../../atf-c/detail/process.h"
39*11be35a1SLionel Sambuc }
40*11be35a1SLionel Sambuc
41*11be35a1SLionel Sambuc #include <string>
42*11be35a1SLionel Sambuc #include <vector>
43*11be35a1SLionel Sambuc
44*11be35a1SLionel Sambuc #include "auto_array.hpp"
45*11be35a1SLionel Sambuc #include "exceptions.hpp"
46*11be35a1SLionel Sambuc #include "fs.hpp"
47*11be35a1SLionel Sambuc
48*11be35a1SLionel Sambuc namespace atf {
49*11be35a1SLionel Sambuc namespace process {
50*11be35a1SLionel Sambuc
51*11be35a1SLionel Sambuc class child;
52*11be35a1SLionel Sambuc class status;
53*11be35a1SLionel Sambuc
54*11be35a1SLionel Sambuc // ------------------------------------------------------------------------
55*11be35a1SLionel Sambuc // The "argv_array" type.
56*11be35a1SLionel Sambuc // ------------------------------------------------------------------------
57*11be35a1SLionel Sambuc
58*11be35a1SLionel Sambuc class argv_array {
59*11be35a1SLionel Sambuc typedef std::vector< std::string > args_vector;
60*11be35a1SLionel Sambuc args_vector m_args;
61*11be35a1SLionel Sambuc
62*11be35a1SLionel Sambuc // TODO: This is immutable, so we should be able to use
63*11be35a1SLionel Sambuc // std::tr1::shared_array instead when it becomes widely available.
64*11be35a1SLionel Sambuc // The reason would be to remove all copy constructors and assignment
65*11be35a1SLionel Sambuc // operators from this class.
66*11be35a1SLionel Sambuc auto_array< const char* > m_exec_argv;
67*11be35a1SLionel Sambuc void ctor_init_exec_argv(void);
68*11be35a1SLionel Sambuc
69*11be35a1SLionel Sambuc public:
70*11be35a1SLionel Sambuc typedef args_vector::const_iterator const_iterator;
71*11be35a1SLionel Sambuc typedef args_vector::size_type size_type;
72*11be35a1SLionel Sambuc
73*11be35a1SLionel Sambuc argv_array(void);
74*11be35a1SLionel Sambuc argv_array(const char*, ...);
75*11be35a1SLionel Sambuc explicit argv_array(const char* const*);
76*11be35a1SLionel Sambuc template< class C > explicit argv_array(const C&);
77*11be35a1SLionel Sambuc argv_array(const argv_array&);
78*11be35a1SLionel Sambuc
79*11be35a1SLionel Sambuc const char* const* exec_argv(void) const;
80*11be35a1SLionel Sambuc size_type size(void) const;
81*11be35a1SLionel Sambuc const char* operator[](int) const;
82*11be35a1SLionel Sambuc
83*11be35a1SLionel Sambuc const_iterator begin(void) const;
84*11be35a1SLionel Sambuc const_iterator end(void) const;
85*11be35a1SLionel Sambuc
86*11be35a1SLionel Sambuc argv_array& operator=(const argv_array&);
87*11be35a1SLionel Sambuc };
88*11be35a1SLionel Sambuc
89*11be35a1SLionel Sambuc template< class C >
argv_array(const C & c)90*11be35a1SLionel Sambuc argv_array::argv_array(const C& c)
91*11be35a1SLionel Sambuc {
92*11be35a1SLionel Sambuc for (typename C::const_iterator iter = c.begin(); iter != c.end();
93*11be35a1SLionel Sambuc iter++)
94*11be35a1SLionel Sambuc m_args.push_back(*iter);
95*11be35a1SLionel Sambuc ctor_init_exec_argv();
96*11be35a1SLionel Sambuc }
97*11be35a1SLionel Sambuc
98*11be35a1SLionel Sambuc // ------------------------------------------------------------------------
99*11be35a1SLionel Sambuc // The "stream" types.
100*11be35a1SLionel Sambuc // ------------------------------------------------------------------------
101*11be35a1SLionel Sambuc
102*11be35a1SLionel Sambuc class basic_stream {
103*11be35a1SLionel Sambuc protected:
104*11be35a1SLionel Sambuc atf_process_stream_t m_sb;
105*11be35a1SLionel Sambuc bool m_inited;
106*11be35a1SLionel Sambuc
107*11be35a1SLionel Sambuc const atf_process_stream_t* get_sb(void) const;
108*11be35a1SLionel Sambuc
109*11be35a1SLionel Sambuc public:
110*11be35a1SLionel Sambuc basic_stream(void);
111*11be35a1SLionel Sambuc ~basic_stream(void);
112*11be35a1SLionel Sambuc };
113*11be35a1SLionel Sambuc
114*11be35a1SLionel Sambuc class stream_capture : basic_stream {
115*11be35a1SLionel Sambuc // Allow access to the getters.
116*11be35a1SLionel Sambuc template< class OutStream, class ErrStream > friend
117*11be35a1SLionel Sambuc child fork(void (*)(void*), const OutStream&, const ErrStream&, void*);
118*11be35a1SLionel Sambuc template< class OutStream, class ErrStream > friend
119*11be35a1SLionel Sambuc status exec(const atf::fs::path&, const argv_array&,
120*11be35a1SLionel Sambuc const OutStream&, const ErrStream&, void (*)(void));
121*11be35a1SLionel Sambuc
122*11be35a1SLionel Sambuc public:
123*11be35a1SLionel Sambuc stream_capture(void);
124*11be35a1SLionel Sambuc };
125*11be35a1SLionel Sambuc
126*11be35a1SLionel Sambuc class stream_connect : basic_stream {
127*11be35a1SLionel Sambuc // Allow access to the getters.
128*11be35a1SLionel Sambuc template< class OutStream, class ErrStream > friend
129*11be35a1SLionel Sambuc child fork(void (*)(void*), const OutStream&, const ErrStream&, void*);
130*11be35a1SLionel Sambuc template< class OutStream, class ErrStream > friend
131*11be35a1SLionel Sambuc status exec(const atf::fs::path&, const argv_array&,
132*11be35a1SLionel Sambuc const OutStream&, const ErrStream&, void (*)(void));
133*11be35a1SLionel Sambuc
134*11be35a1SLionel Sambuc public:
135*11be35a1SLionel Sambuc stream_connect(const int, const int);
136*11be35a1SLionel Sambuc };
137*11be35a1SLionel Sambuc
138*11be35a1SLionel Sambuc class stream_inherit : basic_stream {
139*11be35a1SLionel Sambuc // Allow access to the getters.
140*11be35a1SLionel Sambuc template< class OutStream, class ErrStream > friend
141*11be35a1SLionel Sambuc child fork(void (*)(void*), const OutStream&, const ErrStream&, void*);
142*11be35a1SLionel Sambuc template< class OutStream, class ErrStream > friend
143*11be35a1SLionel Sambuc status exec(const atf::fs::path&, const argv_array&,
144*11be35a1SLionel Sambuc const OutStream&, const ErrStream&, void (*)(void));
145*11be35a1SLionel Sambuc
146*11be35a1SLionel Sambuc public:
147*11be35a1SLionel Sambuc stream_inherit(void);
148*11be35a1SLionel Sambuc };
149*11be35a1SLionel Sambuc
150*11be35a1SLionel Sambuc class stream_redirect_fd : basic_stream {
151*11be35a1SLionel Sambuc // Allow access to the getters.
152*11be35a1SLionel Sambuc template< class OutStream, class ErrStream > friend
153*11be35a1SLionel Sambuc child fork(void (*)(void*), const OutStream&, const ErrStream&, void*);
154*11be35a1SLionel Sambuc template< class OutStream, class ErrStream > friend
155*11be35a1SLionel Sambuc status exec(const atf::fs::path&, const argv_array&,
156*11be35a1SLionel Sambuc const OutStream&, const ErrStream&, void (*)(void));
157*11be35a1SLionel Sambuc
158*11be35a1SLionel Sambuc public:
159*11be35a1SLionel Sambuc stream_redirect_fd(const int);
160*11be35a1SLionel Sambuc };
161*11be35a1SLionel Sambuc
162*11be35a1SLionel Sambuc class stream_redirect_path : basic_stream {
163*11be35a1SLionel Sambuc // Allow access to the getters.
164*11be35a1SLionel Sambuc template< class OutStream, class ErrStream > friend
165*11be35a1SLionel Sambuc child fork(void (*)(void*), const OutStream&, const ErrStream&, void*);
166*11be35a1SLionel Sambuc template< class OutStream, class ErrStream > friend
167*11be35a1SLionel Sambuc status exec(const atf::fs::path&, const argv_array&,
168*11be35a1SLionel Sambuc const OutStream&, const ErrStream&, void (*)(void));
169*11be35a1SLionel Sambuc
170*11be35a1SLionel Sambuc public:
171*11be35a1SLionel Sambuc stream_redirect_path(const fs::path&);
172*11be35a1SLionel Sambuc };
173*11be35a1SLionel Sambuc
174*11be35a1SLionel Sambuc // ------------------------------------------------------------------------
175*11be35a1SLionel Sambuc // The "status" type.
176*11be35a1SLionel Sambuc // ------------------------------------------------------------------------
177*11be35a1SLionel Sambuc
178*11be35a1SLionel Sambuc class status {
179*11be35a1SLionel Sambuc atf_process_status_t m_status;
180*11be35a1SLionel Sambuc
181*11be35a1SLionel Sambuc friend class child;
182*11be35a1SLionel Sambuc template< class OutStream, class ErrStream > friend
183*11be35a1SLionel Sambuc status exec(const atf::fs::path&, const argv_array&,
184*11be35a1SLionel Sambuc const OutStream&, const ErrStream&, void (*)(void));
185*11be35a1SLionel Sambuc
186*11be35a1SLionel Sambuc status(atf_process_status_t&);
187*11be35a1SLionel Sambuc
188*11be35a1SLionel Sambuc public:
189*11be35a1SLionel Sambuc ~status(void);
190*11be35a1SLionel Sambuc
191*11be35a1SLionel Sambuc bool exited(void) const;
192*11be35a1SLionel Sambuc int exitstatus(void) const;
193*11be35a1SLionel Sambuc
194*11be35a1SLionel Sambuc bool signaled(void) const;
195*11be35a1SLionel Sambuc int termsig(void) const;
196*11be35a1SLionel Sambuc bool coredump(void) const;
197*11be35a1SLionel Sambuc };
198*11be35a1SLionel Sambuc
199*11be35a1SLionel Sambuc // ------------------------------------------------------------------------
200*11be35a1SLionel Sambuc // The "child" type.
201*11be35a1SLionel Sambuc // ------------------------------------------------------------------------
202*11be35a1SLionel Sambuc
203*11be35a1SLionel Sambuc class child {
204*11be35a1SLionel Sambuc atf_process_child_t m_child;
205*11be35a1SLionel Sambuc bool m_waited;
206*11be35a1SLionel Sambuc
207*11be35a1SLionel Sambuc template< class OutStream, class ErrStream > friend
208*11be35a1SLionel Sambuc child fork(void (*)(void*), const OutStream&, const ErrStream&, void*);
209*11be35a1SLionel Sambuc
210*11be35a1SLionel Sambuc child(atf_process_child_t& c);
211*11be35a1SLionel Sambuc
212*11be35a1SLionel Sambuc public:
213*11be35a1SLionel Sambuc ~child(void);
214*11be35a1SLionel Sambuc
215*11be35a1SLionel Sambuc status wait(void);
216*11be35a1SLionel Sambuc
217*11be35a1SLionel Sambuc pid_t pid(void) const;
218*11be35a1SLionel Sambuc int stdout_fd(void);
219*11be35a1SLionel Sambuc int stderr_fd(void);
220*11be35a1SLionel Sambuc };
221*11be35a1SLionel Sambuc
222*11be35a1SLionel Sambuc // ------------------------------------------------------------------------
223*11be35a1SLionel Sambuc // Free functions.
224*11be35a1SLionel Sambuc // ------------------------------------------------------------------------
225*11be35a1SLionel Sambuc
226*11be35a1SLionel Sambuc namespace detail {
227*11be35a1SLionel Sambuc void flush_streams(void);
228*11be35a1SLionel Sambuc } // namespace detail
229*11be35a1SLionel Sambuc
230*11be35a1SLionel Sambuc // TODO: The void* cookie can probably be templatized, thus also allowing
231*11be35a1SLionel Sambuc // const data structures.
232*11be35a1SLionel Sambuc template< class OutStream, class ErrStream >
233*11be35a1SLionel Sambuc child
fork(void (* start)(void *),const OutStream & outsb,const ErrStream & errsb,void * v)234*11be35a1SLionel Sambuc fork(void (*start)(void*), const OutStream& outsb,
235*11be35a1SLionel Sambuc const ErrStream& errsb, void* v)
236*11be35a1SLionel Sambuc {
237*11be35a1SLionel Sambuc atf_process_child_t c;
238*11be35a1SLionel Sambuc
239*11be35a1SLionel Sambuc detail::flush_streams();
240*11be35a1SLionel Sambuc atf_error_t err = atf_process_fork(&c, start, outsb.get_sb(),
241*11be35a1SLionel Sambuc errsb.get_sb(), v);
242*11be35a1SLionel Sambuc if (atf_is_error(err))
243*11be35a1SLionel Sambuc throw_atf_error(err);
244*11be35a1SLionel Sambuc
245*11be35a1SLionel Sambuc return child(c);
246*11be35a1SLionel Sambuc }
247*11be35a1SLionel Sambuc
248*11be35a1SLionel Sambuc template< class OutStream, class ErrStream >
249*11be35a1SLionel Sambuc status
exec(const atf::fs::path & prog,const argv_array & argv,const OutStream & outsb,const ErrStream & errsb,void (* prehook)(void))250*11be35a1SLionel Sambuc exec(const atf::fs::path& prog, const argv_array& argv,
251*11be35a1SLionel Sambuc const OutStream& outsb, const ErrStream& errsb,
252*11be35a1SLionel Sambuc void (*prehook)(void))
253*11be35a1SLionel Sambuc {
254*11be35a1SLionel Sambuc atf_process_status_t s;
255*11be35a1SLionel Sambuc
256*11be35a1SLionel Sambuc detail::flush_streams();
257*11be35a1SLionel Sambuc atf_error_t err = atf_process_exec_array(&s, prog.c_path(),
258*11be35a1SLionel Sambuc argv.exec_argv(),
259*11be35a1SLionel Sambuc outsb.get_sb(),
260*11be35a1SLionel Sambuc errsb.get_sb(),
261*11be35a1SLionel Sambuc prehook);
262*11be35a1SLionel Sambuc if (atf_is_error(err))
263*11be35a1SLionel Sambuc throw_atf_error(err);
264*11be35a1SLionel Sambuc
265*11be35a1SLionel Sambuc return status(s);
266*11be35a1SLionel Sambuc }
267*11be35a1SLionel Sambuc
268*11be35a1SLionel Sambuc template< class OutStream, class ErrStream >
269*11be35a1SLionel Sambuc status
exec(const atf::fs::path & prog,const argv_array & argv,const OutStream & outsb,const ErrStream & errsb)270*11be35a1SLionel Sambuc exec(const atf::fs::path& prog, const argv_array& argv,
271*11be35a1SLionel Sambuc const OutStream& outsb, const ErrStream& errsb)
272*11be35a1SLionel Sambuc {
273*11be35a1SLionel Sambuc return exec(prog, argv, outsb, errsb, NULL);
274*11be35a1SLionel Sambuc }
275*11be35a1SLionel Sambuc
276*11be35a1SLionel Sambuc } // namespace process
277*11be35a1SLionel Sambuc } // namespace atf
278*11be35a1SLionel Sambuc
279*11be35a1SLionel Sambuc #endif // !defined(_ATF_CXX_PROCESS_HPP_)
280