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