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