sysrc.subr revision 240783
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 20238438Sdteske# DAMAGES (INLUDING, 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 240783 2012-09-21 19:03:25Z dteske $ 28238438Sdteske# 29238438Sdteske############################################################ INCLUDES 30238438Sdteske 31240684SdteskeBSDCFG_SHARE="/usr/share/bsdconfig" 32240684Sdteske. $BSDCFG_SHARE/common.subr || exit 1 33240684Sdteske 34238438SdteskeBSDCFG_LIBE="/usr/libexec/bsdconfig" 35238438Sdteskef_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 52238438Sdteske############################################################ FUNCTIONS 53238438Sdteske 54238438Sdteske# f_clean_env [ --except $varname ... ] 55238438Sdteske# 56238438Sdteske# Unset all environment variables in the current scope. An optional list of 57238438Sdteske# arguments can be passed, indicating which variables to avoid unsetting; the 58238438Sdteske# `--except' is required to enable the exclusion-list as the remainder of 59238438Sdteske# positional arguments. 60238438Sdteske# 61238438Sdteske# Be careful not to call this in a shell that you still expect to perform 62238438Sdteske# $PATH expansion in, because this will blow $PATH away. This is best used 63238438Sdteske# within a sub-shell block "(...)" or "$(...)" or "`...`". 64238438Sdteske# 65238438Sdteskef_clean_env() 66238438Sdteske{ 67238438Sdteske local var arg except= 68238438Sdteske 69238438Sdteske # 70238438Sdteske # Should we process an exclusion-list? 71238438Sdteske # 72238438Sdteske if [ "$1" = "--except" ]; then 73238438Sdteske except=1 74238438Sdteske shift 1 75238438Sdteske fi 76238438Sdteske 77238438Sdteske # 78238438Sdteske # Loop over a list of variable names from set(1) built-in. 79238438Sdteske # 80238438Sdteske for var in $( set | awk -F= \ 81238438Sdteske '/^[[:alpha:]_][[:alnum:]_]*=/ {print $1}' \ 82238438Sdteske | grep -v '^except$' 83238438Sdteske ); do 84238438Sdteske # 85238438Sdteske # In POSIX bourne-shell, attempting to unset(1) OPTIND results 86238438Sdteske # in "unset: Illegal number:" and causes abrupt termination. 87238438Sdteske # 88238438Sdteske [ "$var" = OPTIND ] && continue 89238438Sdteske 90238438Sdteske # 91238438Sdteske # Process the exclusion-list? 92238438Sdteske # 93238438Sdteske if [ "$except" ]; then 94238438Sdteske for arg in "$@" ""; do 95238438Sdteske [ "$var" = "$arg" ] && break 96238438Sdteske done 97238438Sdteske [ "$arg" ] && continue 98238438Sdteske fi 99238438Sdteske 100238438Sdteske unset "$var" 101238438Sdteske done 102238438Sdteske} 103238438Sdteske 104238438Sdteske# f_sysrc_get $varname 105238438Sdteske# 106238438Sdteske# Get a system configuration setting from the collection of system- 107238438Sdteske# configuration files (in order: /etc/defaults/rc.conf /etc/rc.conf 108238438Sdteske# and /etc/rc.conf). 109238438Sdteske# 110238438Sdteske# NOTE: Additional shell parameter-expansion formats are supported. For 111238438Sdteske# example, passing an argument of "hostname%%.*" (properly quoted) will 112238438Sdteske# return the hostname up to (but not including) the first `.' (see sh(1), 113238438Sdteske# "Parameter Expansion" for more information on additional formats). 114238438Sdteske# 115238438Sdteskef_sysrc_get() 116238438Sdteske{ 117238438Sdteske # Sanity check 118238438Sdteske [ -f "$RC_DEFAULTS" -a -r "$RC_DEFAULTS" ] || return $FAILURE 119238438Sdteske 120238438Sdteske # Taint-check variable name 121238438Sdteske case "$1" in 122238438Sdteske [0-9]*) 123238438Sdteske # Don't expand possible positional parameters 124238438Sdteske return $FAILURE;; 125238438Sdteske *) 126238438Sdteske [ "$1" ] || return $FAILURE 127238438Sdteske esac 128238438Sdteske 129238438Sdteske ( # Execute within sub-shell to protect parent environment 130238438Sdteske 131238438Sdteske # 132238438Sdteske # Clear the environment of all variables, preventing the 133238438Sdteske # expansion of normals such as `PS1', `TERM', etc. 134238438Sdteske # 135238438Sdteske f_clean_env --except RC_CONFS RC_DEFAULTS SUCCESS 136238438Sdteske 137240783Sdteske . "$RC_DEFAULTS" > /dev/null 2>&1 138238438Sdteske 139238438Sdteske unset RC_DEFAULTS 140238438Sdteske # no longer needed 141238438Sdteske 142238438Sdteske # 143238438Sdteske # If the query is for `rc_conf_files' then store the value that 144238438Sdteske # we inherited from sourcing RC_DEFAULTS (above) so that we may 145238438Sdteske # conditionally restore this value after source_rc_confs in the 146238438Sdteske # event that RC_CONFS does not customize the value. 147238438Sdteske # 148238438Sdteske if [ "$1" = "rc_conf_files" ]; then 149238438Sdteske _rc_conf_files="$rc_conf_files" 150238438Sdteske fi 151238438Sdteske 152238438Sdteske # 153238438Sdteske # If RC_CONFS is defined, set $rc_conf_files to an explicit 154238438Sdteske # value, modifying the default behavior of source_rc_confs(). 155238438Sdteske # 156240783Sdteske ( : ${RC_CONFS?} ) > /dev/null 2>&1 157238438Sdteske if [ $? -eq ${SUCCESS:-0} ]; then 158238438Sdteske rc_conf_files="$RC_CONFS" 159238438Sdteske _rc_confs_set=1 160238438Sdteske fi 161238438Sdteske 162238438Sdteske unset SUCCESS 163238438Sdteske # no longer needed 164238438Sdteske 165240783Sdteske source_rc_confs > /dev/null 2>&1 166238438Sdteske 167238438Sdteske # 168238438Sdteske # If the query was for `rc_conf_files' AND after calling 169238438Sdteske # source_rc_confs the vaue has not changed, then we should 170238438Sdteske # restore the value to the one inherited from RC_DEFAULTS 171238438Sdteske # before performing the final query (preventing us from 172238438Sdteske # returning what was set via RC_CONFS when the intent was 173238438Sdteske # instead to query the value from the file(s) specified). 174238438Sdteske # 175238438Sdteske if [ "$1" = "rc_conf_files" -a \ 176238438Sdteske "$_rc_confs_set" -a \ 177238438Sdteske "$rc_conf_files" = "$RC_CONFS" \ 178238438Sdteske ]; then 179238438Sdteske rc_conf_files="$_rc_conf_files" 180238438Sdteske unset _rc_conf_files 181238438Sdteske unset _rc_confs_set 182238438Sdteske fi 183238438Sdteske 184238438Sdteske unset RC_CONFS 185238438Sdteske # no longer needed 186238438Sdteske 187238438Sdteske # 188238438Sdteske # This must be the last functional line for both the sub-shell 189238438Sdteske # and the function to preserve the return status from formats 190238438Sdteske # such as "${varname?}" and "${varname:?}" (see "Parameter 191238438Sdteske # Expansion" in sh(1) for more information). 192238438Sdteske # 193240783Sdteske eval echo '"${'"$1"'}"' 2> /dev/null 194238438Sdteske ) 195238438Sdteske} 196238438Sdteske 197238438Sdteske# f_sysrc_get_default $varname 198238438Sdteske# 199238438Sdteske# Get a system configuration default setting from the default rc.conf(5) file 200238438Sdteske# (or whatever RC_DEFAULTS points at). 201238438Sdteske# 202238438Sdteskef_sysrc_get_default() 203238438Sdteske{ 204238438Sdteske # Sanity check 205238438Sdteske [ -f "$RC_DEFAULTS" -a -r "$RC_DEFAULTS" ] || return $FAILURE 206238438Sdteske 207238438Sdteske # Taint-check variable name 208238438Sdteske case "$1" in 209238438Sdteske [0-9]*) 210238438Sdteske # Don't expand possible positional parameters 211238438Sdteske return $FAILURE;; 212238438Sdteske *) 213238438Sdteske [ "$1" ] || return $FAILURE 214238438Sdteske esac 215238438Sdteske 216238438Sdteske ( # Execute within sub-shell to protect parent environment 217238438Sdteske 218238438Sdteske # 219238438Sdteske # Clear the environment of all variables, preventing the 220238438Sdteske # expansion of normals such as `PS1', `TERM', etc. 221238438Sdteske # 222238438Sdteske f_clean_env --except RC_DEFAULTS 223238438Sdteske 224240783Sdteske . "$RC_DEFAULTS" > /dev/null 2>&1 225238438Sdteske 226238438Sdteske unset RC_DEFAULTS 227238438Sdteske # no longer needed 228238438Sdteske 229238438Sdteske # 230238438Sdteske # This must be the last functional line for both the sub-shell 231238438Sdteske # and the function to preserve the return status from formats 232238438Sdteske # such as "${varname?}" and "${varname:?}" (see "Parameter 233238438Sdteske # Expansion" in sh(1) for more information). 234238438Sdteske # 235240783Sdteske eval echo '"${'"$1"'}"' 2> /dev/null 236238438Sdteske ) 237238438Sdteske} 238238438Sdteske 239238438Sdteske# f_sysrc_find $varname 240238438Sdteske# 241238438Sdteske# Find which file holds the effective last-assignment to a given variable 242238438Sdteske# within the rc.conf(5) file(s). 243238438Sdteske# 244238438Sdteske# If the variable is found in any of the rc.conf(5) files, the function prints 245238438Sdteske# the filename it was found in and then returns success. Otherwise output is 246238438Sdteske# NULL and the function returns with error status. 247238438Sdteske# 248238438Sdteskef_sysrc_find() 249238438Sdteske{ 250238438Sdteske local varname="$1" 251238438Sdteske local regex="^[[:space:]]*$varname=" 252238438Sdteske local rc_conf_files="$( f_sysrc_get rc_conf_files )" 253238438Sdteske local conf_files= 254238438Sdteske local file 255238438Sdteske 256238438Sdteske # Check parameters 257238438Sdteske [ "$varname" ] || return $FAILURE 258238438Sdteske 259238438Sdteske # 260238438Sdteske # If RC_CONFS is defined, set $rc_conf_files to an explicit 261238438Sdteske # value, modifying the default behavior of source_rc_confs(). 262238438Sdteske # 263238438Sdteske [ "$RC_CONFS" ] && rc_conf_files="$RC_CONFS" 264238438Sdteske 265238438Sdteske # 266238438Sdteske # Reverse the order of files in rc_conf_files (the boot process sources 267238438Sdteske # these in order, so we will search them in reverse-order to find the 268238438Sdteske # last-assignment -- the one that ultimately effects the environment). 269238438Sdteske # 270238438Sdteske for file in $rc_conf_files; do 271238438Sdteske conf_files="$file${conf_files:+ }$conf_files" 272238438Sdteske done 273238438Sdteske 274238438Sdteske # 275238438Sdteske # Append the defaults file (since directives in the defaults file 276238438Sdteske # indeed affect the boot process, we'll want to know when a directive 277238438Sdteske # is found there). 278238438Sdteske # 279238438Sdteske conf_files="$conf_files${conf_files:+ }$RC_DEFAULTS" 280238438Sdteske 281238438Sdteske # 282238438Sdteske # Find which file matches assignment to the given variable name. 283238438Sdteske # 284238438Sdteske for file in $conf_files; do 285238438Sdteske [ -f "$file" -a -r "$file" ] || continue 286238438Sdteske if grep -Eq "$regex" $file; then 287238438Sdteske echo $file 288238438Sdteske return $SUCCESS 289238438Sdteske fi 290238438Sdteske done 291238438Sdteske 292238438Sdteske return $FAILURE # Not found 293238438Sdteske} 294238438Sdteske 295238438Sdteske# f_sysrc_desc $varname 296238438Sdteske# 297238438Sdteske# Attempts to return the comments associated with varname from the rc.conf(5) 298238438Sdteske# defaults file `/etc/defaults/rc.conf' (or whatever RC_DEFAULTS points to). 299238438Sdteske# 300238438Sdteske# Multi-line comments are joined together. Results are NULL if no description 301238438Sdteske# could be found. 302238438Sdteske# 303238438Sdteske# This function is a two-parter. Below is the awk(1) portion of the function, 304238438Sdteske# afterward is the sh(1) function which utilizes the below awk script. 305238438Sdteske# 306238438Sdteskef_sysrc_desc_awk=' 307238438Sdteske# Variables that should be defined on the invocation line: 308238438Sdteske# -v varname="varname" 309238438Sdteske# 310238438SdteskeBEGIN { 311238438Sdteske regex = "^[[:space:]]*"varname"=" 312238438Sdteske found = 0 313238438Sdteske buffer = "" 314238438Sdteske} 315238438Sdteske{ 316238438Sdteske if ( ! found ) 317238438Sdteske { 318238438Sdteske if ( ! match($0, regex) ) next 319238438Sdteske 320238438Sdteske found = 1 321238438Sdteske sub(/^[^#]*(#[[:space:]]*)?/, "") 322238438Sdteske buffer = $0 323238438Sdteske next 324238438Sdteske } 325238438Sdteske 326238438Sdteske if ( !/^[[:space:]]*#/ || 327238438Sdteske /^[[:space:]]*[[:alpha:]_][[:alnum:]_]*=/ || 328238438Sdteske /^[[:space:]]*#[[:alpha:]_][[:alnum:]_]*=/ || 329238438Sdteske /^[[:space:]]*$/ ) exit 330238438Sdteske 331238438Sdteske sub(/(.*#)*[[:space:]]*/, "") 332238438Sdteske buffer = buffer" "$0 333238438Sdteske} 334238438SdteskeEND { 335238438Sdteske # Clean up the buffer 336238438Sdteske sub(/^[[:space:]]*/, "", buffer) 337238438Sdteske sub(/[[:space:]]*$/, "", buffer) 338238438Sdteske 339238438Sdteske print buffer 340238438Sdteske exit ! found 341238438Sdteske} 342238438Sdteske' 343238438Sdteskef_sysrc_desc() 344238438Sdteske{ 345238438Sdteske awk -v varname="$1" "$f_sysrc_desc_awk" < "$RC_DEFAULTS" 346238438Sdteske} 347238438Sdteske 348238438Sdteske# f_sysrc_set $varname $new_value 349238438Sdteske# 350238438Sdteske# Change a setting in the system configuration files (edits the files in-place 351238438Sdteske# to change the value in the last assignment to the variable). If the variable 352238438Sdteske# does not appear in the source file, it is appended to the end of the primary 353238438Sdteske# system configuration file `/etc/rc.conf'. 354238438Sdteske# 355238438Sdteske# This function is a two-parter. Below is the awk(1) portion of the function, 356238438Sdteske# afterward is the sh(1) function which utilizes the below awk script. 357238438Sdteske# 358238438Sdteskef_sysrc_set_awk=' 359238438Sdteske# Variables that should be defined on the invocation line: 360238438Sdteske# -v varname="varname" 361238438Sdteske# -v new_value="new_value" 362238438Sdteske# 363238438SdteskeBEGIN { 364238438Sdteske regex = "^[[:space:]]*"varname"=" 365238438Sdteske found = retval = 0 366238438Sdteske} 367238438Sdteske{ 368238438Sdteske # If already found... just spew 369238438Sdteske if ( found ) { print; next } 370238438Sdteske 371238438Sdteske # Does this line match an assignment to our variable? 372238438Sdteske if ( ! match($0, regex) ) { print; next } 373238438Sdteske 374238438Sdteske # Save important match information 375238438Sdteske found = 1 376238438Sdteske matchlen = RSTART + RLENGTH - 1 377238438Sdteske 378238438Sdteske # Store the value text for later munging 379238438Sdteske value = substr($0, matchlen + 1, length($0) - matchlen) 380238438Sdteske 381238438Sdteske # Store the first character of the value 382238438Sdteske t1 = t2 = substr(value, 0, 1) 383238438Sdteske 384238438Sdteske # Assignment w/ back-ticks, expression, or misc. 385238438Sdteske # We ignore these since we did not generate them 386238438Sdteske # 387238438Sdteske if ( t1 ~ /[`$\\]/ ) { retval = 1; print; next } 388238438Sdteske 389238438Sdteske # Assignment w/ single-quoted value 390238438Sdteske else if ( t1 == "'\''" ) { 391238438Sdteske sub(/^'\''[^'\'']*/, "", value) 392238438Sdteske if ( length(value) == 0 ) t2 = "" 393238438Sdteske sub(/^'\''/, "", value) 394238438Sdteske } 395238438Sdteske 396238438Sdteske # Assignment w/ double-quoted value 397238438Sdteske else if ( t1 == "\"" ) { 398238438Sdteske sub(/^"(.*\\\\+")*[^"]*/, "", value) 399238438Sdteske if ( length(value) == 0 ) t2 = "" 400238438Sdteske sub(/^"/, "", value) 401238438Sdteske } 402238438Sdteske 403238438Sdteske # Assignment w/ non-quoted value 404238438Sdteske else if ( t1 ~ /[^[:space:];]/ ) { 405238438Sdteske t1 = t2 = "\"" 406238438Sdteske sub(/^[^[:space:]]*/, "", value) 407238438Sdteske } 408238438Sdteske 409238438Sdteske # Null-assignment 410238438Sdteske else if ( t1 ~ /[[:space:];]/ ) { t1 = t2 = "\"" } 411238438Sdteske 412238438Sdteske printf "%s%c%s%c%s\n", substr($0, 0, matchlen), \ 413238438Sdteske t1, new_value, t2, value 414238438Sdteske} 415238438SdteskeEND { exit retval } 416238438Sdteske' 417238438Sdteskef_sysrc_set() 418238438Sdteske{ 419238438Sdteske local varname="$1" new_value="$2" 420238438Sdteske 421238438Sdteske # Check arguments 422238438Sdteske [ "$varname" ] || return $FAILURE 423238438Sdteske 424238438Sdteske # 425238438Sdteske # Find which rc.conf(5) file contains the last-assignment 426238438Sdteske # 427238438Sdteske local not_found= 428238438Sdteske local file="$( f_sysrc_find "$varname" )" 429238438Sdteske if [ "$file" = "$RC_DEFAULTS" -o ! "$file" ]; then 430238438Sdteske # 431238438Sdteske # We either got a null response (not found) or the variable 432238438Sdteske # was only found in the rc.conf(5) defaults. In either case, 433238438Sdteske # let's instead modify the first file from $rc_conf_files. 434238438Sdteske # 435238438Sdteske 436238438Sdteske not_found=1 437238438Sdteske 438238438Sdteske # 439238438Sdteske # If RC_CONFS is defined, use $RC_CONFS 440238438Sdteske # rather than $rc_conf_files. 441238438Sdteske # 442238438Sdteske if [ "$RC_CONFS" ]; then 443238438Sdteske file="${RC_CONFS%%[$IFS]*}" 444238438Sdteske else 445238438Sdteske file=$( f_sysrc_get rc_conf_files ) 446238438Sdteske file="${file%%[$IFS]*}" 447238438Sdteske fi 448238438Sdteske fi 449238438Sdteske 450238438Sdteske # 451238438Sdteske # If not found, append new value to last file and return. 452238438Sdteske # 453238438Sdteske if [ "$not_found" ]; then 454238438Sdteske echo "$varname=\"$new_value\"" >> "$file" 455238438Sdteske return $? 456238438Sdteske fi 457238438Sdteske 458238438Sdteske # 459238438Sdteske # Perform sanity checks. 460238438Sdteske # 461238438Sdteske if [ ! -w "$file" ]; then 462238438Sdteske f_err "$msg_cannot_create_permission_denied\n" \ 463238438Sdteske "$pgm" "$file" 464238438Sdteske return $FAILURE 465238438Sdteske fi 466238438Sdteske 467238438Sdteske # 468238438Sdteske # Create a new temporary file to write to. 469238438Sdteske # 470238438Sdteske local tmpfile="$( mktemp -t "$pgm" )" 471238438Sdteske [ "$tmpfile" ] || return $FAILURE 472238438Sdteske 473238438Sdteske # 474238438Sdteske # Fixup permissions (else we're in for a surprise, as mktemp(1) creates 475238438Sdteske # the temporary file with 0600 permissions, and if we simply mv(1) the 476238438Sdteske # temporary file over the destination, the destination will inherit the 477238438Sdteske # permissions from the temporary file). 478238438Sdteske # 479238438Sdteske local mode 480240783Sdteske mode=$( stat -f '%#Lp' "$file" 2> /dev/null ) 481238438Sdteske f_quietly chmod "${mode:-0644}" "$tmpfile" 482238438Sdteske 483238438Sdteske # 484238438Sdteske # Fixup ownership. The destination file _is_ writable (we tested 485238438Sdteske # earlier above). However, this will fail if we don't have sufficient 486238438Sdteske # permissions (so we throw stderr into the bit-bucket). 487238438Sdteske # 488238438Sdteske local owner 489240783Sdteske owner=$( stat -f '%u:%g' "$file" 2> /dev/null ) 490238438Sdteske f_quietly chown "${owner:-root:wheel}" "$tmpfile" 491238438Sdteske 492238438Sdteske # 493238438Sdteske # Operate on the matching file, replacing only the last occurrence. 494238438Sdteske # 495238438Sdteske local new_contents retval 496240783Sdteske new_contents=$( tail -r $file 2> /dev/null ) 497238438Sdteske new_contents=$( echo "$new_contents" | awk -v varname="$varname" \ 498238438Sdteske -v new_value="$new_value" "$f_sysrc_set_awk" ) 499238438Sdteske retval=$? 500238438Sdteske 501238438Sdteske # 502238438Sdteske # Write the temporary file contents. 503238438Sdteske # 504238438Sdteske echo "$new_contents" | tail -r > "$tmpfile" || return $FAILURE 505238438Sdteske if [ $retval -ne $SUCCESS ]; then 506238438Sdteske echo "$varname=\"$new_value\"" >> "$tmpfile" 507238438Sdteske fi 508238438Sdteske 509238438Sdteske # 510238438Sdteske # Taint-check our results. 511238438Sdteske # 512238438Sdteske if ! /bin/sh -n "$tmpfile"; then 513238438Sdteske f_err "$msg_previous_syntax_errors\n" "$pgm" "$file" 514238438Sdteske rm -f "$tmpfile" 515238438Sdteske return $FAILURE 516238438Sdteske fi 517238438Sdteske 518238438Sdteske # 519238438Sdteske # Finally, move the temporary file into place. 520238438Sdteske # 521238438Sdteske mv "$tmpfile" "$file" 522238438Sdteske} 523238438Sdteske 524238438Sdteske# f_sysrc_delete $varname 525238438Sdteske# 526238438Sdteske# Remove a setting from the system configuration files (edits files in-place). 527238438Sdteske# Deletes all assignments to the given variable in all config files. If the 528238438Sdteske# `-f file' option is passed, the removal is restricted to only those files 529238438Sdteske# specified, otherwise the system collection of rc_conf_files is used. 530238438Sdteske# 531238438Sdteske# This function is a two-parter. Below is the awk(1) portion of the function, 532238438Sdteske# afterward is the sh(1) function which utilizes the below awk script. 533238438Sdteske# 534238438Sdteskef_sysrc_delete_awk=' 535238438Sdteske# Variables that should be defined on the invocation line: 536238438Sdteske# -v varname="varname" 537238438Sdteske# 538238438SdteskeBEGIN { 539238438Sdteske regex = "^[[:space:]]*"varname"=" 540238438Sdteske found = 0 541238438Sdteske} 542238438Sdteske{ 543238438Sdteske if ( $0 ~ regex ) 544238438Sdteske found = 1 545238438Sdteske else 546238438Sdteske print 547238438Sdteske} 548238438SdteskeEND { exit ! found } 549238438Sdteske' 550238438Sdteskef_sysrc_delete() 551238438Sdteske{ 552238438Sdteske local varname="$1" 553238438Sdteske local file 554238438Sdteske 555238438Sdteske # Check arguments 556238438Sdteske [ "$varname" ] || return $FAILURE 557238438Sdteske 558238438Sdteske # 559238438Sdteske # Operate on each of the specified files 560238438Sdteske # 561238438Sdteske for file in ${RC_CONFS:-$( f_sysrc_get rc_conf_files )}; do 562238438Sdteske [ -e "$file" ] || continue 563238438Sdteske 564238438Sdteske # 565238438Sdteske # Create a new temporary file to write to. 566238438Sdteske # 567238438Sdteske local tmpfile="$( mktemp -t "$pgm" )" 568238438Sdteske [ "$tmpfile" ] || return $FAILURE 569238438Sdteske 570238438Sdteske # 571238438Sdteske # Fixup permissions and ownership (mktemp(1) defaults to 0600 572238438Sdteske # permissions) to instead match the destination file. 573238438Sdteske # 574238438Sdteske local mode owner 575240783Sdteske mode=$( stat -f '%#Lp' "$file" 2> /dev/null ) 576240783Sdteske owner=$( stat -f '%u:%g' "$file" 2> /dev/null ) 577238438Sdteske f_quietly chmod "${mode:-0644}" "$tmpfile" 578238438Sdteske f_quietly chown "${owner:-root:wheel}" "$tmpfile" 579238438Sdteske 580238438Sdteske # 581238438Sdteske # Operate on the file, removing all occurrences, saving the 582238438Sdteske # output in our temporary file. 583238438Sdteske # 584238438Sdteske awk -v varname="$varname" "$f_sysrc_delete_awk" "$file" \ 585238438Sdteske > "$tmpfile" 586238438Sdteske if [ $? -ne $SUCCESS ]; then 587238438Sdteske # The file didn't contain any assignments 588238438Sdteske rm -f "$tmpfile" 589238438Sdteske continue 590238438Sdteske fi 591238438Sdteske 592238438Sdteske # 593238438Sdteske # Taint-check our results. 594238438Sdteske # 595238438Sdteske if ! /bin/sh -n "$tmpfile"; then 596238438Sdteske f_err "$msg_previous_syntax_errors\n" \ 597238438Sdteske "$pgm" "$file" 598238438Sdteske rm -f "$tmpfile" 599238438Sdteske return $FAILURE 600238438Sdteske fi 601238438Sdteske 602238438Sdteske # 603238438Sdteske # Perform sanity checks 604238438Sdteske # 605238438Sdteske if [ ! -w "$file" ]; then 606238438Sdteske f_err "$msg_permission_denied\n" "$pgm" "$file" 607238438Sdteske rm -f "$tmpfile" 608238438Sdteske return $FAILURE 609238438Sdteske fi 610238438Sdteske 611238438Sdteske # 612238438Sdteske # Finally, move the temporary file into place. 613238438Sdteske # 614238438Sdteske mv "$tmpfile" "$file" 615238438Sdteske done 616238438Sdteske} 617238438Sdteske 618238438Sdteskefi # ! $_SYSRC_SUBR 619