13fe5961aSDevin Teske /*
23fe5961aSDevin Teske * Copyright (c) 2013-2026 Devin Teske <dteske@FreeBSD.org>
33fe5961aSDevin Teske * Copyright (c) 2021-2026 Faraz Vahedi <kfv@FreeBSD.org>
43fe5961aSDevin Teske *
53fe5961aSDevin Teske * SPDX-License-Identifier: BSD-2-Clause
63fe5961aSDevin Teske */
73fe5961aSDevin Teske
83fe5961aSDevin Teske /*
93fe5961aSDevin Teske * sysconf(8): CLI entry, option parsing, and program state.
103fe5961aSDevin Teske */
113fe5961aSDevin Teske
123fe5961aSDevin Teske #include "sysconf_priv.h"
133fe5961aSDevin Teske
143fe5961aSDevin Teske /* Requests to process (one per name argument) */
153fe5961aSDevin Teske struct request *reqs; /* set by main() */
163fe5961aSDevin Teske unsigned int nreqs; /* set by main() */
173fe5961aSDevin Teske
183fe5961aSDevin Teske /* Union of all directives, for `-a' against multi-file targets */
193fe5961aSDevin Teske struct dumpent *dumps; /* set by scan_cb() */
203fe5961aSDevin Teske size_t ndumps; /* set by scan_cb() */
213fe5961aSDevin Teske size_t dumpsize; /* set by scan_cb() */
223fe5961aSDevin Teske
233fe5961aSDevin Teske /* Resolved target state */
243fe5961aSDevin Teske char **conf_files; /* ordered backing files */
253fe5961aSDevin Teske size_t nconf_files;
263fe5961aSDevin Teske size_t conf_scanidx; /* file being parsed (scan_pass) */
273fe5961aSDevin Teske size_t write_idx; /* default write target index */
283fe5961aSDevin Teske int defaults_idx = -1; /* defaults file index in conf_files
293fe5961aSDevin Teske * (read-only, never listed); -1 if none */
303fe5961aSDevin Teske enum bsdconf_format format = BSDCONF_FORMAT_GENERIC;
313fe5961aSDevin Teske
323fe5961aSDevin Teske /* Extra display information */
333fe5961aSDevin Teske const char *pgm; /* set to getprogname() by main() */
343fe5961aSDevin Teske bool check = false; /* `-c' */
353fe5961aSDevin Teske bool defaults_only = false; /* `-D' */
363fe5961aSDevin Teske bool dump_all = false; /* `-a' */
373fe5961aSDevin Teske bool existing_only = false; /* `-E' */
383fe5961aSDevin Teske bool ignore_unknown = false; /* `-i' */
393fe5961aSDevin Teske bool list_all = false; /* `-L' */
403fe5961aSDevin Teske bool list_files = false; /* `-l' */
413fe5961aSDevin Teske bool name_only = false; /* `-N' */
423fe5961aSDevin Teske bool quiet = false; /* `-q' */
433fe5961aSDevin Teske bool remove_mode = false; /* `-x' */
443fe5961aSDevin Teske bool set_knobs = false; /* `-s' WITH_/WITHOUT_ presence */
453fe5961aSDevin Teske bool show_desc = false; /* `-d' */
463fe5961aSDevin Teske bool show_equals = false; /* `-e' */
473fe5961aSDevin Teske bool show_file = false; /* `-F' */
483fe5961aSDevin Teske bool value_only = false; /* `-n' */
493fe5961aSDevin Teske bool verbose = false; /* `-v' */
503fe5961aSDevin Teske bool verbose_trail = false; /* `-V' */
513fe5961aSDevin Teske bool with_defaults = false; /* `-A' */
523fe5961aSDevin Teske
533fe5961aSDevin Teske /* Option arguments */
543fe5961aSDevin Teske const char *file = NULL; /* `-f file' */
553fe5961aSDevin Teske bool file_stdin = false; /* `-f -' given */
563fe5961aSDevin Teske const char *jailname = NULL; /* `-j jail' */
573fe5961aSDevin Teske const char *module = NULL; /* `-k module' */
583fe5961aSDevin Teske const char *rootdir = ""; /* `-R dir' */
593fe5961aSDevin Teske
603fe5961aSDevin Teske /*
613fe5961aSDevin Teske * Locate the target keyword in `argv' without consuming or validating
623fe5961aSDevin Teske * anything: the first argument that is neither an option cluster nor the
633fe5961aSDevin Teske * argument of one (per OPTSTRING; an unknown option letter is assumed to
643fe5961aSDevin Teske * take no argument). A `--' ends option scanning as usual. Returns the
653fe5961aSDevin Teske * argv index of the target, or -1 when there is none. Used before any
663fe5961aSDevin Teske * getopt(3) processing so that the `rc' pass-through target (see
673fe5961aSDevin Teske * exec_sysrc() below) can be detected while the command line is still
683fe5961aSDevin Teske * pristine.
693fe5961aSDevin Teske *
703fe5961aSDevin Teske * Attached arguments (`-fPATH', `-R/altroot') are self-contained: the rest
713fe5961aSDevin Teske * of the cluster is the option's argument, so the following argv element is
723fe5961aSDevin Teske * not consumed. Only a trailing option letter that takes an argument and
733fe5961aSDevin Teske * has nothing after it in the cluster (`-f PATH') skips the next element.
743fe5961aSDevin Teske */
753fe5961aSDevin Teske static int
find_target(int argc,char * argv[])763fe5961aSDevin Teske find_target(int argc, char *argv[])
773fe5961aSDevin Teske {
783fe5961aSDevin Teske int n;
793fe5961aSDevin Teske const char *o;
803fe5961aSDevin Teske const char *p;
813fe5961aSDevin Teske
823fe5961aSDevin Teske for (n = 1; n < argc; n++) {
833fe5961aSDevin Teske if (strcmp(argv[n], "--") == 0)
843fe5961aSDevin Teske return (n + 1 < argc ? n + 1 : -1);
853fe5961aSDevin Teske if (argv[n][0] == '-' && argv[n][1] != '\0') {
863fe5961aSDevin Teske for (p = argv[n] + 1; *p != '\0'; p++) {
873fe5961aSDevin Teske o = strchr(OPTSTRING, *p);
883fe5961aSDevin Teske if (o != NULL && o[1] == ':') {
893fe5961aSDevin Teske /* Takes an argument */
903fe5961aSDevin Teske if (p[1] != '\0') {
913fe5961aSDevin Teske ;
923fe5961aSDevin Teske /* attached: rest of argv[n] */
933fe5961aSDevin Teske } else if (n + 1 < argc) {
943fe5961aSDevin Teske n++;
953fe5961aSDevin Teske /* separate argv */
963fe5961aSDevin Teske }
973fe5961aSDevin Teske break;
983fe5961aSDevin Teske }
993fe5961aSDevin Teske }
1003fe5961aSDevin Teske continue;
1013fe5961aSDevin Teske }
1023fe5961aSDevin Teske return (n);
1033fe5961aSDevin Teske }
1043fe5961aSDevin Teske
1053fe5961aSDevin Teske return (-1);
1063fe5961aSDevin Teske }
1073fe5961aSDevin Teske
1083fe5961aSDevin Teske /*
1093fe5961aSDevin Teske * The `rc' pass-through: rc.conf(5) is sysrc(8)'s domain, and its feature
1103fe5961aSDevin Teske * set is a superset of ours, so no option or argument is validated,
1113fe5961aSDevin Teske * interpreted, or reordered here -- every argument except the target
1123fe5961aSDevin Teske * keyword itself (at argv index `skip') is handed to sysrc(8) verbatim.
1133fe5961aSDevin Teske * Never returns.
1143fe5961aSDevin Teske */
1153fe5961aSDevin Teske static void
exec_sysrc(int argc,char * argv[],int skip)1163fe5961aSDevin Teske exec_sysrc(int argc, char *argv[], int skip)
1173fe5961aSDevin Teske {
1183fe5961aSDevin Teske int n;
1193fe5961aSDevin Teske int nargc = 0;
1203fe5961aSDevin Teske char **nargv;
1213fe5961aSDevin Teske
1223fe5961aSDevin Teske if ((nargv = calloc((size_t)argc + 1, sizeof(*nargv))) == NULL)
1233fe5961aSDevin Teske err(EXIT_FAILURE, NULL);
1243fe5961aSDevin Teske nargv[nargc++] = (char *)(uintptr_t)"sysrc";
1253fe5961aSDevin Teske for (n = 1; n < argc; n++) {
1263fe5961aSDevin Teske if (n == skip)
1273fe5961aSDevin Teske continue;
1283fe5961aSDevin Teske nargv[nargc++] = argv[n];
1293fe5961aSDevin Teske }
1303fe5961aSDevin Teske nargv[nargc] = NULL;
1313fe5961aSDevin Teske
1323fe5961aSDevin Teske execvp("sysrc", nargv);
1333fe5961aSDevin Teske err(EXIT_FAILURE, "sysrc");
1343fe5961aSDevin Teske }
1353fe5961aSDevin Teske
1363fe5961aSDevin Teske /*
1373fe5961aSDevin Teske * Run the getopt(3) loop over `argv', setting the option globals. Called
1383fe5961aSDevin Teske * once for the options preceding the target keyword and once for those
1393fe5961aSDevin Teske * following it. Returns the number of arguments consumed (optind).
1403fe5961aSDevin Teske */
1413fe5961aSDevin Teske static int
parse_options(int argc,char * argv[])1423fe5961aSDevin Teske parse_options(int argc, char *argv[])
1433fe5961aSDevin Teske {
1443fe5961aSDevin Teske int ch;
1453fe5961aSDevin Teske
1463fe5961aSDevin Teske while ((ch = getopt(argc, argv, OPTSTRING)) != -1) {
1473fe5961aSDevin Teske switch (ch) {
1483fe5961aSDevin Teske case 'A': /* dump all directives, defaults included */
1493fe5961aSDevin Teske with_defaults = 1;
1503fe5961aSDevin Teske break;
1513fe5961aSDevin Teske case 'a': /* dump all directives */
1523fe5961aSDevin Teske dump_all = 1;
1533fe5961aSDevin Teske break;
1543fe5961aSDevin Teske case 'c': /* check only; do not modify */
1553fe5961aSDevin Teske check = 1;
1563fe5961aSDevin Teske break;
1573fe5961aSDevin Teske case 'd': /* show directive descriptions */
1583fe5961aSDevin Teske show_desc = 1;
1593fe5961aSDevin Teske break;
1603fe5961aSDevin Teske case 'D': /* consult the defaults file only */
1613fe5961aSDevin Teske defaults_only = 1;
1623fe5961aSDevin Teske break;
1633fe5961aSDevin Teske case 'E': /* list existing files only (with -l/-L) */
1643fe5961aSDevin Teske existing_only = 1;
1653fe5961aSDevin Teske break;
1663fe5961aSDevin Teske case 'e': /* show name=value */
1673fe5961aSDevin Teske show_equals = 1;
1683fe5961aSDevin Teske break;
1693fe5961aSDevin Teske case 'F': /* show authoritative file, not value */
1703fe5961aSDevin Teske show_file = 1;
1713fe5961aSDevin Teske break;
1723fe5961aSDevin Teske case 'f': /* explicit file (`-' is standard input) */
1733fe5961aSDevin Teske if (strcmp(optarg, "-") == 0) {
1743fe5961aSDevin Teske file = "/dev/stdin";
1753fe5961aSDevin Teske file_stdin = 1;
1763fe5961aSDevin Teske } else {
1773fe5961aSDevin Teske file = optarg;
1783fe5961aSDevin Teske file_stdin = 0;
1793fe5961aSDevin Teske }
1803fe5961aSDevin Teske break;
1813fe5961aSDevin Teske case 'h': /* help/usage */
1823fe5961aSDevin Teske usage();
1833fe5961aSDevin Teske break;
1843fe5961aSDevin Teske case 'i': /* ignore unknown names */
1853fe5961aSDevin Teske ignore_unknown = 1;
1863fe5961aSDevin Teske break;
1873fe5961aSDevin Teske case 'j': /* jail name or id */
1883fe5961aSDevin Teske jailname = optarg;
1893fe5961aSDevin Teske break;
1903fe5961aSDevin Teske case 'k': /* kernel module drop-in */
1913fe5961aSDevin Teske module = optarg;
1923fe5961aSDevin Teske break;
1933fe5961aSDevin Teske case 'l': /* list backing files */
1943fe5961aSDevin Teske list_files = 1;
1953fe5961aSDevin Teske break;
1963fe5961aSDevin Teske case 'L': /* list all candidate files */
1973fe5961aSDevin Teske list_all = 1;
1983fe5961aSDevin Teske break;
1993fe5961aSDevin Teske case 'n': /* value only */
2003fe5961aSDevin Teske value_only = 1;
2013fe5961aSDevin Teske break;
2023fe5961aSDevin Teske case 'N': /* name only */
2033fe5961aSDevin Teske name_only = 1;
2043fe5961aSDevin Teske break;
2053fe5961aSDevin Teske case 'q': /* quiet */
2063fe5961aSDevin Teske quiet = 1;
2073fe5961aSDevin Teske break;
2083fe5961aSDevin Teske case 'R': /* root dir */
2093fe5961aSDevin Teske rootdir = optarg;
2103fe5961aSDevin Teske break;
2113fe5961aSDevin Teske case 's': /* set empty WITH_/WITHOUT_ knobs (make/src) */
2123fe5961aSDevin Teske set_knobs = 1;
2133fe5961aSDevin Teske break;
2143fe5961aSDevin Teske case 'v': /* verbose (last file + final value) */
2153fe5961aSDevin Teske verbose = 1;
2163fe5961aSDevin Teske break;
2173fe5961aSDevin Teske case 'V': /* verbose trail (every assignment step) */
2183fe5961aSDevin Teske verbose_trail = 1;
2193fe5961aSDevin Teske break;
2203fe5961aSDevin Teske case 'x': /* remove */
2213fe5961aSDevin Teske remove_mode = 1;
2223fe5961aSDevin Teske break;
2233fe5961aSDevin Teske case '?': /* unknown argument (based on optstring) */
2243fe5961aSDevin Teske default: /* unhandled argument (based on switch) */
2253fe5961aSDevin Teske usage();
2263fe5961aSDevin Teske }
2273fe5961aSDevin Teske }
2283fe5961aSDevin Teske
2293fe5961aSDevin Teske return (optind);
2303fe5961aSDevin Teske }
2313fe5961aSDevin Teske
2323fe5961aSDevin Teske /*
2333fe5961aSDevin Teske * The native configuration trinity's third member: read and modify
2343fe5961aSDevin Teske * loader.conf(5), sysctl.conf(5), make.conf(5), and arbitrary configuration
2353fe5961aSDevin Teske * files with sysctl(8) assignment syntax.
2363fe5961aSDevin Teske */
2373fe5961aSDevin Teske int
main(int argc,char * argv[])2383fe5961aSDevin Teske main(int argc, char *argv[])
2393fe5961aSDevin Teske {
2403fe5961aSDevin Teske int have_reads = 0;
2413fe5961aSDevin Teske int have_writes = 0;
2423fe5961aSDevin Teske int n;
2433fe5961aSDevin Teske int rv = EXIT_SUCCESS;
2443fe5961aSDevin Teske const char *target = NULL;
2453fe5961aSDevin Teske
2463fe5961aSDevin Teske pgm = getprogname();
2473fe5961aSDevin Teske
2483fe5961aSDevin Teske /*
2493fe5961aSDevin Teske * The `rc' target is a pure pass-through to sysrc(8), detected
2503fe5961aSDevin Teske * while the command line is still pristine so that nothing --
2513fe5961aSDevin Teske * `--help' and `--version' included -- is intercepted on its way
2523fe5961aSDevin Teske * there (see exec_sysrc()).
2533fe5961aSDevin Teske */
2543fe5961aSDevin Teske n = find_target(argc, argv);
2553fe5961aSDevin Teske if (n > 0 && strcmp(argv[n], "rc") == 0)
2563fe5961aSDevin Teske exec_sysrc(argc, argv, n); /* never returns */
2573fe5961aSDevin Teske
2583fe5961aSDevin Teske /*
2593fe5961aSDevin Teske * Honor `--help' and `--version' wherever they appear (getopt(3)
2603fe5961aSDevin Teske * knows nothing of long options and would reject them as illegal
2613fe5961aSDevin Teske * short options). A bare `--' ends option processing as usual.
2623fe5961aSDevin Teske */
2633fe5961aSDevin Teske for (n = 1; n < argc; n++) {
2643fe5961aSDevin Teske if (strcmp(argv[n], "--") == 0)
2653fe5961aSDevin Teske break;
2663fe5961aSDevin Teske if (strcmp(argv[n], "--help") == 0)
2673fe5961aSDevin Teske help();
2683fe5961aSDevin Teske if (strcmp(argv[n], "--version") == 0) {
269*0380d016SDevin Teske printf("%s (libbsdconf %s)\n", SYSCONF_VERSION,
270*0380d016SDevin Teske BSDCONF_VERSION);
2713fe5961aSDevin Teske exit(EXIT_SUCCESS);
2723fe5961aSDevin Teske }
2733fe5961aSDevin Teske }
2743fe5961aSDevin Teske
2753fe5961aSDevin Teske /*
2763fe5961aSDevin Teske * Process command-line options
2773fe5961aSDevin Teske */
2783fe5961aSDevin Teske n = parse_options(argc, argv);
2793fe5961aSDevin Teske argc -= n;
2803fe5961aSDevin Teske argv += n;
2813fe5961aSDevin Teske
2823fe5961aSDevin Teske /*
2833fe5961aSDevin Teske * Consume the (required) target keyword and allow further options
2843fe5961aSDevin Teske * to follow it, mirroring the option placement freedom of
2853fe5961aSDevin Teske * sysctl(8) (e.g., `sysconf sysctl -L'). getopt(3) skips over its
2863fe5961aSDevin Teske * first argument, so hand it the target keyword's slot as the
2873fe5961aSDevin Teske * program name.
2883fe5961aSDevin Teske */
2893fe5961aSDevin Teske if (argc > 0) {
2903fe5961aSDevin Teske target = argv[0];
2913fe5961aSDevin Teske argc--;
2923fe5961aSDevin Teske argv++;
2933fe5961aSDevin Teske #ifdef __FreeBSD__
2943fe5961aSDevin Teske optreset = 1;
2953fe5961aSDevin Teske optind = 1;
2963fe5961aSDevin Teske #else
2973fe5961aSDevin Teske optind = 0; /* glibc and musl re-initialize at zero */
2983fe5961aSDevin Teske #endif
2993fe5961aSDevin Teske n = parse_options(argc + 1, argv - 1) - 1;
3003fe5961aSDevin Teske argc -= n;
3013fe5961aSDevin Teske argv += n;
3023fe5961aSDevin Teske }
3033fe5961aSDevin Teske
3043fe5961aSDevin Teske if (jailname != NULL && *rootdir != '\0') {
3053fe5961aSDevin Teske warnx("-j and -R are mutually exclusive");
3063fe5961aSDevin Teske usage();
3073fe5961aSDevin Teske }
3083fe5961aSDevin Teske if (file != NULL && module != NULL) {
3093fe5961aSDevin Teske warnx("-f and -k are mutually exclusive");
3103fe5961aSDevin Teske usage();
3113fe5961aSDevin Teske }
3123fe5961aSDevin Teske if (existing_only && !list_files && !list_all) {
3133fe5961aSDevin Teske warnx("-E requires -l or -L");
3143fe5961aSDevin Teske usage();
3153fe5961aSDevin Teske }
3163fe5961aSDevin Teske if (set_knobs && remove_mode) {
3173fe5961aSDevin Teske warnx("-s and -x are mutually exclusive");
3183fe5961aSDevin Teske usage();
3193fe5961aSDevin Teske }
3203fe5961aSDevin Teske
3213fe5961aSDevin Teske #ifdef __FreeBSD__
3223fe5961aSDevin Teske if (jailname != NULL) {
3233fe5961aSDevin Teske int jid;
3243fe5961aSDevin Teske
3253fe5961aSDevin Teske if ((jid = jail_getid(jailname)) < 0)
3263fe5961aSDevin Teske errx(EXIT_FAILURE, "%s", jail_errmsg);
3273fe5961aSDevin Teske if (jail_attach(jid) != 0)
3283fe5961aSDevin Teske err(EXIT_FAILURE, "jail_attach(%d)", jid);
3293fe5961aSDevin Teske }
3303fe5961aSDevin Teske #else
3313fe5961aSDevin Teske if (jailname != NULL)
3323fe5961aSDevin Teske errx(EXIT_FAILURE, "-j is not supported on this platform");
3333fe5961aSDevin Teske #endif
3343fe5961aSDevin Teske
3353fe5961aSDevin Teske /* Resolve the target format and its backing files */
3363fe5961aSDevin Teske resolve_target(target);
3373fe5961aSDevin Teske
3383fe5961aSDevin Teske /* `-k' requires a target with a module drop-in directory */
3393fe5961aSDevin Teske if (module != NULL) {
3403fe5961aSDevin Teske const struct bsdconf_format_def *def;
3413fe5961aSDevin Teske const struct bsdconf_source *source;
3423fe5961aSDevin Teske int has_moddir = 0;
3433fe5961aSDevin Teske
3443fe5961aSDevin Teske def = bsdconf_format_lookup(format);
3453fe5961aSDevin Teske if (def != NULL && def->sources != NULL)
3463fe5961aSDevin Teske for (source = def->sources; source->path != NULL;
3473fe5961aSDevin Teske source++)
3483fe5961aSDevin Teske if (source->type == BSDCONF_SOURCE_MODDIR)
3493fe5961aSDevin Teske has_moddir = 1;
3503fe5961aSDevin Teske if (!has_moddir) {
3513fe5961aSDevin Teske warnx("target does not support -k");
3523fe5961aSDevin Teske usage();
3533fe5961aSDevin Teske }
3543fe5961aSDevin Teske }
3553fe5961aSDevin Teske
3563fe5961aSDevin Teske /*
3573fe5961aSDevin Teske * `-d', `-D', and `-A' consult a body of defaults; only targets
3583fe5961aSDevin Teske * that have one support them (make.conf and friends have no
3593fe5961aSDevin Teske * defaults file, and no directive descriptions to give). The
3603fe5961aSDevin Teske * exception is `sysctl -d', whose descriptions come from the
3613fe5961aSDevin Teske * running kernel rather than any file.
3623fe5961aSDevin Teske */
3633fe5961aSDevin Teske {
3643fe5961aSDevin Teske const struct bsdconf_format_def *def;
3653fe5961aSDevin Teske int has_defaults;
3663fe5961aSDevin Teske
3673fe5961aSDevin Teske def = bsdconf_format_lookup(format);
3683fe5961aSDevin Teske has_defaults = def != NULL && def->defaults != NULL;
3693fe5961aSDevin Teske
3703fe5961aSDevin Teske if (show_desc) {
3713fe5961aSDevin Teske if (format != BSDCONF_FORMAT_SYSCTL &&
3723fe5961aSDevin Teske !has_defaults) {
3733fe5961aSDevin Teske warnx("target does not support -d");
3743fe5961aSDevin Teske usage();
3753fe5961aSDevin Teske }
3763fe5961aSDevin Teske if (file != NULL) {
3773fe5961aSDevin Teske warnx("-d and -f are mutually exclusive");
3783fe5961aSDevin Teske usage();
3793fe5961aSDevin Teske }
3803fe5961aSDevin Teske if (list_files || list_all || remove_mode || check ||
3813fe5961aSDevin Teske set_knobs) {
3823fe5961aSDevin Teske warnx("-d cannot be combined with "
3833fe5961aSDevin Teske "-c/-l/-L/-s/-x");
3843fe5961aSDevin Teske usage();
3853fe5961aSDevin Teske }
3863fe5961aSDevin Teske #ifdef __FreeBSD__
3873fe5961aSDevin Teske if (format == BSDCONF_FORMAT_SYSCTL &&
3883fe5961aSDevin Teske *rootdir != '\0')
3893fe5961aSDevin Teske errx(EXIT_FAILURE, "sysctl descriptions "
3903fe5961aSDevin Teske "come from the running kernel; "
3913fe5961aSDevin Teske "-R does not apply");
3923fe5961aSDevin Teske #endif
3933fe5961aSDevin Teske }
3943fe5961aSDevin Teske if ((defaults_only || with_defaults) && !has_defaults) {
3953fe5961aSDevin Teske warnx("target does not support -%c",
3963fe5961aSDevin Teske defaults_only ? 'D' : 'A');
3973fe5961aSDevin Teske usage();
3983fe5961aSDevin Teske }
3993fe5961aSDevin Teske if ((defaults_only || with_defaults) && file != NULL) {
4003fe5961aSDevin Teske warnx("-%c and -f are mutually exclusive",
4013fe5961aSDevin Teske defaults_only ? 'D' : 'A');
4023fe5961aSDevin Teske usage();
4033fe5961aSDevin Teske }
4043fe5961aSDevin Teske }
4053fe5961aSDevin Teske
4063fe5961aSDevin Teske /* File listings take no names and perform no other work */
4073fe5961aSDevin Teske if (list_files || list_all) {
4083fe5961aSDevin Teske if (argc != 0 || dump_all) {
4093fe5961aSDevin Teske warnx("-l/-L take no names");
4103fe5961aSDevin Teske usage();
4113fe5961aSDevin Teske }
4123fe5961aSDevin Teske exit(do_list());
4133fe5961aSDevin Teske }
4143fe5961aSDevin Teske
4153fe5961aSDevin Teske /* `-A' with no names dumps everything, defaults included */
4163fe5961aSDevin Teske if (with_defaults && argc == 0)
4173fe5961aSDevin Teske dump_all = 1;
4183fe5961aSDevin Teske
4193fe5961aSDevin Teske /* Display usage and exit if not given at least one name */
4203fe5961aSDevin Teske if (argc == 0 && !dump_all) {
4213fe5961aSDevin Teske warnx("no names provided");
4223fe5961aSDevin Teske usage();
4233fe5961aSDevin Teske }
4243fe5961aSDevin Teske if (argc != 0 && dump_all) {
4253fe5961aSDevin Teske warnx("-a does not take names");
4263fe5961aSDevin Teske usage();
4273fe5961aSDevin Teske }
4283fe5961aSDevin Teske
4293fe5961aSDevin Teske /* Classify the remaining arguments */
4303fe5961aSDevin Teske nreqs = (unsigned int)argc;
4313fe5961aSDevin Teske if (nreqs > 0 &&
4323fe5961aSDevin Teske (reqs = calloc(nreqs, sizeof(*reqs))) == NULL)
4333fe5961aSDevin Teske err(EXIT_FAILURE, NULL);
4343fe5961aSDevin Teske if (set_knobs) {
4353fe5961aSDevin Teske if (format != BSDCONF_FORMAT_MAKE &&
4363fe5961aSDevin Teske format != BSDCONF_FORMAT_SRC) {
4373fe5961aSDevin Teske warnx("-s is only valid for make and src");
4383fe5961aSDevin Teske usage();
4393fe5961aSDevin Teske }
4403fe5961aSDevin Teske if (argc == 0) {
4413fe5961aSDevin Teske warnx("-s requires at least one WITH_/WITHOUT_ name");
4423fe5961aSDevin Teske usage();
4433fe5961aSDevin Teske }
4443fe5961aSDevin Teske }
4453fe5961aSDevin Teske for (n = 0; n < argc; n++) {
4463fe5961aSDevin Teske split_request(argv[n], &reqs[n], remove_mode);
4473fe5961aSDevin Teske if (set_knobs) {
4483fe5961aSDevin Teske if (reqs[n].newvalue != NULL) {
4493fe5961aSDevin Teske warnx("-s does not take a value "
4503fe5961aSDevin Teske "('%s')", argv[n]);
4513fe5961aSDevin Teske usage();
4523fe5961aSDevin Teske }
4533fe5961aSDevin Teske if (!make_knob_name_p(reqs[n].name)) {
4543fe5961aSDevin Teske if (strcmp(reqs[n].name,
4553fe5961aSDevin Teske "WITHOUT_MODULES") == 0)
4563fe5961aSDevin Teske warnx("WITHOUT_MODULES takes a "
4573fe5961aSDevin Teske "module list; use "
4583fe5961aSDevin Teske "WITHOUT_MODULES=...");
4593fe5961aSDevin Teske else
4603fe5961aSDevin Teske warnx("-s requires a WITH_ or "
4613fe5961aSDevin Teske "WITHOUT_ name ('%s')",
4623fe5961aSDevin Teske reqs[n].name);
4633fe5961aSDevin Teske usage();
4643fe5961aSDevin Teske }
4653fe5961aSDevin Teske reqs[n].newvalue = "";
4663fe5961aSDevin Teske }
4673fe5961aSDevin Teske if (reqs[n].newvalue != NULL && !reqs[n].remove)
4683fe5961aSDevin Teske warn_with_equals_no(reqs[n].name,
4693fe5961aSDevin Teske reqs[n].newvalue, NULL, 0);
4703fe5961aSDevin Teske if (reqs[n].remove || reqs[n].newvalue != NULL)
4713fe5961aSDevin Teske have_writes = 1;
4723fe5961aSDevin Teske else
4733fe5961aSDevin Teske have_reads = 1;
4743fe5961aSDevin Teske }
4753fe5961aSDevin Teske if (check && !have_writes) {
4763fe5961aSDevin Teske warnx("-c requires at least one name=value or -s name");
4773fe5961aSDevin Teske usage();
4783fe5961aSDevin Teske }
4793fe5961aSDevin Teske
4803fe5961aSDevin Teske /* Descriptions are read-only */
4813fe5961aSDevin Teske if (show_desc) {
4823fe5961aSDevin Teske if (have_writes) {
4833fe5961aSDevin Teske warnx("-d does not take values");
4843fe5961aSDevin Teske usage();
4853fe5961aSDevin Teske }
4863fe5961aSDevin Teske #ifndef __FreeBSD__
4873fe5961aSDevin Teske if (format == BSDCONF_FORMAT_SYSCTL)
4883fe5961aSDevin Teske errx(EXIT_FAILURE,
4893fe5961aSDevin Teske "sysctl descriptions require FreeBSD");
4903fe5961aSDevin Teske #endif
4913fe5961aSDevin Teske /* Explicit names need no file scan at all */
4923fe5961aSDevin Teske if (!dump_all) {
4933fe5961aSDevin Teske #ifdef __FreeBSD__
4943fe5961aSDevin Teske if (format == BSDCONF_FORMAT_SYSCTL)
4953fe5961aSDevin Teske exit(describe_sysctl());
4963fe5961aSDevin Teske #endif
4973fe5961aSDevin Teske exit(describe_defaults());
4983fe5961aSDevin Teske }
4993fe5961aSDevin Teske
5003fe5961aSDevin Teske /*
5013fe5961aSDevin Teske * Dumps (-ad, -Ad, -aDd) pair each scanned directive with
5023fe5961aSDevin Teske * its description; harvest the descriptions before the
5033fe5961aSDevin Teske * read sandbox slams shut.
5043fe5961aSDevin Teske */
5053fe5961aSDevin Teske if (format != BSDCONF_FORMAT_SYSCTL)
5063fe5961aSDevin Teske load_descriptions();
5073fe5961aSDevin Teske }
5083fe5961aSDevin Teske
5093fe5961aSDevin Teske /* Defaults can be read and checked against, never rewritten */
5103fe5961aSDevin Teske if ((defaults_only || with_defaults) && have_writes && !check)
5113fe5961aSDevin Teske errx(EXIT_FAILURE, "defaults are read-only");
5123fe5961aSDevin Teske
5133fe5961aSDevin Teske /* Standard input can be read and checked, never rewritten */
5143fe5961aSDevin Teske if (file_stdin && have_writes && !check)
5153fe5961aSDevin Teske errx(EXIT_FAILURE, "cannot write to standard input");
5163fe5961aSDevin Teske
5173fe5961aSDevin Teske #if defined(__FreeBSD__)
5183fe5961aSDevin Teske /*
5193fe5961aSDevin Teske * Refuse up front to set sysctl OIDs that can never take effect
5203fe5961aSDevin Teske * from sysctl.conf(5) (non-leaf, read-only, loader-only tunables)
5213fe5961aSDevin Teske * or whose values cannot fit the OID's CTLTYPE (so an overflowing
5223fe5961aSDevin Teske * assignment cannot surprise sysctl(8) at boot). Unknown OIDs are
5233fe5961aSDevin Teske * warned about but still written -- the module may not be loaded
5243fe5961aSDevin Teske * yet, matching init(8)'s handling of sysctl.conf(5). Only
5253fe5961aSDevin Teske * meaningful against the running system's sysctl tree, so skipped
5263fe5961aSDevin Teske * under -R. -i/-q quiet the unknown-OID warning; -k remains the
5273fe5961aSDevin Teske * module drop-in selector.
5283fe5961aSDevin Teske */
5293fe5961aSDevin Teske if (format == BSDCONF_FORMAT_SYSCTL && have_writes && !check &&
5303fe5961aSDevin Teske *rootdir == '\0') {
5313fe5961aSDevin Teske int quiet_unknown = ignore_unknown || quiet;
5323fe5961aSDevin Teske unsigned int u;
5333fe5961aSDevin Teske
5343fe5961aSDevin Teske for (u = 0; u < nreqs; u++) {
5353fe5961aSDevin Teske if (reqs[u].newvalue == NULL)
5363fe5961aSDevin Teske continue;
5373fe5961aSDevin Teske if (sysctl_writable(reqs[u].name, reqs[u].newvalue,
5383fe5961aSDevin Teske quiet_unknown) != 0) {
5393fe5961aSDevin Teske /* Convert to a no-op; count the failure */
5403fe5961aSDevin Teske reqs[u].newvalue = NULL;
5413fe5961aSDevin Teske reqs[u].remove = 0;
5423fe5961aSDevin Teske reqs[u].name = "";
5433fe5961aSDevin Teske rv = EXIT_FAILURE;
5443fe5961aSDevin Teske }
5453fe5961aSDevin Teske }
5463fe5961aSDevin Teske have_writes = 0;
5473fe5961aSDevin Teske have_reads = 0;
5483fe5961aSDevin Teske for (u = 0; u < nreqs; u++) {
5493fe5961aSDevin Teske if (reqs[u].remove || reqs[u].newvalue != NULL)
5503fe5961aSDevin Teske have_writes = 1;
5513fe5961aSDevin Teske else if (reqs[u].name[0] != '\0')
5523fe5961aSDevin Teske have_reads = 1;
5533fe5961aSDevin Teske }
5543fe5961aSDevin Teske if (rv != EXIT_SUCCESS && !have_writes && !have_reads)
5553fe5961aSDevin Teske exit(rv); /* nothing settable remains */
5563fe5961aSDevin Teske }
5573fe5961aSDevin Teske #endif
5583fe5961aSDevin Teske
5593fe5961aSDevin Teske /*
5603fe5961aSDevin Teske * Scan the backing files to locate each request's authoritative
5613fe5961aSDevin Teske * definition. Pure reads and -c checks (do_checks() never calls
5623fe5961aSDevin Teske * put) run the scan inside a Capsicum sandbox -- except a sysctl
5633fe5961aSDevin Teske * description dump, whose kernel queries the sandbox would deny.
5643fe5961aSDevin Teske * Classify by whether we will actually write, not by whether the
5653fe5961aSDevin Teske * argv looked like name=value (`-c' sets have_writes for checks).
5663fe5961aSDevin Teske */
5673fe5961aSDevin Teske scan_pass((check || !have_writes) &&
5683fe5961aSDevin Teske !(show_desc && format == BSDCONF_FORMAT_SYSCTL));
5693fe5961aSDevin Teske
5703fe5961aSDevin Teske /* Materialize list edits now that effective values are known */
5713fe5961aSDevin Teske if (merge_list_requests() != EXIT_SUCCESS)
5723fe5961aSDevin Teske rv = EXIT_FAILURE;
5733fe5961aSDevin Teske
5743fe5961aSDevin Teske if (check) {
5753fe5961aSDevin Teske if (do_make_strikes(1) != EXIT_SUCCESS)
5763fe5961aSDevin Teske rv = EXIT_FAILURE;
5773fe5961aSDevin Teske if (do_checks() != EXIT_SUCCESS)
5783fe5961aSDevin Teske rv = EXIT_FAILURE;
5793fe5961aSDevin Teske exit(rv);
5803fe5961aSDevin Teske }
5813fe5961aSDevin Teske
5823fe5961aSDevin Teske /* Apply writes first so that subsequent reads see the result */
5833fe5961aSDevin Teske if (have_writes) {
5843fe5961aSDevin Teske int wrv;
5853fe5961aSDevin Teske
5863fe5961aSDevin Teske if ((wrv = do_make_strikes(0)) != EXIT_SUCCESS)
5873fe5961aSDevin Teske rv = wrv;
5883fe5961aSDevin Teske if ((wrv = do_writes()) != EXIT_SUCCESS)
5893fe5961aSDevin Teske rv = wrv;
5903fe5961aSDevin Teske
5913fe5961aSDevin Teske /* Refresh the scan for any trailing read requests */
5923fe5961aSDevin Teske if (have_reads || dump_all) {
5933fe5961aSDevin Teske for (n = 0; (unsigned int)n < nreqs; n++) {
5943fe5961aSDevin Teske size_t ai;
5953fe5961aSDevin Teske
5963fe5961aSDevin Teske trail_free(reqs[n].trail, reqs[n].ntrail);
5973fe5961aSDevin Teske reqs[n].trail = NULL;
5983fe5961aSDevin Teske reqs[n].ntrail = 0;
5993fe5961aSDevin Teske for (ai = 0; ai < reqs[n].nassigns; ai++)
6003fe5961aSDevin Teske free(reqs[n].assigns[ai].piece);
6013fe5961aSDevin Teske free(reqs[n].assigns);
6023fe5961aSDevin Teske reqs[n].assigns = NULL;
6033fe5961aSDevin Teske reqs[n].nassigns = 0;
6043fe5961aSDevin Teske reqs[n].found = 0;
6053fe5961aSDevin Teske reqs[n].append_present = 0;
6063fe5961aSDevin Teske reqs[n].srcidx = -1;
6073fe5961aSDevin Teske reqs[n].line = 0;
6083fe5961aSDevin Teske memset(reqs[n].infile, 0, nconf_files);
6093fe5961aSDevin Teske }
6103fe5961aSDevin Teske scan_pass(0);
6113fe5961aSDevin Teske }
6123fe5961aSDevin Teske }
6133fe5961aSDevin Teske
6143fe5961aSDevin Teske if (have_reads || dump_all) {
6153fe5961aSDevin Teske int rrv;
6163fe5961aSDevin Teske
6173fe5961aSDevin Teske if ((rrv = do_reads()) != EXIT_SUCCESS)
6183fe5961aSDevin Teske rv = rrv;
6193fe5961aSDevin Teske }
6203fe5961aSDevin Teske
6213fe5961aSDevin Teske exit(rv);
6223fe5961aSDevin Teske }
6233fe5961aSDevin Teske
6243fe5961aSDevin Teske /*
6253fe5961aSDevin Teske * Print short usage statement to stderr and exit with error status.
6263fe5961aSDevin Teske */
6273fe5961aSDevin Teske void
usage(void)6283fe5961aSDevin Teske usage(void)
6293fe5961aSDevin Teske {
6303fe5961aSDevin Teske
6313fe5961aSDevin Teske fprintf(stderr,
6323fe5961aSDevin Teske "usage: %s target [-AcDeFinNqsvVx] [-j jail | -R dir]"
6333fe5961aSDevin Teske " [-f file | -k module]\n"
6343fe5961aSDevin Teske " name[[+|-]=value] ...\n", pgm);
6353fe5961aSDevin Teske fprintf(stderr,
6363fe5961aSDevin Teske " %s target [-ADeFnNqvV] [-j jail | -R dir]"
6373fe5961aSDevin Teske " [-f file | -k module] -a\n", pgm);
6383fe5961aSDevin Teske fprintf(stderr,
6393fe5961aSDevin Teske " %s target [-AaDinNq] [-j jail | -R dir]"
6403fe5961aSDevin Teske " -d [name ...]\n", pgm);
6413fe5961aSDevin Teske fprintf(stderr,
6423fe5961aSDevin Teske " %s target [-E] [-j jail | -R dir] [-k module]"
6433fe5961aSDevin Teske " -l | -L\n", pgm);
6443fe5961aSDevin Teske fprintf(stderr,
6453fe5961aSDevin Teske " %s rc [sysrc(8) argument ...]\n", pgm);
6463fe5961aSDevin Teske fprintf(stderr, "Try `%s --help' for more information.\n", pgm);
6473fe5961aSDevin Teske exit(EXIT_FAILURE);
6483fe5961aSDevin Teske }
6493fe5961aSDevin Teske
6503fe5961aSDevin Teske /*
6513fe5961aSDevin Teske * Print long usage statement to stderr and exit with error status.
6523fe5961aSDevin Teske */
6533fe5961aSDevin Teske void
help(void)6543fe5961aSDevin Teske help(void)
6553fe5961aSDevin Teske {
6563fe5961aSDevin Teske
6573fe5961aSDevin Teske fprintf(stderr,
6583fe5961aSDevin Teske "usage: %s target [-AcDeFinNqsvVx] [-j jail | -R dir]"
6593fe5961aSDevin Teske " [-f file | -k module] name[[+|-]=value] ...\n", pgm);
6603fe5961aSDevin Teske fprintf(stderr, "TARGETS:\n");
6613fe5961aSDevin Teske #define TGTFMT "\t%-9s %s\n"
6623fe5961aSDevin Teske fprintf(stderr, TGTFMT, "loader",
6633fe5961aSDevin Teske "files named by loader_conf_files et al. in");
6643fe5961aSDevin Teske fprintf(stderr, TGTFMT, "",
6653fe5961aSDevin Teske "/boot/defaults/loader.conf (typically /boot/loader.conf,");
6663fe5961aSDevin Teske fprintf(stderr, TGTFMT, "",
6673fe5961aSDevin Teske "loader.conf.d/*.conf, loader.conf.local)");
6683fe5961aSDevin Teske fprintf(stderr, TGTFMT, "sysctl",
6693fe5961aSDevin Teske "/etc/sysctl.conf, sysctl.conf.local, sysctl.kld.d/*.conf");
6703fe5961aSDevin Teske fprintf(stderr, TGTFMT, "make",
6713fe5961aSDevin Teske "/etc/make.conf (or -f for any make-syntax file)");
6723fe5961aSDevin Teske fprintf(stderr, TGTFMT, "src",
6733fe5961aSDevin Teske "/usr/src build triad: src-env.conf, make.conf, src.conf");
6743fe5961aSDevin Teske fprintf(stderr, TGTFMT, "",
6753fe5961aSDevin Teske "(new writes prefer src.conf; env: SRC_ENV_CONF,");
6763fe5961aSDevin Teske fprintf(stderr, TGTFMT, "",
6773fe5961aSDevin Teske "__MAKE_CONF, SRCCONF)");
6783fe5961aSDevin Teske fprintf(stderr, TGTFMT, "rc",
6793fe5961aSDevin Teske "pass-through: all other arguments go to sysrc(8) verbatim");
6803fe5961aSDevin Teske fprintf(stderr, TGTFMT, "generic",
6813fe5961aSDevin Teske "no default files; requires -f file");
6823fe5961aSDevin Teske fprintf(stderr, "OPTIONS:\n");
6833fe5961aSDevin Teske #define OPTFMT "\t%-9s %s\n"
6843fe5961aSDevin Teske fprintf(stderr, OPTFMT, "-A",
6853fe5961aSDevin Teske "Include the target's defaults file in the sourcing order");
6863fe5961aSDevin Teske fprintf(stderr, OPTFMT, "",
6873fe5961aSDevin Teske "(alone, dumps everything, defaults included).");
6883fe5961aSDevin Teske fprintf(stderr, OPTFMT, "-a",
6893fe5961aSDevin Teske "Dump the union of all directives from the target's files.");
6903fe5961aSDevin Teske fprintf(stderr, OPTFMT, "-c",
6913fe5961aSDevin Teske "Check. Return success if no changes needed, else error.");
6923fe5961aSDevin Teske fprintf(stderr, OPTFMT, "-D",
6933fe5961aSDevin Teske "Consult only the target's defaults file.");
6943fe5961aSDevin Teske fprintf(stderr, OPTFMT, "-d",
6953fe5961aSDevin Teske "Show directive descriptions (from the defaults file's");
6963fe5961aSDevin Teske fprintf(stderr, OPTFMT, "",
6973fe5961aSDevin Teske "comments; for sysctl, from the running kernel). With");
6983fe5961aSDevin Teske fprintf(stderr, OPTFMT, "",
6993fe5961aSDevin Teske "-a, -A, or -D, describe every directive in scope.");
7003fe5961aSDevin Teske fprintf(stderr, OPTFMT, "-E",
7013fe5961aSDevin Teske "With -l or -L, list only files that exist on disk.");
7023fe5961aSDevin Teske fprintf(stderr, OPTFMT, "-e",
7033fe5961aSDevin Teske "Separate name and value with `=' (reads and write echoes).");
7043fe5961aSDevin Teske fprintf(stderr, OPTFMT, "-F",
7053fe5961aSDevin Teske "Show the file holding each directive's effective value.");
7063fe5961aSDevin Teske fprintf(stderr, OPTFMT, "-f file",
7073fe5961aSDevin Teske "Operate on file, in the target's format, instead of the");
7083fe5961aSDevin Teske fprintf(stderr, OPTFMT, "",
7093fe5961aSDevin Teske "target's standard files (`-' means standard input).");
7103fe5961aSDevin Teske fprintf(stderr, OPTFMT, "-h",
7113fe5961aSDevin Teske "Print a short usage statement to stderr and exit.");
7123fe5961aSDevin Teske fprintf(stderr, OPTFMT, "--help",
7133fe5961aSDevin Teske "Print this message to stderr and exit.");
7143fe5961aSDevin Teske fprintf(stderr, OPTFMT, "--version",
715*0380d016SDevin Teske "Print the utility and library versions and exit.");
7163fe5961aSDevin Teske fprintf(stderr, OPTFMT, "-i",
7173fe5961aSDevin Teske "Ignore unknown names (and quiet unknown sysctl OID warnings).");
7183fe5961aSDevin Teske fprintf(stderr, OPTFMT, "-j jail",
7193fe5961aSDevin Teske "Operate within the jail `jail' (name or numeric id).");
7203fe5961aSDevin Teske fprintf(stderr, OPTFMT, "-k module",
7213fe5961aSDevin Teske "Include the kernel module drop-in file for `module'.");
7223fe5961aSDevin Teske fprintf(stderr, OPTFMT, "-l",
7233fe5961aSDevin Teske "List the pathnames of the target's backing files.");
7243fe5961aSDevin Teske fprintf(stderr, OPTFMT, "-L",
7253fe5961aSDevin Teske "List all candidate files, including module drop-ins.");
7263fe5961aSDevin Teske fprintf(stderr, OPTFMT, "-n",
7273fe5961aSDevin Teske "Show only directive values, not their names.");
7283fe5961aSDevin Teske fprintf(stderr, OPTFMT, "-N",
7293fe5961aSDevin Teske "Show only directive names, not their values.");
7303fe5961aSDevin Teske fprintf(stderr, OPTFMT, "-q",
7313fe5961aSDevin Teske "Quiet. Suppress unknown-directive warnings and the");
7323fe5961aSDevin Teske fprintf(stderr, OPTFMT, "",
7333fe5961aSDevin Teske "`old -> new' echo of writes.");
7343fe5961aSDevin Teske fprintf(stderr, OPTFMT, "-R dir",
7353fe5961aSDevin Teske "Operate within the root directory `dir' rather than `/'.");
7363fe5961aSDevin Teske fprintf(stderr, OPTFMT, "-s",
7373fe5961aSDevin Teske "Set empty WITH_/WITHOUT_ knobs (make and src only).");
7383fe5961aSDevin Teske fprintf(stderr, OPTFMT, "-v",
7393fe5961aSDevin Teske "Verbose. Print the pathname of the configuration file");
7403fe5961aSDevin Teske fprintf(stderr, OPTFMT, "",
7413fe5961aSDevin Teske "holding the final effective value.");
7423fe5961aSDevin Teske fprintf(stderr, OPTFMT, "-V",
7433fe5961aSDevin Teske "Trail. Reads: each assignment step (file:line, operator,");
7443fe5961aSDevin Teske fprintf(stderr, OPTFMT, "",
7453fe5961aSDevin Teske "fragment, running effective). Writes: file:line:");
7463fe5961aSDevin Teske fprintf(stderr, OPTFMT, "",
7473fe5961aSDevin Teske "name=old -> name=new (or name=value (unchanged)).");
7483fe5961aSDevin Teske fprintf(stderr, OPTFMT, "-x",
7493fe5961aSDevin Teske "Remove name(s) from the target's files.");
7503fe5961aSDevin Teske fprintf(stderr, "ENVIRONMENT:\n");
7513fe5961aSDevin Teske fprintf(stderr, OPTFMT, "LOADER_DEFAULTS",
7523fe5961aSDevin Teske "Defaults file for the loader target (in place of");
7533fe5961aSDevin Teske fprintf(stderr, OPTFMT, "",
7543fe5961aSDevin Teske "/boot/defaults/loader.conf).");
7553fe5961aSDevin Teske fprintf(stderr, OPTFMT, "SRC_ENV_CONF",
7563fe5961aSDevin Teske "src-env.conf for the src target (default /etc/src-env.conf).");
7573fe5961aSDevin Teske fprintf(stderr, OPTFMT, "__MAKE_CONF",
7583fe5961aSDevin Teske "make.conf for the src target (default /etc/make.conf).");
7593fe5961aSDevin Teske fprintf(stderr, OPTFMT, "SRCCONF",
7603fe5961aSDevin Teske "src.conf for the src target (default /etc/src.conf).");
7613fe5961aSDevin Teske exit(EXIT_FAILURE);
7623fe5961aSDevin Teske }
763