1ab2043b8SDevin Teskeif [ ! "$_SYSRC_SUBR" ]; then _SYSRC_SUBR=1 2ab2043b8SDevin Teske# 3ab2043b8SDevin Teske# Copyright (c) 2006-2012 Devin Teske 4ab2043b8SDevin 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 16ab2043b8SDevin 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# $FreeBSD$ 28ab2043b8SDevin Teske# 29ab2043b8SDevin Teske############################################################ INCLUDES 30ab2043b8SDevin Teske 31ab2043b8SDevin TeskeBSDCFG_SHARE="/usr/share/bsdconfig" 32ab2043b8SDevin Teske. $BSDCFG_SHARE/common.subr || exit 1 33ab2043b8SDevin Teske 34ab2043b8SDevin TeskeBSDCFG_LIBE="/usr/libexec/bsdconfig" 35ab2043b8SDevin Teskef_include_lang $BSDCFG_LIBE/include/messages.subr 36ab2043b8SDevin Teske 37ab2043b8SDevin Teske############################################################ CONFIGURATION 38ab2043b8SDevin Teske 39ab2043b8SDevin Teske# 40ab2043b8SDevin Teske# Standard pathnames (inherit values from shell if available) 41ab2043b8SDevin Teske# 42ab2043b8SDevin Teske: ${RC_DEFAULTS:="/etc/defaults/rc.conf"} 43ab2043b8SDevin Teske 44ab2043b8SDevin Teske############################################################ GLOBALS 45ab2043b8SDevin Teske 46ab2043b8SDevin Teske# 47ab2043b8SDevin Teske# Global exit status variables 48ab2043b8SDevin Teske# 49ab2043b8SDevin TeskeSUCCESS=0 50ab2043b8SDevin TeskeFAILURE=1 51ab2043b8SDevin Teske 52ab2043b8SDevin Teske############################################################ FUNCTIONS 53ab2043b8SDevin Teske 54ab2043b8SDevin Teske# f_clean_env [ --except $varname ... ] 55ab2043b8SDevin Teske# 56ab2043b8SDevin Teske# Unset all environment variables in the current scope. An optional list of 57ab2043b8SDevin Teske# arguments can be passed, indicating which variables to avoid unsetting; the 58ab2043b8SDevin Teske# `--except' is required to enable the exclusion-list as the remainder of 59ab2043b8SDevin Teske# positional arguments. 60ab2043b8SDevin Teske# 61ab2043b8SDevin Teske# Be careful not to call this in a shell that you still expect to perform 62ab2043b8SDevin Teske# $PATH expansion in, because this will blow $PATH away. This is best used 63ab2043b8SDevin Teske# within a sub-shell block "(...)" or "$(...)" or "`...`". 64ab2043b8SDevin Teske# 65ab2043b8SDevin Teskef_clean_env() 66ab2043b8SDevin Teske{ 67ab2043b8SDevin Teske local var arg except= 68ab2043b8SDevin Teske 69ab2043b8SDevin Teske # 70ab2043b8SDevin Teske # Should we process an exclusion-list? 71ab2043b8SDevin Teske # 72ab2043b8SDevin Teske if [ "$1" = "--except" ]; then 73ab2043b8SDevin Teske except=1 74ab2043b8SDevin Teske shift 1 75ab2043b8SDevin Teske fi 76ab2043b8SDevin Teske 77ab2043b8SDevin Teske # 78ab2043b8SDevin Teske # Loop over a list of variable names from set(1) built-in. 79ab2043b8SDevin Teske # 80ab2043b8SDevin Teske for var in $( set | awk -F= \ 81ab2043b8SDevin Teske '/^[[:alpha:]_][[:alnum:]_]*=/ {print $1}' \ 82ab2043b8SDevin Teske | grep -v '^except$' 83ab2043b8SDevin Teske ); do 84ab2043b8SDevin Teske # 85ab2043b8SDevin Teske # In POSIX bourne-shell, attempting to unset(1) OPTIND results 86ab2043b8SDevin Teske # in "unset: Illegal number:" and causes abrupt termination. 87ab2043b8SDevin Teske # 88ab2043b8SDevin Teske [ "$var" = OPTIND ] && continue 89ab2043b8SDevin Teske 90ab2043b8SDevin Teske # 91ab2043b8SDevin Teske # Process the exclusion-list? 92ab2043b8SDevin Teske # 93ab2043b8SDevin Teske if [ "$except" ]; then 94ab2043b8SDevin Teske for arg in "$@" ""; do 95ab2043b8SDevin Teske [ "$var" = "$arg" ] && break 96ab2043b8SDevin Teske done 97ab2043b8SDevin Teske [ "$arg" ] && continue 98ab2043b8SDevin Teske fi 99ab2043b8SDevin Teske 100ab2043b8SDevin Teske unset "$var" 101ab2043b8SDevin Teske done 102ab2043b8SDevin Teske} 103ab2043b8SDevin Teske 104ab2043b8SDevin Teske# f_sysrc_get $varname 105ab2043b8SDevin Teske# 106ab2043b8SDevin Teske# Get a system configuration setting from the collection of system- 107ab2043b8SDevin Teske# configuration files (in order: /etc/defaults/rc.conf /etc/rc.conf 108ab2043b8SDevin Teske# and /etc/rc.conf). 109ab2043b8SDevin Teske# 110ab2043b8SDevin Teske# NOTE: Additional shell parameter-expansion formats are supported. For 111ab2043b8SDevin Teske# example, passing an argument of "hostname%%.*" (properly quoted) will 112ab2043b8SDevin Teske# return the hostname up to (but not including) the first `.' (see sh(1), 113ab2043b8SDevin Teske# "Parameter Expansion" for more information on additional formats). 114ab2043b8SDevin Teske# 115ab2043b8SDevin Teskef_sysrc_get() 116ab2043b8SDevin Teske{ 117ab2043b8SDevin Teske # Sanity check 118ab2043b8SDevin Teske [ -f "$RC_DEFAULTS" -a -r "$RC_DEFAULTS" ] || return $FAILURE 119ab2043b8SDevin Teske 120ab2043b8SDevin Teske # Taint-check variable name 121ab2043b8SDevin Teske case "$1" in 122ab2043b8SDevin Teske [0-9]*) 123ab2043b8SDevin Teske # Don't expand possible positional parameters 124ab2043b8SDevin Teske return $FAILURE;; 125ab2043b8SDevin Teske *) 126ab2043b8SDevin Teske [ "$1" ] || return $FAILURE 127ab2043b8SDevin Teske esac 128ab2043b8SDevin Teske 129ab2043b8SDevin Teske ( # Execute within sub-shell to protect parent environment 130ab2043b8SDevin Teske 131ab2043b8SDevin Teske # 132ab2043b8SDevin Teske # Clear the environment of all variables, preventing the 133ab2043b8SDevin Teske # expansion of normals such as `PS1', `TERM', etc. 134ab2043b8SDevin Teske # 135*8d8d314dSDevin Teske f_clean_env --except RC_CONFS RC_DEFAULTS 136ab2043b8SDevin Teske 137fb7d723eSDevin Teske . "$RC_DEFAULTS" > /dev/null 2>&1 138ab2043b8SDevin Teske 139ab2043b8SDevin Teske unset RC_DEFAULTS 140ab2043b8SDevin Teske # no longer needed 141ab2043b8SDevin Teske 142ab2043b8SDevin Teske # 143ab2043b8SDevin Teske # If the query is for `rc_conf_files' then store the value that 144ab2043b8SDevin Teske # we inherited from sourcing RC_DEFAULTS (above) so that we may 145ab2043b8SDevin Teske # conditionally restore this value after source_rc_confs in the 146ab2043b8SDevin Teske # event that RC_CONFS does not customize the value. 147ab2043b8SDevin Teske # 148ab2043b8SDevin Teske if [ "$1" = "rc_conf_files" ]; then 149ab2043b8SDevin Teske _rc_conf_files="$rc_conf_files" 150ab2043b8SDevin Teske fi 151ab2043b8SDevin Teske 152ab2043b8SDevin Teske # 153ab2043b8SDevin Teske # If RC_CONFS is defined, set $rc_conf_files to an explicit 154ab2043b8SDevin Teske # value, modifying the default behavior of source_rc_confs(). 155ab2043b8SDevin Teske # 156*8d8d314dSDevin Teske if [ "${RC_CONFS+set}" ]; then 157ab2043b8SDevin Teske rc_conf_files="$RC_CONFS" 158ab2043b8SDevin Teske _rc_confs_set=1 159ab2043b8SDevin Teske fi 160ab2043b8SDevin Teske 161fb7d723eSDevin Teske source_rc_confs > /dev/null 2>&1 162ab2043b8SDevin Teske 163ab2043b8SDevin Teske # 164ab2043b8SDevin Teske # If the query was for `rc_conf_files' AND after calling 1652d49f165SDevin Teske # source_rc_confs the value has not changed, then we should 166ab2043b8SDevin Teske # restore the value to the one inherited from RC_DEFAULTS 167ab2043b8SDevin Teske # before performing the final query (preventing us from 168ab2043b8SDevin Teske # returning what was set via RC_CONFS when the intent was 169ab2043b8SDevin Teske # instead to query the value from the file(s) specified). 170ab2043b8SDevin Teske # 171ab2043b8SDevin Teske if [ "$1" = "rc_conf_files" -a \ 172ab2043b8SDevin Teske "$_rc_confs_set" -a \ 173ab2043b8SDevin Teske "$rc_conf_files" = "$RC_CONFS" \ 174ab2043b8SDevin Teske ]; then 175ab2043b8SDevin Teske rc_conf_files="$_rc_conf_files" 176ab2043b8SDevin Teske unset _rc_conf_files 177ab2043b8SDevin Teske unset _rc_confs_set 178ab2043b8SDevin Teske fi 179ab2043b8SDevin Teske 180ab2043b8SDevin Teske unset RC_CONFS 181ab2043b8SDevin Teske # no longer needed 182ab2043b8SDevin Teske 183ab2043b8SDevin Teske # 184ab2043b8SDevin Teske # This must be the last functional line for both the sub-shell 185ab2043b8SDevin Teske # and the function to preserve the return status from formats 186ab2043b8SDevin Teske # such as "${varname?}" and "${varname:?}" (see "Parameter 187ab2043b8SDevin Teske # Expansion" in sh(1) for more information). 188ab2043b8SDevin Teske # 189fb7d723eSDevin Teske eval echo '"${'"$1"'}"' 2> /dev/null 190ab2043b8SDevin Teske ) 191ab2043b8SDevin Teske} 192ab2043b8SDevin Teske 193ab2043b8SDevin Teske# f_sysrc_get_default $varname 194ab2043b8SDevin Teske# 195ab2043b8SDevin Teske# Get a system configuration default setting from the default rc.conf(5) file 196ab2043b8SDevin Teske# (or whatever RC_DEFAULTS points at). 197ab2043b8SDevin Teske# 198ab2043b8SDevin Teskef_sysrc_get_default() 199ab2043b8SDevin Teske{ 200ab2043b8SDevin Teske # Sanity check 201ab2043b8SDevin Teske [ -f "$RC_DEFAULTS" -a -r "$RC_DEFAULTS" ] || return $FAILURE 202ab2043b8SDevin Teske 203ab2043b8SDevin Teske # Taint-check variable name 204ab2043b8SDevin Teske case "$1" in 205ab2043b8SDevin Teske [0-9]*) 206ab2043b8SDevin Teske # Don't expand possible positional parameters 207ab2043b8SDevin Teske return $FAILURE;; 208ab2043b8SDevin Teske *) 209ab2043b8SDevin Teske [ "$1" ] || return $FAILURE 210ab2043b8SDevin Teske esac 211ab2043b8SDevin Teske 212ab2043b8SDevin Teske ( # Execute within sub-shell to protect parent environment 213ab2043b8SDevin Teske 214ab2043b8SDevin Teske # 215ab2043b8SDevin Teske # Clear the environment of all variables, preventing the 216ab2043b8SDevin Teske # expansion of normals such as `PS1', `TERM', etc. 217ab2043b8SDevin Teske # 218ab2043b8SDevin Teske f_clean_env --except RC_DEFAULTS 219ab2043b8SDevin Teske 220fb7d723eSDevin Teske . "$RC_DEFAULTS" > /dev/null 2>&1 221ab2043b8SDevin Teske 222ab2043b8SDevin Teske unset RC_DEFAULTS 223ab2043b8SDevin Teske # no longer needed 224ab2043b8SDevin Teske 225ab2043b8SDevin Teske # 226ab2043b8SDevin Teske # This must be the last functional line for both the sub-shell 227ab2043b8SDevin Teske # and the function to preserve the return status from formats 228ab2043b8SDevin Teske # such as "${varname?}" and "${varname:?}" (see "Parameter 229ab2043b8SDevin Teske # Expansion" in sh(1) for more information). 230ab2043b8SDevin Teske # 231fb7d723eSDevin Teske eval echo '"${'"$1"'}"' 2> /dev/null 232ab2043b8SDevin Teske ) 233ab2043b8SDevin Teske} 234ab2043b8SDevin Teske 235ab2043b8SDevin Teske# f_sysrc_find $varname 236ab2043b8SDevin Teske# 237ab2043b8SDevin Teske# Find which file holds the effective last-assignment to a given variable 238ab2043b8SDevin Teske# within the rc.conf(5) file(s). 239ab2043b8SDevin Teske# 240ab2043b8SDevin Teske# If the variable is found in any of the rc.conf(5) files, the function prints 241ab2043b8SDevin Teske# the filename it was found in and then returns success. Otherwise output is 242ab2043b8SDevin Teske# NULL and the function returns with error status. 243ab2043b8SDevin Teske# 244ab2043b8SDevin Teskef_sysrc_find() 245ab2043b8SDevin Teske{ 246ab2043b8SDevin Teske local varname="$1" 247ab2043b8SDevin Teske local regex="^[[:space:]]*$varname=" 248ab2043b8SDevin Teske local rc_conf_files="$( f_sysrc_get rc_conf_files )" 249ab2043b8SDevin Teske local conf_files= 250ab2043b8SDevin Teske local file 251ab2043b8SDevin Teske 252ab2043b8SDevin Teske # Check parameters 253ab2043b8SDevin Teske [ "$varname" ] || return $FAILURE 254ab2043b8SDevin Teske 255ab2043b8SDevin Teske # 256ab2043b8SDevin Teske # If RC_CONFS is defined, set $rc_conf_files to an explicit 257ab2043b8SDevin Teske # value, modifying the default behavior of source_rc_confs(). 258ab2043b8SDevin Teske # 259ab2043b8SDevin Teske [ "$RC_CONFS" ] && rc_conf_files="$RC_CONFS" 260ab2043b8SDevin Teske 261ab2043b8SDevin Teske # 262ab2043b8SDevin Teske # Reverse the order of files in rc_conf_files (the boot process sources 263ab2043b8SDevin Teske # these in order, so we will search them in reverse-order to find the 264ab2043b8SDevin Teske # last-assignment -- the one that ultimately effects the environment). 265ab2043b8SDevin Teske # 266ab2043b8SDevin Teske for file in $rc_conf_files; do 267ab2043b8SDevin Teske conf_files="$file${conf_files:+ }$conf_files" 268ab2043b8SDevin Teske done 269ab2043b8SDevin Teske 270ab2043b8SDevin Teske # 271ab2043b8SDevin Teske # Append the defaults file (since directives in the defaults file 272ab2043b8SDevin Teske # indeed affect the boot process, we'll want to know when a directive 273ab2043b8SDevin Teske # is found there). 274ab2043b8SDevin Teske # 275ab2043b8SDevin Teske conf_files="$conf_files${conf_files:+ }$RC_DEFAULTS" 276ab2043b8SDevin Teske 277ab2043b8SDevin Teske # 278ab2043b8SDevin Teske # Find which file matches assignment to the given variable name. 279ab2043b8SDevin Teske # 280ab2043b8SDevin Teske for file in $conf_files; do 281ab2043b8SDevin Teske [ -f "$file" -a -r "$file" ] || continue 282ab2043b8SDevin Teske if grep -Eq "$regex" $file; then 283ab2043b8SDevin Teske echo $file 284ab2043b8SDevin Teske return $SUCCESS 285ab2043b8SDevin Teske fi 286ab2043b8SDevin Teske done 287ab2043b8SDevin Teske 288ab2043b8SDevin Teske return $FAILURE # Not found 289ab2043b8SDevin Teske} 290ab2043b8SDevin Teske 291ab2043b8SDevin Teske# f_sysrc_desc $varname 292ab2043b8SDevin Teske# 293ab2043b8SDevin Teske# Attempts to return the comments associated with varname from the rc.conf(5) 294ab2043b8SDevin Teske# defaults file `/etc/defaults/rc.conf' (or whatever RC_DEFAULTS points to). 295ab2043b8SDevin Teske# 296ab2043b8SDevin Teske# Multi-line comments are joined together. Results are NULL if no description 297ab2043b8SDevin Teske# could be found. 298ab2043b8SDevin Teske# 299ab2043b8SDevin Teske# This function is a two-parter. Below is the awk(1) portion of the function, 300ab2043b8SDevin Teske# afterward is the sh(1) function which utilizes the below awk script. 301ab2043b8SDevin Teske# 302ab2043b8SDevin Teskef_sysrc_desc_awk=' 303ab2043b8SDevin Teske# Variables that should be defined on the invocation line: 304ab2043b8SDevin Teske# -v varname="varname" 305ab2043b8SDevin Teske# 306ab2043b8SDevin TeskeBEGIN { 307ab2043b8SDevin Teske regex = "^[[:space:]]*"varname"=" 308ab2043b8SDevin Teske found = 0 309ab2043b8SDevin Teske buffer = "" 310ab2043b8SDevin Teske} 311ab2043b8SDevin Teske{ 312ab2043b8SDevin Teske if ( ! found ) 313ab2043b8SDevin Teske { 314ab2043b8SDevin Teske if ( ! match($0, regex) ) next 315ab2043b8SDevin Teske 316ab2043b8SDevin Teske found = 1 317ab2043b8SDevin Teske sub(/^[^#]*(#[[:space:]]*)?/, "") 318ab2043b8SDevin Teske buffer = $0 319ab2043b8SDevin Teske next 320ab2043b8SDevin Teske } 321ab2043b8SDevin Teske 322ab2043b8SDevin Teske if ( !/^[[:space:]]*#/ || 323ab2043b8SDevin Teske /^[[:space:]]*[[:alpha:]_][[:alnum:]_]*=/ || 324ab2043b8SDevin Teske /^[[:space:]]*#[[:alpha:]_][[:alnum:]_]*=/ || 325ab2043b8SDevin Teske /^[[:space:]]*$/ ) exit 326ab2043b8SDevin Teske 327ab2043b8SDevin Teske sub(/(.*#)*[[:space:]]*/, "") 328ab2043b8SDevin Teske buffer = buffer" "$0 329ab2043b8SDevin Teske} 330ab2043b8SDevin TeskeEND { 331ab2043b8SDevin Teske # Clean up the buffer 332ab2043b8SDevin Teske sub(/^[[:space:]]*/, "", buffer) 333ab2043b8SDevin Teske sub(/[[:space:]]*$/, "", buffer) 334ab2043b8SDevin Teske 335ab2043b8SDevin Teske print buffer 336ab2043b8SDevin Teske exit ! found 337ab2043b8SDevin Teske} 338ab2043b8SDevin Teske' 339ab2043b8SDevin Teskef_sysrc_desc() 340ab2043b8SDevin Teske{ 341ab2043b8SDevin Teske awk -v varname="$1" "$f_sysrc_desc_awk" < "$RC_DEFAULTS" 342ab2043b8SDevin Teske} 343ab2043b8SDevin Teske 344ab2043b8SDevin Teske# f_sysrc_set $varname $new_value 345ab2043b8SDevin Teske# 346ab2043b8SDevin Teske# Change a setting in the system configuration files (edits the files in-place 347ab2043b8SDevin Teske# to change the value in the last assignment to the variable). If the variable 348ab2043b8SDevin Teske# does not appear in the source file, it is appended to the end of the primary 349ab2043b8SDevin Teske# system configuration file `/etc/rc.conf'. 350ab2043b8SDevin Teske# 351ab2043b8SDevin Teske# This function is a two-parter. Below is the awk(1) portion of the function, 352ab2043b8SDevin Teske# afterward is the sh(1) function which utilizes the below awk script. 353ab2043b8SDevin Teske# 354ab2043b8SDevin Teskef_sysrc_set_awk=' 355ab2043b8SDevin Teske# Variables that should be defined on the invocation line: 356ab2043b8SDevin Teske# -v varname="varname" 357ab2043b8SDevin Teske# -v new_value="new_value" 358ab2043b8SDevin Teske# 359ab2043b8SDevin TeskeBEGIN { 360ab2043b8SDevin Teske regex = "^[[:space:]]*"varname"=" 361ab2043b8SDevin Teske found = retval = 0 362ab2043b8SDevin Teske} 363ab2043b8SDevin Teske{ 364ab2043b8SDevin Teske # If already found... just spew 365ab2043b8SDevin Teske if ( found ) { print; next } 366ab2043b8SDevin Teske 367ab2043b8SDevin Teske # Does this line match an assignment to our variable? 368ab2043b8SDevin Teske if ( ! match($0, regex) ) { print; next } 369ab2043b8SDevin Teske 370ab2043b8SDevin Teske # Save important match information 371ab2043b8SDevin Teske found = 1 372ab2043b8SDevin Teske matchlen = RSTART + RLENGTH - 1 373ab2043b8SDevin Teske 374ab2043b8SDevin Teske # Store the value text for later munging 375ab2043b8SDevin Teske value = substr($0, matchlen + 1, length($0) - matchlen) 376ab2043b8SDevin Teske 377ab2043b8SDevin Teske # Store the first character of the value 378ab2043b8SDevin Teske t1 = t2 = substr(value, 0, 1) 379ab2043b8SDevin Teske 380ab2043b8SDevin Teske # Assignment w/ back-ticks, expression, or misc. 381ab2043b8SDevin Teske # We ignore these since we did not generate them 382ab2043b8SDevin Teske # 383ab2043b8SDevin Teske if ( t1 ~ /[`$\\]/ ) { retval = 1; print; next } 384ab2043b8SDevin Teske 385ab2043b8SDevin Teske # Assignment w/ single-quoted value 386ab2043b8SDevin Teske else if ( t1 == "'\''" ) { 387ab2043b8SDevin Teske sub(/^'\''[^'\'']*/, "", value) 388ab2043b8SDevin Teske if ( length(value) == 0 ) t2 = "" 389ab2043b8SDevin Teske sub(/^'\''/, "", value) 390ab2043b8SDevin Teske } 391ab2043b8SDevin Teske 392ab2043b8SDevin Teske # Assignment w/ double-quoted value 393ab2043b8SDevin Teske else if ( t1 == "\"" ) { 394ab2043b8SDevin Teske sub(/^"(.*\\\\+")*[^"]*/, "", value) 395ab2043b8SDevin Teske if ( length(value) == 0 ) t2 = "" 396ab2043b8SDevin Teske sub(/^"/, "", value) 397ab2043b8SDevin Teske } 398ab2043b8SDevin Teske 399ab2043b8SDevin Teske # Assignment w/ non-quoted value 400ab2043b8SDevin Teske else if ( t1 ~ /[^[:space:];]/ ) { 401ab2043b8SDevin Teske t1 = t2 = "\"" 402ab2043b8SDevin Teske sub(/^[^[:space:]]*/, "", value) 403ab2043b8SDevin Teske } 404ab2043b8SDevin Teske 405ab2043b8SDevin Teske # Null-assignment 406ab2043b8SDevin Teske else if ( t1 ~ /[[:space:];]/ ) { t1 = t2 = "\"" } 407ab2043b8SDevin Teske 408ab2043b8SDevin Teske printf "%s%c%s%c%s\n", substr($0, 0, matchlen), \ 409ab2043b8SDevin Teske t1, new_value, t2, value 410ab2043b8SDevin Teske} 411ab2043b8SDevin TeskeEND { exit retval } 412ab2043b8SDevin Teske' 413ab2043b8SDevin Teskef_sysrc_set() 414ab2043b8SDevin Teske{ 415ab2043b8SDevin Teske local varname="$1" new_value="$2" 416ab2043b8SDevin Teske 417ab2043b8SDevin Teske # Check arguments 418ab2043b8SDevin Teske [ "$varname" ] || return $FAILURE 419ab2043b8SDevin Teske 420ab2043b8SDevin Teske # 421ab2043b8SDevin Teske # Find which rc.conf(5) file contains the last-assignment 422ab2043b8SDevin Teske # 423ab2043b8SDevin Teske local not_found= 424ab2043b8SDevin Teske local file="$( f_sysrc_find "$varname" )" 425ab2043b8SDevin Teske if [ "$file" = "$RC_DEFAULTS" -o ! "$file" ]; then 426ab2043b8SDevin Teske # 427ab2043b8SDevin Teske # We either got a null response (not found) or the variable 428ab2043b8SDevin Teske # was only found in the rc.conf(5) defaults. In either case, 429ab2043b8SDevin Teske # let's instead modify the first file from $rc_conf_files. 430ab2043b8SDevin Teske # 431ab2043b8SDevin Teske 432ab2043b8SDevin Teske not_found=1 433ab2043b8SDevin Teske 434ab2043b8SDevin Teske # 435ab2043b8SDevin Teske # If RC_CONFS is defined, use $RC_CONFS 436ab2043b8SDevin Teske # rather than $rc_conf_files. 437ab2043b8SDevin Teske # 438ab2043b8SDevin Teske if [ "$RC_CONFS" ]; then 439ab2043b8SDevin Teske file="${RC_CONFS%%[$IFS]*}" 440ab2043b8SDevin Teske else 441ab2043b8SDevin Teske file=$( f_sysrc_get rc_conf_files ) 442ab2043b8SDevin Teske file="${file%%[$IFS]*}" 443ab2043b8SDevin Teske fi 444ab2043b8SDevin Teske fi 445ab2043b8SDevin Teske 446ab2043b8SDevin Teske # 447ab2043b8SDevin Teske # If not found, append new value to last file and return. 448ab2043b8SDevin Teske # 449ab2043b8SDevin Teske if [ "$not_found" ]; then 450ab2043b8SDevin Teske echo "$varname=\"$new_value\"" >> "$file" 451ab2043b8SDevin Teske return $? 452ab2043b8SDevin Teske fi 453ab2043b8SDevin Teske 454ab2043b8SDevin Teske # 455ab2043b8SDevin Teske # Perform sanity checks. 456ab2043b8SDevin Teske # 457ab2043b8SDevin Teske if [ ! -w "$file" ]; then 458ab2043b8SDevin Teske f_err "$msg_cannot_create_permission_denied\n" \ 459ab2043b8SDevin Teske "$pgm" "$file" 460ab2043b8SDevin Teske return $FAILURE 461ab2043b8SDevin Teske fi 462ab2043b8SDevin Teske 463ab2043b8SDevin Teske # 464ab2043b8SDevin Teske # Create a new temporary file to write to. 465ab2043b8SDevin Teske # 466ab2043b8SDevin Teske local tmpfile="$( mktemp -t "$pgm" )" 467ab2043b8SDevin Teske [ "$tmpfile" ] || return $FAILURE 468ab2043b8SDevin Teske 469ab2043b8SDevin Teske # 470ab2043b8SDevin Teske # Fixup permissions (else we're in for a surprise, as mktemp(1) creates 471ab2043b8SDevin Teske # the temporary file with 0600 permissions, and if we simply mv(1) the 472ab2043b8SDevin Teske # temporary file over the destination, the destination will inherit the 473ab2043b8SDevin Teske # permissions from the temporary file). 474ab2043b8SDevin Teske # 475ab2043b8SDevin Teske local mode 476fb7d723eSDevin Teske mode=$( stat -f '%#Lp' "$file" 2> /dev/null ) 477ab2043b8SDevin Teske f_quietly chmod "${mode:-0644}" "$tmpfile" 478ab2043b8SDevin Teske 479ab2043b8SDevin Teske # 480ab2043b8SDevin Teske # Fixup ownership. The destination file _is_ writable (we tested 481ab2043b8SDevin Teske # earlier above). However, this will fail if we don't have sufficient 482ab2043b8SDevin Teske # permissions (so we throw stderr into the bit-bucket). 483ab2043b8SDevin Teske # 484ab2043b8SDevin Teske local owner 485fb7d723eSDevin Teske owner=$( stat -f '%u:%g' "$file" 2> /dev/null ) 486ab2043b8SDevin Teske f_quietly chown "${owner:-root:wheel}" "$tmpfile" 487ab2043b8SDevin Teske 488ab2043b8SDevin Teske # 489ab2043b8SDevin Teske # Operate on the matching file, replacing only the last occurrence. 490ab2043b8SDevin Teske # 491ab2043b8SDevin Teske local new_contents retval 492fb7d723eSDevin Teske new_contents=$( tail -r $file 2> /dev/null ) 493ab2043b8SDevin Teske new_contents=$( echo "$new_contents" | awk -v varname="$varname" \ 494ab2043b8SDevin Teske -v new_value="$new_value" "$f_sysrc_set_awk" ) 495ab2043b8SDevin Teske retval=$? 496ab2043b8SDevin Teske 497ab2043b8SDevin Teske # 498ab2043b8SDevin Teske # Write the temporary file contents. 499ab2043b8SDevin Teske # 500ab2043b8SDevin Teske echo "$new_contents" | tail -r > "$tmpfile" || return $FAILURE 501ab2043b8SDevin Teske if [ $retval -ne $SUCCESS ]; then 502ab2043b8SDevin Teske echo "$varname=\"$new_value\"" >> "$tmpfile" 503ab2043b8SDevin Teske fi 504ab2043b8SDevin Teske 505ab2043b8SDevin Teske # 506ab2043b8SDevin Teske # Taint-check our results. 507ab2043b8SDevin Teske # 508ab2043b8SDevin Teske if ! /bin/sh -n "$tmpfile"; then 509ab2043b8SDevin Teske f_err "$msg_previous_syntax_errors\n" "$pgm" "$file" 510ab2043b8SDevin Teske rm -f "$tmpfile" 511ab2043b8SDevin Teske return $FAILURE 512ab2043b8SDevin Teske fi 513ab2043b8SDevin Teske 514ab2043b8SDevin Teske # 515ab2043b8SDevin Teske # Finally, move the temporary file into place. 516ab2043b8SDevin Teske # 517ab2043b8SDevin Teske mv "$tmpfile" "$file" 518ab2043b8SDevin Teske} 519ab2043b8SDevin Teske 520ab2043b8SDevin Teske# f_sysrc_delete $varname 521ab2043b8SDevin Teske# 522ab2043b8SDevin Teske# Remove a setting from the system configuration files (edits files in-place). 523ab2043b8SDevin Teske# Deletes all assignments to the given variable in all config files. If the 524ab2043b8SDevin Teske# `-f file' option is passed, the removal is restricted to only those files 525ab2043b8SDevin Teske# specified, otherwise the system collection of rc_conf_files is used. 526ab2043b8SDevin Teske# 527ab2043b8SDevin Teske# This function is a two-parter. Below is the awk(1) portion of the function, 528ab2043b8SDevin Teske# afterward is the sh(1) function which utilizes the below awk script. 529ab2043b8SDevin Teske# 530ab2043b8SDevin Teskef_sysrc_delete_awk=' 531ab2043b8SDevin Teske# Variables that should be defined on the invocation line: 532ab2043b8SDevin Teske# -v varname="varname" 533ab2043b8SDevin Teske# 534ab2043b8SDevin TeskeBEGIN { 535ab2043b8SDevin Teske regex = "^[[:space:]]*"varname"=" 536ab2043b8SDevin Teske found = 0 537ab2043b8SDevin Teske} 538ab2043b8SDevin Teske{ 539ab2043b8SDevin Teske if ( $0 ~ regex ) 540ab2043b8SDevin Teske found = 1 541ab2043b8SDevin Teske else 542ab2043b8SDevin Teske print 543ab2043b8SDevin Teske} 544ab2043b8SDevin TeskeEND { exit ! found } 545ab2043b8SDevin Teske' 546ab2043b8SDevin Teskef_sysrc_delete() 547ab2043b8SDevin Teske{ 548ab2043b8SDevin Teske local varname="$1" 549ab2043b8SDevin Teske local file 550ab2043b8SDevin Teske 551ab2043b8SDevin Teske # Check arguments 552ab2043b8SDevin Teske [ "$varname" ] || return $FAILURE 553ab2043b8SDevin Teske 554ab2043b8SDevin Teske # 555ab2043b8SDevin Teske # Operate on each of the specified files 556ab2043b8SDevin Teske # 557ab2043b8SDevin Teske for file in ${RC_CONFS:-$( f_sysrc_get rc_conf_files )}; do 558ab2043b8SDevin Teske [ -e "$file" ] || continue 559ab2043b8SDevin Teske 560ab2043b8SDevin Teske # 561ab2043b8SDevin Teske # Create a new temporary file to write to. 562ab2043b8SDevin Teske # 563ab2043b8SDevin Teske local tmpfile="$( mktemp -t "$pgm" )" 564ab2043b8SDevin Teske [ "$tmpfile" ] || return $FAILURE 565ab2043b8SDevin Teske 566ab2043b8SDevin Teske # 567ab2043b8SDevin Teske # Fixup permissions and ownership (mktemp(1) defaults to 0600 568ab2043b8SDevin Teske # permissions) to instead match the destination file. 569ab2043b8SDevin Teske # 570ab2043b8SDevin Teske local mode owner 571fb7d723eSDevin Teske mode=$( stat -f '%#Lp' "$file" 2> /dev/null ) 572fb7d723eSDevin Teske owner=$( stat -f '%u:%g' "$file" 2> /dev/null ) 573ab2043b8SDevin Teske f_quietly chmod "${mode:-0644}" "$tmpfile" 574ab2043b8SDevin Teske f_quietly chown "${owner:-root:wheel}" "$tmpfile" 575ab2043b8SDevin Teske 576ab2043b8SDevin Teske # 577ab2043b8SDevin Teske # Operate on the file, removing all occurrences, saving the 578ab2043b8SDevin Teske # output in our temporary file. 579ab2043b8SDevin Teske # 580ab2043b8SDevin Teske awk -v varname="$varname" "$f_sysrc_delete_awk" "$file" \ 581ab2043b8SDevin Teske > "$tmpfile" 582ab2043b8SDevin Teske if [ $? -ne $SUCCESS ]; then 583ab2043b8SDevin Teske # The file didn't contain any assignments 584ab2043b8SDevin Teske rm -f "$tmpfile" 585ab2043b8SDevin Teske continue 586ab2043b8SDevin Teske fi 587ab2043b8SDevin Teske 588ab2043b8SDevin Teske # 589ab2043b8SDevin Teske # Taint-check our results. 590ab2043b8SDevin Teske # 591ab2043b8SDevin Teske if ! /bin/sh -n "$tmpfile"; then 592ab2043b8SDevin Teske f_err "$msg_previous_syntax_errors\n" \ 593ab2043b8SDevin Teske "$pgm" "$file" 594ab2043b8SDevin Teske rm -f "$tmpfile" 595ab2043b8SDevin Teske return $FAILURE 596ab2043b8SDevin Teske fi 597ab2043b8SDevin Teske 598ab2043b8SDevin Teske # 599ab2043b8SDevin Teske # Perform sanity checks 600ab2043b8SDevin Teske # 601ab2043b8SDevin Teske if [ ! -w "$file" ]; then 602ab2043b8SDevin Teske f_err "$msg_permission_denied\n" "$pgm" "$file" 603ab2043b8SDevin Teske rm -f "$tmpfile" 604ab2043b8SDevin Teske return $FAILURE 605ab2043b8SDevin Teske fi 606ab2043b8SDevin Teske 607ab2043b8SDevin Teske # 608ab2043b8SDevin Teske # Finally, move the temporary file into place. 609ab2043b8SDevin Teske # 610ab2043b8SDevin Teske mv "$tmpfile" "$file" 611ab2043b8SDevin Teske done 612ab2043b8SDevin Teske} 613ab2043b8SDevin Teske 614ab2043b8SDevin Teskefi # ! $_SYSRC_SUBR 615