1273929Sjmmv/* Copyright (c) 2008 The NetBSD Foundation, Inc. 2240116Smarcel * All rights reserved. 3240116Smarcel * 4240116Smarcel * Redistribution and use in source and binary forms, with or without 5240116Smarcel * modification, are permitted provided that the following conditions 6240116Smarcel * are met: 7240116Smarcel * 1. Redistributions of source code must retain the above copyright 8240116Smarcel * notice, this list of conditions and the following disclaimer. 9240116Smarcel * 2. Redistributions in binary form must reproduce the above copyright 10240116Smarcel * notice, this list of conditions and the following disclaimer in the 11240116Smarcel * documentation and/or other materials provided with the distribution. 12240116Smarcel * 13240116Smarcel * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND 14240116Smarcel * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 15240116Smarcel * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 16240116Smarcel * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17240116Smarcel * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY 18240116Smarcel * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19240116Smarcel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 20240116Smarcel * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21240116Smarcel * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 22240116Smarcel * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23240116Smarcel * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 24273929Sjmmv * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ 25240116Smarcel 26240116Smarcel#if defined(HAVE_CONFIG_H) 27273929Sjmmv#include "config.h" 28240116Smarcel#endif 29240116Smarcel 30240116Smarcel#include <ctype.h> 31240116Smarcel#include <stdarg.h> 32240116Smarcel#include <stdio.h> 33240116Smarcel#include <stdlib.h> 34240116Smarcel#include <string.h> 35240116Smarcel#include <unistd.h> 36240116Smarcel 37273929Sjmmv#include "atf-c/detail/dynstr.h" 38273929Sjmmv#include "atf-c/detail/env.h" 39273929Sjmmv#include "atf-c/detail/fs.h" 40273929Sjmmv#include "atf-c/detail/map.h" 41273929Sjmmv#include "atf-c/detail/sanity.h" 42240116Smarcel#include "atf-c/error.h" 43240116Smarcel#include "atf-c/tc.h" 44240116Smarcel#include "atf-c/tp.h" 45240116Smarcel#include "atf-c/utils.h" 46240116Smarcel 47240116Smarcel#if defined(HAVE_GNU_GETOPT) 48240116Smarcel# define GETOPT_POSIX "+" 49240116Smarcel#else 50240116Smarcel# define GETOPT_POSIX "" 51240116Smarcel#endif 52240116Smarcel 53240116Smarcelstatic const char *progname = NULL; 54240116Smarcel 55240116Smarcel/* This prototype is provided by macros.h during instantiation of the test 56240116Smarcel * program, so it can be kept private. Don't know if that's the best idea 57240116Smarcel * though. */ 58240116Smarcelint atf_tp_main(int, char **, atf_error_t (*)(atf_tp_t *)); 59240116Smarcel 60240116Smarcelenum tc_part { 61240116Smarcel BODY, 62240116Smarcel CLEANUP, 63240116Smarcel}; 64240116Smarcel 65240116Smarcel/* --------------------------------------------------------------------- 66240116Smarcel * The "usage" and "user" error types. 67240116Smarcel * --------------------------------------------------------------------- */ 68240116Smarcel 69240116Smarcel#define FREE_FORM_ERROR(name) \ 70240116Smarcel struct name ## _error_data { \ 71240116Smarcel char m_what[2048]; \ 72240116Smarcel }; \ 73240116Smarcel \ 74240116Smarcel static \ 75240116Smarcel void \ 76240116Smarcel name ## _format(const atf_error_t err, char *buf, size_t buflen) \ 77240116Smarcel { \ 78240116Smarcel const struct name ## _error_data *data; \ 79240116Smarcel \ 80240116Smarcel PRE(atf_error_is(err, #name)); \ 81240116Smarcel \ 82240116Smarcel data = atf_error_data(err); \ 83240116Smarcel snprintf(buf, buflen, "%s", data->m_what); \ 84240116Smarcel } \ 85240116Smarcel \ 86240116Smarcel static \ 87240116Smarcel atf_error_t \ 88240116Smarcel name ## _error(const char *fmt, ...) \ 89240116Smarcel { \ 90240116Smarcel atf_error_t err; \ 91240116Smarcel struct name ## _error_data data; \ 92240116Smarcel va_list ap; \ 93240116Smarcel \ 94240116Smarcel va_start(ap, fmt); \ 95240116Smarcel vsnprintf(data.m_what, sizeof(data.m_what), fmt, ap); \ 96240116Smarcel va_end(ap); \ 97240116Smarcel \ 98240116Smarcel err = atf_error_new(#name, &data, sizeof(data), name ## _format); \ 99240116Smarcel \ 100240116Smarcel return err; \ 101240116Smarcel } 102240116Smarcel 103240116SmarcelFREE_FORM_ERROR(usage); 104240116SmarcelFREE_FORM_ERROR(user); 105240116Smarcel 106240116Smarcel/* --------------------------------------------------------------------- 107240116Smarcel * Printing functions. 108240116Smarcel * --------------------------------------------------------------------- */ 109240116Smarcel 110240116Smarcelstatic 111240116Smarcelvoid 112240116Smarcelprint_error(const atf_error_t err) 113240116Smarcel{ 114240116Smarcel char buf[4096]; 115240116Smarcel 116240116Smarcel PRE(atf_is_error(err)); 117240116Smarcel 118240116Smarcel atf_error_format(err, buf, sizeof(buf)); 119240116Smarcel fprintf(stderr, "%s: ERROR: %s\n", progname, buf); 120240116Smarcel 121240116Smarcel if (atf_error_is(err, "usage")) 122240116Smarcel fprintf(stderr, "%s: See atf-test-program(1) for usage details.\n", 123240116Smarcel progname); 124240116Smarcel} 125240116Smarcel 126240116Smarcelstatic 127240116Smarcelvoid 128240116Smarcelprint_warning(const char *message) 129240116Smarcel{ 130240116Smarcel fprintf(stderr, "%s: WARNING: %s\n", progname, message); 131240116Smarcel} 132240116Smarcel 133240116Smarcel/* --------------------------------------------------------------------- 134240116Smarcel * Options handling. 135240116Smarcel * --------------------------------------------------------------------- */ 136240116Smarcel 137240116Smarcelstruct params { 138240116Smarcel bool m_do_list; 139240116Smarcel atf_fs_path_t m_srcdir; 140240116Smarcel char *m_tcname; 141240116Smarcel enum tc_part m_tcpart; 142240116Smarcel atf_fs_path_t m_resfile; 143240116Smarcel atf_map_t m_config; 144240116Smarcel}; 145240116Smarcel 146240116Smarcelstatic 147240116Smarcelatf_error_t 148240116Smarcelargv0_to_dir(const char *argv0, atf_fs_path_t *dir) 149240116Smarcel{ 150240116Smarcel atf_error_t err; 151240116Smarcel atf_fs_path_t temp; 152240116Smarcel 153240116Smarcel err = atf_fs_path_init_fmt(&temp, "%s", argv0); 154240116Smarcel if (atf_is_error(err)) 155240116Smarcel goto out; 156240116Smarcel 157240116Smarcel err = atf_fs_path_branch_path(&temp, dir); 158240116Smarcel 159240116Smarcel atf_fs_path_fini(&temp); 160240116Smarcelout: 161240116Smarcel return err; 162240116Smarcel} 163240116Smarcel 164240116Smarcelstatic 165240116Smarcelatf_error_t 166240116Smarcelparams_init(struct params *p, const char *argv0) 167240116Smarcel{ 168240116Smarcel atf_error_t err; 169240116Smarcel 170240116Smarcel p->m_do_list = false; 171240116Smarcel p->m_tcname = NULL; 172240116Smarcel p->m_tcpart = BODY; 173240116Smarcel 174240116Smarcel err = argv0_to_dir(argv0, &p->m_srcdir); 175240116Smarcel if (atf_is_error(err)) 176240116Smarcel return err; 177240116Smarcel 178240116Smarcel err = atf_fs_path_init_fmt(&p->m_resfile, "/dev/stdout"); 179240116Smarcel if (atf_is_error(err)) { 180240116Smarcel atf_fs_path_fini(&p->m_srcdir); 181240116Smarcel return err; 182240116Smarcel } 183240116Smarcel 184240116Smarcel err = atf_map_init(&p->m_config); 185240116Smarcel if (atf_is_error(err)) { 186240116Smarcel atf_fs_path_fini(&p->m_resfile); 187240116Smarcel atf_fs_path_fini(&p->m_srcdir); 188240116Smarcel return err; 189240116Smarcel } 190240116Smarcel 191240116Smarcel return err; 192240116Smarcel} 193240116Smarcel 194240116Smarcelstatic 195240116Smarcelvoid 196240116Smarcelparams_fini(struct params *p) 197240116Smarcel{ 198240116Smarcel atf_map_fini(&p->m_config); 199240116Smarcel atf_fs_path_fini(&p->m_resfile); 200240116Smarcel atf_fs_path_fini(&p->m_srcdir); 201240116Smarcel if (p->m_tcname != NULL) 202240116Smarcel free(p->m_tcname); 203240116Smarcel} 204240116Smarcel 205240116Smarcelstatic 206240116Smarcelatf_error_t 207240116Smarcelparse_vflag(char *arg, atf_map_t *config) 208240116Smarcel{ 209240116Smarcel atf_error_t err; 210240116Smarcel char *split; 211240116Smarcel 212240116Smarcel split = strchr(arg, '='); 213240116Smarcel if (split == NULL) { 214240116Smarcel err = usage_error("-v requires an argument of the form var=value"); 215240116Smarcel goto out; 216240116Smarcel } 217240116Smarcel 218240116Smarcel *split = '\0'; 219240116Smarcel split++; 220240116Smarcel 221240116Smarcel err = atf_map_insert(config, arg, split, false); 222240116Smarcel 223240116Smarcelout: 224240116Smarcel return err; 225240116Smarcel} 226240116Smarcel 227240116Smarcelstatic 228240116Smarcelatf_error_t 229240116Smarcelreplace_path_param(atf_fs_path_t *param, const char *value) 230240116Smarcel{ 231240116Smarcel atf_error_t err; 232240116Smarcel atf_fs_path_t temp; 233240116Smarcel 234240116Smarcel err = atf_fs_path_init_fmt(&temp, "%s", value); 235240116Smarcel if (!atf_is_error(err)) { 236240116Smarcel atf_fs_path_fini(param); 237240116Smarcel *param = temp; 238240116Smarcel } 239240116Smarcel 240240116Smarcel return err; 241240116Smarcel} 242240116Smarcel 243240116Smarcel/* --------------------------------------------------------------------- 244240116Smarcel * Test case listing. 245240116Smarcel * --------------------------------------------------------------------- */ 246240116Smarcel 247240116Smarcelstatic 248240116Smarcelvoid 249240116Smarcellist_tcs(const atf_tp_t *tp) 250240116Smarcel{ 251240116Smarcel const atf_tc_t *const *tcs; 252240116Smarcel const atf_tc_t *const *tcsptr; 253240116Smarcel 254240116Smarcel printf("Content-Type: application/X-atf-tp; version=\"1\"\n\n"); 255240116Smarcel 256240116Smarcel tcs = atf_tp_get_tcs(tp); 257240116Smarcel INV(tcs != NULL); /* Should be checked. */ 258240116Smarcel for (tcsptr = tcs; *tcsptr != NULL; tcsptr++) { 259240116Smarcel const atf_tc_t *tc = *tcsptr; 260240116Smarcel char **vars = atf_tc_get_md_vars(tc); 261240116Smarcel char **ptr; 262240116Smarcel 263240116Smarcel INV(vars != NULL); /* Should be checked. */ 264240116Smarcel 265240116Smarcel if (tcsptr != tcs) /* Not first. */ 266240116Smarcel printf("\n"); 267240116Smarcel 268240116Smarcel for (ptr = vars; *ptr != NULL; ptr += 2) { 269240116Smarcel if (strcmp(*ptr, "ident") == 0) { 270240116Smarcel printf("ident: %s\n", *(ptr + 1)); 271240116Smarcel break; 272240116Smarcel } 273240116Smarcel } 274240116Smarcel 275240116Smarcel for (ptr = vars; *ptr != NULL; ptr += 2) { 276240116Smarcel if (strcmp(*ptr, "ident") != 0) { 277240116Smarcel printf("%s: %s\n", *ptr, *(ptr + 1)); 278240116Smarcel } 279240116Smarcel } 280240116Smarcel 281240116Smarcel atf_utils_free_charpp(vars); 282240116Smarcel } 283240116Smarcel} 284240116Smarcel 285240116Smarcel/* --------------------------------------------------------------------- 286240116Smarcel * Main. 287240116Smarcel * --------------------------------------------------------------------- */ 288240116Smarcel 289240116Smarcelstatic 290240116Smarcelatf_error_t 291240116Smarcelhandle_tcarg(const char *tcarg, char **tcname, enum tc_part *tcpart) 292240116Smarcel{ 293240116Smarcel atf_error_t err; 294240116Smarcel 295240116Smarcel err = atf_no_error(); 296240116Smarcel 297240116Smarcel *tcname = strdup(tcarg); 298240116Smarcel if (*tcname == NULL) { 299240116Smarcel err = atf_no_memory_error(); 300240116Smarcel goto out; 301240116Smarcel } 302240116Smarcel 303240116Smarcel char *delim = strchr(*tcname, ':'); 304240116Smarcel if (delim != NULL) { 305240116Smarcel *delim = '\0'; 306240116Smarcel 307240116Smarcel delim++; 308240116Smarcel if (strcmp(delim, "body") == 0) { 309240116Smarcel *tcpart = BODY; 310240116Smarcel } else if (strcmp(delim, "cleanup") == 0) { 311240116Smarcel *tcpart = CLEANUP; 312240116Smarcel } else { 313240116Smarcel err = usage_error("Invalid test case part `%s'", delim); 314240116Smarcel goto out; 315240116Smarcel } 316240116Smarcel } 317240116Smarcel 318240116Smarcelout: 319240116Smarcel return err; 320240116Smarcel} 321240116Smarcel 322240116Smarcelstatic 323240116Smarcelatf_error_t 324240116Smarcelprocess_params(int argc, char **argv, struct params *p) 325240116Smarcel{ 326240116Smarcel atf_error_t err; 327240116Smarcel int ch; 328240116Smarcel int old_opterr; 329240116Smarcel 330240116Smarcel err = params_init(p, argv[0]); 331240116Smarcel if (atf_is_error(err)) 332240116Smarcel goto out; 333240116Smarcel 334240116Smarcel old_opterr = opterr; 335240116Smarcel opterr = 0; 336240116Smarcel while (!atf_is_error(err) && 337240116Smarcel (ch = getopt(argc, argv, GETOPT_POSIX ":lr:s:v:")) != -1) { 338240116Smarcel switch (ch) { 339240116Smarcel case 'l': 340240116Smarcel p->m_do_list = true; 341240116Smarcel break; 342240116Smarcel 343240116Smarcel case 'r': 344240116Smarcel err = replace_path_param(&p->m_resfile, optarg); 345240116Smarcel break; 346240116Smarcel 347240116Smarcel case 's': 348240116Smarcel err = replace_path_param(&p->m_srcdir, optarg); 349240116Smarcel break; 350240116Smarcel 351240116Smarcel case 'v': 352240116Smarcel err = parse_vflag(optarg, &p->m_config); 353240116Smarcel break; 354240116Smarcel 355240116Smarcel case ':': 356240116Smarcel err = usage_error("Option -%c requires an argument.", optopt); 357240116Smarcel break; 358240116Smarcel 359240116Smarcel case '?': 360240116Smarcel default: 361240116Smarcel err = usage_error("Unknown option -%c.", optopt); 362240116Smarcel } 363240116Smarcel } 364240116Smarcel argc -= optind; 365240116Smarcel argv += optind; 366240116Smarcel 367240116Smarcel /* Clear getopt state just in case the test wants to use it. */ 368240116Smarcel opterr = old_opterr; 369240116Smarcel optind = 1; 370240116Smarcel#if defined(HAVE_OPTRESET) 371240116Smarcel optreset = 1; 372240116Smarcel#endif 373240116Smarcel 374240116Smarcel if (!atf_is_error(err)) { 375240116Smarcel if (p->m_do_list) { 376240116Smarcel if (argc > 0) 377240116Smarcel err = usage_error("Cannot provide test case names with -l"); 378240116Smarcel } else { 379240116Smarcel if (argc == 0) 380240116Smarcel err = usage_error("Must provide a test case name"); 381240116Smarcel else if (argc == 1) 382240116Smarcel err = handle_tcarg(argv[0], &p->m_tcname, &p->m_tcpart); 383240116Smarcel else if (argc > 1) { 384240116Smarcel err = usage_error("Cannot provide more than one test case " 385240116Smarcel "name"); 386240116Smarcel } 387240116Smarcel } 388240116Smarcel } 389240116Smarcel 390240116Smarcel if (atf_is_error(err)) 391240116Smarcel params_fini(p); 392240116Smarcel 393240116Smarcelout: 394240116Smarcel return err; 395240116Smarcel} 396240116Smarcel 397240116Smarcelstatic 398240116Smarcelatf_error_t 399240116Smarcelsrcdir_strip_libtool(atf_fs_path_t *srcdir) 400240116Smarcel{ 401240116Smarcel atf_error_t err; 402240116Smarcel atf_fs_path_t parent; 403240116Smarcel 404240116Smarcel err = atf_fs_path_branch_path(srcdir, &parent); 405240116Smarcel if (atf_is_error(err)) 406240116Smarcel goto out; 407240116Smarcel 408240116Smarcel atf_fs_path_fini(srcdir); 409240116Smarcel *srcdir = parent; 410240116Smarcel 411240116Smarcel INV(!atf_is_error(err)); 412240116Smarcelout: 413240116Smarcel return err; 414240116Smarcel} 415240116Smarcel 416240116Smarcelstatic 417240116Smarcelatf_error_t 418240116Smarcelhandle_srcdir(struct params *p) 419240116Smarcel{ 420240116Smarcel atf_error_t err; 421240116Smarcel atf_dynstr_t leafname; 422240116Smarcel atf_fs_path_t exe, srcdir; 423240116Smarcel bool b; 424240116Smarcel 425240116Smarcel err = atf_fs_path_copy(&srcdir, &p->m_srcdir); 426240116Smarcel if (atf_is_error(err)) 427240116Smarcel goto out; 428240116Smarcel 429240116Smarcel if (!atf_fs_path_is_absolute(&srcdir)) { 430240116Smarcel atf_fs_path_t srcdirabs; 431240116Smarcel 432240116Smarcel err = atf_fs_path_to_absolute(&srcdir, &srcdirabs); 433240116Smarcel if (atf_is_error(err)) 434240116Smarcel goto out_srcdir; 435240116Smarcel 436240116Smarcel atf_fs_path_fini(&srcdir); 437240116Smarcel srcdir = srcdirabs; 438240116Smarcel } 439240116Smarcel 440240116Smarcel err = atf_fs_path_leaf_name(&srcdir, &leafname); 441240116Smarcel if (atf_is_error(err)) 442240116Smarcel goto out_srcdir; 443240116Smarcel else { 444240116Smarcel const bool libs = atf_equal_dynstr_cstring(&leafname, ".libs"); 445240116Smarcel atf_dynstr_fini(&leafname); 446240116Smarcel 447240116Smarcel if (libs) { 448240116Smarcel err = srcdir_strip_libtool(&srcdir); 449240116Smarcel if (atf_is_error(err)) 450240116Smarcel goto out; 451240116Smarcel } 452240116Smarcel } 453240116Smarcel 454240116Smarcel err = atf_fs_path_copy(&exe, &srcdir); 455240116Smarcel if (atf_is_error(err)) 456240116Smarcel goto out_srcdir; 457240116Smarcel 458240116Smarcel err = atf_fs_path_append_fmt(&exe, "%s", progname); 459240116Smarcel if (atf_is_error(err)) 460240116Smarcel goto out_exe; 461240116Smarcel 462240116Smarcel err = atf_fs_exists(&exe, &b); 463240116Smarcel if (!atf_is_error(err)) { 464240116Smarcel if (b) { 465240116Smarcel err = atf_map_insert(&p->m_config, "srcdir", 466240116Smarcel strdup(atf_fs_path_cstring(&srcdir)), true); 467240116Smarcel } else { 468240116Smarcel err = user_error("Cannot find the test program in the source " 469240116Smarcel "directory `%s'", atf_fs_path_cstring(&srcdir)); 470240116Smarcel } 471240116Smarcel } 472240116Smarcel 473240116Smarcelout_exe: 474240116Smarcel atf_fs_path_fini(&exe); 475240116Smarcelout_srcdir: 476240116Smarcel atf_fs_path_fini(&srcdir); 477240116Smarcelout: 478240116Smarcel return err; 479240116Smarcel} 480240116Smarcel 481240116Smarcelstatic 482240116Smarcelatf_error_t 483240116Smarcelrun_tc(const atf_tp_t *tp, struct params *p, int *exitcode) 484240116Smarcel{ 485240116Smarcel atf_error_t err; 486240116Smarcel 487240116Smarcel err = atf_no_error(); 488240116Smarcel 489240116Smarcel if (!atf_tp_has_tc(tp, p->m_tcname)) { 490240116Smarcel err = usage_error("Unknown test case `%s'", p->m_tcname); 491240116Smarcel goto out; 492240116Smarcel } 493240116Smarcel 494240116Smarcel if (!atf_env_has("__RUNNING_INSIDE_ATF_RUN") || strcmp(atf_env_get( 495240116Smarcel "__RUNNING_INSIDE_ATF_RUN"), "internal-yes-value") != 0) 496240116Smarcel { 497273929Sjmmv print_warning("Running test cases outside of kyua(1) is unsupported"); 498240116Smarcel print_warning("No isolation nor timeout control is being applied; you " 499240116Smarcel "may get unexpected failures; see atf-test-case(4)"); 500240116Smarcel } 501240116Smarcel 502240116Smarcel switch (p->m_tcpart) { 503240116Smarcel case BODY: 504240116Smarcel err = atf_tp_run(tp, p->m_tcname, atf_fs_path_cstring(&p->m_resfile)); 505240116Smarcel if (atf_is_error(err)) { 506240116Smarcel /* TODO: Handle error */ 507240116Smarcel *exitcode = EXIT_FAILURE; 508240116Smarcel atf_error_free(err); 509240116Smarcel } else { 510240116Smarcel *exitcode = EXIT_SUCCESS; 511240116Smarcel } 512240116Smarcel 513240116Smarcel break; 514240116Smarcel 515240116Smarcel case CLEANUP: 516240116Smarcel err = atf_tp_cleanup(tp, p->m_tcname); 517240116Smarcel if (atf_is_error(err)) { 518240116Smarcel /* TODO: Handle error */ 519240116Smarcel *exitcode = EXIT_FAILURE; 520240116Smarcel atf_error_free(err); 521240116Smarcel } else { 522240116Smarcel *exitcode = EXIT_SUCCESS; 523240116Smarcel } 524240116Smarcel 525240116Smarcel break; 526240116Smarcel 527240116Smarcel default: 528240116Smarcel UNREACHABLE; 529240116Smarcel } 530240116Smarcel 531240116Smarcel INV(!atf_is_error(err)); 532240116Smarcelout: 533240116Smarcel return err; 534240116Smarcel} 535240116Smarcel 536240116Smarcelstatic 537240116Smarcelatf_error_t 538240116Smarcelcontrolled_main(int argc, char **argv, 539240116Smarcel atf_error_t (*add_tcs_hook)(atf_tp_t *), 540240116Smarcel int *exitcode) 541240116Smarcel{ 542240116Smarcel atf_error_t err; 543240116Smarcel struct params p; 544240116Smarcel atf_tp_t tp; 545240116Smarcel char **raw_config; 546240116Smarcel 547240116Smarcel err = process_params(argc, argv, &p); 548240116Smarcel if (atf_is_error(err)) 549240116Smarcel goto out; 550240116Smarcel 551240116Smarcel err = handle_srcdir(&p); 552240116Smarcel if (atf_is_error(err)) 553240116Smarcel goto out_p; 554240116Smarcel 555240116Smarcel raw_config = atf_map_to_charpp(&p.m_config); 556240116Smarcel if (raw_config == NULL) { 557240116Smarcel err = atf_no_memory_error(); 558240116Smarcel goto out_p; 559240116Smarcel } 560240116Smarcel err = atf_tp_init(&tp, (const char* const*)raw_config); 561240116Smarcel atf_utils_free_charpp(raw_config); 562240116Smarcel if (atf_is_error(err)) 563240116Smarcel goto out_p; 564240116Smarcel 565240116Smarcel err = add_tcs_hook(&tp); 566240116Smarcel if (atf_is_error(err)) 567240116Smarcel goto out_tp; 568240116Smarcel 569240116Smarcel if (p.m_do_list) { 570240116Smarcel list_tcs(&tp); 571240116Smarcel INV(!atf_is_error(err)); 572240116Smarcel *exitcode = EXIT_SUCCESS; 573240116Smarcel } else { 574240116Smarcel err = run_tc(&tp, &p, exitcode); 575240116Smarcel } 576240116Smarcel 577240116Smarcelout_tp: 578240116Smarcel atf_tp_fini(&tp); 579240116Smarcelout_p: 580240116Smarcel params_fini(&p); 581240116Smarcelout: 582240116Smarcel return err; 583240116Smarcel} 584240116Smarcel 585240116Smarcelint 586240116Smarcelatf_tp_main(int argc, char **argv, atf_error_t (*add_tcs_hook)(atf_tp_t *)) 587240116Smarcel{ 588240116Smarcel atf_error_t err; 589240116Smarcel int exitcode; 590240116Smarcel 591240116Smarcel progname = strrchr(argv[0], '/'); 592240116Smarcel if (progname == NULL) 593240116Smarcel progname = argv[0]; 594240116Smarcel else 595240116Smarcel progname++; 596240116Smarcel 597240116Smarcel /* Libtool workaround: if running from within the source tree (binaries 598240116Smarcel * that are not installed yet), skip the "lt-" prefix added to files in 599240116Smarcel * the ".libs" directory to show the real (not temporary) name. */ 600240116Smarcel if (strncmp(progname, "lt-", 3) == 0) 601240116Smarcel progname += 3; 602240116Smarcel 603240116Smarcel exitcode = EXIT_FAILURE; /* Silence GCC warning. */ 604240116Smarcel err = controlled_main(argc, argv, add_tcs_hook, &exitcode); 605240116Smarcel if (atf_is_error(err)) { 606240116Smarcel print_error(err); 607240116Smarcel atf_error_free(err); 608240116Smarcel exitcode = EXIT_FAILURE; 609240116Smarcel } 610240116Smarcel 611240116Smarcel return exitcode; 612240116Smarcel} 613