rc.subr revision 295949
1# $NetBSD: rc.subr,v 1.67 2006/10/07 11:25:15 elad Exp $ 2# $FreeBSD: head/etc/rc.subr 295949 2016-02-24 01:32:12Z araujo $ 3# 4# Copyright (c) 1997-2004 The NetBSD Foundation, Inc. 5# All rights reserved. 6# 7# This code is derived from software contributed to The NetBSD Foundation 8# by Luke Mewburn. 9# 10# Redistribution and use in source and binary forms, with or without 11# modification, are permitted provided that the following conditions 12# are met: 13# 1. Redistributions of source code must retain the above copyright 14# notice, this list of conditions and the following disclaimer. 15# 2. Redistributions in binary form must reproduce the above copyright 16# notice, this list of conditions and the following disclaimer in the 17# documentation and/or other materials provided with the distribution. 18# 19# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29# POSSIBILITY OF SUCH DAMAGE. 30# 31# rc.subr 32# functions used by various rc scripts 33# 34 35: ${RC_PID:=$$}; export RC_PID 36 37# 38# Operating System dependent/independent variables 39# 40 41if [ -z "${_rc_subr_loaded}" ]; then 42 43_rc_subr_loaded="YES" 44 45SYSCTL="/sbin/sysctl" 46SYSCTL_N="${SYSCTL} -n" 47SYSCTL_W="${SYSCTL}" 48PROTECT="/usr/bin/protect" 49ID="/usr/bin/id" 50IDCMD="if [ -x $ID ]; then $ID -un; fi" 51PS="/bin/ps -ww" 52JID=`$PS -p $$ -o jid=` 53 54# 55# functions 56# --------- 57 58# list_vars pattern 59# List vars matching pattern. 60# 61list_vars() 62{ 63 set | { while read LINE; do 64 var="${LINE%%=*}" 65 case "$var" in 66 "$LINE"|*[!a-zA-Z0-9_]*) continue ;; 67 $1) echo $var 68 esac 69 done; } 70} 71 72# set_rcvar [var] [defval] [desc] 73# 74# Echo or define a rc.conf(5) variable name. Global variable 75# $rcvars is used. 76# 77# If no argument is specified, echo "${name}_enable". 78# 79# If only a var is specified, echo "${var}_enable". 80# 81# If var and defval are specified, the ${var} is defined as 82# rc.conf(5) variable and the default value is ${defvar}. An 83# optional argument $desc can also be specified to add a 84# description for that. 85# 86set_rcvar() 87{ 88 local _var 89 90 case $# in 91 0) echo ${name}_enable ;; 92 1) echo ${1}_enable ;; 93 *) 94 debug "set_rcvar: \$$1=$2 is added" \ 95 " as a rc.conf(5) variable." 96 _var=$1 97 rcvars="${rcvars# } $_var" 98 eval ${_var}_defval=\"$2\" 99 shift 2 100 eval ${_var}_desc=\"$*\" 101 ;; 102 esac 103} 104 105# set_rcvar_obsolete oldvar [newvar] [msg] 106# Define obsolete variable. 107# Global variable $rcvars_obsolete is used. 108# 109set_rcvar_obsolete() 110{ 111 local _var 112 _var=$1 113 debug "set_rcvar_obsolete: \$$1(old) -> \$$2(new) is defined" 114 115 rcvars_obsolete="${rcvars_obsolete# } $1" 116 eval ${1}_newvar=\"$2\" 117 shift 2 118 eval ${_var}_obsolete_msg=\"$*\" 119} 120 121# 122# force_depend script [rcvar] 123# Force a service to start. Intended for use by services 124# to resolve dependency issues. 125# $1 - filename of script, in /etc/rc.d, to run 126# $2 - name of the script's rcvar (minus the _enable) 127# 128force_depend() 129{ 130 local _depend _dep_rcvar 131 132 _depend="$1" 133 _dep_rcvar="${2:-$1}_enable" 134 135 [ -n "$rc_fast" ] && ! checkyesno always_force_depends && 136 checkyesno $_dep_rcvar && return 0 137 138 /etc/rc.d/${_depend} forcestatus >/dev/null 2>&1 && return 0 139 140 info "${name} depends on ${_depend}, which will be forced to start." 141 if ! /etc/rc.d/${_depend} forcestart; then 142 warn "Unable to force ${_depend}. It may already be running." 143 return 1 144 fi 145} 146 147# 148# checkyesno var 149# Test $1 variable, and warn if not set to YES or NO. 150# Return 0 if it's "yes" (et al), nonzero otherwise. 151# 152checkyesno() 153{ 154 eval _value=\$${1} 155 debug "checkyesno: $1 is set to $_value." 156 case $_value in 157 158 # "yes", "true", "on", or "1" 159 [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1) 160 return 0 161 ;; 162 163 # "no", "false", "off", or "0" 164 [Nn][Oo]|[Ff][Aa][Ll][Ss][Ee]|[Oo][Ff][Ff]|0) 165 return 1 166 ;; 167 *) 168 warn "\$${1} is not set properly - see rc.conf(5)." 169 return 1 170 ;; 171 esac 172} 173 174# 175# reverse_list list 176# print the list in reverse order 177# 178reverse_list() 179{ 180 _revlist= 181 for _revfile; do 182 _revlist="$_revfile $_revlist" 183 done 184 echo $_revlist 185} 186 187# stop_boot always 188# If booting directly to multiuser or $always is enabled, 189# send SIGTERM to the parent (/etc/rc) to abort the boot. 190# Otherwise just exit. 191# 192stop_boot() 193{ 194 local always 195 196 case $1 in 197 # "yes", "true", "on", or "1" 198 [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1) 199 always=true 200 ;; 201 *) 202 always=false 203 ;; 204 esac 205 if [ "$autoboot" = yes -o "$always" = true ]; then 206 echo "ERROR: ABORTING BOOT (sending SIGTERM to parent)!" 207 kill -TERM ${RC_PID} 208 fi 209 exit 1 210} 211 212# 213# mount_critical_filesystems type 214# Go through the list of critical filesystems as provided in 215# the rc.conf(5) variable $critical_filesystems_${type}, checking 216# each one to see if it is mounted, and if it is not, mounting it. 217# 218mount_critical_filesystems() 219{ 220 eval _fslist=\$critical_filesystems_${1} 221 for _fs in $_fslist; do 222 mount | ( 223 _ismounted=false 224 while read what _on on _type type; do 225 if [ $on = $_fs ]; then 226 _ismounted=true 227 fi 228 done 229 if $_ismounted; then 230 : 231 else 232 mount $_fs >/dev/null 2>&1 233 fi 234 ) 235 done 236} 237 238# 239# check_pidfile pidfile procname [interpreter] 240# Parses the first line of pidfile for a PID, and ensures 241# that the process is running and matches procname. 242# Prints the matching PID upon success, nothing otherwise. 243# interpreter is optional; see _find_processes() for details. 244# 245check_pidfile() 246{ 247 _pidfile=$1 248 _procname=$2 249 _interpreter=$3 250 if [ -z "$_pidfile" -o -z "$_procname" ]; then 251 err 3 'USAGE: check_pidfile pidfile procname [interpreter]' 252 fi 253 if [ ! -f $_pidfile ]; then 254 debug "pid file ($_pidfile): not readable." 255 return 256 fi 257 read _pid _junk < $_pidfile 258 if [ -z "$_pid" ]; then 259 debug "pid file ($_pidfile): no pid in file." 260 return 261 fi 262 _find_processes $_procname ${_interpreter:-.} '-p '"$_pid" 263} 264 265# 266# check_process procname [interpreter] 267# Ensures that a process (or processes) named procname is running. 268# Prints a list of matching PIDs. 269# interpreter is optional; see _find_processes() for details. 270# 271check_process() 272{ 273 _procname=$1 274 _interpreter=$2 275 if [ -z "$_procname" ]; then 276 err 3 'USAGE: check_process procname [interpreter]' 277 fi 278 _find_processes $_procname ${_interpreter:-.} '-ax' 279} 280 281# 282# _find_processes procname interpreter psargs 283# Search for procname in the output of ps generated by psargs. 284# Prints the PIDs of any matching processes, space separated. 285# 286# If interpreter == ".", check the following variations of procname 287# against the first word of each command: 288# procname 289# `basename procname` 290# `basename procname` + ":" 291# "(" + `basename procname` + ")" 292# "[" + `basename procname` + "]" 293# 294# If interpreter != ".", read the first line of procname, remove the 295# leading #!, normalise whitespace, append procname, and attempt to 296# match that against each command, either as is, or with extra words 297# at the end. As an alternative, to deal with interpreted daemons 298# using perl, the basename of the interpreter plus a colon is also 299# tried as the prefix to procname. 300# 301_find_processes() 302{ 303 if [ $# -ne 3 ]; then 304 err 3 'USAGE: _find_processes procname interpreter psargs' 305 fi 306 _procname=$1 307 _interpreter=$2 308 _psargs=$3 309 310 _pref= 311 if [ $_interpreter != "." ]; then # an interpreted script 312 _script="${_chroot}${_chroot:+/}$_procname" 313 if [ -r "$_script" ]; then 314 read _interp < $_script # read interpreter name 315 case "$_interp" in 316 \#!*) 317 _interp=${_interp#\#!} # strip #! 318 set -- $_interp 319 case $1 in 320 */bin/env) 321 shift # drop env to get real name 322 ;; 323 esac 324 if [ $_interpreter != $1 ]; then 325 warn "\$command_interpreter $_interpreter != $1" 326 fi 327 ;; 328 *) 329 warn "no shebang line in $_script" 330 set -- $_interpreter 331 ;; 332 esac 333 else 334 warn "cannot read shebang line from $_script" 335 set -- $_interpreter 336 fi 337 _interp="$* $_procname" # cleanup spaces, add _procname 338 _interpbn=${1##*/} 339 _fp_args='_argv' 340 _fp_match='case "$_argv" in 341 ${_interp}|"${_interp} "*|"[${_interpbn}]"|"${_interpbn}: ${_procname}"*)' 342 else # a normal daemon 343 _procnamebn=${_procname##*/} 344 _fp_args='_arg0 _argv' 345 _fp_match='case "$_arg0" in 346 $_procname|$_procnamebn|${_procnamebn}:|"(${_procnamebn})"|"[${_procnamebn}]")' 347 fi 348 349 _proccheck="\ 350 $PS 2>/dev/null -o pid= -o jid= -o command= $_psargs"' | 351 while read _npid _jid '"$_fp_args"'; do 352 '"$_fp_match"' 353 if [ "$JID" -eq "$_jid" ]; 354 then echo -n "$_pref$_npid"; 355 _pref=" "; 356 fi 357 ;; 358 esac 359 done' 360 361# debug "in _find_processes: proccheck is ($_proccheck)." 362 eval $_proccheck 363} 364 365# sort_lite [-b] [-n] [-k POS] [-t SEP] 366# A lite version of sort(1) (supporting a few options) that can be used 367# before the real sort(1) is available (e.g., in scripts that run prior 368# to mountcritremote). Requires only shell built-in functionality. 369# 370sort_lite() 371{ 372 local funcname=sort_lite 373 local sort_sep="$IFS" sort_ignore_leading_space= 374 local sort_field=0 sort_strict_fields= sort_numeric= 375 local nitems=0 skip_leading=0 trim= 376 377 local OPTIND flag 378 while getopts bnk:t: flag; do 379 case "$flag" in 380 b) sort_ignore_leading_space=1 ;; 381 n) sort_numeric=1 sort_ignore_leading_space=1 ;; 382 k) sort_field="${OPTARG%%,*}" ;; # only up to first comma 383 # NB: Unlike sort(1) only one POS allowed 384 t) sort_sep="$OPTARG" 385 if [ ${#sort_sep} -gt 1 ]; then 386 echo "$funcname: multi-character tab \`$sort_sep'" >&2 387 return 1 388 fi 389 sort_strict_fields=1 390 ;; 391 \?) return 1 ;; 392 esac 393 done 394 shift $(( $OPTIND - 1 )) 395 396 # Create transformation pattern to trim leading text if desired 397 case "$sort_field" in 398 ""|[!0-9]*|*[!0-9.]*) 399 echo "$funcname: invalid sort field \`$sort_field'" >&2 400 return 1 401 ;; 402 *.*) 403 skip_leading=${sort_field#*.} sort_field=${sort_field%%.*} 404 while [ ${skip_leading:-0} -gt 1 ] 2> /dev/null; do 405 trim="$trim?" skip_leading=$(( $skip_leading - 1 )) 406 done 407 esac 408 409 # Copy input to series of local numbered variables 410 # NB: IFS of NULL preserves leading whitespace 411 local LINE 412 while IFS= read -r LINE || [ "$LINE" ]; do 413 nitems=$(( $nitems + 1 )) 414 local src_$nitems="$LINE" 415 done 416 417 # 418 # Sort numbered locals using insertion sort 419 # 420 local curitem curitem_orig curitem_mod curitem_haskey 421 local dest dest_orig dest_mod dest_haskey 422 local d gt n 423 local i=1 424 while [ $i -le $nitems ]; do 425 curitem_haskey=1 # Assume sort field (-k POS) exists 426 eval curitem=\"\$src_$i\" 427 curitem_mod="$curitem" # for modified comparison 428 curitem_orig="$curitem" # for original comparison 429 430 # Trim leading whitespace if desired 431 if [ "$sort_ignore_leading_space" ]; then 432 while case "$curitem_orig" in 433 [$IFS]*) : ;; *) false; esac 434 do 435 curitem_orig="${curitem_orig#?}" 436 done 437 curitem_mod="$curitem_orig" 438 fi 439 440 # Shift modified comparison value if sort field (-k POS) is > 1 441 n=$sort_field 442 while [ $n -gt 1 ]; do 443 case "$curitem_mod" in 444 *[$sort_sep]*) 445 # Cut text up-to (and incl.) first separator 446 curitem_mod="${curitem_mod#*[$sort_sep]}" 447 448 # Skip NULLs unless strict field splitting 449 [ "$sort_strict_fields" ] || 450 [ "${curitem_mod%%[$sort_sep]*}" ] || 451 [ $n -eq 2 ] || 452 continue 453 ;; 454 *) 455 # Asked for a field that doesn't exist 456 curitem_haskey= break 457 esac 458 n=$(( $n - 1 )) 459 done 460 461 # Trim trailing words if sort field >= 1 462 [ $sort_field -ge 1 -a "$sort_numeric" ] && 463 curitem_mod="${curitem_mod%%[$sort_sep]*}" 464 465 # Apply optional trim (-k POS.TRIM) to cut leading characters 466 curitem_mod="${curitem_mod#$trim}" 467 468 # Determine the type of modified comparison to use initially 469 # NB: Prefer numerical if requested but fallback to standard 470 case "$curitem_mod" in 471 ""|[!0-9]*) # NULL or begins with non-number 472 gt=">" 473 [ "$sort_numeric" ] && curitem_mod=0 474 ;; 475 *) 476 if [ "$sort_numeric" ]; then 477 gt="-gt" 478 curitem_mod="${curitem_mod%%[!0-9]*}" 479 # NB: trailing non-digits removed 480 # otherwise numeric comparison fails 481 else 482 gt=">" 483 fi 484 esac 485 486 # If first time through, short-circuit below position-search 487 if [ $i -le 1 ]; then 488 d=0 489 else 490 d=1 491 fi 492 493 # 494 # Find appropriate element position 495 # 496 while [ $d -gt 0 ] 497 do 498 dest_haskey=$curitem_haskey 499 eval dest=\"\$dest_$d\" 500 dest_mod="$dest" # for modified comparison 501 dest_orig="$dest" # for original comparison 502 503 # Trim leading whitespace if desired 504 if [ "$sort_ignore_leading_space" ]; then 505 while case "$dest_orig" in 506 [$IFS]*) : ;; *) false; esac 507 do 508 dest_orig="${dest_orig#?}" 509 done 510 dest_mod="$dest_orig" 511 fi 512 513 # Shift modified value if sort field (-k POS) is > 1 514 n=$sort_field 515 while [ $n -gt 1 ]; do 516 case "$dest_mod" in 517 *[$sort_sep]*) 518 # Cut text up-to (and incl.) 1st sep 519 dest_mod="${dest_mod#*[$sort_sep]}" 520 521 # Skip NULLs unless strict fields 522 [ "$sort_strict_fields" ] || 523 [ "${dest_mod%%[$sort_sep]*}" ] || 524 [ $n -eq 2 ] || 525 continue 526 ;; 527 *) 528 # Asked for a field that doesn't exist 529 dest_haskey= break 530 esac 531 n=$(( $n - 1 )) 532 done 533 534 # Trim trailing words if sort field >= 1 535 [ $sort_field -ge 1 -a "$sort_numeric" ] && 536 dest_mod="${dest_mod%%[$sort_sep]*}" 537 538 # Apply optional trim (-k POS.TRIM), cut leading chars 539 dest_mod="${dest_mod#$trim}" 540 541 # Determine type of modified comparison to use 542 # NB: Prefer numerical if requested, fallback to std 543 case "$dest_mod" in 544 ""|[!0-9]*) # NULL or begins with non-number 545 gt=">" 546 [ "$sort_numeric" ] && dest_mod=0 547 ;; 548 *) 549 if [ "$sort_numeric" ]; then 550 gt="-gt" 551 dest_mod="${dest_mod%%[!0-9]*}" 552 # NB: kill trailing non-digits 553 # for numeric comparison safety 554 else 555 gt=">" 556 fi 557 esac 558 559 # Break if we've found the proper element position 560 if [ "$curitem_haskey" -a "$dest_haskey" ]; then 561 if [ "$dest_mod" = "$curitem_mod" ]; then 562 [ "$dest_orig" ">" "$curitem_orig" ] && 563 break 564 elif [ "$dest_mod" $gt "$curitem_mod" ] \ 565 2> /dev/null 566 then 567 break 568 fi 569 else 570 [ "$dest_orig" ">" "$curitem_orig" ] && break 571 fi 572 573 # Break if we've hit the end 574 [ $d -ge $i ] && break 575 576 d=$(( $d + 1 )) 577 done 578 579 # Shift remaining positions forward, making room for new item 580 n=$i 581 while [ $n -ge $d ]; do 582 # Shift destination item forward one placement 583 eval dest_$(( $n + 1 ))=\"\$dest_$n\" 584 n=$(( $n - 1 )) 585 done 586 587 # Place the element 588 if [ $i -eq 1 ]; then 589 local dest_1="$curitem" 590 else 591 local dest_$d="$curitem" 592 fi 593 594 i=$(( $i + 1 )) 595 done 596 597 # Print sorted results 598 d=1 599 while [ $d -le $nitems ]; do 600 eval echo \"\$dest_$d\" 601 d=$(( $d + 1 )) 602 done 603} 604 605# 606# wait_for_pids pid [pid ...] 607# spins until none of the pids exist 608# 609wait_for_pids() 610{ 611 local _list _prefix _nlist _j 612 613 _list="$@" 614 if [ -z "$_list" ]; then 615 return 616 fi 617 _prefix= 618 while true; do 619 _nlist=""; 620 for _j in $_list; do 621 if kill -0 $_j 2>/dev/null; then 622 _nlist="${_nlist}${_nlist:+ }$_j" 623 [ -n "$_prefix" ] && sleep 1 624 fi 625 done 626 if [ -z "$_nlist" ]; then 627 break 628 fi 629 _list=$_nlist 630 echo -n ${_prefix:-"Waiting for PIDS: "}$_list 631 _prefix=", " 632 pwait $_list 2>/dev/null 633 done 634 if [ -n "$_prefix" ]; then 635 echo "." 636 fi 637} 638 639# 640# get_pidfile_from_conf string file 641# 642# Takes a string to search for in the specified file. 643# Ignores lines with traditional comment characters. 644# 645# Example: 646# 647# if get_pidfile_from_conf string file; then 648# pidfile="$_pidfile_from_conf" 649# else 650# pidfile='appropriate default' 651# fi 652# 653get_pidfile_from_conf() 654{ 655 if [ -z "$1" -o -z "$2" ]; then 656 err 3 "USAGE: get_pidfile_from_conf string file ($name)" 657 fi 658 659 local string file line 660 661 string="$1" ; file="$2" 662 663 if [ ! -s "$file" ]; then 664 err 3 "get_pidfile_from_conf: $file does not exist ($name)" 665 fi 666 667 while read line; do 668 case "$line" in 669 *[#\;]*${string}*) continue ;; 670 *${string}*) break ;; 671 esac 672 done < $file 673 674 if [ -n "$line" ]; then 675 line=${line#*/} 676 _pidfile_from_conf="/${line%%[\"\;]*}" 677 else 678 return 1 679 fi 680} 681 682# 683# check_startmsgs 684# If rc_quiet is set (usually as a result of using faststart at 685# boot time) check if rc_startmsgs is enabled. 686# 687check_startmsgs() 688{ 689 if [ -n "$rc_quiet" ]; then 690 checkyesno rc_startmsgs 691 else 692 return 0 693 fi 694} 695 696# 697# run_rc_command argument 698# Search for argument in the list of supported commands, which is: 699# "start stop restart rcvar status poll ${extra_commands}" 700# If there's a match, run ${argument}_cmd or the default method 701# (see below). 702# 703# If argument has a given prefix, then change the operation as follows: 704# Prefix Operation 705# ------ --------- 706# fast Skip the pid check, and set rc_fast=yes, rc_quiet=yes 707# force Set ${rcvar} to YES, and set rc_force=yes 708# one Set ${rcvar} to YES 709# quiet Don't output some diagnostics, and set rc_quiet=yes 710# 711# The following globals are used: 712# 713# Name Needed Purpose 714# ---- ------ ------- 715# name y Name of script. 716# 717# command n Full path to command. 718# Not needed if ${rc_arg}_cmd is set for 719# each keyword. 720# 721# command_args n Optional args/shell directives for command. 722# 723# command_interpreter n If not empty, command is interpreted, so 724# call check_{pidfile,process}() appropriately. 725# 726# desc n Description of script. 727# 728# extra_commands n List of extra commands supported. 729# 730# pidfile n If set, use check_pidfile $pidfile $command, 731# otherwise use check_process $command. 732# In either case, only check if $command is set. 733# 734# procname n Process name to check for instead of $command. 735# 736# rcvar n This is checked with checkyesno to determine 737# if the action should be run. 738# 739# ${name}_program n Full path to command. 740# Meant to be used in /etc/rc.conf to override 741# ${command}. 742# 743# ${name}_chroot n Directory to chroot to before running ${command} 744# Requires /usr to be mounted. 745# 746# ${name}_chdir n Directory to cd to before running ${command} 747# (if not using ${name}_chroot). 748# 749# ${name}_flags n Arguments to call ${command} with. 750# NOTE: $flags from the parent environment 751# can be used to override this. 752# 753# ${name}_env n Environment variables to run ${command} with. 754# 755# ${name}_fib n Routing table number to run ${command} with. 756# 757# ${name}_nice n Nice level to run ${command} at. 758# 759# ${name}_oomprotect n Don't kill ${command} when swap space is exhausted. 760# 761# ${name}_user n User to run ${command} as, using su(1) if not 762# using ${name}_chroot. 763# Requires /usr to be mounted. 764# 765# ${name}_group n Group to run chrooted ${command} as. 766# Requires /usr to be mounted. 767# 768# ${name}_groups n Comma separated list of supplementary groups 769# to run the chrooted ${command} with. 770# Requires /usr to be mounted. 771# 772# ${name}_prepend n Command added before ${command}. 773# 774# ${name}_login_class n Login class to use, else "daemon". 775# 776# ${rc_arg}_cmd n If set, use this as the method when invoked; 777# Otherwise, use default command (see below) 778# 779# ${rc_arg}_precmd n If set, run just before performing the 780# ${rc_arg}_cmd method in the default 781# operation (i.e, after checking for required 782# bits and process (non)existence). 783# If this completes with a non-zero exit code, 784# don't run ${rc_arg}_cmd. 785# 786# ${rc_arg}_postcmd n If set, run just after performing the 787# ${rc_arg}_cmd method, if that method 788# returned a zero exit code. 789# 790# required_dirs n If set, check for the existence of the given 791# directories before running a (re)start command. 792# 793# required_files n If set, check for the readability of the given 794# files before running a (re)start command. 795# 796# required_modules n If set, ensure the given kernel modules are 797# loaded before running a (re)start command. 798# The check and possible loads are actually 799# done after start_precmd so that the modules 800# aren't loaded in vain, should the precmd 801# return a non-zero status to indicate a error. 802# If a word in the list looks like "foo:bar", 803# "foo" is the KLD file name and "bar" is the 804# module name. If a word looks like "foo~bar", 805# "foo" is the KLD file name and "bar" is a 806# egrep(1) pattern matching the module name. 807# Otherwise the module name is assumed to be 808# the same as the KLD file name, which is most 809# common. See load_kld(). 810# 811# required_vars n If set, perform checkyesno on each of the 812# listed variables before running the default 813# (re)start command. 814# 815# Default behaviour for a given argument, if no override method is 816# provided: 817# 818# Argument Default behaviour 819# -------- ----------------- 820# start if !running && checkyesno ${rcvar} 821# ${command} 822# 823# stop if ${pidfile} 824# rc_pid=$(check_pidfile $pidfile $command) 825# else 826# rc_pid=$(check_process $command) 827# kill $sig_stop $rc_pid 828# wait_for_pids $rc_pid 829# ($sig_stop defaults to TERM.) 830# 831# reload Similar to stop, except use $sig_reload instead, 832# and doesn't wait_for_pids. 833# $sig_reload defaults to HUP. 834# Note that `reload' isn't provided by default, 835# it should be enabled via $extra_commands. 836# 837# restart Run `stop' then `start'. 838# 839# status Show if ${command} is running, etc. 840# 841# poll Wait for ${command} to exit. 842# 843# rcvar Display what rc.conf variable is used (if any). 844# 845# enabled Return true if the service is enabled. 846# 847# Variables available to methods, and after run_rc_command() has 848# completed: 849# 850# Variable Purpose 851# -------- ------- 852# rc_arg Argument to command, after fast/force/one processing 853# performed 854# 855# rc_flags Flags to start the default command with. 856# Defaults to ${name}_flags, unless overridden 857# by $flags from the environment. 858# This variable may be changed by the precmd method. 859# 860# rc_pid PID of command (if appropriate) 861# 862# rc_fast Not empty if "fast" was provided (q.v.) 863# 864# rc_force Not empty if "force" was provided (q.v.) 865# 866# rc_quiet Not empty if "quiet" was provided 867# 868# 869run_rc_command() 870{ 871 _return=0 872 rc_arg=$1 873 if [ -z "$name" ]; then 874 err 3 'run_rc_command: $name is not set.' 875 fi 876 877 # Don't repeat the first argument when passing additional command- 878 # line arguments to the command subroutines. 879 # 880 shift 1 881 rc_extra_args="$*" 882 883 _rc_prefix= 884 case "$rc_arg" in 885 fast*) # "fast" prefix; don't check pid 886 rc_arg=${rc_arg#fast} 887 rc_fast=yes 888 rc_quiet=yes 889 ;; 890 force*) # "force" prefix; always run 891 rc_force=yes 892 _rc_prefix=force 893 rc_arg=${rc_arg#${_rc_prefix}} 894 if [ -n "${rcvar}" ]; then 895 eval ${rcvar}=YES 896 fi 897 ;; 898 one*) # "one" prefix; set ${rcvar}=yes 899 _rc_prefix=one 900 rc_arg=${rc_arg#${_rc_prefix}} 901 if [ -n "${rcvar}" ]; then 902 eval ${rcvar}=YES 903 fi 904 ;; 905 quiet*) # "quiet" prefix; omit some messages 906 _rc_prefix=quiet 907 rc_arg=${rc_arg#${_rc_prefix}} 908 rc_quiet=yes 909 ;; 910 esac 911 912 eval _override_command=\$${name}_program 913 command=${_override_command:-$command} 914 915 _keywords="start stop restart rcvar enabled $extra_commands" 916 rc_pid= 917 _pidcmd= 918 _procname=${procname:-${command}} 919 920 # setup pid check command 921 if [ -n "$_procname" ]; then 922 if [ -n "$pidfile" ]; then 923 _pidcmd='rc_pid=$(check_pidfile '"$pidfile $_procname $command_interpreter"')' 924 else 925 _pidcmd='rc_pid=$(check_process '"$_procname $command_interpreter"')' 926 fi 927 if [ -n "$_pidcmd" ]; then 928 _keywords="${_keywords} status poll" 929 fi 930 fi 931 932 if [ -z "$rc_arg" ]; then 933 rc_usage $_keywords 934 fi 935 936 if [ "$rc_arg" = "enabled" ] ; then 937 checkyesno ${rcvar} 938 return $? 939 fi 940 941 if [ -n "$flags" ]; then # allow override from environment 942 rc_flags=$flags 943 else 944 eval rc_flags=\$${name}_flags 945 fi 946 eval _chdir=\$${name}_chdir _chroot=\$${name}_chroot \ 947 _nice=\$${name}_nice _user=\$${name}_user \ 948 _group=\$${name}_group _groups=\$${name}_groups \ 949 _fib=\$${name}_fib _env=\$${name}_env \ 950 _prepend=\$${name}_prepend _login_class=\${${name}_login_class:-daemon} \ 951 _oomprotect=\$${name}_oomprotect 952 953 if [ -n "$_user" ]; then # unset $_user if running as that user 954 if [ "$_user" = "$(eval $IDCMD)" ]; then 955 unset _user 956 fi 957 fi 958 959 [ -z "$autoboot" ] && eval $_pidcmd # determine the pid if necessary 960 961 for _elem in $_keywords; do 962 if [ "$_elem" != "$rc_arg" ]; then 963 continue 964 fi 965 # if ${rcvar} is set, $1 is not "rcvar" 966 # and ${rc_pid} is not set, then run 967 # checkyesno ${rcvar} 968 # and return if that failed 969 # 970 if [ -n "${rcvar}" -a "$rc_arg" != "rcvar" -a "$rc_arg" != "stop" ] || 971 [ -n "${rcvar}" -a "$rc_arg" = "stop" -a -z "${rc_pid}" ]; then 972 if ! checkyesno ${rcvar}; then 973 if [ -n "${rc_quiet}" ]; then 974 return 0 975 fi 976 echo -n "Cannot '${rc_arg}' $name. Set ${rcvar} to " 977 echo -n "YES in /etc/rc.conf or use 'one${rc_arg}' " 978 echo "instead of '${rc_arg}'." 979 return 0 980 fi 981 fi 982 983 if [ $rc_arg = "start" -a -z "$rc_fast" -a -n "$rc_pid" ]; then 984 if [ -z "$rc_quiet" ]; then 985 echo 1>&2 "${name} already running? " \ 986 "(pid=$rc_pid)." 987 fi 988 return 1 989 fi 990 991 # if there's a custom ${XXX_cmd}, 992 # run that instead of the default 993 # 994 eval _cmd=\$${rc_arg}_cmd \ 995 _precmd=\$${rc_arg}_precmd \ 996 _postcmd=\$${rc_arg}_postcmd 997 998 if [ -n "$_cmd" ]; then 999 _run_rc_precmd || return 1 1000 _run_rc_doit "$_cmd $rc_extra_args" || return 1 1001 _run_rc_postcmd 1002 return $_return 1003 fi 1004 1005 case "$rc_arg" in # default operations... 1006 1007 status) 1008 _run_rc_precmd || return 1 1009 if [ -n "$rc_pid" ]; then 1010 echo "${name} is running as pid $rc_pid." 1011 else 1012 echo "${name} is not running." 1013 return 1 1014 fi 1015 _run_rc_postcmd 1016 ;; 1017 1018 start) 1019 if [ ! -x "${_chroot}${_chroot:+/}${command}" ]; then 1020 warn "run_rc_command: cannot run $command" 1021 return 1 1022 fi 1023 1024 if ! _run_rc_precmd; then 1025 warn "failed precmd routine for ${name}" 1026 return 1 1027 fi 1028 1029 # setup the full command to run 1030 # 1031 check_startmsgs && echo "Starting ${name}." 1032 if [ -n "$_chroot" ]; then 1033 _doit="\ 1034${_nice:+nice -n $_nice }\ 1035${_fib:+setfib -F $_fib }\ 1036${_env:+env $_env }\ 1037chroot ${_user:+-u $_user }${_group:+-g $_group }${_groups:+-G $_groups }\ 1038$_chroot $command $rc_flags $command_args" 1039 else 1040 _doit="\ 1041${_chdir:+cd $_chdir && }\ 1042${_fib:+setfib -F $_fib }\ 1043${_env:+env $_env }\ 1044$command $rc_flags $command_args" 1045 if [ -n "$_user" ]; then 1046 _doit="su -m $_user -c 'sh -c \"$_doit\"'" 1047 fi 1048 if [ -n "$_nice" ]; then 1049 if [ -z "$_user" ]; then 1050 _doit="sh -c \"$_doit\"" 1051 fi 1052 _doit="nice -n $_nice $_doit" 1053 fi 1054 if [ -n "$_prepend" ]; then 1055 _doit="$_prepend $_doit" 1056 fi 1057 fi 1058 1059 # Prepend default limits 1060 _doit="limits -C $_login_class $_doit" 1061 1062 # run the full command 1063 # 1064 if ! _run_rc_doit "$_doit"; then 1065 warn "failed to start ${name}" 1066 return 1 1067 fi 1068 1069 # finally, run postcmd 1070 # 1071 _run_rc_postcmd 1072 ;; 1073 1074 stop) 1075 if [ -z "$rc_pid" ]; then 1076 [ -n "$rc_fast" ] && return 0 1077 _run_rc_notrunning 1078 return 1 1079 fi 1080 1081 _run_rc_precmd || return 1 1082 1083 # send the signal to stop 1084 # 1085 echo "Stopping ${name}." 1086 _doit=$(_run_rc_killcmd "${sig_stop:-TERM}") 1087 _run_rc_doit "$_doit" || return 1 1088 1089 # wait for the command to exit, 1090 # and run postcmd. 1091 wait_for_pids $rc_pid 1092 1093 _run_rc_postcmd 1094 ;; 1095 1096 reload) 1097 if [ -z "$rc_pid" ]; then 1098 _run_rc_notrunning 1099 return 1 1100 fi 1101 1102 _run_rc_precmd || return 1 1103 1104 _doit=$(_run_rc_killcmd "${sig_reload:-HUP}") 1105 _run_rc_doit "$_doit" || return 1 1106 1107 _run_rc_postcmd 1108 ;; 1109 1110 restart) 1111 # prevent restart being called more 1112 # than once by any given script 1113 # 1114 if ${_rc_restart_done:-false}; then 1115 return 0 1116 fi 1117 _rc_restart_done=true 1118 1119 _run_rc_precmd || return 1 1120 1121 # run those in a subshell to keep global variables 1122 ( run_rc_command ${_rc_prefix}stop $rc_extra_args ) 1123 ( run_rc_command ${_rc_prefix}start $rc_extra_args ) 1124 _return=$? 1125 [ $_return -ne 0 ] && [ -z "$rc_force" ] && return 1 1126 1127 _run_rc_postcmd 1128 ;; 1129 1130 poll) 1131 _run_rc_precmd || return 1 1132 if [ -n "$rc_pid" ]; then 1133 wait_for_pids $rc_pid 1134 fi 1135 _run_rc_postcmd 1136 ;; 1137 1138 rcvar) 1139 echo -n "# $name" 1140 if [ -n "$desc" ]; then 1141 echo " : $desc" 1142 else 1143 echo "" 1144 fi 1145 echo "#" 1146 # Get unique vars in $rcvar $rcvars 1147 for _v in $rcvar $rcvars; do 1148 case $v in 1149 $_v\ *|\ *$_v|*\ $_v\ *) ;; 1150 *) v="${v# } $_v" ;; 1151 esac 1152 done 1153 1154 # Display variables. 1155 for _v in $v; do 1156 if [ -z "$_v" ]; then 1157 continue 1158 fi 1159 1160 eval _desc=\$${_v}_desc 1161 eval _defval=\$${_v}_defval 1162 _h="-" 1163 1164 eval echo \"$_v=\\\"\$$_v\\\"\" 1165 # decode multiple lines of _desc 1166 while [ -n "$_desc" ]; do 1167 case $_desc in 1168 *^^*) 1169 echo "# $_h ${_desc%%^^*}" 1170 _desc=${_desc#*^^} 1171 _h=" " 1172 ;; 1173 *) 1174 echo "# $_h ${_desc}" 1175 break 1176 ;; 1177 esac 1178 done 1179 echo "# (default: \"$_defval\")" 1180 done 1181 echo "" 1182 ;; 1183 1184 *) 1185 rc_usage $_keywords 1186 ;; 1187 1188 esac 1189 1190 # Apply protect(1) to the PID if ${name}_oomprotect is set. 1191 case "$rc_arg" in 1192 start) 1193 if [ -n "$_oomprotect" ]; then 1194 if [ -f "${PROTECT}" ]; then 1195 pid=$(check_process $command) 1196 case $_oomprotect in 1197 [Aa][Ll][Ll]) 1198 ${PROTECT} -i -p ${pid} 1199 ;; 1200 [Yy][Ee][Ss]) 1201 ${PROTECT} -p ${pid} 1202 ;; 1203 esac 1204 fi 1205 fi 1206 ;; 1207 esac 1208 1209 return $_return 1210 done 1211 1212 echo 1>&2 "$0: unknown directive '$rc_arg'." 1213 rc_usage $_keywords 1214 # not reached 1215} 1216 1217# 1218# Helper functions for run_rc_command: common code. 1219# They use such global variables besides the exported rc_* ones: 1220# 1221# name R/W 1222# ------------------ 1223# _precmd R 1224# _postcmd R 1225# _return W 1226# 1227_run_rc_precmd() 1228{ 1229 check_required_before "$rc_arg" || return 1 1230 1231 if [ -n "$_precmd" ]; then 1232 debug "run_rc_command: ${rc_arg}_precmd: $_precmd $rc_extra_args" 1233 eval "$_precmd $rc_extra_args" 1234 _return=$? 1235 1236 # If precmd failed and force isn't set, request exit. 1237 if [ $_return -ne 0 ] && [ -z "$rc_force" ]; then 1238 return 1 1239 fi 1240 fi 1241 1242 check_required_after "$rc_arg" || return 1 1243 1244 return 0 1245} 1246 1247_run_rc_postcmd() 1248{ 1249 if [ -n "$_postcmd" ]; then 1250 debug "run_rc_command: ${rc_arg}_postcmd: $_postcmd $rc_extra_args" 1251 eval "$_postcmd $rc_extra_args" 1252 _return=$? 1253 fi 1254 return 0 1255} 1256 1257_run_rc_doit() 1258{ 1259 debug "run_rc_command: doit: $*" 1260 eval "$@" 1261 _return=$? 1262 1263 # If command failed and force isn't set, request exit. 1264 if [ $_return -ne 0 ] && [ -z "$rc_force" ]; then 1265 return 1 1266 fi 1267 1268 return 0 1269} 1270 1271_run_rc_notrunning() 1272{ 1273 local _pidmsg 1274 1275 if [ -n "$pidfile" ]; then 1276 _pidmsg=" (check $pidfile)." 1277 else 1278 _pidmsg= 1279 fi 1280 echo 1>&2 "${name} not running?${_pidmsg}" 1281} 1282 1283_run_rc_killcmd() 1284{ 1285 local _cmd 1286 1287 _cmd="kill -$1 $rc_pid" 1288 if [ -n "$_user" ]; then 1289 _cmd="su -m ${_user} -c 'sh -c \"${_cmd}\"'" 1290 fi 1291 echo "$_cmd" 1292} 1293 1294# 1295# run_rc_script file arg 1296# Start the script `file' with `arg', and correctly handle the 1297# return value from the script. 1298# If `file' ends with `.sh' and lives in /etc/rc.d, ignore it as it's 1299# an old-style startup file. 1300# If `file' ends with `.sh' and does not live in /etc/rc.d, it's sourced 1301# into the current environment if $rc_fast_and_loose is set; otherwise 1302# it is run as a child process. 1303# If `file' appears to be a backup or scratch file, ignore it. 1304# Otherwise if it is executable run as a child process. 1305# 1306run_rc_script() 1307{ 1308 _file=$1 1309 _arg=$2 1310 if [ -z "$_file" -o -z "$_arg" ]; then 1311 err 3 'USAGE: run_rc_script file arg' 1312 fi 1313 1314 unset name command command_args command_interpreter \ 1315 extra_commands pidfile procname \ 1316 rcvar rcvars rcvars_obsolete required_dirs required_files \ 1317 required_vars 1318 eval unset ${_arg}_cmd ${_arg}_precmd ${_arg}_postcmd 1319 1320 case "$_file" in 1321 /etc/rc.d/*.sh) # no longer allowed in the base 1322 warn "Ignoring old-style startup script $_file" 1323 ;; 1324 *[~#]|*.OLD|*.bak|*.orig|*,v) # scratch file; skip 1325 warn "Ignoring scratch file $_file" 1326 ;; 1327 *) # run in subshell 1328 if [ -x $_file ]; then 1329 if [ -n "$rc_fast_and_loose" ]; then 1330 set $_arg; . $_file 1331 else 1332 ( trap "echo Script $_file interrupted >&2 ; kill -QUIT $$" 3 1333 trap "echo Script $_file interrupted >&2 ; exit 1" 2 1334 trap "echo Script $_file running >&2" 29 1335 set $_arg; . $_file ) 1336 fi 1337 fi 1338 ;; 1339 esac 1340} 1341 1342# 1343# load_rc_config [service] 1344# Source in the configuration file(s) for a given service. 1345# If no service is specified, only the global configuration 1346# file(s) will be loaded. 1347# 1348load_rc_config() 1349{ 1350 local _name _rcvar_val _var _defval _v _msg _new _d 1351 _name=$1 1352 1353 if ${_rc_conf_loaded:-false}; then 1354 : 1355 else 1356 if [ -r /etc/defaults/rc.conf ]; then 1357 debug "Sourcing /etc/defaults/rc.conf" 1358 . /etc/defaults/rc.conf 1359 source_rc_confs 1360 elif [ -r /etc/rc.conf ]; then 1361 debug "Sourcing /etc/rc.conf (/etc/defaults/rc.conf doesn't exist)." 1362 . /etc/rc.conf 1363 fi 1364 _rc_conf_loaded=true 1365 fi 1366 1367 # If a service name was specified, attempt to load 1368 # service-specific configuration 1369 if [ -n "$_name" ] ; then 1370 for _d in /etc ${local_startup}; do 1371 _d=${_d%/rc.d} 1372 if [ -f ${_d}/rc.conf.d/"$_name" ]; then 1373 debug "Sourcing ${_d}/rc.conf.d/$_name" 1374 . ${_d}/rc.conf.d/"$_name" 1375 elif [ -d ${_d}/rc.conf.d/"$_name" ] ; then 1376 local _rc 1377 for _rc in ${_d}/rc.conf.d/"$_name"/* ; do 1378 if [ -f "$_rc" ] ; then 1379 debug "Sourcing $_rc" 1380 . "$_rc" 1381 fi 1382 done 1383 fi 1384 done 1385 fi 1386 1387 # Set defaults if defined. 1388 for _var in $rcvar $rcvars; do 1389 eval _defval=\$${_var}_defval 1390 if [ -n "$_defval" ]; then 1391 eval : \${$_var:=\$${_var}_defval} 1392 fi 1393 done 1394 1395 # check obsolete rc.conf variables 1396 for _var in $rcvars_obsolete; do 1397 eval _v=\$$_var 1398 eval _msg=\$${_var}_obsolete_msg 1399 eval _new=\$${_var}_newvar 1400 case $_v in 1401 "") 1402 ;; 1403 *) 1404 if [ -z "$_new" ]; then 1405 _msg="Ignored." 1406 else 1407 eval $_new=\"\$$_var\" 1408 if [ -z "$_msg" ]; then 1409 _msg="Use \$$_new instead." 1410 fi 1411 fi 1412 warn "\$$_var is obsolete. $_msg" 1413 ;; 1414 esac 1415 done 1416} 1417 1418# 1419# load_rc_config_var name var 1420# Read the rc.conf(5) var for name and set in the 1421# current shell, using load_rc_config in a subshell to prevent 1422# unwanted side effects from other variable assignments. 1423# 1424load_rc_config_var() 1425{ 1426 if [ $# -ne 2 ]; then 1427 err 3 'USAGE: load_rc_config_var name var' 1428 fi 1429 eval $(eval '( 1430 load_rc_config '$1' >/dev/null; 1431 if [ -n "${'$2'}" -o "${'$2'-UNSET}" != "UNSET" ]; then 1432 echo '$2'=\'\''${'$2'}\'\''; 1433 fi 1434 )' ) 1435} 1436 1437# 1438# rc_usage commands 1439# Print a usage string for $0, with `commands' being a list of 1440# valid commands. 1441# 1442rc_usage() 1443{ 1444 echo -n 1>&2 "Usage: $0 [fast|force|one|quiet](" 1445 1446 _sep= 1447 for _elem; do 1448 echo -n 1>&2 "$_sep$_elem" 1449 _sep="|" 1450 done 1451 echo 1>&2 ")" 1452 exit 1 1453} 1454 1455# 1456# err exitval message 1457# Display message to stderr and log to the syslog, and exit with exitval. 1458# 1459err() 1460{ 1461 exitval=$1 1462 shift 1463 1464 if [ -x /usr/bin/logger ]; then 1465 logger "$0: ERROR: $*" 1466 fi 1467 echo 1>&2 "$0: ERROR: $*" 1468 exit $exitval 1469} 1470 1471# 1472# warn message 1473# Display message to stderr and log to the syslog. 1474# 1475warn() 1476{ 1477 if [ -x /usr/bin/logger ]; then 1478 logger "$0: WARNING: $*" 1479 fi 1480 echo 1>&2 "$0: WARNING: $*" 1481} 1482 1483# 1484# info message 1485# Display informational message to stdout and log to syslog. 1486# 1487info() 1488{ 1489 case ${rc_info} in 1490 [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1) 1491 if [ -x /usr/bin/logger ]; then 1492 logger "$0: INFO: $*" 1493 fi 1494 echo "$0: INFO: $*" 1495 ;; 1496 esac 1497} 1498 1499# 1500# debug message 1501# If debugging is enabled in rc.conf output message to stderr. 1502# BEWARE that you don't call any subroutine that itself calls this 1503# function. 1504# 1505debug() 1506{ 1507 case ${rc_debug} in 1508 [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1) 1509 if [ -x /usr/bin/logger ]; then 1510 logger "$0: DEBUG: $*" 1511 fi 1512 echo 1>&2 "$0: DEBUG: $*" 1513 ;; 1514 esac 1515} 1516 1517# 1518# backup_file action file cur backup 1519# Make a backup copy of `file' into `cur', and save the previous 1520# version of `cur' as `backup' or use rcs for archiving. 1521# 1522# This routine checks the value of the backup_uses_rcs variable, 1523# which can be either YES or NO. 1524# 1525# The `action' keyword can be one of the following: 1526# 1527# add `file' is now being backed up (and is possibly 1528# being reentered into the backups system). `cur' 1529# is created and RCS files, if necessary, are 1530# created as well. 1531# 1532# update `file' has changed and needs to be backed up. 1533# If `cur' exists, it is copied to to `back' or 1534# checked into RCS (if the repository file is old), 1535# and then `file' is copied to `cur'. Another RCS 1536# check in done here if RCS is being used. 1537# 1538# remove `file' is no longer being tracked by the backups 1539# system. If RCS is not being used, `cur' is moved 1540# to `back', otherwise an empty file is checked in, 1541# and then `cur' is removed. 1542# 1543# 1544backup_file() 1545{ 1546 _action=$1 1547 _file=$2 1548 _cur=$3 1549 _back=$4 1550 1551 if checkyesno backup_uses_rcs; then 1552 _msg0="backup archive" 1553 _msg1="update" 1554 1555 # ensure that history file is not locked 1556 if [ -f $_cur,v ]; then 1557 rcs -q -u -U -M $_cur 1558 fi 1559 1560 # ensure after switching to rcs that the 1561 # current backup is not lost 1562 if [ -f $_cur ]; then 1563 # no archive, or current newer than archive 1564 if [ ! -f $_cur,v -o $_cur -nt $_cur,v ]; then 1565 ci -q -f -u -t-"$_msg0" -m"$_msg1" $_cur 1566 rcs -q -kb -U $_cur 1567 co -q -f -u $_cur 1568 fi 1569 fi 1570 1571 case $_action in 1572 add|update) 1573 cp -p $_file $_cur 1574 ci -q -f -u -t-"$_msg0" -m"$_msg1" $_cur 1575 rcs -q -kb -U $_cur 1576 co -q -f -u $_cur 1577 chown root:wheel $_cur $_cur,v 1578 ;; 1579 remove) 1580 cp /dev/null $_cur 1581 ci -q -f -u -t-"$_msg0" -m"$_msg1" $_cur 1582 rcs -q -kb -U $_cur 1583 chown root:wheel $_cur $_cur,v 1584 rm $_cur 1585 ;; 1586 esac 1587 else 1588 case $_action in 1589 add|update) 1590 if [ -f $_cur ]; then 1591 cp -p $_cur $_back 1592 fi 1593 cp -p $_file $_cur 1594 chown root:wheel $_cur 1595 ;; 1596 remove) 1597 mv -f $_cur $_back 1598 ;; 1599 esac 1600 fi 1601} 1602 1603# make_symlink src link 1604# Make a symbolic link 'link' to src from basedir. If the 1605# directory in which link is to be created does not exist 1606# a warning will be displayed and an error will be returned. 1607# Returns 0 on success, 1 otherwise. 1608# 1609make_symlink() 1610{ 1611 local src link linkdir _me 1612 src="$1" 1613 link="$2" 1614 linkdir="`dirname $link`" 1615 _me="make_symlink()" 1616 1617 if [ -z "$src" -o -z "$link" ]; then 1618 warn "$_me: requires two arguments." 1619 return 1 1620 fi 1621 if [ ! -d "$linkdir" ]; then 1622 warn "$_me: the directory $linkdir does not exist." 1623 return 1 1624 fi 1625 if ! ln -sf $src $link; then 1626 warn "$_me: unable to make a symbolic link from $link to $src" 1627 return 1 1628 fi 1629 return 0 1630} 1631 1632# devfs_rulesets_from_file file 1633# Reads a set of devfs commands from file, and creates 1634# the specified rulesets with their rules. Returns non-zero 1635# if there was an error. 1636# 1637devfs_rulesets_from_file() 1638{ 1639 local file _err _me _opts 1640 file="$1" 1641 _me="devfs_rulesets_from_file" 1642 _err=0 1643 1644 if [ -z "$file" ]; then 1645 warn "$_me: you must specify a file" 1646 return 1 1647 fi 1648 if [ ! -e "$file" ]; then 1649 debug "$_me: no such file ($file)" 1650 return 0 1651 fi 1652 1653 # Disable globbing so that the rule patterns are not expanded 1654 # by accident with matching filesystem entries. 1655 _opts=$-; set -f 1656 1657 debug "reading rulesets from file ($file)" 1658 { while read line 1659 do 1660 case $line in 1661 \#*) 1662 continue 1663 ;; 1664 \[*\]*) 1665 rulenum=`expr "$line" : "\[.*=\([0-9]*\)\]"` 1666 if [ -z "$rulenum" ]; then 1667 warn "$_me: cannot extract rule number ($line)" 1668 _err=1 1669 break 1670 fi 1671 rulename=`expr "$line" : "\[\(.*\)=[0-9]*\]"` 1672 if [ -z "$rulename" ]; then 1673 warn "$_me: cannot extract rule name ($line)" 1674 _err=1 1675 break; 1676 fi 1677 eval $rulename=\$rulenum 1678 debug "found ruleset: $rulename=$rulenum" 1679 if ! /sbin/devfs rule -s $rulenum delset; then 1680 _err=1 1681 break 1682 fi 1683 ;; 1684 *) 1685 rulecmd="${line%%"\#*"}" 1686 # evaluate the command incase it includes 1687 # other rules 1688 if [ -n "$rulecmd" ]; then 1689 debug "adding rule ($rulecmd)" 1690 if ! eval /sbin/devfs rule -s $rulenum $rulecmd 1691 then 1692 _err=1 1693 break 1694 fi 1695 fi 1696 ;; 1697 esac 1698 if [ $_err -ne 0 ]; then 1699 debug "error in $_me" 1700 break 1701 fi 1702 done } < $file 1703 case $_opts in *f*) ;; *) set +f ;; esac 1704 return $_err 1705} 1706 1707# devfs_init_rulesets 1708# Initializes rulesets from configuration files. Returns 1709# non-zero if there was an error. 1710# 1711devfs_init_rulesets() 1712{ 1713 local file _me 1714 _me="devfs_init_rulesets" 1715 1716 # Go through this only once 1717 if [ -n "$devfs_rulesets_init" ]; then 1718 debug "$_me: devfs rulesets already initialized" 1719 return 1720 fi 1721 for file in $devfs_rulesets; do 1722 if ! devfs_rulesets_from_file $file; then 1723 warn "$_me: could not read rules from $file" 1724 return 1 1725 fi 1726 done 1727 devfs_rulesets_init=1 1728 debug "$_me: devfs rulesets initialized" 1729 return 0 1730} 1731 1732# devfs_set_ruleset ruleset [dir] 1733# Sets the default ruleset of dir to ruleset. The ruleset argument 1734# must be a ruleset name as specified in devfs.rules(5) file. 1735# Returns non-zero if it could not set it successfully. 1736# 1737devfs_set_ruleset() 1738{ 1739 local devdir rs _me 1740 [ -n "$1" ] && eval rs=\$$1 || rs= 1741 [ -n "$2" ] && devdir="-m "$2"" || devdir= 1742 _me="devfs_set_ruleset" 1743 1744 if [ -z "$rs" ]; then 1745 warn "$_me: you must specify a ruleset number" 1746 return 1 1747 fi 1748 debug "$_me: setting ruleset ($rs) on mount-point (${devdir#-m })" 1749 if ! /sbin/devfs $devdir ruleset $rs; then 1750 warn "$_me: unable to set ruleset $rs to ${devdir#-m }" 1751 return 1 1752 fi 1753 return 0 1754} 1755 1756# devfs_apply_ruleset ruleset [dir] 1757# Apply ruleset number $ruleset to the devfs mountpoint $dir. 1758# The ruleset argument must be a ruleset name as specified 1759# in a devfs.rules(5) file. Returns 0 on success or non-zero 1760# if it could not apply the ruleset. 1761# 1762devfs_apply_ruleset() 1763{ 1764 local devdir rs _me 1765 [ -n "$1" ] && eval rs=\$$1 || rs= 1766 [ -n "$2" ] && devdir="-m "$2"" || devdir= 1767 _me="devfs_apply_ruleset" 1768 1769 if [ -z "$rs" ]; then 1770 warn "$_me: you must specify a ruleset" 1771 return 1 1772 fi 1773 debug "$_me: applying ruleset ($rs) to mount-point (${devdir#-m })" 1774 if ! /sbin/devfs $devdir rule -s $rs applyset; then 1775 warn "$_me: unable to apply ruleset $rs to ${devdir#-m }" 1776 return 1 1777 fi 1778 return 0 1779} 1780 1781# devfs_domount dir [ruleset] 1782# Mount devfs on dir. If ruleset is specified it is set 1783# on the mount-point. It must also be a ruleset name as specified 1784# in a devfs.rules(5) file. Returns 0 on success. 1785# 1786devfs_domount() 1787{ 1788 local devdir rs _me 1789 devdir="$1" 1790 [ -n "$2" ] && rs=$2 || rs= 1791 _me="devfs_domount()" 1792 1793 if [ -z "$devdir" ]; then 1794 warn "$_me: you must specify a mount-point" 1795 return 1 1796 fi 1797 debug "$_me: mount-point is ($devdir), ruleset is ($rs)" 1798 if ! mount -t devfs dev "$devdir"; then 1799 warn "$_me: Unable to mount devfs on $devdir" 1800 return 1 1801 fi 1802 if [ -n "$rs" ]; then 1803 devfs_init_rulesets 1804 devfs_set_ruleset $rs $devdir 1805 devfs -m $devdir rule applyset 1806 fi 1807 return 0 1808} 1809 1810# Provide a function for normalizing the mounting of memory 1811# filesystems. This should allow the rest of the code here to remain 1812# as close as possible between 5-current and 4-stable. 1813# $1 = size 1814# $2 = mount point 1815# $3 = (optional) extra mdmfs flags 1816mount_md() 1817{ 1818 if [ -n "$3" ]; then 1819 flags="$3" 1820 fi 1821 /sbin/mdmfs $flags -s $1 md $2 1822} 1823 1824# Code common to scripts that need to load a kernel module 1825# if it isn't in the kernel yet. Syntax: 1826# load_kld [-e regex] [-m module] file 1827# where -e or -m chooses the way to check if the module 1828# is already loaded: 1829# regex is egrep'd in the output from `kldstat -v', 1830# module is passed to `kldstat -m'. 1831# The default way is as though `-m file' were specified. 1832load_kld() 1833{ 1834 local _loaded _mod _opt _re 1835 1836 while getopts "e:m:" _opt; do 1837 case "$_opt" in 1838 e) _re="$OPTARG" ;; 1839 m) _mod="$OPTARG" ;; 1840 *) err 3 'USAGE: load_kld [-e regex] [-m module] file' ;; 1841 esac 1842 done 1843 shift $(($OPTIND - 1)) 1844 if [ $# -ne 1 ]; then 1845 err 3 'USAGE: load_kld [-e regex] [-m module] file' 1846 fi 1847 _mod=${_mod:-$1} 1848 _loaded=false 1849 if [ -n "$_re" ]; then 1850 if kldstat -v | egrep -q -e "$_re"; then 1851 _loaded=true 1852 fi 1853 else 1854 if kldstat -q -m "$_mod"; then 1855 _loaded=true 1856 fi 1857 fi 1858 if ! $_loaded; then 1859 if ! kldload "$1"; then 1860 warn "Unable to load kernel module $1" 1861 return 1 1862 else 1863 info "$1 kernel module loaded." 1864 fi 1865 else 1866 debug "load_kld: $1 kernel module already loaded." 1867 fi 1868 return 0 1869} 1870 1871# ltr str src dst [var] 1872# Change every $src in $str to $dst. 1873# Useful when /usr is not yet mounted and we cannot use tr(1), sed(1) nor 1874# awk(1). If var is non-NULL, set it to the result. 1875ltr() 1876{ 1877 local _str _src _dst _out _com _var 1878 _str="$1" 1879 _src="$2" 1880 _dst="$3" 1881 _var="$4" 1882 _out="" 1883 1884 local IFS="${_src}" 1885 for _com in ${_str}; do 1886 if [ -z "${_out}" ]; then 1887 _out="${_com}" 1888 else 1889 _out="${_out}${_dst}${_com}" 1890 fi 1891 done 1892 if [ -n "${_var}" ]; then 1893 setvar "${_var}" "${_out}" 1894 else 1895 echo "${_out}" 1896 fi 1897} 1898 1899# Creates a list of providers for GELI encryption. 1900geli_make_list() 1901{ 1902 local devices devices2 1903 local provider mountpoint type options rest 1904 1905 # Create list of GELI providers from fstab. 1906 while read provider mountpoint type options rest ; do 1907 case ":${options}" in 1908 :*noauto*) 1909 noauto=yes 1910 ;; 1911 *) 1912 noauto=no 1913 ;; 1914 esac 1915 1916 case ":${provider}" in 1917 :#*) 1918 continue 1919 ;; 1920 *.eli) 1921 # Skip swap devices. 1922 if [ "${type}" = "swap" -o "${options}" = "sw" -o "${noauto}" = "yes" ]; then 1923 continue 1924 fi 1925 devices="${devices} ${provider}" 1926 ;; 1927 esac 1928 done < /etc/fstab 1929 1930 # Append providers from geli_devices. 1931 devices="${devices} ${geli_devices}" 1932 1933 for provider in ${devices}; do 1934 provider=${provider%.eli} 1935 provider=${provider#/dev/} 1936 devices2="${devices2} ${provider}" 1937 done 1938 1939 echo ${devices2} 1940} 1941 1942# Find scripts in local_startup directories that use the old syntax 1943# 1944find_local_scripts_old() { 1945 zlist='' 1946 slist='' 1947 for dir in ${local_startup}; do 1948 if [ -d "${dir}" ]; then 1949 for file in ${dir}/[0-9]*.sh; do 1950 grep '^# PROVIDE:' $file >/dev/null 2>&1 && 1951 continue 1952 zlist="$zlist $file" 1953 done 1954 for file in ${dir}/[!0-9]*.sh; do 1955 grep '^# PROVIDE:' $file >/dev/null 2>&1 && 1956 continue 1957 slist="$slist $file" 1958 done 1959 fi 1960 done 1961} 1962 1963find_local_scripts_new() { 1964 local_rc='' 1965 for dir in ${local_startup}; do 1966 if [ -d "${dir}" ]; then 1967 for file in `grep -l '^# PROVIDE:' ${dir}/* 2>/dev/null`; do 1968 case "$file" in 1969 *.sample) ;; 1970 *) if [ -x "$file" ]; then 1971 local_rc="${local_rc} ${file}" 1972 fi 1973 ;; 1974 esac 1975 done 1976 fi 1977 done 1978} 1979 1980# check_required_{before|after} command 1981# Check for things required by the command before and after its precmd, 1982# respectively. The two separate functions are needed because some 1983# conditions should prevent precmd from being run while other things 1984# depend on precmd having already been run. 1985# 1986check_required_before() 1987{ 1988 local _f 1989 1990 case "$1" in 1991 start) 1992 for _f in $required_vars; do 1993 if ! checkyesno $_f; then 1994 warn "\$${_f} is not enabled." 1995 if [ -z "$rc_force" ]; then 1996 return 1 1997 fi 1998 fi 1999 done 2000 2001 for _f in $required_dirs; do 2002 if [ ! -d "${_f}/." ]; then 2003 warn "${_f} is not a directory." 2004 if [ -z "$rc_force" ]; then 2005 return 1 2006 fi 2007 fi 2008 done 2009 2010 for _f in $required_files; do 2011 if [ ! -r "${_f}" ]; then 2012 warn "${_f} is not readable." 2013 if [ -z "$rc_force" ]; then 2014 return 1 2015 fi 2016 fi 2017 done 2018 ;; 2019 esac 2020 2021 return 0 2022} 2023 2024check_required_after() 2025{ 2026 local _f _args 2027 2028 case "$1" in 2029 start) 2030 for _f in $required_modules; do 2031 case "${_f}" in 2032 *~*) _args="-e ${_f#*~} ${_f%%~*}" ;; 2033 *:*) _args="-m ${_f#*:} ${_f%%:*}" ;; 2034 *) _args="${_f}" ;; 2035 esac 2036 if ! load_kld ${_args}; then 2037 if [ -z "$rc_force" ]; then 2038 return 1 2039 fi 2040 fi 2041 done 2042 ;; 2043 esac 2044 2045 return 0 2046} 2047 2048# check_jail mib 2049# Return true if security.jail.$mib exists and set to 1. 2050 2051check_jail() 2052{ 2053 local _mib _v 2054 2055 _mib=$1 2056 if _v=$(${SYSCTL_N} "security.jail.$_mib" 2> /dev/null); then 2057 case $_v in 2058 1) return 0;; 2059 esac 2060 fi 2061 return 1 2062} 2063 2064# check_kern_features mib 2065# Return existence of kern.features.* sysctl MIB as true or 2066# false. The result will be cached in $_rc_cache_kern_features_ 2067# namespace. "0" means the kern.features.X exists. 2068 2069check_kern_features() 2070{ 2071 local _v 2072 2073 [ -n "$1" ] || return 1; 2074 eval _v=\$_rc_cache_kern_features_$1 2075 [ -n "$_v" ] && return "$_v"; 2076 2077 if ${SYSCTL_N} kern.features.$1 > /dev/null 2>&1; then 2078 eval _rc_cache_kern_features_$1=0 2079 return 0 2080 else 2081 eval _rc_cache_kern_features_$1=1 2082 return 1 2083 fi 2084} 2085 2086# check_namevarlist var 2087# Return "0" if ${name}_var is reserved in rc.subr. 2088 2089_rc_namevarlist="program chroot chdir env flags fib nice user group groups prepend" 2090check_namevarlist() 2091{ 2092 local _v 2093 2094 for _v in $_rc_namevarlist; do 2095 case $1 in 2096 $_v) return 0 ;; 2097 esac 2098 done 2099 2100 return 1 2101} 2102 2103# _echoonce var msg mode 2104# mode=0: Echo $msg if ${$var} is empty. 2105# After doing echo, a string is set to ${$var}. 2106# 2107# mode=1: Echo $msg if ${$var} is a string with non-zero length. 2108# 2109_echoonce() 2110{ 2111 local _var _msg _mode 2112 eval _var=\$$1 2113 _msg=$2 2114 _mode=$3 2115 2116 case $_mode in 2117 1) [ -n "$_var" ] && echo "$_msg" ;; 2118 *) [ -z "$_var" ] && echo -n "$_msg" && eval "$1=finished" ;; 2119 esac 2120} 2121 2122fi # [ -z "${_rc_subr_loaded}" ] 2123 2124_rc_subr_loaded=: 2125