1238438Sdteskeif [ ! "$_SYSRC_SUBR" ]; then _SYSRC_SUBR=1 2238438Sdteske# 3238438Sdteske# Copyright (c) 2006-2012 Devin Teske 4252982Sdteske# 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 16252987Sdteske# 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$ 28238438Sdteske# 29238438Sdteske############################################################ INCLUDES 30238438Sdteske 31240684SdteskeBSDCFG_SHARE="/usr/share/bsdconfig" 32241149Sdteske[ "$_COMMON_SUBR" ] || . $BSDCFG_SHARE/common.subr || exit 1 33240684Sdteske 34238438SdteskeBSDCFG_LIBE="/usr/libexec/bsdconfig" 35244675Sdteskeif [ ! "$_SYSRC_JAILED" ]; then 36244675Sdteske f_dprintf "%s: loading includes..." sysrc.subr 37244675Sdteske f_include_lang $BSDCFG_LIBE/include/messages.subr 38244675Sdteskefi 39238438Sdteske 40238438Sdteske############################################################ CONFIGURATION 41238438Sdteske 42238438Sdteske# 43238438Sdteske# Standard pathnames (inherit values from shell if available) 44238438Sdteske# 45238438Sdteske: ${RC_DEFAULTS:="/etc/defaults/rc.conf"} 46238438Sdteske 47238438Sdteske############################################################ GLOBALS 48238438Sdteske 49238438Sdteske# 50238438Sdteske# Global exit status variables 51238438Sdteske# 52238438SdteskeSUCCESS=0 53238438SdteskeFAILURE=1 54238438Sdteske 55241019Sdteske# 56241019Sdteske# Valid characters that can appear in an sh(1) variable name 57241019Sdteske# 58241019Sdteske# Please note that the character ranges A-Z and a-z should be avoided because 59241019Sdteske# these can include accent characters (which are not valid in a variable name). 60241019Sdteske# For example, A-Z matches any character that sorts after A but before Z, 61241019Sdteske# including A and Z. Although ASCII order would make more sense, that is not 62241019Sdteske# how it works. 63241019Sdteske# 64241019SdteskeVALID_VARNAME_CHARS="0-9ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_" 65241019Sdteske 66238438Sdteske############################################################ FUNCTIONS 67238438Sdteske 68238438Sdteske# f_clean_env [ --except $varname ... ] 69238438Sdteske# 70238438Sdteske# Unset all environment variables in the current scope. An optional list of 71238438Sdteske# arguments can be passed, indicating which variables to avoid unsetting; the 72238438Sdteske# `--except' is required to enable the exclusion-list as the remainder of 73238438Sdteske# positional arguments. 74238438Sdteske# 75238438Sdteske# Be careful not to call this in a shell that you still expect to perform 76238438Sdteske# $PATH expansion in, because this will blow $PATH away. This is best used 77238438Sdteske# within a sub-shell block "(...)" or "$(...)" or "`...`". 78238438Sdteske# 79238438Sdteskef_clean_env() 80238438Sdteske{ 81238438Sdteske local var arg except= 82238438Sdteske 83238438Sdteske # 84238438Sdteske # Should we process an exclusion-list? 85238438Sdteske # 86238438Sdteske if [ "$1" = "--except" ]; then 87238438Sdteske except=1 88238438Sdteske shift 1 89238438Sdteske fi 90238438Sdteske 91238438Sdteske # 92238438Sdteske # Loop over a list of variable names from set(1) built-in. 93238438Sdteske # 94238438Sdteske for var in $( set | awk -F= \ 95238438Sdteske '/^[[:alpha:]_][[:alnum:]_]*=/ {print $1}' \ 96238438Sdteske | grep -v '^except$' 97238438Sdteske ); do 98238438Sdteske # 99238438Sdteske # In POSIX bourne-shell, attempting to unset(1) OPTIND results 100238438Sdteske # in "unset: Illegal number:" and causes abrupt termination. 101238438Sdteske # 102238438Sdteske [ "$var" = OPTIND ] && continue 103238438Sdteske 104238438Sdteske # 105238438Sdteske # Process the exclusion-list? 106238438Sdteske # 107238438Sdteske if [ "$except" ]; then 108238438Sdteske for arg in "$@" ""; do 109238438Sdteske [ "$var" = "$arg" ] && break 110238438Sdteske done 111238438Sdteske [ "$arg" ] && continue 112238438Sdteske fi 113238438Sdteske 114238438Sdteske unset "$var" 115238438Sdteske done 116238438Sdteske} 117238438Sdteske 118238438Sdteske# f_sysrc_get $varname 119238438Sdteske# 120238438Sdteske# Get a system configuration setting from the collection of system- 121258420Sdteske# configuration files (in order: /etc/defaults/rc.conf /etc/rc.conf and 122258420Sdteske# /etc/rc.conf.local) 123238438Sdteske# 124238438Sdteske# NOTE: Additional shell parameter-expansion formats are supported. For 125238438Sdteske# example, passing an argument of "hostname%%.*" (properly quoted) will 126238438Sdteske# return the hostname up to (but not including) the first `.' (see sh(1), 127238438Sdteske# "Parameter Expansion" for more information on additional formats). 128238438Sdteske# 129238438Sdteskef_sysrc_get() 130238438Sdteske{ 131238438Sdteske # Sanity check 132238438Sdteske [ -f "$RC_DEFAULTS" -a -r "$RC_DEFAULTS" ] || return $FAILURE 133238438Sdteske 134238438Sdteske # Taint-check variable name 135238438Sdteske case "$1" in 136238438Sdteske [0-9]*) 137238438Sdteske # Don't expand possible positional parameters 138252178Sdteske return $FAILURE ;; 139238438Sdteske *) 140238438Sdteske [ "$1" ] || return $FAILURE 141238438Sdteske esac 142238438Sdteske 143238438Sdteske ( # Execute within sub-shell to protect parent environment 144238438Sdteske 145238438Sdteske # 146238438Sdteske # Clear the environment of all variables, preventing the 147238438Sdteske # expansion of normals such as `PS1', `TERM', etc. 148238438Sdteske # 149241042Sdteske f_clean_env --except IFS RC_CONFS RC_DEFAULTS 150238438Sdteske 151240783Sdteske . "$RC_DEFAULTS" > /dev/null 2>&1 152238438Sdteske 153238438Sdteske unset RC_DEFAULTS 154238438Sdteske # no longer needed 155238438Sdteske 156238438Sdteske # 157238438Sdteske # If the query is for `rc_conf_files' then store the value that 158238438Sdteske # we inherited from sourcing RC_DEFAULTS (above) so that we may 159238438Sdteske # conditionally restore this value after source_rc_confs in the 160238438Sdteske # event that RC_CONFS does not customize the value. 161238438Sdteske # 162238438Sdteske if [ "$1" = "rc_conf_files" ]; then 163238438Sdteske _rc_conf_files="$rc_conf_files" 164238438Sdteske fi 165238438Sdteske 166238438Sdteske # 167238438Sdteske # If RC_CONFS is defined, set $rc_conf_files to an explicit 168238438Sdteske # value, modifying the default behavior of source_rc_confs(). 169238438Sdteske # 170240798Sdteske if [ "${RC_CONFS+set}" ]; then 171238438Sdteske rc_conf_files="$RC_CONFS" 172238438Sdteske _rc_confs_set=1 173238438Sdteske fi 174238438Sdteske 175240783Sdteske source_rc_confs > /dev/null 2>&1 176238438Sdteske 177238438Sdteske # 178238438Sdteske # If the query was for `rc_conf_files' AND after calling 179240797Sdteske # source_rc_confs the value has not changed, then we should 180238438Sdteske # restore the value to the one inherited from RC_DEFAULTS 181238438Sdteske # before performing the final query (preventing us from 182238438Sdteske # returning what was set via RC_CONFS when the intent was 183238438Sdteske # instead to query the value from the file(s) specified). 184238438Sdteske # 185238438Sdteske if [ "$1" = "rc_conf_files" -a \ 186238438Sdteske "$_rc_confs_set" -a \ 187238438Sdteske "$rc_conf_files" = "$RC_CONFS" \ 188238438Sdteske ]; then 189238438Sdteske rc_conf_files="$_rc_conf_files" 190238438Sdteske unset _rc_conf_files 191238438Sdteske unset _rc_confs_set 192238438Sdteske fi 193238438Sdteske 194238438Sdteske unset RC_CONFS 195238438Sdteske # no longer needed 196238438Sdteske 197238438Sdteske # 198238438Sdteske # This must be the last functional line for both the sub-shell 199238438Sdteske # and the function to preserve the return status from formats 200238438Sdteske # such as "${varname?}" and "${varname:?}" (see "Parameter 201238438Sdteske # Expansion" in sh(1) for more information). 202238438Sdteske # 203240783Sdteske eval echo '"${'"$1"'}"' 2> /dev/null 204238438Sdteske ) 205238438Sdteske} 206238438Sdteske 207238438Sdteske# f_sysrc_get_default $varname 208238438Sdteske# 209238438Sdteske# Get a system configuration default setting from the default rc.conf(5) file 210238438Sdteske# (or whatever RC_DEFAULTS points at). 211238438Sdteske# 212238438Sdteskef_sysrc_get_default() 213238438Sdteske{ 214238438Sdteske # Sanity check 215238438Sdteske [ -f "$RC_DEFAULTS" -a -r "$RC_DEFAULTS" ] || return $FAILURE 216238438Sdteske 217238438Sdteske # Taint-check variable name 218238438Sdteske case "$1" in 219238438Sdteske [0-9]*) 220238438Sdteske # Don't expand possible positional parameters 221252178Sdteske return $FAILURE ;; 222238438Sdteske *) 223238438Sdteske [ "$1" ] || return $FAILURE 224238438Sdteske esac 225238438Sdteske 226238438Sdteske ( # Execute within sub-shell to protect parent environment 227238438Sdteske 228238438Sdteske # 229238438Sdteske # Clear the environment of all variables, preventing the 230238438Sdteske # expansion of normals such as `PS1', `TERM', etc. 231238438Sdteske # 232238438Sdteske f_clean_env --except RC_DEFAULTS 233238438Sdteske 234240783Sdteske . "$RC_DEFAULTS" > /dev/null 2>&1 235238438Sdteske 236238438Sdteske unset RC_DEFAULTS 237238438Sdteske # no longer needed 238238438Sdteske 239238438Sdteske # 240238438Sdteske # This must be the last functional line for both the sub-shell 241238438Sdteske # and the function to preserve the return status from formats 242238438Sdteske # such as "${varname?}" and "${varname:?}" (see "Parameter 243238438Sdteske # Expansion" in sh(1) for more information). 244238438Sdteske # 245240783Sdteske eval echo '"${'"$1"'}"' 2> /dev/null 246238438Sdteske ) 247238438Sdteske} 248238438Sdteske 249238438Sdteske# f_sysrc_find $varname 250238438Sdteske# 251238438Sdteske# Find which file holds the effective last-assignment to a given variable 252238438Sdteske# within the rc.conf(5) file(s). 253238438Sdteske# 254238438Sdteske# If the variable is found in any of the rc.conf(5) files, the function prints 255238438Sdteske# the filename it was found in and then returns success. Otherwise output is 256238438Sdteske# NULL and the function returns with error status. 257238438Sdteske# 258238438Sdteskef_sysrc_find() 259238438Sdteske{ 260241019Sdteske local varname="${1%%[!$VALID_VARNAME_CHARS]*}" 261238438Sdteske local regex="^[[:space:]]*$varname=" 262238438Sdteske local rc_conf_files="$( f_sysrc_get rc_conf_files )" 263238438Sdteske local conf_files= 264238438Sdteske local file 265238438Sdteske 266238438Sdteske # Check parameters 267241019Sdteske case "$varname" in 268241019Sdteske ""|[0-9]*) return $FAILURE 269241019Sdteske esac 270238438Sdteske 271238438Sdteske # 272238438Sdteske # If RC_CONFS is defined, set $rc_conf_files to an explicit 273238438Sdteske # value, modifying the default behavior of source_rc_confs(). 274238438Sdteske # 275240863Sdteske [ "${RC_CONFS+set}" ] && rc_conf_files="$RC_CONFS" 276238438Sdteske 277238438Sdteske # 278238438Sdteske # Reverse the order of files in rc_conf_files (the boot process sources 279238438Sdteske # these in order, so we will search them in reverse-order to find the 280238438Sdteske # last-assignment -- the one that ultimately effects the environment). 281238438Sdteske # 282238438Sdteske for file in $rc_conf_files; do 283238438Sdteske conf_files="$file${conf_files:+ }$conf_files" 284238438Sdteske done 285238438Sdteske 286238438Sdteske # 287238438Sdteske # Append the defaults file (since directives in the defaults file 288238438Sdteske # indeed affect the boot process, we'll want to know when a directive 289238438Sdteske # is found there). 290238438Sdteske # 291238438Sdteske conf_files="$conf_files${conf_files:+ }$RC_DEFAULTS" 292238438Sdteske 293238438Sdteske # 294238438Sdteske # Find which file matches assignment to the given variable name. 295238438Sdteske # 296238438Sdteske for file in $conf_files; do 297238438Sdteske [ -f "$file" -a -r "$file" ] || continue 298238438Sdteske if grep -Eq "$regex" $file; then 299238438Sdteske echo $file 300238438Sdteske return $SUCCESS 301238438Sdteske fi 302238438Sdteske done 303238438Sdteske 304238438Sdteske return $FAILURE # Not found 305238438Sdteske} 306238438Sdteske 307238438Sdteske# f_sysrc_desc $varname 308238438Sdteske# 309238438Sdteske# Attempts to return the comments associated with varname from the rc.conf(5) 310238438Sdteske# defaults file `/etc/defaults/rc.conf' (or whatever RC_DEFAULTS points to). 311238438Sdteske# 312238438Sdteske# Multi-line comments are joined together. Results are NULL if no description 313238438Sdteske# could be found. 314238438Sdteske# 315238438Sdteske# This function is a two-parter. Below is the awk(1) portion of the function, 316238438Sdteske# afterward is the sh(1) function which utilizes the below awk script. 317238438Sdteske# 318238438Sdteskef_sysrc_desc_awk=' 319238438Sdteske# Variables that should be defined on the invocation line: 320238438Sdteske# -v varname="varname" 321238438Sdteske# 322238438SdteskeBEGIN { 323238438Sdteske regex = "^[[:space:]]*"varname"=" 324238438Sdteske found = 0 325238438Sdteske buffer = "" 326238438Sdteske} 327238438Sdteske{ 328238438Sdteske if ( ! found ) 329238438Sdteske { 330238438Sdteske if ( ! match($0, regex) ) next 331238438Sdteske 332238438Sdteske found = 1 333238438Sdteske sub(/^[^#]*(#[[:space:]]*)?/, "") 334238438Sdteske buffer = $0 335238438Sdteske next 336238438Sdteske } 337238438Sdteske 338238438Sdteske if ( !/^[[:space:]]*#/ || 339238438Sdteske /^[[:space:]]*[[:alpha:]_][[:alnum:]_]*=/ || 340238438Sdteske /^[[:space:]]*#[[:alpha:]_][[:alnum:]_]*=/ || 341238438Sdteske /^[[:space:]]*$/ ) exit 342238438Sdteske 343238438Sdteske sub(/(.*#)*[[:space:]]*/, "") 344238438Sdteske buffer = buffer" "$0 345238438Sdteske} 346238438SdteskeEND { 347238438Sdteske # Clean up the buffer 348238438Sdteske sub(/^[[:space:]]*/, "", buffer) 349238438Sdteske sub(/[[:space:]]*$/, "", buffer) 350238438Sdteske 351238438Sdteske print buffer 352238438Sdteske exit ! found 353238438Sdteske} 354238438Sdteske' 355238438Sdteskef_sysrc_desc() 356238438Sdteske{ 357238438Sdteske awk -v varname="$1" "$f_sysrc_desc_awk" < "$RC_DEFAULTS" 358238438Sdteske} 359238438Sdteske 360238438Sdteske# f_sysrc_set $varname $new_value 361238438Sdteske# 362238438Sdteske# Change a setting in the system configuration files (edits the files in-place 363238438Sdteske# to change the value in the last assignment to the variable). If the variable 364238438Sdteske# does not appear in the source file, it is appended to the end of the primary 365238438Sdteske# system configuration file `/etc/rc.conf'. 366238438Sdteske# 367238438Sdteske# This function is a two-parter. Below is the awk(1) portion of the function, 368238438Sdteske# afterward is the sh(1) function which utilizes the below awk script. 369238438Sdteske# 370238438Sdteskef_sysrc_set_awk=' 371238438Sdteske# Variables that should be defined on the invocation line: 372238438Sdteske# -v varname="varname" 373238438Sdteske# -v new_value="new_value" 374238438Sdteske# 375238438SdteskeBEGIN { 376238438Sdteske regex = "^[[:space:]]*"varname"=" 377238438Sdteske found = retval = 0 378238438Sdteske} 379238438Sdteske{ 380238438Sdteske # If already found... just spew 381238438Sdteske if ( found ) { print; next } 382238438Sdteske 383238438Sdteske # Does this line match an assignment to our variable? 384238438Sdteske if ( ! match($0, regex) ) { print; next } 385238438Sdteske 386238438Sdteske # Save important match information 387238438Sdteske found = 1 388238438Sdteske matchlen = RSTART + RLENGTH - 1 389238438Sdteske 390238438Sdteske # Store the value text for later munging 391238438Sdteske value = substr($0, matchlen + 1, length($0) - matchlen) 392238438Sdteske 393238438Sdteske # Store the first character of the value 394238438Sdteske t1 = t2 = substr(value, 0, 1) 395238438Sdteske 396238438Sdteske # Assignment w/ back-ticks, expression, or misc. 397238438Sdteske # We ignore these since we did not generate them 398238438Sdteske # 399238438Sdteske if ( t1 ~ /[`$\\]/ ) { retval = 1; print; next } 400238438Sdteske 401238438Sdteske # Assignment w/ single-quoted value 402238438Sdteske else if ( t1 == "'\''" ) { 403238438Sdteske sub(/^'\''[^'\'']*/, "", value) 404238438Sdteske if ( length(value) == 0 ) t2 = "" 405238438Sdteske sub(/^'\''/, "", value) 406238438Sdteske } 407238438Sdteske 408238438Sdteske # Assignment w/ double-quoted value 409238438Sdteske else if ( t1 == "\"" ) { 410238438Sdteske sub(/^"(.*\\\\+")*[^"]*/, "", value) 411238438Sdteske if ( length(value) == 0 ) t2 = "" 412238438Sdteske sub(/^"/, "", value) 413238438Sdteske } 414238438Sdteske 415238438Sdteske # Assignment w/ non-quoted value 416238438Sdteske else if ( t1 ~ /[^[:space:];]/ ) { 417238438Sdteske t1 = t2 = "\"" 418238438Sdteske sub(/^[^[:space:]]*/, "", value) 419238438Sdteske } 420238438Sdteske 421238438Sdteske # Null-assignment 422238438Sdteske else if ( t1 ~ /[[:space:];]/ ) { t1 = t2 = "\"" } 423238438Sdteske 424238438Sdteske printf "%s%c%s%c%s\n", substr($0, 0, matchlen), \ 425238438Sdteske t1, new_value, t2, value 426238438Sdteske} 427238438SdteskeEND { exit retval } 428238438Sdteske' 429238438Sdteskef_sysrc_set() 430238438Sdteske{ 431260678Sdteske local funcname=f_sysrc_set 432238438Sdteske local varname="$1" new_value="$2" 433238438Sdteske 434238438Sdteske # Check arguments 435238438Sdteske [ "$varname" ] || return $FAILURE 436238438Sdteske 437238438Sdteske # 438238438Sdteske # Find which rc.conf(5) file contains the last-assignment 439238438Sdteske # 440238438Sdteske local not_found= 441238438Sdteske local file="$( f_sysrc_find "$varname" )" 442238438Sdteske if [ "$file" = "$RC_DEFAULTS" -o ! "$file" ]; then 443238438Sdteske # 444238438Sdteske # We either got a null response (not found) or the variable 445238438Sdteske # was only found in the rc.conf(5) defaults. In either case, 446238438Sdteske # let's instead modify the first file from $rc_conf_files. 447238438Sdteske # 448238438Sdteske 449238438Sdteske not_found=1 450238438Sdteske 451238438Sdteske # 452238438Sdteske # If RC_CONFS is defined, use $RC_CONFS 453238438Sdteske # rather than $rc_conf_files. 454238438Sdteske # 455240863Sdteske if [ "${RC_CONFS+set}" ]; then 456238438Sdteske file="${RC_CONFS%%[$IFS]*}" 457238438Sdteske else 458241042Sdteske file=$( f_sysrc_get 'rc_conf_files%%[$IFS]*' ) 459238438Sdteske fi 460238438Sdteske fi 461238438Sdteske 462238438Sdteske # 463238438Sdteske # If not found, append new value to last file and return. 464238438Sdteske # 465238438Sdteske if [ "$not_found" ]; then 466238438Sdteske echo "$varname=\"$new_value\"" >> "$file" 467238438Sdteske return $? 468238438Sdteske fi 469238438Sdteske 470238438Sdteske # 471238438Sdteske # Perform sanity checks. 472238438Sdteske # 473238438Sdteske if [ ! -w "$file" ]; then 474238438Sdteske f_err "$msg_cannot_create_permission_denied\n" \ 475238438Sdteske "$pgm" "$file" 476238438Sdteske return $FAILURE 477238438Sdteske fi 478238438Sdteske 479238438Sdteske # 480238438Sdteske # Create a new temporary file to write to. 481238438Sdteske # 482260678Sdteske local tmpfile 483260678Sdteske if ! f_eval_catch -dk tmpfile $funcname mktemp 'mktemp -t "%s"' "$pgm" 484260678Sdteske then 485260678Sdteske echo "$tmpfile" >&2 486260678Sdteske return $FAILURE 487260678Sdteske fi 488238438Sdteske 489238438Sdteske # 490238438Sdteske # Fixup permissions (else we're in for a surprise, as mktemp(1) creates 491238438Sdteske # the temporary file with 0600 permissions, and if we simply mv(1) the 492238438Sdteske # temporary file over the destination, the destination will inherit the 493238438Sdteske # permissions from the temporary file). 494238438Sdteske # 495238438Sdteske local mode 496260678Sdteske f_eval_catch -dk mode $funcname stat 'stat -f "%%#Lp" "%s"' "$file" || 497260678Sdteske mode=0644 498260678Sdteske f_eval_catch -d $funcname chmod 'chmod "%s" "%s"' "$mode" "$tmpfile" 499238438Sdteske 500238438Sdteske # 501238438Sdteske # Fixup ownership. The destination file _is_ writable (we tested 502238438Sdteske # earlier above). However, this will fail if we don't have sufficient 503238438Sdteske # permissions (so we throw stderr into the bit-bucket). 504238438Sdteske # 505238438Sdteske local owner 506260678Sdteske f_eval_catch -dk owner $funcname stat \ 507260678Sdteske 'stat -f "%%u:%%g" "%s"' "$file" || owner="root:wheel" 508260678Sdteske f_eval_catch -d $funcname chown 'chown "%s" "%s"' "$owner" "$tmpfile" 509238438Sdteske 510238438Sdteske # 511238438Sdteske # Operate on the matching file, replacing only the last occurrence. 512238438Sdteske # 513238438Sdteske local new_contents retval 514240783Sdteske new_contents=$( tail -r $file 2> /dev/null ) 515238438Sdteske new_contents=$( echo "$new_contents" | awk -v varname="$varname" \ 516238438Sdteske -v new_value="$new_value" "$f_sysrc_set_awk" ) 517238438Sdteske retval=$? 518238438Sdteske 519238438Sdteske # 520238438Sdteske # Write the temporary file contents. 521238438Sdteske # 522238438Sdteske echo "$new_contents" | tail -r > "$tmpfile" || return $FAILURE 523238438Sdteske if [ $retval -ne $SUCCESS ]; then 524238438Sdteske echo "$varname=\"$new_value\"" >> "$tmpfile" 525238438Sdteske fi 526238438Sdteske 527238438Sdteske # 528238438Sdteske # Taint-check our results. 529238438Sdteske # 530260678Sdteske if ! f_eval_catch -d $funcname sh '/bin/sh -n "%s"' "$tmpfile"; then 531238438Sdteske f_err "$msg_previous_syntax_errors\n" "$pgm" "$file" 532238438Sdteske rm -f "$tmpfile" 533238438Sdteske return $FAILURE 534238438Sdteske fi 535238438Sdteske 536238438Sdteske # 537238438Sdteske # Finally, move the temporary file into place. 538238438Sdteske # 539260678Sdteske f_eval_catch -de $funcname mv 'mv "%s" "%s"' "$tmpfile" "$file" 540238438Sdteske} 541238438Sdteske 542238438Sdteske# f_sysrc_delete $varname 543238438Sdteske# 544238438Sdteske# Remove a setting from the system configuration files (edits files in-place). 545238438Sdteske# Deletes all assignments to the given variable in all config files. If the 546238438Sdteske# `-f file' option is passed, the removal is restricted to only those files 547238438Sdteske# specified, otherwise the system collection of rc_conf_files is used. 548238438Sdteske# 549238438Sdteske# This function is a two-parter. Below is the awk(1) portion of the function, 550238438Sdteske# afterward is the sh(1) function which utilizes the below awk script. 551238438Sdteske# 552238438Sdteskef_sysrc_delete_awk=' 553238438Sdteske# Variables that should be defined on the invocation line: 554238438Sdteske# -v varname="varname" 555238438Sdteske# 556238438SdteskeBEGIN { 557238438Sdteske regex = "^[[:space:]]*"varname"=" 558238438Sdteske found = 0 559238438Sdteske} 560238438Sdteske{ 561238438Sdteske if ( $0 ~ regex ) 562238438Sdteske found = 1 563238438Sdteske else 564238438Sdteske print 565238438Sdteske} 566238438SdteskeEND { exit ! found } 567238438Sdteske' 568238438Sdteskef_sysrc_delete() 569238438Sdteske{ 570260678Sdteske local funcname=f_sysrc_delete 571238438Sdteske local varname="$1" 572238438Sdteske local file 573238438Sdteske 574238438Sdteske # Check arguments 575238438Sdteske [ "$varname" ] || return $FAILURE 576238438Sdteske 577238438Sdteske # 578238438Sdteske # Operate on each of the specified files 579238438Sdteske # 580260678Sdteske local tmpfile 581240863Sdteske for file in ${RC_CONFS-$( f_sysrc_get rc_conf_files )}; do 582238438Sdteske [ -e "$file" ] || continue 583238438Sdteske 584238438Sdteske # 585238438Sdteske # Create a new temporary file to write to. 586238438Sdteske # 587260678Sdteske if ! f_eval_catch -dk tmpfile $funcname mktemp \ 588260678Sdteske 'mktemp -t "%s"' "$pgm" 589260678Sdteske then 590260678Sdteske echo "$tmpfile" >&2 591260678Sdteske return $FAILURE 592260678Sdteske fi 593238438Sdteske 594238438Sdteske # 595238438Sdteske # Fixup permissions and ownership (mktemp(1) defaults to 0600 596238438Sdteske # permissions) to instead match the destination file. 597238438Sdteske # 598238438Sdteske local mode owner 599260678Sdteske f_eval_catch -dk mode $funcname stat \ 600260678Sdteske 'stat -f "%%#Lp" "%s"' "$file" || mode=0644 601260678Sdteske f_eval_catch -dk owner $funcname stat \ 602260678Sdteske 'stat -f "%%u:%%g" "%s"' "$file" || owner="root:wheel" 603260678Sdteske f_eval_catch -d $funcname chmod \ 604260678Sdteske 'chmod "%s" "%s"' "$mode" "$tmpfile" 605260678Sdteske f_eval_catch -d $funcname chown \ 606260678Sdteske 'chown "%s" "%s"' "$owner" "$tmpfile" 607238438Sdteske 608238438Sdteske # 609238438Sdteske # Operate on the file, removing all occurrences, saving the 610238438Sdteske # output in our temporary file. 611238438Sdteske # 612238438Sdteske awk -v varname="$varname" "$f_sysrc_delete_awk" "$file" \ 613238438Sdteske > "$tmpfile" 614238438Sdteske if [ $? -ne $SUCCESS ]; then 615238438Sdteske # The file didn't contain any assignments 616238438Sdteske rm -f "$tmpfile" 617238438Sdteske continue 618238438Sdteske fi 619238438Sdteske 620238438Sdteske # 621238438Sdteske # Taint-check our results. 622238438Sdteske # 623260678Sdteske if ! f_eval_catch -d $funcname sh '/bin/sh -n "%s"' "$tmpfile" 624260678Sdteske then 625238438Sdteske f_err "$msg_previous_syntax_errors\n" \ 626238438Sdteske "$pgm" "$file" 627238438Sdteske rm -f "$tmpfile" 628238438Sdteske return $FAILURE 629238438Sdteske fi 630238438Sdteske 631238438Sdteske # 632238438Sdteske # Perform sanity checks 633238438Sdteske # 634238438Sdteske if [ ! -w "$file" ]; then 635238438Sdteske f_err "$msg_permission_denied\n" "$pgm" "$file" 636238438Sdteske rm -f "$tmpfile" 637238438Sdteske return $FAILURE 638238438Sdteske fi 639238438Sdteske 640238438Sdteske # 641238438Sdteske # Finally, move the temporary file into place. 642238438Sdteske # 643260678Sdteske f_eval_catch -de $funcname mv \ 644260678Sdteske 'mv "%s" "%s"' "$tmpfile" "$file" || return $FAILURE 645238438Sdteske done 646238438Sdteske} 647238438Sdteske 648244675Sdteske############################################################ MAIN 649244675Sdteske 650244675Sdteskef_dprintf "%s: Successfully loaded." sysrc.subr 651244675Sdteske 652238438Sdteskefi # ! $_SYSRC_SUBR 653