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 30240116Smarcelextern "C" { 31240116Smarcel#include <signal.h> 32240116Smarcel 33240116Smarcel#include "../../atf-c/error.h" 34240116Smarcel 35240116Smarcel#include "../../atf-c/detail/process.h" 36240116Smarcel} 37240116Smarcel 38240116Smarcel#include <iostream> 39240116Smarcel 40240116Smarcel#include "exceptions.hpp" 41240116Smarcel#include "process.hpp" 42240116Smarcel#include "sanity.hpp" 43240116Smarcel 44240116Smarcelnamespace detail = atf::process::detail; 45240116Smarcelnamespace impl = atf::process; 46240116Smarcel#define IMPL_NAME "atf::process" 47240116Smarcel 48240116Smarcel// ------------------------------------------------------------------------ 49240116Smarcel// Auxiliary functions. 50240116Smarcel// ------------------------------------------------------------------------ 51240116Smarcel 52240116Smarceltemplate< class C > 53260029Sjmmvatf::auto_array< const char* > 54240116Smarcelcollection_to_argv(const C& c) 55240116Smarcel{ 56260029Sjmmv atf::auto_array< const char* > argv(new const char*[c.size() + 1]); 57240116Smarcel 58240116Smarcel std::size_t pos = 0; 59240116Smarcel for (typename C::const_iterator iter = c.begin(); iter != c.end(); 60240116Smarcel iter++) { 61240116Smarcel argv[pos] = (*iter).c_str(); 62240116Smarcel pos++; 63240116Smarcel } 64240116Smarcel INV(pos == c.size()); 65240116Smarcel argv[pos] = NULL; 66240116Smarcel 67240116Smarcel return argv; 68240116Smarcel} 69240116Smarcel 70240116Smarceltemplate< class C > 71240116SmarcelC 72240116Smarcelargv_to_collection(const char* const* argv) 73240116Smarcel{ 74240116Smarcel C c; 75240116Smarcel 76240116Smarcel for (const char* const* iter = argv; *iter != NULL; iter++) 77240116Smarcel c.push_back(std::string(*iter)); 78240116Smarcel 79240116Smarcel return c; 80240116Smarcel} 81240116Smarcel 82240116Smarcel// ------------------------------------------------------------------------ 83240116Smarcel// The "argv_array" type. 84240116Smarcel// ------------------------------------------------------------------------ 85240116Smarcel 86240116Smarcelimpl::argv_array::argv_array(void) : 87240116Smarcel m_exec_argv(collection_to_argv(m_args)) 88240116Smarcel{ 89240116Smarcel} 90240116Smarcel 91240116Smarcelimpl::argv_array::argv_array(const char* arg1, ...) 92240116Smarcel{ 93240116Smarcel m_args.push_back(arg1); 94240116Smarcel 95240116Smarcel { 96240116Smarcel va_list ap; 97240116Smarcel const char* nextarg; 98240116Smarcel 99240116Smarcel va_start(ap, arg1); 100240116Smarcel while ((nextarg = va_arg(ap, const char*)) != NULL) 101240116Smarcel m_args.push_back(nextarg); 102240116Smarcel va_end(ap); 103240116Smarcel } 104240116Smarcel 105240116Smarcel ctor_init_exec_argv(); 106240116Smarcel} 107240116Smarcel 108240116Smarcelimpl::argv_array::argv_array(const char* const* ca) : 109240116Smarcel m_args(argv_to_collection< args_vector >(ca)), 110240116Smarcel m_exec_argv(collection_to_argv(m_args)) 111240116Smarcel{ 112240116Smarcel} 113240116Smarcel 114240116Smarcelimpl::argv_array::argv_array(const argv_array& a) : 115240116Smarcel m_args(a.m_args), 116240116Smarcel m_exec_argv(collection_to_argv(m_args)) 117240116Smarcel{ 118240116Smarcel} 119240116Smarcel 120240116Smarcelvoid 121240116Smarcelimpl::argv_array::ctor_init_exec_argv(void) 122240116Smarcel{ 123240116Smarcel m_exec_argv = collection_to_argv(m_args); 124240116Smarcel} 125240116Smarcel 126240116Smarcelconst char* const* 127240116Smarcelimpl::argv_array::exec_argv(void) 128240116Smarcel const 129240116Smarcel{ 130240116Smarcel return m_exec_argv.get(); 131240116Smarcel} 132240116Smarcel 133240116Smarcelimpl::argv_array::size_type 134240116Smarcelimpl::argv_array::size(void) 135240116Smarcel const 136240116Smarcel{ 137240116Smarcel return m_args.size(); 138240116Smarcel} 139240116Smarcel 140240116Smarcelconst char* 141240116Smarcelimpl::argv_array::operator[](int idx) 142240116Smarcel const 143240116Smarcel{ 144240116Smarcel return m_args[idx].c_str(); 145240116Smarcel} 146240116Smarcel 147240116Smarcelimpl::argv_array::const_iterator 148240116Smarcelimpl::argv_array::begin(void) 149240116Smarcel const 150240116Smarcel{ 151240116Smarcel return m_args.begin(); 152240116Smarcel} 153240116Smarcel 154240116Smarcelimpl::argv_array::const_iterator 155240116Smarcelimpl::argv_array::end(void) 156240116Smarcel const 157240116Smarcel{ 158240116Smarcel return m_args.end(); 159240116Smarcel} 160240116Smarcel 161240116Smarcelimpl::argv_array& 162240116Smarcelimpl::argv_array::operator=(const argv_array& a) 163240116Smarcel{ 164240116Smarcel if (this != &a) { 165240116Smarcel m_args = a.m_args; 166240116Smarcel m_exec_argv = collection_to_argv(m_args); 167240116Smarcel } 168240116Smarcel return *this; 169240116Smarcel} 170240116Smarcel 171240116Smarcel// ------------------------------------------------------------------------ 172240116Smarcel// The "stream" types. 173240116Smarcel// ------------------------------------------------------------------------ 174240116Smarcel 175240116Smarcelimpl::basic_stream::basic_stream(void) : 176240116Smarcel m_inited(false) 177240116Smarcel{ 178240116Smarcel} 179240116Smarcel 180240116Smarcelimpl::basic_stream::~basic_stream(void) 181240116Smarcel{ 182240116Smarcel if (m_inited) 183240116Smarcel atf_process_stream_fini(&m_sb); 184240116Smarcel} 185240116Smarcel 186240116Smarcelconst atf_process_stream_t* 187240116Smarcelimpl::basic_stream::get_sb(void) 188240116Smarcel const 189240116Smarcel{ 190240116Smarcel INV(m_inited); 191240116Smarcel return &m_sb; 192240116Smarcel} 193240116Smarcel 194240116Smarcelimpl::stream_capture::stream_capture(void) 195240116Smarcel{ 196240116Smarcel atf_error_t err = atf_process_stream_init_capture(&m_sb); 197240116Smarcel if (atf_is_error(err)) 198240116Smarcel throw_atf_error(err); 199240116Smarcel m_inited = true; 200240116Smarcel} 201240116Smarcel 202240116Smarcelimpl::stream_connect::stream_connect(const int src_fd, const int tgt_fd) 203240116Smarcel{ 204240116Smarcel atf_error_t err = atf_process_stream_init_connect(&m_sb, src_fd, tgt_fd); 205240116Smarcel if (atf_is_error(err)) 206240116Smarcel throw_atf_error(err); 207240116Smarcel m_inited = true; 208240116Smarcel} 209240116Smarcel 210240116Smarcelimpl::stream_inherit::stream_inherit(void) 211240116Smarcel{ 212240116Smarcel atf_error_t err = atf_process_stream_init_inherit(&m_sb); 213240116Smarcel if (atf_is_error(err)) 214240116Smarcel throw_atf_error(err); 215240116Smarcel m_inited = true; 216240116Smarcel} 217240116Smarcel 218240116Smarcelimpl::stream_redirect_fd::stream_redirect_fd(const int fd) 219240116Smarcel{ 220240116Smarcel atf_error_t err = atf_process_stream_init_redirect_fd(&m_sb, fd); 221240116Smarcel if (atf_is_error(err)) 222240116Smarcel throw_atf_error(err); 223240116Smarcel m_inited = true; 224240116Smarcel} 225240116Smarcel 226240116Smarcelimpl::stream_redirect_path::stream_redirect_path(const fs::path& p) 227240116Smarcel{ 228240116Smarcel atf_error_t err = atf_process_stream_init_redirect_path(&m_sb, p.c_path()); 229240116Smarcel if (atf_is_error(err)) 230240116Smarcel throw_atf_error(err); 231240116Smarcel m_inited = true; 232240116Smarcel} 233240116Smarcel 234240116Smarcel// ------------------------------------------------------------------------ 235240116Smarcel// The "status" type. 236240116Smarcel// ------------------------------------------------------------------------ 237240116Smarcel 238240116Smarcelimpl::status::status(atf_process_status_t& s) : 239240116Smarcel m_status(s) 240240116Smarcel{ 241240116Smarcel} 242240116Smarcel 243240116Smarcelimpl::status::~status(void) 244240116Smarcel{ 245240116Smarcel atf_process_status_fini(&m_status); 246240116Smarcel} 247240116Smarcel 248240116Smarcelbool 249240116Smarcelimpl::status::exited(void) 250240116Smarcel const 251240116Smarcel{ 252240116Smarcel return atf_process_status_exited(&m_status); 253240116Smarcel} 254240116Smarcel 255240116Smarcelint 256240116Smarcelimpl::status::exitstatus(void) 257240116Smarcel const 258240116Smarcel{ 259240116Smarcel return atf_process_status_exitstatus(&m_status); 260240116Smarcel} 261240116Smarcel 262240116Smarcelbool 263240116Smarcelimpl::status::signaled(void) 264240116Smarcel const 265240116Smarcel{ 266240116Smarcel return atf_process_status_signaled(&m_status); 267240116Smarcel} 268240116Smarcel 269240116Smarcelint 270240116Smarcelimpl::status::termsig(void) 271240116Smarcel const 272240116Smarcel{ 273240116Smarcel return atf_process_status_termsig(&m_status); 274240116Smarcel} 275240116Smarcel 276240116Smarcelbool 277240116Smarcelimpl::status::coredump(void) 278240116Smarcel const 279240116Smarcel{ 280240116Smarcel return atf_process_status_coredump(&m_status); 281240116Smarcel} 282240116Smarcel 283240116Smarcel// ------------------------------------------------------------------------ 284240116Smarcel// The "child" type. 285240116Smarcel// ------------------------------------------------------------------------ 286240116Smarcel 287240116Smarcelimpl::child::child(atf_process_child_t& c) : 288240116Smarcel m_child(c), 289240116Smarcel m_waited(false) 290240116Smarcel{ 291240116Smarcel} 292240116Smarcel 293240116Smarcelimpl::child::~child(void) 294240116Smarcel{ 295240116Smarcel if (!m_waited) { 296240116Smarcel ::kill(atf_process_child_pid(&m_child), SIGTERM); 297240116Smarcel 298240116Smarcel atf_process_status_t s; 299240116Smarcel atf_error_t err = atf_process_child_wait(&m_child, &s); 300240116Smarcel INV(!atf_is_error(err)); 301240116Smarcel atf_process_status_fini(&s); 302240116Smarcel } 303240116Smarcel} 304240116Smarcel 305240116Smarcelimpl::status 306240116Smarcelimpl::child::wait(void) 307240116Smarcel{ 308240116Smarcel atf_process_status_t s; 309240116Smarcel 310240116Smarcel atf_error_t err = atf_process_child_wait(&m_child, &s); 311240116Smarcel if (atf_is_error(err)) 312240116Smarcel throw_atf_error(err); 313240116Smarcel 314240116Smarcel m_waited = true; 315240116Smarcel return status(s); 316240116Smarcel} 317240116Smarcel 318240116Smarcelpid_t 319240116Smarcelimpl::child::pid(void) 320240116Smarcel const 321240116Smarcel{ 322240116Smarcel return atf_process_child_pid(&m_child); 323240116Smarcel} 324240116Smarcel 325240116Smarcelint 326240116Smarcelimpl::child::stdout_fd(void) 327240116Smarcel{ 328240116Smarcel return atf_process_child_stdout(&m_child); 329240116Smarcel} 330240116Smarcel 331240116Smarcelint 332240116Smarcelimpl::child::stderr_fd(void) 333240116Smarcel{ 334240116Smarcel return atf_process_child_stderr(&m_child); 335240116Smarcel} 336240116Smarcel 337240116Smarcel// ------------------------------------------------------------------------ 338240116Smarcel// Free functions. 339240116Smarcel// ------------------------------------------------------------------------ 340240116Smarcel 341240116Smarcelvoid 342240116Smarceldetail::flush_streams(void) 343240116Smarcel{ 344240116Smarcel // This is a weird hack to ensure that the output of the parent process 345240116Smarcel // is flushed before executing a child which prevents, for example, the 346240116Smarcel // output of the atf-run hooks to appear before the output of atf-run 347240116Smarcel // itself. 348240116Smarcel // 349240116Smarcel // TODO: This should only be executed when inheriting the stdout or 350240116Smarcel // stderr file descriptors. However, the flushing is specific to the 351240116Smarcel // iostreams, so we cannot do it from the C library where all the process 352240116Smarcel // logic is performed. Come up with a better design. 353240116Smarcel std::cout.flush(); 354240116Smarcel std::cerr.flush(); 355240116Smarcel} 356