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