1240116Smarcel// 2240116Smarcel// Automated Testing Framework (atf) 3240116Smarcel// 4240116Smarcel// Copyright (c) 2008 The NetBSD Foundation, Inc. 5240116Smarcel// All rights reserved. 6240116Smarcel// 7240116Smarcel// Redistribution and use in source and binary forms, with or without 8240116Smarcel// modification, are permitted provided that the following conditions 9240116Smarcel// are met: 10240116Smarcel// 1. Redistributions of source code must retain the above copyright 11240116Smarcel// notice, this list of conditions and the following disclaimer. 12240116Smarcel// 2. Redistributions in binary form must reproduce the above copyright 13240116Smarcel// notice, this list of conditions and the following disclaimer in the 14240116Smarcel// documentation and/or other materials provided with the distribution. 15240116Smarcel// 16240116Smarcel// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND 17240116Smarcel// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 18240116Smarcel// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19240116Smarcel// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20240116Smarcel// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY 21240116Smarcel// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22240116Smarcel// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 23240116Smarcel// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24240116Smarcel// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25240116Smarcel// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 26240116Smarcel// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 27240116Smarcel// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28240116Smarcel// 29240116Smarcel 30240116Smarcel#if !defined(_ATF_CXX_PROCESS_HPP_) 31240116Smarcel#define _ATF_CXX_PROCESS_HPP_ 32240116Smarcel 33240116Smarcelextern "C" { 34240116Smarcel#include <sys/types.h> 35240116Smarcel 36240116Smarcel#include "../../atf-c/error.h" 37240116Smarcel 38240116Smarcel#include "../../atf-c/detail/process.h" 39240116Smarcel} 40240116Smarcel 41240116Smarcel#include <string> 42240116Smarcel#include <vector> 43240116Smarcel 44260029Sjmmv#include "auto_array.hpp" 45240116Smarcel#include "exceptions.hpp" 46240116Smarcel#include "fs.hpp" 47240116Smarcel 48240116Smarcelnamespace atf { 49240116Smarcelnamespace process { 50240116Smarcel 51240116Smarcelclass child; 52240116Smarcelclass status; 53240116Smarcel 54240116Smarcel// ------------------------------------------------------------------------ 55240116Smarcel// The "argv_array" type. 56240116Smarcel// ------------------------------------------------------------------------ 57240116Smarcel 58240116Smarcelclass argv_array { 59240116Smarcel typedef std::vector< std::string > args_vector; 60240116Smarcel args_vector m_args; 61240116Smarcel 62240116Smarcel // TODO: This is immutable, so we should be able to use 63240116Smarcel // std::tr1::shared_array instead when it becomes widely available. 64240116Smarcel // The reason would be to remove all copy constructors and assignment 65240116Smarcel // operators from this class. 66260029Sjmmv auto_array< const char* > m_exec_argv; 67240116Smarcel void ctor_init_exec_argv(void); 68240116Smarcel 69240116Smarcelpublic: 70240116Smarcel typedef args_vector::const_iterator const_iterator; 71240116Smarcel typedef args_vector::size_type size_type; 72240116Smarcel 73240116Smarcel argv_array(void); 74240116Smarcel argv_array(const char*, ...); 75240116Smarcel explicit argv_array(const char* const*); 76240116Smarcel template< class C > explicit argv_array(const C&); 77240116Smarcel argv_array(const argv_array&); 78240116Smarcel 79240116Smarcel const char* const* exec_argv(void) const; 80240116Smarcel size_type size(void) const; 81240116Smarcel const char* operator[](int) const; 82240116Smarcel 83240116Smarcel const_iterator begin(void) const; 84240116Smarcel const_iterator end(void) const; 85240116Smarcel 86240116Smarcel argv_array& operator=(const argv_array&); 87240116Smarcel}; 88240116Smarcel 89240116Smarceltemplate< class C > 90240116Smarcelargv_array::argv_array(const C& c) 91240116Smarcel{ 92240116Smarcel for (typename C::const_iterator iter = c.begin(); iter != c.end(); 93240116Smarcel iter++) 94240116Smarcel m_args.push_back(*iter); 95240116Smarcel ctor_init_exec_argv(); 96240116Smarcel} 97240116Smarcel 98240116Smarcel// ------------------------------------------------------------------------ 99240116Smarcel// The "stream" types. 100240116Smarcel// ------------------------------------------------------------------------ 101240116Smarcel 102240116Smarcelclass basic_stream { 103240116Smarcelprotected: 104240116Smarcel atf_process_stream_t m_sb; 105240116Smarcel bool m_inited; 106240116Smarcel 107240116Smarcel const atf_process_stream_t* get_sb(void) const; 108240116Smarcel 109240116Smarcelpublic: 110240116Smarcel basic_stream(void); 111240116Smarcel ~basic_stream(void); 112240116Smarcel}; 113240116Smarcel 114240116Smarcelclass stream_capture : basic_stream { 115240116Smarcel // Allow access to the getters. 116240116Smarcel template< class OutStream, class ErrStream > friend 117240116Smarcel child fork(void (*)(void*), const OutStream&, const ErrStream&, void*); 118240116Smarcel template< class OutStream, class ErrStream > friend 119240116Smarcel status exec(const atf::fs::path&, const argv_array&, 120240116Smarcel const OutStream&, const ErrStream&, void (*)(void)); 121240116Smarcel 122240116Smarcelpublic: 123240116Smarcel stream_capture(void); 124240116Smarcel}; 125240116Smarcel 126240116Smarcelclass stream_connect : basic_stream { 127240116Smarcel // Allow access to the getters. 128240116Smarcel template< class OutStream, class ErrStream > friend 129240116Smarcel child fork(void (*)(void*), const OutStream&, const ErrStream&, void*); 130240116Smarcel template< class OutStream, class ErrStream > friend 131240116Smarcel status exec(const atf::fs::path&, const argv_array&, 132240116Smarcel const OutStream&, const ErrStream&, void (*)(void)); 133240116Smarcel 134240116Smarcelpublic: 135240116Smarcel stream_connect(const int, const int); 136240116Smarcel}; 137240116Smarcel 138240116Smarcelclass stream_inherit : basic_stream { 139240116Smarcel // Allow access to the getters. 140240116Smarcel template< class OutStream, class ErrStream > friend 141240116Smarcel child fork(void (*)(void*), const OutStream&, const ErrStream&, void*); 142240116Smarcel template< class OutStream, class ErrStream > friend 143240116Smarcel status exec(const atf::fs::path&, const argv_array&, 144240116Smarcel const OutStream&, const ErrStream&, void (*)(void)); 145240116Smarcel 146240116Smarcelpublic: 147240116Smarcel stream_inherit(void); 148240116Smarcel}; 149240116Smarcel 150240116Smarcelclass stream_redirect_fd : basic_stream { 151240116Smarcel // Allow access to the getters. 152240116Smarcel template< class OutStream, class ErrStream > friend 153240116Smarcel child fork(void (*)(void*), const OutStream&, const ErrStream&, void*); 154240116Smarcel template< class OutStream, class ErrStream > friend 155240116Smarcel status exec(const atf::fs::path&, const argv_array&, 156240116Smarcel const OutStream&, const ErrStream&, void (*)(void)); 157240116Smarcel 158240116Smarcelpublic: 159240116Smarcel stream_redirect_fd(const int); 160240116Smarcel}; 161240116Smarcel 162240116Smarcelclass stream_redirect_path : basic_stream { 163240116Smarcel // Allow access to the getters. 164240116Smarcel template< class OutStream, class ErrStream > friend 165240116Smarcel child fork(void (*)(void*), const OutStream&, const ErrStream&, void*); 166240116Smarcel template< class OutStream, class ErrStream > friend 167240116Smarcel status exec(const atf::fs::path&, const argv_array&, 168240116Smarcel const OutStream&, const ErrStream&, void (*)(void)); 169240116Smarcel 170240116Smarcelpublic: 171240116Smarcel stream_redirect_path(const fs::path&); 172240116Smarcel}; 173240116Smarcel 174240116Smarcel// ------------------------------------------------------------------------ 175240116Smarcel// The "status" type. 176240116Smarcel// ------------------------------------------------------------------------ 177240116Smarcel 178240116Smarcelclass status { 179240116Smarcel atf_process_status_t m_status; 180240116Smarcel 181240116Smarcel friend class child; 182240116Smarcel template< class OutStream, class ErrStream > friend 183240116Smarcel status exec(const atf::fs::path&, const argv_array&, 184240116Smarcel const OutStream&, const ErrStream&, void (*)(void)); 185240116Smarcel 186240116Smarcel status(atf_process_status_t&); 187240116Smarcel 188240116Smarcelpublic: 189240116Smarcel ~status(void); 190240116Smarcel 191240116Smarcel bool exited(void) const; 192240116Smarcel int exitstatus(void) const; 193240116Smarcel 194240116Smarcel bool signaled(void) const; 195240116Smarcel int termsig(void) const; 196240116Smarcel bool coredump(void) const; 197240116Smarcel}; 198240116Smarcel 199240116Smarcel// ------------------------------------------------------------------------ 200240116Smarcel// The "child" type. 201240116Smarcel// ------------------------------------------------------------------------ 202240116Smarcel 203240116Smarcelclass child { 204240116Smarcel atf_process_child_t m_child; 205240116Smarcel bool m_waited; 206240116Smarcel 207240116Smarcel template< class OutStream, class ErrStream > friend 208240116Smarcel child fork(void (*)(void*), const OutStream&, const ErrStream&, void*); 209240116Smarcel 210240116Smarcel child(atf_process_child_t& c); 211240116Smarcel 212240116Smarcelpublic: 213240116Smarcel ~child(void); 214240116Smarcel 215240116Smarcel status wait(void); 216240116Smarcel 217240116Smarcel pid_t pid(void) const; 218240116Smarcel int stdout_fd(void); 219240116Smarcel int stderr_fd(void); 220240116Smarcel}; 221240116Smarcel 222240116Smarcel// ------------------------------------------------------------------------ 223240116Smarcel// Free functions. 224240116Smarcel// ------------------------------------------------------------------------ 225240116Smarcel 226240116Smarcelnamespace detail { 227240116Smarcelvoid flush_streams(void); 228240116Smarcel} // namespace detail 229240116Smarcel 230240116Smarcel// TODO: The void* cookie can probably be templatized, thus also allowing 231240116Smarcel// const data structures. 232240116Smarceltemplate< class OutStream, class ErrStream > 233240116Smarcelchild 234240116Smarcelfork(void (*start)(void*), const OutStream& outsb, 235240116Smarcel const ErrStream& errsb, void* v) 236240116Smarcel{ 237240116Smarcel atf_process_child_t c; 238240116Smarcel 239240116Smarcel detail::flush_streams(); 240240116Smarcel atf_error_t err = atf_process_fork(&c, start, outsb.get_sb(), 241240116Smarcel errsb.get_sb(), v); 242240116Smarcel if (atf_is_error(err)) 243240116Smarcel throw_atf_error(err); 244240116Smarcel 245240116Smarcel return child(c); 246240116Smarcel} 247240116Smarcel 248240116Smarceltemplate< class OutStream, class ErrStream > 249240116Smarcelstatus 250240116Smarcelexec(const atf::fs::path& prog, const argv_array& argv, 251240116Smarcel const OutStream& outsb, const ErrStream& errsb, 252240116Smarcel void (*prehook)(void)) 253240116Smarcel{ 254240116Smarcel atf_process_status_t s; 255240116Smarcel 256240116Smarcel detail::flush_streams(); 257240116Smarcel atf_error_t err = atf_process_exec_array(&s, prog.c_path(), 258240116Smarcel argv.exec_argv(), 259240116Smarcel outsb.get_sb(), 260240116Smarcel errsb.get_sb(), 261240116Smarcel prehook); 262240116Smarcel if (atf_is_error(err)) 263240116Smarcel throw_atf_error(err); 264240116Smarcel 265240116Smarcel return status(s); 266240116Smarcel} 267240116Smarcel 268240116Smarceltemplate< class OutStream, class ErrStream > 269240116Smarcelstatus 270240116Smarcelexec(const atf::fs::path& prog, const argv_array& argv, 271240116Smarcel const OutStream& outsb, const ErrStream& errsb) 272240116Smarcel{ 273240116Smarcel return exec(prog, argv, outsb, errsb, NULL); 274240116Smarcel} 275240116Smarcel 276240116Smarcel} // namespace process 277240116Smarcel} // namespace atf 278240116Smarcel 279240116Smarcel#endif // !defined(_ATF_CXX_PROCESS_HPP_) 280