1#!/bin/sh 2#- 3# Copyright (c) 2010-2018 Devin Teske 4# All rights reserved. 5# 6# Redistribution and use in source and binary forms, with or without 7# modification, are permitted provided that the following conditions 8# are met: 9# 1. Redistributions of source code must retain the above copyright 10# notice, this list of conditions and the following disclaimer. 11# 2. Redistributions in binary form must reproduce the above copyright 12# notice, this list of conditions and the following disclaimer in the 13# documentation and/or other materials provided with the distribution. 14# 15# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25# SUCH DAMAGE. 26# 27# $FreeBSD$ 28# 29############################################################ INCLUDES 30 31# Prevent `-d' from being interpreted as a debug flag by common.subr 32DEBUG_SELF_INITIALIZE= 33 34BSDCFG_SHARE="/usr/share/bsdconfig" 35[ "$_COMMON_SUBR" ] || . $BSDCFG_SHARE/common.subr || exit 1 36[ "$_SYSRC_SUBR" ] || f_include $BSDCFG_SHARE/sysrc.subr 37 38############################################################ GLOBALS 39 40# 41# Version information 42# 43SYSRC_VERSION="7.2 Jun-16,2018" 44 45# 46# Options 47# 48CHECK_ONLY= 49DEFAULT= 50DELETE= 51DESCRIBE= 52EXISTING_ONLY= 53IGNORE_UNKNOWNS= 54JAIL= 55LIST_SERVICE_CONFS= 56LIST_CONFS= 57QUIET= 58ROOTDIR= 59SERVICE= 60SHOW_ALL= 61SHOW_EQUALS= 62SHOW_FILE= 63SHOW_NAME=1 64SHOW_VALUE=1 65VERBOSE= 66 67############################################################ FUNCTIONS 68 69# die [$fmt [$opts ...]] 70# 71# Optionally print a message to stderr before exiting with failure status. 72# 73die() 74{ 75 local fmt="$1" 76 [ $# -gt 0 ] && shift 1 77 [ "$fmt" ] && f_err "$fmt\n" "$@" 78 79 exit $FAILURE 80} 81 82# usage 83# 84# Prints a short syntax statement and exits. 85# 86usage() 87{ 88 f_err "Usage: %s [OPTIONS] %s\n" "$pgm" \ 89 "{name[[+|-]=value] ... | -a | -A | -l | -L [name ...]}" 90 f_err "Try \`%s --help' for more information.\n" "$pgm" 91 die 92} 93 94# help 95# 96# Prints a full syntax statement and exits. 97# 98help() 99{ 100 local optfmt="\t%-11s%s\n" 101 local envfmt="\t%-17s%s\n" 102 103 f_err "Usage: %s [OPTIONS] name[[+|-]=value] ...\n" "$pgm" 104 f_err "Usage: %s [OPTIONS] -a | -A\n" "$pgm" 105 f_err "Usage: %s [OPTIONS] -l | -L [name ...]\n" "$pgm" 106 107 f_err "OPTIONS:\n" 108 f_err "$optfmt" "-a" \ 109 "Dump a list of all non-default configuration variables." 110 f_err "$optfmt" "-A" \ 111 "Dump a list of all configuration variables (incl. defaults)." 112 f_err "$optfmt" "-c" \ 113 "Check. Return success if set or no changes, else error." 114 f_err "$optfmt" "-d" \ 115 "Print a description of the given variable." 116 f_err "$optfmt" "-D" \ 117 "Show default value(s) only (this is the same as setting" 118 f_err "$optfmt" "" \ 119 "RC_CONFS to NULL or passing \`-f' with a NULL file-argument)." 120 f_err "$optfmt" "-e" \ 121 "Print query results as \`var=value' (useful for producing" 122 f_err "$optfmt" "" \ 123 "output to be fed back in). Ignored if \`-n' is specified." 124 f_err "$optfmt" "-E" \ 125 "Existing files only with \`-[lL]' or when changing a setting." 126 f_err "$optfmt" "-f file" \ 127 "Operate on the specified file(s) instead of rc_conf_files." 128 f_err "$optfmt" "" \ 129 "Can be specified multiple times for additional files." 130 f_err "$optfmt" "-F" \ 131 "Show only the last rc.conf(5) file each directive is in." 132 f_err "$optfmt" "-h" \ 133 "Print a short usage statement to stderr and exit." 134 f_err "$optfmt" "--help" \ 135 "Print this message to stderr and exit." 136 f_err "$optfmt" "-i" \ 137 "Ignore unknown variables." 138 f_err "$optfmt" "-j jail" \ 139 "The jid or name of the jail to operate within (overrides" 140 f_err "$optfmt" "" \ 141 "\`-R dir'; requires jexec(8))." 142 f_err "$optfmt" "-l" \ 143 "List configuration files used at startup on stdout and exit." 144 f_err "$optfmt" "-L" \ 145 "List all configuration files including rc.conf.d entries." 146 f_err "$optfmt" "-n" \ 147 "Show only variable values, not their names." 148 f_err "$optfmt" "-N" \ 149 "Show only variable names, not their values." 150 f_err "$optfmt" "-q" \ 151 "Quiet. Disable verbose and hide certain errors." 152 f_err "$optfmt" "-s name" \ 153 "Process additional \`rc.conf.d' entries for service name." 154 f_err "$optfmt" "" \ 155 "Ignored if \`-f file' is given." 156 f_err "$optfmt" "-R dir" \ 157 "Operate within the root directory \`dir' rather than \`/'." 158 f_err "$optfmt" "-v" \ 159 "Verbose. Print the pathname of the specific rc.conf(5)" 160 f_err "$optfmt" "" \ 161 "file where the directive was found." 162 f_err "$optfmt" "--version" \ 163 "Print version information to stdout and exit." 164 f_err "$optfmt" "-x" \ 165 "Remove variable(s) from specified file(s)." 166 f_err "\n" 167 168 f_err "ENVIRONMENT:\n" 169 f_err "$envfmt" "RC_CONFS" \ 170 "Override default rc_conf_files (even if set to NULL)." 171 f_err "$envfmt" "RC_DEFAULTS" \ 172 "Location of \`/etc/defaults/rc.conf' file." 173 174 die 175} 176 177# jail_depend 178# 179# Dump dependencies such as language-file variables and include files to stdout 180# to be piped-into sh(1) running via jexec(8)/chroot(8). As a security measure, 181# this prevents existing language files and library files from being loaded in 182# the jail. This also relaxes the requirement to have these files in every jail 183# before sysrc can be used on said jail. 184# 185jail_depend() 186{ 187 # 188 # Indicate that we are jailed 189 # 190 echo export _SYSRC_JAILED=1 191 192 # 193 # Print i18n language variables (their current values are sanitized 194 # and re-printed for interpretation so that the i18n language files 195 # do not need to exist within the jail). 196 # 197 local var val 198 for var in \ 199 msg_cannot_create_permission_denied \ 200 msg_permission_denied \ 201 msg_previous_syntax_errors \ 202 ; do 203 val=$( eval echo \"\$$var\" | 204 awk '{ gsub(/'\''/, "'\''\\'\'\''"); print }' ) 205 echo $var="'$val'" 206 done 207 208 # 209 # Print include dependencies 210 # 211 echo DEBUG_SELF_INITIALIZE= 212 cat $BSDCFG_SHARE/common.subr 213 cat $BSDCFG_SHARE/sysrc.subr 214} 215 216# escape $string [$var_to_set] 217# 218# Escape $string contents so that the contents can be properly encapsulated in 219# single-quotes (making for safe evaluation). 220# 221# NB: See `bsdconfig includes -dF escape' for relevant information/discussion. 222# NB: Abridged version of `f_shell_escape()' from bsdconfig(8) `strings.subr'. 223# 224escape() 225{ 226 local __start="$1" __var_to_set="$2" __string= 227 while [ "$__start" ]; do 228 case "$__start" in *\'*) 229 __string="$__string${__start%%\'*}'\\''" 230 __start="${__start#*\'}" continue 231 esac 232 break 233 done 234 __string="$__string$__start" 235 if [ "$__var_to_set" ]; then 236 setvar "$__var_to_set" "$__string" 237 else 238 echo "$__string" 239 fi 240} 241 242############################################################ MAIN SOURCE 243 244# 245# Perform sanity checks 246# 247[ $# -gt 0 ] || usage # NOTREACHED 248 249# 250# Check for `--help' and `--version' command-line option 251# 252for arg in "$@"; do 253 case "$arg" in 254 --) break ;; 255 --help) help ;; # NOTREACHED 256 --version) # see GLOBALS 257 echo "$SYSRC_VERSION" 258 exit $FAILURE ;; 259 esac 260done 261unset arg 262 263# 264# Process command-line flags 265# 266while getopts aAcdDeEf:Fhij:lLnNqR:s:vxX flag; do 267 case "$flag" in 268 a) SHOW_ALL=${SHOW_ALL:-1} ;; 269 A) SHOW_ALL=2 ;; 270 c) CHECK_ONLY=1 ;; 271 d) DESCRIBE=1 ;; 272 D) DEFAULT=1 RC_CONFS= ;; 273 e) SHOW_EQUALS=1 ;; 274 E) EXISTING_ONLY=1 ;; 275 f) DEFAULT= RC_CONFS="$RC_CONFS${RC_CONFS:+ }$OPTARG" ;; 276 F) SHOW_FILE=1 ;; 277 h) usage ;; # NOTREACHED 278 i) IGNORE_UNKNOWNS=1 ;; 279 j) [ "$OPTARG" ] || 280 die "%s: Missing or null argument to \`-j' flag" "$pgm" 281 JAIL="$OPTARG" ;; 282 l) LIST_CONFS=1 ;; 283 L) LIST_SERVICE_CONFS=1 ;; 284 n) SHOW_NAME= ;; 285 N) SHOW_VALUE= ;; 286 q) QUIET=1 VERBOSE= ;; 287 R) [ "$OPTARG" ] || 288 die "%s: Missing or null argument to \`-R' flag" "$pgm" 289 ROOTDIR="$OPTARG" ;; 290 s) [ "$OPTARG" ] || 291 die "%s: Missing or null argument to \`-s' flag" "$pgm" 292 SERVICE="$OPTARG" ;; 293 v) VERBOSE=1 QUIET= ;; 294 x) DELETE=${DELETE:-1} ;; 295 X) DELETE=2 ;; 296 \?) usage ;; # NOTREACHED 297 esac 298done 299shift $(( $OPTIND - 1 )) 300 301# 302# Process `-L' flag 303# 304if [ "$LIST_SERVICE_CONFS" ]; then 305 list= 306 307 # 308 # List rc_conf_files if no service names given 309 # 310 files= 311 [ $# -eq 0 ] && files=$( f_sysrc_get rc_conf_files ) 312 for file in $files; do 313 if [ "$EXISTING_ONLY" ]; then 314 [ -e "$file" -a ! -d "$file" ] || continue 315 fi 316 case "$list" in 317 "$file"|*" $file"|"$file "*|*" $file "*) continue ;; 318 esac 319 list="$list $file" 320 done 321 list="${list# }" 322 if [ $# -eq 0 ]; then 323 if [ "$VERBOSE" ]; then 324 echo rc_conf_files: $list 325 elif [ "$SHOW_EQUALS" ]; then 326 echo "rc_conf_files=\"$list\"" 327 fi 328 fi 329 330 # 331 # List rc.conf.d entries 332 # 333 retval=$SUCCESS 334 for service in ${*:-$( service -l )}; do 335 slist= 336 f_sysrc_service_configs $service files || retval=$? continue 337 for file in $files; do 338 if [ "$EXISTING_ONLY" ]; then 339 [ -e "$file" -a ! -d "$file" ] || continue 340 fi 341 if [ ! "$VERBOSE" -a ! "$SHOW_EQUALS" ]; then 342 case "$list" in 343 "$file"|*" $file"|"$file "*|*" $file "*) 344 continue ;; 345 esac 346 fi 347 slist="$slist $file" 348 done 349 slist="${slist# }" 350 if [ $# -gt 0 ]; then 351 [ "$slist" ] || retval=$? 352 fi 353 if [ "$VERBOSE" ]; then 354 [ "$slist" ] && echo "$service: $slist" 355 continue 356 elif [ "$SHOW_EQUALS" ]; then 357 [ "$slist" ] && echo "$service=\"$slist\"" 358 continue 359 fi 360 list="$list${slist:+ }$slist" 361 done 362 if [ ! "$VERBOSE" -a ! "$SHOW_EQUALS" ]; then 363 if [ $# -eq 0 -o ! "$QUIET" ]; then 364 list="${list# }" 365 [ "$list" ] && echo $list 366 fi 367 fi 368 369 exit $retval 370fi 371 372# 373# Validate arguments 374# 375for name in "$@"; do 376 # NB: shell expansion syntax removed first 377 name="${name%%:[+=-]*}" 378 name="${name%%[%#+=-]*}" 379 [ "$name" = "${name#*[!$VALID_VARNAME_CHARS]}" ] || die \ 380 "%s: %s: name contains characters not allowed in shell" \ 381 "$pgm" "$name" 382done 383 384# 385# Process `-s name' argument 386# 387if [ "$SERVICE" -a ! "${RC_CONFS+set}" ]; then 388 if f_sysrc_service_configs "$SERVICE" RC_CONFS; then 389 rc_conf_files=$( f_sysrc_get rc_conf_files ) 390 RC_CONFS="$rc_conf_files${RC_CONFS:+ }$RC_CONFS" 391 unset rc_conf_files 392 else 393 unset RC_CONFS 394 fi 395fi 396 397# 398# Process `-E' option flag 399# 400if [ "$EXISTING_ONLY" ]; then 401 # 402 # To get f_sysrc_*() to ignore missing rc_conf_files, we have to use 403 # RC_CONFS to override the unpreened value. If RC_CONFS already has a 404 # value (`-D', `-f file', `-s name', or inherited from parent), use it. 405 # Otherwise, include filtered contents of rc_conf_files. 406 # 407 RC_CONFS=$( 408 if [ "${RC_CONFS+set}" ]; then 409 set -- $RC_CONFS 410 else 411 set -- $( f_sysrc_get rc_conf_files ) 412 fi 413 while [ $# -gt 0 ]; do 414 [ -f "$1" ] && echo -n " $1" 415 shift 416 done 417 ) 418 RC_CONFS="${RC_CONFS# }" 419fi 420 421# 422# Process `-l' option flag 423# 424if [ "$LIST_CONFS" ]; then 425 [ $# -eq 0 ] || usage 426 if [ "$DEFAULT" ]; then 427 echo "$RC_DEFAULTS" 428 elif [ "${RC_CONFS+set}" ]; then 429 echo "$RC_CONFS" 430 else 431 f_sysrc_get rc_conf_files 432 fi 433 exit $SUCCESS 434fi 435 436# 437# [More] Sanity checks (e.g., "sysrc --") 438# 439[ $# -eq 0 -a ! "$SHOW_ALL" ] && usage # NOTREACHED 440 441# 442# Taint-check all rc.conf(5) files 443# 444errmsg="$pgm: Exiting due to previous syntax errors" 445if [ "${RC_CONFS+set}" ]; then 446 ( for i in $RC_CONFS; do 447 [ -e "$i" ] || continue 448 /bin/sh -n "$i" || exit $FAILURE 449 done 450 exit $SUCCESS 451 ) || die "$errmsg" 452else 453 /bin/sh -n "$RC_DEFAULTS" || die "$errmsg" 454 ( . "$RC_DEFAULTS" 455 for i in $rc_conf_files; do 456 [ -e "$i" ] || continue 457 /bin/sh -n "$i" || exit $FAILURE 458 done 459 exit $SUCCESS 460 ) || die "$errmsg" 461fi 462 463# 464# Process `-x' (and secret `-X') command-line options 465# 466errmsg="$pgm: \`-x' option incompatible with \`-a'/\`-A' options" 467errmsg="$errmsg (use \`-X' to override)" 468if [ "$DELETE" -a "$SHOW_ALL" ]; then 469 [ "$DELETE" = "2" ] || die "$errmsg" 470fi 471 472# 473# Pre-flight for `-c' command-line option 474# 475[ "$CHECK_ONLY" -a "$SHOW_ALL" ] && 476 die "$pgm: \`-c' option incompatible with \`-a'/\`-A' options" 477 478# 479# Process `-e', `-n', and `-N' command-line options 480# 481SEP=': ' 482[ "$SHOW_FILE" ] && SHOW_EQUALS= 483[ "$SHOW_NAME" ] || SHOW_EQUALS= 484[ "$VERBOSE" = "0" ] && VERBOSE= 485if [ ! "$SHOW_VALUE" ]; then 486 SHOW_NAME=1 487 SHOW_EQUALS= 488fi 489[ "$SHOW_EQUALS" ] && SEP='="' 490 491# 492# Process `-j jail' and `-R dir' command-line options 493# 494if [ "$JAIL" -o "$ROOTDIR" ]; then 495 # 496 # Reconstruct the arguments that we want to carry-over 497 # 498 args=" 499 ${VERBOSE:+-v} 500 ${QUIET:+-q} 501 $( [ "$DELETE" = "1" ] && echo \ -x ) 502 $( [ "$DELETE" = "2" ] && echo \ -X ) 503 $( [ "$SHOW_ALL" = "1" ] && echo \ -a ) 504 $( [ "$SHOW_ALL" = "2" ] && echo \ -A ) 505 ${CHECK_ONLY:+-c} 506 ${DEFAULT:+-D} 507 ${EXISTING_ONLY:+-E} 508 ${LIST_CONFS:+-l} 509 ${LIST_SERVICE_CONFS:+-L} 510 ${DESCRIBE:+-d} 511 ${SHOW_EQUALS:+-e} 512 ${IGNORE_UNKNOWNS:+-i} 513 $( [ "$SHOW_NAME" ] || echo \ -n ) 514 $( [ "$SHOW_VALUE" ] || echo \ -N ) 515 $( [ "$SHOW_FILE" ] && echo \ -F ) 516 " 517 if [ "$SERVICE" ]; then 518 escape "$SERVICE" _SERVICE 519 args="$args -s '$_SERVICE'" 520 unset _SERVICE 521 fi 522 if [ "${RC_CONFS+set}" ]; then 523 escape "$RC_CONFS" _RC_CONFS 524 args="$args -f '$_RC_CONFS'" 525 unset _RC_CONFS 526 fi 527 for arg in "$@"; do 528 escape "$arg" arg 529 args="$args '$arg'" 530 done 531 532 # 533 # If both are supplied, `-j jail' supercedes `-R dir' 534 # 535 if [ "$JAIL" ]; then 536 # 537 # Re-execute ourselves with sh(1) via jexec(8) 538 # 539 ( echo set -- $args 540 jail_depend 541 cat $0 542 ) | env - RC_DEFAULTS="$RC_DEFAULTS" \ 543 /usr/sbin/jexec "$JAIL" /bin/sh 544 exit $? 545 elif [ "$ROOTDIR" ]; then 546 # 547 # Make sure that the root directory specified is not to any 548 # running jails. 549 # 550 # NOTE: To maintain backward compatibility with older jails on 551 # older systems, we will not perform this check if either the 552 # jls(1) or jexec(8) utilities are missing. 553 # 554 if f_have jexec && f_have jls; then 555 jid=$( jls jid path | 556 while read JID JROOT; do 557 [ "$JROOT" = "$ROOTDIR" ] || continue 558 echo $JID 559 done 560 ) 561 562 # 563 # If multiple running jails match the specified root 564 # directory, exit with error. 565 # 566 if [ "$jid" -a "${jid%[$IFS]*}" != "$jid" ]; then 567 die "%s: %s: %s" "$pgm" "$ROOTDIR" \ 568 "$( echo "Multiple jails claim this" \ 569 "directory as their root." \ 570 "(use \`-j jail' instead)" )" 571 fi 572 573 # 574 # If only a single running jail matches the specified 575 # root directory, implicitly use `-j jail'. 576 # 577 if [ "$jid" ]; then 578 # 579 # Re-execute outselves with sh(1) via jexec(8) 580 # 581 ( echo set -- $args 582 jail_depend 583 cat $0 584 ) | env - RC_DEFAULTS="$RC_DEFAULTS" \ 585 /usr/sbin/jexec "$jid" /bin/sh 586 exit $? 587 fi 588 589 # Otherwise, fall through and allow chroot(8) 590 fi 591 592 # 593 # Re-execute ourselves with sh(1) via chroot(8) 594 # 595 ( echo set -- $args 596 jail_depend 597 cat $0 598 ) | env - RC_DEFAULTS="$RC_DEFAULTS" \ 599 /usr/sbin/chroot "$ROOTDIR" /bin/sh 600 exit $? 601 fi 602fi 603 604# 605# Process `-a' or `-A' command-line options 606# 607if [ "$SHOW_ALL" ]; then 608 # 609 # Get a list of variables that are currently set in the rc.conf(5) 610 # files (including `/etc/defaults/rc.conf') by performing a call to 611 # source_rc_confs() in a clean environment. 612 # 613 ( # Operate in a sub-shell to protect the parent environment 614 # 615 # Set which variables we want to preserve in the environment. 616 # Append the pipe-character (|) to the list of internal field 617 # separation (IFS) characters, allowing us to use the below 618 # list both as an extended grep (-E) pattern and argument list 619 # (required to first get f_clean_env() to preserve these in the 620 # environment and then later to prune them from the list of 621 # variables produced by set(1)). 622 # 623 IFS="$IFS|" 624 EXCEPT="IFS|EXCEPT|PATH|RC_DEFAULTS|OPTIND|DESCRIBE|SEP" 625 EXCEPT="$EXCEPT|DELETE|SHOW_ALL|SHOW_EQUALS|SHOW_NAME|DEFAULT" 626 EXCEPT="$EXCEPT|SHOW_VALUE|SHOW_FILE|VERBOSE|RC_CONFS|SERVICE" 627 EXCEPT="$EXCEPT|pgm|SUCCESS|FAILURE|CHECK_ONLY|EXISTING_ONLY" 628 EXCEPT="$EXCEPT|LIST_CONFS|LIST_SERVICE_CONFS" 629 EXCEPT="$EXCEPT|f_sysrc_desc_awk|f_sysrc_delete_awk" 630 631 # 632 # Clean the environment (except for our required variables) 633 # and then source the required files. 634 # 635 f_clean_env --except $EXCEPT 636 if [ -f "$RC_DEFAULTS" -a -r "$RC_DEFAULTS" ]; then 637 . "$RC_DEFAULTS" 638 639 # 640 # If passed `-a' (rather than `-A'), re-purge the 641 # environment, removing the rc.conf(5) defaults. 642 # 643 [ "$SHOW_ALL" = "1" ] && 644 f_clean_env --except rc_conf_files $EXCEPT 645 646 # 647 # If `-f file' was passed, set $rc_conf_files to an 648 # explicit value, modifying the default behavior of 649 # source_rc_confs(). 650 # 651 if [ "${RC_CONFS+set}" ]; then 652 [ "$SHOW_ALL" = "1" -a "$SERVICE" -a \ 653 ! "$DEFAULT" ] || rc_conf_files= 654 rc_conf_files="$rc_conf_files $RC_CONFS" 655 rc_conf_files="${rc_conf_files# }" 656 rc_conf_files="${rc_conf_files% }" 657 fi 658 659 source_rc_confs 660 661 # 662 # If passed `-a' (rather than `-A'), remove 663 # `rc_conf_files' unless it was defined somewhere 664 # other than rc.conf(5) defaults. 665 # 666 [ "$SHOW_ALL" = "1" -a \ 667 "$( f_sysrc_find rc_conf_files )" = "$RC_DEFAULTS" \ 668 ] && unset rc_conf_files 669 fi 670 671 for NAME in $( set | 672 awk -F= '/^[[:alpha:]_][[:alnum:]_]*=/ {print $1}' | 673 grep -Ev "^($EXCEPT)$" 674 ); do 675 # 676 # If enabled, describe rather than expand value 677 # 678 if [ "$DESCRIBE" ]; then 679 echo "$NAME: $( f_sysrc_desc "$NAME" )" 680 continue 681 fi 682 683 # 684 # If `-F' is passed, find it and move on 685 # 686 if [ "$SHOW_FILE" ]; then 687 [ "$SHOW_NAME" ] && echo -n "$NAME: " 688 f_sysrc_find "$NAME" 689 continue 690 fi 691 692 # 693 # If `-X' is passed, delete the variables 694 # 695 if [ "$DELETE" = "2" ]; then 696 f_sysrc_delete "$NAME" 697 continue 698 fi 699 700 [ "$VERBOSE" ] && 701 echo -n "$( f_sysrc_find "$NAME" ): " 702 703 # 704 # If `-N' is passed, simplify the output 705 # 706 if [ ! "$SHOW_VALUE" ]; then 707 echo "$NAME" 708 continue 709 fi 710 711 echo "${SHOW_NAME:+$NAME$SEP}$( 712 f_sysrc_get "$NAME" )${SHOW_EQUALS:+\"}" 713 714 done 715 ) 716 717 # 718 # Ignore the remainder of positional arguments. 719 # 720 exit $SUCCESS 721fi 722 723# 724# Process command-line arguments 725# 726status=$SUCCESS 727while [ $# -gt 0 ]; do 728 NAME="${1%%=*}" 729 730 case "$NAME" in 731 *+) mode=APPEND NAME="${NAME%+}" ;; 732 *-) mode=REMOVE NAME="${NAME%-}" ;; 733 *) mode=ASSIGN 734 esac 735 736 [ "$DESCRIBE" ] && 737 echo "$NAME: $( f_sysrc_desc "$NAME" )" 738 739 case "$1" in 740 *=*) 741 # 742 # Like sysctl(8), if both `-d' AND "name=value" is passed, 743 # first describe (done above), then attempt to set 744 # 745 746 # If verbose, prefix line with where the directive lives 747 if [ "$VERBOSE" -a ! "$CHECK_ONLY" ]; then 748 file=$( f_sysrc_find "$NAME" ) 749 [ "$file" = "$RC_DEFAULTS" -o ! "$file" ] && 750 file=$( f_sysrc_get 'rc_conf_files%%[$IFS]*' ) 751 if [ "$SHOW_EQUALS" ]; then 752 echo -n ": $file; " 753 else 754 echo -n "$file: " 755 fi 756 fi 757 758 # 759 # If `-x' or `-X' is passed, delete the variable and ignore the 760 # desire to set some value 761 # 762 if [ "$DELETE" ]; then 763 f_sysrc_delete "$NAME" || status=$FAILURE 764 shift 1 765 continue 766 fi 767 768 # 769 # If `-c' is passed, simply compare and move on 770 # 771 if [ "$CHECK_ONLY" ]; then 772 if ! IGNORED=$( f_sysrc_get "$NAME?" ); then 773 status=$FAILURE 774 [ "$VERBOSE" ] && 775 echo "$NAME: not currently set" 776 shift 1 777 continue 778 fi 779 value=$( f_sysrc_get "$NAME" ) 780 if [ "$value" != "${1#*=}" ]; then 781 status=$FAILURE 782 if [ "$VERBOSE" ]; then 783 echo -n "$( f_sysrc_find "$NAME" ): " 784 echo -n "$NAME: would change from " 785 echo "\`$value' to \`${1#*=}'" 786 fi 787 elif [ "$VERBOSE" ]; then 788 echo -n "$( f_sysrc_find "$NAME" ): " 789 echo "$NAME: already set to \`$value'" 790 fi 791 shift 1 792 continue 793 fi 794 795 # 796 # Determine both `before' value and appropriate `new' value 797 # 798 case "$mode" in 799 APPEND) 800 before=$( f_sysrc_get "$NAME" ) 801 add="${1#*=}" 802 delim="${add%"${add#?}"}" # first character 803 oldIFS="$IFS" 804 case "$delim" in 805 ""|[$IFS]|[a-zA-Z0-9./]) delim=" " ;; 806 *) IFS="$delim" 807 esac 808 new="$before" 809 for a in $add; do 810 [ "$a" ] || continue 811 skip= 812 for b in $before; do 813 [ "$b" = "$a" ] && skip=1 break 814 done 815 [ "$skip" ] || new="$new$delim$a" 816 done 817 new="${new#"$delim"}" IFS="$oldIFS" 818 unset add delim oldIFS a skip b 819 [ "$SHOW_FILE" ] && before=$( f_sysrc_find "$NAME" ) 820 ;; 821 REMOVE) 822 before=$( f_sysrc_get "$NAME" ) 823 remove="${1#*=}" 824 delim="${remove%"${remove#?}"}" # first character 825 oldIFS="$IFS" 826 case "$delim" in 827 ""|[$IFS]|[a-zA-Z0-9./]) delim=" " ;; 828 *) IFS="$delim" 829 esac 830 new= 831 for b in $before; do 832 [ "$b" ] || continue 833 add=1 834 for r in $remove; do 835 [ "$r" = "$b" ] && add= break 836 done 837 [ "$add" ] && new="$new$delim$b" 838 done 839 new="${new#"$delim"}" IFS="$oldIFS" 840 unset remove delim oldIFS b add r 841 [ "$SHOW_FILE" ] && before=$( f_sysrc_find "$NAME" ) 842 ;; 843 *) # ASSIGN 844 if [ "$SHOW_FILE" ]; then 845 before=$( f_sysrc_find "$NAME" ) 846 else 847 before=$( f_sysrc_get "$NAME" ) 848 fi 849 new="${1#*=}" 850 esac 851 852 # 853 # If `-N' is passed, simplify the output 854 # 855 if [ ! "$SHOW_VALUE" ]; then 856 echo "$NAME" 857 f_sysrc_set "$NAME" "$new" || status=$FAILURE 858 else 859 if f_sysrc_set "$NAME" "$new"; then 860 if [ "$SHOW_FILE" ]; then 861 after=$( f_sysrc_find "$NAME" ) 862 else 863 after=$( f_sysrc_get "$NAME" ) 864 fi 865 echo -n "${SHOW_NAME:+$NAME$SEP}" 866 echo -n "$before${SHOW_EQUALS:+\" #}" 867 echo -n " -> ${SHOW_EQUALS:+\"}$after" 868 echo "${SHOW_EQUALS:+\"}" 869 else 870 status=$FAILURE 871 fi 872 fi 873 ;; 874 *) 875 if ! IGNORED=$( f_sysrc_get "$NAME?" ); then 876 [ "$IGNORE_UNKNOWNS" -o "$QUIET" ] || 877 f_err "%s: unknown variable '%s'\n" \ 878 "$pgm" "$NAME" 879 shift 1 880 status=$FAILURE 881 continue 882 fi 883 884 # The above check told us what we needed for `-c' 885 if [ "$CHECK_ONLY" ]; then 886 shift 1 887 continue 888 fi 889 890 # 891 # Like sysctl(8), when `-d' is passed, desribe it 892 # (already done above) rather than expanding it 893 # 894 895 if [ "$DESCRIBE" ]; then 896 shift 1 897 continue 898 fi 899 900 # 901 # If `-x' or `-X' is passed, delete the variable 902 # 903 if [ "$DELETE" ]; then 904 f_sysrc_delete "$NAME" || status=$FAILURE 905 shift 1 906 continue 907 fi 908 909 # 910 # If `-F' is passed, find it and move on 911 # 912 if [ "$SHOW_FILE" ]; then 913 [ "$SHOW_NAME" ] && echo -n "$NAME: " 914 f_sysrc_find "$NAME" 915 shift 1 916 continue 917 fi 918 919 if [ "$VERBOSE" ]; then 920 if [ "$SHOW_EQUALS" ]; then 921 echo -n ": $( f_sysrc_find "$NAME" ); " 922 else 923 echo -n "$( f_sysrc_find "$NAME" ): " 924 fi 925 fi 926 927 # 928 # If `-N' is passed, simplify the output 929 # 930 if [ ! "$SHOW_VALUE" ]; then 931 echo "$NAME" 932 else 933 echo "${SHOW_NAME:+$NAME$SEP}$( 934 f_sysrc_get "$NAME" )${SHOW_EQUALS:+\"}" 935 fi 936 esac 937 shift 1 938done 939 940exit $status # $SUCCESS unless error occurred with either `-c' or `-x' 941 942################################################################################ 943# END 944################################################################################ 945