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