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