xref: /freebsd/usr.sbin/sysconf/sysconf.c (revision 0380d016d9ba407af12eb743b7c5806d49ddf848)
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