Home | History | Annotate | Line # | Download | only in atf-c
check.c revision 1.1.1.4
      1      1.1  jmmv /*
      2      1.1  jmmv  * Automated Testing Framework (atf)
      3      1.1  jmmv  *
      4  1.1.1.3  jmmv  * Copyright (c) 2008, 2009, 2010 The NetBSD Foundation, Inc.
      5      1.1  jmmv  * All rights reserved.
      6      1.1  jmmv  *
      7      1.1  jmmv  * Redistribution and use in source and binary forms, with or without
      8      1.1  jmmv  * modification, are permitted provided that the following conditions
      9      1.1  jmmv  * are met:
     10      1.1  jmmv  * 1. Redistributions of source code must retain the above copyright
     11      1.1  jmmv  *    notice, this list of conditions and the following disclaimer.
     12      1.1  jmmv  * 2. Redistributions in binary form must reproduce the above copyright
     13      1.1  jmmv  *    notice, this list of conditions and the following disclaimer in the
     14      1.1  jmmv  *    documentation and/or other materials provided with the distribution.
     15      1.1  jmmv  *
     16      1.1  jmmv  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
     17      1.1  jmmv  * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
     18      1.1  jmmv  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     19      1.1  jmmv  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     20      1.1  jmmv  * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
     21      1.1  jmmv  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     22      1.1  jmmv  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
     23      1.1  jmmv  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     24      1.1  jmmv  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
     25      1.1  jmmv  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     26      1.1  jmmv  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
     27      1.1  jmmv  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     28      1.1  jmmv  */
     29      1.1  jmmv 
     30      1.1  jmmv #include <sys/wait.h>
     31      1.1  jmmv 
     32      1.1  jmmv #include <errno.h>
     33  1.1.1.2  jmmv #include <fcntl.h>
     34      1.1  jmmv #include <stdio.h>
     35      1.1  jmmv #include <stdlib.h>
     36      1.1  jmmv #include <string.h>
     37      1.1  jmmv #include <unistd.h>
     38      1.1  jmmv 
     39  1.1.1.2  jmmv #include "atf-c/build.h"
     40      1.1  jmmv #include "atf-c/check.h"
     41      1.1  jmmv #include "atf-c/config.h"
     42  1.1.1.2  jmmv #include "atf-c/defs.h"
     43      1.1  jmmv #include "atf-c/dynstr.h"
     44      1.1  jmmv #include "atf-c/error.h"
     45      1.1  jmmv #include "atf-c/fs.h"
     46  1.1.1.2  jmmv #include "atf-c/list.h"
     47      1.1  jmmv #include "atf-c/process.h"
     48      1.1  jmmv #include "atf-c/sanity.h"
     49      1.1  jmmv 
     50      1.1  jmmv /* ---------------------------------------------------------------------
     51      1.1  jmmv  * Auxiliary functions.
     52      1.1  jmmv  * --------------------------------------------------------------------- */
     53      1.1  jmmv 
     54      1.1  jmmv static
     55      1.1  jmmv atf_error_t
     56  1.1.1.2  jmmv create_tmpdir(atf_fs_path_t *dir)
     57      1.1  jmmv {
     58      1.1  jmmv     atf_error_t err;
     59      1.1  jmmv 
     60  1.1.1.2  jmmv     err = atf_fs_path_init_fmt(dir, "%s/check.XXXXXX",
     61  1.1.1.2  jmmv                                atf_config_get("atf_workdir"));
     62      1.1  jmmv     if (atf_is_error(err))
     63      1.1  jmmv         goto out;
     64      1.1  jmmv 
     65  1.1.1.2  jmmv     err = atf_fs_mkdtemp(dir);
     66  1.1.1.2  jmmv     if (atf_is_error(err)) {
     67  1.1.1.2  jmmv         atf_fs_path_fini(dir);
     68  1.1.1.2  jmmv         goto out;
     69  1.1.1.2  jmmv     }
     70      1.1  jmmv 
     71      1.1  jmmv     INV(!atf_is_error(err));
     72      1.1  jmmv out:
     73      1.1  jmmv     return err;
     74      1.1  jmmv }
     75      1.1  jmmv 
     76      1.1  jmmv static
     77      1.1  jmmv void
     78  1.1.1.2  jmmv cleanup_tmpdir(const atf_fs_path_t *dir, const atf_fs_path_t *outfile,
     79  1.1.1.2  jmmv                const atf_fs_path_t *errfile)
     80  1.1.1.2  jmmv {
     81  1.1.1.2  jmmv     {
     82  1.1.1.2  jmmv         atf_error_t err = atf_fs_unlink(outfile);
     83  1.1.1.2  jmmv         if (atf_is_error(err)) {
     84  1.1.1.2  jmmv             INV(atf_error_is(err, "libc") &&
     85  1.1.1.2  jmmv                 atf_libc_error_code(err) == ENOENT);
     86  1.1.1.2  jmmv             atf_error_free(err);
     87  1.1.1.2  jmmv         } else
     88  1.1.1.2  jmmv             INV(!atf_is_error(err));
     89  1.1.1.2  jmmv     }
     90  1.1.1.2  jmmv 
     91  1.1.1.2  jmmv     {
     92  1.1.1.2  jmmv         atf_error_t err = atf_fs_unlink(errfile);
     93  1.1.1.2  jmmv         if (atf_is_error(err)) {
     94  1.1.1.2  jmmv             INV(atf_error_is(err, "libc") &&
     95  1.1.1.2  jmmv                 atf_libc_error_code(err) == ENOENT);
     96  1.1.1.2  jmmv             atf_error_free(err);
     97  1.1.1.2  jmmv         } else
     98  1.1.1.2  jmmv             INV(!atf_is_error(err));
     99  1.1.1.2  jmmv     }
    100  1.1.1.2  jmmv 
    101  1.1.1.2  jmmv     {
    102  1.1.1.2  jmmv         atf_error_t err = atf_fs_rmdir(dir);
    103  1.1.1.2  jmmv         INV(!atf_is_error(err));
    104  1.1.1.2  jmmv     }
    105  1.1.1.2  jmmv }
    106  1.1.1.2  jmmv 
    107  1.1.1.2  jmmv static
    108  1.1.1.2  jmmv int
    109  1.1.1.2  jmmv const_execvp(const char *file, const char *const *argv)
    110  1.1.1.2  jmmv {
    111  1.1.1.2  jmmv #define UNCONST(a) ((void *)(unsigned long)(const void *)(a))
    112  1.1.1.2  jmmv     return execvp(file, UNCONST(argv));
    113  1.1.1.2  jmmv #undef UNCONST
    114  1.1.1.2  jmmv }
    115  1.1.1.2  jmmv 
    116  1.1.1.2  jmmv static
    117  1.1.1.2  jmmv atf_error_t
    118  1.1.1.2  jmmv init_sb(const atf_fs_path_t *path, atf_process_stream_t *sb)
    119  1.1.1.2  jmmv {
    120  1.1.1.2  jmmv     atf_error_t err;
    121  1.1.1.2  jmmv 
    122  1.1.1.2  jmmv     if (path == NULL)
    123  1.1.1.2  jmmv         err = atf_process_stream_init_inherit(sb);
    124  1.1.1.2  jmmv     else
    125  1.1.1.2  jmmv         err = atf_process_stream_init_redirect_path(sb, path);
    126  1.1.1.2  jmmv 
    127  1.1.1.2  jmmv     return err;
    128  1.1.1.2  jmmv }
    129  1.1.1.2  jmmv 
    130  1.1.1.2  jmmv static
    131  1.1.1.2  jmmv atf_error_t
    132  1.1.1.2  jmmv init_sbs(const atf_fs_path_t *outfile, atf_process_stream_t *outsb,
    133  1.1.1.2  jmmv          const atf_fs_path_t *errfile, atf_process_stream_t *errsb)
    134      1.1  jmmv {
    135  1.1.1.2  jmmv     atf_error_t err;
    136  1.1.1.2  jmmv 
    137  1.1.1.2  jmmv     err = init_sb(outfile, outsb);
    138  1.1.1.2  jmmv     if (atf_is_error(err))
    139  1.1.1.2  jmmv         goto out;
    140      1.1  jmmv 
    141  1.1.1.2  jmmv     err = init_sb(errfile, errsb);
    142  1.1.1.2  jmmv     if (atf_is_error(err)) {
    143  1.1.1.2  jmmv         atf_process_stream_fini(outsb);
    144  1.1.1.2  jmmv         goto out;
    145  1.1.1.2  jmmv     }
    146  1.1.1.2  jmmv 
    147  1.1.1.2  jmmv out:
    148  1.1.1.2  jmmv     return err;
    149  1.1.1.2  jmmv }
    150  1.1.1.2  jmmv 
    151  1.1.1.2  jmmv struct exec_data {
    152  1.1.1.2  jmmv     const char *const *m_argv;
    153  1.1.1.2  jmmv };
    154  1.1.1.2  jmmv 
    155  1.1.1.2  jmmv static void exec_child(void *) ATF_DEFS_ATTRIBUTE_NORETURN;
    156  1.1.1.2  jmmv 
    157  1.1.1.2  jmmv static
    158  1.1.1.2  jmmv void
    159  1.1.1.2  jmmv exec_child(void *v)
    160  1.1.1.2  jmmv {
    161  1.1.1.2  jmmv     struct exec_data *ea = v;
    162      1.1  jmmv 
    163  1.1.1.2  jmmv     const_execvp(ea->m_argv[0], ea->m_argv);
    164  1.1.1.2  jmmv     fprintf(stderr, "execvp(%s) failed: %s\n", ea->m_argv[0], strerror(errno));
    165  1.1.1.2  jmmv     exit(127);
    166      1.1  jmmv }
    167      1.1  jmmv 
    168      1.1  jmmv static
    169      1.1  jmmv atf_error_t
    170  1.1.1.2  jmmv fork_and_wait(const char *const *argv, const atf_fs_path_t *outfile,
    171  1.1.1.2  jmmv               const atf_fs_path_t *errfile, atf_process_status_t *status)
    172      1.1  jmmv {
    173      1.1  jmmv     atf_error_t err;
    174  1.1.1.2  jmmv     atf_process_child_t child;
    175  1.1.1.2  jmmv     atf_process_stream_t outsb, errsb;
    176  1.1.1.2  jmmv     struct exec_data ea = { argv };
    177      1.1  jmmv 
    178  1.1.1.2  jmmv     err = init_sbs(outfile, &outsb, errfile, &errsb);
    179      1.1  jmmv     if (atf_is_error(err))
    180      1.1  jmmv         goto out;
    181      1.1  jmmv 
    182  1.1.1.2  jmmv     err = atf_process_fork(&child, exec_child, &outsb, &errsb, &ea);
    183  1.1.1.2  jmmv     if (atf_is_error(err))
    184  1.1.1.2  jmmv         goto out_sbs;
    185  1.1.1.2  jmmv 
    186  1.1.1.2  jmmv     err = atf_process_child_wait(&child, status);
    187  1.1.1.2  jmmv 
    188  1.1.1.2  jmmv out_sbs:
    189  1.1.1.2  jmmv     atf_process_stream_fini(&errsb);
    190  1.1.1.2  jmmv     atf_process_stream_fini(&outsb);
    191  1.1.1.2  jmmv out:
    192  1.1.1.2  jmmv     return err;
    193  1.1.1.2  jmmv }
    194  1.1.1.2  jmmv 
    195  1.1.1.2  jmmv static
    196  1.1.1.2  jmmv void
    197  1.1.1.2  jmmv update_success_from_status(const char *progname,
    198  1.1.1.2  jmmv                            const atf_process_status_t *status, bool *success)
    199  1.1.1.2  jmmv {
    200  1.1.1.2  jmmv     bool s = atf_process_status_exited(status) &&
    201  1.1.1.2  jmmv              atf_process_status_exitstatus(status) == EXIT_SUCCESS;
    202  1.1.1.2  jmmv 
    203  1.1.1.2  jmmv     if (atf_process_status_exited(status)) {
    204  1.1.1.2  jmmv         if (atf_process_status_exitstatus(status) == EXIT_SUCCESS)
    205  1.1.1.2  jmmv             INV(s);
    206  1.1.1.2  jmmv         else {
    207  1.1.1.2  jmmv             INV(!s);
    208  1.1.1.2  jmmv             fprintf(stderr, "%s failed with exit code %d\n", progname,
    209  1.1.1.2  jmmv                     atf_process_status_exitstatus(status));
    210  1.1.1.2  jmmv         }
    211  1.1.1.2  jmmv     } else if (atf_process_status_signaled(status)) {
    212  1.1.1.2  jmmv         INV(!s);
    213  1.1.1.2  jmmv         fprintf(stderr, "%s failed due to signal %d%s\n", progname,
    214  1.1.1.2  jmmv                 atf_process_status_termsig(status),
    215  1.1.1.2  jmmv                 atf_process_status_coredump(status) ? " (core dumped)" : "");
    216      1.1  jmmv     } else {
    217  1.1.1.2  jmmv         INV(!s);
    218  1.1.1.2  jmmv         fprintf(stderr, "%s failed due to unknown reason\n", progname);
    219  1.1.1.2  jmmv     }
    220  1.1.1.2  jmmv 
    221  1.1.1.2  jmmv     *success = s;
    222  1.1.1.2  jmmv }
    223  1.1.1.2  jmmv 
    224  1.1.1.2  jmmv static
    225  1.1.1.2  jmmv atf_error_t
    226  1.1.1.2  jmmv array_to_list(const char *const *a, atf_list_t *l)
    227  1.1.1.2  jmmv {
    228  1.1.1.2  jmmv     atf_error_t err;
    229  1.1.1.2  jmmv 
    230  1.1.1.2  jmmv     err = atf_list_init(l);
    231  1.1.1.2  jmmv     if (atf_is_error(err))
    232  1.1.1.2  jmmv         goto out;
    233  1.1.1.2  jmmv 
    234  1.1.1.2  jmmv     while (*a != NULL) {
    235  1.1.1.2  jmmv         char *item = strdup(*a);
    236  1.1.1.2  jmmv         if (item == NULL) {
    237  1.1.1.2  jmmv             err = atf_no_memory_error();
    238  1.1.1.2  jmmv             goto out;
    239      1.1  jmmv         }
    240  1.1.1.2  jmmv 
    241  1.1.1.2  jmmv         err = atf_list_append(l, item, true);
    242  1.1.1.2  jmmv         if (atf_is_error(err))
    243  1.1.1.2  jmmv             goto out;
    244  1.1.1.2  jmmv 
    245  1.1.1.2  jmmv         a++;
    246      1.1  jmmv     }
    247      1.1  jmmv 
    248      1.1  jmmv out:
    249      1.1  jmmv     return err;
    250      1.1  jmmv }
    251      1.1  jmmv 
    252  1.1.1.2  jmmv static
    253  1.1.1.2  jmmv atf_error_t
    254  1.1.1.2  jmmv list_to_array(const atf_list_t *l, const char ***ap)
    255  1.1.1.2  jmmv {
    256  1.1.1.2  jmmv     atf_error_t err;
    257  1.1.1.2  jmmv     const char **a;
    258  1.1.1.2  jmmv 
    259  1.1.1.2  jmmv     a = (const char **)malloc((atf_list_size(l) + 1) * sizeof(const char *));
    260  1.1.1.2  jmmv     if (a == NULL)
    261  1.1.1.2  jmmv         err = atf_no_memory_error();
    262  1.1.1.2  jmmv     else {
    263  1.1.1.2  jmmv         const char **aiter;
    264  1.1.1.2  jmmv         atf_list_citer_t liter;
    265  1.1.1.2  jmmv 
    266  1.1.1.2  jmmv         aiter = a;
    267  1.1.1.2  jmmv         atf_list_for_each_c(liter, l) {
    268  1.1.1.2  jmmv             *aiter = (const char *)atf_list_citer_data(liter);
    269  1.1.1.2  jmmv             aiter++;
    270  1.1.1.2  jmmv         }
    271  1.1.1.2  jmmv         *aiter = NULL;
    272  1.1.1.2  jmmv 
    273  1.1.1.2  jmmv         err = atf_no_error();
    274  1.1.1.2  jmmv         *ap = a;
    275  1.1.1.2  jmmv     }
    276  1.1.1.2  jmmv 
    277  1.1.1.2  jmmv     return err;
    278  1.1.1.2  jmmv }
    279  1.1.1.2  jmmv 
    280  1.1.1.2  jmmv static
    281  1.1.1.2  jmmv void
    282  1.1.1.2  jmmv print_list(const atf_list_t *l, const char *pfx)
    283  1.1.1.2  jmmv {
    284  1.1.1.2  jmmv     atf_list_citer_t iter;
    285  1.1.1.2  jmmv 
    286  1.1.1.2  jmmv     printf("%s", pfx);
    287  1.1.1.2  jmmv     atf_list_for_each_c(iter, l)
    288  1.1.1.2  jmmv         printf(" %s", (const char *)atf_list_citer_data(iter));
    289  1.1.1.2  jmmv     printf("\n");
    290  1.1.1.2  jmmv }
    291  1.1.1.2  jmmv 
    292  1.1.1.2  jmmv static
    293  1.1.1.2  jmmv atf_error_t
    294  1.1.1.2  jmmv fork_and_wait_list(const atf_list_t *argvl, const atf_fs_path_t *outfile,
    295  1.1.1.2  jmmv                    const atf_fs_path_t *errfile, atf_process_status_t *status)
    296  1.1.1.2  jmmv {
    297  1.1.1.2  jmmv     atf_error_t err;
    298  1.1.1.2  jmmv     const char **argva;
    299  1.1.1.2  jmmv 
    300  1.1.1.2  jmmv     err = list_to_array(argvl, &argva);
    301  1.1.1.2  jmmv     if (atf_is_error(err))
    302  1.1.1.2  jmmv         goto out;
    303  1.1.1.2  jmmv 
    304  1.1.1.2  jmmv     err = fork_and_wait(argva, outfile, errfile, status);
    305  1.1.1.2  jmmv 
    306  1.1.1.2  jmmv     free(argva);
    307  1.1.1.2  jmmv out:
    308  1.1.1.2  jmmv     return err;
    309  1.1.1.2  jmmv }
    310  1.1.1.2  jmmv 
    311  1.1.1.2  jmmv static
    312  1.1.1.2  jmmv atf_error_t
    313  1.1.1.2  jmmv check_build_run(const atf_list_t *argv, bool *success)
    314  1.1.1.2  jmmv {
    315  1.1.1.2  jmmv     atf_error_t err;
    316  1.1.1.2  jmmv     atf_process_status_t status;
    317  1.1.1.2  jmmv 
    318  1.1.1.2  jmmv     print_list(argv, ">");
    319  1.1.1.2  jmmv 
    320  1.1.1.2  jmmv     err = fork_and_wait_list(argv, NULL, NULL, &status);
    321  1.1.1.2  jmmv     if (atf_is_error(err))
    322  1.1.1.2  jmmv         goto out;
    323  1.1.1.2  jmmv 
    324  1.1.1.2  jmmv     update_success_from_status((const char *)atf_list_index_c(argv, 0),
    325  1.1.1.2  jmmv                                &status, success);
    326  1.1.1.2  jmmv     atf_process_status_fini(&status);
    327  1.1.1.2  jmmv 
    328  1.1.1.2  jmmv     INV(!atf_is_error(err));
    329  1.1.1.2  jmmv out:
    330  1.1.1.2  jmmv     return err;
    331  1.1.1.2  jmmv }
    332  1.1.1.2  jmmv 
    333      1.1  jmmv /* ---------------------------------------------------------------------
    334      1.1  jmmv  * The "atf_check_result" type.
    335      1.1  jmmv  * --------------------------------------------------------------------- */
    336      1.1  jmmv 
    337  1.1.1.2  jmmv static
    338      1.1  jmmv atf_error_t
    339  1.1.1.2  jmmv atf_check_result_init(atf_check_result_t *r, const char *const *argv,
    340  1.1.1.2  jmmv                       const atf_fs_path_t *dir)
    341      1.1  jmmv {
    342      1.1  jmmv     atf_error_t err;
    343      1.1  jmmv     const char *workdir;
    344      1.1  jmmv 
    345      1.1  jmmv     workdir = atf_config_get("atf_workdir");
    346      1.1  jmmv 
    347  1.1.1.2  jmmv     err = array_to_list(argv, &r->m_argv);
    348      1.1  jmmv     if (atf_is_error(err))
    349      1.1  jmmv         goto out;
    350      1.1  jmmv 
    351  1.1.1.2  jmmv     err = atf_fs_path_copy(&r->m_dir, dir);
    352  1.1.1.2  jmmv     if (atf_is_error(err))
    353  1.1.1.2  jmmv         goto err_argv;
    354  1.1.1.2  jmmv 
    355  1.1.1.2  jmmv     err = atf_fs_path_init_fmt(&r->m_stdout, "%s/stdout",
    356  1.1.1.2  jmmv                                atf_fs_path_cstring(dir));
    357  1.1.1.2  jmmv     if (atf_is_error(err))
    358  1.1.1.2  jmmv         goto err_dir;
    359  1.1.1.2  jmmv 
    360  1.1.1.2  jmmv     err = atf_fs_path_init_fmt(&r->m_stderr, "%s/stderr",
    361  1.1.1.2  jmmv                                atf_fs_path_cstring(dir));
    362      1.1  jmmv     if (atf_is_error(err))
    363      1.1  jmmv         goto err_stdout;
    364      1.1  jmmv 
    365      1.1  jmmv     INV(!atf_is_error(err));
    366      1.1  jmmv     goto out;
    367      1.1  jmmv 
    368      1.1  jmmv err_stdout:
    369      1.1  jmmv     atf_fs_path_fini(&r->m_stdout);
    370  1.1.1.2  jmmv err_dir:
    371  1.1.1.2  jmmv     atf_fs_path_fini(&r->m_dir);
    372  1.1.1.2  jmmv err_argv:
    373  1.1.1.2  jmmv     atf_list_fini(&r->m_argv);
    374      1.1  jmmv out:
    375      1.1  jmmv     return err;
    376      1.1  jmmv }
    377      1.1  jmmv 
    378      1.1  jmmv void
    379      1.1  jmmv atf_check_result_fini(atf_check_result_t *r)
    380      1.1  jmmv {
    381  1.1.1.2  jmmv     atf_process_status_fini(&r->m_status);
    382      1.1  jmmv 
    383  1.1.1.2  jmmv     cleanup_tmpdir(&r->m_dir, &r->m_stdout, &r->m_stderr);
    384  1.1.1.2  jmmv     atf_fs_path_fini(&r->m_stdout);
    385      1.1  jmmv     atf_fs_path_fini(&r->m_stderr);
    386  1.1.1.2  jmmv     atf_fs_path_fini(&r->m_dir);
    387  1.1.1.2  jmmv 
    388  1.1.1.2  jmmv     atf_list_fini(&r->m_argv);
    389      1.1  jmmv }
    390      1.1  jmmv 
    391  1.1.1.2  jmmv const atf_list_t *
    392  1.1.1.2  jmmv atf_check_result_argv(const atf_check_result_t *r)
    393  1.1.1.2  jmmv {
    394  1.1.1.2  jmmv     return &r->m_argv;
    395  1.1.1.2  jmmv }
    396  1.1.1.2  jmmv 
    397      1.1  jmmv const atf_fs_path_t *
    398      1.1  jmmv atf_check_result_stdout(const atf_check_result_t *r)
    399      1.1  jmmv {
    400      1.1  jmmv     return &r->m_stdout;
    401      1.1  jmmv }
    402      1.1  jmmv 
    403      1.1  jmmv const atf_fs_path_t *
    404      1.1  jmmv atf_check_result_stderr(const atf_check_result_t *r)
    405      1.1  jmmv {
    406      1.1  jmmv     return &r->m_stderr;
    407      1.1  jmmv }
    408      1.1  jmmv 
    409      1.1  jmmv bool
    410      1.1  jmmv atf_check_result_exited(const atf_check_result_t *r)
    411      1.1  jmmv {
    412  1.1.1.2  jmmv     return atf_process_status_exited(&r->m_status);
    413      1.1  jmmv }
    414      1.1  jmmv 
    415      1.1  jmmv int
    416      1.1  jmmv atf_check_result_exitcode(const atf_check_result_t *r)
    417      1.1  jmmv {
    418  1.1.1.2  jmmv     return atf_process_status_exitstatus(&r->m_status);
    419      1.1  jmmv }
    420      1.1  jmmv 
    421  1.1.1.4  jmmv bool
    422  1.1.1.4  jmmv atf_check_result_signaled(const atf_check_result_t *r)
    423  1.1.1.4  jmmv {
    424  1.1.1.4  jmmv     return atf_process_status_signaled(&r->m_status);
    425  1.1.1.4  jmmv }
    426  1.1.1.4  jmmv 
    427  1.1.1.4  jmmv int
    428  1.1.1.4  jmmv atf_check_result_termsig(const atf_check_result_t *r)
    429  1.1.1.4  jmmv {
    430  1.1.1.4  jmmv     return atf_process_status_termsig(&r->m_status);
    431  1.1.1.4  jmmv }
    432  1.1.1.4  jmmv 
    433      1.1  jmmv /* ---------------------------------------------------------------------
    434      1.1  jmmv  * Free functions.
    435      1.1  jmmv  * --------------------------------------------------------------------- */
    436      1.1  jmmv 
    437  1.1.1.2  jmmv /* XXX: This function shouldn't be in this module.  It messes with stdout
    438  1.1.1.2  jmmv  * and stderr, and it provides a very high-end interface.  This belongs,
    439  1.1.1.2  jmmv  * probably, somewhere related to test cases (such as in the tc module). */
    440  1.1.1.2  jmmv atf_error_t
    441  1.1.1.2  jmmv atf_check_build_c_o(const char *sfile,
    442  1.1.1.2  jmmv                     const char *ofile,
    443  1.1.1.2  jmmv                     const char *const optargs[],
    444  1.1.1.2  jmmv                     bool *success)
    445  1.1.1.2  jmmv {
    446  1.1.1.2  jmmv     atf_error_t err;
    447  1.1.1.2  jmmv     atf_list_t argv;
    448  1.1.1.2  jmmv 
    449  1.1.1.2  jmmv     err = atf_build_c_o(sfile, ofile, optargs, &argv);
    450  1.1.1.2  jmmv     if (atf_is_error(err))
    451  1.1.1.2  jmmv         goto out;
    452  1.1.1.2  jmmv 
    453  1.1.1.2  jmmv     err = check_build_run(&argv, success);
    454  1.1.1.2  jmmv 
    455  1.1.1.2  jmmv     atf_list_fini(&argv);
    456  1.1.1.2  jmmv out:
    457  1.1.1.2  jmmv     return err;
    458  1.1.1.2  jmmv }
    459  1.1.1.2  jmmv 
    460      1.1  jmmv atf_error_t
    461  1.1.1.2  jmmv atf_check_build_cpp(const char *sfile,
    462  1.1.1.2  jmmv                     const char *ofile,
    463  1.1.1.2  jmmv                     const char *const optargs[],
    464  1.1.1.2  jmmv                     bool *success)
    465      1.1  jmmv {
    466      1.1  jmmv     atf_error_t err;
    467  1.1.1.2  jmmv     atf_list_t argv;
    468      1.1  jmmv 
    469  1.1.1.2  jmmv     err = atf_build_cpp(sfile, ofile, optargs, &argv);
    470      1.1  jmmv     if (atf_is_error(err))
    471      1.1  jmmv         goto out;
    472      1.1  jmmv 
    473  1.1.1.2  jmmv     err = check_build_run(&argv, success);
    474  1.1.1.2  jmmv 
    475  1.1.1.2  jmmv     atf_list_fini(&argv);
    476  1.1.1.2  jmmv out:
    477  1.1.1.2  jmmv     return err;
    478  1.1.1.2  jmmv }
    479  1.1.1.2  jmmv 
    480  1.1.1.2  jmmv atf_error_t
    481  1.1.1.2  jmmv atf_check_build_cxx_o(const char *sfile,
    482  1.1.1.2  jmmv                       const char *ofile,
    483  1.1.1.2  jmmv                       const char *const optargs[],
    484  1.1.1.2  jmmv                       bool *success)
    485  1.1.1.2  jmmv {
    486  1.1.1.2  jmmv     atf_error_t err;
    487  1.1.1.2  jmmv     atf_list_t argv;
    488  1.1.1.2  jmmv 
    489  1.1.1.2  jmmv     err = atf_build_cxx_o(sfile, ofile, optargs, &argv);
    490      1.1  jmmv     if (atf_is_error(err))
    491  1.1.1.2  jmmv         goto out;
    492  1.1.1.2  jmmv 
    493  1.1.1.2  jmmv     err = check_build_run(&argv, success);
    494      1.1  jmmv 
    495  1.1.1.2  jmmv     atf_list_fini(&argv);
    496  1.1.1.2  jmmv out:
    497  1.1.1.2  jmmv     return err;
    498  1.1.1.2  jmmv }
    499  1.1.1.2  jmmv 
    500  1.1.1.2  jmmv atf_error_t
    501  1.1.1.2  jmmv atf_check_exec_array(const char *const *argv, atf_check_result_t *r)
    502  1.1.1.2  jmmv {
    503  1.1.1.2  jmmv     atf_error_t err;
    504  1.1.1.2  jmmv     atf_fs_path_t dir;
    505  1.1.1.2  jmmv 
    506  1.1.1.2  jmmv     err = create_tmpdir(&dir);
    507  1.1.1.2  jmmv     if (atf_is_error(err))
    508  1.1.1.2  jmmv         goto out;
    509  1.1.1.2  jmmv 
    510  1.1.1.2  jmmv     err = atf_check_result_init(r, argv, &dir);
    511      1.1  jmmv     if (atf_is_error(err))
    512  1.1.1.2  jmmv         goto err_dir;
    513  1.1.1.2  jmmv 
    514  1.1.1.2  jmmv     err = fork_and_wait(argv, &r->m_stdout, &r->m_stderr, &r->m_status);
    515  1.1.1.2  jmmv     if (atf_is_error(err))
    516  1.1.1.2  jmmv         goto err_r;
    517      1.1  jmmv 
    518      1.1  jmmv     INV(!atf_is_error(err));
    519  1.1.1.2  jmmv     goto out_dir;
    520      1.1  jmmv 
    521      1.1  jmmv err_r:
    522      1.1  jmmv     atf_check_result_fini(r);
    523  1.1.1.2  jmmv err_dir:
    524  1.1.1.2  jmmv     {
    525  1.1.1.2  jmmv         atf_error_t err2 = atf_fs_rmdir(&dir);
    526  1.1.1.2  jmmv         INV(!atf_is_error(err2));
    527  1.1.1.2  jmmv     }
    528  1.1.1.2  jmmv out_dir:
    529  1.1.1.2  jmmv     atf_fs_path_fini(&dir);
    530  1.1.1.2  jmmv out:
    531  1.1.1.2  jmmv     return err;
    532  1.1.1.2  jmmv }
    533  1.1.1.2  jmmv 
    534  1.1.1.2  jmmv atf_error_t
    535  1.1.1.2  jmmv atf_check_exec_list(const atf_list_t *argv, atf_check_result_t *r)
    536  1.1.1.2  jmmv {
    537  1.1.1.2  jmmv     atf_error_t err;
    538  1.1.1.2  jmmv     const char **argv2;
    539  1.1.1.2  jmmv 
    540  1.1.1.2  jmmv     argv2 = NULL; /* Silence GCC warning. */
    541  1.1.1.2  jmmv     err = list_to_array(argv, &argv2);
    542  1.1.1.2  jmmv     if (atf_is_error(err))
    543  1.1.1.2  jmmv         goto out;
    544  1.1.1.2  jmmv 
    545  1.1.1.2  jmmv     err = atf_check_exec_array(argv2, r);
    546  1.1.1.2  jmmv 
    547  1.1.1.2  jmmv     free(argv2);
    548      1.1  jmmv out:
    549      1.1  jmmv     return err;
    550      1.1  jmmv }
    551