4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews/* Copyright (c) 2007 The NetBSD Foundation, Inc.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * All rights reserved.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt *
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * Redistribution and use in source and binary forms, with or without
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * modification, are permitted provided that the following conditions
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * are met:
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * 1. Redistributions of source code must retain the above copyright
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * notice, this list of conditions and the following disclaimer.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * 2. Redistributions in binary form must reproduce the above copyright
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * notice, this list of conditions and the following disclaimer in the
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * documentation and/or other materials provided with the distribution.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt *
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * 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#include "atf-c/detail/process.h"
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt#include <sys/types.h>
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt#include <sys/wait.h>
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt#include <errno.h>
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt#include <fcntl.h>
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt#include <stdio.h>
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt#include <stdlib.h>
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt#include <string.h>
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt#include <unistd.h>
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt#include "atf-c/defs.h"
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews#include "atf-c/detail/sanity.h"
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt#include "atf-c/error.h"
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt/* This prototype is not in the header file because this is a private
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * function; however, we need to access it during testing. */
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntatf_error_t atf_process_status_init(atf_process_status_t *, int);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt/* ---------------------------------------------------------------------
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * The "stream_prepare" auxiliary type.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * --------------------------------------------------------------------- */
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntstruct stream_prepare {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const atf_process_stream_t *m_sb;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt bool m_pipefds_ok;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt int m_pipefds[2];
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt};
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunttypedef struct stream_prepare stream_prepare_t;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntstatic
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntatf_error_t
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntstream_prepare_init(stream_prepare_t *sp, const atf_process_stream_t *sb)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt atf_error_t err;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const int type = atf_process_stream_type(sb);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt sp->m_sb = sb;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt sp->m_pipefds_ok = false;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (type == atf_process_stream_type_capture) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (pipe(sp->m_pipefds) == -1)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt err = atf_libc_error(errno, "Failed to create pipe");
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt else {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt err = atf_no_error();
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt sp->m_pipefds_ok = true;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt err = atf_no_error();
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return err;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntstatic
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntvoid
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntstream_prepare_fini(stream_prepare_t *sp)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (sp->m_pipefds_ok) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt close(sp->m_pipefds[0]);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt close(sp->m_pipefds[1]);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt/* ---------------------------------------------------------------------
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * The "atf_process_stream" type.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * --------------------------------------------------------------------- */
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntconst int atf_process_stream_type_capture = 1;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntconst int atf_process_stream_type_connect = 2;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntconst int atf_process_stream_type_inherit = 3;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntconst int atf_process_stream_type_redirect_fd = 4;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntconst int atf_process_stream_type_redirect_path = 5;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntstatic
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntbool
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntstream_is_valid(const atf_process_stream_t *sb)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return (sb->m_type == atf_process_stream_type_capture) ||
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt (sb->m_type == atf_process_stream_type_connect) ||
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt (sb->m_type == atf_process_stream_type_inherit) ||
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt (sb->m_type == atf_process_stream_type_redirect_fd) ||
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt (sb->m_type == atf_process_stream_type_redirect_path);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntatf_error_t
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntatf_process_stream_init_capture(atf_process_stream_t *sb)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt sb->m_type = atf_process_stream_type_capture;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt POST(stream_is_valid(sb));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return atf_no_error();
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntatf_error_t
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntatf_process_stream_init_connect(atf_process_stream_t *sb,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const int src_fd, const int tgt_fd)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt PRE(src_fd >= 0);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt PRE(tgt_fd >= 0);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt PRE(src_fd != tgt_fd);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt sb->m_type = atf_process_stream_type_connect;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt sb->m_src_fd = src_fd;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt sb->m_tgt_fd = tgt_fd;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt POST(stream_is_valid(sb));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return atf_no_error();
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntatf_error_t
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntatf_process_stream_init_inherit(atf_process_stream_t *sb)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt sb->m_type = atf_process_stream_type_inherit;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt POST(stream_is_valid(sb));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return atf_no_error();
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntatf_error_t
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntatf_process_stream_init_redirect_fd(atf_process_stream_t *sb,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const int fd)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt sb->m_type = atf_process_stream_type_redirect_fd;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt sb->m_fd = fd;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt POST(stream_is_valid(sb));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return atf_no_error();
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntatf_error_t
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntatf_process_stream_init_redirect_path(atf_process_stream_t *sb,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const atf_fs_path_t *path)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt sb->m_type = atf_process_stream_type_redirect_path;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt sb->m_path = path;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt POST(stream_is_valid(sb));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return atf_no_error();
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntvoid
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntatf_process_stream_fini(atf_process_stream_t *sb)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt PRE(stream_is_valid(sb));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntint
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntatf_process_stream_type(const atf_process_stream_t *sb)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt PRE(stream_is_valid(sb));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return sb->m_type;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt/* ---------------------------------------------------------------------
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * The "atf_process_status" type.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * --------------------------------------------------------------------- */
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntatf_error_t
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntatf_process_status_init(atf_process_status_t *s, int status)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt s->m_status = status;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return atf_no_error();
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntvoid
a747113422afaa29ce72d2c5ba7f0b7ea9ec2054Evan Huntatf_process_status_fini(atf_process_status_t *s ATF_DEFS_ATTRIBUTE_UNUSED)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntbool
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntatf_process_status_exited(const atf_process_status_t *s)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt int mutable_status = s->m_status;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return WIFEXITED(mutable_status);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntint
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntatf_process_status_exitstatus(const atf_process_status_t *s)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt PRE(atf_process_status_exited(s));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt int mutable_status = s->m_status;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return WEXITSTATUS(mutable_status);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntbool
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntatf_process_status_signaled(const atf_process_status_t *s)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt int mutable_status = s->m_status;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return WIFSIGNALED(mutable_status);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntint
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntatf_process_status_termsig(const atf_process_status_t *s)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt PRE(atf_process_status_signaled(s));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt int mutable_status = s->m_status;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return WTERMSIG(mutable_status);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntbool
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntatf_process_status_coredump(const atf_process_status_t *s)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt PRE(atf_process_status_signaled(s));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt#if defined(WCOREDUMP)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt int mutable_status = s->m_status;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return WCOREDUMP(mutable_status);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt#else
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return false;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt#endif
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt/* ---------------------------------------------------------------------
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * The "atf_process_child" type.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * --------------------------------------------------------------------- */
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntstatic
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntatf_error_t
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntatf_process_child_init(atf_process_child_t *c)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt c->m_pid = 0;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt c->m_stdout = -1;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt c->m_stderr = -1;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return atf_no_error();
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntstatic
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntvoid
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntatf_process_child_fini(atf_process_child_t *c)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (c->m_stdout != -1)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt close(c->m_stdout);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (c->m_stderr != -1)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt close(c->m_stderr);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntatf_error_t
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntatf_process_child_wait(atf_process_child_t *c, atf_process_status_t *s)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt atf_error_t err;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt int status;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (waitpid(c->m_pid, &status, 0) == -1)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt err = atf_libc_error(errno, "Failed waiting for process %d",
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt c->m_pid);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt else {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt atf_process_child_fini(c);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt err = atf_process_status_init(s, status);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return err;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntpid_t
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntatf_process_child_pid(const atf_process_child_t *c)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return c->m_pid;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntint
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntatf_process_child_stdout(atf_process_child_t *c)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt PRE(c->m_stdout != -1);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return c->m_stdout;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntint
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntatf_process_child_stderr(atf_process_child_t *c)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt PRE(c->m_stderr != -1);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return c->m_stderr;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt/* ---------------------------------------------------------------------
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * Free functions.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt * --------------------------------------------------------------------- */
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntstatic
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntatf_error_t
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntsafe_dup(const int oldfd, const int newfd)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt atf_error_t err;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (oldfd != newfd) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (dup2(oldfd, newfd) == -1) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt err = atf_libc_error(errno, "Could not allocate file descriptor");
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt close(oldfd);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt err = atf_no_error();
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt err = atf_no_error();
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return err;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntstatic
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntatf_error_t
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntchild_connect(const stream_prepare_t *sp, int procfd)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt atf_error_t err;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const int type = atf_process_stream_type(sp->m_sb);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (type == atf_process_stream_type_capture) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt close(sp->m_pipefds[0]);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt err = safe_dup(sp->m_pipefds[1], procfd);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else if (type == atf_process_stream_type_connect) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (dup2(sp->m_sb->m_tgt_fd, sp->m_sb->m_src_fd) == -1)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt err = atf_libc_error(errno, "Cannot connect descriptor %d to %d",
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt sp->m_sb->m_tgt_fd, sp->m_sb->m_src_fd);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt else
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt err = atf_no_error();
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else if (type == atf_process_stream_type_inherit) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt err = atf_no_error();
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else if (type == atf_process_stream_type_redirect_fd) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt err = safe_dup(sp->m_sb->m_fd, procfd);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else if (type == atf_process_stream_type_redirect_path) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt int aux = open(atf_fs_path_cstring(sp->m_sb->m_path),
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt O_WRONLY | O_CREAT | O_TRUNC, 0644);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (aux == -1)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt err = atf_libc_error(errno, "Could not create %s",
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt atf_fs_path_cstring(sp->m_sb->m_path));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt else {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt err = safe_dup(aux, procfd);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (atf_is_error(err))
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt close(aux);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt UNREACHABLE;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt err = atf_no_error();
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return err;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntstatic
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntvoid
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntparent_connect(const stream_prepare_t *sp, int *fd)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const int type = atf_process_stream_type(sp->m_sb);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (type == atf_process_stream_type_capture) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt close(sp->m_pipefds[1]);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt *fd = sp->m_pipefds[0];
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else if (type == atf_process_stream_type_connect) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt /* Do nothing. */
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else if (type == atf_process_stream_type_inherit) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt /* Do nothing. */
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else if (type == atf_process_stream_type_redirect_fd) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt /* Do nothing. */
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else if (type == atf_process_stream_type_redirect_path) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt /* Do nothing. */
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt UNREACHABLE;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntstatic
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntatf_error_t
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntdo_parent(atf_process_child_t *c,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const pid_t pid,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const stream_prepare_t *outsp,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const stream_prepare_t *errsp)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt atf_error_t err;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt err = atf_process_child_init(c);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (atf_is_error(err))
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt goto out;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt c->m_pid = pid;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt parent_connect(outsp, &c->m_stdout);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt parent_connect(errsp, &c->m_stderr);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntout:
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return err;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntstatic
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntvoid
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntdo_child(void (*)(void *),
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt void *,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const stream_prepare_t *,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const stream_prepare_t *) ATF_DEFS_ATTRIBUTE_NORETURN;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntstatic
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntvoid
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntdo_child(void (*start)(void *),
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt void *v,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const stream_prepare_t *outsp,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const stream_prepare_t *errsp)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt atf_error_t err;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt err = child_connect(outsp, STDOUT_FILENO);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (atf_is_error(err))
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt goto out;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt err = child_connect(errsp, STDERR_FILENO);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (atf_is_error(err))
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt goto out;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt start(v);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt UNREACHABLE;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntout:
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (atf_is_error(err)) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt char buf[1024];
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt atf_error_format(err, buf, sizeof(buf));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt fprintf(stderr, "Unhandled error: %s\n", buf);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt atf_error_free(err);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt exit(EXIT_FAILURE);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt exit(EXIT_SUCCESS);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntstatic
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntatf_error_t
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntfork_with_streams(atf_process_child_t *c,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt void (*start)(void *),
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const atf_process_stream_t *outsb,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const atf_process_stream_t *errsb,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt void *v)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt atf_error_t err;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt stream_prepare_t outsp;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt stream_prepare_t errsp;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt pid_t pid;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt err = stream_prepare_init(&outsp, outsb);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (atf_is_error(err))
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt goto out;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt err = stream_prepare_init(&errsp, errsb);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (atf_is_error(err))
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt goto err_outpipe;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt pid = fork();
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (pid == -1) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt err = atf_libc_error(errno, "Failed to fork");
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt goto err_errpipe;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (pid == 0) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt do_child(start, v, &outsp, &errsp);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt UNREACHABLE;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt abort();
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt err = atf_no_error();
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt err = do_parent(c, pid, &outsp, &errsp);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (atf_is_error(err))
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt goto err_errpipe;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt goto out;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunterr_errpipe:
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt stream_prepare_fini(&errsp);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunterr_outpipe:
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt stream_prepare_fini(&outsp);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntout:
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return err;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntstatic
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntatf_error_t
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntinit_stream_w_default(const atf_process_stream_t *usersb,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt atf_process_stream_t *inheritsb,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const atf_process_stream_t **realsb)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt atf_error_t err;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (usersb == NULL) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt err = atf_process_stream_init_inherit(inheritsb);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (!atf_is_error(err))
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt *realsb = inheritsb;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt err = atf_no_error();
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt *realsb = usersb;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return err;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntatf_error_t
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntatf_process_fork(atf_process_child_t *c,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt void (*start)(void *),
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const atf_process_stream_t *outsb,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const atf_process_stream_t *errsb,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt void *v)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt atf_error_t err;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt atf_process_stream_t inherit_outsb, inherit_errsb;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const atf_process_stream_t *real_outsb, *real_errsb;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt real_outsb = NULL; /* Shut up GCC warning. */
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt err = init_stream_w_default(outsb, &inherit_outsb, &real_outsb);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (atf_is_error(err))
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt goto out;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt real_errsb = NULL; /* Shut up GCC warning. */
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt err = init_stream_w_default(errsb, &inherit_errsb, &real_errsb);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (atf_is_error(err))
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt goto out_out;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt err = fork_with_streams(c, start, real_outsb, real_errsb, v);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (errsb == NULL)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt atf_process_stream_fini(&inherit_errsb);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntout_out:
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (outsb == NULL)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt atf_process_stream_fini(&inherit_outsb);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntout:
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return err;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntstatic
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntint
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntconst_execvp(const char *file, const char *const *argv)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt#define UNCONST(a) ((void *)(unsigned long)(const void *)(a))
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return execvp(file, UNCONST(argv));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt#undef UNCONST
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntstatic
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntatf_error_t
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntlist_to_array(const atf_list_t *l, const char ***ap)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt atf_error_t err;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const char **a;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt a = (const char **)malloc((atf_list_size(l) + 1) * sizeof(const char *));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (a == NULL)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt err = atf_no_memory_error();
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt else {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const char **aiter;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt atf_list_citer_t liter;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt aiter = a;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt atf_list_for_each_c(liter, l) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt *aiter = (const char *)atf_list_citer_data(liter);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt aiter++;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt *aiter = NULL;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt err = atf_no_error();
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt *ap = a;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return err;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntstruct exec_args {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const atf_fs_path_t *m_prog;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const char *const *m_argv;
a747113422afaa29ce72d2c5ba7f0b7ea9ec2054Evan Hunt void (*m_prehook)(void);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt};
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntstatic
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntvoid
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntdo_exec(void *v)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt struct exec_args *ea = v;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
a747113422afaa29ce72d2c5ba7f0b7ea9ec2054Evan Hunt if (ea->m_prehook != NULL)
a747113422afaa29ce72d2c5ba7f0b7ea9ec2054Evan Hunt ea->m_prehook();
a747113422afaa29ce72d2c5ba7f0b7ea9ec2054Evan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const int ret = const_execvp(atf_fs_path_cstring(ea->m_prog), ea->m_argv);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const int errnocopy = errno;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt INV(ret == -1);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt fprintf(stderr, "exec(%s) failed: %s\n",
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt atf_fs_path_cstring(ea->m_prog), strerror(errnocopy));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt exit(EXIT_FAILURE);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntatf_error_t
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntatf_process_exec_array(atf_process_status_t *s,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const atf_fs_path_t *prog,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const char *const *argv,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const atf_process_stream_t *outsb,
a747113422afaa29ce72d2c5ba7f0b7ea9ec2054Evan Hunt const atf_process_stream_t *errsb,
a747113422afaa29ce72d2c5ba7f0b7ea9ec2054Evan Hunt void (*prehook)(void))
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt atf_error_t err;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt atf_process_child_t c;
a747113422afaa29ce72d2c5ba7f0b7ea9ec2054Evan Hunt struct exec_args ea = { prog, argv, prehook };
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt PRE(outsb == NULL ||
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt atf_process_stream_type(outsb) != atf_process_stream_type_capture);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt PRE(errsb == NULL ||
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt atf_process_stream_type(errsb) != atf_process_stream_type_capture);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt err = atf_process_fork(&c, do_exec, outsb, errsb, &ea);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (atf_is_error(err))
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt goto out;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntagain:
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt err = atf_process_child_wait(&c, s);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (atf_is_error(err)) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt INV(atf_error_is(err, "libc") && atf_libc_error_code(err) == EINTR);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt atf_error_free(err);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt goto again;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntout:
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return err;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntatf_error_t
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntatf_process_exec_list(atf_process_status_t *s,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const atf_fs_path_t *prog,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const atf_list_t *argv,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const atf_process_stream_t *outsb,
a747113422afaa29ce72d2c5ba7f0b7ea9ec2054Evan Hunt const atf_process_stream_t *errsb,
a747113422afaa29ce72d2c5ba7f0b7ea9ec2054Evan Hunt void (*prehook)(void))
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt atf_error_t err;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const char **argv2;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt PRE(outsb == NULL ||
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt atf_process_stream_type(outsb) != atf_process_stream_type_capture);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt PRE(errsb == NULL ||
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt atf_process_stream_type(errsb) != atf_process_stream_type_capture);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt argv2 = NULL; /* Silence GCC warning. */
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt err = list_to_array(argv, &argv2);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (atf_is_error(err))
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt goto out;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
a747113422afaa29ce72d2c5ba7f0b7ea9ec2054Evan Hunt err = atf_process_exec_array(s, prog, argv2, outsb, errsb, prehook);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt free(argv2);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntout:
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return err;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}