1*00b67f09SDavid van Moolenbroek //
2*00b67f09SDavid van Moolenbroek // Automated Testing Framework (atf)
3*00b67f09SDavid van Moolenbroek //
4*00b67f09SDavid van Moolenbroek // Copyright (c) 2008 The NetBSD Foundation, Inc.
5*00b67f09SDavid van Moolenbroek // All rights reserved.
6*00b67f09SDavid van Moolenbroek //
7*00b67f09SDavid van Moolenbroek // Redistribution and use in source and binary forms, with or without
8*00b67f09SDavid van Moolenbroek // modification, are permitted provided that the following conditions
9*00b67f09SDavid van Moolenbroek // are met:
10*00b67f09SDavid van Moolenbroek // 1. Redistributions of source code must retain the above copyright
11*00b67f09SDavid van Moolenbroek // notice, this list of conditions and the following disclaimer.
12*00b67f09SDavid van Moolenbroek // 2. Redistributions in binary form must reproduce the above copyright
13*00b67f09SDavid van Moolenbroek // notice, this list of conditions and the following disclaimer in the
14*00b67f09SDavid van Moolenbroek // documentation and/or other materials provided with the distribution.
15*00b67f09SDavid van Moolenbroek //
16*00b67f09SDavid van Moolenbroek // THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
17*00b67f09SDavid van Moolenbroek // CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
18*00b67f09SDavid van Moolenbroek // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19*00b67f09SDavid van Moolenbroek // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20*00b67f09SDavid van Moolenbroek // IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
21*00b67f09SDavid van Moolenbroek // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22*00b67f09SDavid van Moolenbroek // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23*00b67f09SDavid van Moolenbroek // GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24*00b67f09SDavid van Moolenbroek // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25*00b67f09SDavid van Moolenbroek // IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26*00b67f09SDavid van Moolenbroek // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27*00b67f09SDavid van Moolenbroek // IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*00b67f09SDavid van Moolenbroek //
29*00b67f09SDavid van Moolenbroek
30*00b67f09SDavid van Moolenbroek extern "C" {
31*00b67f09SDavid van Moolenbroek #include <signal.h>
32*00b67f09SDavid van Moolenbroek
33*00b67f09SDavid van Moolenbroek #include "../../atf-c/error.h"
34*00b67f09SDavid van Moolenbroek
35*00b67f09SDavid van Moolenbroek #include "../../atf-c/detail/process.h"
36*00b67f09SDavid van Moolenbroek }
37*00b67f09SDavid van Moolenbroek
38*00b67f09SDavid van Moolenbroek #include <iostream>
39*00b67f09SDavid van Moolenbroek
40*00b67f09SDavid van Moolenbroek #include "exceptions.hpp"
41*00b67f09SDavid van Moolenbroek #include "process.hpp"
42*00b67f09SDavid van Moolenbroek #include "sanity.hpp"
43*00b67f09SDavid van Moolenbroek
44*00b67f09SDavid van Moolenbroek namespace detail = atf::process::detail;
45*00b67f09SDavid van Moolenbroek namespace impl = atf::process;
46*00b67f09SDavid van Moolenbroek #define IMPL_NAME "atf::process"
47*00b67f09SDavid van Moolenbroek
48*00b67f09SDavid van Moolenbroek // ------------------------------------------------------------------------
49*00b67f09SDavid van Moolenbroek // Auxiliary functions.
50*00b67f09SDavid van Moolenbroek // ------------------------------------------------------------------------
51*00b67f09SDavid van Moolenbroek
52*00b67f09SDavid van Moolenbroek template< class C >
53*00b67f09SDavid van Moolenbroek atf::auto_array< const char* >
collection_to_argv(const C & c)54*00b67f09SDavid van Moolenbroek collection_to_argv(const C& c)
55*00b67f09SDavid van Moolenbroek {
56*00b67f09SDavid van Moolenbroek atf::auto_array< const char* > argv(new const char*[c.size() + 1]);
57*00b67f09SDavid van Moolenbroek
58*00b67f09SDavid van Moolenbroek std::size_t pos = 0;
59*00b67f09SDavid van Moolenbroek for (typename C::const_iterator iter = c.begin(); iter != c.end();
60*00b67f09SDavid van Moolenbroek iter++) {
61*00b67f09SDavid van Moolenbroek argv[pos] = (*iter).c_str();
62*00b67f09SDavid van Moolenbroek pos++;
63*00b67f09SDavid van Moolenbroek }
64*00b67f09SDavid van Moolenbroek INV(pos == c.size());
65*00b67f09SDavid van Moolenbroek argv[pos] = NULL;
66*00b67f09SDavid van Moolenbroek
67*00b67f09SDavid van Moolenbroek return argv;
68*00b67f09SDavid van Moolenbroek }
69*00b67f09SDavid van Moolenbroek
70*00b67f09SDavid van Moolenbroek template< class C >
71*00b67f09SDavid van Moolenbroek C
argv_to_collection(const char * const * argv)72*00b67f09SDavid van Moolenbroek argv_to_collection(const char* const* argv)
73*00b67f09SDavid van Moolenbroek {
74*00b67f09SDavid van Moolenbroek C c;
75*00b67f09SDavid van Moolenbroek
76*00b67f09SDavid van Moolenbroek for (const char* const* iter = argv; *iter != NULL; iter++)
77*00b67f09SDavid van Moolenbroek c.push_back(std::string(*iter));
78*00b67f09SDavid van Moolenbroek
79*00b67f09SDavid van Moolenbroek return c;
80*00b67f09SDavid van Moolenbroek }
81*00b67f09SDavid van Moolenbroek
82*00b67f09SDavid van Moolenbroek // ------------------------------------------------------------------------
83*00b67f09SDavid van Moolenbroek // The "argv_array" type.
84*00b67f09SDavid van Moolenbroek // ------------------------------------------------------------------------
85*00b67f09SDavid van Moolenbroek
argv_array(void)86*00b67f09SDavid van Moolenbroek impl::argv_array::argv_array(void) :
87*00b67f09SDavid van Moolenbroek m_exec_argv(collection_to_argv(m_args))
88*00b67f09SDavid van Moolenbroek {
89*00b67f09SDavid van Moolenbroek }
90*00b67f09SDavid van Moolenbroek
argv_array(const char * arg1,...)91*00b67f09SDavid van Moolenbroek impl::argv_array::argv_array(const char* arg1, ...)
92*00b67f09SDavid van Moolenbroek {
93*00b67f09SDavid van Moolenbroek m_args.push_back(arg1);
94*00b67f09SDavid van Moolenbroek
95*00b67f09SDavid van Moolenbroek {
96*00b67f09SDavid van Moolenbroek va_list ap;
97*00b67f09SDavid van Moolenbroek const char* nextarg;
98*00b67f09SDavid van Moolenbroek
99*00b67f09SDavid van Moolenbroek va_start(ap, arg1);
100*00b67f09SDavid van Moolenbroek while ((nextarg = va_arg(ap, const char*)) != NULL)
101*00b67f09SDavid van Moolenbroek m_args.push_back(nextarg);
102*00b67f09SDavid van Moolenbroek va_end(ap);
103*00b67f09SDavid van Moolenbroek }
104*00b67f09SDavid van Moolenbroek
105*00b67f09SDavid van Moolenbroek ctor_init_exec_argv();
106*00b67f09SDavid van Moolenbroek }
107*00b67f09SDavid van Moolenbroek
argv_array(const char * const * ca)108*00b67f09SDavid van Moolenbroek impl::argv_array::argv_array(const char* const* ca) :
109*00b67f09SDavid van Moolenbroek m_args(argv_to_collection< args_vector >(ca)),
110*00b67f09SDavid van Moolenbroek m_exec_argv(collection_to_argv(m_args))
111*00b67f09SDavid van Moolenbroek {
112*00b67f09SDavid van Moolenbroek }
113*00b67f09SDavid van Moolenbroek
argv_array(const argv_array & a)114*00b67f09SDavid van Moolenbroek impl::argv_array::argv_array(const argv_array& a) :
115*00b67f09SDavid van Moolenbroek m_args(a.m_args),
116*00b67f09SDavid van Moolenbroek m_exec_argv(collection_to_argv(m_args))
117*00b67f09SDavid van Moolenbroek {
118*00b67f09SDavid van Moolenbroek }
119*00b67f09SDavid van Moolenbroek
120*00b67f09SDavid van Moolenbroek void
ctor_init_exec_argv(void)121*00b67f09SDavid van Moolenbroek impl::argv_array::ctor_init_exec_argv(void)
122*00b67f09SDavid van Moolenbroek {
123*00b67f09SDavid van Moolenbroek m_exec_argv = collection_to_argv(m_args);
124*00b67f09SDavid van Moolenbroek }
125*00b67f09SDavid van Moolenbroek
126*00b67f09SDavid van Moolenbroek const char* const*
exec_argv(void) const127*00b67f09SDavid van Moolenbroek impl::argv_array::exec_argv(void)
128*00b67f09SDavid van Moolenbroek const
129*00b67f09SDavid van Moolenbroek {
130*00b67f09SDavid van Moolenbroek return m_exec_argv.get();
131*00b67f09SDavid van Moolenbroek }
132*00b67f09SDavid van Moolenbroek
133*00b67f09SDavid van Moolenbroek impl::argv_array::size_type
size(void) const134*00b67f09SDavid van Moolenbroek impl::argv_array::size(void)
135*00b67f09SDavid van Moolenbroek const
136*00b67f09SDavid van Moolenbroek {
137*00b67f09SDavid van Moolenbroek return m_args.size();
138*00b67f09SDavid van Moolenbroek }
139*00b67f09SDavid van Moolenbroek
140*00b67f09SDavid van Moolenbroek const char*
operator [](int idx) const141*00b67f09SDavid van Moolenbroek impl::argv_array::operator[](int idx)
142*00b67f09SDavid van Moolenbroek const
143*00b67f09SDavid van Moolenbroek {
144*00b67f09SDavid van Moolenbroek return m_args[idx].c_str();
145*00b67f09SDavid van Moolenbroek }
146*00b67f09SDavid van Moolenbroek
147*00b67f09SDavid van Moolenbroek impl::argv_array::const_iterator
begin(void) const148*00b67f09SDavid van Moolenbroek impl::argv_array::begin(void)
149*00b67f09SDavid van Moolenbroek const
150*00b67f09SDavid van Moolenbroek {
151*00b67f09SDavid van Moolenbroek return m_args.begin();
152*00b67f09SDavid van Moolenbroek }
153*00b67f09SDavid van Moolenbroek
154*00b67f09SDavid van Moolenbroek impl::argv_array::const_iterator
end(void) const155*00b67f09SDavid van Moolenbroek impl::argv_array::end(void)
156*00b67f09SDavid van Moolenbroek const
157*00b67f09SDavid van Moolenbroek {
158*00b67f09SDavid van Moolenbroek return m_args.end();
159*00b67f09SDavid van Moolenbroek }
160*00b67f09SDavid van Moolenbroek
161*00b67f09SDavid van Moolenbroek impl::argv_array&
operator =(const argv_array & a)162*00b67f09SDavid van Moolenbroek impl::argv_array::operator=(const argv_array& a)
163*00b67f09SDavid van Moolenbroek {
164*00b67f09SDavid van Moolenbroek if (this != &a) {
165*00b67f09SDavid van Moolenbroek m_args = a.m_args;
166*00b67f09SDavid van Moolenbroek m_exec_argv = collection_to_argv(m_args);
167*00b67f09SDavid van Moolenbroek }
168*00b67f09SDavid van Moolenbroek return *this;
169*00b67f09SDavid van Moolenbroek }
170*00b67f09SDavid van Moolenbroek
171*00b67f09SDavid van Moolenbroek // ------------------------------------------------------------------------
172*00b67f09SDavid van Moolenbroek // The "stream" types.
173*00b67f09SDavid van Moolenbroek // ------------------------------------------------------------------------
174*00b67f09SDavid van Moolenbroek
basic_stream(void)175*00b67f09SDavid van Moolenbroek impl::basic_stream::basic_stream(void) :
176*00b67f09SDavid van Moolenbroek m_inited(false)
177*00b67f09SDavid van Moolenbroek {
178*00b67f09SDavid van Moolenbroek }
179*00b67f09SDavid van Moolenbroek
~basic_stream(void)180*00b67f09SDavid van Moolenbroek impl::basic_stream::~basic_stream(void)
181*00b67f09SDavid van Moolenbroek {
182*00b67f09SDavid van Moolenbroek if (m_inited)
183*00b67f09SDavid van Moolenbroek atf_process_stream_fini(&m_sb);
184*00b67f09SDavid van Moolenbroek }
185*00b67f09SDavid van Moolenbroek
186*00b67f09SDavid van Moolenbroek const atf_process_stream_t*
get_sb(void) const187*00b67f09SDavid van Moolenbroek impl::basic_stream::get_sb(void)
188*00b67f09SDavid van Moolenbroek const
189*00b67f09SDavid van Moolenbroek {
190*00b67f09SDavid van Moolenbroek INV(m_inited);
191*00b67f09SDavid van Moolenbroek return &m_sb;
192*00b67f09SDavid van Moolenbroek }
193*00b67f09SDavid van Moolenbroek
stream_capture(void)194*00b67f09SDavid van Moolenbroek impl::stream_capture::stream_capture(void)
195*00b67f09SDavid van Moolenbroek {
196*00b67f09SDavid van Moolenbroek atf_error_t err = atf_process_stream_init_capture(&m_sb);
197*00b67f09SDavid van Moolenbroek if (atf_is_error(err))
198*00b67f09SDavid van Moolenbroek throw_atf_error(err);
199*00b67f09SDavid van Moolenbroek m_inited = true;
200*00b67f09SDavid van Moolenbroek }
201*00b67f09SDavid van Moolenbroek
stream_connect(const int src_fd,const int tgt_fd)202*00b67f09SDavid van Moolenbroek impl::stream_connect::stream_connect(const int src_fd, const int tgt_fd)
203*00b67f09SDavid van Moolenbroek {
204*00b67f09SDavid van Moolenbroek atf_error_t err = atf_process_stream_init_connect(&m_sb, src_fd, tgt_fd);
205*00b67f09SDavid van Moolenbroek if (atf_is_error(err))
206*00b67f09SDavid van Moolenbroek throw_atf_error(err);
207*00b67f09SDavid van Moolenbroek m_inited = true;
208*00b67f09SDavid van Moolenbroek }
209*00b67f09SDavid van Moolenbroek
stream_inherit(void)210*00b67f09SDavid van Moolenbroek impl::stream_inherit::stream_inherit(void)
211*00b67f09SDavid van Moolenbroek {
212*00b67f09SDavid van Moolenbroek atf_error_t err = atf_process_stream_init_inherit(&m_sb);
213*00b67f09SDavid van Moolenbroek if (atf_is_error(err))
214*00b67f09SDavid van Moolenbroek throw_atf_error(err);
215*00b67f09SDavid van Moolenbroek m_inited = true;
216*00b67f09SDavid van Moolenbroek }
217*00b67f09SDavid van Moolenbroek
stream_redirect_fd(const int fd)218*00b67f09SDavid van Moolenbroek impl::stream_redirect_fd::stream_redirect_fd(const int fd)
219*00b67f09SDavid van Moolenbroek {
220*00b67f09SDavid van Moolenbroek atf_error_t err = atf_process_stream_init_redirect_fd(&m_sb, fd);
221*00b67f09SDavid van Moolenbroek if (atf_is_error(err))
222*00b67f09SDavid van Moolenbroek throw_atf_error(err);
223*00b67f09SDavid van Moolenbroek m_inited = true;
224*00b67f09SDavid van Moolenbroek }
225*00b67f09SDavid van Moolenbroek
stream_redirect_path(const fs::path & p)226*00b67f09SDavid van Moolenbroek impl::stream_redirect_path::stream_redirect_path(const fs::path& p)
227*00b67f09SDavid van Moolenbroek {
228*00b67f09SDavid van Moolenbroek atf_error_t err = atf_process_stream_init_redirect_path(&m_sb, p.c_path());
229*00b67f09SDavid van Moolenbroek if (atf_is_error(err))
230*00b67f09SDavid van Moolenbroek throw_atf_error(err);
231*00b67f09SDavid van Moolenbroek m_inited = true;
232*00b67f09SDavid van Moolenbroek }
233*00b67f09SDavid van Moolenbroek
234*00b67f09SDavid van Moolenbroek // ------------------------------------------------------------------------
235*00b67f09SDavid van Moolenbroek // The "status" type.
236*00b67f09SDavid van Moolenbroek // ------------------------------------------------------------------------
237*00b67f09SDavid van Moolenbroek
status(atf_process_status_t & s)238*00b67f09SDavid van Moolenbroek impl::status::status(atf_process_status_t& s) :
239*00b67f09SDavid van Moolenbroek m_status(s)
240*00b67f09SDavid van Moolenbroek {
241*00b67f09SDavid van Moolenbroek }
242*00b67f09SDavid van Moolenbroek
~status(void)243*00b67f09SDavid van Moolenbroek impl::status::~status(void)
244*00b67f09SDavid van Moolenbroek {
245*00b67f09SDavid van Moolenbroek atf_process_status_fini(&m_status);
246*00b67f09SDavid van Moolenbroek }
247*00b67f09SDavid van Moolenbroek
248*00b67f09SDavid van Moolenbroek bool
exited(void) const249*00b67f09SDavid van Moolenbroek impl::status::exited(void)
250*00b67f09SDavid van Moolenbroek const
251*00b67f09SDavid van Moolenbroek {
252*00b67f09SDavid van Moolenbroek return atf_process_status_exited(&m_status);
253*00b67f09SDavid van Moolenbroek }
254*00b67f09SDavid van Moolenbroek
255*00b67f09SDavid van Moolenbroek int
exitstatus(void) const256*00b67f09SDavid van Moolenbroek impl::status::exitstatus(void)
257*00b67f09SDavid van Moolenbroek const
258*00b67f09SDavid van Moolenbroek {
259*00b67f09SDavid van Moolenbroek return atf_process_status_exitstatus(&m_status);
260*00b67f09SDavid van Moolenbroek }
261*00b67f09SDavid van Moolenbroek
262*00b67f09SDavid van Moolenbroek bool
signaled(void) const263*00b67f09SDavid van Moolenbroek impl::status::signaled(void)
264*00b67f09SDavid van Moolenbroek const
265*00b67f09SDavid van Moolenbroek {
266*00b67f09SDavid van Moolenbroek return atf_process_status_signaled(&m_status);
267*00b67f09SDavid van Moolenbroek }
268*00b67f09SDavid van Moolenbroek
269*00b67f09SDavid van Moolenbroek int
termsig(void) const270*00b67f09SDavid van Moolenbroek impl::status::termsig(void)
271*00b67f09SDavid van Moolenbroek const
272*00b67f09SDavid van Moolenbroek {
273*00b67f09SDavid van Moolenbroek return atf_process_status_termsig(&m_status);
274*00b67f09SDavid van Moolenbroek }
275*00b67f09SDavid van Moolenbroek
276*00b67f09SDavid van Moolenbroek bool
coredump(void) const277*00b67f09SDavid van Moolenbroek impl::status::coredump(void)
278*00b67f09SDavid van Moolenbroek const
279*00b67f09SDavid van Moolenbroek {
280*00b67f09SDavid van Moolenbroek return atf_process_status_coredump(&m_status);
281*00b67f09SDavid van Moolenbroek }
282*00b67f09SDavid van Moolenbroek
283*00b67f09SDavid van Moolenbroek // ------------------------------------------------------------------------
284*00b67f09SDavid van Moolenbroek // The "child" type.
285*00b67f09SDavid van Moolenbroek // ------------------------------------------------------------------------
286*00b67f09SDavid van Moolenbroek
child(atf_process_child_t & c)287*00b67f09SDavid van Moolenbroek impl::child::child(atf_process_child_t& c) :
288*00b67f09SDavid van Moolenbroek m_child(c),
289*00b67f09SDavid van Moolenbroek m_waited(false)
290*00b67f09SDavid van Moolenbroek {
291*00b67f09SDavid van Moolenbroek }
292*00b67f09SDavid van Moolenbroek
~child(void)293*00b67f09SDavid van Moolenbroek impl::child::~child(void)
294*00b67f09SDavid van Moolenbroek {
295*00b67f09SDavid van Moolenbroek if (!m_waited) {
296*00b67f09SDavid van Moolenbroek ::kill(atf_process_child_pid(&m_child), SIGTERM);
297*00b67f09SDavid van Moolenbroek
298*00b67f09SDavid van Moolenbroek atf_process_status_t s;
299*00b67f09SDavid van Moolenbroek atf_error_t err = atf_process_child_wait(&m_child, &s);
300*00b67f09SDavid van Moolenbroek INV(!atf_is_error(err));
301*00b67f09SDavid van Moolenbroek atf_process_status_fini(&s);
302*00b67f09SDavid van Moolenbroek }
303*00b67f09SDavid van Moolenbroek }
304*00b67f09SDavid van Moolenbroek
305*00b67f09SDavid van Moolenbroek impl::status
wait(void)306*00b67f09SDavid van Moolenbroek impl::child::wait(void)
307*00b67f09SDavid van Moolenbroek {
308*00b67f09SDavid van Moolenbroek atf_process_status_t s;
309*00b67f09SDavid van Moolenbroek
310*00b67f09SDavid van Moolenbroek atf_error_t err = atf_process_child_wait(&m_child, &s);
311*00b67f09SDavid van Moolenbroek if (atf_is_error(err))
312*00b67f09SDavid van Moolenbroek throw_atf_error(err);
313*00b67f09SDavid van Moolenbroek
314*00b67f09SDavid van Moolenbroek m_waited = true;
315*00b67f09SDavid van Moolenbroek return status(s);
316*00b67f09SDavid van Moolenbroek }
317*00b67f09SDavid van Moolenbroek
318*00b67f09SDavid van Moolenbroek pid_t
pid(void) const319*00b67f09SDavid van Moolenbroek impl::child::pid(void)
320*00b67f09SDavid van Moolenbroek const
321*00b67f09SDavid van Moolenbroek {
322*00b67f09SDavid van Moolenbroek return atf_process_child_pid(&m_child);
323*00b67f09SDavid van Moolenbroek }
324*00b67f09SDavid van Moolenbroek
325*00b67f09SDavid van Moolenbroek int
stdout_fd(void)326*00b67f09SDavid van Moolenbroek impl::child::stdout_fd(void)
327*00b67f09SDavid van Moolenbroek {
328*00b67f09SDavid van Moolenbroek return atf_process_child_stdout(&m_child);
329*00b67f09SDavid van Moolenbroek }
330*00b67f09SDavid van Moolenbroek
331*00b67f09SDavid van Moolenbroek int
stderr_fd(void)332*00b67f09SDavid van Moolenbroek impl::child::stderr_fd(void)
333*00b67f09SDavid van Moolenbroek {
334*00b67f09SDavid van Moolenbroek return atf_process_child_stderr(&m_child);
335*00b67f09SDavid van Moolenbroek }
336*00b67f09SDavid van Moolenbroek
337*00b67f09SDavid van Moolenbroek // ------------------------------------------------------------------------
338*00b67f09SDavid van Moolenbroek // Free functions.
339*00b67f09SDavid van Moolenbroek // ------------------------------------------------------------------------
340*00b67f09SDavid van Moolenbroek
341*00b67f09SDavid van Moolenbroek void
flush_streams(void)342*00b67f09SDavid van Moolenbroek detail::flush_streams(void)
343*00b67f09SDavid van Moolenbroek {
344*00b67f09SDavid van Moolenbroek // This is a weird hack to ensure that the output of the parent process
345*00b67f09SDavid van Moolenbroek // is flushed before executing a child which prevents, for example, the
346*00b67f09SDavid van Moolenbroek // output of the atf-run hooks to appear before the output of atf-run
347*00b67f09SDavid van Moolenbroek // itself.
348*00b67f09SDavid van Moolenbroek //
349*00b67f09SDavid van Moolenbroek // TODO: This should only be executed when inheriting the stdout or
350*00b67f09SDavid van Moolenbroek // stderr file descriptors. However, the flushing is specific to the
351*00b67f09SDavid van Moolenbroek // iostreams, so we cannot do it from the C library where all the process
352*00b67f09SDavid van Moolenbroek // logic is performed. Come up with a better design.
353*00b67f09SDavid van Moolenbroek std::cout.flush();
354*00b67f09SDavid van Moolenbroek std::cerr.flush();
355*00b67f09SDavid van Moolenbroek }
356