1#!/bin/sh 2#- 3# Copyright (c) 2010-2016 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.1 Feb-2,2016" 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# Process `-s name' argument 374# 375if [ "$SERVICE" -a ! "${RC_CONFS+set}" ]; then 376 if f_sysrc_service_configs "$SERVICE" RC_CONFS; then 377 rc_conf_files=$( f_sysrc_get rc_conf_files ) 378 RC_CONFS="$rc_conf_files${RC_CONFS:+ }$RC_CONFS" 379 unset rc_conf_files 380 else 381 unset RC_CONFS 382 fi 383fi 384 385# 386# Process `-E' option flag 387# 388if [ "$EXISTING_ONLY" ]; then 389 # 390 # To get f_sysrc_*() to ignore missing rc_conf_files, we have to use 391 # RC_CONFS to override the unpreened value. If RC_CONFS already has a 392 # value (`-D', `-f file', `-s name', or inherited from parent), use it. 393 # Otherwise, include filtered contents of rc_conf_files. 394 # 395 RC_CONFS=$( 396 if [ "${RC_CONFS+set}" ]; then 397 set -- $RC_CONFS 398 else 399 set -- $( f_sysrc_get rc_conf_files ) 400 fi 401 while [ $# -gt 0 ]; do 402 [ -f "$1" ] && echo -n " $1" 403 shift 404 done 405 ) 406 RC_CONFS="${RC_CONFS# }" 407fi 408 409# 410# Process `-l' option flag 411# 412if [ "$LIST_CONFS" ]; then 413 [ $# -eq 0 ] || usage 414 if [ "$DEFAULT" ]; then 415 echo "$RC_DEFAULTS" 416 elif [ "${RC_CONFS+set}" ]; then 417 echo "$RC_CONFS" 418 else 419 f_sysrc_get rc_conf_files 420 fi 421 exit $SUCCESS 422fi 423 424# 425# [More] Sanity checks (e.g., "sysrc --") 426# 427[ $# -eq 0 -a ! "$SHOW_ALL" ] && usage # NOTREACHED 428 429# 430# Taint-check all rc.conf(5) files 431# 432errmsg="$pgm: Exiting due to previous syntax errors" 433if [ "${RC_CONFS+set}" ]; then 434 ( for i in $RC_CONFS; do 435 [ -e "$i" ] || continue 436 /bin/sh -n "$i" || exit $FAILURE 437 done 438 exit $SUCCESS 439 ) || die "$errmsg" 440else 441 /bin/sh -n "$RC_DEFAULTS" || die "$errmsg" 442 ( . "$RC_DEFAULTS" 443 for i in $rc_conf_files; do 444 [ -e "$i" ] || continue 445 /bin/sh -n "$i" || exit $FAILURE 446 done 447 exit $SUCCESS 448 ) || die "$errmsg" 449fi 450 451# 452# Process `-x' (and secret `-X') command-line options 453# 454errmsg="$pgm: \`-x' option incompatible with \`-a'/\`-A' options" 455errmsg="$errmsg (use \`-X' to override)" 456if [ "$DELETE" -a "$SHOW_ALL" ]; then 457 [ "$DELETE" = "2" ] || die "$errmsg" 458fi 459 460# 461# Pre-flight for `-c' command-line option 462# 463[ "$CHECK_ONLY" -a "$SHOW_ALL" ] && 464 die "$pgm: \`-c' option incompatible with \`-a'/\`-A' options" 465 466# 467# Process `-e', `-n', and `-N' command-line options 468# 469SEP=': ' 470[ "$SHOW_FILE" ] && SHOW_EQUALS= 471[ "$SHOW_NAME" ] || SHOW_EQUALS= 472[ "$VERBOSE" = "0" ] && VERBOSE= 473if [ ! "$SHOW_VALUE" ]; then 474 SHOW_NAME=1 475 SHOW_EQUALS= 476fi 477[ "$SHOW_EQUALS" ] && SEP='="' 478 479# 480# Process `-j jail' and `-R dir' command-line options 481# 482if [ "$JAIL" -o "$ROOTDIR" ]; then 483 # 484 # Reconstruct the arguments that we want to carry-over 485 # 486 args=" 487 ${VERBOSE:+-v} 488 ${QUIET:+-q} 489 $( [ "$DELETE" = "1" ] && echo \ -x ) 490 $( [ "$DELETE" = "2" ] && echo \ -X ) 491 $( [ "$SHOW_ALL" = "1" ] && echo \ -a ) 492 $( [ "$SHOW_ALL" = "2" ] && echo \ -A ) 493 ${CHECK_ONLY:+-c} 494 ${DEFAULT:+-D} 495 ${EXISTING_ONLY:+-E} 496 ${LIST_CONFS:+-l} 497 ${LIST_SERVICE_CONFS:+-L} 498 ${DESCRIBE:+-d} 499 ${SHOW_EQUALS:+-e} 500 ${IGNORE_UNKNOWNS:+-i} 501 $( [ "$SHOW_NAME" ] || echo \ -n ) 502 $( [ "$SHOW_VALUE" ] || echo \ -N ) 503 $( [ "$SHOW_FILE" ] && echo \ -F ) 504 " 505 if [ "$SERVICE" ]; then 506 escape "$SERVICE" _SERVICE 507 args="$args -s '$_SERVICE'" 508 unset _SERVICE 509 fi 510 if [ "${RC_CONFS+set}" ]; then 511 escape "$RC_CONFS" _RC_CONFS 512 args="$args -f '$_RC_CONFS'" 513 unset _RC_CONFS 514 fi 515 for arg in "$@"; do 516 escape "$arg" arg 517 args="$args '$arg'" 518 done 519 520 # 521 # If both are supplied, `-j jail' supercedes `-R dir' 522 # 523 if [ "$JAIL" ]; then 524 # 525 # Re-execute ourselves with sh(1) via jexec(8) 526 # 527 ( echo set -- $args 528 jail_depend 529 cat $0 530 ) | env - RC_DEFAULTS="$RC_DEFAULTS" \ 531 /usr/sbin/jexec "$JAIL" /bin/sh 532 exit $? 533 elif [ "$ROOTDIR" ]; then 534 # 535 # Make sure that the root directory specified is not to any 536 # running jails. 537 # 538 # NOTE: To maintain backward compatibility with older jails on 539 # older systems, we will not perform this check if either the 540 # jls(1) or jexec(8) utilities are missing. 541 # 542 if f_have jexec && f_have jls; then 543 jid=$( jls jid path | 544 while read JID JROOT; do 545 [ "$JROOT" = "$ROOTDIR" ] || continue 546 echo $JID 547 done 548 ) 549 550 # 551 # If multiple running jails match the specified root 552 # directory, exit with error. 553 # 554 if [ "$jid" -a "${jid%[$IFS]*}" != "$jid" ]; then 555 die "%s: %s: %s" "$pgm" "$ROOTDIR" \ 556 "$( echo "Multiple jails claim this" \ 557 "directory as their root." \ 558 "(use \`-j jail' instead)" )" 559 fi 560 561 # 562 # If only a single running jail matches the specified 563 # root directory, implicitly use `-j jail'. 564 # 565 if [ "$jid" ]; then 566 # 567 # Re-execute outselves with sh(1) via jexec(8) 568 # 569 ( echo set -- $args 570 jail_depend 571 cat $0 572 ) | env - RC_DEFAULTS="$RC_DEFAULTS" \ 573 /usr/sbin/jexec "$jid" /bin/sh 574 exit $? 575 fi 576 577 # Otherwise, fall through and allow chroot(8) 578 fi 579 580 # 581 # Re-execute ourselves with sh(1) via chroot(8) 582 # 583 ( echo set -- $args 584 jail_depend 585 cat $0 586 ) | env - RC_DEFAULTS="$RC_DEFAULTS" \ 587 /usr/sbin/chroot "$ROOTDIR" /bin/sh 588 exit $? 589 fi 590fi 591 592# 593# Process `-a' or `-A' command-line options 594# 595if [ "$SHOW_ALL" ]; then 596 # 597 # Get a list of variables that are currently set in the rc.conf(5) 598 # files (including `/etc/defaults/rc.conf') by performing a call to 599 # source_rc_confs() in a clean environment. 600 # 601 ( # Operate in a sub-shell to protect the parent environment 602 # 603 # Set which variables we want to preserve in the environment. 604 # Append the pipe-character (|) to the list of internal field 605 # separation (IFS) characters, allowing us to use the below 606 # list both as an extended grep (-E) pattern and argument list 607 # (required to first get f_clean_env() to preserve these in the 608 # environment and then later to prune them from the list of 609 # variables produced by set(1)). 610 # 611 IFS="$IFS|" 612 EXCEPT="IFS|EXCEPT|PATH|RC_DEFAULTS|OPTIND|DESCRIBE|SEP" 613 EXCEPT="$EXCEPT|DELETE|SHOW_ALL|SHOW_EQUALS|SHOW_NAME|DEFAULT" 614 EXCEPT="$EXCEPT|SHOW_VALUE|SHOW_FILE|VERBOSE|RC_CONFS|SERVICE" 615 EXCEPT="$EXCEPT|pgm|SUCCESS|FAILURE|CHECK_ONLY|EXISTING_ONLY" 616 EXCEPT="$EXCEPT|LIST_CONFS|LIST_SERVICE_CONFS" 617 EXCEPT="$EXCEPT|f_sysrc_desc_awk|f_sysrc_delete_awk" 618 619 # 620 # Clean the environment (except for our required variables) 621 # and then source the required files. 622 # 623 f_clean_env --except $EXCEPT 624 if [ -f "$RC_DEFAULTS" -a -r "$RC_DEFAULTS" ]; then 625 . "$RC_DEFAULTS" 626 627 # 628 # If passed `-a' (rather than `-A'), re-purge the 629 # environment, removing the rc.conf(5) defaults. 630 # 631 [ "$SHOW_ALL" = "1" ] && 632 f_clean_env --except rc_conf_files $EXCEPT 633 634 # 635 # If `-f file' was passed, set $rc_conf_files to an 636 # explicit value, modifying the default behavior of 637 # source_rc_confs(). 638 # 639 if [ "${RC_CONFS+set}" ]; then 640 [ "$SHOW_ALL" = "1" -a "$SERVICE" -a \ 641 ! "$DEFAULT" ] || rc_conf_files= 642 rc_conf_files="$rc_conf_files $RC_CONFS" 643 rc_conf_files="${rc_conf_files# }" 644 rc_conf_files="${rc_conf_files% }" 645 fi 646 647 source_rc_confs 648 649 # 650 # If passed `-a' (rather than `-A'), remove 651 # `rc_conf_files' unless it was defined somewhere 652 # other than rc.conf(5) defaults. 653 # 654 [ "$SHOW_ALL" = "1" -a \ 655 "$( f_sysrc_find rc_conf_files )" = "$RC_DEFAULTS" \ 656 ] && unset rc_conf_files 657 fi 658 659 for NAME in $( set | 660 awk -F= '/^[[:alpha:]_][[:alnum:]_]*=/ {print $1}' | 661 grep -Ev "^($EXCEPT)$" 662 ); do 663 # 664 # If enabled, describe rather than expand value 665 # 666 if [ "$DESCRIBE" ]; then 667 echo "$NAME: $( f_sysrc_desc "$NAME" )" 668 continue 669 fi 670 671 # 672 # If `-F' is passed, find it and move on 673 # 674 if [ "$SHOW_FILE" ]; then 675 [ "$SHOW_NAME" ] && echo -n "$NAME: " 676 f_sysrc_find "$NAME" 677 continue 678 fi 679 680 # 681 # If `-X' is passed, delete the variables 682 # 683 if [ "$DELETE" = "2" ]; then 684 f_sysrc_delete "$NAME" 685 continue 686 fi 687 688 [ "$VERBOSE" ] && 689 echo -n "$( f_sysrc_find "$NAME" ): " 690 691 # 692 # If `-N' is passed, simplify the output 693 # 694 if [ ! "$SHOW_VALUE" ]; then 695 echo "$NAME" 696 continue 697 fi 698 699 echo "${SHOW_NAME:+$NAME$SEP}$( 700 f_sysrc_get "$NAME" )${SHOW_EQUALS:+\"}" 701 702 done 703 ) 704 705 # 706 # Ignore the remainder of positional arguments. 707 # 708 exit $SUCCESS 709fi 710 711# 712# Process command-line arguments 713# 714status=$SUCCESS 715while [ $# -gt 0 ]; do 716 NAME="${1%%=*}" 717 718 case "$NAME" in 719 *+) mode=APPEND NAME="${NAME%+}" ;; 720 *-) mode=REMOVE NAME="${NAME%-}" ;; 721 *) mode=ASSIGN 722 esac 723 724 [ "$DESCRIBE" ] && 725 echo "$NAME: $( f_sysrc_desc "$NAME" )" 726 727 case "$1" in 728 *=*) 729 # 730 # Like sysctl(8), if both `-d' AND "name=value" is passed, 731 # first describe (done above), then attempt to set 732 # 733 734 # If verbose, prefix line with where the directive lives 735 if [ "$VERBOSE" -a ! "$CHECK_ONLY" ]; then 736 file=$( f_sysrc_find "$NAME" ) 737 [ "$file" = "$RC_DEFAULTS" -o ! "$file" ] && 738 file=$( f_sysrc_get 'rc_conf_files%%[$IFS]*' ) 739 if [ "$SHOW_EQUALS" ]; then 740 echo -n ": $file; " 741 else 742 echo -n "$file: " 743 fi 744 fi 745 746 # 747 # If `-x' or `-X' is passed, delete the variable and ignore the 748 # desire to set some value 749 # 750 if [ "$DELETE" ]; then 751 f_sysrc_delete "$NAME" || status=$FAILURE 752 shift 1 753 continue 754 fi 755 756 # 757 # If `-c' is passed, simply compare and move on 758 # 759 if [ "$CHECK_ONLY" ]; then 760 if ! IGNORED=$( f_sysrc_get "$NAME?" ); then 761 status=$FAILURE 762 [ "$VERBOSE" ] && 763 echo "$NAME: not currently set" 764 shift 1 765 continue 766 fi 767 value=$( f_sysrc_get "$NAME" ) 768 if [ "$value" != "${1#*=}" ]; then 769 status=$FAILURE 770 if [ "$VERBOSE" ]; then 771 echo -n "$( f_sysrc_find "$NAME" ): " 772 echo -n "$NAME: would change from " 773 echo "\`$value' to \`${1#*=}'" 774 fi 775 elif [ "$VERBOSE" ]; then 776 echo -n "$( f_sysrc_find "$NAME" ): " 777 echo "$NAME: already set to \`$value'" 778 fi 779 shift 1 780 continue 781 fi 782 783 # 784 # Determine both `before' value and appropriate `new' value 785 # 786 case "$mode" in 787 APPEND) 788 before=$( f_sysrc_get "$NAME" ) 789 add="${1#*=}" 790 delim="${add%"${add#?}"}" # first character 791 oldIFS="$IFS" 792 case "$delim" in 793 ""|[$IFS]|[a-zA-Z0-9./]) delim=" " ;; 794 *) IFS="$delim" 795 esac 796 new="$before" 797 for a in $add; do 798 [ "$a" ] || continue 799 skip= 800 for b in $before; do 801 [ "$b" = "$a" ] && skip=1 break 802 done 803 [ "$skip" ] || new="$new$delim$a" 804 done 805 new="${new#"$delim"}" IFS="$oldIFS" 806 unset add delim oldIFS a skip b 807 [ "$SHOW_FILE" ] && before=$( f_sysrc_find "$NAME" ) 808 ;; 809 REMOVE) 810 before=$( f_sysrc_get "$NAME" ) 811 remove="${1#*=}" 812 delim="${remove%"${remove#?}"}" # first character 813 oldIFS="$IFS" 814 case "$delim" in 815 ""|[$IFS]|[a-zA-Z0-9./]) delim=" " ;; 816 *) IFS="$delim" 817 esac 818 new= 819 for b in $before; do 820 [ "$b" ] || continue 821 add=1 822 for r in $remove; do 823 [ "$r" = "$b" ] && add= break 824 done 825 [ "$add" ] && new="$new$delim$b" 826 done 827 new="${new#"$delim"}" IFS="$oldIFS" 828 unset remove delim oldIFS b add r 829 [ "$SHOW_FILE" ] && before=$( f_sysrc_find "$NAME" ) 830 ;; 831 *) # ASSIGN 832 if [ "$SHOW_FILE" ]; then 833 before=$( f_sysrc_find "$NAME" ) 834 else 835 before=$( f_sysrc_get "$NAME" ) 836 fi 837 new="${1#*=}" 838 esac 839 840 # 841 # If `-N' is passed, simplify the output 842 # 843 if [ ! "$SHOW_VALUE" ]; then 844 echo "$NAME" 845 f_sysrc_set "$NAME" "$new" 846 else 847 if f_sysrc_set "$NAME" "$new"; then 848 if [ "$SHOW_FILE" ]; then 849 after=$( f_sysrc_find "$NAME" ) 850 else 851 after=$( f_sysrc_get "$NAME" ) 852 fi 853 echo -n "${SHOW_NAME:+$NAME$SEP}" 854 echo -n "$before${SHOW_EQUALS:+\" #}" 855 echo -n " -> ${SHOW_EQUALS:+\"}$after" 856 echo "${SHOW_EQUALS:+\"}" 857 fi 858 fi 859 ;; 860 *) 861 if ! IGNORED=$( f_sysrc_get "$NAME?" ); then 862 [ "$IGNORE_UNKNOWNS" -o "$QUIET" ] || 863 echo "$pgm: unknown variable '$NAME'" 864 shift 1 865 status=$FAILURE 866 continue 867 fi 868 869 # The above check told us what we needed for `-c' 870 if [ "$CHECK_ONLY" ]; then 871 shift 1 872 continue 873 fi 874 875 # 876 # Like sysctl(8), when `-d' is passed, desribe it 877 # (already done above) rather than expanding it 878 # 879 880 if [ "$DESCRIBE" ]; then 881 shift 1 882 continue 883 fi 884 885 # 886 # If `-x' or `-X' is passed, delete the variable 887 # 888 if [ "$DELETE" ]; then 889 f_sysrc_delete "$NAME" || status=$FAILURE 890 shift 1 891 continue 892 fi 893 894 # 895 # If `-F' is passed, find it and move on 896 # 897 if [ "$SHOW_FILE" ]; then 898 [ "$SHOW_NAME" ] && echo -n "$NAME: " 899 f_sysrc_find "$NAME" 900 shift 1 901 continue 902 fi 903 904 if [ "$VERBOSE" ]; then 905 if [ "$SHOW_EQUALS" ]; then 906 echo -n ": $( f_sysrc_find "$NAME" ); " 907 else 908 echo -n "$( f_sysrc_find "$NAME" ): " 909 fi 910 fi 911 912 # 913 # If `-N' is passed, simplify the output 914 # 915 if [ ! "$SHOW_VALUE" ]; then 916 echo "$NAME" 917 else 918 echo "${SHOW_NAME:+$NAME$SEP}$( 919 f_sysrc_get "$NAME" )${SHOW_EQUALS:+\"}" 920 fi 921 esac 922 shift 1 923done 924 925exit $status # $SUCCESS unless error occurred with either `-c' or `-x' 926 927################################################################################ 928# END 929################################################################################ 930