sysrc revision 290305
178344Sobrien#!/bin/sh
278344Sobrien#-
398184Sgordon# Copyright (c) 2010-2015 Devin Teske
478344Sobrien# All rights reserved.
578344Sobrien#
678344Sobrien# Redistribution and use in source and binary forms, with or without
7127345Sbrooks# modification, are permitted provided that the following conditions
898184Sgordon# are met:
978344Sobrien# 1. Redistributions of source code must retain the above copyright
1078344Sobrien#    notice, this list of conditions and the following disclaimer.
1178344Sobrien# 2. Redistributions in binary form must reproduce the above copyright
1278344Sobrien#    notice, this list of conditions and the following disclaimer in the
13163427Syar#    documentation and/or other materials provided with the distribution.
14230099Sdougb#
15153537Sdougb# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16163427Syar# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1778344Sobrien# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18163427Syar# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1978344Sobrien# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20163427Syar# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21163427Syar# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22153537Sdougb# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23163427Syar# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24163427Syar# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25163427Syar# SUCH DAMAGE.
26153537Sdougb#
27163427Syar# $FreeBSD: stable/10/usr.sbin/sysrc/sysrc 290305 2015-11-02 22:33:34Z dteske $
28197947Sdougb#
29153537Sdougb############################################################ INCLUDES
30163427Syar
31163427Syar# Prevent `-d' from being interpreted as a debug flag by common.subr
32163427SyarDEBUG_SELF_INITIALIZE=
33163427Syar
34163427SyarBSDCFG_SHARE="/usr/share/bsdconfig"
35163427Syar[ "$_COMMON_SUBR" ] || . $BSDCFG_SHARE/common.subr || exit 1
36163427Syar[ "$_SYSRC_SUBR"  ] || f_include $BSDCFG_SHARE/sysrc.subr
37163427Syar
38163427Syar############################################################ GLOBALS
39212222Sdaichi
40163427Syar#
41212222Sdaichi# Version information
42212222Sdaichi#
43163427SyarSYSRC_VERSION="6.3 Mar-4,2015"
44163427Syar
45163427Syar#
46163427Syar# Options
47163427Syar#
48163427SyarCHECK_ONLY=
49163427SyarDELETE=
50197947SdougbDESCRIBE=
51163427SyarIGNORE_UNKNOWNS=
52163427SyarJAIL=
53163427SyarQUIET=
54163427SyarROOTDIR=
55163427SyarSHOW_ALL=
56163427SyarSHOW_EQUALS=
5778344SobrienSHOW_FILE=
5878344SobrienSHOW_NAME=1
5978344SobrienSHOW_VALUE=1
6078344SobrienVERBOSE=
61
62############################################################ FUNCTIONS
63
64# die [ $fmt [ $opts ... ]]
65#
66# Optionally print a message to stderr before exiting with failure status.
67#
68die()
69{
70	local fmt="$1"
71	[ $# -gt 0 ] && shift 1
72	[  "$fmt"  ] && f_err "$fmt\n" "$@"
73
74	exit $FAILURE
75}
76
77# usage
78#
79# Prints a short syntax statement and exits.
80#
81usage()
82{
83	f_err "Usage: %s [OPTIONS] name[[+|-]=value] ...\n" "$pgm"
84	f_err "Try \`%s --help' for more information.\n" "$pgm"
85	die
86}
87
88# help
89#
90# Prints a full syntax statement and exits.
91#
92help()
93{
94	local optfmt="\t%-11s%s\n"
95	local envfmt="\t%-17s%s\n"
96
97	f_err "Usage: %s [OPTIONS] name[[+|-]=value] ...\n" "$pgm"
98
99	f_err "OPTIONS:\n"
100	f_err "$optfmt" "-a" \
101	      "Dump a list of all non-default configuration variables."
102	f_err "$optfmt" "-A" \
103	      "Dump a list of all configuration variables (incl. defaults)."
104	f_err "$optfmt" "-c" \
105	      "Check. Return success if set or no changes, else error."
106	f_err "$optfmt" "-d" \
107	      "Print a description of the given variable."
108	f_err "$optfmt" "-D" \
109	      "Show default value(s) only (this is the same as setting"
110	f_err "$optfmt" "" \
111	      "RC_CONFS to NULL or passing \`-f' with a NULL file-argument)."
112	f_err "$optfmt" "-e" \
113	      "Print query results as \`var=value' (useful for producing"
114	f_err "$optfmt" "" \
115	      "output to be fed back in). Ignored if \`-n' is specified."
116	f_err "$optfmt" "-f file" \
117	      "Operate on the specified file(s) instead of rc_conf_files."
118	f_err "$optfmt" "" \
119	      "Can be specified multiple times for additional files."
120	f_err "$optfmt" "-F" \
121	      "Show only the last rc.conf(5) file each directive is in."
122	f_err "$optfmt" "-h" \
123	      "Print a short usage statement to stderr and exit."
124	f_err "$optfmt" "--help" \
125	      "Print this message to stderr and exit."
126	f_err "$optfmt" "-i" \
127	      "Ignore unknown variables."
128	f_err "$optfmt" "-j jail" \
129	      "The jid or name of the jail to operate within (overrides"
130	f_err "$optfmt" "" \
131	      "\`-R dir'; requires jexec(8))."
132	f_err "$optfmt" "-n" \
133	      "Show only variable values, not their names."
134	f_err "$optfmt" "-N" \
135	      "Show only variable names, not their values."
136	f_err "$optfmt" "-q" \
137	      "Quiet. Disable verbose and hide certain errors."
138	f_err "$optfmt" "-R dir" \
139	      "Operate within the root directory \`dir' rather than \`/'."
140	f_err "$optfmt" "-v" \
141	      "Verbose. Print the pathname of the specific rc.conf(5)"
142	f_err "$optfmt" "" \
143	      "file where the directive was found."
144	f_err "$optfmt" "--version" \
145	      "Print version information to stdout and exit."
146	f_err "$optfmt" "-x" \
147	      "Remove variable(s) from specified file(s)."
148	f_err "\n"
149
150	f_err "ENVIRONMENT:\n"
151	f_err "$envfmt" "RC_CONFS" \
152	      "Override default rc_conf_files (even if set to NULL)."
153	f_err "$envfmt" "RC_DEFAULTS" \
154	      "Location of \`/etc/defaults/rc.conf' file."
155
156	die
157}
158
159# jail_depend
160#
161# Dump dependencies such as language-file variables and include files to stdout
162# to be piped-into sh(1) running via jexec(8)/chroot(8). As a security measure,
163# this prevents existing language files and library files from being loaded in
164# the jail. This also relaxes the requirement to have these files in every jail
165# before sysrc can be used on said jail.
166#
167jail_depend()
168{
169	#
170	# Indicate that we are jailed
171	#
172	echo export _SYSRC_JAILED=1
173
174	#
175	# Print i18n language variables (their current values are sanitized
176	# and re-printed for interpretation so that the i18n language files
177	# do not need to exist within the jail).
178	#
179	local var val
180	for var in \
181		msg_cannot_create_permission_denied \
182		msg_permission_denied \
183		msg_previous_syntax_errors \
184	; do
185		val=$( eval echo \"\$$var\" |
186			awk '{ gsub(/'\''/, "'\''\\'\'\''"); print }' )
187		echo $var="'$val'"
188	done
189
190	#
191	# Print include dependencies
192	#
193	echo DEBUG_SELF_INITIALIZE=
194	cat $BSDCFG_SHARE/common.subr
195	cat $BSDCFG_SHARE/sysrc.subr
196}
197
198escape()
199{
200	local __start="$1" __var_to_set="$2" __string=
201	while [ "$__start" ]; do
202		case "$__start" in *\'*)
203			__string="$__string${__start%%\'*}'\\''"
204			__start="${__start#*\'}" continue
205		esac
206		break
207	done
208	__string="$__string$__start"
209	if [ "$__var_to_set" ]; then
210		setvar "$__var_to_set" "$__string"
211	else
212		echo "$__string"
213	fi
214}
215
216############################################################ MAIN SOURCE
217
218#
219# Perform sanity checks
220#
221[ $# -gt 0 ] || usage # NOTREACHED
222
223#
224# Check for `--help' and `--version' command-line option
225#
226( # Operate in sub-shell to protect $@ in parent
227	while [ $# -gt 0 ]; do
228		case "$1" in
229		--help) help ;;
230		--version) # see GLOBALS
231			echo "$SYSRC_VERSION"
232			exit 1 ;;
233		-[fRj]) # These flags take an argument
234			shift 1 ;;
235		esac
236		shift 1
237	done
238	exit 0
239) || die
240
241#
242# Process command-line flags
243#
244while getopts aAcdDef:Fhij:nNqR:vxX flag; do
245	case "$flag" in
246	a) SHOW_ALL=${SHOW_ALL:-1} ;;
247	A) SHOW_ALL=2 ;;
248	c) CHECK_ONLY=1 ;;
249	d) DESCRIBE=1 ;;
250	D) RC_CONFS= ;;
251	e) SHOW_EQUALS=1 ;;
252	f) RC_CONFS="$RC_CONFS${RC_CONFS:+ }$OPTARG" ;;
253	F) SHOW_FILE=1 ;;
254	h) usage ;; # NOTREACHED
255	i) IGNORE_UNKNOWNS=1 ;;
256	j) [ "$OPTARG" ] || die \
257	   	"%s: Missing or null argument to \`-j' flag" "$pgm"
258	   JAIL="$OPTARG" ;;
259	n) SHOW_NAME= ;;
260	N) SHOW_VALUE= ;;
261	q) QUIET=1 VERBOSE= ;;
262	R) [ "$OPTARG" ] || die \
263	   	"%s: Missing or null argument to \`-R' flag" "$pgm"
264	   ROOTDIR="$OPTARG" ;;
265	v) VERBOSE=1 QUIET= ;;
266	x) DELETE=${DELETE:-1} ;;
267	X) DELETE=2 ;;
268	\?) usage ;; # NOTREACHED
269	esac
270done
271shift $(( $OPTIND - 1 ))
272
273#
274# [More] Sanity checks (e.g., "sysrc --")
275#
276[ $# -eq 0 -a ! "$SHOW_ALL" ] && usage # NOTREACHED
277
278#
279# Taint-check all rc.conf(5) files
280#
281errmsg="$pgm: Exiting due to previous syntax errors"
282if [ "${RC_CONFS+set}" ]; then
283	( for i in $RC_CONFS; do
284	  	[ -e "$i" ] || continue
285	  	/bin/sh -n "$i" || exit $FAILURE
286	  done
287	  exit $SUCCESS
288	) || die "$errmsg"
289else
290	/bin/sh -n "$RC_DEFAULTS" || die "$errmsg"
291	( . "$RC_DEFAULTS"
292	  for i in $rc_conf_files; do
293	  	[ -e "$i" ] || continue
294	  	/bin/sh -n "$i" || exit $FAILURE
295	  done
296	  exit $SUCCESS
297	) || die "$errmsg"
298fi
299
300#
301# Process `-x' (and secret `-X') command-line options
302#
303errmsg="$pgm: \`-x' option incompatible with \`-a'/\`-A' options"
304errmsg="$errmsg (use \`-X' to override)"
305if [ "$DELETE" -a "$SHOW_ALL" ]; then
306	[ "$DELETE" = "2" ] || die "$errmsg"
307fi
308
309#
310# Pre-flight for `-c' command-line option
311#
312[ "$CHECK_ONLY" -a "$SHOW_ALL" ] &&
313	die "$pgm: \`-c' option incompatible with \`-a'/\`-A' options"
314
315#
316# Process `-e', `-n', and `-N' command-line options
317#
318SEP=': '
319[ "$SHOW_FILE" ] && SHOW_EQUALS=
320[ "$SHOW_NAME" ] || SHOW_EQUALS=
321[ "$VERBOSE" = "0" ] && VERBOSE=
322if [ ! "$SHOW_VALUE" ]; then
323	SHOW_NAME=1
324	SHOW_EQUALS=
325fi
326[ "$SHOW_EQUALS" ] && SEP='="'
327
328#
329# Process `-j jail' and `-R dir' command-line options
330#
331if [ "$JAIL" -o "$ROOTDIR" ]; then
332	#
333	# Reconstruct the arguments that we want to carry-over
334	#
335	args="
336		${VERBOSE:+-v}
337		${QUIET:+-q}
338		$( [ "$DELETE" = "1" ] && echo \ -x )
339		$( [ "$DELETE" = "2" ] && echo \ -X )
340		$( [ "$SHOW_ALL" = "1" ] && echo \ -a )
341		$( [ "$SHOW_ALL" = "2" ] && echo \ -A )
342		${CHECK_ONLY:+-c}
343		${DESCRIBE:+-d}
344		${SHOW_EQUALS:+-e}
345		${IGNORE_UNKNOWNS:+-i}
346		$( [ "$SHOW_NAME"  ] || echo \ -n )
347		$( [ "$SHOW_VALUE" ] || echo \ -N )
348		$( [ "$SHOW_FILE"  ] && echo \ -F )
349	"
350	if [ "${RC_CONFS+set}" ]; then
351		escape "$RC_CONFS" _RC_CONFS
352		args="$args -f '$_RC_CONFS'"
353		unset _RC_CONFS
354	fi
355	for arg in "$@"; do
356		escape "$arg" arg
357		args="$args '$arg'"
358	done
359
360	#
361	# If both are supplied, `-j jail' supercedes `-R dir'
362	#
363	if [ "$JAIL" ]; then
364		#
365		# Re-execute ourselves with sh(1) via jexec(8)
366		#
367		( echo set -- $args
368		  jail_depend
369		  cat $0
370		) | env - RC_DEFAULTS="$RC_DEFAULTS" \
371		    	/usr/sbin/jexec "$JAIL" /bin/sh
372		exit $?
373	elif [ "$ROOTDIR" ]; then
374		#
375		# Make sure that the root directory specified is not to any
376		# running jails.
377		#
378		# NOTE: To maintain backward compatibility with older jails on
379		# older systems, we will not perform this check if either the
380		# jls(1) or jexec(8) utilities are missing.
381		#
382		if f_have jexec && f_have jls; then
383			jid="`jls jid path | \
384			(
385				while read JID JROOT; do
386					[ "$JROOT" = "$ROOTDIR" ] || continue
387					echo $JID
388				done
389			)`"
390
391			#
392			# If multiple running jails match the specified root
393			# directory, exit with error.
394			#
395			if [ "$jid" -a "${jid%[$IFS]*}" != "$jid" ]; then
396				die "%s: %s: %s" "$pgm" "$ROOTDIR" \
397				    "$( echo "Multiple jails claim this" \
398				             "directory as their root." \
399				             "(use \`-j jail' instead)" )"
400			fi
401
402			#
403			# If only a single running jail matches the specified
404			# root directory, implicitly use `-j jail'.
405			#
406			if [ "$jid" ]; then
407				#
408				# Re-execute outselves with sh(1) via jexec(8)
409				#
410				( echo set -- $args
411				  jail_depend
412				  cat $0
413				) | env - RC_DEFAULTS="$RC_DEFAULTS" \
414					/usr/sbin/jexec "$jid" /bin/sh
415				exit $?
416			fi
417
418			# Otherwise, fall through and allow chroot(8)
419		fi
420
421		#
422		# Re-execute ourselves with sh(1) via chroot(8)
423		#
424		( echo set -- $args
425		  jail_depend
426		  cat $0
427		) | env - RC_DEFAULTS="$RC_DEFAULTS" \
428		    	/usr/sbin/chroot "$ROOTDIR" /bin/sh
429		exit $?
430	fi
431fi
432
433#
434# Process `-a' or `-A' command-line options
435#
436if [ "$SHOW_ALL" ]; then
437	#
438	# Get a list of variables that are currently set in the rc.conf(5)
439	# files (included `/etc/defaults/rc.conf') by performing a call to
440	# source_rc_confs() in a clean environment.
441	#
442	( # Operate in a sub-shell to protect the parent environment
443		#
444		# Set which variables we want to preserve in the environment.
445		# Append the pipe-character (|) to the list of internal field
446		# separation (IFS) characters, allowing us to use the below
447		# list both as an extended grep (-E) pattern and argument list
448		# (required to first get f_clean_env() to preserve these in the
449		# environment and then later to prune them from the list of
450		# variables produced by set(1)).
451		#
452		IFS="$IFS|"
453		EXCEPT="IFS|EXCEPT|PATH|RC_DEFAULTS|OPTIND|DESCRIBE|SEP"
454		EXCEPT="$EXCEPT|DELETE|SHOW_ALL|SHOW_EQUALS|SHOW_NAME"
455		EXCEPT="$EXCEPT|SHOW_VALUE|SHOW_FILE|VERBOSE|RC_CONFS"
456		EXCEPT="$EXCEPT|pgm|SUCCESS|FAILURE|CHECK_ONLY"
457		EXCEPT="$EXCEPT|f_sysrc_desc_awk|f_sysrc_delete_awk"
458
459		#
460		# Clean the environment (except for our required variables)
461		# and then source the required files.
462		#
463		f_clean_env --except $EXCEPT
464		if [ -f "$RC_DEFAULTS" -a -r "$RC_DEFAULTS" ]; then
465			. "$RC_DEFAULTS"
466
467			#
468			# If passed `-a' (rather than `-A'), re-purge the
469			# environment, removing the rc.conf(5) defaults.
470			#
471			[ "$SHOW_ALL" = "1" ] \
472				&& f_clean_env --except rc_conf_files $EXCEPT
473
474			#
475			# If `-f file' was passed, set $rc_conf_files to an
476			# explicit value, modifying the default behavior of
477			# source_rc_confs().
478			#
479			[ "${RC_CONFS+set}" ] && rc_conf_files="$RC_CONFS"
480
481			source_rc_confs
482
483			#
484			# If passed `-a' (rather than `-A'), remove
485			# `rc_conf_files' unless it was defined somewhere
486			# other than rc.conf(5) defaults.
487			#
488			[ "$SHOW_ALL" = "1" -a \
489			  "$( f_sysrc_find rc_conf_files )" = "$RC_DEFAULTS" \
490			] \
491			&& unset rc_conf_files
492		fi
493
494		for NAME in $( set |
495			awk -F= '/^[[:alpha:]_][[:alnum:]_]*=/ {print $1}' |
496			grep -Ev "^($EXCEPT)$"
497		); do
498			#
499			# If enabled, describe rather than expand value
500			#
501			if [ "$DESCRIBE" ]; then
502				echo "$NAME: $( f_sysrc_desc "$NAME" )"
503				continue
504			fi
505
506			#
507			# If `-F' is passed, find it and move on
508			#
509			if [ "$SHOW_FILE" ]; then
510				[ "$SHOW_NAME" ] && echo -n "$NAME: "
511				f_sysrc_find "$NAME"
512				continue
513			fi
514
515			#
516			# If `-X' is passed, delete the variables
517			#
518			if [ "$DELETE" = "2" ]; then
519				f_sysrc_delete "$NAME"
520				continue
521			fi
522
523			[ "$VERBOSE" ] && \
524				echo -n "$( f_sysrc_find "$NAME" ): "
525
526			#
527			# If `-N' is passed, simplify the output
528			#
529			if [ ! "$SHOW_VALUE" ]; then
530				echo "$NAME"
531				continue
532			fi
533
534			echo "${SHOW_NAME:+$NAME$SEP}$(
535			      f_sysrc_get "$NAME" )${SHOW_EQUALS:+\"}"
536
537		done
538	)
539
540	#
541	# Ignore the remainder of positional arguments.
542	#
543	exit $SUCCESS
544fi
545
546#
547# Process command-line arguments
548#
549status=$SUCCESS
550while [ $# -gt 0 ]; do
551	NAME="${1%%=*}"
552
553	case "$NAME" in
554	*+) mode=APPEND NAME="${NAME%+}" ;;
555	*-) mode=REMOVE NAME="${NAME%-}" ;;
556	 *) mode=ASSIGN
557	esac
558
559	[ "$DESCRIBE" ] && \
560		echo "$NAME: $( f_sysrc_desc "$NAME" )"
561
562	case "$1" in
563	*=*)
564		#
565		# Like sysctl(8), if both `-d' AND "name=value" is passed,
566		# first describe (done above), then attempt to set
567		#
568
569		# If verbose, prefix line with where the directive lives
570		if [ "$VERBOSE" -a ! "$CHECK_ONLY" ]; then
571			file=$( f_sysrc_find "$NAME" )
572			[ "$file" = "$RC_DEFAULTS" -o ! "$file" ] && \
573				file=$( f_sysrc_get 'rc_conf_files%%[$IFS]*' )
574			if [ "$SHOW_EQUALS" ]; then
575				echo -n ": $file; "
576			else
577				echo -n "$file: "
578			fi
579		fi
580
581		#
582		# If `-x' or `-X' is passed, delete the variable and ignore the
583		# desire to set some value
584		#
585		if [ "$DELETE" ]; then
586			f_sysrc_delete "$NAME" || status=$FAILURE
587			shift 1
588			continue
589		fi
590
591		#
592		# If `-c' is passed, simply compare and move on
593		#
594		if [ "$CHECK_ONLY" ]; then
595			if ! IGNORED=$( f_sysrc_get "$NAME?" ); then
596				status=$FAILURE
597				[ "$VERBOSE" ] &&
598					echo "$NAME: not currently set"
599				shift 1
600				continue
601			fi
602			value=$( f_sysrc_get "$NAME" )
603			if [ "$value" != "${1#*=}" ]; then
604				status=$FAILURE
605				if [ "$VERBOSE" ]; then
606					echo -n "$( f_sysrc_find "$NAME" ): "
607					echo -n "$NAME: would change from "
608					echo "\`$value' to \`${1#*=}'"
609				fi
610			elif [ "$VERBOSE" ]; then
611				echo -n "$( f_sysrc_find "$NAME" ): "
612				echo "$NAME: already set to \`$value'"
613			fi
614			shift 1
615			continue
616		fi
617
618		#
619		# Determine both `before' value and appropriate `new' value
620		#
621		case "$mode" in
622		APPEND)
623			before=$( f_sysrc_get "$NAME" )
624			add="${1#*=}"
625			delim="${add%"${add#?}"}" # first character
626			oldIFS="$IFS"
627			case "$delim" in
628			""|[$IFS]|[a-zA-Z0-9]) delim=" " ;;
629			*) IFS="$delim"
630			esac
631			new="$before"
632			for a in $add; do
633				[ "$a" ] || continue
634				skip=
635				for b in $before; do
636					[ "$b" = "$a" ] && skip=1 break
637				done
638				[ "$skip" ] || new="$new$delim$a"
639			done
640			new="${new#"$delim"}" IFS="$oldIFS"
641			unset add delim oldIFS a skip b
642			[ "$SHOW_FILE" ] && before=$( f_sysrc_find "$NAME" )
643			;;
644		REMOVE)
645			before=$( f_sysrc_get "$NAME" )
646			remove="${1#*=}"
647			delim="${remove%"${remove#?}"}" # first character
648			oldIFS="$IFS"
649			case "$delim" in
650			""|[$IFS]|[a-zA-Z0-9]) delim=" " ;;
651			*) IFS="$delim"
652			esac
653			new=
654			for b in $before; do
655				[ "$b" ] || continue
656				add=1
657				for r in $remove; do
658					[ "$r" = "$b" ] && add= break
659				done
660				[ "$add" ] && new="$new$delim$b"
661			done
662			new="${new#"$delim"}" IFS="$oldIFS"
663			unset remove delim oldIFS b add r
664			[ "$SHOW_FILE" ] && before=$( f_sysrc_find "$NAME" )
665			;;
666		*) # ASSIGN
667			if [ "$SHOW_FILE" ]; then
668				before=$( f_sysrc_find "$NAME" )
669			else
670				before=$( f_sysrc_get "$NAME" )
671			fi
672			new="${1#*=}"
673		esac
674
675		#
676		# If `-N' is passed, simplify the output
677		#
678		if [ ! "$SHOW_VALUE" ]; then
679			echo "$NAME"
680			f_sysrc_set "$NAME" "$new"
681		else
682			if f_sysrc_set "$NAME" "$new"; then
683				if [ "$SHOW_FILE" ]; then
684					after=$( f_sysrc_find "$NAME" )
685				else
686					after=$( f_sysrc_get "$NAME" )
687				fi
688				echo -n "${SHOW_NAME:+$NAME$SEP}"
689				echo -n "$before${SHOW_EQUALS:+\" #}"
690				echo -n " -> ${SHOW_EQUALS:+\"}$after"
691				echo "${SHOW_EQUALS:+\"}"
692			fi
693		fi
694		;;
695	*)
696		if ! IGNORED=$( f_sysrc_get "$NAME?" ); then
697			[ "$IGNORE_UNKNOWNS" -o "$QUIET" ] ||
698				echo "$pgm: unknown variable '$NAME'"
699			shift 1
700			status=$FAILURE
701			continue
702		fi
703
704		# The above check told us what we needed for `-c'
705		if [ "$CHECK_ONLY" ]; then
706			shift 1
707			continue
708		fi
709
710		#
711		# Like sysctl(8), when `-d' is passed, desribe it
712		# (already done above) rather than expanding it
713		#
714
715		if [ "$DESCRIBE" ]; then
716			shift 1
717			continue
718		fi
719
720		#
721		# If `-x' or `-X' is passed, delete the variable
722		#
723		if [ "$DELETE" ]; then
724			f_sysrc_delete "$NAME" || status=$FAILURE
725			shift 1
726			continue
727		fi
728
729		#
730		# If `-F' is passed, find it and move on
731		#
732		if [ "$SHOW_FILE" ]; then
733			[ "$SHOW_NAME" ] && echo -n "$NAME: "
734			f_sysrc_find "$NAME"
735			shift 1
736			continue
737		fi
738
739		if [ "$VERBOSE" ]; then
740			if [ "$SHOW_EQUALS" ]; then
741				echo -n ": $( f_sysrc_find "$NAME" ); "
742			else
743				echo -n "$( f_sysrc_find "$NAME" ): "
744			fi
745		fi
746
747		#
748		# If `-N' is passed, simplify the output
749		#
750		if [ ! "$SHOW_VALUE" ]; then
751			echo "$NAME"
752		else
753			echo "${SHOW_NAME:+$NAME$SEP}$(
754			      f_sysrc_get "$NAME" )${SHOW_EQUALS:+\"}"
755		fi
756	esac
757	shift 1
758done
759
760exit $status # $SUCCESS unless error occurred with either `-c' or `-x'
761
762################################################################################
763# END
764################################################################################
765