4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews// Automated Testing Framework (atf)
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews// Copyright (c) 2008 The NetBSD Foundation, Inc.
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews// All rights reserved.
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews// Redistribution and use in source and binary forms, with or without
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews// modification, are permitted provided that the following conditions
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews// 1. Redistributions of source code must retain the above copyright
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews// notice, this list of conditions and the following disclaimer.
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews// 2. Redistributions in binary form must reproduce the above copyright
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews// notice, this list of conditions and the following disclaimer in the
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews// documentation and/or other materials provided with the distribution.
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews// ------------------------------------------------------------------------
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews// Auxiliary functions.
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews// ------------------------------------------------------------------------
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrewstemplate< class C >
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews tools::auto_array< const char* > argv(new const char*[c.size() + 1]);
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews for (typename C::const_iterator iter = c.begin(); iter != c.end();
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrewstemplate< class C >
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews for (const char* const* iter = argv; *iter != NULL; iter++)
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews throw tools::system_error(IMPL_NAME "::safe_dup",
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews "Could not allocate file descriptor",
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrewsconst_execvp(const char *file, const char *const *argv)
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews#define UNCONST(a) ((void *)(unsigned long)(const void *)(a))
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews return ::execvp(file, (char* const*)(UNCONST(argv)));
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews struct exec_args *ea = reinterpret_cast<struct exec_args *>(v);
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews const int ret = const_execvp(ea->m_prog.c_str(), ea->m_argv.exec_argv());
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews std::cerr << "exec(" << ea->m_prog.str() << ") failed: "
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews// ------------------------------------------------------------------------
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews// The "argv_array" type.
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews// ------------------------------------------------------------------------
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrewsimpl::argv_array::argv_array(const char* arg1, ...)
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews while ((nextarg = va_arg(ap, const char*)) != NULL)
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrewsimpl::argv_array::argv_array(const char* const* ca) :
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrewsimpl::argv_array::argv_array(const argv_array& a) :
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrewsconst char* const*
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrewsimpl::argv_array::operator=(const argv_array& a)
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews if (this != &a) {
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews return *this;
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews// ------------------------------------------------------------------------
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews// The "stream" types.
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews// ------------------------------------------------------------------------
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews for (int i = 0; i < 2; i++)
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews for (int i = 0; i < 2; i++)
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews throw system_error(IMPL_NAME "::stream_capture::prepare",
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrewsimpl::stream_capture::connect_child(const int fd)
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrewsimpl::stream_connect::stream_connect(const int src_fd, const int tgt_fd) :
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrewsimpl::stream_connect::connect_child(const int fd ATF_DEFS_ATTRIBUTE_UNUSED)
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrewsimpl::stream_inherit::connect_child(const int fd ATF_DEFS_ATTRIBUTE_UNUSED)
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrewsimpl::stream_redirect_fd::stream_redirect_fd(const int fd) :
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrewsimpl::stream_redirect_fd::connect_child(const int fd)
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrewsimpl::stream_redirect_path::stream_redirect_path(const tools::fs::path& p) :
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrewsimpl::stream_redirect_path::connect_parent(void)
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrewsimpl::stream_redirect_path::connect_child(const int fd)
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews const int aux = ::open(m_path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0644);
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews throw system_error(IMPL_NAME "::stream_redirect_path::connect_child",
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews// ------------------------------------------------------------------------
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews// The "status" type.
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews// ------------------------------------------------------------------------
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews return false;
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews// ------------------------------------------------------------------------
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews// The "child" type.
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews// ------------------------------------------------------------------------
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrewsimpl::child::child(const pid_t pid_arg, const int stdout_fd_arg,
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews throw system_error(IMPL_NAME "::child::wait", "Failed waiting for "
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews// ------------------------------------------------------------------------
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews// Free functions.
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews// ------------------------------------------------------------------------
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews // This is a weird hack to ensure that the output of the parent process
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews // is flushed before executing a child which prevents, for example, the
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews // output of the atf-run hooks to appear before the output of atf-run
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews // TODO: This should only be executed when inheriting the stdout or
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews // stderr file descriptors. However, the flushing is specific to the
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews // iostreams, so we cannot do it from the C library where all the process
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews // logic is performed. Come up with a better design.