1if [ ! "$_SYSRC_SUBR" ]; then _SYSRC_SUBR=1 2# 3# Copyright (c) 2006-2015 Devin Teske 4# All rights reserved. 5# 6# Redistribution and use in source and binary forms, with or without 7# modification, are permitted provided that the following conditions 8# are met: 9# 1. Redistributions of source code must retain the above copyright 10# notice, this list of conditions and the following disclaimer. 11# 2. Redistributions in binary form must reproduce the above copyright 12# notice, this list of conditions and the following disclaimer in the 13# documentation and/or other materials provided with the distribution. 14# 15# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25# SUCH DAMAGE. 26# 27# $FreeBSD$ 28# 29############################################################ INCLUDES 30 31BSDCFG_SHARE="/usr/share/bsdconfig" 32[ "$_COMMON_SUBR" ] || . $BSDCFG_SHARE/common.subr || exit 1 33 34BSDCFG_LIBE="/usr/libexec/bsdconfig" 35if [ ! "$_SYSRC_JAILED" ]; then 36 f_dprintf "%s: loading includes..." sysrc.subr 37 f_include_lang $BSDCFG_LIBE/include/messages.subr 38fi 39 40############################################################ CONFIGURATION 41 42# 43# Standard pathnames (inherit values from shell if available) 44# 45: ${RC_DEFAULTS:="/etc/defaults/rc.conf"} 46 47############################################################ GLOBALS 48 49# 50# Global exit status variables 51# 52SUCCESS=0 53FAILURE=1 54 55# 56# Valid characters that can appear in an sh(1) variable name 57# 58# Please note that the character ranges A-Z and a-z should be avoided because 59# these can include accent characters (which are not valid in a variable name). 60# For example, A-Z matches any character that sorts after A but before Z, 61# including A and Z. Although ASCII order would make more sense, that is not 62# how it works. 63# 64VALID_VARNAME_CHARS="0-9ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_" 65 66############################################################ FUNCTIONS 67 68# f_clean_env [ --except $varname ... ] 69# 70# Unset all environment variables in the current scope. An optional list of 71# arguments can be passed, indicating which variables to avoid unsetting; the 72# `--except' is required to enable the exclusion-list as the remainder of 73# positional arguments. 74# 75# Be careful not to call this in a shell that you still expect to perform 76# $PATH expansion in, because this will blow $PATH away. This is best used 77# within a sub-shell block "(...)" or "$(...)" or "`...`". 78# 79f_clean_env() 80{ 81 local var arg except= 82 83 # 84 # Should we process an exclusion-list? 85 # 86 if [ "$1" = "--except" ]; then 87 except=1 88 shift 1 89 fi 90 91 # 92 # Loop over a list of variable names from set(1) built-in. 93 # 94 for var in $( set | awk -F= \ 95 '/^[[:alpha:]_][[:alnum:]_]*=/ {print $1}' \ 96 | grep -v '^except$' 97 ); do 98 # 99 # In POSIX bourne-shell, attempting to unset(1) OPTIND results 100 # in "unset: Illegal number:" and causes abrupt termination. 101 # 102 [ "$var" = OPTIND ] && continue 103 104 # 105 # Process the exclusion-list? 106 # 107 if [ "$except" ]; then 108 for arg in "$@" ""; do 109 [ "$var" = "$arg" ] && break 110 done 111 [ "$arg" ] && continue 112 fi 113 114 unset "$var" 115 done 116} 117 118# f_sysrc_get $varname 119# 120# Get a system configuration setting from the collection of system- 121# configuration files (in order: /etc/defaults/rc.conf /etc/rc.conf and 122# /etc/rc.conf.local) 123# 124# NOTE: Additional shell parameter-expansion formats are supported. For 125# example, passing an argument of "hostname%%.*" (properly quoted) will 126# return the hostname up to (but not including) the first `.' (see sh(1), 127# "Parameter Expansion" for more information on additional formats). 128# 129f_sysrc_get() 130{ 131 # Sanity check 132 [ -f "$RC_DEFAULTS" -a -r "$RC_DEFAULTS" ] || return $FAILURE 133 134 # Taint-check variable name 135 case "$1" in 136 [0-9]*) 137 # Don't expand possible positional parameters 138 return $FAILURE ;; 139 *) 140 [ "$1" ] || return $FAILURE 141 esac 142 143 ( # Execute within sub-shell to protect parent environment 144 145 # 146 # Clear the environment of all variables, preventing the 147 # expansion of normals such as `PS1', `TERM', etc. 148 # 149 f_clean_env --except IFS RC_CONFS RC_DEFAULTS 150 151 . "$RC_DEFAULTS" > /dev/null 2>&1 152 153 unset RC_DEFAULTS 154 # no longer needed 155 156 # 157 # If the query is for `rc_conf_files' then store the value that 158 # we inherited from sourcing RC_DEFAULTS (above) so that we may 159 # conditionally restore this value after source_rc_confs in the 160 # event that RC_CONFS does not customize the value. 161 # 162 if [ "$1" = "rc_conf_files" ]; then 163 _rc_conf_files="$rc_conf_files" 164 fi 165 166 # 167 # If RC_CONFS is defined, set $rc_conf_files to an explicit 168 # value, modifying the default behavior of source_rc_confs(). 169 # 170 if [ "${RC_CONFS+set}" ]; then 171 rc_conf_files="$RC_CONFS" 172 _rc_confs_set=1 173 fi 174 175 source_rc_confs > /dev/null 2>&1 176 177 # 178 # If the query was for `rc_conf_files' AND after calling 179 # source_rc_confs the value has not changed, then we should 180 # restore the value to the one inherited from RC_DEFAULTS 181 # before performing the final query (preventing us from 182 # returning what was set via RC_CONFS when the intent was 183 # instead to query the value from the file(s) specified). 184 # 185 if [ "$1" = "rc_conf_files" -a \ 186 "$_rc_confs_set" -a \ 187 "$rc_conf_files" = "$RC_CONFS" \ 188 ]; then 189 rc_conf_files="$_rc_conf_files" 190 unset _rc_conf_files 191 unset _rc_confs_set 192 fi 193 194 unset RC_CONFS 195 # no longer needed 196 197 # 198 # This must be the last functional line for both the sub-shell 199 # and the function to preserve the return status from formats 200 # such as "${varname?}" and "${varname:?}" (see "Parameter 201 # Expansion" in sh(1) for more information). 202 # 203 eval echo '"${'"$1"'}"' 2> /dev/null 204 ) 205} 206 207# f_sysrc_service_configs [-a|-p] $name [$var_to_set] 208# 209# Get a list of optional `rc.conf.d' entries sourced by system `rc.d' script 210# $name (see rc.subr(8) for additional information on `rc.conf.d'). If $name 211# exists in `/etc/rc.d' or $local_startup directories and is an rc(8) script 212# the result is a space separated list of `rc.conf.d' entries sourced by the 213# $name `rc.d' script. Otherwise, if $name exists as a binary `rc.d' script, 214# the result is ``/etc/rc.conf.d/$name /usr/local/etc/rc.conf.d/$name''. The 215# result is NULL if $name does not exist. 216# 217# If $var_to_set is missing or NULL, output is to standard out. Returns success 218# if $name was found, failure otherwise. 219# 220# If `-a' flag is given and $var_to_set is non-NULL, append result to value of 221# $var_to_set rather than overwriting current contents. 222# 223# If `-p' flag is given and $var_to_set is non-NULL, prepend result to value of 224# $var_to_set rather than overwriting current contents. 225# 226# NB: The `-a' and `-p' option flags are mutually exclusive. 227# 228f_sysrc_service_configs() 229{ 230 local OPTIND=1 OPTARG __flag __append= __prepend= 231 local __local_startup __dir __spath __stype __names= 232 233 while getopts ap __flag; do 234 case "$__flag" in 235 a) __append=1 __prepend= ;; 236 p) __prepend=1 __append= ;; 237 esac 238 done 239 shift $(( $OPTIND - 1 )) 240 241 [ $# -gt 0 ] || return $FAILURE 242 local __sname="$1" __var_to_set="$2" 243 244 __local_startup=$( f_sysrc_get local_startup ) 245 for __dir in /etc/rc.d $__local_startup; do 246 __spath="$__dir/$__sname" 247 [ -f "$__spath" -a -x "$__spath" ] || __spath= continue 248 break 249 done 250 [ "$__spath" ] || return $FAILURE 251 252 __stype=$( file -b "$__spath" 2> /dev/null ) 253 case "$__stype" in 254 *"shell script"*) 255 __names=$( exec 9<&1 1>&- 2>&- 256 last_name= 257 print_name() { 258 local name="$1" 259 case "$name" in 260 ""|.|..|*/*|"$last_name") return ;; 261 esac 262 echo "$name" >&9 263 last_name="$name" 264 } 265 eval "$( awk '{ 266 gsub(/load_rc_config /, "print_name ") 267 gsub(/run_rc_command /, ": ") 268 print 269 }' "$__spath" )" 270 ) ;; 271 *) 272 __names="$__sname" 273 esac 274 275 local __name __test_path __configs= 276 for __name in $__names; do 277 for __dir in /etc/rc.d $__local_startup; do 278 __test_path="${__dir%/rc.d}/rc.conf.d/$__name" 279 [ -d "$__test_path" ] || 280 __configs="$__configs $__test_path" continue 281 for __test_path in "$__test_path"/*; do 282 [ -f "$__test_path" ] || continue 283 __configs="$__configs $__test_path" 284 done 285 done 286 done 287 __configs="${__configs# }" 288 289 if [ "$__var_to_set" ]; then 290 local __cur= 291 [ "$__append" -o "$__prepend" ] && 292 f_getvar "$__var_to_set" __cur 293 [ "$__append" ] && __configs="$__cur{$__cur:+ }$__configs" 294 [ "$__prepend" ] && __configs="$__configs${__cur:+ }$__cur" 295 setvar "$__var_to_set" "$__configs" 296 else 297 echo "$__configs" 298 fi 299 300 return $SUCCESS 301} 302 303# f_sysrc_get_default $varname 304# 305# Get a system configuration default setting from the default rc.conf(5) file 306# (or whatever RC_DEFAULTS points at). 307# 308f_sysrc_get_default() 309{ 310 # Sanity check 311 [ -f "$RC_DEFAULTS" -a -r "$RC_DEFAULTS" ] || return $FAILURE 312 313 # Taint-check variable name 314 case "$1" in 315 [0-9]*) 316 # Don't expand possible positional parameters 317 return $FAILURE ;; 318 *) 319 [ "$1" ] || return $FAILURE 320 esac 321 322 ( # Execute within sub-shell to protect parent environment 323 324 # 325 # Clear the environment of all variables, preventing the 326 # expansion of normals such as `PS1', `TERM', etc. 327 # 328 f_clean_env --except RC_DEFAULTS 329 330 . "$RC_DEFAULTS" > /dev/null 2>&1 331 332 unset RC_DEFAULTS 333 # no longer needed 334 335 # 336 # This must be the last functional line for both the sub-shell 337 # and the function to preserve the return status from formats 338 # such as "${varname?}" and "${varname:?}" (see "Parameter 339 # Expansion" in sh(1) for more information). 340 # 341 eval echo '"${'"$1"'}"' 2> /dev/null 342 ) 343} 344 345# f_sysrc_find $varname 346# 347# Find which file holds the effective last-assignment to a given variable 348# within the rc.conf(5) file(s). 349# 350# If the variable is found in any of the rc.conf(5) files, the function prints 351# the filename it was found in and then returns success. Otherwise output is 352# NULL and the function returns with error status. 353# 354f_sysrc_find() 355{ 356 local varname="${1%%[!$VALID_VARNAME_CHARS]*}" 357 local regex="^[[:space:]]*$varname=" 358 local rc_conf_files="$( f_sysrc_get rc_conf_files )" 359 local conf_files= 360 local file 361 362 # Check parameters 363 case "$varname" in 364 ""|[0-9]*) return $FAILURE 365 esac 366 367 # 368 # If RC_CONFS is defined, set $rc_conf_files to an explicit 369 # value, modifying the default behavior of source_rc_confs(). 370 # 371 [ "${RC_CONFS+set}" ] && rc_conf_files="$RC_CONFS" 372 373 # 374 # Reverse the order of files in rc_conf_files (the boot process sources 375 # these in order, so we will search them in reverse-order to find the 376 # last-assignment -- the one that ultimately effects the environment). 377 # 378 for file in $rc_conf_files; do 379 conf_files="$file${conf_files:+ }$conf_files" 380 done 381 382 # 383 # Append the defaults file (since directives in the defaults file 384 # indeed affect the boot process, we'll want to know when a directive 385 # is found there). 386 # 387 conf_files="$conf_files${conf_files:+ }$RC_DEFAULTS" 388 389 # 390 # Find which file matches assignment to the given variable name. 391 # 392 for file in $conf_files; do 393 [ -f "$file" -a -r "$file" ] || continue 394 if grep -Eq "$regex" $file; then 395 echo $file 396 return $SUCCESS 397 fi 398 done 399 400 return $FAILURE # Not found 401} 402 403# f_sysrc_desc $varname 404# 405# Attempts to return the comments associated with varname from the rc.conf(5) 406# defaults file `/etc/defaults/rc.conf' (or whatever RC_DEFAULTS points to). 407# 408# Multi-line comments are joined together. Results are NULL if no description 409# could be found. 410# 411# This function is a two-parter. Below is the awk(1) portion of the function, 412# afterward is the sh(1) function which utilizes the below awk script. 413# 414f_sysrc_desc_awk=' 415# Variables that should be defined on the invocation line: 416# -v varname="varname" 417# 418BEGIN { 419 regex = "^[[:space:]]*"varname"=" 420 found = 0 421 buffer = "" 422} 423{ 424 if ( ! found ) 425 { 426 if ( ! match($0, regex) ) next 427 428 found = 1 429 sub(/^[^#]*(#[[:space:]]*)?/, "") 430 buffer = $0 431 next 432 } 433 434 if ( !/^[[:space:]]*#/ || 435 /^[[:space:]]*[[:alpha:]_][[:alnum:]_]*=/ || 436 /^[[:space:]]*#[[:alpha:]_][[:alnum:]_]*=/ || 437 /^[[:space:]]*$/ ) exit 438 439 sub(/(.*#)*[[:space:]]*/, "") 440 buffer = buffer" "$0 441} 442END { 443 # Clean up the buffer 444 sub(/^[[:space:]]*/, "", buffer) 445 sub(/[[:space:]]*$/, "", buffer) 446 447 print buffer 448 exit ! found 449} 450' 451f_sysrc_desc() 452{ 453 awk -v varname="$1" "$f_sysrc_desc_awk" < "$RC_DEFAULTS" 454} 455 456# f_sysrc_set $varname $new_value 457# 458# Change a setting in the system configuration files (edits the files in-place 459# to change the value in the last assignment to the variable). If the variable 460# does not appear in the source file, it is appended to the end of the primary 461# system configuration file `/etc/rc.conf'. 462# 463# This function is a two-parter. Below is the awk(1) portion of the function, 464# afterward is the sh(1) function which utilizes the below awk script. 465# 466f_sysrc_set_awk=' 467# Variables that should be defined on the invocation line: 468# -v varname="varname" 469# -v new_value="new_value" 470# 471BEGIN { 472 regex = "^[[:space:]]*"varname"=" 473 found = retval = 0 474} 475{ 476 # If already found... just spew 477 if ( found ) { print; next } 478 479 # Does this line match an assignment to our variable? 480 if ( ! match($0, regex) ) { print; next } 481 482 # Save important match information 483 found = 1 484 matchlen = RSTART + RLENGTH - 1 485 486 # Store the value text for later munging 487 value = substr($0, matchlen + 1, length($0) - matchlen) 488 489 # Store the first character of the value 490 t1 = t2 = substr(value, 0, 1) 491 492 # Assignment w/ back-ticks, expression, or misc. 493 # We ignore these since we did not generate them 494 # 495 if ( t1 ~ /[`$\\]/ ) { retval = 1; print; next } 496 497 # Assignment w/ single-quoted value 498 else if ( t1 == "'\''" ) { 499 sub(/^'\''[^'\'']*/, "", value) 500 if ( length(value) == 0 ) t2 = "" 501 sub(/^'\''/, "", value) 502 } 503 504 # Assignment w/ double-quoted value 505 else if ( t1 == "\"" ) { 506 sub(/^"(.*\\\\+")*[^"]*/, "", value) 507 if ( length(value) == 0 ) t2 = "" 508 sub(/^"/, "", value) 509 } 510 511 # Assignment w/ non-quoted value 512 else if ( t1 ~ /[^[:space:];]/ ) { 513 t1 = t2 = "\"" 514 sub(/^[^[:space:]]*/, "", value) 515 } 516 517 # Null-assignment 518 else if ( t1 ~ /[[:space:];]/ ) { t1 = t2 = "\"" } 519 520 printf "%s%c%s%c%s\n", substr($0, 0, matchlen), \ 521 t1, new_value, t2, value 522} 523END { exit retval } 524' 525f_sysrc_set() 526{ 527 local funcname=f_sysrc_set 528 local varname="$1" new_value="$2" 529 530 # Check arguments 531 [ "$varname" ] || return $FAILURE 532 533 # 534 # Find which rc.conf(5) file contains the last-assignment 535 # 536 local not_found= 537 local file="$( f_sysrc_find "$varname" )" 538 if [ "$file" = "$RC_DEFAULTS" -o ! "$file" ]; then 539 # 540 # We either got a null response (not found) or the variable 541 # was only found in the rc.conf(5) defaults. In either case, 542 # let's instead modify the first file from $rc_conf_files. 543 # 544 545 not_found=1 546 547 # 548 # If RC_CONFS is defined, use $RC_CONFS 549 # rather than $rc_conf_files. 550 # 551 if [ "${RC_CONFS+set}" ]; then 552 file="${RC_CONFS%%[$IFS]*}" 553 else 554 file=$( f_sysrc_get 'rc_conf_files%%[$IFS]*' ) 555 fi 556 fi 557 558 # 559 # If not found, append new value to last file and return. 560 # 561 if [ "$not_found" ]; then 562 echo "$varname=\"$new_value\"" >> "$file" 563 return $? 564 fi 565 566 # 567 # Perform sanity checks. 568 # 569 if [ ! -w "$file" ]; then 570 f_err "$msg_cannot_create_permission_denied\n" \ 571 "$pgm" "$file" 572 return $FAILURE 573 fi 574 575 # 576 # Create a new temporary file to write to. 577 # 578 local tmpfile 579 if ! f_eval_catch -dk tmpfile $funcname mktemp 'mktemp -t "%s"' "$pgm" 580 then 581 echo "$tmpfile" >&2 582 return $FAILURE 583 fi 584 585 # 586 # Fixup permissions (else we're in for a surprise, as mktemp(1) creates 587 # the temporary file with 0600 permissions, and if we simply mv(1) the 588 # temporary file over the destination, the destination will inherit the 589 # permissions from the temporary file). 590 # 591 local mode 592 f_eval_catch -dk mode $funcname stat 'stat -f "%%#Lp" "%s"' "$file" || 593 mode=0644 594 f_eval_catch -d $funcname chmod 'chmod "%s" "%s"' "$mode" "$tmpfile" 595 596 # 597 # Fixup ownership. The destination file _is_ writable (we tested 598 # earlier above). However, this will fail if we don't have sufficient 599 # permissions (so we throw stderr into the bit-bucket). 600 # 601 local owner 602 f_eval_catch -dk owner $funcname stat \ 603 'stat -f "%%u:%%g" "%s"' "$file" || owner="root:wheel" 604 f_eval_catch -d $funcname chown 'chown "%s" "%s"' "$owner" "$tmpfile" 605 606 # 607 # Operate on the matching file, replacing only the last occurrence. 608 # 609 local new_contents retval 610 new_contents=$( tail -r $file 2> /dev/null ) 611 new_contents=$( echo "$new_contents" | awk -v varname="$varname" \ 612 -v new_value="$new_value" "$f_sysrc_set_awk" ) 613 retval=$? 614 615 # 616 # Write the temporary file contents. 617 # 618 echo "$new_contents" | tail -r > "$tmpfile" || return $FAILURE 619 if [ $retval -ne $SUCCESS ]; then 620 echo "$varname=\"$new_value\"" >> "$tmpfile" 621 fi 622 623 # 624 # Taint-check our results. 625 # 626 if ! f_eval_catch -d $funcname sh '/bin/sh -n "%s"' "$tmpfile"; then 627 f_err "$msg_previous_syntax_errors\n" "$pgm" "$file" 628 rm -f "$tmpfile" 629 return $FAILURE 630 fi 631 632 # 633 # Finally, move the temporary file into place. 634 # 635 f_eval_catch -de $funcname mv 'mv "%s" "%s"' "$tmpfile" "$file" 636} 637 638# f_sysrc_delete $varname 639# 640# Remove a setting from the system configuration files (edits files in-place). 641# Deletes all assignments to the given variable in all config files. If the 642# `-f file' option is passed, the removal is restricted to only those files 643# specified, otherwise the system collection of rc_conf_files is used. 644# 645# This function is a two-parter. Below is the awk(1) portion of the function, 646# afterward is the sh(1) function which utilizes the below awk script. 647# 648f_sysrc_delete_awk=' 649# Variables that should be defined on the invocation line: 650# -v varname="varname" 651# 652BEGIN { 653 regex = "^[[:space:]]*"varname"=" 654 found = 0 655} 656{ 657 if ( $0 ~ regex ) 658 found = 1 659 else 660 print 661} 662END { exit ! found } 663' 664f_sysrc_delete() 665{ 666 local funcname=f_sysrc_delete 667 local varname="$1" 668 local file 669 670 # Check arguments 671 [ "$varname" ] || return $FAILURE 672 673 # 674 # Operate on each of the specified files 675 # 676 local tmpfile 677 for file in ${RC_CONFS-$( f_sysrc_get rc_conf_files )}; do 678 [ -e "$file" ] || continue 679 680 # 681 # Create a new temporary file to write to. 682 # 683 if ! f_eval_catch -dk tmpfile $funcname mktemp \ 684 'mktemp -t "%s"' "$pgm" 685 then 686 echo "$tmpfile" >&2 687 return $FAILURE 688 fi 689 690 # 691 # Fixup permissions and ownership (mktemp(1) defaults to 0600 692 # permissions) to instead match the destination file. 693 # 694 local mode owner 695 f_eval_catch -dk mode $funcname stat \ 696 'stat -f "%%#Lp" "%s"' "$file" || mode=0644 697 f_eval_catch -dk owner $funcname stat \ 698 'stat -f "%%u:%%g" "%s"' "$file" || owner="root:wheel" 699 f_eval_catch -d $funcname chmod \ 700 'chmod "%s" "%s"' "$mode" "$tmpfile" 701 f_eval_catch -d $funcname chown \ 702 'chown "%s" "%s"' "$owner" "$tmpfile" 703 704 # 705 # Operate on the file, removing all occurrences, saving the 706 # output in our temporary file. 707 # 708 awk -v varname="$varname" "$f_sysrc_delete_awk" "$file" \ 709 > "$tmpfile" 710 if [ $? -ne $SUCCESS ]; then 711 # The file didn't contain any assignments 712 rm -f "$tmpfile" 713 continue 714 fi 715 716 # 717 # Taint-check our results. 718 # 719 if ! f_eval_catch -d $funcname sh '/bin/sh -n "%s"' "$tmpfile" 720 then 721 f_err "$msg_previous_syntax_errors\n" \ 722 "$pgm" "$file" 723 rm -f "$tmpfile" 724 return $FAILURE 725 fi 726 727 # 728 # Perform sanity checks 729 # 730 if [ ! -w "$file" ]; then 731 f_err "$msg_permission_denied\n" "$pgm" "$file" 732 rm -f "$tmpfile" 733 return $FAILURE 734 fi 735 736 # 737 # Finally, move the temporary file into place. 738 # 739 f_eval_catch -de $funcname mv \ 740 'mv "%s" "%s"' "$tmpfile" "$file" || return $FAILURE 741 done 742} 743 744############################################################ MAIN 745 746f_dprintf "%s: Successfully loaded." sysrc.subr 747 748fi # ! $_SYSRC_SUBR 749