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