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