sysrc.subr revision 240863
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 240863 2012-09-23 17:47:01Z 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 # 135240798Sdteske f_clean_env --except RC_CONFS RC_DEFAULTS 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 # 156240798Sdteske if [ "${RC_CONFS+set}" ]; then 157238438Sdteske rc_conf_files="$RC_CONFS" 158238438Sdteske _rc_confs_set=1 159238438Sdteske fi 160238438Sdteske 161240783Sdteske source_rc_confs > /dev/null 2>&1 162238438Sdteske 163238438Sdteske # 164238438Sdteske # If the query was for `rc_conf_files' AND after calling 165240797Sdteske # source_rc_confs the value has not changed, then we should 166238438Sdteske # restore the value to the one inherited from RC_DEFAULTS 167238438Sdteske # before performing the final query (preventing us from 168238438Sdteske # returning what was set via RC_CONFS when the intent was 169238438Sdteske # instead to query the value from the file(s) specified). 170238438Sdteske # 171238438Sdteske if [ "$1" = "rc_conf_files" -a \ 172238438Sdteske "$_rc_confs_set" -a \ 173238438Sdteske "$rc_conf_files" = "$RC_CONFS" \ 174238438Sdteske ]; then 175238438Sdteske rc_conf_files="$_rc_conf_files" 176238438Sdteske unset _rc_conf_files 177238438Sdteske unset _rc_confs_set 178238438Sdteske fi 179238438Sdteske 180238438Sdteske unset RC_CONFS 181238438Sdteske # no longer needed 182238438Sdteske 183238438Sdteske # 184238438Sdteske # This must be the last functional line for both the sub-shell 185238438Sdteske # and the function to preserve the return status from formats 186238438Sdteske # such as "${varname?}" and "${varname:?}" (see "Parameter 187238438Sdteske # Expansion" in sh(1) for more information). 188238438Sdteske # 189240783Sdteske eval echo '"${'"$1"'}"' 2> /dev/null 190238438Sdteske ) 191238438Sdteske} 192238438Sdteske 193238438Sdteske# f_sysrc_get_default $varname 194238438Sdteske# 195238438Sdteske# Get a system configuration default setting from the default rc.conf(5) file 196238438Sdteske# (or whatever RC_DEFAULTS points at). 197238438Sdteske# 198238438Sdteskef_sysrc_get_default() 199238438Sdteske{ 200238438Sdteske # Sanity check 201238438Sdteske [ -f "$RC_DEFAULTS" -a -r "$RC_DEFAULTS" ] || return $FAILURE 202238438Sdteske 203238438Sdteske # Taint-check variable name 204238438Sdteske case "$1" in 205238438Sdteske [0-9]*) 206238438Sdteske # Don't expand possible positional parameters 207238438Sdteske return $FAILURE;; 208238438Sdteske *) 209238438Sdteske [ "$1" ] || return $FAILURE 210238438Sdteske esac 211238438Sdteske 212238438Sdteske ( # Execute within sub-shell to protect parent environment 213238438Sdteske 214238438Sdteske # 215238438Sdteske # Clear the environment of all variables, preventing the 216238438Sdteske # expansion of normals such as `PS1', `TERM', etc. 217238438Sdteske # 218238438Sdteske f_clean_env --except RC_DEFAULTS 219238438Sdteske 220240783Sdteske . "$RC_DEFAULTS" > /dev/null 2>&1 221238438Sdteske 222238438Sdteske unset RC_DEFAULTS 223238438Sdteske # no longer needed 224238438Sdteske 225238438Sdteske # 226238438Sdteske # This must be the last functional line for both the sub-shell 227238438Sdteske # and the function to preserve the return status from formats 228238438Sdteske # such as "${varname?}" and "${varname:?}" (see "Parameter 229238438Sdteske # Expansion" in sh(1) for more information). 230238438Sdteske # 231240783Sdteske eval echo '"${'"$1"'}"' 2> /dev/null 232238438Sdteske ) 233238438Sdteske} 234238438Sdteske 235238438Sdteske# f_sysrc_find $varname 236238438Sdteske# 237238438Sdteske# Find which file holds the effective last-assignment to a given variable 238238438Sdteske# within the rc.conf(5) file(s). 239238438Sdteske# 240238438Sdteske# If the variable is found in any of the rc.conf(5) files, the function prints 241238438Sdteske# the filename it was found in and then returns success. Otherwise output is 242238438Sdteske# NULL and the function returns with error status. 243238438Sdteske# 244238438Sdteskef_sysrc_find() 245238438Sdteske{ 246238438Sdteske local varname="$1" 247238438Sdteske local regex="^[[:space:]]*$varname=" 248238438Sdteske local rc_conf_files="$( f_sysrc_get rc_conf_files )" 249238438Sdteske local conf_files= 250238438Sdteske local file 251238438Sdteske 252238438Sdteske # Check parameters 253238438Sdteske [ "$varname" ] || return $FAILURE 254238438Sdteske 255238438Sdteske # 256238438Sdteske # If RC_CONFS is defined, set $rc_conf_files to an explicit 257238438Sdteske # value, modifying the default behavior of source_rc_confs(). 258238438Sdteske # 259240863Sdteske [ "${RC_CONFS+set}" ] && rc_conf_files="$RC_CONFS" 260238438Sdteske 261238438Sdteske # 262238438Sdteske # Reverse the order of files in rc_conf_files (the boot process sources 263238438Sdteske # these in order, so we will search them in reverse-order to find the 264238438Sdteske # last-assignment -- the one that ultimately effects the environment). 265238438Sdteske # 266238438Sdteske for file in $rc_conf_files; do 267238438Sdteske conf_files="$file${conf_files:+ }$conf_files" 268238438Sdteske done 269238438Sdteske 270238438Sdteske # 271238438Sdteske # Append the defaults file (since directives in the defaults file 272238438Sdteske # indeed affect the boot process, we'll want to know when a directive 273238438Sdteske # is found there). 274238438Sdteske # 275238438Sdteske conf_files="$conf_files${conf_files:+ }$RC_DEFAULTS" 276238438Sdteske 277238438Sdteske # 278238438Sdteske # Find which file matches assignment to the given variable name. 279238438Sdteske # 280238438Sdteske for file in $conf_files; do 281238438Sdteske [ -f "$file" -a -r "$file" ] || continue 282238438Sdteske if grep -Eq "$regex" $file; then 283238438Sdteske echo $file 284238438Sdteske return $SUCCESS 285238438Sdteske fi 286238438Sdteske done 287238438Sdteske 288238438Sdteske return $FAILURE # Not found 289238438Sdteske} 290238438Sdteske 291238438Sdteske# f_sysrc_desc $varname 292238438Sdteske# 293238438Sdteske# Attempts to return the comments associated with varname from the rc.conf(5) 294238438Sdteske# defaults file `/etc/defaults/rc.conf' (or whatever RC_DEFAULTS points to). 295238438Sdteske# 296238438Sdteske# Multi-line comments are joined together. Results are NULL if no description 297238438Sdteske# could be found. 298238438Sdteske# 299238438Sdteske# This function is a two-parter. Below is the awk(1) portion of the function, 300238438Sdteske# afterward is the sh(1) function which utilizes the below awk script. 301238438Sdteske# 302238438Sdteskef_sysrc_desc_awk=' 303238438Sdteske# Variables that should be defined on the invocation line: 304238438Sdteske# -v varname="varname" 305238438Sdteske# 306238438SdteskeBEGIN { 307238438Sdteske regex = "^[[:space:]]*"varname"=" 308238438Sdteske found = 0 309238438Sdteske buffer = "" 310238438Sdteske} 311238438Sdteske{ 312238438Sdteske if ( ! found ) 313238438Sdteske { 314238438Sdteske if ( ! match($0, regex) ) next 315238438Sdteske 316238438Sdteske found = 1 317238438Sdteske sub(/^[^#]*(#[[:space:]]*)?/, "") 318238438Sdteske buffer = $0 319238438Sdteske next 320238438Sdteske } 321238438Sdteske 322238438Sdteske if ( !/^[[:space:]]*#/ || 323238438Sdteske /^[[:space:]]*[[:alpha:]_][[:alnum:]_]*=/ || 324238438Sdteske /^[[:space:]]*#[[:alpha:]_][[:alnum:]_]*=/ || 325238438Sdteske /^[[:space:]]*$/ ) exit 326238438Sdteske 327238438Sdteske sub(/(.*#)*[[:space:]]*/, "") 328238438Sdteske buffer = buffer" "$0 329238438Sdteske} 330238438SdteskeEND { 331238438Sdteske # Clean up the buffer 332238438Sdteske sub(/^[[:space:]]*/, "", buffer) 333238438Sdteske sub(/[[:space:]]*$/, "", buffer) 334238438Sdteske 335238438Sdteske print buffer 336238438Sdteske exit ! found 337238438Sdteske} 338238438Sdteske' 339238438Sdteskef_sysrc_desc() 340238438Sdteske{ 341238438Sdteske awk -v varname="$1" "$f_sysrc_desc_awk" < "$RC_DEFAULTS" 342238438Sdteske} 343238438Sdteske 344238438Sdteske# f_sysrc_set $varname $new_value 345238438Sdteske# 346238438Sdteske# Change a setting in the system configuration files (edits the files in-place 347238438Sdteske# to change the value in the last assignment to the variable). If the variable 348238438Sdteske# does not appear in the source file, it is appended to the end of the primary 349238438Sdteske# system configuration file `/etc/rc.conf'. 350238438Sdteske# 351238438Sdteske# This function is a two-parter. Below is the awk(1) portion of the function, 352238438Sdteske# afterward is the sh(1) function which utilizes the below awk script. 353238438Sdteske# 354238438Sdteskef_sysrc_set_awk=' 355238438Sdteske# Variables that should be defined on the invocation line: 356238438Sdteske# -v varname="varname" 357238438Sdteske# -v new_value="new_value" 358238438Sdteske# 359238438SdteskeBEGIN { 360238438Sdteske regex = "^[[:space:]]*"varname"=" 361238438Sdteske found = retval = 0 362238438Sdteske} 363238438Sdteske{ 364238438Sdteske # If already found... just spew 365238438Sdteske if ( found ) { print; next } 366238438Sdteske 367238438Sdteske # Does this line match an assignment to our variable? 368238438Sdteske if ( ! match($0, regex) ) { print; next } 369238438Sdteske 370238438Sdteske # Save important match information 371238438Sdteske found = 1 372238438Sdteske matchlen = RSTART + RLENGTH - 1 373238438Sdteske 374238438Sdteske # Store the value text for later munging 375238438Sdteske value = substr($0, matchlen + 1, length($0) - matchlen) 376238438Sdteske 377238438Sdteske # Store the first character of the value 378238438Sdteske t1 = t2 = substr(value, 0, 1) 379238438Sdteske 380238438Sdteske # Assignment w/ back-ticks, expression, or misc. 381238438Sdteske # We ignore these since we did not generate them 382238438Sdteske # 383238438Sdteske if ( t1 ~ /[`$\\]/ ) { retval = 1; print; next } 384238438Sdteske 385238438Sdteske # Assignment w/ single-quoted value 386238438Sdteske else if ( t1 == "'\''" ) { 387238438Sdteske sub(/^'\''[^'\'']*/, "", value) 388238438Sdteske if ( length(value) == 0 ) t2 = "" 389238438Sdteske sub(/^'\''/, "", value) 390238438Sdteske } 391238438Sdteske 392238438Sdteske # Assignment w/ double-quoted value 393238438Sdteske else if ( t1 == "\"" ) { 394238438Sdteske sub(/^"(.*\\\\+")*[^"]*/, "", value) 395238438Sdteske if ( length(value) == 0 ) t2 = "" 396238438Sdteske sub(/^"/, "", value) 397238438Sdteske } 398238438Sdteske 399238438Sdteske # Assignment w/ non-quoted value 400238438Sdteske else if ( t1 ~ /[^[:space:];]/ ) { 401238438Sdteske t1 = t2 = "\"" 402238438Sdteske sub(/^[^[:space:]]*/, "", value) 403238438Sdteske } 404238438Sdteske 405238438Sdteske # Null-assignment 406238438Sdteske else if ( t1 ~ /[[:space:];]/ ) { t1 = t2 = "\"" } 407238438Sdteske 408238438Sdteske printf "%s%c%s%c%s\n", substr($0, 0, matchlen), \ 409238438Sdteske t1, new_value, t2, value 410238438Sdteske} 411238438SdteskeEND { exit retval } 412238438Sdteske' 413238438Sdteskef_sysrc_set() 414238438Sdteske{ 415238438Sdteske local varname="$1" new_value="$2" 416238438Sdteske 417238438Sdteske # Check arguments 418238438Sdteske [ "$varname" ] || return $FAILURE 419238438Sdteske 420238438Sdteske # 421238438Sdteske # Find which rc.conf(5) file contains the last-assignment 422238438Sdteske # 423238438Sdteske local not_found= 424238438Sdteske local file="$( f_sysrc_find "$varname" )" 425238438Sdteske if [ "$file" = "$RC_DEFAULTS" -o ! "$file" ]; then 426238438Sdteske # 427238438Sdteske # We either got a null response (not found) or the variable 428238438Sdteske # was only found in the rc.conf(5) defaults. In either case, 429238438Sdteske # let's instead modify the first file from $rc_conf_files. 430238438Sdteske # 431238438Sdteske 432238438Sdteske not_found=1 433238438Sdteske 434238438Sdteske # 435238438Sdteske # If RC_CONFS is defined, use $RC_CONFS 436238438Sdteske # rather than $rc_conf_files. 437238438Sdteske # 438240863Sdteske if [ "${RC_CONFS+set}" ]; then 439238438Sdteske file="${RC_CONFS%%[$IFS]*}" 440238438Sdteske else 441238438Sdteske file=$( f_sysrc_get rc_conf_files ) 442238438Sdteske file="${file%%[$IFS]*}" 443238438Sdteske fi 444238438Sdteske fi 445238438Sdteske 446238438Sdteske # 447238438Sdteske # If not found, append new value to last file and return. 448238438Sdteske # 449238438Sdteske if [ "$not_found" ]; then 450238438Sdteske echo "$varname=\"$new_value\"" >> "$file" 451238438Sdteske return $? 452238438Sdteske fi 453238438Sdteske 454238438Sdteske # 455238438Sdteske # Perform sanity checks. 456238438Sdteske # 457238438Sdteske if [ ! -w "$file" ]; then 458238438Sdteske f_err "$msg_cannot_create_permission_denied\n" \ 459238438Sdteske "$pgm" "$file" 460238438Sdteske return $FAILURE 461238438Sdteske fi 462238438Sdteske 463238438Sdteske # 464238438Sdteske # Create a new temporary file to write to. 465238438Sdteske # 466238438Sdteske local tmpfile="$( mktemp -t "$pgm" )" 467238438Sdteske [ "$tmpfile" ] || return $FAILURE 468238438Sdteske 469238438Sdteske # 470238438Sdteske # Fixup permissions (else we're in for a surprise, as mktemp(1) creates 471238438Sdteske # the temporary file with 0600 permissions, and if we simply mv(1) the 472238438Sdteske # temporary file over the destination, the destination will inherit the 473238438Sdteske # permissions from the temporary file). 474238438Sdteske # 475238438Sdteske local mode 476240783Sdteske mode=$( stat -f '%#Lp' "$file" 2> /dev/null ) 477238438Sdteske f_quietly chmod "${mode:-0644}" "$tmpfile" 478238438Sdteske 479238438Sdteske # 480238438Sdteske # Fixup ownership. The destination file _is_ writable (we tested 481238438Sdteske # earlier above). However, this will fail if we don't have sufficient 482238438Sdteske # permissions (so we throw stderr into the bit-bucket). 483238438Sdteske # 484238438Sdteske local owner 485240783Sdteske owner=$( stat -f '%u:%g' "$file" 2> /dev/null ) 486238438Sdteske f_quietly chown "${owner:-root:wheel}" "$tmpfile" 487238438Sdteske 488238438Sdteske # 489238438Sdteske # Operate on the matching file, replacing only the last occurrence. 490238438Sdteske # 491238438Sdteske local new_contents retval 492240783Sdteske new_contents=$( tail -r $file 2> /dev/null ) 493238438Sdteske new_contents=$( echo "$new_contents" | awk -v varname="$varname" \ 494238438Sdteske -v new_value="$new_value" "$f_sysrc_set_awk" ) 495238438Sdteske retval=$? 496238438Sdteske 497238438Sdteske # 498238438Sdteske # Write the temporary file contents. 499238438Sdteske # 500238438Sdteske echo "$new_contents" | tail -r > "$tmpfile" || return $FAILURE 501238438Sdteske if [ $retval -ne $SUCCESS ]; then 502238438Sdteske echo "$varname=\"$new_value\"" >> "$tmpfile" 503238438Sdteske fi 504238438Sdteske 505238438Sdteske # 506238438Sdteske # Taint-check our results. 507238438Sdteske # 508238438Sdteske if ! /bin/sh -n "$tmpfile"; then 509238438Sdteske f_err "$msg_previous_syntax_errors\n" "$pgm" "$file" 510238438Sdteske rm -f "$tmpfile" 511238438Sdteske return $FAILURE 512238438Sdteske fi 513238438Sdteske 514238438Sdteske # 515238438Sdteske # Finally, move the temporary file into place. 516238438Sdteske # 517238438Sdteske mv "$tmpfile" "$file" 518238438Sdteske} 519238438Sdteske 520238438Sdteske# f_sysrc_delete $varname 521238438Sdteske# 522238438Sdteske# Remove a setting from the system configuration files (edits files in-place). 523238438Sdteske# Deletes all assignments to the given variable in all config files. If the 524238438Sdteske# `-f file' option is passed, the removal is restricted to only those files 525238438Sdteske# specified, otherwise the system collection of rc_conf_files is used. 526238438Sdteske# 527238438Sdteske# This function is a two-parter. Below is the awk(1) portion of the function, 528238438Sdteske# afterward is the sh(1) function which utilizes the below awk script. 529238438Sdteske# 530238438Sdteskef_sysrc_delete_awk=' 531238438Sdteske# Variables that should be defined on the invocation line: 532238438Sdteske# -v varname="varname" 533238438Sdteske# 534238438SdteskeBEGIN { 535238438Sdteske regex = "^[[:space:]]*"varname"=" 536238438Sdteske found = 0 537238438Sdteske} 538238438Sdteske{ 539238438Sdteske if ( $0 ~ regex ) 540238438Sdteske found = 1 541238438Sdteske else 542238438Sdteske print 543238438Sdteske} 544238438SdteskeEND { exit ! found } 545238438Sdteske' 546238438Sdteskef_sysrc_delete() 547238438Sdteske{ 548238438Sdteske local varname="$1" 549238438Sdteske local file 550238438Sdteske 551238438Sdteske # Check arguments 552238438Sdteske [ "$varname" ] || return $FAILURE 553238438Sdteske 554238438Sdteske # 555238438Sdteske # Operate on each of the specified files 556238438Sdteske # 557240863Sdteske for file in ${RC_CONFS-$( f_sysrc_get rc_conf_files )}; do 558238438Sdteske [ -e "$file" ] || continue 559238438Sdteske 560238438Sdteske # 561238438Sdteske # Create a new temporary file to write to. 562238438Sdteske # 563238438Sdteske local tmpfile="$( mktemp -t "$pgm" )" 564238438Sdteske [ "$tmpfile" ] || return $FAILURE 565238438Sdteske 566238438Sdteske # 567238438Sdteske # Fixup permissions and ownership (mktemp(1) defaults to 0600 568238438Sdteske # permissions) to instead match the destination file. 569238438Sdteske # 570238438Sdteske local mode owner 571240783Sdteske mode=$( stat -f '%#Lp' "$file" 2> /dev/null ) 572240783Sdteske owner=$( stat -f '%u:%g' "$file" 2> /dev/null ) 573238438Sdteske f_quietly chmod "${mode:-0644}" "$tmpfile" 574238438Sdteske f_quietly chown "${owner:-root:wheel}" "$tmpfile" 575238438Sdteske 576238438Sdteske # 577238438Sdteske # Operate on the file, removing all occurrences, saving the 578238438Sdteske # output in our temporary file. 579238438Sdteske # 580238438Sdteske awk -v varname="$varname" "$f_sysrc_delete_awk" "$file" \ 581238438Sdteske > "$tmpfile" 582238438Sdteske if [ $? -ne $SUCCESS ]; then 583238438Sdteske # The file didn't contain any assignments 584238438Sdteske rm -f "$tmpfile" 585238438Sdteske continue 586238438Sdteske fi 587238438Sdteske 588238438Sdteske # 589238438Sdteske # Taint-check our results. 590238438Sdteske # 591238438Sdteske if ! /bin/sh -n "$tmpfile"; then 592238438Sdteske f_err "$msg_previous_syntax_errors\n" \ 593238438Sdteske "$pgm" "$file" 594238438Sdteske rm -f "$tmpfile" 595238438Sdteske return $FAILURE 596238438Sdteske fi 597238438Sdteske 598238438Sdteske # 599238438Sdteske # Perform sanity checks 600238438Sdteske # 601238438Sdteske if [ ! -w "$file" ]; then 602238438Sdteske f_err "$msg_permission_denied\n" "$pgm" "$file" 603238438Sdteske rm -f "$tmpfile" 604238438Sdteske return $FAILURE 605238438Sdteske fi 606238438Sdteske 607238438Sdteske # 608238438Sdteske # Finally, move the temporary file into place. 609238438Sdteske # 610238438Sdteske mv "$tmpfile" "$file" 611238438Sdteske done 612238438Sdteske} 613238438Sdteske 614238438Sdteskefi # ! $_SYSRC_SUBR 615