1238438Sdteskeif [ ! "$_SYSRC_SUBR" ]; then _SYSRC_SUBR=1 2238438Sdteske# 3290693Sdteske# Copyright (c) 2006-2015 Devin Teske 4252982Sdteske# All rights reserved. 5238438Sdteske# 6238438Sdteske# Redistribution and use in source and binary forms, with or without 7238438Sdteske# modification, are permitted provided that the following conditions 8238438Sdteske# are met: 9238438Sdteske# 1. Redistributions of source code must retain the above copyright 10238438Sdteske# notice, this list of conditions and the following disclaimer. 11238438Sdteske# 2. Redistributions in binary form must reproduce the above copyright 12238438Sdteske# notice, this list of conditions and the following disclaimer in the 13238438Sdteske# documentation and/or other materials provided with the distribution. 14238438Sdteske# 15238438Sdteske# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16252987Sdteske# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17238438Sdteske# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18238438Sdteske# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19238438Sdteske# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20240797Sdteske# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21238438Sdteske# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22238438Sdteske# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23238438Sdteske# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24238438Sdteske# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25238438Sdteske# SUCH DAMAGE. 26238438Sdteske# 27238438Sdteske# $FreeBSD: releng/11.0/usr.sbin/bsdconfig/share/sysrc.subr 290693 2015-11-12 00:30:33Z dteske $ 28238438Sdteske# 29238438Sdteske############################################################ INCLUDES 30238438Sdteske 31240684SdteskeBSDCFG_SHARE="/usr/share/bsdconfig" 32241149Sdteske[ "$_COMMON_SUBR" ] || . $BSDCFG_SHARE/common.subr || exit 1 33240684Sdteske 34238438SdteskeBSDCFG_LIBE="/usr/libexec/bsdconfig" 35244675Sdteskeif [ ! "$_SYSRC_JAILED" ]; then 36244675Sdteske f_dprintf "%s: loading includes..." sysrc.subr 37244675Sdteske f_include_lang $BSDCFG_LIBE/include/messages.subr 38244675Sdteskefi 39238438Sdteske 40238438Sdteske############################################################ CONFIGURATION 41238438Sdteske 42238438Sdteske# 43238438Sdteske# Standard pathnames (inherit values from shell if available) 44238438Sdteske# 45238438Sdteske: ${RC_DEFAULTS:="/etc/defaults/rc.conf"} 46238438Sdteske 47238438Sdteske############################################################ GLOBALS 48238438Sdteske 49238438Sdteske# 50238438Sdteske# Global exit status variables 51238438Sdteske# 52238438SdteskeSUCCESS=0 53238438SdteskeFAILURE=1 54238438Sdteske 55241019Sdteske# 56241019Sdteske# Valid characters that can appear in an sh(1) variable name 57241019Sdteske# 58241019Sdteske# Please note that the character ranges A-Z and a-z should be avoided because 59241019Sdteske# these can include accent characters (which are not valid in a variable name). 60241019Sdteske# For example, A-Z matches any character that sorts after A but before Z, 61241019Sdteske# including A and Z. Although ASCII order would make more sense, that is not 62241019Sdteske# how it works. 63241019Sdteske# 64241019SdteskeVALID_VARNAME_CHARS="0-9ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_" 65241019Sdteske 66238438Sdteske############################################################ FUNCTIONS 67238438Sdteske 68238438Sdteske# f_clean_env [ --except $varname ... ] 69238438Sdteske# 70238438Sdteske# Unset all environment variables in the current scope. An optional list of 71238438Sdteske# arguments can be passed, indicating which variables to avoid unsetting; the 72238438Sdteske# `--except' is required to enable the exclusion-list as the remainder of 73238438Sdteske# positional arguments. 74238438Sdteske# 75238438Sdteske# Be careful not to call this in a shell that you still expect to perform 76238438Sdteske# $PATH expansion in, because this will blow $PATH away. This is best used 77238438Sdteske# within a sub-shell block "(...)" or "$(...)" or "`...`". 78238438Sdteske# 79238438Sdteskef_clean_env() 80238438Sdteske{ 81238438Sdteske local var arg except= 82238438Sdteske 83238438Sdteske # 84238438Sdteske # Should we process an exclusion-list? 85238438Sdteske # 86238438Sdteske if [ "$1" = "--except" ]; then 87238438Sdteske except=1 88238438Sdteske shift 1 89238438Sdteske fi 90238438Sdteske 91238438Sdteske # 92238438Sdteske # Loop over a list of variable names from set(1) built-in. 93238438Sdteske # 94238438Sdteske for var in $( set | awk -F= \ 95238438Sdteske '/^[[:alpha:]_][[:alnum:]_]*=/ {print $1}' \ 96238438Sdteske | grep -v '^except$' 97238438Sdteske ); do 98238438Sdteske # 99238438Sdteske # In POSIX bourne-shell, attempting to unset(1) OPTIND results 100238438Sdteske # in "unset: Illegal number:" and causes abrupt termination. 101238438Sdteske # 102238438Sdteske [ "$var" = OPTIND ] && continue 103238438Sdteske 104238438Sdteske # 105238438Sdteske # Process the exclusion-list? 106238438Sdteske # 107238438Sdteske if [ "$except" ]; then 108238438Sdteske for arg in "$@" ""; do 109238438Sdteske [ "$var" = "$arg" ] && break 110238438Sdteske done 111238438Sdteske [ "$arg" ] && continue 112238438Sdteske fi 113238438Sdteske 114238438Sdteske unset "$var" 115238438Sdteske done 116238438Sdteske} 117238438Sdteske 118238438Sdteske# f_sysrc_get $varname 119238438Sdteske# 120238438Sdteske# Get a system configuration setting from the collection of system- 121258029Sdteske# configuration files (in order: /etc/defaults/rc.conf /etc/rc.conf and 122258029Sdteske# /etc/rc.conf.local) 123238438Sdteske# 124238438Sdteske# NOTE: Additional shell parameter-expansion formats are supported. For 125238438Sdteske# example, passing an argument of "hostname%%.*" (properly quoted) will 126238438Sdteske# return the hostname up to (but not including) the first `.' (see sh(1), 127238438Sdteske# "Parameter Expansion" for more information on additional formats). 128238438Sdteske# 129238438Sdteskef_sysrc_get() 130238438Sdteske{ 131238438Sdteske # Sanity check 132238438Sdteske [ -f "$RC_DEFAULTS" -a -r "$RC_DEFAULTS" ] || return $FAILURE 133238438Sdteske 134238438Sdteske # Taint-check variable name 135238438Sdteske case "$1" in 136238438Sdteske [0-9]*) 137238438Sdteske # Don't expand possible positional parameters 138252178Sdteske return $FAILURE ;; 139238438Sdteske *) 140238438Sdteske [ "$1" ] || return $FAILURE 141238438Sdteske esac 142238438Sdteske 143238438Sdteske ( # Execute within sub-shell to protect parent environment 144238438Sdteske 145238438Sdteske # 146238438Sdteske # Clear the environment of all variables, preventing the 147238438Sdteske # expansion of normals such as `PS1', `TERM', etc. 148238438Sdteske # 149241042Sdteske f_clean_env --except IFS RC_CONFS RC_DEFAULTS 150238438Sdteske 151240783Sdteske . "$RC_DEFAULTS" > /dev/null 2>&1 152238438Sdteske 153238438Sdteske unset RC_DEFAULTS 154238438Sdteske # no longer needed 155238438Sdteske 156238438Sdteske # 157238438Sdteske # If the query is for `rc_conf_files' then store the value that 158238438Sdteske # we inherited from sourcing RC_DEFAULTS (above) so that we may 159238438Sdteske # conditionally restore this value after source_rc_confs in the 160238438Sdteske # event that RC_CONFS does not customize the value. 161238438Sdteske # 162238438Sdteske if [ "$1" = "rc_conf_files" ]; then 163238438Sdteske _rc_conf_files="$rc_conf_files" 164238438Sdteske fi 165238438Sdteske 166238438Sdteske # 167238438Sdteske # If RC_CONFS is defined, set $rc_conf_files to an explicit 168238438Sdteske # value, modifying the default behavior of source_rc_confs(). 169238438Sdteske # 170240798Sdteske if [ "${RC_CONFS+set}" ]; then 171238438Sdteske rc_conf_files="$RC_CONFS" 172238438Sdteske _rc_confs_set=1 173238438Sdteske fi 174238438Sdteske 175240783Sdteske source_rc_confs > /dev/null 2>&1 176238438Sdteske 177238438Sdteske # 178238438Sdteske # If the query was for `rc_conf_files' AND after calling 179240797Sdteske # source_rc_confs the value has not changed, then we should 180238438Sdteske # restore the value to the one inherited from RC_DEFAULTS 181238438Sdteske # before performing the final query (preventing us from 182238438Sdteske # returning what was set via RC_CONFS when the intent was 183238438Sdteske # instead to query the value from the file(s) specified). 184238438Sdteske # 185238438Sdteske if [ "$1" = "rc_conf_files" -a \ 186238438Sdteske "$_rc_confs_set" -a \ 187238438Sdteske "$rc_conf_files" = "$RC_CONFS" \ 188238438Sdteske ]; then 189238438Sdteske rc_conf_files="$_rc_conf_files" 190238438Sdteske unset _rc_conf_files 191238438Sdteske unset _rc_confs_set 192238438Sdteske fi 193238438Sdteske 194238438Sdteske unset RC_CONFS 195238438Sdteske # no longer needed 196238438Sdteske 197238438Sdteske # 198238438Sdteske # This must be the last functional line for both the sub-shell 199238438Sdteske # and the function to preserve the return status from formats 200238438Sdteske # such as "${varname?}" and "${varname:?}" (see "Parameter 201238438Sdteske # Expansion" in sh(1) for more information). 202238438Sdteske # 203240783Sdteske eval echo '"${'"$1"'}"' 2> /dev/null 204238438Sdteske ) 205238438Sdteske} 206238438Sdteske 207290693Sdteske# f_sysrc_service_configs [-a|-p] $name [$var_to_set] 208290693Sdteske# 209290693Sdteske# Get a list of optional `rc.conf.d' entries sourced by system `rc.d' script 210290693Sdteske# $name (see rc.subr(8) for additional information on `rc.conf.d'). If $name 211290693Sdteske# exists in `/etc/rc.d' or $local_startup directories and is an rc(8) script 212290693Sdteske# the result is a space separated list of `rc.conf.d' entries sourced by the 213290693Sdteske# $name `rc.d' script. Otherwise, if $name exists as a binary `rc.d' script, 214290693Sdteske# the result is ``/etc/rc.conf.d/$name /usr/local/etc/rc.conf.d/$name''. The 215290693Sdteske# result is NULL if $name does not exist. 216290693Sdteske# 217290693Sdteske# If $var_to_set is missing or NULL, output is to standard out. Returns success 218290693Sdteske# if $name was found, failure otherwise. 219290693Sdteske# 220290693Sdteske# If `-a' flag is given and $var_to_set is non-NULL, append result to value of 221290693Sdteske# $var_to_set rather than overwriting current contents. 222290693Sdteske# 223290693Sdteske# If `-p' flag is given and $var_to_set is non-NULL, prepend result to value of 224290693Sdteske# $var_to_set rather than overwriting current contents. 225290693Sdteske# 226290693Sdteske# NB: The `-a' and `-p' option flags are mutually exclusive. 227290693Sdteske# 228290693Sdteskef_sysrc_service_configs() 229290693Sdteske{ 230290693Sdteske local OPTIND=1 OPTARG __flag __append= __prepend= 231290693Sdteske local __local_startup __dir __spath __stype __names= 232290693Sdteske 233290693Sdteske while getopts ap __flag; do 234290693Sdteske case "$__flag" in 235290693Sdteske a) __append=1 __prepend= ;; 236290693Sdteske p) __prepend=1 __append= ;; 237290693Sdteske esac 238290693Sdteske done 239290693Sdteske shift $(( $OPTIND - 1 )) 240290693Sdteske 241290693Sdteske [ $# -gt 0 ] || return $FAILURE 242290693Sdteske local __sname="$1" __var_to_set="$2" 243290693Sdteske 244290693Sdteske __local_startup=$( f_sysrc_get local_startup ) 245290693Sdteske for __dir in /etc/rc.d $__local_startup; do 246290693Sdteske __spath="$__dir/$__sname" 247290693Sdteske [ -f "$__spath" -a -x "$__spath" ] || __spath= continue 248290693Sdteske break 249290693Sdteske done 250290693Sdteske [ "$__spath" ] || return $FAILURE 251290693Sdteske 252290693Sdteske __stype=$( file -b "$__spath" 2> /dev/null ) 253290693Sdteske case "$__stype" in 254290693Sdteske *"shell script"*) 255290693Sdteske __names=$( exec 9<&1 1>&- 2>&- 256290693Sdteske last_name= 257290693Sdteske print_name() { 258290693Sdteske local name="$1" 259290693Sdteske [ "$name" = "$last_name" ] && return 260290693Sdteske echo "$name" >&9 261290693Sdteske last_name="$name" 262290693Sdteske } 263290693Sdteske eval "$( awk '{ 264290693Sdteske gsub(/load_rc_config /, "print_name ") 265290693Sdteske gsub(/run_rc_command /, ": ") 266290693Sdteske print 267290693Sdteske }' "$__spath" )" 268290693Sdteske ) ;; 269290693Sdteske *) 270290693Sdteske __names="$__sname" 271290693Sdteske esac 272290693Sdteske 273290693Sdteske local __name __test_path __configs= 274290693Sdteske for __name in $__names; do 275290693Sdteske for __dir in /etc/rc.d $__local_startup; do 276290693Sdteske __test_path="${__dir%/rc.d}/rc.conf.d/$__name" 277290693Sdteske [ -d "$__test_path" ] || 278290693Sdteske __configs="$__configs $__test_path" continue 279290693Sdteske for __test_path in "$__test_path"/*; do 280290693Sdteske [ -f "$__test_path" ] || continue 281290693Sdteske __configs="$__configs $__test_path" 282290693Sdteske done 283290693Sdteske done 284290693Sdteske done 285290693Sdteske __configs="${__configs# }" 286290693Sdteske 287290693Sdteske if [ "$__var_to_set" ]; then 288290693Sdteske local __cur= 289290693Sdteske [ "$__append" -o "$__prepend" ] && 290290693Sdteske f_getvar "$__var_to_set" __cur 291290693Sdteske [ "$__append" ] && __configs="$__cur{$__cur:+ }$__configs" 292290693Sdteske [ "$__prepend" ] && __configs="$__configs${__cur:+ }$__cur" 293290693Sdteske setvar "$__var_to_set" "$__configs" 294290693Sdteske else 295290693Sdteske echo "$__configs" 296290693Sdteske fi 297290693Sdteske 298290693Sdteske return $SUCCESS 299290693Sdteske} 300290693Sdteske 301238438Sdteske# f_sysrc_get_default $varname 302238438Sdteske# 303238438Sdteske# Get a system configuration default setting from the default rc.conf(5) file 304238438Sdteske# (or whatever RC_DEFAULTS points at). 305238438Sdteske# 306238438Sdteskef_sysrc_get_default() 307238438Sdteske{ 308238438Sdteske # Sanity check 309238438Sdteske [ -f "$RC_DEFAULTS" -a -r "$RC_DEFAULTS" ] || return $FAILURE 310238438Sdteske 311238438Sdteske # Taint-check variable name 312238438Sdteske case "$1" in 313238438Sdteske [0-9]*) 314238438Sdteske # Don't expand possible positional parameters 315252178Sdteske return $FAILURE ;; 316238438Sdteske *) 317238438Sdteske [ "$1" ] || return $FAILURE 318238438Sdteske esac 319238438Sdteske 320238438Sdteske ( # Execute within sub-shell to protect parent environment 321238438Sdteske 322238438Sdteske # 323238438Sdteske # Clear the environment of all variables, preventing the 324238438Sdteske # expansion of normals such as `PS1', `TERM', etc. 325238438Sdteske # 326238438Sdteske f_clean_env --except RC_DEFAULTS 327238438Sdteske 328240783Sdteske . "$RC_DEFAULTS" > /dev/null 2>&1 329238438Sdteske 330238438Sdteske unset RC_DEFAULTS 331238438Sdteske # no longer needed 332238438Sdteske 333238438Sdteske # 334238438Sdteske # This must be the last functional line for both the sub-shell 335238438Sdteske # and the function to preserve the return status from formats 336238438Sdteske # such as "${varname?}" and "${varname:?}" (see "Parameter 337238438Sdteske # Expansion" in sh(1) for more information). 338238438Sdteske # 339240783Sdteske eval echo '"${'"$1"'}"' 2> /dev/null 340238438Sdteske ) 341238438Sdteske} 342238438Sdteske 343238438Sdteske# f_sysrc_find $varname 344238438Sdteske# 345238438Sdteske# Find which file holds the effective last-assignment to a given variable 346238438Sdteske# within the rc.conf(5) file(s). 347238438Sdteske# 348238438Sdteske# If the variable is found in any of the rc.conf(5) files, the function prints 349238438Sdteske# the filename it was found in and then returns success. Otherwise output is 350238438Sdteske# NULL and the function returns with error status. 351238438Sdteske# 352238438Sdteskef_sysrc_find() 353238438Sdteske{ 354241019Sdteske local varname="${1%%[!$VALID_VARNAME_CHARS]*}" 355238438Sdteske local regex="^[[:space:]]*$varname=" 356238438Sdteske local rc_conf_files="$( f_sysrc_get rc_conf_files )" 357238438Sdteske local conf_files= 358238438Sdteske local file 359238438Sdteske 360238438Sdteske # Check parameters 361241019Sdteske case "$varname" in 362241019Sdteske ""|[0-9]*) return $FAILURE 363241019Sdteske esac 364238438Sdteske 365238438Sdteske # 366238438Sdteske # If RC_CONFS is defined, set $rc_conf_files to an explicit 367238438Sdteske # value, modifying the default behavior of source_rc_confs(). 368238438Sdteske # 369240863Sdteske [ "${RC_CONFS+set}" ] && rc_conf_files="$RC_CONFS" 370238438Sdteske 371238438Sdteske # 372238438Sdteske # Reverse the order of files in rc_conf_files (the boot process sources 373238438Sdteske # these in order, so we will search them in reverse-order to find the 374238438Sdteske # last-assignment -- the one that ultimately effects the environment). 375238438Sdteske # 376238438Sdteske for file in $rc_conf_files; do 377238438Sdteske conf_files="$file${conf_files:+ }$conf_files" 378238438Sdteske done 379238438Sdteske 380238438Sdteske # 381238438Sdteske # Append the defaults file (since directives in the defaults file 382238438Sdteske # indeed affect the boot process, we'll want to know when a directive 383238438Sdteske # is found there). 384238438Sdteske # 385238438Sdteske conf_files="$conf_files${conf_files:+ }$RC_DEFAULTS" 386238438Sdteske 387238438Sdteske # 388238438Sdteske # Find which file matches assignment to the given variable name. 389238438Sdteske # 390238438Sdteske for file in $conf_files; do 391238438Sdteske [ -f "$file" -a -r "$file" ] || continue 392238438Sdteske if grep -Eq "$regex" $file; then 393238438Sdteske echo $file 394238438Sdteske return $SUCCESS 395238438Sdteske fi 396238438Sdteske done 397238438Sdteske 398238438Sdteske return $FAILURE # Not found 399238438Sdteske} 400238438Sdteske 401238438Sdteske# f_sysrc_desc $varname 402238438Sdteske# 403238438Sdteske# Attempts to return the comments associated with varname from the rc.conf(5) 404238438Sdteske# defaults file `/etc/defaults/rc.conf' (or whatever RC_DEFAULTS points to). 405238438Sdteske# 406238438Sdteske# Multi-line comments are joined together. Results are NULL if no description 407238438Sdteske# could be found. 408238438Sdteske# 409238438Sdteske# This function is a two-parter. Below is the awk(1) portion of the function, 410238438Sdteske# afterward is the sh(1) function which utilizes the below awk script. 411238438Sdteske# 412238438Sdteskef_sysrc_desc_awk=' 413238438Sdteske# Variables that should be defined on the invocation line: 414238438Sdteske# -v varname="varname" 415238438Sdteske# 416238438SdteskeBEGIN { 417238438Sdteske regex = "^[[:space:]]*"varname"=" 418238438Sdteske found = 0 419238438Sdteske buffer = "" 420238438Sdteske} 421238438Sdteske{ 422238438Sdteske if ( ! found ) 423238438Sdteske { 424238438Sdteske if ( ! match($0, regex) ) next 425238438Sdteske 426238438Sdteske found = 1 427238438Sdteske sub(/^[^#]*(#[[:space:]]*)?/, "") 428238438Sdteske buffer = $0 429238438Sdteske next 430238438Sdteske } 431238438Sdteske 432238438Sdteske if ( !/^[[:space:]]*#/ || 433238438Sdteske /^[[:space:]]*[[:alpha:]_][[:alnum:]_]*=/ || 434238438Sdteske /^[[:space:]]*#[[:alpha:]_][[:alnum:]_]*=/ || 435238438Sdteske /^[[:space:]]*$/ ) exit 436238438Sdteske 437238438Sdteske sub(/(.*#)*[[:space:]]*/, "") 438238438Sdteske buffer = buffer" "$0 439238438Sdteske} 440238438SdteskeEND { 441238438Sdteske # Clean up the buffer 442238438Sdteske sub(/^[[:space:]]*/, "", buffer) 443238438Sdteske sub(/[[:space:]]*$/, "", buffer) 444238438Sdteske 445238438Sdteske print buffer 446238438Sdteske exit ! found 447238438Sdteske} 448238438Sdteske' 449238438Sdteskef_sysrc_desc() 450238438Sdteske{ 451238438Sdteske awk -v varname="$1" "$f_sysrc_desc_awk" < "$RC_DEFAULTS" 452238438Sdteske} 453238438Sdteske 454238438Sdteske# f_sysrc_set $varname $new_value 455238438Sdteske# 456238438Sdteske# Change a setting in the system configuration files (edits the files in-place 457238438Sdteske# to change the value in the last assignment to the variable). If the variable 458238438Sdteske# does not appear in the source file, it is appended to the end of the primary 459238438Sdteske# system configuration file `/etc/rc.conf'. 460238438Sdteske# 461238438Sdteske# This function is a two-parter. Below is the awk(1) portion of the function, 462238438Sdteske# afterward is the sh(1) function which utilizes the below awk script. 463238438Sdteske# 464238438Sdteskef_sysrc_set_awk=' 465238438Sdteske# Variables that should be defined on the invocation line: 466238438Sdteske# -v varname="varname" 467238438Sdteske# -v new_value="new_value" 468238438Sdteske# 469238438SdteskeBEGIN { 470238438Sdteske regex = "^[[:space:]]*"varname"=" 471238438Sdteske found = retval = 0 472238438Sdteske} 473238438Sdteske{ 474238438Sdteske # If already found... just spew 475238438Sdteske if ( found ) { print; next } 476238438Sdteske 477238438Sdteske # Does this line match an assignment to our variable? 478238438Sdteske if ( ! match($0, regex) ) { print; next } 479238438Sdteske 480238438Sdteske # Save important match information 481238438Sdteske found = 1 482238438Sdteske matchlen = RSTART + RLENGTH - 1 483238438Sdteske 484238438Sdteske # Store the value text for later munging 485238438Sdteske value = substr($0, matchlen + 1, length($0) - matchlen) 486238438Sdteske 487238438Sdteske # Store the first character of the value 488238438Sdteske t1 = t2 = substr(value, 0, 1) 489238438Sdteske 490238438Sdteske # Assignment w/ back-ticks, expression, or misc. 491238438Sdteske # We ignore these since we did not generate them 492238438Sdteske # 493238438Sdteske if ( t1 ~ /[`$\\]/ ) { retval = 1; print; next } 494238438Sdteske 495238438Sdteske # Assignment w/ single-quoted value 496238438Sdteske else if ( t1 == "'\''" ) { 497238438Sdteske sub(/^'\''[^'\'']*/, "", value) 498238438Sdteske if ( length(value) == 0 ) t2 = "" 499238438Sdteske sub(/^'\''/, "", value) 500238438Sdteske } 501238438Sdteske 502238438Sdteske # Assignment w/ double-quoted value 503238438Sdteske else if ( t1 == "\"" ) { 504238438Sdteske sub(/^"(.*\\\\+")*[^"]*/, "", value) 505238438Sdteske if ( length(value) == 0 ) t2 = "" 506238438Sdteske sub(/^"/, "", value) 507238438Sdteske } 508238438Sdteske 509238438Sdteske # Assignment w/ non-quoted value 510238438Sdteske else if ( t1 ~ /[^[:space:];]/ ) { 511238438Sdteske t1 = t2 = "\"" 512238438Sdteske sub(/^[^[:space:]]*/, "", value) 513238438Sdteske } 514238438Sdteske 515238438Sdteske # Null-assignment 516238438Sdteske else if ( t1 ~ /[[:space:];]/ ) { t1 = t2 = "\"" } 517238438Sdteske 518238438Sdteske printf "%s%c%s%c%s\n", substr($0, 0, matchlen), \ 519238438Sdteske t1, new_value, t2, value 520238438Sdteske} 521238438SdteskeEND { exit retval } 522238438Sdteske' 523238438Sdteskef_sysrc_set() 524238438Sdteske{ 525259054Sdteske local funcname=f_sysrc_set 526238438Sdteske local varname="$1" new_value="$2" 527238438Sdteske 528238438Sdteske # Check arguments 529238438Sdteske [ "$varname" ] || return $FAILURE 530238438Sdteske 531238438Sdteske # 532238438Sdteske # Find which rc.conf(5) file contains the last-assignment 533238438Sdteske # 534238438Sdteske local not_found= 535238438Sdteske local file="$( f_sysrc_find "$varname" )" 536238438Sdteske if [ "$file" = "$RC_DEFAULTS" -o ! "$file" ]; then 537238438Sdteske # 538238438Sdteske # We either got a null response (not found) or the variable 539238438Sdteske # was only found in the rc.conf(5) defaults. In either case, 540238438Sdteske # let's instead modify the first file from $rc_conf_files. 541238438Sdteske # 542238438Sdteske 543238438Sdteske not_found=1 544238438Sdteske 545238438Sdteske # 546238438Sdteske # If RC_CONFS is defined, use $RC_CONFS 547238438Sdteske # rather than $rc_conf_files. 548238438Sdteske # 549240863Sdteske if [ "${RC_CONFS+set}" ]; then 550238438Sdteske file="${RC_CONFS%%[$IFS]*}" 551238438Sdteske else 552241042Sdteske file=$( f_sysrc_get 'rc_conf_files%%[$IFS]*' ) 553238438Sdteske fi 554238438Sdteske fi 555238438Sdteske 556238438Sdteske # 557238438Sdteske # If not found, append new value to last file and return. 558238438Sdteske # 559238438Sdteske if [ "$not_found" ]; then 560238438Sdteske echo "$varname=\"$new_value\"" >> "$file" 561238438Sdteske return $? 562238438Sdteske fi 563238438Sdteske 564238438Sdteske # 565238438Sdteske # Perform sanity checks. 566238438Sdteske # 567238438Sdteske if [ ! -w "$file" ]; then 568238438Sdteske f_err "$msg_cannot_create_permission_denied\n" \ 569238438Sdteske "$pgm" "$file" 570238438Sdteske return $FAILURE 571238438Sdteske fi 572238438Sdteske 573238438Sdteske # 574238438Sdteske # Create a new temporary file to write to. 575238438Sdteske # 576259054Sdteske local tmpfile 577259054Sdteske if ! f_eval_catch -dk tmpfile $funcname mktemp 'mktemp -t "%s"' "$pgm" 578259054Sdteske then 579259054Sdteske echo "$tmpfile" >&2 580259054Sdteske return $FAILURE 581259054Sdteske fi 582238438Sdteske 583238438Sdteske # 584238438Sdteske # Fixup permissions (else we're in for a surprise, as mktemp(1) creates 585238438Sdteske # the temporary file with 0600 permissions, and if we simply mv(1) the 586238438Sdteske # temporary file over the destination, the destination will inherit the 587238438Sdteske # permissions from the temporary file). 588238438Sdteske # 589238438Sdteske local mode 590259054Sdteske f_eval_catch -dk mode $funcname stat 'stat -f "%%#Lp" "%s"' "$file" || 591259054Sdteske mode=0644 592259054Sdteske f_eval_catch -d $funcname chmod 'chmod "%s" "%s"' "$mode" "$tmpfile" 593238438Sdteske 594238438Sdteske # 595238438Sdteske # Fixup ownership. The destination file _is_ writable (we tested 596238438Sdteske # earlier above). However, this will fail if we don't have sufficient 597238438Sdteske # permissions (so we throw stderr into the bit-bucket). 598238438Sdteske # 599238438Sdteske local owner 600259054Sdteske f_eval_catch -dk owner $funcname stat \ 601259054Sdteske 'stat -f "%%u:%%g" "%s"' "$file" || owner="root:wheel" 602259054Sdteske f_eval_catch -d $funcname chown 'chown "%s" "%s"' "$owner" "$tmpfile" 603238438Sdteske 604238438Sdteske # 605238438Sdteske # Operate on the matching file, replacing only the last occurrence. 606238438Sdteske # 607238438Sdteske local new_contents retval 608240783Sdteske new_contents=$( tail -r $file 2> /dev/null ) 609238438Sdteske new_contents=$( echo "$new_contents" | awk -v varname="$varname" \ 610238438Sdteske -v new_value="$new_value" "$f_sysrc_set_awk" ) 611238438Sdteske retval=$? 612238438Sdteske 613238438Sdteske # 614238438Sdteske # Write the temporary file contents. 615238438Sdteske # 616238438Sdteske echo "$new_contents" | tail -r > "$tmpfile" || return $FAILURE 617238438Sdteske if [ $retval -ne $SUCCESS ]; then 618238438Sdteske echo "$varname=\"$new_value\"" >> "$tmpfile" 619238438Sdteske fi 620238438Sdteske 621238438Sdteske # 622238438Sdteske # Taint-check our results. 623238438Sdteske # 624259054Sdteske if ! f_eval_catch -d $funcname sh '/bin/sh -n "%s"' "$tmpfile"; then 625238438Sdteske f_err "$msg_previous_syntax_errors\n" "$pgm" "$file" 626238438Sdteske rm -f "$tmpfile" 627238438Sdteske return $FAILURE 628238438Sdteske fi 629238438Sdteske 630238438Sdteske # 631238438Sdteske # Finally, move the temporary file into place. 632238438Sdteske # 633259054Sdteske f_eval_catch -de $funcname mv 'mv "%s" "%s"' "$tmpfile" "$file" 634238438Sdteske} 635238438Sdteske 636238438Sdteske# f_sysrc_delete $varname 637238438Sdteske# 638238438Sdteske# Remove a setting from the system configuration files (edits files in-place). 639238438Sdteske# Deletes all assignments to the given variable in all config files. If the 640238438Sdteske# `-f file' option is passed, the removal is restricted to only those files 641238438Sdteske# specified, otherwise the system collection of rc_conf_files is used. 642238438Sdteske# 643238438Sdteske# This function is a two-parter. Below is the awk(1) portion of the function, 644238438Sdteske# afterward is the sh(1) function which utilizes the below awk script. 645238438Sdteske# 646238438Sdteskef_sysrc_delete_awk=' 647238438Sdteske# Variables that should be defined on the invocation line: 648238438Sdteske# -v varname="varname" 649238438Sdteske# 650238438SdteskeBEGIN { 651238438Sdteske regex = "^[[:space:]]*"varname"=" 652238438Sdteske found = 0 653238438Sdteske} 654238438Sdteske{ 655238438Sdteske if ( $0 ~ regex ) 656238438Sdteske found = 1 657238438Sdteske else 658238438Sdteske print 659238438Sdteske} 660238438SdteskeEND { exit ! found } 661238438Sdteske' 662238438Sdteskef_sysrc_delete() 663238438Sdteske{ 664259054Sdteske local funcname=f_sysrc_delete 665238438Sdteske local varname="$1" 666238438Sdteske local file 667238438Sdteske 668238438Sdteske # Check arguments 669238438Sdteske [ "$varname" ] || return $FAILURE 670238438Sdteske 671238438Sdteske # 672238438Sdteske # Operate on each of the specified files 673238438Sdteske # 674259054Sdteske local tmpfile 675240863Sdteske for file in ${RC_CONFS-$( f_sysrc_get rc_conf_files )}; do 676238438Sdteske [ -e "$file" ] || continue 677238438Sdteske 678238438Sdteske # 679238438Sdteske # Create a new temporary file to write to. 680238438Sdteske # 681259054Sdteske if ! f_eval_catch -dk tmpfile $funcname mktemp \ 682259054Sdteske 'mktemp -t "%s"' "$pgm" 683259054Sdteske then 684259054Sdteske echo "$tmpfile" >&2 685259054Sdteske return $FAILURE 686259054Sdteske fi 687238438Sdteske 688238438Sdteske # 689238438Sdteske # Fixup permissions and ownership (mktemp(1) defaults to 0600 690238438Sdteske # permissions) to instead match the destination file. 691238438Sdteske # 692238438Sdteske local mode owner 693259054Sdteske f_eval_catch -dk mode $funcname stat \ 694259054Sdteske 'stat -f "%%#Lp" "%s"' "$file" || mode=0644 695259054Sdteske f_eval_catch -dk owner $funcname stat \ 696259054Sdteske 'stat -f "%%u:%%g" "%s"' "$file" || owner="root:wheel" 697259054Sdteske f_eval_catch -d $funcname chmod \ 698259054Sdteske 'chmod "%s" "%s"' "$mode" "$tmpfile" 699259054Sdteske f_eval_catch -d $funcname chown \ 700259054Sdteske 'chown "%s" "%s"' "$owner" "$tmpfile" 701238438Sdteske 702238438Sdteske # 703238438Sdteske # Operate on the file, removing all occurrences, saving the 704238438Sdteske # output in our temporary file. 705238438Sdteske # 706238438Sdteske awk -v varname="$varname" "$f_sysrc_delete_awk" "$file" \ 707238438Sdteske > "$tmpfile" 708238438Sdteske if [ $? -ne $SUCCESS ]; then 709238438Sdteske # The file didn't contain any assignments 710238438Sdteske rm -f "$tmpfile" 711238438Sdteske continue 712238438Sdteske fi 713238438Sdteske 714238438Sdteske # 715238438Sdteske # Taint-check our results. 716238438Sdteske # 717259054Sdteske if ! f_eval_catch -d $funcname sh '/bin/sh -n "%s"' "$tmpfile" 718259054Sdteske then 719238438Sdteske f_err "$msg_previous_syntax_errors\n" \ 720238438Sdteske "$pgm" "$file" 721238438Sdteske rm -f "$tmpfile" 722238438Sdteske return $FAILURE 723238438Sdteske fi 724238438Sdteske 725238438Sdteske # 726238438Sdteske # Perform sanity checks 727238438Sdteske # 728238438Sdteske if [ ! -w "$file" ]; then 729238438Sdteske f_err "$msg_permission_denied\n" "$pgm" "$file" 730238438Sdteske rm -f "$tmpfile" 731238438Sdteske return $FAILURE 732238438Sdteske fi 733238438Sdteske 734238438Sdteske # 735238438Sdteske # Finally, move the temporary file into place. 736238438Sdteske # 737259054Sdteske f_eval_catch -de $funcname mv \ 738259054Sdteske 'mv "%s" "%s"' "$tmpfile" "$file" || return $FAILURE 739238438Sdteske done 740238438Sdteske} 741238438Sdteske 742244675Sdteske############################################################ MAIN 743244675Sdteske 744244675Sdteskef_dprintf "%s: Successfully loaded." sysrc.subr 745244675Sdteske 746238438Sdteskefi # ! $_SYSRC_SUBR 747