diff options
author | jmmv <jmmv@FreeBSD.org> | 2014-02-14 14:44:03 +0000 |
---|---|---|
committer | jmmv <jmmv@FreeBSD.org> | 2014-02-14 14:44:03 +0000 |
commit | 14f39fed9fe557bdd640e02d9abbe2e695400d9e (patch) | |
tree | 907c960968fce28b8ca3cb9367140ed92c404150 /tools/process.cpp | |
parent | a817576754c6af0869b83f2f3efc4659963962a1 (diff) | |
download | FreeBSD-src-14f39fed9fe557bdd640e02d9abbe2e695400d9e.zip FreeBSD-src-14f39fed9fe557bdd640e02d9abbe2e695400d9e.tar.gz |
Import atf-0.20:
Experimental version released on February 7th, 2014.
This is the first release without the code for the deprecated tools. If
you require such code, please fetch a copy of the 0.19 release and extract
the 'tools' directory for your own consumption.
* Removed the deprecated tools. This includes atf-config, atf-report,
atf-run and atf-version.
Diffstat (limited to 'tools/process.cpp')
-rw-r--r-- | tools/process.cpp | 492 |
1 files changed, 0 insertions, 492 deletions
diff --git a/tools/process.cpp b/tools/process.cpp deleted file mode 100644 index 987a60e..0000000 --- a/tools/process.cpp +++ /dev/null @@ -1,492 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2008 The NetBSD Foundation, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND -// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -extern "C" { -#include <sys/types.h> -#include <sys/wait.h> - -#include <fcntl.h> -#include <signal.h> -} - -#include <cassert> -#include <cstdarg> -#include <cerrno> -#include <cstring> -#include <iostream> - -#include "defs.hpp" -#include "exceptions.hpp" -#include "text.hpp" -#include "process.hpp" - -namespace detail = tools::process::detail; -namespace impl = tools::process; -#define IMPL_NAME "tools::process" - -// ------------------------------------------------------------------------ -// Auxiliary functions. -// ------------------------------------------------------------------------ - -template< class C > -tools::auto_array< const char* > -collection_to_argv(const C& c) -{ - tools::auto_array< const char* > argv(new const char*[c.size() + 1]); - - std::size_t pos = 0; - for (typename C::const_iterator iter = c.begin(); iter != c.end(); - iter++) { - argv[pos] = (*iter).c_str(); - pos++; - } - assert(pos == c.size()); - argv[pos] = NULL; - - return argv; -} - -template< class C > -C -argv_to_collection(const char* const* argv) -{ - C c; - - for (const char* const* iter = argv; *iter != NULL; iter++) - c.push_back(std::string(*iter)); - - return c; -} - -static -void -safe_dup(const int oldfd, const int newfd) -{ - if (oldfd != newfd) { - if (dup2(oldfd, newfd) == -1) { - throw tools::system_error(IMPL_NAME "::safe_dup", - "Could not allocate file descriptor", - errno); - } else { - ::close(oldfd); - } - } -} - -static -int -const_execvp(const char *file, const char *const *argv) -{ -#define UNCONST(a) ((void *)(unsigned long)(const void *)(a)) - return ::execvp(file, (char* const*)(UNCONST(argv))); -#undef UNCONST -} - -void -detail::do_exec(void *v) -{ - struct exec_args *ea = reinterpret_cast<struct exec_args *>(v); - - if (ea->m_prehook != NULL) - ea->m_prehook(); - - const int ret = const_execvp(ea->m_prog.c_str(), ea->m_argv.exec_argv()); - const int errnocopy = errno; - assert(ret == -1); - std::cerr << "exec(" << ea->m_prog.str() << ") failed: " - << std::strerror(errnocopy) << "\n"; - std::exit(EXIT_FAILURE); -} - -// ------------------------------------------------------------------------ -// The "argv_array" type. -// ------------------------------------------------------------------------ - -impl::argv_array::argv_array(void) : - m_exec_argv(collection_to_argv(m_args)) -{ -} - -impl::argv_array::argv_array(const char* arg1, ...) -{ - m_args.push_back(arg1); - - { - va_list ap; - const char* nextarg; - - va_start(ap, arg1); - while ((nextarg = va_arg(ap, const char*)) != NULL) - m_args.push_back(nextarg); - va_end(ap); - } - - ctor_init_exec_argv(); -} - -impl::argv_array::argv_array(const char* const* ca) : - m_args(argv_to_collection< args_vector >(ca)), - m_exec_argv(collection_to_argv(m_args)) -{ -} - -impl::argv_array::argv_array(const argv_array& a) : - m_args(a.m_args), - m_exec_argv(collection_to_argv(m_args)) -{ -} - -void -impl::argv_array::ctor_init_exec_argv(void) -{ - m_exec_argv = collection_to_argv(m_args); -} - -const char* const* -impl::argv_array::exec_argv(void) - const -{ - return m_exec_argv.get(); -} - -impl::argv_array::size_type -impl::argv_array::size(void) - const -{ - return m_args.size(); -} - -const char* -impl::argv_array::operator[](int idx) - const -{ - return m_args[idx].c_str(); -} - -impl::argv_array::const_iterator -impl::argv_array::begin(void) - const -{ - return m_args.begin(); -} - -impl::argv_array::const_iterator -impl::argv_array::end(void) - const -{ - return m_args.end(); -} - -impl::argv_array& -impl::argv_array::operator=(const argv_array& a) -{ - if (this != &a) { - m_args = a.m_args; - m_exec_argv = collection_to_argv(m_args); - } - return *this; -} - -// ------------------------------------------------------------------------ -// The "stream" types. -// ------------------------------------------------------------------------ - -impl::stream_capture::stream_capture(void) -{ - for (int i = 0; i < 2; i++) - m_pipefds[i] = -1; -} - -impl::stream_capture::~stream_capture(void) -{ - for (int i = 0; i < 2; i++) - if (m_pipefds[i] != -1) - ::close(m_pipefds[i]); -} - -void -impl::stream_capture::prepare(void) -{ - if (pipe(m_pipefds) == -1) - throw system_error(IMPL_NAME "::stream_capture::prepare", - "Failed to create pipe", errno); -} - -int -impl::stream_capture::connect_parent(void) -{ - ::close(m_pipefds[1]); m_pipefds[1] = -1; - const int fd = m_pipefds[0]; - m_pipefds[0] = -1; - return fd; -} - -void -impl::stream_capture::connect_child(const int fd) -{ - ::close(m_pipefds[0]); m_pipefds[0] = -1; - if (m_pipefds[1] != fd) { - safe_dup(m_pipefds[1], fd); - } - m_pipefds[1] = -1; -} - -impl::stream_connect::stream_connect(const int src_fd, const int tgt_fd) : - m_src_fd(src_fd), m_tgt_fd(tgt_fd) -{ -} - -void -impl::stream_connect::prepare(void) -{ -} - -int -impl::stream_connect::connect_parent(void) -{ - return -1; -} - -void -impl::stream_connect::connect_child(const int fd ATF_DEFS_ATTRIBUTE_UNUSED) -{ - safe_dup(m_tgt_fd, m_src_fd); -} - -impl::stream_inherit::stream_inherit(void) -{ -} - -void -impl::stream_inherit::prepare(void) -{ -} - -int -impl::stream_inherit::connect_parent(void) -{ - return -1; -} - -void -impl::stream_inherit::connect_child(const int fd ATF_DEFS_ATTRIBUTE_UNUSED) -{ -} - -impl::stream_redirect_fd::stream_redirect_fd(const int fd) : - m_fd(fd) -{ -} - -void -impl::stream_redirect_fd::prepare(void) -{ -} - -int -impl::stream_redirect_fd::connect_parent(void) -{ - return -1; -} - -void -impl::stream_redirect_fd::connect_child(const int fd) -{ - safe_dup(m_fd, fd); -} - -impl::stream_redirect_path::stream_redirect_path(const tools::fs::path& p) : - m_path(p) -{ -} - -void -impl::stream_redirect_path::prepare(void) -{ -} - -int -impl::stream_redirect_path::connect_parent(void) -{ - return -1; -} - -void -impl::stream_redirect_path::connect_child(const int fd) -{ - const int aux = ::open(m_path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0644); - if (aux == -1) - throw system_error(IMPL_NAME "::stream_redirect_path::connect_child", - "Could not create " + m_path.str(), errno); - else - safe_dup(aux, fd); -} - -// ------------------------------------------------------------------------ -// The "status" type. -// ------------------------------------------------------------------------ - -impl::status::status(int s) : - m_status(s) -{ -} - -impl::status::~status(void) -{ -} - -bool -impl::status::exited(void) - const -{ - int mutable_status = m_status; - return WIFEXITED(mutable_status); -} - -int -impl::status::exitstatus(void) - const -{ - assert(exited()); - int mutable_status = m_status; - return WEXITSTATUS(mutable_status); -} - -bool -impl::status::signaled(void) - const -{ - int mutable_status = m_status; - return WIFSIGNALED(mutable_status); -} - -int -impl::status::termsig(void) - const -{ - assert(signaled()); - int mutable_status = m_status; - return WTERMSIG(mutable_status); -} - -bool -impl::status::coredump(void) - const -{ - assert(signaled()); -#if defined(WCOREDUMP) - int mutable_status = m_status; - return WCOREDUMP(mutable_status); -#else - return false; -#endif -} - -// ------------------------------------------------------------------------ -// The "child" type. -// ------------------------------------------------------------------------ - -impl::child::child(const pid_t pid_arg, const int stdout_fd_arg, - const int stderr_fd_arg) : - m_pid(pid_arg), - m_stdout(stdout_fd_arg), - m_stderr(stderr_fd_arg), - m_waited(false) -{ -} - -impl::child::~child(void) -{ - if (!m_waited) { - ::kill(m_pid, SIGTERM); - (void)wait(); - - if (m_stdout != -1) - ::close(m_stdout); - if (m_stderr != -1) - ::close(m_stderr); - } -} - -impl::status -impl::child::wait(void) -{ - int s; - - if (::waitpid(m_pid, &s, 0) == -1) - throw system_error(IMPL_NAME "::child::wait", "Failed waiting for " - "process " + text::to_string(m_pid), errno); - - if (m_stdout != -1) - ::close(m_stdout); m_stdout = -1; - if (m_stderr != -1) - ::close(m_stderr); m_stderr = -1; - - m_waited = true; - return status(s); -} - -pid_t -impl::child::pid(void) - const -{ - return m_pid; -} - -int -impl::child::stdout_fd(void) -{ - return m_stdout; -} - -int -impl::child::stderr_fd(void) -{ - return m_stderr; -} - -// ------------------------------------------------------------------------ -// Free functions. -// ------------------------------------------------------------------------ - -void -detail::flush_streams(void) -{ - // This is a weird hack to ensure that the output of the parent process - // is flushed before executing a child which prevents, for example, the - // output of the atf-run hooks to appear before the output of atf-run - // itself. - // - // TODO: This should only be executed when inheriting the stdout or - // stderr file descriptors. However, the flushing is specific to the - // iostreams, so we cannot do it from the C library where all the process - // logic is performed. Come up with a better design. - std::cout.flush(); - std::cerr.flush(); -} |