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 20ab2043b8SDevin Teske# DAMAGES (INLUDING, 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 # 135ab2043b8SDevin Teske f_clean_env --except RC_CONFS RC_DEFAULTS SUCCESS 136ab2043b8SDevin Teske 137*fb7d723eSDevin 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*fb7d723eSDevin Teske ( : ${RC_CONFS?} ) > /dev/null 2>&1 157ab2043b8SDevin Teske if [ $? -eq ${SUCCESS:-0} ]; then 158ab2043b8SDevin Teske rc_conf_files="$RC_CONFS" 159ab2043b8SDevin Teske _rc_confs_set=1 160ab2043b8SDevin Teske fi 161ab2043b8SDevin Teske 162ab2043b8SDevin Teske unset SUCCESS 163ab2043b8SDevin Teske # no longer needed 164ab2043b8SDevin Teske 165*fb7d723eSDevin Teske source_rc_confs > /dev/null 2>&1 166ab2043b8SDevin Teske 167ab2043b8SDevin Teske # 168ab2043b8SDevin Teske # If the query was for `rc_conf_files' AND after calling 169ab2043b8SDevin Teske # source_rc_confs the vaue has not changed, then we should 170ab2043b8SDevin Teske # restore the value to the one inherited from RC_DEFAULTS 171ab2043b8SDevin Teske # before performing the final query (preventing us from 172ab2043b8SDevin Teske # returning what was set via RC_CONFS when the intent was 173ab2043b8SDevin Teske # instead to query the value from the file(s) specified). 174ab2043b8SDevin Teske # 175ab2043b8SDevin Teske if [ "$1" = "rc_conf_files" -a \ 176ab2043b8SDevin Teske "$_rc_confs_set" -a \ 177ab2043b8SDevin Teske "$rc_conf_files" = "$RC_CONFS" \ 178ab2043b8SDevin Teske ]; then 179ab2043b8SDevin Teske rc_conf_files="$_rc_conf_files" 180ab2043b8SDevin Teske unset _rc_conf_files 181ab2043b8SDevin Teske unset _rc_confs_set 182ab2043b8SDevin Teske fi 183ab2043b8SDevin Teske 184ab2043b8SDevin Teske unset RC_CONFS 185ab2043b8SDevin Teske # no longer needed 186ab2043b8SDevin Teske 187ab2043b8SDevin Teske # 188ab2043b8SDevin Teske # This must be the last functional line for both the sub-shell 189ab2043b8SDevin Teske # and the function to preserve the return status from formats 190ab2043b8SDevin Teske # such as "${varname?}" and "${varname:?}" (see "Parameter 191ab2043b8SDevin Teske # Expansion" in sh(1) for more information). 192ab2043b8SDevin Teske # 193*fb7d723eSDevin Teske eval echo '"${'"$1"'}"' 2> /dev/null 194ab2043b8SDevin Teske ) 195ab2043b8SDevin Teske} 196ab2043b8SDevin Teske 197ab2043b8SDevin Teske# f_sysrc_get_default $varname 198ab2043b8SDevin Teske# 199ab2043b8SDevin Teske# Get a system configuration default setting from the default rc.conf(5) file 200ab2043b8SDevin Teske# (or whatever RC_DEFAULTS points at). 201ab2043b8SDevin Teske# 202ab2043b8SDevin Teskef_sysrc_get_default() 203ab2043b8SDevin Teske{ 204ab2043b8SDevin Teske # Sanity check 205ab2043b8SDevin Teske [ -f "$RC_DEFAULTS" -a -r "$RC_DEFAULTS" ] || return $FAILURE 206ab2043b8SDevin Teske 207ab2043b8SDevin Teske # Taint-check variable name 208ab2043b8SDevin Teske case "$1" in 209ab2043b8SDevin Teske [0-9]*) 210ab2043b8SDevin Teske # Don't expand possible positional parameters 211ab2043b8SDevin Teske return $FAILURE;; 212ab2043b8SDevin Teske *) 213ab2043b8SDevin Teske [ "$1" ] || return $FAILURE 214ab2043b8SDevin Teske esac 215ab2043b8SDevin Teske 216ab2043b8SDevin Teske ( # Execute within sub-shell to protect parent environment 217ab2043b8SDevin Teske 218ab2043b8SDevin Teske # 219ab2043b8SDevin Teske # Clear the environment of all variables, preventing the 220ab2043b8SDevin Teske # expansion of normals such as `PS1', `TERM', etc. 221ab2043b8SDevin Teske # 222ab2043b8SDevin Teske f_clean_env --except RC_DEFAULTS 223ab2043b8SDevin Teske 224*fb7d723eSDevin Teske . "$RC_DEFAULTS" > /dev/null 2>&1 225ab2043b8SDevin Teske 226ab2043b8SDevin Teske unset RC_DEFAULTS 227ab2043b8SDevin Teske # no longer needed 228ab2043b8SDevin Teske 229ab2043b8SDevin Teske # 230ab2043b8SDevin Teske # This must be the last functional line for both the sub-shell 231ab2043b8SDevin Teske # and the function to preserve the return status from formats 232ab2043b8SDevin Teske # such as "${varname?}" and "${varname:?}" (see "Parameter 233ab2043b8SDevin Teske # Expansion" in sh(1) for more information). 234ab2043b8SDevin Teske # 235*fb7d723eSDevin Teske eval echo '"${'"$1"'}"' 2> /dev/null 236ab2043b8SDevin Teske ) 237ab2043b8SDevin Teske} 238ab2043b8SDevin Teske 239ab2043b8SDevin Teske# f_sysrc_find $varname 240ab2043b8SDevin Teske# 241ab2043b8SDevin Teske# Find which file holds the effective last-assignment to a given variable 242ab2043b8SDevin Teske# within the rc.conf(5) file(s). 243ab2043b8SDevin Teske# 244ab2043b8SDevin Teske# If the variable is found in any of the rc.conf(5) files, the function prints 245ab2043b8SDevin Teske# the filename it was found in and then returns success. Otherwise output is 246ab2043b8SDevin Teske# NULL and the function returns with error status. 247ab2043b8SDevin Teske# 248ab2043b8SDevin Teskef_sysrc_find() 249ab2043b8SDevin Teske{ 250ab2043b8SDevin Teske local varname="$1" 251ab2043b8SDevin Teske local regex="^[[:space:]]*$varname=" 252ab2043b8SDevin Teske local rc_conf_files="$( f_sysrc_get rc_conf_files )" 253ab2043b8SDevin Teske local conf_files= 254ab2043b8SDevin Teske local file 255ab2043b8SDevin Teske 256ab2043b8SDevin Teske # Check parameters 257ab2043b8SDevin Teske [ "$varname" ] || return $FAILURE 258ab2043b8SDevin Teske 259ab2043b8SDevin Teske # 260ab2043b8SDevin Teske # If RC_CONFS is defined, set $rc_conf_files to an explicit 261ab2043b8SDevin Teske # value, modifying the default behavior of source_rc_confs(). 262ab2043b8SDevin Teske # 263ab2043b8SDevin Teske [ "$RC_CONFS" ] && rc_conf_files="$RC_CONFS" 264ab2043b8SDevin Teske 265ab2043b8SDevin Teske # 266ab2043b8SDevin Teske # Reverse the order of files in rc_conf_files (the boot process sources 267ab2043b8SDevin Teske # these in order, so we will search them in reverse-order to find the 268ab2043b8SDevin Teske # last-assignment -- the one that ultimately effects the environment). 269ab2043b8SDevin Teske # 270ab2043b8SDevin Teske for file in $rc_conf_files; do 271ab2043b8SDevin Teske conf_files="$file${conf_files:+ }$conf_files" 272ab2043b8SDevin Teske done 273ab2043b8SDevin Teske 274ab2043b8SDevin Teske # 275ab2043b8SDevin Teske # Append the defaults file (since directives in the defaults file 276ab2043b8SDevin Teske # indeed affect the boot process, we'll want to know when a directive 277ab2043b8SDevin Teske # is found there). 278ab2043b8SDevin Teske # 279ab2043b8SDevin Teske conf_files="$conf_files${conf_files:+ }$RC_DEFAULTS" 280ab2043b8SDevin Teske 281ab2043b8SDevin Teske # 282ab2043b8SDevin Teske # Find which file matches assignment to the given variable name. 283ab2043b8SDevin Teske # 284ab2043b8SDevin Teske for file in $conf_files; do 285ab2043b8SDevin Teske [ -f "$file" -a -r "$file" ] || continue 286ab2043b8SDevin Teske if grep -Eq "$regex" $file; then 287ab2043b8SDevin Teske echo $file 288ab2043b8SDevin Teske return $SUCCESS 289ab2043b8SDevin Teske fi 290ab2043b8SDevin Teske done 291ab2043b8SDevin Teske 292ab2043b8SDevin Teske return $FAILURE # Not found 293ab2043b8SDevin Teske} 294ab2043b8SDevin Teske 295ab2043b8SDevin Teske# f_sysrc_desc $varname 296ab2043b8SDevin Teske# 297ab2043b8SDevin Teske# Attempts to return the comments associated with varname from the rc.conf(5) 298ab2043b8SDevin Teske# defaults file `/etc/defaults/rc.conf' (or whatever RC_DEFAULTS points to). 299ab2043b8SDevin Teske# 300ab2043b8SDevin Teske# Multi-line comments are joined together. Results are NULL if no description 301ab2043b8SDevin Teske# could be found. 302ab2043b8SDevin Teske# 303ab2043b8SDevin Teske# This function is a two-parter. Below is the awk(1) portion of the function, 304ab2043b8SDevin Teske# afterward is the sh(1) function which utilizes the below awk script. 305ab2043b8SDevin Teske# 306ab2043b8SDevin Teskef_sysrc_desc_awk=' 307ab2043b8SDevin Teske# Variables that should be defined on the invocation line: 308ab2043b8SDevin Teske# -v varname="varname" 309ab2043b8SDevin Teske# 310ab2043b8SDevin TeskeBEGIN { 311ab2043b8SDevin Teske regex = "^[[:space:]]*"varname"=" 312ab2043b8SDevin Teske found = 0 313ab2043b8SDevin Teske buffer = "" 314ab2043b8SDevin Teske} 315ab2043b8SDevin Teske{ 316ab2043b8SDevin Teske if ( ! found ) 317ab2043b8SDevin Teske { 318ab2043b8SDevin Teske if ( ! match($0, regex) ) next 319ab2043b8SDevin Teske 320ab2043b8SDevin Teske found = 1 321ab2043b8SDevin Teske sub(/^[^#]*(#[[:space:]]*)?/, "") 322ab2043b8SDevin Teske buffer = $0 323ab2043b8SDevin Teske next 324ab2043b8SDevin Teske } 325ab2043b8SDevin Teske 326ab2043b8SDevin Teske if ( !/^[[:space:]]*#/ || 327ab2043b8SDevin Teske /^[[:space:]]*[[:alpha:]_][[:alnum:]_]*=/ || 328ab2043b8SDevin Teske /^[[:space:]]*#[[:alpha:]_][[:alnum:]_]*=/ || 329ab2043b8SDevin Teske /^[[:space:]]*$/ ) exit 330ab2043b8SDevin Teske 331ab2043b8SDevin Teske sub(/(.*#)*[[:space:]]*/, "") 332ab2043b8SDevin Teske buffer = buffer" "$0 333ab2043b8SDevin Teske} 334ab2043b8SDevin TeskeEND { 335ab2043b8SDevin Teske # Clean up the buffer 336ab2043b8SDevin Teske sub(/^[[:space:]]*/, "", buffer) 337ab2043b8SDevin Teske sub(/[[:space:]]*$/, "", buffer) 338ab2043b8SDevin Teske 339ab2043b8SDevin Teske print buffer 340ab2043b8SDevin Teske exit ! found 341ab2043b8SDevin Teske} 342ab2043b8SDevin Teske' 343ab2043b8SDevin Teskef_sysrc_desc() 344ab2043b8SDevin Teske{ 345ab2043b8SDevin Teske awk -v varname="$1" "$f_sysrc_desc_awk" < "$RC_DEFAULTS" 346ab2043b8SDevin Teske} 347ab2043b8SDevin Teske 348ab2043b8SDevin Teske# f_sysrc_set $varname $new_value 349ab2043b8SDevin Teske# 350ab2043b8SDevin Teske# Change a setting in the system configuration files (edits the files in-place 351ab2043b8SDevin Teske# to change the value in the last assignment to the variable). If the variable 352ab2043b8SDevin Teske# does not appear in the source file, it is appended to the end of the primary 353ab2043b8SDevin Teske# system configuration file `/etc/rc.conf'. 354ab2043b8SDevin Teske# 355ab2043b8SDevin Teske# This function is a two-parter. Below is the awk(1) portion of the function, 356ab2043b8SDevin Teske# afterward is the sh(1) function which utilizes the below awk script. 357ab2043b8SDevin Teske# 358ab2043b8SDevin Teskef_sysrc_set_awk=' 359ab2043b8SDevin Teske# Variables that should be defined on the invocation line: 360ab2043b8SDevin Teske# -v varname="varname" 361ab2043b8SDevin Teske# -v new_value="new_value" 362ab2043b8SDevin Teske# 363ab2043b8SDevin TeskeBEGIN { 364ab2043b8SDevin Teske regex = "^[[:space:]]*"varname"=" 365ab2043b8SDevin Teske found = retval = 0 366ab2043b8SDevin Teske} 367ab2043b8SDevin Teske{ 368ab2043b8SDevin Teske # If already found... just spew 369ab2043b8SDevin Teske if ( found ) { print; next } 370ab2043b8SDevin Teske 371ab2043b8SDevin Teske # Does this line match an assignment to our variable? 372ab2043b8SDevin Teske if ( ! match($0, regex) ) { print; next } 373ab2043b8SDevin Teske 374ab2043b8SDevin Teske # Save important match information 375ab2043b8SDevin Teske found = 1 376ab2043b8SDevin Teske matchlen = RSTART + RLENGTH - 1 377ab2043b8SDevin Teske 378ab2043b8SDevin Teske # Store the value text for later munging 379ab2043b8SDevin Teske value = substr($0, matchlen + 1, length($0) - matchlen) 380ab2043b8SDevin Teske 381ab2043b8SDevin Teske # Store the first character of the value 382ab2043b8SDevin Teske t1 = t2 = substr(value, 0, 1) 383ab2043b8SDevin Teske 384ab2043b8SDevin Teske # Assignment w/ back-ticks, expression, or misc. 385ab2043b8SDevin Teske # We ignore these since we did not generate them 386ab2043b8SDevin Teske # 387ab2043b8SDevin Teske if ( t1 ~ /[`$\\]/ ) { retval = 1; print; next } 388ab2043b8SDevin Teske 389ab2043b8SDevin Teske # Assignment w/ single-quoted value 390ab2043b8SDevin Teske else if ( t1 == "'\''" ) { 391ab2043b8SDevin Teske sub(/^'\''[^'\'']*/, "", value) 392ab2043b8SDevin Teske if ( length(value) == 0 ) t2 = "" 393ab2043b8SDevin Teske sub(/^'\''/, "", value) 394ab2043b8SDevin Teske } 395ab2043b8SDevin Teske 396ab2043b8SDevin Teske # Assignment w/ double-quoted value 397ab2043b8SDevin Teske else if ( t1 == "\"" ) { 398ab2043b8SDevin Teske sub(/^"(.*\\\\+")*[^"]*/, "", value) 399ab2043b8SDevin Teske if ( length(value) == 0 ) t2 = "" 400ab2043b8SDevin Teske sub(/^"/, "", value) 401ab2043b8SDevin Teske } 402ab2043b8SDevin Teske 403ab2043b8SDevin Teske # Assignment w/ non-quoted value 404ab2043b8SDevin Teske else if ( t1 ~ /[^[:space:];]/ ) { 405ab2043b8SDevin Teske t1 = t2 = "\"" 406ab2043b8SDevin Teske sub(/^[^[:space:]]*/, "", value) 407ab2043b8SDevin Teske } 408ab2043b8SDevin Teske 409ab2043b8SDevin Teske # Null-assignment 410ab2043b8SDevin Teske else if ( t1 ~ /[[:space:];]/ ) { t1 = t2 = "\"" } 411ab2043b8SDevin Teske 412ab2043b8SDevin Teske printf "%s%c%s%c%s\n", substr($0, 0, matchlen), \ 413ab2043b8SDevin Teske t1, new_value, t2, value 414ab2043b8SDevin Teske} 415ab2043b8SDevin TeskeEND { exit retval } 416ab2043b8SDevin Teske' 417ab2043b8SDevin Teskef_sysrc_set() 418ab2043b8SDevin Teske{ 419ab2043b8SDevin Teske local varname="$1" new_value="$2" 420ab2043b8SDevin Teske 421ab2043b8SDevin Teske # Check arguments 422ab2043b8SDevin Teske [ "$varname" ] || return $FAILURE 423ab2043b8SDevin Teske 424ab2043b8SDevin Teske # 425ab2043b8SDevin Teske # Find which rc.conf(5) file contains the last-assignment 426ab2043b8SDevin Teske # 427ab2043b8SDevin Teske local not_found= 428ab2043b8SDevin Teske local file="$( f_sysrc_find "$varname" )" 429ab2043b8SDevin Teske if [ "$file" = "$RC_DEFAULTS" -o ! "$file" ]; then 430ab2043b8SDevin Teske # 431ab2043b8SDevin Teske # We either got a null response (not found) or the variable 432ab2043b8SDevin Teske # was only found in the rc.conf(5) defaults. In either case, 433ab2043b8SDevin Teske # let's instead modify the first file from $rc_conf_files. 434ab2043b8SDevin Teske # 435ab2043b8SDevin Teske 436ab2043b8SDevin Teske not_found=1 437ab2043b8SDevin Teske 438ab2043b8SDevin Teske # 439ab2043b8SDevin Teske # If RC_CONFS is defined, use $RC_CONFS 440ab2043b8SDevin Teske # rather than $rc_conf_files. 441ab2043b8SDevin Teske # 442ab2043b8SDevin Teske if [ "$RC_CONFS" ]; then 443ab2043b8SDevin Teske file="${RC_CONFS%%[$IFS]*}" 444ab2043b8SDevin Teske else 445ab2043b8SDevin Teske file=$( f_sysrc_get rc_conf_files ) 446ab2043b8SDevin Teske file="${file%%[$IFS]*}" 447ab2043b8SDevin Teske fi 448ab2043b8SDevin Teske fi 449ab2043b8SDevin Teske 450ab2043b8SDevin Teske # 451ab2043b8SDevin Teske # If not found, append new value to last file and return. 452ab2043b8SDevin Teske # 453ab2043b8SDevin Teske if [ "$not_found" ]; then 454ab2043b8SDevin Teske echo "$varname=\"$new_value\"" >> "$file" 455ab2043b8SDevin Teske return $? 456ab2043b8SDevin Teske fi 457ab2043b8SDevin Teske 458ab2043b8SDevin Teske # 459ab2043b8SDevin Teske # Perform sanity checks. 460ab2043b8SDevin Teske # 461ab2043b8SDevin Teske if [ ! -w "$file" ]; then 462ab2043b8SDevin Teske f_err "$msg_cannot_create_permission_denied\n" \ 463ab2043b8SDevin Teske "$pgm" "$file" 464ab2043b8SDevin Teske return $FAILURE 465ab2043b8SDevin Teske fi 466ab2043b8SDevin Teske 467ab2043b8SDevin Teske # 468ab2043b8SDevin Teske # Create a new temporary file to write to. 469ab2043b8SDevin Teske # 470ab2043b8SDevin Teske local tmpfile="$( mktemp -t "$pgm" )" 471ab2043b8SDevin Teske [ "$tmpfile" ] || return $FAILURE 472ab2043b8SDevin Teske 473ab2043b8SDevin Teske # 474ab2043b8SDevin Teske # Fixup permissions (else we're in for a surprise, as mktemp(1) creates 475ab2043b8SDevin Teske # the temporary file with 0600 permissions, and if we simply mv(1) the 476ab2043b8SDevin Teske # temporary file over the destination, the destination will inherit the 477ab2043b8SDevin Teske # permissions from the temporary file). 478ab2043b8SDevin Teske # 479ab2043b8SDevin Teske local mode 480*fb7d723eSDevin Teske mode=$( stat -f '%#Lp' "$file" 2> /dev/null ) 481ab2043b8SDevin Teske f_quietly chmod "${mode:-0644}" "$tmpfile" 482ab2043b8SDevin Teske 483ab2043b8SDevin Teske # 484ab2043b8SDevin Teske # Fixup ownership. The destination file _is_ writable (we tested 485ab2043b8SDevin Teske # earlier above). However, this will fail if we don't have sufficient 486ab2043b8SDevin Teske # permissions (so we throw stderr into the bit-bucket). 487ab2043b8SDevin Teske # 488ab2043b8SDevin Teske local owner 489*fb7d723eSDevin Teske owner=$( stat -f '%u:%g' "$file" 2> /dev/null ) 490ab2043b8SDevin Teske f_quietly chown "${owner:-root:wheel}" "$tmpfile" 491ab2043b8SDevin Teske 492ab2043b8SDevin Teske # 493ab2043b8SDevin Teske # Operate on the matching file, replacing only the last occurrence. 494ab2043b8SDevin Teske # 495ab2043b8SDevin Teske local new_contents retval 496*fb7d723eSDevin Teske new_contents=$( tail -r $file 2> /dev/null ) 497ab2043b8SDevin Teske new_contents=$( echo "$new_contents" | awk -v varname="$varname" \ 498ab2043b8SDevin Teske -v new_value="$new_value" "$f_sysrc_set_awk" ) 499ab2043b8SDevin Teske retval=$? 500ab2043b8SDevin Teske 501ab2043b8SDevin Teske # 502ab2043b8SDevin Teske # Write the temporary file contents. 503ab2043b8SDevin Teske # 504ab2043b8SDevin Teske echo "$new_contents" | tail -r > "$tmpfile" || return $FAILURE 505ab2043b8SDevin Teske if [ $retval -ne $SUCCESS ]; then 506ab2043b8SDevin Teske echo "$varname=\"$new_value\"" >> "$tmpfile" 507ab2043b8SDevin Teske fi 508ab2043b8SDevin Teske 509ab2043b8SDevin Teske # 510ab2043b8SDevin Teske # Taint-check our results. 511ab2043b8SDevin Teske # 512ab2043b8SDevin Teske if ! /bin/sh -n "$tmpfile"; then 513ab2043b8SDevin Teske f_err "$msg_previous_syntax_errors\n" "$pgm" "$file" 514ab2043b8SDevin Teske rm -f "$tmpfile" 515ab2043b8SDevin Teske return $FAILURE 516ab2043b8SDevin Teske fi 517ab2043b8SDevin Teske 518ab2043b8SDevin Teske # 519ab2043b8SDevin Teske # Finally, move the temporary file into place. 520ab2043b8SDevin Teske # 521ab2043b8SDevin Teske mv "$tmpfile" "$file" 522ab2043b8SDevin Teske} 523ab2043b8SDevin Teske 524ab2043b8SDevin Teske# f_sysrc_delete $varname 525ab2043b8SDevin Teske# 526ab2043b8SDevin Teske# Remove a setting from the system configuration files (edits files in-place). 527ab2043b8SDevin Teske# Deletes all assignments to the given variable in all config files. If the 528ab2043b8SDevin Teske# `-f file' option is passed, the removal is restricted to only those files 529ab2043b8SDevin Teske# specified, otherwise the system collection of rc_conf_files is used. 530ab2043b8SDevin Teske# 531ab2043b8SDevin Teske# This function is a two-parter. Below is the awk(1) portion of the function, 532ab2043b8SDevin Teske# afterward is the sh(1) function which utilizes the below awk script. 533ab2043b8SDevin Teske# 534ab2043b8SDevin Teskef_sysrc_delete_awk=' 535ab2043b8SDevin Teske# Variables that should be defined on the invocation line: 536ab2043b8SDevin Teske# -v varname="varname" 537ab2043b8SDevin Teske# 538ab2043b8SDevin TeskeBEGIN { 539ab2043b8SDevin Teske regex = "^[[:space:]]*"varname"=" 540ab2043b8SDevin Teske found = 0 541ab2043b8SDevin Teske} 542ab2043b8SDevin Teske{ 543ab2043b8SDevin Teske if ( $0 ~ regex ) 544ab2043b8SDevin Teske found = 1 545ab2043b8SDevin Teske else 546ab2043b8SDevin Teske print 547ab2043b8SDevin Teske} 548ab2043b8SDevin TeskeEND { exit ! found } 549ab2043b8SDevin Teske' 550ab2043b8SDevin Teskef_sysrc_delete() 551ab2043b8SDevin Teske{ 552ab2043b8SDevin Teske local varname="$1" 553ab2043b8SDevin Teske local file 554ab2043b8SDevin Teske 555ab2043b8SDevin Teske # Check arguments 556ab2043b8SDevin Teske [ "$varname" ] || return $FAILURE 557ab2043b8SDevin Teske 558ab2043b8SDevin Teske # 559ab2043b8SDevin Teske # Operate on each of the specified files 560ab2043b8SDevin Teske # 561ab2043b8SDevin Teske for file in ${RC_CONFS:-$( f_sysrc_get rc_conf_files )}; do 562ab2043b8SDevin Teske [ -e "$file" ] || continue 563ab2043b8SDevin Teske 564ab2043b8SDevin Teske # 565ab2043b8SDevin Teske # Create a new temporary file to write to. 566ab2043b8SDevin Teske # 567ab2043b8SDevin Teske local tmpfile="$( mktemp -t "$pgm" )" 568ab2043b8SDevin Teske [ "$tmpfile" ] || return $FAILURE 569ab2043b8SDevin Teske 570ab2043b8SDevin Teske # 571ab2043b8SDevin Teske # Fixup permissions and ownership (mktemp(1) defaults to 0600 572ab2043b8SDevin Teske # permissions) to instead match the destination file. 573ab2043b8SDevin Teske # 574ab2043b8SDevin Teske local mode owner 575*fb7d723eSDevin Teske mode=$( stat -f '%#Lp' "$file" 2> /dev/null ) 576*fb7d723eSDevin Teske owner=$( stat -f '%u:%g' "$file" 2> /dev/null ) 577ab2043b8SDevin Teske f_quietly chmod "${mode:-0644}" "$tmpfile" 578ab2043b8SDevin Teske f_quietly chown "${owner:-root:wheel}" "$tmpfile" 579ab2043b8SDevin Teske 580ab2043b8SDevin Teske # 581ab2043b8SDevin Teske # Operate on the file, removing all occurrences, saving the 582ab2043b8SDevin Teske # output in our temporary file. 583ab2043b8SDevin Teske # 584ab2043b8SDevin Teske awk -v varname="$varname" "$f_sysrc_delete_awk" "$file" \ 585ab2043b8SDevin Teske > "$tmpfile" 586ab2043b8SDevin Teske if [ $? -ne $SUCCESS ]; then 587ab2043b8SDevin Teske # The file didn't contain any assignments 588ab2043b8SDevin Teske rm -f "$tmpfile" 589ab2043b8SDevin Teske continue 590ab2043b8SDevin Teske fi 591ab2043b8SDevin Teske 592ab2043b8SDevin Teske # 593ab2043b8SDevin Teske # Taint-check our results. 594ab2043b8SDevin Teske # 595ab2043b8SDevin Teske if ! /bin/sh -n "$tmpfile"; then 596ab2043b8SDevin Teske f_err "$msg_previous_syntax_errors\n" \ 597ab2043b8SDevin Teske "$pgm" "$file" 598ab2043b8SDevin Teske rm -f "$tmpfile" 599ab2043b8SDevin Teske return $FAILURE 600ab2043b8SDevin Teske fi 601ab2043b8SDevin Teske 602ab2043b8SDevin Teske # 603ab2043b8SDevin Teske # Perform sanity checks 604ab2043b8SDevin Teske # 605ab2043b8SDevin Teske if [ ! -w "$file" ]; then 606ab2043b8SDevin Teske f_err "$msg_permission_denied\n" "$pgm" "$file" 607ab2043b8SDevin Teske rm -f "$tmpfile" 608ab2043b8SDevin Teske return $FAILURE 609ab2043b8SDevin Teske fi 610ab2043b8SDevin Teske 611ab2043b8SDevin Teske # 612ab2043b8SDevin Teske # Finally, move the temporary file into place. 613ab2043b8SDevin Teske # 614ab2043b8SDevin Teske mv "$tmpfile" "$file" 615ab2043b8SDevin Teske done 616ab2043b8SDevin Teske} 617ab2043b8SDevin Teske 618ab2043b8SDevin Teskefi # ! $_SYSRC_SUBR 619