sysrc.subr revision 241149
1238438Sdteskeif [ ! "$_SYSRC_SUBR" ]; then _SYSRC_SUBR=1 2238438Sdteske# 3238438Sdteske# Copyright (c) 2006-2012 Devin Teske 4238438Sdteske# All Rights Reserved. 5238438Sdteske# 6238438Sdteske# Redistribution and use in source and binary forms, with or without 7238438Sdteske# modification, are permitted provided that the following conditions 8238438Sdteske# are met: 9238438Sdteske# 1. Redistributions of source code must retain the above copyright 10238438Sdteske# notice, this list of conditions and the following disclaimer. 11238438Sdteske# 2. Redistributions in binary form must reproduce the above copyright 12238438Sdteske# notice, this list of conditions and the following disclaimer in the 13238438Sdteske# documentation and/or other materials provided with the distribution. 14238438Sdteske# 15238438Sdteske# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16238438Sdteske# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, THE 17238438Sdteske# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18238438Sdteske# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19238438Sdteske# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20240797Sdteske# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21238438Sdteske# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22238438Sdteske# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23238438Sdteske# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24238438Sdteske# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25238438Sdteske# SUCH DAMAGE. 26238438Sdteske# 27238438Sdteske# $FreeBSD: head/usr.sbin/bsdconfig/share/sysrc.subr 241149 2012-10-03 02:32:47Z dteske $ 28238438Sdteske# 29238438Sdteske############################################################ INCLUDES 30238438Sdteske 31240684SdteskeBSDCFG_SHARE="/usr/share/bsdconfig" 32241149Sdteske[ "$_COMMON_SUBR" ] || . $BSDCFG_SHARE/common.subr || exit 1 33240684Sdteske 34238438SdteskeBSDCFG_LIBE="/usr/libexec/bsdconfig" 35241149Sdteske[ ! "$_SYSRC_JAILED" ] && f_include_lang $BSDCFG_LIBE/include/messages.subr 36238438Sdteske 37238438Sdteske############################################################ CONFIGURATION 38238438Sdteske 39238438Sdteske# 40238438Sdteske# Standard pathnames (inherit values from shell if available) 41238438Sdteske# 42238438Sdteske: ${RC_DEFAULTS:="/etc/defaults/rc.conf"} 43238438Sdteske 44238438Sdteske############################################################ GLOBALS 45238438Sdteske 46238438Sdteske# 47238438Sdteske# Global exit status variables 48238438Sdteske# 49238438SdteskeSUCCESS=0 50238438SdteskeFAILURE=1 51238438Sdteske 52241019Sdteske# 53241019Sdteske# Valid characters that can appear in an sh(1) variable name 54241019Sdteske# 55241019Sdteske# Please note that the character ranges A-Z and a-z should be avoided because 56241019Sdteske# these can include accent characters (which are not valid in a variable name). 57241019Sdteske# For example, A-Z matches any character that sorts after A but before Z, 58241019Sdteske# including A and Z. Although ASCII order would make more sense, that is not 59241019Sdteske# how it works. 60241019Sdteske# 61241019SdteskeVALID_VARNAME_CHARS="0-9ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_" 62241019Sdteske 63238438Sdteske############################################################ FUNCTIONS 64238438Sdteske 65238438Sdteske# f_clean_env [ --except $varname ... ] 66238438Sdteske# 67238438Sdteske# Unset all environment variables in the current scope. An optional list of 68238438Sdteske# arguments can be passed, indicating which variables to avoid unsetting; the 69238438Sdteske# `--except' is required to enable the exclusion-list as the remainder of 70238438Sdteske# positional arguments. 71238438Sdteske# 72238438Sdteske# Be careful not to call this in a shell that you still expect to perform 73238438Sdteske# $PATH expansion in, because this will blow $PATH away. This is best used 74238438Sdteske# within a sub-shell block "(...)" or "$(...)" or "`...`". 75238438Sdteske# 76238438Sdteskef_clean_env() 77238438Sdteske{ 78238438Sdteske local var arg except= 79238438Sdteske 80238438Sdteske # 81238438Sdteske # Should we process an exclusion-list? 82238438Sdteske # 83238438Sdteske if [ "$1" = "--except" ]; then 84238438Sdteske except=1 85238438Sdteske shift 1 86238438Sdteske fi 87238438Sdteske 88238438Sdteske # 89238438Sdteske # Loop over a list of variable names from set(1) built-in. 90238438Sdteske # 91238438Sdteske for var in $( set | awk -F= \ 92238438Sdteske '/^[[:alpha:]_][[:alnum:]_]*=/ {print $1}' \ 93238438Sdteske | grep -v '^except$' 94238438Sdteske ); do 95238438Sdteske # 96238438Sdteske # In POSIX bourne-shell, attempting to unset(1) OPTIND results 97238438Sdteske # in "unset: Illegal number:" and causes abrupt termination. 98238438Sdteske # 99238438Sdteske [ "$var" = OPTIND ] && continue 100238438Sdteske 101238438Sdteske # 102238438Sdteske # Process the exclusion-list? 103238438Sdteske # 104238438Sdteske if [ "$except" ]; then 105238438Sdteske for arg in "$@" ""; do 106238438Sdteske [ "$var" = "$arg" ] && break 107238438Sdteske done 108238438Sdteske [ "$arg" ] && continue 109238438Sdteske fi 110238438Sdteske 111238438Sdteske unset "$var" 112238438Sdteske done 113238438Sdteske} 114238438Sdteske 115238438Sdteske# f_sysrc_get $varname 116238438Sdteske# 117238438Sdteske# Get a system configuration setting from the collection of system- 118238438Sdteske# configuration files (in order: /etc/defaults/rc.conf /etc/rc.conf 119238438Sdteske# and /etc/rc.conf). 120238438Sdteske# 121238438Sdteske# NOTE: Additional shell parameter-expansion formats are supported. For 122238438Sdteske# example, passing an argument of "hostname%%.*" (properly quoted) will 123238438Sdteske# return the hostname up to (but not including) the first `.' (see sh(1), 124238438Sdteske# "Parameter Expansion" for more information on additional formats). 125238438Sdteske# 126238438Sdteskef_sysrc_get() 127238438Sdteske{ 128238438Sdteske # Sanity check 129238438Sdteske [ -f "$RC_DEFAULTS" -a -r "$RC_DEFAULTS" ] || return $FAILURE 130238438Sdteske 131238438Sdteske # Taint-check variable name 132238438Sdteske case "$1" in 133238438Sdteske [0-9]*) 134238438Sdteske # Don't expand possible positional parameters 135238438Sdteske return $FAILURE;; 136238438Sdteske *) 137238438Sdteske [ "$1" ] || return $FAILURE 138238438Sdteske esac 139238438Sdteske 140238438Sdteske ( # Execute within sub-shell to protect parent environment 141238438Sdteske 142238438Sdteske # 143238438Sdteske # Clear the environment of all variables, preventing the 144238438Sdteske # expansion of normals such as `PS1', `TERM', etc. 145238438Sdteske # 146241042Sdteske f_clean_env --except IFS RC_CONFS RC_DEFAULTS 147238438Sdteske 148240783Sdteske . "$RC_DEFAULTS" > /dev/null 2>&1 149238438Sdteske 150238438Sdteske unset RC_DEFAULTS 151238438Sdteske # no longer needed 152238438Sdteske 153238438Sdteske # 154238438Sdteske # If the query is for `rc_conf_files' then store the value that 155238438Sdteske # we inherited from sourcing RC_DEFAULTS (above) so that we may 156238438Sdteske # conditionally restore this value after source_rc_confs in the 157238438Sdteske # event that RC_CONFS does not customize the value. 158238438Sdteske # 159238438Sdteske if [ "$1" = "rc_conf_files" ]; then 160238438Sdteske _rc_conf_files="$rc_conf_files" 161238438Sdteske fi 162238438Sdteske 163238438Sdteske # 164238438Sdteske # If RC_CONFS is defined, set $rc_conf_files to an explicit 165238438Sdteske # value, modifying the default behavior of source_rc_confs(). 166238438Sdteske # 167240798Sdteske if [ "${RC_CONFS+set}" ]; then 168238438Sdteske rc_conf_files="$RC_CONFS" 169238438Sdteske _rc_confs_set=1 170238438Sdteske fi 171238438Sdteske 172240783Sdteske source_rc_confs > /dev/null 2>&1 173238438Sdteske 174238438Sdteske # 175238438Sdteske # If the query was for `rc_conf_files' AND after calling 176240797Sdteske # source_rc_confs the value has not changed, then we should 177238438Sdteske # restore the value to the one inherited from RC_DEFAULTS 178238438Sdteske # before performing the final query (preventing us from 179238438Sdteske # returning what was set via RC_CONFS when the intent was 180238438Sdteske # instead to query the value from the file(s) specified). 181238438Sdteske # 182238438Sdteske if [ "$1" = "rc_conf_files" -a \ 183238438Sdteske "$_rc_confs_set" -a \ 184238438Sdteske "$rc_conf_files" = "$RC_CONFS" \ 185238438Sdteske ]; then 186238438Sdteske rc_conf_files="$_rc_conf_files" 187238438Sdteske unset _rc_conf_files 188238438Sdteske unset _rc_confs_set 189238438Sdteske fi 190238438Sdteske 191238438Sdteske unset RC_CONFS 192238438Sdteske # no longer needed 193238438Sdteske 194238438Sdteske # 195238438Sdteske # This must be the last functional line for both the sub-shell 196238438Sdteske # and the function to preserve the return status from formats 197238438Sdteske # such as "${varname?}" and "${varname:?}" (see "Parameter 198238438Sdteske # Expansion" in sh(1) for more information). 199238438Sdteske # 200240783Sdteske eval echo '"${'"$1"'}"' 2> /dev/null 201238438Sdteske ) 202238438Sdteske} 203238438Sdteske 204238438Sdteske# f_sysrc_get_default $varname 205238438Sdteske# 206238438Sdteske# Get a system configuration default setting from the default rc.conf(5) file 207238438Sdteske# (or whatever RC_DEFAULTS points at). 208238438Sdteske# 209238438Sdteskef_sysrc_get_default() 210238438Sdteske{ 211238438Sdteske # Sanity check 212238438Sdteske [ -f "$RC_DEFAULTS" -a -r "$RC_DEFAULTS" ] || return $FAILURE 213238438Sdteske 214238438Sdteske # Taint-check variable name 215238438Sdteske case "$1" in 216238438Sdteske [0-9]*) 217238438Sdteske # Don't expand possible positional parameters 218238438Sdteske return $FAILURE;; 219238438Sdteske *) 220238438Sdteske [ "$1" ] || return $FAILURE 221238438Sdteske esac 222238438Sdteske 223238438Sdteske ( # Execute within sub-shell to protect parent environment 224238438Sdteske 225238438Sdteske # 226238438Sdteske # Clear the environment of all variables, preventing the 227238438Sdteske # expansion of normals such as `PS1', `TERM', etc. 228238438Sdteske # 229238438Sdteske f_clean_env --except RC_DEFAULTS 230238438Sdteske 231240783Sdteske . "$RC_DEFAULTS" > /dev/null 2>&1 232238438Sdteske 233238438Sdteske unset RC_DEFAULTS 234238438Sdteske # no longer needed 235238438Sdteske 236238438Sdteske # 237238438Sdteske # This must be the last functional line for both the sub-shell 238238438Sdteske # and the function to preserve the return status from formats 239238438Sdteske # such as "${varname?}" and "${varname:?}" (see "Parameter 240238438Sdteske # Expansion" in sh(1) for more information). 241238438Sdteske # 242240783Sdteske eval echo '"${'"$1"'}"' 2> /dev/null 243238438Sdteske ) 244238438Sdteske} 245238438Sdteske 246238438Sdteske# f_sysrc_find $varname 247238438Sdteske# 248238438Sdteske# Find which file holds the effective last-assignment to a given variable 249238438Sdteske# within the rc.conf(5) file(s). 250238438Sdteske# 251238438Sdteske# If the variable is found in any of the rc.conf(5) files, the function prints 252238438Sdteske# the filename it was found in and then returns success. Otherwise output is 253238438Sdteske# NULL and the function returns with error status. 254238438Sdteske# 255238438Sdteskef_sysrc_find() 256238438Sdteske{ 257241019Sdteske local varname="${1%%[!$VALID_VARNAME_CHARS]*}" 258238438Sdteske local regex="^[[:space:]]*$varname=" 259238438Sdteske local rc_conf_files="$( f_sysrc_get rc_conf_files )" 260238438Sdteske local conf_files= 261238438Sdteske local file 262238438Sdteske 263238438Sdteske # Check parameters 264241019Sdteske case "$varname" in 265241019Sdteske ""|[0-9]*) return $FAILURE 266241019Sdteske esac 267238438Sdteske 268238438Sdteske # 269238438Sdteske # If RC_CONFS is defined, set $rc_conf_files to an explicit 270238438Sdteske # value, modifying the default behavior of source_rc_confs(). 271238438Sdteske # 272240863Sdteske [ "${RC_CONFS+set}" ] && rc_conf_files="$RC_CONFS" 273238438Sdteske 274238438Sdteske # 275238438Sdteske # Reverse the order of files in rc_conf_files (the boot process sources 276238438Sdteske # these in order, so we will search them in reverse-order to find the 277238438Sdteske # last-assignment -- the one that ultimately effects the environment). 278238438Sdteske # 279238438Sdteske for file in $rc_conf_files; do 280238438Sdteske conf_files="$file${conf_files:+ }$conf_files" 281238438Sdteske done 282238438Sdteske 283238438Sdteske # 284238438Sdteske # Append the defaults file (since directives in the defaults file 285238438Sdteske # indeed affect the boot process, we'll want to know when a directive 286238438Sdteske # is found there). 287238438Sdteske # 288238438Sdteske conf_files="$conf_files${conf_files:+ }$RC_DEFAULTS" 289238438Sdteske 290238438Sdteske # 291238438Sdteske # Find which file matches assignment to the given variable name. 292238438Sdteske # 293238438Sdteske for file in $conf_files; do 294238438Sdteske [ -f "$file" -a -r "$file" ] || continue 295238438Sdteske if grep -Eq "$regex" $file; then 296238438Sdteske echo $file 297238438Sdteske return $SUCCESS 298238438Sdteske fi 299238438Sdteske done 300238438Sdteske 301238438Sdteske return $FAILURE # Not found 302238438Sdteske} 303238438Sdteske 304238438Sdteske# f_sysrc_desc $varname 305238438Sdteske# 306238438Sdteske# Attempts to return the comments associated with varname from the rc.conf(5) 307238438Sdteske# defaults file `/etc/defaults/rc.conf' (or whatever RC_DEFAULTS points to). 308238438Sdteske# 309238438Sdteske# Multi-line comments are joined together. Results are NULL if no description 310238438Sdteske# could be found. 311238438Sdteske# 312238438Sdteske# This function is a two-parter. Below is the awk(1) portion of the function, 313238438Sdteske# afterward is the sh(1) function which utilizes the below awk script. 314238438Sdteske# 315238438Sdteskef_sysrc_desc_awk=' 316238438Sdteske# Variables that should be defined on the invocation line: 317238438Sdteske# -v varname="varname" 318238438Sdteske# 319238438SdteskeBEGIN { 320238438Sdteske regex = "^[[:space:]]*"varname"=" 321238438Sdteske found = 0 322238438Sdteske buffer = "" 323238438Sdteske} 324238438Sdteske{ 325238438Sdteske if ( ! found ) 326238438Sdteske { 327238438Sdteske if ( ! match($0, regex) ) next 328238438Sdteske 329238438Sdteske found = 1 330238438Sdteske sub(/^[^#]*(#[[:space:]]*)?/, "") 331238438Sdteske buffer = $0 332238438Sdteske next 333238438Sdteske } 334238438Sdteske 335238438Sdteske if ( !/^[[:space:]]*#/ || 336238438Sdteske /^[[:space:]]*[[:alpha:]_][[:alnum:]_]*=/ || 337238438Sdteske /^[[:space:]]*#[[:alpha:]_][[:alnum:]_]*=/ || 338238438Sdteske /^[[:space:]]*$/ ) exit 339238438Sdteske 340238438Sdteske sub(/(.*#)*[[:space:]]*/, "") 341238438Sdteske buffer = buffer" "$0 342238438Sdteske} 343238438SdteskeEND { 344238438Sdteske # Clean up the buffer 345238438Sdteske sub(/^[[:space:]]*/, "", buffer) 346238438Sdteske sub(/[[:space:]]*$/, "", buffer) 347238438Sdteske 348238438Sdteske print buffer 349238438Sdteske exit ! found 350238438Sdteske} 351238438Sdteske' 352238438Sdteskef_sysrc_desc() 353238438Sdteske{ 354238438Sdteske awk -v varname="$1" "$f_sysrc_desc_awk" < "$RC_DEFAULTS" 355238438Sdteske} 356238438Sdteske 357238438Sdteske# f_sysrc_set $varname $new_value 358238438Sdteske# 359238438Sdteske# Change a setting in the system configuration files (edits the files in-place 360238438Sdteske# to change the value in the last assignment to the variable). If the variable 361238438Sdteske# does not appear in the source file, it is appended to the end of the primary 362238438Sdteske# system configuration file `/etc/rc.conf'. 363238438Sdteske# 364238438Sdteske# This function is a two-parter. Below is the awk(1) portion of the function, 365238438Sdteske# afterward is the sh(1) function which utilizes the below awk script. 366238438Sdteske# 367238438Sdteskef_sysrc_set_awk=' 368238438Sdteske# Variables that should be defined on the invocation line: 369238438Sdteske# -v varname="varname" 370238438Sdteske# -v new_value="new_value" 371238438Sdteske# 372238438SdteskeBEGIN { 373238438Sdteske regex = "^[[:space:]]*"varname"=" 374238438Sdteske found = retval = 0 375238438Sdteske} 376238438Sdteske{ 377238438Sdteske # If already found... just spew 378238438Sdteske if ( found ) { print; next } 379238438Sdteske 380238438Sdteske # Does this line match an assignment to our variable? 381238438Sdteske if ( ! match($0, regex) ) { print; next } 382238438Sdteske 383238438Sdteske # Save important match information 384238438Sdteske found = 1 385238438Sdteske matchlen = RSTART + RLENGTH - 1 386238438Sdteske 387238438Sdteske # Store the value text for later munging 388238438Sdteske value = substr($0, matchlen + 1, length($0) - matchlen) 389238438Sdteske 390238438Sdteske # Store the first character of the value 391238438Sdteske t1 = t2 = substr(value, 0, 1) 392238438Sdteske 393238438Sdteske # Assignment w/ back-ticks, expression, or misc. 394238438Sdteske # We ignore these since we did not generate them 395238438Sdteske # 396238438Sdteske if ( t1 ~ /[`$\\]/ ) { retval = 1; print; next } 397238438Sdteske 398238438Sdteske # Assignment w/ single-quoted value 399238438Sdteske else if ( t1 == "'\''" ) { 400238438Sdteske sub(/^'\''[^'\'']*/, "", value) 401238438Sdteske if ( length(value) == 0 ) t2 = "" 402238438Sdteske sub(/^'\''/, "", value) 403238438Sdteske } 404238438Sdteske 405238438Sdteske # Assignment w/ double-quoted value 406238438Sdteske else if ( t1 == "\"" ) { 407238438Sdteske sub(/^"(.*\\\\+")*[^"]*/, "", value) 408238438Sdteske if ( length(value) == 0 ) t2 = "" 409238438Sdteske sub(/^"/, "", value) 410238438Sdteske } 411238438Sdteske 412238438Sdteske # Assignment w/ non-quoted value 413238438Sdteske else if ( t1 ~ /[^[:space:];]/ ) { 414238438Sdteske t1 = t2 = "\"" 415238438Sdteske sub(/^[^[:space:]]*/, "", value) 416238438Sdteske } 417238438Sdteske 418238438Sdteske # Null-assignment 419238438Sdteske else if ( t1 ~ /[[:space:];]/ ) { t1 = t2 = "\"" } 420238438Sdteske 421238438Sdteske printf "%s%c%s%c%s\n", substr($0, 0, matchlen), \ 422238438Sdteske t1, new_value, t2, value 423238438Sdteske} 424238438SdteskeEND { exit retval } 425238438Sdteske' 426238438Sdteskef_sysrc_set() 427238438Sdteske{ 428238438Sdteske local varname="$1" new_value="$2" 429238438Sdteske 430238438Sdteske # Check arguments 431238438Sdteske [ "$varname" ] || return $FAILURE 432238438Sdteske 433238438Sdteske # 434238438Sdteske # Find which rc.conf(5) file contains the last-assignment 435238438Sdteske # 436238438Sdteske local not_found= 437238438Sdteske local file="$( f_sysrc_find "$varname" )" 438238438Sdteske if [ "$file" = "$RC_DEFAULTS" -o ! "$file" ]; then 439238438Sdteske # 440238438Sdteske # We either got a null response (not found) or the variable 441238438Sdteske # was only found in the rc.conf(5) defaults. In either case, 442238438Sdteske # let's instead modify the first file from $rc_conf_files. 443238438Sdteske # 444238438Sdteske 445238438Sdteske not_found=1 446238438Sdteske 447238438Sdteske # 448238438Sdteske # If RC_CONFS is defined, use $RC_CONFS 449238438Sdteske # rather than $rc_conf_files. 450238438Sdteske # 451240863Sdteske if [ "${RC_CONFS+set}" ]; then 452238438Sdteske file="${RC_CONFS%%[$IFS]*}" 453238438Sdteske else 454241042Sdteske file=$( f_sysrc_get 'rc_conf_files%%[$IFS]*' ) 455238438Sdteske fi 456238438Sdteske fi 457238438Sdteske 458238438Sdteske # 459238438Sdteske # If not found, append new value to last file and return. 460238438Sdteske # 461238438Sdteske if [ "$not_found" ]; then 462238438Sdteske echo "$varname=\"$new_value\"" >> "$file" 463238438Sdteske return $? 464238438Sdteske fi 465238438Sdteske 466238438Sdteske # 467238438Sdteske # Perform sanity checks. 468238438Sdteske # 469238438Sdteske if [ ! -w "$file" ]; then 470238438Sdteske f_err "$msg_cannot_create_permission_denied\n" \ 471238438Sdteske "$pgm" "$file" 472238438Sdteske return $FAILURE 473238438Sdteske fi 474238438Sdteske 475238438Sdteske # 476238438Sdteske # Create a new temporary file to write to. 477238438Sdteske # 478238438Sdteske local tmpfile="$( mktemp -t "$pgm" )" 479238438Sdteske [ "$tmpfile" ] || return $FAILURE 480238438Sdteske 481238438Sdteske # 482238438Sdteske # Fixup permissions (else we're in for a surprise, as mktemp(1) creates 483238438Sdteske # the temporary file with 0600 permissions, and if we simply mv(1) the 484238438Sdteske # temporary file over the destination, the destination will inherit the 485238438Sdteske # permissions from the temporary file). 486238438Sdteske # 487238438Sdteske local mode 488240783Sdteske mode=$( stat -f '%#Lp' "$file" 2> /dev/null ) 489238438Sdteske f_quietly chmod "${mode:-0644}" "$tmpfile" 490238438Sdteske 491238438Sdteske # 492238438Sdteske # Fixup ownership. The destination file _is_ writable (we tested 493238438Sdteske # earlier above). However, this will fail if we don't have sufficient 494238438Sdteske # permissions (so we throw stderr into the bit-bucket). 495238438Sdteske # 496238438Sdteske local owner 497240783Sdteske owner=$( stat -f '%u:%g' "$file" 2> /dev/null ) 498238438Sdteske f_quietly chown "${owner:-root:wheel}" "$tmpfile" 499238438Sdteske 500238438Sdteske # 501238438Sdteske # Operate on the matching file, replacing only the last occurrence. 502238438Sdteske # 503238438Sdteske local new_contents retval 504240783Sdteske new_contents=$( tail -r $file 2> /dev/null ) 505238438Sdteske new_contents=$( echo "$new_contents" | awk -v varname="$varname" \ 506238438Sdteske -v new_value="$new_value" "$f_sysrc_set_awk" ) 507238438Sdteske retval=$? 508238438Sdteske 509238438Sdteske # 510238438Sdteske # Write the temporary file contents. 511238438Sdteske # 512238438Sdteske echo "$new_contents" | tail -r > "$tmpfile" || return $FAILURE 513238438Sdteske if [ $retval -ne $SUCCESS ]; then 514238438Sdteske echo "$varname=\"$new_value\"" >> "$tmpfile" 515238438Sdteske fi 516238438Sdteske 517238438Sdteske # 518238438Sdteske # Taint-check our results. 519238438Sdteske # 520238438Sdteske if ! /bin/sh -n "$tmpfile"; then 521238438Sdteske f_err "$msg_previous_syntax_errors\n" "$pgm" "$file" 522238438Sdteske rm -f "$tmpfile" 523238438Sdteske return $FAILURE 524238438Sdteske fi 525238438Sdteske 526238438Sdteske # 527238438Sdteske # Finally, move the temporary file into place. 528238438Sdteske # 529238438Sdteske mv "$tmpfile" "$file" 530238438Sdteske} 531238438Sdteske 532238438Sdteske# f_sysrc_delete $varname 533238438Sdteske# 534238438Sdteske# Remove a setting from the system configuration files (edits files in-place). 535238438Sdteske# Deletes all assignments to the given variable in all config files. If the 536238438Sdteske# `-f file' option is passed, the removal is restricted to only those files 537238438Sdteske# specified, otherwise the system collection of rc_conf_files is used. 538238438Sdteske# 539238438Sdteske# This function is a two-parter. Below is the awk(1) portion of the function, 540238438Sdteske# afterward is the sh(1) function which utilizes the below awk script. 541238438Sdteske# 542238438Sdteskef_sysrc_delete_awk=' 543238438Sdteske# Variables that should be defined on the invocation line: 544238438Sdteske# -v varname="varname" 545238438Sdteske# 546238438SdteskeBEGIN { 547238438Sdteske regex = "^[[:space:]]*"varname"=" 548238438Sdteske found = 0 549238438Sdteske} 550238438Sdteske{ 551238438Sdteske if ( $0 ~ regex ) 552238438Sdteske found = 1 553238438Sdteske else 554238438Sdteske print 555238438Sdteske} 556238438SdteskeEND { exit ! found } 557238438Sdteske' 558238438Sdteskef_sysrc_delete() 559238438Sdteske{ 560238438Sdteske local varname="$1" 561238438Sdteske local file 562238438Sdteske 563238438Sdteske # Check arguments 564238438Sdteske [ "$varname" ] || return $FAILURE 565238438Sdteske 566238438Sdteske # 567238438Sdteske # Operate on each of the specified files 568238438Sdteske # 569240863Sdteske for file in ${RC_CONFS-$( f_sysrc_get rc_conf_files )}; do 570238438Sdteske [ -e "$file" ] || continue 571238438Sdteske 572238438Sdteske # 573238438Sdteske # Create a new temporary file to write to. 574238438Sdteske # 575238438Sdteske local tmpfile="$( mktemp -t "$pgm" )" 576238438Sdteske [ "$tmpfile" ] || return $FAILURE 577238438Sdteske 578238438Sdteske # 579238438Sdteske # Fixup permissions and ownership (mktemp(1) defaults to 0600 580238438Sdteske # permissions) to instead match the destination file. 581238438Sdteske # 582238438Sdteske local mode owner 583240783Sdteske mode=$( stat -f '%#Lp' "$file" 2> /dev/null ) 584240783Sdteske owner=$( stat -f '%u:%g' "$file" 2> /dev/null ) 585238438Sdteske f_quietly chmod "${mode:-0644}" "$tmpfile" 586238438Sdteske f_quietly chown "${owner:-root:wheel}" "$tmpfile" 587238438Sdteske 588238438Sdteske # 589238438Sdteske # Operate on the file, removing all occurrences, saving the 590238438Sdteske # output in our temporary file. 591238438Sdteske # 592238438Sdteske awk -v varname="$varname" "$f_sysrc_delete_awk" "$file" \ 593238438Sdteske > "$tmpfile" 594238438Sdteske if [ $? -ne $SUCCESS ]; then 595238438Sdteske # The file didn't contain any assignments 596238438Sdteske rm -f "$tmpfile" 597238438Sdteske continue 598238438Sdteske fi 599238438Sdteske 600238438Sdteske # 601238438Sdteske # Taint-check our results. 602238438Sdteske # 603238438Sdteske if ! /bin/sh -n "$tmpfile"; then 604238438Sdteske f_err "$msg_previous_syntax_errors\n" \ 605238438Sdteske "$pgm" "$file" 606238438Sdteske rm -f "$tmpfile" 607238438Sdteske return $FAILURE 608238438Sdteske fi 609238438Sdteske 610238438Sdteske # 611238438Sdteske # Perform sanity checks 612238438Sdteske # 613238438Sdteske if [ ! -w "$file" ]; then 614238438Sdteske f_err "$msg_permission_denied\n" "$pgm" "$file" 615238438Sdteske rm -f "$tmpfile" 616238438Sdteske return $FAILURE 617238438Sdteske fi 618238438Sdteske 619238438Sdteske # 620238438Sdteske # Finally, move the temporary file into place. 621238438Sdteske # 622238438Sdteske mv "$tmpfile" "$file" 623238438Sdteske done 624238438Sdteske} 625238438Sdteske 626238438Sdteskefi # ! $_SYSRC_SUBR 627