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 44240116Smarcel#include "exceptions.hpp" 45240116Smarcel#include "fs.hpp" 46240116Smarcel 47240116Smarcel#include "../utils.hpp" 48240116Smarcel 49240116Smarcelnamespace atf { 50240116Smarcelnamespace process { 51240116Smarcel 52240116Smarcelclass child; 53240116Smarcelclass status; 54240116Smarcel 55240116Smarcel// ------------------------------------------------------------------------ 56240116Smarcel// The "argv_array" type. 57240116Smarcel// ------------------------------------------------------------------------ 58240116Smarcel 59240116Smarcelclass argv_array { 60240116Smarcel typedef std::vector< std::string > args_vector; 61240116Smarcel args_vector m_args; 62240116Smarcel 63240116Smarcel // TODO: This is immutable, so we should be able to use 64240116Smarcel // std::tr1::shared_array instead when it becomes widely available. 65240116Smarcel // The reason would be to remove all copy constructors and assignment 66240116Smarcel // operators from this class. 67240116Smarcel utils::auto_array< const char* > m_exec_argv; 68240116Smarcel void ctor_init_exec_argv(void); 69240116Smarcel 70240116Smarcelpublic: 71240116Smarcel typedef args_vector::const_iterator const_iterator; 72240116Smarcel typedef args_vector::size_type size_type; 73240116Smarcel 74240116Smarcel argv_array(void); 75240116Smarcel argv_array(const char*, ...); 76240116Smarcel explicit argv_array(const char* const*); 77240116Smarcel template< class C > explicit argv_array(const C&); 78240116Smarcel argv_array(const argv_array&); 79240116Smarcel 80240116Smarcel const char* const* exec_argv(void) const; 81240116Smarcel size_type size(void) const; 82240116Smarcel const char* operator[](int) const; 83240116Smarcel 84240116Smarcel const_iterator begin(void) const; 85240116Smarcel const_iterator end(void) const; 86240116Smarcel 87240116Smarcel argv_array& operator=(const argv_array&); 88240116Smarcel}; 89240116Smarcel 90240116Smarceltemplate< class C > 91240116Smarcelargv_array::argv_array(const C& c) 92240116Smarcel{ 93240116Smarcel for (typename C::const_iterator iter = c.begin(); iter != c.end(); 94240116Smarcel iter++) 95240116Smarcel m_args.push_back(*iter); 96240116Smarcel ctor_init_exec_argv(); 97240116Smarcel} 98240116Smarcel 99240116Smarcel// ------------------------------------------------------------------------ 100240116Smarcel// The "stream" types. 101240116Smarcel// ------------------------------------------------------------------------ 102240116Smarcel 103240116Smarcelclass basic_stream { 104240116Smarcelprotected: 105240116Smarcel atf_process_stream_t m_sb; 106240116Smarcel bool m_inited; 107240116Smarcel 108240116Smarcel const atf_process_stream_t* get_sb(void) const; 109240116Smarcel 110240116Smarcelpublic: 111240116Smarcel basic_stream(void); 112240116Smarcel ~basic_stream(void); 113240116Smarcel}; 114240116Smarcel 115240116Smarcelclass stream_capture : basic_stream { 116240116Smarcel // Allow access to the getters. 117240116Smarcel template< class OutStream, class ErrStream > friend 118240116Smarcel child fork(void (*)(void*), const OutStream&, const ErrStream&, void*); 119240116Smarcel template< class OutStream, class ErrStream > friend 120240116Smarcel status exec(const atf::fs::path&, const argv_array&, 121240116Smarcel const OutStream&, const ErrStream&, void (*)(void)); 122240116Smarcel 123240116Smarcelpublic: 124240116Smarcel stream_capture(void); 125240116Smarcel}; 126240116Smarcel 127240116Smarcelclass stream_connect : basic_stream { 128240116Smarcel // Allow access to the getters. 129240116Smarcel template< class OutStream, class ErrStream > friend 130240116Smarcel child fork(void (*)(void*), const OutStream&, const ErrStream&, void*); 131240116Smarcel template< class OutStream, class ErrStream > friend 132240116Smarcel status exec(const atf::fs::path&, const argv_array&, 133240116Smarcel const OutStream&, const ErrStream&, void (*)(void)); 134240116Smarcel 135240116Smarcelpublic: 136240116Smarcel stream_connect(const int, const int); 137240116Smarcel}; 138240116Smarcel 139240116Smarcelclass stream_inherit : basic_stream { 140240116Smarcel // Allow access to the getters. 141240116Smarcel template< class OutStream, class ErrStream > friend 142240116Smarcel child fork(void (*)(void*), const OutStream&, const ErrStream&, void*); 143240116Smarcel template< class OutStream, class ErrStream > friend 144240116Smarcel status exec(const atf::fs::path&, const argv_array&, 145240116Smarcel const OutStream&, const ErrStream&, void (*)(void)); 146240116Smarcel 147240116Smarcelpublic: 148240116Smarcel stream_inherit(void); 149240116Smarcel}; 150240116Smarcel 151240116Smarcelclass stream_redirect_fd : basic_stream { 152240116Smarcel // Allow access to the getters. 153240116Smarcel template< class OutStream, class ErrStream > friend 154240116Smarcel child fork(void (*)(void*), const OutStream&, const ErrStream&, void*); 155240116Smarcel template< class OutStream, class ErrStream > friend 156240116Smarcel status exec(const atf::fs::path&, const argv_array&, 157240116Smarcel const OutStream&, const ErrStream&, void (*)(void)); 158240116Smarcel 159240116Smarcelpublic: 160240116Smarcel stream_redirect_fd(const int); 161240116Smarcel}; 162240116Smarcel 163240116Smarcelclass stream_redirect_path : basic_stream { 164240116Smarcel // Allow access to the getters. 165240116Smarcel template< class OutStream, class ErrStream > friend 166240116Smarcel child fork(void (*)(void*), const OutStream&, const ErrStream&, void*); 167240116Smarcel template< class OutStream, class ErrStream > friend 168240116Smarcel status exec(const atf::fs::path&, const argv_array&, 169240116Smarcel const OutStream&, const ErrStream&, void (*)(void)); 170240116Smarcel 171240116Smarcelpublic: 172240116Smarcel stream_redirect_path(const fs::path&); 173240116Smarcel}; 174240116Smarcel 175240116Smarcel// ------------------------------------------------------------------------ 176240116Smarcel// The "status" type. 177240116Smarcel// ------------------------------------------------------------------------ 178240116Smarcel 179240116Smarcelclass status { 180240116Smarcel atf_process_status_t m_status; 181240116Smarcel 182240116Smarcel friend class child; 183240116Smarcel template< class OutStream, class ErrStream > friend 184240116Smarcel status exec(const atf::fs::path&, const argv_array&, 185240116Smarcel const OutStream&, const ErrStream&, void (*)(void)); 186240116Smarcel 187240116Smarcel status(atf_process_status_t&); 188240116Smarcel 189240116Smarcelpublic: 190240116Smarcel ~status(void); 191240116Smarcel 192240116Smarcel bool exited(void) const; 193240116Smarcel int exitstatus(void) const; 194240116Smarcel 195240116Smarcel bool signaled(void) const; 196240116Smarcel int termsig(void) const; 197240116Smarcel bool coredump(void) const; 198240116Smarcel}; 199240116Smarcel 200240116Smarcel// ------------------------------------------------------------------------ 201240116Smarcel// The "child" type. 202240116Smarcel// ------------------------------------------------------------------------ 203240116Smarcel 204240116Smarcelclass child { 205240116Smarcel atf_process_child_t m_child; 206240116Smarcel bool m_waited; 207240116Smarcel 208240116Smarcel template< class OutStream, class ErrStream > friend 209240116Smarcel child fork(void (*)(void*), const OutStream&, const ErrStream&, void*); 210240116Smarcel 211240116Smarcel child(atf_process_child_t& c); 212240116Smarcel 213240116Smarcelpublic: 214240116Smarcel ~child(void); 215240116Smarcel 216240116Smarcel status wait(void); 217240116Smarcel 218240116Smarcel pid_t pid(void) const; 219240116Smarcel int stdout_fd(void); 220240116Smarcel int stderr_fd(void); 221240116Smarcel}; 222240116Smarcel 223240116Smarcel// ------------------------------------------------------------------------ 224240116Smarcel// Free functions. 225240116Smarcel// ------------------------------------------------------------------------ 226240116Smarcel 227240116Smarcelnamespace detail { 228240116Smarcelvoid flush_streams(void); 229240116Smarcel} // namespace detail 230240116Smarcel 231240116Smarcel// TODO: The void* cookie can probably be templatized, thus also allowing 232240116Smarcel// const data structures. 233240116Smarceltemplate< class OutStream, class ErrStream > 234240116Smarcelchild 235240116Smarcelfork(void (*start)(void*), const OutStream& outsb, 236240116Smarcel const ErrStream& errsb, void* v) 237240116Smarcel{ 238240116Smarcel atf_process_child_t c; 239240116Smarcel 240240116Smarcel detail::flush_streams(); 241240116Smarcel atf_error_t err = atf_process_fork(&c, start, outsb.get_sb(), 242240116Smarcel errsb.get_sb(), v); 243240116Smarcel if (atf_is_error(err)) 244240116Smarcel throw_atf_error(err); 245240116Smarcel 246240116Smarcel return child(c); 247240116Smarcel} 248240116Smarcel 249240116Smarceltemplate< class OutStream, class ErrStream > 250240116Smarcelstatus 251240116Smarcelexec(const atf::fs::path& prog, const argv_array& argv, 252240116Smarcel const OutStream& outsb, const ErrStream& errsb, 253240116Smarcel void (*prehook)(void)) 254240116Smarcel{ 255240116Smarcel atf_process_status_t s; 256240116Smarcel 257240116Smarcel detail::flush_streams(); 258240116Smarcel atf_error_t err = atf_process_exec_array(&s, prog.c_path(), 259240116Smarcel argv.exec_argv(), 260240116Smarcel outsb.get_sb(), 261240116Smarcel errsb.get_sb(), 262240116Smarcel prehook); 263240116Smarcel if (atf_is_error(err)) 264240116Smarcel throw_atf_error(err); 265240116Smarcel 266240116Smarcel return status(s); 267240116Smarcel} 268240116Smarcel 269240116Smarceltemplate< class OutStream, class ErrStream > 270240116Smarcelstatus 271240116Smarcelexec(const atf::fs::path& prog, const argv_array& argv, 272240116Smarcel const OutStream& outsb, const ErrStream& errsb) 273240116Smarcel{ 274240116Smarcel return exec(prog, argv, outsb, errsb, NULL); 275240116Smarcel} 276240116Smarcel 277240116Smarcel} // namespace process 278240116Smarcel} // namespace atf 279240116Smarcel 280240116Smarcel#endif // !defined(_ATF_CXX_PROCESS_HPP_) 281