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