Home | History | Annotate | Line # | Download | only in atf-c
      1      1.1  jmmv /*
      2      1.1  jmmv  * Automated Testing Framework (atf)
      3      1.1  jmmv  *
      4  1.1.1.7  jmmv  * Copyright (c) 2008 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/error.h"
     44  1.1.1.5  jmmv #include "atf-c/utils.h"
     45  1.1.1.5  jmmv 
     46  1.1.1.5  jmmv #include "detail/dynstr.h"
     47  1.1.1.5  jmmv #include "detail/fs.h"
     48  1.1.1.5  jmmv #include "detail/list.h"
     49  1.1.1.5  jmmv #include "detail/process.h"
     50  1.1.1.5  jmmv #include "detail/sanity.h"
     51      1.1  jmmv 
     52      1.1  jmmv /* ---------------------------------------------------------------------
     53      1.1  jmmv  * Auxiliary functions.
     54      1.1  jmmv  * --------------------------------------------------------------------- */
     55      1.1  jmmv 
     56      1.1  jmmv static
     57      1.1  jmmv atf_error_t
     58  1.1.1.2  jmmv create_tmpdir(atf_fs_path_t *dir)
     59      1.1  jmmv {
     60      1.1  jmmv     atf_error_t err;
     61      1.1  jmmv 
     62  1.1.1.2  jmmv     err = atf_fs_path_init_fmt(dir, "%s/check.XXXXXX",
     63  1.1.1.2  jmmv                                atf_config_get("atf_workdir"));
     64      1.1  jmmv     if (atf_is_error(err))
     65      1.1  jmmv         goto out;
     66      1.1  jmmv 
     67  1.1.1.2  jmmv     err = atf_fs_mkdtemp(dir);
     68  1.1.1.2  jmmv     if (atf_is_error(err)) {
     69  1.1.1.2  jmmv         atf_fs_path_fini(dir);
     70  1.1.1.2  jmmv         goto out;
     71  1.1.1.2  jmmv     }
     72      1.1  jmmv 
     73      1.1  jmmv     INV(!atf_is_error(err));
     74      1.1  jmmv out:
     75      1.1  jmmv     return err;
     76      1.1  jmmv }
     77      1.1  jmmv 
     78      1.1  jmmv static
     79      1.1  jmmv void
     80  1.1.1.2  jmmv cleanup_tmpdir(const atf_fs_path_t *dir, const atf_fs_path_t *outfile,
     81  1.1.1.2  jmmv                const atf_fs_path_t *errfile)
     82  1.1.1.2  jmmv {
     83  1.1.1.2  jmmv     {
     84  1.1.1.2  jmmv         atf_error_t err = atf_fs_unlink(outfile);
     85  1.1.1.2  jmmv         if (atf_is_error(err)) {
     86  1.1.1.2  jmmv             INV(atf_error_is(err, "libc") &&
     87  1.1.1.2  jmmv                 atf_libc_error_code(err) == ENOENT);
     88  1.1.1.2  jmmv             atf_error_free(err);
     89  1.1.1.2  jmmv         } else
     90  1.1.1.2  jmmv             INV(!atf_is_error(err));
     91  1.1.1.2  jmmv     }
     92  1.1.1.2  jmmv 
     93  1.1.1.2  jmmv     {
     94  1.1.1.2  jmmv         atf_error_t err = atf_fs_unlink(errfile);
     95  1.1.1.2  jmmv         if (atf_is_error(err)) {
     96  1.1.1.2  jmmv             INV(atf_error_is(err, "libc") &&
     97  1.1.1.2  jmmv                 atf_libc_error_code(err) == ENOENT);
     98  1.1.1.2  jmmv             atf_error_free(err);
     99  1.1.1.2  jmmv         } else
    100  1.1.1.2  jmmv             INV(!atf_is_error(err));
    101  1.1.1.2  jmmv     }
    102  1.1.1.2  jmmv 
    103  1.1.1.2  jmmv     {
    104  1.1.1.2  jmmv         atf_error_t err = atf_fs_rmdir(dir);
    105  1.1.1.2  jmmv         INV(!atf_is_error(err));
    106  1.1.1.2  jmmv     }
    107  1.1.1.2  jmmv }
    108  1.1.1.2  jmmv 
    109  1.1.1.2  jmmv static
    110  1.1.1.2  jmmv int
    111  1.1.1.2  jmmv const_execvp(const char *file, const char *const *argv)
    112  1.1.1.2  jmmv {
    113  1.1.1.2  jmmv #define UNCONST(a) ((void *)(unsigned long)(const void *)(a))
    114  1.1.1.2  jmmv     return execvp(file, UNCONST(argv));
    115  1.1.1.2  jmmv #undef UNCONST
    116  1.1.1.2  jmmv }
    117  1.1.1.2  jmmv 
    118  1.1.1.2  jmmv static
    119  1.1.1.2  jmmv atf_error_t
    120  1.1.1.2  jmmv init_sb(const atf_fs_path_t *path, atf_process_stream_t *sb)
    121  1.1.1.2  jmmv {
    122  1.1.1.2  jmmv     atf_error_t err;
    123  1.1.1.2  jmmv 
    124  1.1.1.2  jmmv     if (path == NULL)
    125  1.1.1.2  jmmv         err = atf_process_stream_init_inherit(sb);
    126  1.1.1.2  jmmv     else
    127  1.1.1.2  jmmv         err = atf_process_stream_init_redirect_path(sb, path);
    128  1.1.1.2  jmmv 
    129  1.1.1.2  jmmv     return err;
    130  1.1.1.2  jmmv }
    131  1.1.1.2  jmmv 
    132  1.1.1.2  jmmv static
    133  1.1.1.2  jmmv atf_error_t
    134  1.1.1.2  jmmv init_sbs(const atf_fs_path_t *outfile, atf_process_stream_t *outsb,
    135  1.1.1.2  jmmv          const atf_fs_path_t *errfile, atf_process_stream_t *errsb)
    136      1.1  jmmv {
    137  1.1.1.2  jmmv     atf_error_t err;
    138  1.1.1.2  jmmv 
    139  1.1.1.2  jmmv     err = init_sb(outfile, outsb);
    140  1.1.1.2  jmmv     if (atf_is_error(err))
    141  1.1.1.2  jmmv         goto out;
    142      1.1  jmmv 
    143  1.1.1.2  jmmv     err = init_sb(errfile, errsb);
    144  1.1.1.2  jmmv     if (atf_is_error(err)) {
    145  1.1.1.2  jmmv         atf_process_stream_fini(outsb);
    146  1.1.1.2  jmmv         goto out;
    147  1.1.1.2  jmmv     }
    148  1.1.1.2  jmmv 
    149  1.1.1.2  jmmv out:
    150  1.1.1.2  jmmv     return err;
    151  1.1.1.2  jmmv }
    152  1.1.1.2  jmmv 
    153  1.1.1.2  jmmv struct exec_data {
    154  1.1.1.2  jmmv     const char *const *m_argv;
    155  1.1.1.2  jmmv };
    156  1.1.1.2  jmmv 
    157  1.1.1.2  jmmv static void exec_child(void *) ATF_DEFS_ATTRIBUTE_NORETURN;
    158  1.1.1.2  jmmv 
    159  1.1.1.2  jmmv static
    160  1.1.1.2  jmmv void
    161  1.1.1.2  jmmv exec_child(void *v)
    162  1.1.1.2  jmmv {
    163  1.1.1.2  jmmv     struct exec_data *ea = v;
    164      1.1  jmmv 
    165  1.1.1.2  jmmv     const_execvp(ea->m_argv[0], ea->m_argv);
    166  1.1.1.2  jmmv     fprintf(stderr, "execvp(%s) failed: %s\n", ea->m_argv[0], strerror(errno));
    167  1.1.1.2  jmmv     exit(127);
    168      1.1  jmmv }
    169      1.1  jmmv 
    170      1.1  jmmv static
    171      1.1  jmmv atf_error_t
    172  1.1.1.2  jmmv fork_and_wait(const char *const *argv, const atf_fs_path_t *outfile,
    173  1.1.1.2  jmmv               const atf_fs_path_t *errfile, atf_process_status_t *status)
    174      1.1  jmmv {
    175      1.1  jmmv     atf_error_t err;
    176  1.1.1.2  jmmv     atf_process_child_t child;
    177  1.1.1.2  jmmv     atf_process_stream_t outsb, errsb;
    178  1.1.1.2  jmmv     struct exec_data ea = { argv };
    179      1.1  jmmv 
    180  1.1.1.2  jmmv     err = init_sbs(outfile, &outsb, errfile, &errsb);
    181      1.1  jmmv     if (atf_is_error(err))
    182      1.1  jmmv         goto out;
    183      1.1  jmmv 
    184  1.1.1.2  jmmv     err = atf_process_fork(&child, exec_child, &outsb, &errsb, &ea);
    185  1.1.1.2  jmmv     if (atf_is_error(err))
    186  1.1.1.2  jmmv         goto out_sbs;
    187  1.1.1.2  jmmv 
    188  1.1.1.2  jmmv     err = atf_process_child_wait(&child, status);
    189  1.1.1.2  jmmv 
    190  1.1.1.2  jmmv out_sbs:
    191  1.1.1.2  jmmv     atf_process_stream_fini(&errsb);
    192  1.1.1.2  jmmv     atf_process_stream_fini(&outsb);
    193  1.1.1.2  jmmv out:
    194  1.1.1.2  jmmv     return err;
    195  1.1.1.2  jmmv }
    196  1.1.1.2  jmmv 
    197  1.1.1.2  jmmv static
    198  1.1.1.2  jmmv void
    199  1.1.1.2  jmmv update_success_from_status(const char *progname,
    200  1.1.1.2  jmmv                            const atf_process_status_t *status, bool *success)
    201  1.1.1.2  jmmv {
    202  1.1.1.2  jmmv     bool s = atf_process_status_exited(status) &&
    203  1.1.1.2  jmmv              atf_process_status_exitstatus(status) == EXIT_SUCCESS;
    204  1.1.1.2  jmmv 
    205  1.1.1.2  jmmv     if (atf_process_status_exited(status)) {
    206  1.1.1.2  jmmv         if (atf_process_status_exitstatus(status) == EXIT_SUCCESS)
    207  1.1.1.2  jmmv             INV(s);
    208  1.1.1.2  jmmv         else {
    209  1.1.1.2  jmmv             INV(!s);
    210  1.1.1.2  jmmv             fprintf(stderr, "%s failed with exit code %d\n", progname,
    211  1.1.1.2  jmmv                     atf_process_status_exitstatus(status));
    212  1.1.1.2  jmmv         }
    213  1.1.1.2  jmmv     } else if (atf_process_status_signaled(status)) {
    214  1.1.1.2  jmmv         INV(!s);
    215  1.1.1.2  jmmv         fprintf(stderr, "%s failed due to signal %d%s\n", progname,
    216  1.1.1.2  jmmv                 atf_process_status_termsig(status),
    217  1.1.1.2  jmmv                 atf_process_status_coredump(status) ? " (core dumped)" : "");
    218      1.1  jmmv     } else {
    219  1.1.1.2  jmmv         INV(!s);
    220  1.1.1.2  jmmv         fprintf(stderr, "%s failed due to unknown reason\n", progname);
    221  1.1.1.2  jmmv     }
    222  1.1.1.2  jmmv 
    223  1.1.1.2  jmmv     *success = s;
    224  1.1.1.2  jmmv }
    225  1.1.1.2  jmmv 
    226  1.1.1.2  jmmv static
    227  1.1.1.2  jmmv atf_error_t
    228  1.1.1.2  jmmv array_to_list(const char *const *a, atf_list_t *l)
    229  1.1.1.2  jmmv {
    230  1.1.1.2  jmmv     atf_error_t err;
    231  1.1.1.2  jmmv 
    232  1.1.1.2  jmmv     err = atf_list_init(l);
    233  1.1.1.2  jmmv     if (atf_is_error(err))
    234  1.1.1.2  jmmv         goto out;
    235  1.1.1.2  jmmv 
    236  1.1.1.2  jmmv     while (*a != NULL) {
    237  1.1.1.2  jmmv         char *item = strdup(*a);
    238  1.1.1.2  jmmv         if (item == NULL) {
    239  1.1.1.2  jmmv             err = atf_no_memory_error();
    240  1.1.1.2  jmmv             goto out;
    241      1.1  jmmv         }
    242  1.1.1.2  jmmv 
    243  1.1.1.2  jmmv         err = atf_list_append(l, item, true);
    244  1.1.1.2  jmmv         if (atf_is_error(err))
    245  1.1.1.2  jmmv             goto out;
    246  1.1.1.2  jmmv 
    247  1.1.1.2  jmmv         a++;
    248      1.1  jmmv     }
    249      1.1  jmmv 
    250      1.1  jmmv out:
    251      1.1  jmmv     return err;
    252      1.1  jmmv }
    253      1.1  jmmv 
    254  1.1.1.5  jmmv static void
    255  1.1.1.5  jmmv print_array(const char *const *array, const char *pfx)
    256  1.1.1.2  jmmv {
    257  1.1.1.5  jmmv     const char *const *ptr;
    258  1.1.1.2  jmmv 
    259  1.1.1.2  jmmv     printf("%s", pfx);
    260  1.1.1.5  jmmv     for (ptr = array; *ptr != NULL; ptr++)
    261  1.1.1.5  jmmv         printf(" %s", *ptr);
    262  1.1.1.2  jmmv     printf("\n");
    263  1.1.1.2  jmmv }
    264  1.1.1.2  jmmv 
    265  1.1.1.2  jmmv static
    266  1.1.1.2  jmmv atf_error_t
    267  1.1.1.5  jmmv check_build_run(const char *const *argv, bool *success)
    268  1.1.1.2  jmmv {
    269  1.1.1.2  jmmv     atf_error_t err;
    270  1.1.1.2  jmmv     atf_process_status_t status;
    271  1.1.1.2  jmmv 
    272  1.1.1.5  jmmv     print_array(argv, ">");
    273  1.1.1.2  jmmv 
    274  1.1.1.5  jmmv     err = fork_and_wait(argv, NULL, NULL, &status);
    275  1.1.1.2  jmmv     if (atf_is_error(err))
    276  1.1.1.2  jmmv         goto out;
    277  1.1.1.2  jmmv 
    278  1.1.1.5  jmmv     update_success_from_status(argv[0], &status, success);
    279  1.1.1.2  jmmv     atf_process_status_fini(&status);
    280  1.1.1.2  jmmv 
    281  1.1.1.2  jmmv     INV(!atf_is_error(err));
    282  1.1.1.2  jmmv out:
    283  1.1.1.2  jmmv     return err;
    284  1.1.1.2  jmmv }
    285  1.1.1.2  jmmv 
    286      1.1  jmmv /* ---------------------------------------------------------------------
    287      1.1  jmmv  * The "atf_check_result" type.
    288      1.1  jmmv  * --------------------------------------------------------------------- */
    289      1.1  jmmv 
    290  1.1.1.5  jmmv struct atf_check_result_impl {
    291  1.1.1.5  jmmv     atf_list_t m_argv;
    292  1.1.1.5  jmmv     atf_fs_path_t m_dir;
    293  1.1.1.5  jmmv     atf_fs_path_t m_stdout;
    294  1.1.1.5  jmmv     atf_fs_path_t m_stderr;
    295  1.1.1.5  jmmv     atf_process_status_t m_status;
    296  1.1.1.5  jmmv };
    297  1.1.1.5  jmmv 
    298  1.1.1.2  jmmv static
    299      1.1  jmmv atf_error_t
    300  1.1.1.2  jmmv atf_check_result_init(atf_check_result_t *r, const char *const *argv,
    301  1.1.1.2  jmmv                       const atf_fs_path_t *dir)
    302      1.1  jmmv {
    303      1.1  jmmv     atf_error_t err;
    304      1.1  jmmv 
    305  1.1.1.5  jmmv     r->pimpl = malloc(sizeof(struct atf_check_result_impl));
    306  1.1.1.5  jmmv     if (r->pimpl == NULL)
    307  1.1.1.5  jmmv         return atf_no_memory_error();
    308  1.1.1.5  jmmv 
    309  1.1.1.5  jmmv     err = array_to_list(argv, &r->pimpl->m_argv);
    310      1.1  jmmv     if (atf_is_error(err))
    311      1.1  jmmv         goto out;
    312      1.1  jmmv 
    313  1.1.1.5  jmmv     err = atf_fs_path_copy(&r->pimpl->m_dir, dir);
    314  1.1.1.2  jmmv     if (atf_is_error(err))
    315  1.1.1.2  jmmv         goto err_argv;
    316  1.1.1.2  jmmv 
    317  1.1.1.5  jmmv     err = atf_fs_path_init_fmt(&r->pimpl->m_stdout, "%s/stdout",
    318  1.1.1.2  jmmv                                atf_fs_path_cstring(dir));
    319  1.1.1.2  jmmv     if (atf_is_error(err))
    320  1.1.1.2  jmmv         goto err_dir;
    321  1.1.1.2  jmmv 
    322  1.1.1.5  jmmv     err = atf_fs_path_init_fmt(&r->pimpl->m_stderr, "%s/stderr",
    323  1.1.1.2  jmmv                                atf_fs_path_cstring(dir));
    324      1.1  jmmv     if (atf_is_error(err))
    325      1.1  jmmv         goto err_stdout;
    326      1.1  jmmv 
    327      1.1  jmmv     INV(!atf_is_error(err));
    328      1.1  jmmv     goto out;
    329      1.1  jmmv 
    330      1.1  jmmv err_stdout:
    331  1.1.1.5  jmmv     atf_fs_path_fini(&r->pimpl->m_stdout);
    332  1.1.1.2  jmmv err_dir:
    333  1.1.1.5  jmmv     atf_fs_path_fini(&r->pimpl->m_dir);
    334  1.1.1.2  jmmv err_argv:
    335  1.1.1.5  jmmv     atf_list_fini(&r->pimpl->m_argv);
    336      1.1  jmmv out:
    337      1.1  jmmv     return err;
    338      1.1  jmmv }
    339      1.1  jmmv 
    340      1.1  jmmv void
    341      1.1  jmmv atf_check_result_fini(atf_check_result_t *r)
    342      1.1  jmmv {
    343  1.1.1.5  jmmv     atf_process_status_fini(&r->pimpl->m_status);
    344      1.1  jmmv 
    345  1.1.1.5  jmmv     cleanup_tmpdir(&r->pimpl->m_dir, &r->pimpl->m_stdout,
    346  1.1.1.5  jmmv                    &r->pimpl->m_stderr);
    347  1.1.1.5  jmmv     atf_fs_path_fini(&r->pimpl->m_stdout);
    348  1.1.1.5  jmmv     atf_fs_path_fini(&r->pimpl->m_stderr);
    349  1.1.1.5  jmmv     atf_fs_path_fini(&r->pimpl->m_dir);
    350  1.1.1.2  jmmv 
    351  1.1.1.5  jmmv     atf_list_fini(&r->pimpl->m_argv);
    352      1.1  jmmv 
    353  1.1.1.5  jmmv     free(r->pimpl);
    354  1.1.1.2  jmmv }
    355  1.1.1.2  jmmv 
    356  1.1.1.5  jmmv const char *
    357      1.1  jmmv atf_check_result_stdout(const atf_check_result_t *r)
    358      1.1  jmmv {
    359  1.1.1.5  jmmv     return atf_fs_path_cstring(&r->pimpl->m_stdout);
    360      1.1  jmmv }
    361      1.1  jmmv 
    362  1.1.1.5  jmmv const char *
    363      1.1  jmmv atf_check_result_stderr(const atf_check_result_t *r)
    364      1.1  jmmv {
    365  1.1.1.5  jmmv     return atf_fs_path_cstring(&r->pimpl->m_stderr);
    366      1.1  jmmv }
    367      1.1  jmmv 
    368      1.1  jmmv bool
    369      1.1  jmmv atf_check_result_exited(const atf_check_result_t *r)
    370      1.1  jmmv {
    371  1.1.1.5  jmmv     return atf_process_status_exited(&r->pimpl->m_status);
    372      1.1  jmmv }
    373      1.1  jmmv 
    374      1.1  jmmv int
    375      1.1  jmmv atf_check_result_exitcode(const atf_check_result_t *r)
    376      1.1  jmmv {
    377  1.1.1.5  jmmv     return atf_process_status_exitstatus(&r->pimpl->m_status);
    378      1.1  jmmv }
    379      1.1  jmmv 
    380  1.1.1.4  jmmv bool
    381  1.1.1.4  jmmv atf_check_result_signaled(const atf_check_result_t *r)
    382  1.1.1.4  jmmv {
    383  1.1.1.5  jmmv     return atf_process_status_signaled(&r->pimpl->m_status);
    384  1.1.1.4  jmmv }
    385  1.1.1.4  jmmv 
    386  1.1.1.4  jmmv int
    387  1.1.1.4  jmmv atf_check_result_termsig(const atf_check_result_t *r)
    388  1.1.1.4  jmmv {
    389  1.1.1.5  jmmv     return atf_process_status_termsig(&r->pimpl->m_status);
    390  1.1.1.4  jmmv }
    391  1.1.1.4  jmmv 
    392      1.1  jmmv /* ---------------------------------------------------------------------
    393      1.1  jmmv  * Free functions.
    394      1.1  jmmv  * --------------------------------------------------------------------- */
    395      1.1  jmmv 
    396  1.1.1.2  jmmv /* XXX: This function shouldn't be in this module.  It messes with stdout
    397  1.1.1.2  jmmv  * and stderr, and it provides a very high-end interface.  This belongs,
    398  1.1.1.2  jmmv  * probably, somewhere related to test cases (such as in the tc module). */
    399  1.1.1.2  jmmv atf_error_t
    400  1.1.1.2  jmmv atf_check_build_c_o(const char *sfile,
    401  1.1.1.2  jmmv                     const char *ofile,
    402  1.1.1.2  jmmv                     const char *const optargs[],
    403  1.1.1.2  jmmv                     bool *success)
    404  1.1.1.2  jmmv {
    405  1.1.1.2  jmmv     atf_error_t err;
    406  1.1.1.5  jmmv     char **argv;
    407  1.1.1.2  jmmv 
    408  1.1.1.2  jmmv     err = atf_build_c_o(sfile, ofile, optargs, &argv);
    409  1.1.1.2  jmmv     if (atf_is_error(err))
    410  1.1.1.2  jmmv         goto out;
    411  1.1.1.2  jmmv 
    412  1.1.1.5  jmmv     err = check_build_run((const char *const *)argv, success);
    413  1.1.1.2  jmmv 
    414  1.1.1.5  jmmv     atf_utils_free_charpp(argv);
    415  1.1.1.2  jmmv out:
    416  1.1.1.2  jmmv     return err;
    417  1.1.1.2  jmmv }
    418  1.1.1.2  jmmv 
    419      1.1  jmmv atf_error_t
    420  1.1.1.2  jmmv atf_check_build_cpp(const char *sfile,
    421  1.1.1.2  jmmv                     const char *ofile,
    422  1.1.1.2  jmmv                     const char *const optargs[],
    423  1.1.1.2  jmmv                     bool *success)
    424      1.1  jmmv {
    425      1.1  jmmv     atf_error_t err;
    426  1.1.1.5  jmmv     char **argv;
    427      1.1  jmmv 
    428  1.1.1.2  jmmv     err = atf_build_cpp(sfile, ofile, optargs, &argv);
    429      1.1  jmmv     if (atf_is_error(err))
    430      1.1  jmmv         goto out;
    431      1.1  jmmv 
    432  1.1.1.5  jmmv     err = check_build_run((const char *const *)argv, success);
    433  1.1.1.2  jmmv 
    434  1.1.1.5  jmmv     atf_utils_free_charpp(argv);
    435  1.1.1.2  jmmv out:
    436  1.1.1.2  jmmv     return err;
    437  1.1.1.2  jmmv }
    438  1.1.1.2  jmmv 
    439  1.1.1.2  jmmv atf_error_t
    440  1.1.1.2  jmmv atf_check_build_cxx_o(const char *sfile,
    441  1.1.1.2  jmmv                       const char *ofile,
    442  1.1.1.2  jmmv                       const char *const optargs[],
    443  1.1.1.2  jmmv                       bool *success)
    444  1.1.1.2  jmmv {
    445  1.1.1.2  jmmv     atf_error_t err;
    446  1.1.1.5  jmmv     char **argv;
    447  1.1.1.2  jmmv 
    448  1.1.1.2  jmmv     err = atf_build_cxx_o(sfile, ofile, optargs, &argv);
    449      1.1  jmmv     if (atf_is_error(err))
    450  1.1.1.2  jmmv         goto out;
    451  1.1.1.2  jmmv 
    452  1.1.1.5  jmmv     err = check_build_run((const char *const *)argv, success);
    453      1.1  jmmv 
    454  1.1.1.5  jmmv     atf_utils_free_charpp(argv);
    455  1.1.1.2  jmmv out:
    456  1.1.1.2  jmmv     return err;
    457  1.1.1.2  jmmv }
    458  1.1.1.2  jmmv 
    459  1.1.1.2  jmmv atf_error_t
    460  1.1.1.2  jmmv atf_check_exec_array(const char *const *argv, atf_check_result_t *r)
    461  1.1.1.2  jmmv {
    462  1.1.1.2  jmmv     atf_error_t err;
    463  1.1.1.2  jmmv     atf_fs_path_t dir;
    464  1.1.1.2  jmmv 
    465  1.1.1.2  jmmv     err = create_tmpdir(&dir);
    466  1.1.1.2  jmmv     if (atf_is_error(err))
    467  1.1.1.2  jmmv         goto out;
    468  1.1.1.2  jmmv 
    469  1.1.1.2  jmmv     err = atf_check_result_init(r, argv, &dir);
    470  1.1.1.6  jmmv     if (atf_is_error(err)) {
    471  1.1.1.6  jmmv         atf_error_t err2 = atf_fs_rmdir(&dir);
    472  1.1.1.6  jmmv         INV(!atf_is_error(err2));
    473  1.1.1.6  jmmv         goto out;
    474  1.1.1.6  jmmv     }
    475  1.1.1.2  jmmv 
    476  1.1.1.5  jmmv     err = fork_and_wait(argv, &r->pimpl->m_stdout, &r->pimpl->m_stderr,
    477  1.1.1.5  jmmv                         &r->pimpl->m_status);
    478  1.1.1.6  jmmv     if (atf_is_error(err)) {
    479  1.1.1.6  jmmv         atf_check_result_fini(r);
    480  1.1.1.6  jmmv         goto out;
    481  1.1.1.6  jmmv     }
    482      1.1  jmmv 
    483      1.1  jmmv     INV(!atf_is_error(err));
    484      1.1  jmmv 
    485  1.1.1.2  jmmv     atf_fs_path_fini(&dir);
    486  1.1.1.2  jmmv out:
    487  1.1.1.2  jmmv     return err;
    488  1.1.1.2  jmmv }
    489