1ab2043b8SDevin Teskeif [ ! "$_SYSRC_SUBR" ]; then _SYSRC_SUBR=1 2ab2043b8SDevin Teske# 3bfe64a81SDevin Teske# Copyright (c) 2006-2015 Devin Teske 4dfe61b44SDevin Teske# All rights reserved. 5ab2043b8SDevin Teske# 6ab2043b8SDevin Teske# Redistribution and use in source and binary forms, with or without 7ab2043b8SDevin Teske# modification, are permitted provided that the following conditions 8ab2043b8SDevin Teske# are met: 9ab2043b8SDevin Teske# 1. Redistributions of source code must retain the above copyright 10ab2043b8SDevin Teske# notice, this list of conditions and the following disclaimer. 11ab2043b8SDevin Teske# 2. Redistributions in binary form must reproduce the above copyright 12ab2043b8SDevin Teske# notice, this list of conditions and the following disclaimer in the 13ab2043b8SDevin Teske# documentation and/or other materials provided with the distribution. 14ab2043b8SDevin Teske# 15ab2043b8SDevin Teske# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 168e37a7c8SDevin Teske# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17ab2043b8SDevin Teske# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18ab2043b8SDevin Teske# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19ab2043b8SDevin Teske# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 202d49f165SDevin Teske# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21ab2043b8SDevin Teske# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22ab2043b8SDevin Teske# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23ab2043b8SDevin Teske# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24ab2043b8SDevin Teske# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25ab2043b8SDevin Teske# SUCH DAMAGE. 26ab2043b8SDevin Teske# 27ab2043b8SDevin Teske# 28ab2043b8SDevin Teske############################################################ INCLUDES 29ab2043b8SDevin Teske 30ab2043b8SDevin TeskeBSDCFG_SHARE="/usr/share/bsdconfig" 312a357efaSDevin Teske[ "$_COMMON_SUBR" ] || . $BSDCFG_SHARE/common.subr || exit 1 32ab2043b8SDevin Teske 33ab2043b8SDevin TeskeBSDCFG_LIBE="/usr/libexec/bsdconfig" 3456961fd7SDevin Teskeif [ ! "$_SYSRC_JAILED" ]; then 3556961fd7SDevin Teske f_dprintf "%s: loading includes..." sysrc.subr 3656961fd7SDevin Teske f_include_lang $BSDCFG_LIBE/include/messages.subr 3756961fd7SDevin Teskefi 38ab2043b8SDevin Teske 39ab2043b8SDevin Teske############################################################ CONFIGURATION 40ab2043b8SDevin Teske 41ab2043b8SDevin Teske# 42ab2043b8SDevin Teske# Standard pathnames (inherit values from shell if available) 43ab2043b8SDevin Teske# 44ab2043b8SDevin Teske: ${RC_DEFAULTS:="/etc/defaults/rc.conf"} 45ab2043b8SDevin Teske 46ab2043b8SDevin Teske############################################################ GLOBALS 47ab2043b8SDevin Teske 48ab2043b8SDevin Teske# 49ab2043b8SDevin Teske# Global exit status variables 50ab2043b8SDevin Teske# 51ab2043b8SDevin TeskeSUCCESS=0 52ab2043b8SDevin TeskeFAILURE=1 53ab2043b8SDevin Teske 549b0f0cc5SDevin Teske# 559b0f0cc5SDevin Teske# Valid characters that can appear in an sh(1) variable name 569b0f0cc5SDevin Teske# 579b0f0cc5SDevin Teske# Please note that the character ranges A-Z and a-z should be avoided because 589b0f0cc5SDevin Teske# these can include accent characters (which are not valid in a variable name). 599b0f0cc5SDevin Teske# For example, A-Z matches any character that sorts after A but before Z, 609b0f0cc5SDevin Teske# including A and Z. Although ASCII order would make more sense, that is not 619b0f0cc5SDevin Teske# how it works. 629b0f0cc5SDevin Teske# 639b0f0cc5SDevin TeskeVALID_VARNAME_CHARS="0-9ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_" 649b0f0cc5SDevin Teske 65ab2043b8SDevin Teske############################################################ FUNCTIONS 66ab2043b8SDevin Teske 67ab2043b8SDevin Teske# f_clean_env [ --except $varname ... ] 68ab2043b8SDevin Teske# 69ab2043b8SDevin Teske# Unset all environment variables in the current scope. An optional list of 70ab2043b8SDevin Teske# arguments can be passed, indicating which variables to avoid unsetting; the 71ab2043b8SDevin Teske# `--except' is required to enable the exclusion-list as the remainder of 72ab2043b8SDevin Teske# positional arguments. 73ab2043b8SDevin Teske# 74ab2043b8SDevin Teske# Be careful not to call this in a shell that you still expect to perform 75ab2043b8SDevin Teske# $PATH expansion in, because this will blow $PATH away. This is best used 76ab2043b8SDevin Teske# within a sub-shell block "(...)" or "$(...)" or "`...`". 77ab2043b8SDevin Teske# 78ab2043b8SDevin Teskef_clean_env() 79ab2043b8SDevin Teske{ 80ab2043b8SDevin Teske local var arg except= 81ab2043b8SDevin Teske 82ab2043b8SDevin Teske # 83ab2043b8SDevin Teske # Should we process an exclusion-list? 84ab2043b8SDevin Teske # 85ab2043b8SDevin Teske if [ "$1" = "--except" ]; then 86ab2043b8SDevin Teske except=1 87ab2043b8SDevin Teske shift 1 88ab2043b8SDevin Teske fi 89ab2043b8SDevin Teske 90ab2043b8SDevin Teske # 91ab2043b8SDevin Teske # Loop over a list of variable names from set(1) built-in. 92ab2043b8SDevin Teske # 93ab2043b8SDevin Teske for var in $( set | awk -F= \ 94ab2043b8SDevin Teske '/^[[:alpha:]_][[:alnum:]_]*=/ {print $1}' \ 95ab2043b8SDevin Teske | grep -v '^except$' 96ab2043b8SDevin Teske ); do 97ab2043b8SDevin Teske # 98ab2043b8SDevin Teske # In POSIX bourne-shell, attempting to unset(1) OPTIND results 99ab2043b8SDevin Teske # in "unset: Illegal number:" and causes abrupt termination. 100ab2043b8SDevin Teske # 101ab2043b8SDevin Teske [ "$var" = OPTIND ] && continue 102ab2043b8SDevin Teske 103ab2043b8SDevin Teske # 104ab2043b8SDevin Teske # Process the exclusion-list? 105ab2043b8SDevin Teske # 106ab2043b8SDevin Teske if [ "$except" ]; then 107ab2043b8SDevin Teske for arg in "$@" ""; do 108ab2043b8SDevin Teske [ "$var" = "$arg" ] && break 109ab2043b8SDevin Teske done 110ab2043b8SDevin Teske [ "$arg" ] && continue 111ab2043b8SDevin Teske fi 112ab2043b8SDevin Teske 113ab2043b8SDevin Teske unset "$var" 114ab2043b8SDevin Teske done 115ab2043b8SDevin Teske} 116ab2043b8SDevin Teske 117ab2043b8SDevin Teske# f_sysrc_get $varname 118ab2043b8SDevin Teske# 119ab2043b8SDevin Teske# Get a system configuration setting from the collection of system- 120b2b4a04eSDevin Teske# configuration files (in order: /etc/defaults/rc.conf /etc/rc.conf and 121b2b4a04eSDevin Teske# /etc/rc.conf.local) 122ab2043b8SDevin Teske# 123ab2043b8SDevin Teske# NOTE: Additional shell parameter-expansion formats are supported. For 124ab2043b8SDevin Teske# example, passing an argument of "hostname%%.*" (properly quoted) will 125ab2043b8SDevin Teske# return the hostname up to (but not including) the first `.' (see sh(1), 126ab2043b8SDevin Teske# "Parameter Expansion" for more information on additional formats). 127ab2043b8SDevin Teske# 128ab2043b8SDevin Teskef_sysrc_get() 129ab2043b8SDevin Teske{ 130ab2043b8SDevin Teske # Sanity check 131ab2043b8SDevin Teske [ -f "$RC_DEFAULTS" -a -r "$RC_DEFAULTS" ] || return $FAILURE 132ab2043b8SDevin Teske 133ab2043b8SDevin Teske # Taint-check variable name 134ab2043b8SDevin Teske case "$1" in 135ab2043b8SDevin Teske [0-9]*) 136ab2043b8SDevin Teske # Don't expand possible positional parameters 137ab2043b8SDevin Teske return $FAILURE ;; 138ab2043b8SDevin Teske *) 139ab2043b8SDevin Teske [ "$1" ] || return $FAILURE 140ab2043b8SDevin Teske esac 141ab2043b8SDevin Teske 142ab2043b8SDevin Teske ( # Execute within sub-shell to protect parent environment 143ab2043b8SDevin Teske 144ab2043b8SDevin Teske # 145ab2043b8SDevin Teske # Clear the environment of all variables, preventing the 146ab2043b8SDevin Teske # expansion of normals such as `PS1', `TERM', etc. 147ab2043b8SDevin Teske # 1481f843bc0SDevin Teske f_clean_env --except IFS RC_CONFS RC_DEFAULTS 149ab2043b8SDevin Teske 150fb7d723eSDevin Teske . "$RC_DEFAULTS" > /dev/null 2>&1 151ab2043b8SDevin Teske 152ab2043b8SDevin Teske unset RC_DEFAULTS 153ab2043b8SDevin Teske # no longer needed 154ab2043b8SDevin Teske 155ab2043b8SDevin Teske # 156ab2043b8SDevin Teske # If the query is for `rc_conf_files' then store the value that 157ab2043b8SDevin Teske # we inherited from sourcing RC_DEFAULTS (above) so that we may 158ab2043b8SDevin Teske # conditionally restore this value after source_rc_confs in the 159ab2043b8SDevin Teske # event that RC_CONFS does not customize the value. 160ab2043b8SDevin Teske # 161ab2043b8SDevin Teske if [ "$1" = "rc_conf_files" ]; then 162ab2043b8SDevin Teske _rc_conf_files="$rc_conf_files" 163ab2043b8SDevin Teske fi 164ab2043b8SDevin Teske 165ab2043b8SDevin Teske # 166ab2043b8SDevin Teske # If RC_CONFS is defined, set $rc_conf_files to an explicit 167ab2043b8SDevin Teske # value, modifying the default behavior of source_rc_confs(). 168ab2043b8SDevin Teske # 1698d8d314dSDevin Teske if [ "${RC_CONFS+set}" ]; then 170ab2043b8SDevin Teske rc_conf_files="$RC_CONFS" 171ab2043b8SDevin Teske _rc_confs_set=1 172ab2043b8SDevin Teske fi 173ab2043b8SDevin Teske 174fb7d723eSDevin Teske source_rc_confs > /dev/null 2>&1 175ab2043b8SDevin Teske 176ab2043b8SDevin Teske # 177ab2043b8SDevin Teske # If the query was for `rc_conf_files' AND after calling 1782d49f165SDevin Teske # source_rc_confs the value has not changed, then we should 179ab2043b8SDevin Teske # restore the value to the one inherited from RC_DEFAULTS 180ab2043b8SDevin Teske # before performing the final query (preventing us from 181ab2043b8SDevin Teske # returning what was set via RC_CONFS when the intent was 182ab2043b8SDevin Teske # instead to query the value from the file(s) specified). 183ab2043b8SDevin Teske # 184ab2043b8SDevin Teske if [ "$1" = "rc_conf_files" -a \ 185ab2043b8SDevin Teske "$_rc_confs_set" -a \ 186ab2043b8SDevin Teske "$rc_conf_files" = "$RC_CONFS" \ 187ab2043b8SDevin Teske ]; then 188ab2043b8SDevin Teske rc_conf_files="$_rc_conf_files" 189ab2043b8SDevin Teske unset _rc_conf_files 190ab2043b8SDevin Teske unset _rc_confs_set 191ab2043b8SDevin Teske fi 192ab2043b8SDevin Teske 193ab2043b8SDevin Teske unset RC_CONFS 194ab2043b8SDevin Teske # no longer needed 195ab2043b8SDevin Teske 196ab2043b8SDevin Teske # 197ab2043b8SDevin Teske # This must be the last functional line for both the sub-shell 198ab2043b8SDevin Teske # and the function to preserve the return status from formats 199ab2043b8SDevin Teske # such as "${varname?}" and "${varname:?}" (see "Parameter 200ab2043b8SDevin Teske # Expansion" in sh(1) for more information). 201ab2043b8SDevin Teske # 2025164504aSDevin Teske eval printf "'%s\\n'" '"${'"$1"'}"' 2> /dev/null 203ab2043b8SDevin Teske ) 204ab2043b8SDevin Teske} 205ab2043b8SDevin Teske 206bfe64a81SDevin Teske# f_sysrc_service_configs [-a|-p] $name [$var_to_set] 207bfe64a81SDevin Teske# 208bfe64a81SDevin Teske# Get a list of optional `rc.conf.d' entries sourced by system `rc.d' script 209bfe64a81SDevin Teske# $name (see rc.subr(8) for additional information on `rc.conf.d'). If $name 210bfe64a81SDevin Teske# exists in `/etc/rc.d' or $local_startup directories and is an rc(8) script 211bfe64a81SDevin Teske# the result is a space separated list of `rc.conf.d' entries sourced by the 212bfe64a81SDevin Teske# $name `rc.d' script. Otherwise, if $name exists as a binary `rc.d' script, 213bfe64a81SDevin Teske# the result is ``/etc/rc.conf.d/$name /usr/local/etc/rc.conf.d/$name''. The 214bfe64a81SDevin Teske# result is NULL if $name does not exist. 215bfe64a81SDevin Teske# 216bfe64a81SDevin Teske# If $var_to_set is missing or NULL, output is to standard out. Returns success 217bfe64a81SDevin Teske# if $name was found, failure otherwise. 218bfe64a81SDevin Teske# 219bfe64a81SDevin Teske# If `-a' flag is given and $var_to_set is non-NULL, append result to value of 220bfe64a81SDevin Teske# $var_to_set rather than overwriting current contents. 221bfe64a81SDevin Teske# 222bfe64a81SDevin Teske# If `-p' flag is given and $var_to_set is non-NULL, prepend result to value of 223bfe64a81SDevin Teske# $var_to_set rather than overwriting current contents. 224bfe64a81SDevin Teske# 225bfe64a81SDevin Teske# NB: The `-a' and `-p' option flags are mutually exclusive. 226bfe64a81SDevin Teske# 227bfe64a81SDevin Teskef_sysrc_service_configs() 228bfe64a81SDevin Teske{ 229bfe64a81SDevin Teske local OPTIND=1 OPTARG __flag __append= __prepend= 230bfe64a81SDevin Teske local __local_startup __dir __spath __stype __names= 231bfe64a81SDevin Teske 232bfe64a81SDevin Teske while getopts ap __flag; do 233bfe64a81SDevin Teske case "$__flag" in 234bfe64a81SDevin Teske a) __append=1 __prepend= ;; 235bfe64a81SDevin Teske p) __prepend=1 __append= ;; 236bfe64a81SDevin Teske esac 237bfe64a81SDevin Teske done 238bfe64a81SDevin Teske shift $(( $OPTIND - 1 )) 239bfe64a81SDevin Teske 240bfe64a81SDevin Teske [ $# -gt 0 ] || return $FAILURE 241bfe64a81SDevin Teske local __sname="$1" __var_to_set="$2" 242bfe64a81SDevin Teske 243bfe64a81SDevin Teske __local_startup=$( f_sysrc_get local_startup ) 244bfe64a81SDevin Teske for __dir in /etc/rc.d $__local_startup; do 245bfe64a81SDevin Teske __spath="$__dir/$__sname" 246bfe64a81SDevin Teske [ -f "$__spath" -a -x "$__spath" ] || __spath= continue 247bfe64a81SDevin Teske break 248bfe64a81SDevin Teske done 249bfe64a81SDevin Teske [ "$__spath" ] || return $FAILURE 250bfe64a81SDevin Teske 251bfe64a81SDevin Teske __stype=$( file -b "$__spath" 2> /dev/null ) 252bfe64a81SDevin Teske case "$__stype" in 253bfe64a81SDevin Teske *"shell script"*) 254bfe64a81SDevin Teske __names=$( exec 9<&1 1>&- 2>&- 255bfe64a81SDevin Teske last_name= 256bfe64a81SDevin Teske print_name() { 257bfe64a81SDevin Teske local name="$1" 258bd8d6400SDevin Teske case "$name" in 259bd8d6400SDevin Teske ""|.|..|*/*|"$last_name") return ;; 260bd8d6400SDevin Teske esac 261bfe64a81SDevin Teske echo "$name" >&9 262bfe64a81SDevin Teske last_name="$name" 263bfe64a81SDevin Teske } 264bfe64a81SDevin Teske eval "$( awk '{ 265bfe64a81SDevin Teske gsub(/load_rc_config /, "print_name ") 266bfe64a81SDevin Teske gsub(/run_rc_command /, ": ") 267bfe64a81SDevin Teske print 268bfe64a81SDevin Teske }' "$__spath" )" 269bfe64a81SDevin Teske ) ;; 270bfe64a81SDevin Teske *) 271bfe64a81SDevin Teske __names="$__sname" 272bfe64a81SDevin Teske esac 273bfe64a81SDevin Teske 274bfe64a81SDevin Teske local __name __test_path __configs= 275bfe64a81SDevin Teske for __name in $__names; do 276bfe64a81SDevin Teske for __dir in /etc/rc.d $__local_startup; do 277bfe64a81SDevin Teske __test_path="${__dir%/rc.d}/rc.conf.d/$__name" 278bfe64a81SDevin Teske [ -d "$__test_path" ] || 279bfe64a81SDevin Teske __configs="$__configs $__test_path" continue 280bfe64a81SDevin Teske for __test_path in "$__test_path"/*; do 281bfe64a81SDevin Teske [ -f "$__test_path" ] || continue 282bfe64a81SDevin Teske __configs="$__configs $__test_path" 283bfe64a81SDevin Teske done 284bfe64a81SDevin Teske done 285bfe64a81SDevin Teske done 286bfe64a81SDevin Teske __configs="${__configs# }" 287bfe64a81SDevin Teske 288bfe64a81SDevin Teske if [ "$__var_to_set" ]; then 289bfe64a81SDevin Teske local __cur= 290bfe64a81SDevin Teske [ "$__append" -o "$__prepend" ] && 291bfe64a81SDevin Teske f_getvar "$__var_to_set" __cur 292bfe64a81SDevin Teske [ "$__append" ] && __configs="$__cur{$__cur:+ }$__configs" 293bfe64a81SDevin Teske [ "$__prepend" ] && __configs="$__configs${__cur:+ }$__cur" 294bfe64a81SDevin Teske setvar "$__var_to_set" "$__configs" 295bfe64a81SDevin Teske else 296bfe64a81SDevin Teske echo "$__configs" 297bfe64a81SDevin Teske fi 298bfe64a81SDevin Teske 299bfe64a81SDevin Teske return $SUCCESS 300bfe64a81SDevin Teske} 301bfe64a81SDevin Teske 302ab2043b8SDevin Teske# f_sysrc_get_default $varname 303ab2043b8SDevin Teske# 304ab2043b8SDevin Teske# Get a system configuration default setting from the default rc.conf(5) file 305ab2043b8SDevin Teske# (or whatever RC_DEFAULTS points at). 306ab2043b8SDevin Teske# 307ab2043b8SDevin Teskef_sysrc_get_default() 308ab2043b8SDevin Teske{ 309ab2043b8SDevin Teske # Sanity check 310ab2043b8SDevin Teske [ -f "$RC_DEFAULTS" -a -r "$RC_DEFAULTS" ] || return $FAILURE 311ab2043b8SDevin Teske 312ab2043b8SDevin Teske # Taint-check variable name 313ab2043b8SDevin Teske case "$1" in 314ab2043b8SDevin Teske [0-9]*) 315ab2043b8SDevin Teske # Don't expand possible positional parameters 316ab2043b8SDevin Teske return $FAILURE ;; 317ab2043b8SDevin Teske *) 318ab2043b8SDevin Teske [ "$1" ] || return $FAILURE 319ab2043b8SDevin Teske esac 320ab2043b8SDevin Teske 321ab2043b8SDevin Teske ( # Execute within sub-shell to protect parent environment 322ab2043b8SDevin Teske 323ab2043b8SDevin Teske # 324ab2043b8SDevin Teske # Clear the environment of all variables, preventing the 325ab2043b8SDevin Teske # expansion of normals such as `PS1', `TERM', etc. 326ab2043b8SDevin Teske # 327ab2043b8SDevin Teske f_clean_env --except RC_DEFAULTS 328ab2043b8SDevin Teske 329fb7d723eSDevin Teske . "$RC_DEFAULTS" > /dev/null 2>&1 330ab2043b8SDevin Teske 331ab2043b8SDevin Teske unset RC_DEFAULTS 332ab2043b8SDevin Teske # no longer needed 333ab2043b8SDevin Teske 334ab2043b8SDevin Teske # 335ab2043b8SDevin Teske # This must be the last functional line for both the sub-shell 336ab2043b8SDevin Teske # and the function to preserve the return status from formats 337ab2043b8SDevin Teske # such as "${varname?}" and "${varname:?}" (see "Parameter 338ab2043b8SDevin Teske # Expansion" in sh(1) for more information). 339ab2043b8SDevin Teske # 3405164504aSDevin Teske eval printf "'%s\\n'" '"${'"$1"'}"' 2> /dev/null 341ab2043b8SDevin Teske ) 342ab2043b8SDevin Teske} 343ab2043b8SDevin Teske 344ab2043b8SDevin Teske# f_sysrc_find $varname 345ab2043b8SDevin Teske# 346ab2043b8SDevin Teske# Find which file holds the effective last-assignment to a given variable 347ab2043b8SDevin Teske# within the rc.conf(5) file(s). 348ab2043b8SDevin Teske# 349ab2043b8SDevin Teske# If the variable is found in any of the rc.conf(5) files, the function prints 350ab2043b8SDevin Teske# the filename it was found in and then returns success. Otherwise output is 351ab2043b8SDevin Teske# NULL and the function returns with error status. 352ab2043b8SDevin Teske# 353ab2043b8SDevin Teskef_sysrc_find() 354ab2043b8SDevin Teske{ 3559b0f0cc5SDevin Teske local varname="${1%%[!$VALID_VARNAME_CHARS]*}" 356ab2043b8SDevin Teske local regex="^[[:space:]]*$varname=" 357ab2043b8SDevin Teske local rc_conf_files="$( f_sysrc_get rc_conf_files )" 358ab2043b8SDevin Teske local conf_files= 359ab2043b8SDevin Teske local file 360ab2043b8SDevin Teske 361ab2043b8SDevin Teske # Check parameters 3629b0f0cc5SDevin Teske case "$varname" in 3639b0f0cc5SDevin Teske ""|[0-9]*) return $FAILURE 3649b0f0cc5SDevin Teske esac 365ab2043b8SDevin Teske 366ab2043b8SDevin Teske # 367ab2043b8SDevin Teske # If RC_CONFS is defined, set $rc_conf_files to an explicit 368ab2043b8SDevin Teske # value, modifying the default behavior of source_rc_confs(). 369ab2043b8SDevin Teske # 3700ad5179dSDevin Teske [ "${RC_CONFS+set}" ] && rc_conf_files="$RC_CONFS" 371ab2043b8SDevin Teske 372ab2043b8SDevin Teske # 373ab2043b8SDevin Teske # Reverse the order of files in rc_conf_files (the boot process sources 374ab2043b8SDevin Teske # these in order, so we will search them in reverse-order to find the 375ab2043b8SDevin Teske # last-assignment -- the one that ultimately effects the environment). 376ab2043b8SDevin Teske # 377ab2043b8SDevin Teske for file in $rc_conf_files; do 378ab2043b8SDevin Teske conf_files="$file${conf_files:+ }$conf_files" 379ab2043b8SDevin Teske done 380ab2043b8SDevin Teske 381ab2043b8SDevin Teske # 382ab2043b8SDevin Teske # Append the defaults file (since directives in the defaults file 383ab2043b8SDevin Teske # indeed affect the boot process, we'll want to know when a directive 384ab2043b8SDevin Teske # is found there). 385ab2043b8SDevin Teske # 386ab2043b8SDevin Teske conf_files="$conf_files${conf_files:+ }$RC_DEFAULTS" 387ab2043b8SDevin Teske 388ab2043b8SDevin Teske # 389ab2043b8SDevin Teske # Find which file matches assignment to the given variable name. 390ab2043b8SDevin Teske # 391ab2043b8SDevin Teske for file in $conf_files; do 392ab2043b8SDevin Teske [ -f "$file" -a -r "$file" ] || continue 393ab2043b8SDevin Teske if grep -Eq "$regex" $file; then 394ab2043b8SDevin Teske echo $file 395ab2043b8SDevin Teske return $SUCCESS 396ab2043b8SDevin Teske fi 397ab2043b8SDevin Teske done 398ab2043b8SDevin Teske 399ab2043b8SDevin Teske return $FAILURE # Not found 400ab2043b8SDevin Teske} 401ab2043b8SDevin Teske 402ab2043b8SDevin Teske# f_sysrc_desc $varname 403ab2043b8SDevin Teske# 404ab2043b8SDevin Teske# Attempts to return the comments associated with varname from the rc.conf(5) 405ab2043b8SDevin Teske# defaults file `/etc/defaults/rc.conf' (or whatever RC_DEFAULTS points to). 406ab2043b8SDevin Teske# 407ab2043b8SDevin Teske# Multi-line comments are joined together. Results are NULL if no description 408ab2043b8SDevin Teske# could be found. 409ab2043b8SDevin Teske# 410ab2043b8SDevin Teske# This function is a two-parter. Below is the awk(1) portion of the function, 411ab2043b8SDevin Teske# afterward is the sh(1) function which utilizes the below awk script. 412ab2043b8SDevin Teske# 413ab2043b8SDevin Teskef_sysrc_desc_awk=' 414ab2043b8SDevin Teske# Variables that should be defined on the invocation line: 415ab2043b8SDevin Teske# -v varname="varname" 416ab2043b8SDevin Teske# 417ab2043b8SDevin TeskeBEGIN { 418ab2043b8SDevin Teske regex = "^[[:space:]]*"varname"=" 419ab2043b8SDevin Teske found = 0 420ab2043b8SDevin Teske buffer = "" 421ab2043b8SDevin Teske} 422ab2043b8SDevin Teske{ 423ab2043b8SDevin Teske if ( ! found ) 424ab2043b8SDevin Teske { 425ab2043b8SDevin Teske if ( ! match($0, regex) ) next 426ab2043b8SDevin Teske 427ab2043b8SDevin Teske found = 1 428ab2043b8SDevin Teske sub(/^[^#]*(#[[:space:]]*)?/, "") 429ab2043b8SDevin Teske buffer = $0 430ab2043b8SDevin Teske next 431ab2043b8SDevin Teske } 432ab2043b8SDevin Teske 433ab2043b8SDevin Teske if ( !/^[[:space:]]*#/ || 434ab2043b8SDevin Teske /^[[:space:]]*[[:alpha:]_][[:alnum:]_]*=/ || 435ab2043b8SDevin Teske /^[[:space:]]*#[[:alpha:]_][[:alnum:]_]*=/ || 436ab2043b8SDevin Teske /^[[:space:]]*$/ ) exit 437ab2043b8SDevin Teske 438ab2043b8SDevin Teske sub(/(.*#)*[[:space:]]*/, "") 439ab2043b8SDevin Teske buffer = buffer" "$0 440ab2043b8SDevin Teske} 441ab2043b8SDevin TeskeEND { 442ab2043b8SDevin Teske # Clean up the buffer 443ab2043b8SDevin Teske sub(/^[[:space:]]*/, "", buffer) 444ab2043b8SDevin Teske sub(/[[:space:]]*$/, "", buffer) 445ab2043b8SDevin Teske 446ab2043b8SDevin Teske print buffer 447ab2043b8SDevin Teske exit ! found 448ab2043b8SDevin Teske} 449ab2043b8SDevin Teske' 450ab2043b8SDevin Teskef_sysrc_desc() 451ab2043b8SDevin Teske{ 452ab2043b8SDevin Teske awk -v varname="$1" "$f_sysrc_desc_awk" < "$RC_DEFAULTS" 453ab2043b8SDevin Teske} 454ab2043b8SDevin Teske 455ab2043b8SDevin Teske# f_sysrc_set $varname $new_value 456ab2043b8SDevin Teske# 457ab2043b8SDevin Teske# Change a setting in the system configuration files (edits the files in-place 458ab2043b8SDevin Teske# to change the value in the last assignment to the variable). If the variable 459ab2043b8SDevin Teske# does not appear in the source file, it is appended to the end of the primary 460ab2043b8SDevin Teske# system configuration file `/etc/rc.conf'. 461ab2043b8SDevin Teske# 462ab2043b8SDevin Teske# This function is a two-parter. Below is the awk(1) portion of the function, 463ab2043b8SDevin Teske# afterward is the sh(1) function which utilizes the below awk script. 464ab2043b8SDevin Teske# 465ab2043b8SDevin Teskef_sysrc_set_awk=' 466ab2043b8SDevin Teske# Variables that should be defined on the invocation line: 467ab2043b8SDevin Teske# -v varname="varname" 468ab2043b8SDevin Teske# -v new_value="new_value" 469ab2043b8SDevin Teske# 470ab2043b8SDevin TeskeBEGIN { 471ab2043b8SDevin Teske regex = "^[[:space:]]*"varname"=" 472ab2043b8SDevin Teske found = retval = 0 473ab2043b8SDevin Teske} 474ab2043b8SDevin Teske{ 475ab2043b8SDevin Teske # If already found... just spew 476ab2043b8SDevin Teske if ( found ) { print; next } 477ab2043b8SDevin Teske 478ab2043b8SDevin Teske # Does this line match an assignment to our variable? 479ab2043b8SDevin Teske if ( ! match($0, regex) ) { print; next } 480ab2043b8SDevin Teske 481ab2043b8SDevin Teske # Save important match information 482ab2043b8SDevin Teske found = 1 483ab2043b8SDevin Teske matchlen = RSTART + RLENGTH - 1 484ab2043b8SDevin Teske 485ab2043b8SDevin Teske # Store the value text for later munging 486ab2043b8SDevin Teske value = substr($0, matchlen + 1, length($0) - matchlen) 487ab2043b8SDevin Teske 488ab2043b8SDevin Teske # Store the first character of the value 489ab2043b8SDevin Teske t1 = t2 = substr(value, 0, 1) 490ab2043b8SDevin Teske 491ab2043b8SDevin Teske # Assignment w/ back-ticks, expression, or misc. 492ab2043b8SDevin Teske # We ignore these since we did not generate them 493ab2043b8SDevin Teske # 494ab2043b8SDevin Teske if ( t1 ~ /[`$\\]/ ) { retval = 1; print; next } 495ab2043b8SDevin Teske 496ab2043b8SDevin Teske # Assignment w/ single-quoted value 497ab2043b8SDevin Teske else if ( t1 == "'\''" ) { 498ab2043b8SDevin Teske sub(/^'\''[^'\'']*/, "", value) 499ab2043b8SDevin Teske if ( length(value) == 0 ) t2 = "" 500ab2043b8SDevin Teske sub(/^'\''/, "", value) 501ab2043b8SDevin Teske } 502ab2043b8SDevin Teske 503ab2043b8SDevin Teske # Assignment w/ double-quoted value 504ab2043b8SDevin Teske else if ( t1 == "\"" ) { 505ab2043b8SDevin Teske sub(/^"(.*\\\\+")*[^"]*/, "", value) 506ab2043b8SDevin Teske if ( length(value) == 0 ) t2 = "" 507ab2043b8SDevin Teske sub(/^"/, "", value) 508ab2043b8SDevin Teske } 509ab2043b8SDevin Teske 510ab2043b8SDevin Teske # Assignment w/ non-quoted value 511ab2043b8SDevin Teske else if ( t1 ~ /[^[:space:];]/ ) { 512ab2043b8SDevin Teske t1 = t2 = "\"" 513ab2043b8SDevin Teske sub(/^[^[:space:]]*/, "", value) 514ab2043b8SDevin Teske } 515ab2043b8SDevin Teske 516ab2043b8SDevin Teske # Null-assignment 517ab2043b8SDevin Teske else if ( t1 ~ /[[:space:];]/ ) { t1 = t2 = "\"" } 518ab2043b8SDevin Teske 519ab2043b8SDevin Teske printf "%s%c%s%c%s\n", substr($0, 0, matchlen), \ 520ab2043b8SDevin Teske t1, new_value, t2, value 521ab2043b8SDevin Teske} 522ab2043b8SDevin TeskeEND { exit retval } 523ab2043b8SDevin Teske' 524ab2043b8SDevin Teskef_sysrc_set() 525ab2043b8SDevin Teske{ 526d4ae33f0SDevin Teske local funcname=f_sysrc_set 527ab2043b8SDevin Teske local varname="$1" new_value="$2" 528ab2043b8SDevin Teske 529ab2043b8SDevin Teske # Check arguments 530ab2043b8SDevin Teske [ "$varname" ] || return $FAILURE 531ab2043b8SDevin Teske 532ab2043b8SDevin Teske # 533ab2043b8SDevin Teske # Find which rc.conf(5) file contains the last-assignment 534ab2043b8SDevin Teske # 535ab2043b8SDevin Teske local not_found= 536ab2043b8SDevin Teske local file="$( f_sysrc_find "$varname" )" 537ab2043b8SDevin Teske if [ "$file" = "$RC_DEFAULTS" -o ! "$file" ]; then 538ab2043b8SDevin Teske # 539ab2043b8SDevin Teske # We either got a null response (not found) or the variable 540ab2043b8SDevin Teske # was only found in the rc.conf(5) defaults. In either case, 541ab2043b8SDevin Teske # let's instead modify the first file from $rc_conf_files. 542ab2043b8SDevin Teske # 543ab2043b8SDevin Teske 544ab2043b8SDevin Teske not_found=1 545ab2043b8SDevin Teske 546ab2043b8SDevin Teske # 547ab2043b8SDevin Teske # If RC_CONFS is defined, use $RC_CONFS 548ab2043b8SDevin Teske # rather than $rc_conf_files. 549ab2043b8SDevin Teske # 5500ad5179dSDevin Teske if [ "${RC_CONFS+set}" ]; then 551ab2043b8SDevin Teske file="${RC_CONFS%%[$IFS]*}" 552ab2043b8SDevin Teske else 5531f843bc0SDevin Teske file=$( f_sysrc_get 'rc_conf_files%%[$IFS]*' ) 554ab2043b8SDevin Teske fi 555ab2043b8SDevin Teske fi 556ab2043b8SDevin Teske 557ab2043b8SDevin Teske # 558eca1e88cSDevin Teske # If not found, append new value to first file and return. 559ab2043b8SDevin Teske # 560ab2043b8SDevin Teske if [ "$not_found" ]; then 561181560bbSDevin Teske # Add a newline if missing before appending to the file 562*e19a2226SDevin Teske [ ! -e "$file" ] || awk 'BEGIN { wc = 0 } NR == 1 { 563181560bbSDevin Teske (cmd = "wc -l " FILENAME) | getline 564181560bbSDevin Teske close(cmd) 565181560bbSDevin Teske wc = $1 566181560bbSDevin Teske } END { exit wc != NR }' "$file" || 567181560bbSDevin Teske echo >> "$file" || return $? 568ab2043b8SDevin Teske echo "$varname=\"$new_value\"" >> "$file" 569ab2043b8SDevin Teske return $? 570ab2043b8SDevin Teske fi 571ab2043b8SDevin Teske 572ab2043b8SDevin Teske # 573ab2043b8SDevin Teske # Perform sanity checks. 574ab2043b8SDevin Teske # 575ab2043b8SDevin Teske if [ ! -w "$file" ]; then 576ab2043b8SDevin Teske f_err "$msg_cannot_create_permission_denied\n" \ 577ab2043b8SDevin Teske "$pgm" "$file" 578ab2043b8SDevin Teske return $FAILURE 579ab2043b8SDevin Teske fi 580ab2043b8SDevin Teske 581ab2043b8SDevin Teske # 582ab2043b8SDevin Teske # Create a new temporary file to write to. 583ab2043b8SDevin Teske # 584d4ae33f0SDevin Teske local tmpfile 585d4ae33f0SDevin Teske if ! f_eval_catch -dk tmpfile $funcname mktemp 'mktemp -t "%s"' "$pgm" 586d4ae33f0SDevin Teske then 587d4ae33f0SDevin Teske echo "$tmpfile" >&2 588d4ae33f0SDevin Teske return $FAILURE 589d4ae33f0SDevin Teske fi 590ab2043b8SDevin Teske 591ab2043b8SDevin Teske # 592ab2043b8SDevin Teske # Fixup permissions (else we're in for a surprise, as mktemp(1) creates 593ab2043b8SDevin Teske # the temporary file with 0600 permissions, and if we simply mv(1) the 594ab2043b8SDevin Teske # temporary file over the destination, the destination will inherit the 595ab2043b8SDevin Teske # permissions from the temporary file). 596ab2043b8SDevin Teske # 597ab2043b8SDevin Teske local mode 598d4ae33f0SDevin Teske f_eval_catch -dk mode $funcname stat 'stat -f "%%#Lp" "%s"' "$file" || 599d4ae33f0SDevin Teske mode=0644 600d4ae33f0SDevin Teske f_eval_catch -d $funcname chmod 'chmod "%s" "%s"' "$mode" "$tmpfile" 601ab2043b8SDevin Teske 602ab2043b8SDevin Teske # 603ab2043b8SDevin Teske # Fixup ownership. The destination file _is_ writable (we tested 604ab2043b8SDevin Teske # earlier above). However, this will fail if we don't have sufficient 605ab2043b8SDevin Teske # permissions (so we throw stderr into the bit-bucket). 606ab2043b8SDevin Teske # 607ab2043b8SDevin Teske local owner 608d4ae33f0SDevin Teske f_eval_catch -dk owner $funcname stat \ 609d4ae33f0SDevin Teske 'stat -f "%%u:%%g" "%s"' "$file" || owner="root:wheel" 610d4ae33f0SDevin Teske f_eval_catch -d $funcname chown 'chown "%s" "%s"' "$owner" "$tmpfile" 611ab2043b8SDevin Teske 612ab2043b8SDevin Teske # 613ab2043b8SDevin Teske # Operate on the matching file, replacing only the last occurrence. 614ab2043b8SDevin Teske # 615181560bbSDevin Teske # Use awk to ensure LF at end of each line, else files without ending 616181560bbSDevin Teske # LF will trigger a bug in `tail -r' where last two lines are joined. 617181560bbSDevin Teske # 618ab2043b8SDevin Teske local new_contents retval 619181560bbSDevin Teske new_contents=$( awk 1 "$file" 2> /dev/null | tail -r ) 620ab2043b8SDevin Teske new_contents=$( echo "$new_contents" | awk -v varname="$varname" \ 621ab2043b8SDevin Teske -v new_value="$new_value" "$f_sysrc_set_awk" ) 622ab2043b8SDevin Teske retval=$? 623ab2043b8SDevin Teske 624ab2043b8SDevin Teske # 625ab2043b8SDevin Teske # Write the temporary file contents. 626ab2043b8SDevin Teske # 627ab2043b8SDevin Teske echo "$new_contents" | tail -r > "$tmpfile" || return $FAILURE 628ab2043b8SDevin Teske if [ $retval -ne $SUCCESS ]; then 629ab2043b8SDevin Teske echo "$varname=\"$new_value\"" >> "$tmpfile" 630ab2043b8SDevin Teske fi 631ab2043b8SDevin Teske 632ab2043b8SDevin Teske # 633ab2043b8SDevin Teske # Taint-check our results. 634ab2043b8SDevin Teske # 635d4ae33f0SDevin Teske if ! f_eval_catch -d $funcname sh '/bin/sh -n "%s"' "$tmpfile"; then 636ab2043b8SDevin Teske f_err "$msg_previous_syntax_errors\n" "$pgm" "$file" 637ab2043b8SDevin Teske rm -f "$tmpfile" 638ab2043b8SDevin Teske return $FAILURE 639ab2043b8SDevin Teske fi 640ab2043b8SDevin Teske 641ab2043b8SDevin Teske # 642ab2043b8SDevin Teske # Finally, move the temporary file into place. 643ab2043b8SDevin Teske # 644d4ae33f0SDevin Teske f_eval_catch -de $funcname mv 'mv "%s" "%s"' "$tmpfile" "$file" 645ab2043b8SDevin Teske} 646ab2043b8SDevin Teske 647ab2043b8SDevin Teske# f_sysrc_delete $varname 648ab2043b8SDevin Teske# 649ab2043b8SDevin Teske# Remove a setting from the system configuration files (edits files in-place). 650ab2043b8SDevin Teske# Deletes all assignments to the given variable in all config files. If the 651ab2043b8SDevin Teske# `-f file' option is passed, the removal is restricted to only those files 652ab2043b8SDevin Teske# specified, otherwise the system collection of rc_conf_files is used. 653ab2043b8SDevin Teske# 654ab2043b8SDevin Teske# This function is a two-parter. Below is the awk(1) portion of the function, 655ab2043b8SDevin Teske# afterward is the sh(1) function which utilizes the below awk script. 656ab2043b8SDevin Teske# 657ab2043b8SDevin Teskef_sysrc_delete_awk=' 658ab2043b8SDevin Teske# Variables that should be defined on the invocation line: 659ab2043b8SDevin Teske# -v varname="varname" 660ab2043b8SDevin Teske# 661ab2043b8SDevin TeskeBEGIN { 662ab2043b8SDevin Teske regex = "^[[:space:]]*"varname"=" 663ab2043b8SDevin Teske found = 0 664ab2043b8SDevin Teske} 665ab2043b8SDevin Teske{ 666ab2043b8SDevin Teske if ( $0 ~ regex ) 667ab2043b8SDevin Teske found = 1 668ab2043b8SDevin Teske else 669ab2043b8SDevin Teske print 670ab2043b8SDevin Teske} 671ab2043b8SDevin TeskeEND { exit ! found } 672ab2043b8SDevin Teske' 673ab2043b8SDevin Teskef_sysrc_delete() 674ab2043b8SDevin Teske{ 675d4ae33f0SDevin Teske local funcname=f_sysrc_delete 676ab2043b8SDevin Teske local varname="$1" 677ab2043b8SDevin Teske local file 678ab2043b8SDevin Teske 679ab2043b8SDevin Teske # Check arguments 680ab2043b8SDevin Teske [ "$varname" ] || return $FAILURE 681ab2043b8SDevin Teske 682ab2043b8SDevin Teske # 683ab2043b8SDevin Teske # Operate on each of the specified files 684ab2043b8SDevin Teske # 685d4ae33f0SDevin Teske local tmpfile 6860ad5179dSDevin Teske for file in ${RC_CONFS-$( f_sysrc_get rc_conf_files )}; do 687ab2043b8SDevin Teske [ -e "$file" ] || continue 688ab2043b8SDevin Teske 689ab2043b8SDevin Teske # 690ab2043b8SDevin Teske # Create a new temporary file to write to. 691ab2043b8SDevin Teske # 692d4ae33f0SDevin Teske if ! f_eval_catch -dk tmpfile $funcname mktemp \ 693d4ae33f0SDevin Teske 'mktemp -t "%s"' "$pgm" 694d4ae33f0SDevin Teske then 695d4ae33f0SDevin Teske echo "$tmpfile" >&2 696d4ae33f0SDevin Teske return $FAILURE 697d4ae33f0SDevin Teske fi 698ab2043b8SDevin Teske 699ab2043b8SDevin Teske # 700ab2043b8SDevin Teske # Fixup permissions and ownership (mktemp(1) defaults to 0600 701ab2043b8SDevin Teske # permissions) to instead match the destination file. 702ab2043b8SDevin Teske # 703ab2043b8SDevin Teske local mode owner 704d4ae33f0SDevin Teske f_eval_catch -dk mode $funcname stat \ 705d4ae33f0SDevin Teske 'stat -f "%%#Lp" "%s"' "$file" || mode=0644 706d4ae33f0SDevin Teske f_eval_catch -dk owner $funcname stat \ 707d4ae33f0SDevin Teske 'stat -f "%%u:%%g" "%s"' "$file" || owner="root:wheel" 708d4ae33f0SDevin Teske f_eval_catch -d $funcname chmod \ 709d4ae33f0SDevin Teske 'chmod "%s" "%s"' "$mode" "$tmpfile" 710d4ae33f0SDevin Teske f_eval_catch -d $funcname chown \ 711d4ae33f0SDevin Teske 'chown "%s" "%s"' "$owner" "$tmpfile" 712ab2043b8SDevin Teske 713ab2043b8SDevin Teske # 714ab2043b8SDevin Teske # Operate on the file, removing all occurrences, saving the 715ab2043b8SDevin Teske # output in our temporary file. 716ab2043b8SDevin Teske # 717ab2043b8SDevin Teske awk -v varname="$varname" "$f_sysrc_delete_awk" "$file" \ 718ab2043b8SDevin Teske > "$tmpfile" 719ab2043b8SDevin Teske if [ $? -ne $SUCCESS ]; then 720ab2043b8SDevin Teske # The file didn't contain any assignments 721ab2043b8SDevin Teske rm -f "$tmpfile" 722ab2043b8SDevin Teske continue 723ab2043b8SDevin Teske fi 724ab2043b8SDevin Teske 725ab2043b8SDevin Teske # 726ab2043b8SDevin Teske # Taint-check our results. 727ab2043b8SDevin Teske # 728d4ae33f0SDevin Teske if ! f_eval_catch -d $funcname sh '/bin/sh -n "%s"' "$tmpfile" 729d4ae33f0SDevin Teske then 730ab2043b8SDevin Teske f_err "$msg_previous_syntax_errors\n" \ 731ab2043b8SDevin Teske "$pgm" "$file" 732ab2043b8SDevin Teske rm -f "$tmpfile" 733ab2043b8SDevin Teske return $FAILURE 734ab2043b8SDevin Teske fi 735ab2043b8SDevin Teske 736ab2043b8SDevin Teske # 737ab2043b8SDevin Teske # Perform sanity checks 738ab2043b8SDevin Teske # 739ab2043b8SDevin Teske if [ ! -w "$file" ]; then 740ab2043b8SDevin Teske f_err "$msg_permission_denied\n" "$pgm" "$file" 741ab2043b8SDevin Teske rm -f "$tmpfile" 742ab2043b8SDevin Teske return $FAILURE 743ab2043b8SDevin Teske fi 744ab2043b8SDevin Teske 745ab2043b8SDevin Teske # 746ab2043b8SDevin Teske # Finally, move the temporary file into place. 747ab2043b8SDevin Teske # 748d4ae33f0SDevin Teske f_eval_catch -de $funcname mv \ 749d4ae33f0SDevin Teske 'mv "%s" "%s"' "$tmpfile" "$file" || return $FAILURE 750ab2043b8SDevin Teske done 751ab2043b8SDevin Teske} 752ab2043b8SDevin Teske 75356961fd7SDevin Teske############################################################ MAIN 75456961fd7SDevin Teske 75556961fd7SDevin Teskef_dprintf "%s: Successfully loaded." sysrc.subr 75656961fd7SDevin Teske 757ab2043b8SDevin Teskefi # ! $_SYSRC_SUBR 758