1# $NetBSD: rc.subr,v 1.49 2002/05/21 12:31:01 lukem Exp $ 2# $FreeBSD: head/etc/rc.subr 275359 2014-12-01 12:17:42Z des $ 3# 4# Copyright (c) 1997-2002 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# 3. All advertising materials mentioning features or use of this software 19# must display the following acknowledgement: 20# This product includes software developed by the NetBSD 21# Foundation, Inc. and its contributors. 22# 4. Neither the name of The NetBSD Foundation nor the names of its 23# contributors may be used to endorse or promote products derived 24# from this software without specific prior written permission. 25# 26# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36# POSSIBILITY OF SUCH DAMAGE. 37# 38# rc.subr 39# functions used by various rc scripts 40# 41 42# 43# Operating System dependent/independent variables 44# 45 46if [ -z "$_file" ]; then 47 _file="$0" 48fi 49provide_list=`rcorder -p $_file` 50 51if [ -n "${_rc_subr_loaded}" ]; then 52 return 53fi 54 55_rc_subr_loaded="YES" 56 57SYSCTL="/sbin/sysctl" 58SYSCTL_N="${SYSCTL} -n" 59CMD_OSTYPE="${SYSCTL_N} kern.ostype" 60OSTYPE=`${CMD_OSTYPE}` 61 62RC_RUNNING=0 63RC_FAILED=1 64RC_DISABLED=2 65RC_IRRELEVANT=3 66RC_CONFIGURED=4 67RC_STOPPED=5 68SYSCTL_W="${SYSCTL}" 69 70# 71# functions 72# --------- 73 74# list_vars pattern 75# List vars matching pattern. 76# 77list_vars() 78{ 79 set | { while read LINE; do 80 var="${LINE%%=*}" 81 case "$var" in 82 "$LINE"|*[!a-zA-Z0-9_]*) continue ;; 83 $1) echo $var 84 esac 85 done; } 86} 87 88# set_rcvar base_var 89# Set the variable name enabling a specific service. 90# FreeBSD uses ${service}_enable, while NetBSD uses 91# just the name of the service. For example: 92# FreeBSD: sendmail_enable="YES" 93# NetBSD : sendmail="YES" 94# $1 - if $name is not the base to work of off, specify 95# a different one 96# 97set_rcvar() 98{ 99 if [ -z "$1" ]; then 100 base_var=${name} 101 else 102 base_var="$1" 103 fi 104 105 echo ${base_var} 106} 107 108# set_provide_list 109# 110# $1 should be $rc_arg (start, stop, restart, reload, etc) 111# $2 return value $RC_* 112# 113# Set the rcng_* variables associated with elements in provide_list 114# based on $1 and $2. 115# 116# Returns non-zero when early termination should occur, in which 117# case the caller should return with a value of $? - 1 118# 119set_provide_list() 120{ 121 # Remember, plret is set to the early termination return code + 1, 122 # or 0 if we want to continue the operation. 123 # 124 for i in $provide_list; do 125 case $1$2 in 126 start$RC_RUNNING|restart$RC_RUNNING) 127 varsym -s rcng_$i=running 128 ;; 129 start$RC_FAILED|restart$RC_FAILED) 130 varsym -s rcng_$i=failed 131 ;; 132 start$RC_DISABLED|restart$RC_DISABLED|reload$RC_DISABLED) 133 varsym -s rcng_$i=disabled 134 ;; 135 start$RC_IRRELEVANT|restart$RC_IRRELEVANT|reload$RC_IRRELEVANT) 136 varsym -s rcng_$i=irrelevant 137 ;; 138 start$RC_CONFIGURED|restart$RC_CONFIGURED) 139 varsym -s rcng_$i=configured 140 ;; 141 stop$RC_DISABLED) 142 varsym -s rcng_$i=disabled 143 ;; 144 stop$RC_IRRELEVANT) 145 varsym -s rcng_$i=irrelevant 146 ;; 147 stop*) 148 varsym -s rcng_$i=stopped 149 ;; 150 *) 151 ;; 152 esac 153 done 154} 155 156# check_early_term 157# $1 should be $rc_arg (start, stop, restart, reload, etc) 158# $2 return value $RC_* 159# $3 $rc_force "" not to force, "anything" to force. 160# 161# The return code is 0 if early termination is not to occur, non-zero if 162# it is to occur. When early termination is to occur the caller should 163# return check_early_term()'s return code - 1. That is, early termination 164# can occur with or without an error. 165# 166# The provide list will be adjusted when early termination occurs. 167# 168check_early_term() 169{ 170 case $2 in 171 $RC_RUNNING) 172 return 0 173 ;; 174 $RC_FAILED) 175 set_provide_list $1 $2 176 [ -z "$3" ] || return 0 177 return 2 178 ;; 179 $RC_DISABLED) 180 set_provide_list $1 $2 181 [ -z "$3" ] || return 0 182 return 1 183 ;; 184 $RC_IRRELEVANT) 185 set_provide_list $1 $2 186 [ -z "$3" ] || return 0 187 return 1 188 ;; 189 $RC_CONFIGURED) 190 return 0 191 ;; 192 $RC_STOPPED) 193 return 0 194 ;; 195 esac 196 set_provide_list $1 $2 197 [ -z "$3" ] || return 0 198 return 2 199} 200 201# adjust_return_code $1 202# 203# Convert the return code to an exit code of 0 (success) or 1 (failure) 204# 205adjust_return_code() 206{ 207 if [ $1 = $RC_FAILED ]; then 208 return 1 209 fi 210 return 0 211} 212 213# 214# force_depend script 215# Force a service to start. Intended for use by services 216# to resolve dependency issues. It is assumed the caller 217# has check to make sure this call is necessary 218# $1 - filename of script, in /etc/rc.d, to run 219# 220force_depend() 221{ 222 _depend="$1" 223 224 info "${name} depends on ${_depend}, which will be forced to start." 225 if ! /etc/rc.d/${_depend} forcestart ; then 226 warn "Unable to force ${_depend}. It may already be running." 227 return 1 228 fi 229 return 0 230} 231 232# 233# checkyesno var 234# Test $1 variable, and warn if not set to YES or NO. 235# Return 0 if it's "yes" (et al), nonzero otherwise. 236# 237checkyesno() 238{ 239 # try foo 240 eval _value=\$${1%_enable} 241 # try foo_enable 242 if [ -z $_value ] 243 then 244 eval _value=\$${1%_enable}_enable; 245 fi 246 debug "checkyesno: $1 is set to $_value." 247 case $_value in 248 249 # "yes", "true", "on", or "1" 250 [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1) 251 return 0 252 ;; 253 254 # "no", "false", "off", or "0" 255 [Nn][Oo]|[Ff][Aa][Ll][Ss][Ee]|[Oo][Ff][Ff]|0) 256 return 1 257 ;; 258 *) 259 warn "\$${1} is not set properly - see rc.conf(5)." 260 return 1 261 ;; 262 esac 263} 264 265# reverse_list list 266# print the list in reverse order 267# 268reverse_list() 269{ 270 _revlist= 271 for _revfile in $*; do 272 _revlist="$_revfile $_revlist" 273 done 274 echo $_revlist 275} 276 277# 278# mount_critical_filesystems type 279# Go through the list of critical filesystems as provided in 280# the rc.conf(5) variable $critical_filesystems_${type}, checking 281# each one to see if it is mounted, and if it is not, mounting it. 282# 283mount_critical_filesystems() 284{ 285 eval _fslist=\$critical_filesystems_${1} 286 for _fs in $_fslist; do 287 mount | ( 288 _ismounted=no 289 while read what _on on _type type; do 290 if [ $on = $_fs ]; then 291 _ismounted=yes 292 fi 293 done 294 if [ $_ismounted = no ]; then 295 mount $_fs >/dev/null 2>&1 296 fi 297 ) 298 done 299} 300 301# 302# check_pidfile pidfile procname [interpreter] 303# Parses the first line of pidfile for a PID, and ensures 304# that the process is running and matches procname. 305# Prints the matching PID upon success, nothing otherwise. 306# interpreter is optional; see _find_processes() for details. 307# 308check_pidfile() 309{ 310 _pidfile=$1 311 _procname=$2 312 _interpreter=$3 313 if [ -z "$_pidfile" -o -z "$_procname" ]; then 314 err 3 'USAGE: check_pidfile pidfile procname [interpreter]' 315 fi 316 if [ ! -f $_pidfile ]; then 317 debug "pid file {$_pidfile): not readable." 318 return 319 fi 320 read _pid _junk < $_pidfile 321 if [ -z "$_pid" ]; then 322 debug "pid file {$_pidfile): no pid in file." 323 return 324 fi 325 _find_processes $_procname ${_interpreter:-.} '-p '"$_pid" 326} 327 328# 329# check_process procname [interpreter] 330# Ensures that a process (or processes) named procname is running. 331# Prints a list of matching PIDs. 332# interpreter is optional; see _find_processes() for details. 333# 334check_process() 335{ 336 _procname=$1 337 _interpreter=$2 338 if [ -z "$_procname" ]; then 339 err 3 'USAGE: check_process procname [interpreter]' 340 fi 341 _find_processes $_procname ${_interpreter:-.} '-ax' 342} 343 344# 345# _find_processes procname interpreter psargs 346# Search for procname in the output of ps generated by psargs. 347# Prints the PIDs of any matching processes, space separated. 348# 349# If interpreter == ".", check the following variations of procname 350# against the first word of each command: 351# procname 352# `basename procname` 353# `basename procname` + ":" 354# "(" + `basename procname` + ")" 355# 356# If interpreter != ".", read the first line of procname, remove the 357# leading #!, normalise whitespace, append procname, and attempt to 358# match that against each command, either as is, or with extra words 359# at the end. 360# 361_find_processes() 362{ 363 if [ $# -ne 3 ]; then 364 err 3 'USAGE: _find_processes procname interpreter psargs' 365 fi 366 _procname=$1 367 _interpreter=$2 368 _psargs=$3 369 370 _pref= 371 if [ $_interpreter != "." ]; then # an interpreted script 372 read _interp < $_procname # read interpreter name 373 _interp=${_interp#\#!} # strip #! 374 set -- $_interp 375 if [ $_interpreter != $1 ]; then 376 warn "\$command_interpreter $_interpreter != $1" 377 fi 378 _interp="$* $_procname" # cleanup spaces, add _procname 379 _interpbn="$1" # the interpreter binary 380 _fp_args='_argv' 381 _fp_match='case "$_argv" in 382 "${_interpbn##*/}: "$_procname*|${_interp}|"${_interp} "*)' 383 else # a normal daemon 384 _procnamebn=${_procname##*/} 385 _fp_args='_arg0 _argv' 386 _fp_match='case "$_arg0" in 387 $_procname|$_procnamebn|${_procnamebn}:|"(${_procnamebn})")' 388 fi 389 390 _proccheck=' 391 ps -o "pid,command" '"$_psargs"' | 392 while read _npid '"$_fp_args"'; do 393 case "$_npid" in 394 PID) 395 continue ;; 396 esac ; '"$_fp_match"' 397 echo -n "$_pref$_npid" ; 398 _pref=" " 399 ;; 400 esac 401 done' 402 403# debug "in _find_processes: proccheck is ($_proccheck)." 404 eval $_proccheck 405} 406 407# 408# wait_for_pids pid [pid ...] 409# spins until none of the pids exist 410# 411wait_for_pids() 412{ 413 _list=$* 414 if [ -z "$_list" ]; then 415 return 416 fi 417 _prefix= 418 while true; do 419 _nlist=""; 420 for _j in $_list; do 421 if kill -0 $_j 2>/dev/null; then 422 _nlist="${_nlist}${_nlist:+ }$_j" 423 fi 424 done 425 if [ -z "$_nlist" ]; then 426 break 427 fi 428 _list=$_nlist 429 echo -n ${_prefix:-"Waiting for PIDS: "}$_list 430 _prefix=", " 431 sleep 2 432 done 433 if [ -n "$_prefix" ]; then 434 echo "." 435 fi 436} 437 438# 439# get_pidfile_from_conf string file 440# 441# Takes a string to search for in the specified file. 442# Ignores lines with traditional comment characters. 443# 444# Example: 445# 446# if get_pidfile_from_conf string file; then 447# pidfile="$_pidfile_from_conf" 448# else 449# pidfile='appropriate default' 450# fi 451# 452get_pidfile_from_conf() 453{ 454 if [ -z "$1" -o -z "$2" ]; then 455 err 3 "USAGE: get_pidfile_from_conf string file ($name)" 456 fi 457 458 local string file line 459 460 string="$1" ; file="$2" 461 462 if [ ! -s "$file" ]; then 463 err 3 "get_pidfile_from_conf: $file does not exist ($name)" 464 fi 465 466 while read line; do 467 case "$line" in 468 *[#\;]*${string}*) continue ;; 469 *${string}*) break ;; 470 esac 471 done < $file 472 473 if [ -n "$line" ]; then 474 line=${line#*/} 475 _pidfile_from_conf="/${line%%[\"\;]*}" 476 else 477 return 1 478 fi 479} 480 481# 482# check_startmsgs 483# If rc_quiet is set (usually as a result of using faststart at 484# boot time) check if rc_startmsgs is enabled. 485# 486check_startmsgs() 487{ 488 if [ -n "$rc_quiet" ]; then 489 checkyesno rc_startmsgs 490 else 491 return 0 492 fi 493} 494 495# 496# run_rc_command argument 497# Search for argument in the list of supported commands, which is: 498# "start stop restart rcvar status poll ${extra_commands}" 499# If there's a match, run ${argument}_cmd or the default method 500# (see below). 501# 502# If argument has a given prefix, then change the operation as follows: 503# Prefix Operation 504# ------ --------- 505# fast Skip the pid check, and set rc_fast=yes, rc_quiet=yes 506# force Set ${rcvar} to YES, and set rc_force=yes 507# one Set ${rcvar} to YES 508# quiet Don't output some diagnostics, and set rc_quiet=yes 509# 510# The following globals are used: 511# 512# Name Needed Purpose 513# ---- ------ ------- 514# provide_list (gen) list of keywords provided by current rcng file 515# 516# name y Name of script. 517# 518# command n Full path to command. 519# Not needed if ${rc_arg}_cmd is set for 520# each keyword. 521# 522# command_args n Optional args/shell directives for command. 523# 524# command_interpreter n If not empty, command is interpreted, so 525# call check_{pidfile,process}() appropriately. 526# 527# extra_commands n List of extra commands supported. 528# 529# pidfile n If set, use check_pidfile $pidfile $command, 530# otherwise use check_process $command. 531# In either case, only check if $command is set. 532# 533# procname n Process name to check for instead of $command. 534# 535# rcvar n This is checked with checkyesno to determine 536# if the action should be run. 537# 538# ${name}_chroot n Directory to chroot to before running ${command} 539# Requires /usr to be mounted. 540# 541# ${name}_chdir n Directory to cd to before running ${command} 542# (if not using ${name}_chroot). 543# 544# ${name}_flags n Arguments to call ${command} with. 545# NOTE: $flags from the parent environment 546# can be used to override this. 547# 548# ${name}_env n Environment variables to run ${command} with. 549# 550# ${name}_nice n Nice level to run ${command} at. 551# 552# ${name}_user n User to run ${command} as, using su(1) if not 553# using ${name}_chroot. 554# Requires /usr to be mounted. 555# 556# ${name}_group n Group to run chrooted ${command} as. 557# Requires /usr to be mounted. 558# 559# ${name}_groups n Comma separated list of supplementary groups 560# to run the chrooted ${command} with. 561# Requires /usr to be mounted. 562# 563# ${name}_prepend n Command added before ${command}. 564# 565# ${rc_arg}_cmd n If set, use this as the method when invoked; 566# Otherwise, use default command (see below) 567# 568# ${rc_arg}_precmd n If set, run just before performing the 569# ${rc_arg}_cmd method in the default 570# operation (i.e, after checking for required 571# bits and process (non)existence). 572# If this completes with a non-zero exit code, 573# don't run ${rc_arg}_cmd. 574# 575# ${rc_arg}_postcmd n If set, run just after performing the 576# ${rc_arg}_cmd method, if that method 577# returned a zero exit code. 578# 579# required_dirs n If set, check for the existence of the given 580# directories before running the default 581# (re)start command. 582# 583# required_files n If set, check for the readability of the given 584# files before running the default (re)start 585# command. 586# 587# required_modules n If set, ensure the given kernel modules are 588# loaded before running a (re)start command. 589# The check and possible loads are actually 590# done after start_precmd so that the modules 591# aren't loaded in vain, should the precmd 592# return a non-zero status to indicate a error. 593# If a word in the list looks like "foo:bar", 594# "foo" is the KLD file name and "bar" is the 595# module name. If a word looks like "foo~bar", 596# "foo" is the KLD file name and "bar" is a 597# egrep(1) pattern matching the module name. 598# Otherwise the module name is assumed to be 599# the same as the KLD file name, which is most 600# common. See load_kld(). 601# 602# required_vars n If set, perform checkyesno on each of the 603# listed variables before running the default 604# (re)start command. 605# 606# Default behaviour for a given argument, if no override method is 607# provided: 608# 609# Argument Default behaviour 610# -------- ----------------- 611# start if !running && checkyesno ${rcvar} 612# ${command} 613# 614# stop if ${pidfile} 615# rc_pid=$(check_pidfile $pidfile $command) 616# else 617# rc_pid=$(check_process $command) 618# kill $sig_stop $rc_pid 619# wait_for_pids $rc_pid 620# ($sig_stop defaults to TERM.) 621# 622# reload Similar to stop, except use $sig_reload instead, 623# and doesn't wait_for_pids. 624# $sig_reload defaults to HUP. 625# 626# restart Run `stop' then `start'. 627# 628# status Show if ${command} is running, etc. 629# 630# poll Wait for ${command} to exit. 631# 632# rcvar Display what rc.conf variable is used (if any). 633# 634# Variables available to methods, and after run_rc_command() has 635# completed: 636# 637# Variable Purpose 638# -------- ------- 639# rc_arg Argument to command, after fast/force/one processing 640# performed 641# 642# rc_flags Flags to start the default command with. 643# Defaults to ${name}_flags, unless overridden 644# by $flags from the environment. 645# This variable may be changed by the precmd method. 646# 647# rc_pid PID of command (if appropriate) 648# 649# rc_fast Not empty if "fast" was provided (q.v.) 650# 651# rc_force Not empty if "force" was provided (q.v.) 652# 653# rc_quiet Not empty if "quiet" was provided 654# 655# 656dummy_rc_command() 657{ 658 rc_arg=$1 659 660 case "$rc_arg" in 661 fast*) # "fast" prefix; don't check pid 662 rc_arg=${rc_arg#fast} 663 ;; 664 force*) # "force" prefix; always start 665 rc_arg=${rc_arg#force} 666 ;; 667 one*) # "one" prefix; set ${rcvar}=yes 668 rc_arg=${rc_arg#one} 669 ;; 670 esac 671 set_provide_list $rc_arg $RC_CONFIGURED 672 return 0 673} 674 675run_rc_command() 676{ 677 _return=0 678 rc_arg=$1 679 if [ -z "$name" ]; then 680 err 3 'run_rc_command: $name is not set.' 681 fi 682 683 # Don't repeat the first argument when passing additional command- 684 # line arguments to the command subroutines. 685 # 686 shift 1 687 rc_extra_args="$*" 688 689 case "$rc_arg" in 690 fast*) # "fast" prefix; don't check pid 691 rc_arg=${rc_arg#fast} 692 rc_fast=yes 693 rc_quiet=yes 694 ;; 695 force*) # "force" prefix; always start 696 rc_arg=${rc_arg#force} 697 rc_force=yes 698 if [ -n "${rcvar}" ]; then 699 eval ${rcvar}=YES 700 fi 701 ;; 702 one*) # "one" prefix; set ${rcvar}=yes 703 rc_arg=${rc_arg#one} 704 if [ -n "${rcvar}" ]; then 705 eval ${rcvar}=YES 706 fi 707 ;; 708 quiet*) # "quiet" prefix; omit some messages 709 _rc_prefix=quiet 710 rc_arg=${rc_arg#${_rc_prefix}} 711 rc_quiet=yes 712 ;; 713 esac 714 715 eval _override_command=\$${name}_program 716 if [ -n "$_override_command" ]; then 717 command=$_override_command 718 fi 719 720 _keywords="start stop restart rcvar $extra_commands" 721 rc_pid= 722 _pidcmd= 723 _procname=${procname:-${command}} 724 725 # setup pid check command if not fast 726 if [ -z "$rc_fast" -a -n "$_procname" ]; then 727 if [ -n "$pidfile" ]; then 728 _pidcmd='rc_pid=$(check_pidfile '"$pidfile $_procname $command_interpreter"')' 729 else 730 _pidcmd='rc_pid=$(check_process '"$_procname $command_interpreter"')' 731 fi 732 if [ -n "$_pidcmd" ]; then 733 _keywords="${_keywords} status poll" 734 fi 735 fi 736 737 if [ -z "$rc_arg" ]; then 738 rc_usage "$_keywords" 739 fi 740 741 if [ -n "$flags" ]; then # allow override from environment 742 rc_flags=$flags 743 else 744 eval rc_flags=\$${name}_flags 745 fi 746 eval _chdir=\$${name}_chdir _chroot=\$${name}_chroot \ 747 _nice=\$${name}_nice _user=\$${name}_user \ 748 _group=\$${name}_group _groups=\$${name}_groups \ 749 _env=\$${name}_env _prepend=\$${name}_prepend 750 751 if [ -n "$_user" ]; then # unset $_user if running as that user 752 if [ "$_user" = "$(id -un)" ]; then 753 unset _user 754 fi 755 fi 756 757 # if ${rcvar} is set, and $1 is not 758 # "rcvar", then run 759 # checkyesno ${rcvar} 760 # and return if that failed 761 # 762 if [ -n "${rcvar}" -a "$rc_arg" != "rcvar" ]; then 763 if ! checkyesno ${rcvar}; then 764 set_provide_list $rc_arg $RC_DISABLED 765 return 0 766 fi 767 fi 768 769 eval $_pidcmd # determine the pid if necessary 770 771 for _elem in $_keywords; do 772 if [ "$_elem" != "$rc_arg" ]; then 773 continue 774 fi 775 776 # if there's a custom ${XXX_cmd}, 777 # run that instead of the default 778 # 779 eval _cmd=\$${rc_arg}_cmd _precmd=\$${rc_arg}_precmd \ 780 _postcmd=\$${rc_arg}_postcmd 781 if [ -n "$_cmd" ]; then 782 # if the precmd failed and force 783 # isn't set, exit 784 # 785 if [ -n "$_precmd" ]; then 786 debug "run_rc_command: evaluating ${_precmd}()." 787 eval $_precmd $rc_extra_args 788 789 _return=$? 790 check_early_term $rc_arg $_return "$rc_force" || return $(($?-1)) 791 fi 792 793 if [ -n "$_cmd" ]; then 794 debug "run_rc_command: evaluating ${_cmd}()." 795 eval $_cmd $rc_extra_args 796 _return=$? 797 check_early_term $rc_arg $_return "$rc_force" || return $(($?-1)) 798 fi 799 800 if [ -n "$_postcmd" ]; then 801 debug "run_rc_command: evaluating ${_postcmd}()." 802 eval $_postcmd $rc_extra_args 803 _return=$? 804 check_early_term $rc_arg $_return "" || return $(($?-1)) 805 fi 806 set_provide_list $rc_arg $_return 807 adjust_return_code $_return 808 return $? 809 fi 810 811 case "$rc_arg" in # default operations... 812 813 status) 814 if [ -n "$rc_pid" ]; then 815 echo "${name} is running as pid $rc_pid." 816 else 817 echo "${name} is not running." 818 return 1 819 fi 820 ;; 821 822 start) 823 if [ -n "$rc_pid" ]; then 824 if [ -z "$rc_quiet" ]; then 825 echo "${name} already running? (pid=$rc_pid)." 826 fi 827 exit 1 828 fi 829 830 if [ ! -x $command ]; then 831 info "run_rc_command: cannot run ($command)." 832 set_provide_list $rc_arg $RC_FAILED 833 adjust_return_code $RC_FAILED 834 return $? 835 fi 836 837 # check for required variables, 838 # directories, and files 839 # 840 for _f in $required_vars; do 841 if ! checkyesno $_f; then 842 warn "\$${_f} is not set." 843 if [ -z "$rc_force" ]; then 844 set_provide_list $rc_arg $RC_FAILED 845 adjust_return_code $RC_FAILED 846 return $? 847 fi 848 fi 849 done 850 for _f in $required_dirs; do 851 if [ ! -d "${_f}/." ]; then 852 warn "${_f} is not a directory." 853 if [ -z "$rc_force" ]; then 854 set_provide_list $rc_arg $RC_FAILED 855 adjust_return_code $RC_FAILED 856 return $? 857 fi 858 fi 859 done 860 for _f in $required_files; do 861 if [ ! -r "${_f}" ]; then 862 warn "${_f} is not readable." 863 if [ -z "$rc_force" ]; then 864 set_provide_list $rc_arg $RC_FAILED 865 adjust_return_code $RC_FAILED 866 return $? 867 fi 868 fi 869 done 870 for _f in $required_modules; do 871 case "${_f}" in 872 *~*) _args="-e ${_f#*~} ${_f%%~*}" ;; 873 *:*) _args="-m ${_f#*:} ${_f%%:*}" ;; 874 *) _args="${_f}" ;; 875 esac 876 if ! load_kld ${_args}; then 877 if [ -z "$rc_force" ]; then 878 set_provide_list $rc_arg $RC_FAILED 879 adjust_return_code $RC_FAILED 880 return $? 881 fi 882 fi 883 done 884 885 # if the precmd failed and force 886 # isn't set, exit 887 # 888 if [ -n "${_precmd}" ]; then 889 debug "run_rc_command: evaluating ${_precmd}()." 890 eval $_precmd 891 _return=$? 892 check_early_term $rc_arg $_return "$rc_force" || return $(($?-1)) 893 fi 894 895 # setup the command to run, and run it 896 # 897 echo "Starting ${name}." 898 if [ -n "$_chroot" ]; then 899 _doit="\ 900${_nice:+nice -n $_nice }\ 901${_env:+env $_env }\ 902chroot ${_user:+-u $_user }${_group:+-g $_group }${_groups:+-G $_groups }\ 903$_chroot $command $rc_flags $command_args" 904 else 905 _doit="\ 906${_chdir:+cd $_chdir; }\ 907${_nice:+nice -n $_nice }\ 908${_env:+env $_env }\ 909$command $rc_flags $command_args" 910 if [ -n "$_user" ]; then 911 _doit="su -m $_user -c 'sh -c \"$_doit\"'" 912 fi 913 if [ -n "$_prepend" ]; then 914 _doit="$_prepend $_doit" 915 fi 916 fi 917 918 # if the cmd failed and force 919 # isn't set, exit 920 # 921 debug "run_rc_command: _doit: $_doit" 922 eval $_doit 923 _return=$? 924 check_early_term $rc_arg $_return "$rc_force" || return $(($?-1)) 925 # finally, run postcmd 926 # 927 if [ -n "${_postcmd}" ]; then 928 debug "run_rc_command: evaluating ${_postcmd}()." 929 eval $_postcmd 930 fi 931 ;; 932 933 stop) 934 if [ -z "$rc_pid" ]; then 935 if [ -n "$pidfile" ]; then 936 echo \ 937 "${name} not running? (check $pidfile)." 938 else 939 echo "${name} not running?" 940 fi 941 set_provide_list $rc_arg $RC_STOPPED 942 exit 1 943 fi 944 945 # if the precmd failed and force 946 # isn't set, exit 947 # 948 if [ -n "$_precmd" ]; then 949 eval $_precmd 950 _return=$? 951 check_early_term $rc_arg $_return "$rc_force" || return $(($?-1)) 952 fi 953 954 # send the signal to stop 955 # 956 echo "Stopping ${name}." 957 _doit="kill -${sig_stop:-TERM} $rc_pid" 958 if [ -n "$_user" ]; then 959 _doit="su -m $_user -c 'sh -c \"$_doit\"'" 960 fi 961 962 # if the stop cmd failed and force 963 # isn't set, exit 964 # 965 eval $_doit 966 _return=$? 967 check_early_term $rc_arg $_return "$rc_force" || return $(($?-1)) 968 # wait for the command to exit, 969 # and run postcmd. 970 sleep 0.1 971 wait_for_pids $rc_pid 972 if [ -n "$_postcmd" ]; then 973 eval $_postcmd 974 _return=$? 975 fi 976 ;; 977 978 reload) 979 if [ -z "$rc_pid" ]; then 980 if [ -n "$pidfile" ]; then 981 echo \ 982 "${name} not running? (check $pidfile)." 983 else 984 echo "${name} not running?" 985 fi 986 set_provide_list $rc_arg $RC_FAILED 987 exit 1 988 fi 989 echo "Reloading ${name} config files." 990 if [ -n "$_precmd" ]; then 991 eval $_precmd 992 _return=$? 993 check_early_term $rc_arg $_return "$rc_force" || return $(($?-1)) 994 fi 995 _doit="kill -${sig_reload:-HUP} $rc_pid" 996 if [ -n "$_user" ]; then 997 _doit="su -m $_user -c 'sh -c \"$_doit\"'" 998 fi 999 eval $_doit 1000 _return=$? 1001 check_early_term $rc_arg $_return "$rc_force" || return $(($?-1)) 1002 if [ -n "$_postcmd" ]; then 1003 eval $_postcmd 1004 _return=$? 1005 fi 1006 ;; 1007 1008 restart) 1009 if [ -n "$_precmd" ]; then 1010 eval $_precmd $rc_extra_args 1011 _return=$? 1012 check_early_term $rc_arg $_return "$rc_force" || return $(($?-1)) 1013 fi 1014 # prevent restart being called more 1015 # than once by any given script 1016 # 1017 if [ -n "$_rc_restart_done" ]; then 1018 return 0 1019 fi 1020 _rc_restart_done=YES 1021 1022 ( $0 ${rc_force:+force}stop $rc_extra_args ) 1023 $0 ${rc_force:+force}start $rc_extra_args 1024 _return=$? 1025 1026 if [ -n "$_postcmd" ]; then 1027 eval $_postcmd $rc_extra_args 1028 adjust_return_code $? 1029 _return=$? 1030 fi 1031 # Do not set_provide_list(), the start command above 1032 # will have done it for us and we do not know the 1033 # actual RC code to base a setting on here. 1034 # 1035 return $_return 1036 ;; 1037 1038 poll) 1039 if [ -n "$rc_pid" ]; then 1040 wait_for_pids $rc_pid 1041 fi 1042 ;; 1043 1044 rcvar) 1045 echo "# $name" 1046 if [ -n "$rcvar" ]; then 1047 if checkyesno ${rcvar}; then 1048 echo "\$${rcvar}=YES" 1049 else 1050 echo "\$${rcvar}=NO" 1051 fi 1052 fi 1053 ;; 1054 1055 *) 1056 rc_usage "$_keywords" 1057 ;; 1058 1059 esac 1060 set_provide_list $rc_arg $_return 1061 adjust_return_code $_return 1062 return $? 1063 done 1064 1065 echo 1>&2 "$0: unknown directive '$rc_arg'." 1066 rc_usage "$_keywords" 1067 exit 1 1068} 1069 1070# 1071# Helper functions for run_rc_command: common code. 1072# They use such global variables besides the exported rc_* ones: 1073# 1074# name R/W 1075# ------------------ 1076# _precmd R 1077# _postcmd R 1078# _return W 1079# 1080_run_rc_precmd() 1081{ 1082 check_required_before "$rc_arg" || return 1 1083 1084 if [ -n "$_precmd" ]; then 1085 debug "run_rc_command: ${rc_arg}_precmd: $_precmd $rc_extra_args" 1086 eval "$_precmd $rc_extra_args" 1087 _return=$? 1088 1089 # If precmd failed and force isn't set, request exit. 1090 if [ $_return -ne 0 ] && [ -z "$rc_force" ]; then 1091 return 1 1092 fi 1093 fi 1094 1095 check_required_after "$rc_arg" || return 1 1096 1097 return 0 1098} 1099 1100_run_rc_postcmd() 1101{ 1102 if [ -n "$_postcmd" ]; then 1103 debug "run_rc_command: ${rc_arg}_postcmd: $_postcmd $rc_extra_args" 1104 eval "$_postcmd $rc_extra_args" 1105 _return=$? 1106 fi 1107 return 0 1108} 1109 1110_run_rc_doit() 1111{ 1112 debug "run_rc_command: doit: $*" 1113 eval "$@" 1114 _return=$? 1115 1116 # If command failed and force isn't set, request exit. 1117 if [ $_return -ne 0 ] && [ -z "$rc_force" ]; then 1118 return 1 1119 fi 1120 1121 return 0 1122} 1123 1124_run_rc_notrunning() 1125{ 1126 local _pidmsg 1127 1128 if [ -n "$pidfile" ]; then 1129 _pidmsg=" (check $pidfile)." 1130 else 1131 _pidmsg= 1132 fi 1133 echo 1>&2 "${name} not running?${_pidmsg}" 1134} 1135 1136_run_rc_killcmd() 1137{ 1138 local _cmd 1139 1140 _cmd="kill -$1 $rc_pid" 1141 if [ -n "$_user" ]; then 1142 _cmd="su -m ${_user} -c 'sh -c \"${_cmd}\"'" 1143 fi 1144 echo "$_cmd" 1145} 1146 1147# 1148# run_rc_script file arg 1149# Start the script `file' with `arg', and correctly handle the 1150# return value from the script. If `file' ends with `.sh', it's 1151# sourced into the current environment. If `file' appears to be 1152# a backup or scratch file, ignore it. Otherwise if it's 1153# executable run as a child process. 1154# 1155run_rc_script() 1156{ 1157 _file=$1 1158 _arg=$2 1159 if [ -z "$_file" -o -z "$_arg" ]; then 1160 err 3 'USAGE: run_rc_script file arg' 1161 fi 1162 1163 trap "echo 'Reboot interrupted'; exit 1" 3 1164 1165 unset name command command_args command_interpreter \ 1166 extra_commands pidfile procname \ 1167 rcvar required_dirs required_files required_vars 1168 eval unset ${_arg}_cmd ${_arg}_precmd ${_arg}_postcmd 1169 1170 case "$_file" in 1171 *.sh) # run in current shell 1172 set $_arg ; . $_file 1173 ;; 1174 *[~#]|*.OLD|*.orig) # scratch file; skip 1175 warn "Ignoring scratch file $_file" 1176 ;; 1177 *) # run in subshell 1178 if [ -x $_file ]; then 1179 if [ -n "$rc_fast_and_loose" ]; then 1180 set $_arg ; . $_file 1181 else 1182 ( trap "echo 'Reboot interrupted'; exit 1" 3 1183 set $_arg ; . $_file ) 1184 fi 1185 fi 1186 ;; 1187 esac 1188} 1189 1190# Code common to scripts that need to load a kernel module 1191# if it isn't in the kernel yet. Syntax: 1192# load_kld [-e regex] [-m module] file 1193# where -e or -m chooses the way to check if the module 1194# is already loaded: 1195# regex is egrep'd in the output from `kldstat -v', 1196# module is passed to `kldstat -m'. 1197# The default way is as though `-m file' were specified. 1198load_kld() 1199{ 1200 local _loaded _mod _opt _re 1201 1202 while getopts "e:m:" _opt; do 1203 case "$_opt" in 1204 e) _re="$OPTARG" ;; 1205 m) _mod="$OPTARG" ;; 1206 *) err 3 'USAGE: load_kld [-e regex] [-m module] file' ;; 1207 esac 1208 done 1209 shift $(($OPTIND - 1)) 1210 if [ $# -ne 1 ]; then 1211 err 3 'USAGE: load_kld [-e regex] [-m module] file' 1212 fi 1213 _mod=${_mod:-$1} 1214 _loaded=false 1215 if [ -n "$_re" ]; then 1216 if kldstat -v | egrep -q -e "$_re"; then 1217 _loaded=true 1218 fi 1219 else 1220 if kldstat -q -m "$_mod"; then 1221 _loaded=true 1222 fi 1223 fi 1224 if ! $_loaded; then 1225 if ! kldload "$1"; then 1226 warn "Unable to load kernel module $1" 1227 return 1 1228 else 1229 info "$1 kernel module loaded." 1230 fi 1231 else 1232 debug "load_kld: $1 kernel module already loaded." 1233 fi 1234 return 0 1235} 1236 1237 1238# ltr str src dst 1239# Change every $src in $str to $dst. 1240# Useful when /usr is not yet mounted and we cannot use tr(1), sed(1) nor 1241# awk(1). 1242ltr() 1243{ 1244 local _str _src _dst _out _com 1245 _str=$1 1246 _src=$2 1247 _dst=$3 1248 _out="" 1249 1250 IFS=${_src} 1251 for _com in ${_str}; do 1252 if [ -z "${_out}" ]; then 1253 _out="${_com}" 1254 else 1255 _out="${_out}${_dst}${_com}" 1256 fi 1257 done 1258 echo "${_out}" 1259} 1260 1261# 1262# load_rc_config 1263# Source in the configuration file for a given command. 1264# 1265load_rc_config() 1266{ 1267 _command=$1 1268 if [ -z "$_command" ]; then 1269 err 3 'USAGE: load_rc_config command' 1270 fi 1271 1272 if [ -z "$_rc_conf_loaded" ]; then 1273 if [ -r /etc/defaults/rc.conf ]; then 1274 debug "Sourcing /etc/defaults/rc.conf" 1275 . /etc/defaults/rc.conf 1276 source_rc_confs 1277 elif [ -r /etc/rc.conf ]; then 1278 debug "Sourcing /etc/rc.conf (/etc/defaults/rc.conf doesn't exist)." 1279 . /etc/rc.conf 1280 fi 1281 _rc_conf_loaded=YES 1282 fi 1283 if [ -f /etc/rc.conf.d/"$_command" ]; then 1284 debug "Sourcing /etc/rc.conf.d/${_command}" 1285 . /etc/rc.conf.d/"$_command" 1286 fi 1287 1288 # XXX - Deprecated variable name support 1289 # 1290 [ -n "$portmap_enable" ] && rpcbind_enable="$portmap_enable" 1291 [ -n "$portmap_program" ] && rpcbind_program="$portmap_program" 1292 [ -n "$portmap_flags" ] && rpcbind_flags="$portmap_flags" 1293 [ -n "$single_mountd_enable" ] && mountd_enable="$single_mountd_enable" 1294 1295} 1296 1297# 1298# rc_usage commands 1299# Print a usage string for $0, with `commands' being a list of 1300# valid commands. 1301# 1302rc_usage() 1303{ 1304 echo -n 1>&2 "Usage: $0 [fast|force|one|quiet](" 1305 1306 _sep= 1307 for _elem in $*; do 1308 echo -n 1>&2 "$_sep$_elem" 1309 _sep="|" 1310 done 1311 echo 1>&2 ")" 1312 exit 1 1313} 1314 1315# 1316# err exitval message 1317# Display message to stderr and log to the syslog, and exit with exitval. 1318# 1319err() 1320{ 1321 exitval=$1 1322 shift 1323 1324 if [ -x /usr/bin/logger ]; then 1325 logger "$0: ERROR: $*" 1326 fi 1327 echo 1>&2 "$0: ERROR: $*" 1328 exit $exitval 1329} 1330 1331# 1332# warn message 1333# Display message to stderr and log to the syslog. 1334# 1335warn() 1336{ 1337 if [ -x /usr/bin/logger ]; then 1338 logger "$0: WARNING: $*" 1339 fi 1340 echo 1>&2 "$0: WARNING: $*" 1341} 1342 1343# 1344# info message 1345# Display informational message to stdout and log to syslog. 1346# 1347info() 1348{ 1349 case ${rc_info} in 1350 [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1) 1351 if [ -x /usr/bin/logger ]; then 1352 logger "$0: INFO: $*" 1353 fi 1354 echo "$0: INFO: $*" 1355 ;; 1356 esac 1357} 1358 1359# 1360# debug message 1361# If debugging is enabled in rc.conf output message to stderr. 1362# BEWARE that you don't call any subroutine that itself calls this 1363# function. 1364# 1365debug() 1366{ 1367 case ${rc_debug} in 1368 [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1) 1369 if [ -x /usr/bin/logger ]; then 1370 logger "$0: INFO: $*" 1371 fi 1372 echo 1>&2 "$0: DEBUG: $*" 1373 ;; 1374 esac 1375} 1376 1377# 1378# backup_file action file cur backup 1379# Make a backup copy of `file' into `cur', and save the previous 1380# version of `cur' as `backup' or use rcs for archiving. 1381# 1382# This routine checks the value of the backup_uses_rcs variable, 1383# which can be either YES or NO. 1384# 1385# The `action' keyword can be one of the following: 1386# 1387# add `file' is now being backed up (and is possibly 1388# being reentered into the backups system). `cur' 1389# is created and RCS files, if necessary, are 1390# created as well. 1391# 1392# update `file' has changed and needs to be backed up. 1393# If `cur' exists, it is copied to to `back' or 1394# checked into RCS (if the repository file is old), 1395# and then `file' is copied to `cur'. Another RCS 1396# check in done here if RCS is being used. 1397# 1398# remove `file' is no longer being tracked by the backups 1399# system. If RCS is not being used, `cur' is moved 1400# to `back', otherwise an empty file is checked in, 1401# and then `cur' is removed. 1402# 1403# 1404backup_file() 1405{ 1406 _action=$1 1407 _cpfile=$2 1408 _cur=$3 1409 _back=$4 1410 1411 if checkyesno backup_uses_rcs; then 1412 _msg0="backup archive" 1413 _msg1="update" 1414 1415 # ensure that history file is not locked 1416 if [ -f $_cur,v ]; then 1417 rcs -q -u -U -M $_cur 1418 fi 1419 1420 # ensure after switching to rcs that the 1421 # current backup is not lost 1422 if [ -f $_cur ]; then 1423 # no archive, or current newer than archive 1424 if [ ! -f $_cur,v -o $_cur -nt $_cur,v ]; then 1425 ci -q -f -u -t-"$_msg0" -m"$_msg1" $_cur 1426 rcs -q -kb -U $_cur 1427 co -q -f -u $_cur 1428 fi 1429 fi 1430 1431 case $_action in 1432 add|update) 1433 cp -p $_cpfile $_cur 1434 ci -q -f -u -t-"$_msg0" -m"$_msg1" $_cur 1435 rcs -q -kb -U $_cur 1436 co -q -f -u $_cur 1437 chown root:wheel $_cur $_cur,v 1438 ;; 1439 remove) 1440 cp /dev/null $_cur 1441 ci -q -f -u -t-"$_msg0" -m"$_msg1" $_cur 1442 rcs -q -kb -U $_cur 1443 chown root:wheel $_cur $_cur,v 1444 rm $_cur 1445 ;; 1446 esac 1447 else 1448 case $_action in 1449 add|update) 1450 if [ -f $_cur ]; then 1451 cp -p $_cur $_back 1452 fi 1453 cp -p $_cpfile $_cur 1454 chown root:wheel $_cur 1455 ;; 1456 remove) 1457 mv -f $_cur $_back 1458 ;; 1459 esac 1460 fi 1461} 1462 1463# devfs_mount_jail dir 1464# Mounts a devfs file system appropriate for jails 1465# on the directory dir. 1466# This function returns non-zero if an error occurs. 1467# 1468devfs_mount_jail() 1469{ 1470 local jdev _me 1471 jdev="$1" 1472 _me="devfs_mount_jail" 1473 1474 if ! devfs_domount "$jdev" $rs; then 1475 warn "$_me: devfs was not mounted on $jdev" 1476 return 1 1477 fi 1478 return 0 1479} 1480 1481# devfs_domount dir 1482# Mount devfs on dir. 1483# Returns 0 on success. 1484# 1485devfs_domount() 1486{ 1487 local devdir _me 1488 devdir="$1" 1489 _me="devfs_domount()" 1490 1491 if [ -z "$devdir" ]; then 1492 warn "$_me: you must specify a mount-point" 1493 return 1 1494 fi 1495 1496 debug "$_me: mount-point is ($devdir)" 1497 if ! mount -t devfs devfs "$devdir"; then 1498 warn "$_me: Unable to mount devfs on $devdir" 1499 return 1 1500 fi 1501 1502return 0 1503} 1504 1505# Find scripts in local_startup directories. 1506find_local_scripts() { 1507 local_rc='' 1508 for dir in ${local_startup}; do 1509 if [ -d "${dir}" ]; then 1510 for file in `grep -l '^# PROVIDE:' ${dir}/* 2>/dev/null`; do 1511 case "$file" in 1512 *.sample) ;; 1513 *) if [ -x "$file" ]; then 1514 local_rc="${local_rc} ${file}" 1515 fi 1516 ;; 1517 esac 1518 done 1519 fi 1520 done 1521} 1522