1# $NetBSD: rc.subr,v 1.49 2002/05/21 12:31:01 lukem Exp $ 2# $FreeBSD: src/etc/rc.subr,v 1.13 2003/06/09 17:31:06 mtm Exp $ 3# $DragonFly: src/etc/rc.subr,v 1.15 2008/04/05 08:07:11 matthias Exp $ 4# 5# Copyright (c) 1997-2002 The NetBSD Foundation, Inc. 6# All rights reserved. 7# 8# This code is derived from software contributed to The NetBSD Foundation 9# by Luke Mewburn. 10# 11# Redistribution and use in source and binary forms, with or without 12# modification, are permitted provided that the following conditions 13# are met: 14# 1. Redistributions of source code must retain the above copyright 15# notice, this list of conditions and the following disclaimer. 16# 2. Redistributions in binary form must reproduce the above copyright 17# notice, this list of conditions and the following disclaimer in the 18# documentation and/or other materials provided with the distribution. 19# 3. All advertising materials mentioning features or use of this software 20# must display the following acknowledgement: 21# This product includes software developed by the NetBSD 22# Foundation, Inc. and its contributors. 23# 4. Neither the name of The NetBSD Foundation nor the names of its 24# contributors may be used to endorse or promote products derived 25# from this software without specific prior written permission. 26# 27# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 28# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 29# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 31# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37# POSSIBILITY OF SUCH DAMAGE. 38# 39# rc.subr 40# functions used by various rc scripts 41# 42 43# 44# Operating System dependent/independent variables 45# 46 47if [ "X$_file" = "X" ]; then 48 _file=$0 49fi 50 51provide_list=`rcorder -p $_file` 52 53SYSCTL="/sbin/sysctl" 54SYSCTL_N="${SYSCTL} -n" 55CMD_OSTYPE="${SYSCTL_N} kern.ostype" 56OSTYPE=`${CMD_OSTYPE}` 57 58RC_RUNNING=0 59RC_FAILED=1 60RC_DISABLED=2 61RC_IRRELEVANT=3 62RC_CONFIGURED=4 63RC_STOPPED=5 64SYSCTL_W="${SYSCTL}" 65 66# 67# functions 68# --------- 69 70# 71# set_rcvar base_var 72# Set the variable name enabling a specific service. 73# FreeBSD uses ${service}_enable, while NetBSD uses 74# just the name of the service. For example: 75# FreeBSD: sendmail_enable="YES" 76# NetBSD : sendmail="YES" 77# $1 - if $name is not the base to work of off, specify 78# a different one 79# 80set_rcvar() 81{ 82 if [ -z "$1" ]; then 83 base_var=${name} 84 else 85 base_var="$1" 86 fi 87 88 echo ${base_var} 89} 90 91# set_provide_list 92# 93# $1 should be $rc_arg (start, stop, restart, reload, etc) 94# $2 return value $RC_* 95# 96# Set the rcng_* variables associated with elements in provide_list 97# based on $1 and $2. 98# 99# Returns non-zero when early termination should occur, in which 100# case the caller should return with a value of $? - 1 101# 102set_provide_list() 103{ 104 # Remember, plret is set to the early termination return code + 1, 105 # or 0 if we want to continue the operation. 106 # 107 for i in $provide_list; do 108 case $1$2 in 109 start$RC_RUNNING|restart$RC_RUNNING) 110 varsym -s rcng_$i=running 111 ;; 112 start$RC_FAILED|restart$RC_FAILED) 113 varsym -s rcng_$i=failed 114 ;; 115 start$RC_DISABLED|restart$RC_DISABLED|reload$RC_DISABLED) 116 varsym -s rcng_$i=disabled 117 ;; 118 start$RC_IRRELEVANT|restart$RC_IRRELEVANT|reload$RC_IRRELEVANT) 119 varsym -s rcng_$i=irrelevant 120 ;; 121 start$RC_CONFIGURED|restart$RC_CONFIGURED) 122 varsym -s rcng_$i=configured 123 ;; 124 stop$RC_DISABLED) 125 varsym -s rcng_$i=disabled 126 ;; 127 stop$RC_IRRELEVANT) 128 varsym -s rcng_$i=irrelevant 129 ;; 130 stop*) 131 varsym -s rcng_$i=stopped 132 ;; 133 *) 134 ;; 135 esac 136 done 137} 138 139# check_early_term 140# $1 should be $rc_arg (start, stop, restart, reload, etc) 141# $2 return value $RC_* 142# $3 $rc_force "" not to force, "anything" to force. 143# 144# The return code is 0 if early termination is not to occur, non-zero if 145# it is to occur. When early termination is to occur the caller should 146# return check_early_term()'s return code - 1. That is, early termination 147# can occur with or without an error. 148# 149# The provide list will be adjusted when early termination occurs. 150# 151check_early_term() 152{ 153 case $2 in 154 $RC_RUNNING) 155 return 0 156 ;; 157 $RC_FAILED) 158 set_provide_list $1 $2 159 [ -z "$3" ] || return 0 160 return 2 161 ;; 162 $RC_DISABLED) 163 set_provide_list $1 $2 164 [ -z "$3" ] || return 0 165 return 1 166 ;; 167 $RC_IRRELEVANT) 168 set_provide_list $1 $2 169 [ -z "$3" ] || return 0 170 return 1 171 ;; 172 $RC_CONFIGURED) 173 return 0 174 ;; 175 $RC_STOPPED) 176 return 0 177 ;; 178 esac 179 set_provide_list $1 $2 180 [ -z "$3" ] || return 0 181 return 2 182} 183 184# adjust_return_code $1 185# 186# Convert the return code to an exit code of 0 (success) or 1 (failure) 187# 188adjust_return_code() 189{ 190 if [ $1 = $RC_FAILED ]; then 191 return 1 192 fi 193 return 0 194} 195 196# 197# force_depend script 198# Force a service to start. Intended for use by services 199# to resolve dependency issues. It is assumed the caller 200# has check to make sure this call is necessary 201# $1 - filename of script, in /etc/rc.d, to run 202# 203force_depend() 204{ 205 _depend="$1" 206 207 info "${name} depends on ${_depend}, which will be forced to start." 208 if ! /etc/rc.d/${_depend} forcestart ; then 209 warn "Unable to force ${_depend}. It may already be running." 210 return 1 211 fi 212 return 0 213} 214 215# 216# checkyesno var 217# Test $1 variable, and warn if not set to YES or NO. 218# Return 0 if it's "yes" (et al), nonzero otherwise. 219# 220checkyesno() 221{ 222 # try foo 223 eval _value=\$${1%_enable} 224 # try foo_enable 225 if [ -z $_value ] 226 then 227 eval _value=\$${1%_enable}_enable; 228 fi 229 debug "checkyesno: $1 is set to $_value." 230 case $_value in 231 232 # "yes", "true", "on", or "1" 233 [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1) 234 return 0 235 ;; 236 237 # "no", "false", "off", or "0" 238 [Nn][Oo]|[Ff][Aa][Ll][Ss][Ee]|[Oo][Ff][Ff]|0) 239 return 1 240 ;; 241 *) 242 warn "\$${1} is not set properly - see rc.conf(5)." 243 return 1 244 ;; 245 esac 246} 247 248# reverse_list list 249# print the list in reverse order 250# 251reverse_list() 252{ 253 _revlist= 254 for _revfile in $*; do 255 _revlist="$_revfile $_revlist" 256 done 257 echo $_revlist 258} 259 260# 261# mount_critical_filesystems type 262# Go through the list of critical filesystems as provided in 263# the rc.conf(5) variable $critical_filesystems_${type}, checking 264# each one to see if it is mounted, and if it is not, mounting it. 265# 266mount_critical_filesystems() 267{ 268 eval _fslist=\$critical_filesystems_${1} 269 for _fs in $_fslist; do 270 mount | ( 271 _ismounted=no 272 while read what _on on _type type; do 273 if [ $on = $_fs ]; then 274 _ismounted=yes 275 fi 276 done 277 if [ $_ismounted = no ]; then 278 mount $_fs >/dev/null 2>&1 279 fi 280 ) 281 done 282} 283 284# 285# check_pidfile pidfile procname [interpreter] 286# Parses the first line of pidfile for a PID, and ensures 287# that the process is running and matches procname. 288# Prints the matching PID upon success, nothing otherwise. 289# interpreter is optional; see _find_processes() for details. 290# 291check_pidfile() 292{ 293 _pidfile=$1 294 _procname=$2 295 _interpreter=$3 296 if [ -z "$_pidfile" -o -z "$_procname" ]; then 297 err 3 'USAGE: check_pidfile pidfile procname [interpreter]' 298 fi 299 if [ ! -f $_pidfile ]; then 300 debug "pid file {$_pidfile): not readable." 301 return 302 fi 303 read _pid _junk < $_pidfile 304 if [ -z "$_pid" ]; then 305 debug "pid file {$_pidfile): no pid in file." 306 return 307 fi 308 _find_processes $_procname ${_interpreter:-.} '-p '"$_pid" 309} 310 311# 312# check_process procname [interpreter] 313# Ensures that a process (or processes) named procname is running. 314# Prints a list of matching PIDs. 315# interpreter is optional; see _find_processes() for details. 316# 317check_process() 318{ 319 _procname=$1 320 _interpreter=$2 321 if [ -z "$_procname" ]; then 322 err 3 'USAGE: check_process procname [interpreter]' 323 fi 324 _find_processes $_procname ${_interpreter:-.} '-ax' 325} 326 327# 328# _find_processes procname interpreter psargs 329# Search for procname in the output of ps generated by psargs. 330# Prints the PIDs of any matching processes, space separated. 331# 332# If interpreter == ".", check the following variations of procname 333# against the first word of each command: 334# procname 335# `basename procname` 336# `basename procname` + ":" 337# "(" + `basename procname` + ")" 338# 339# If interpreter != ".", read the first line of procname, remove the 340# leading #!, normalise whitespace, append procname, and attempt to 341# match that against each command, either as is, or with extra words 342# at the end. 343# 344_find_processes() 345{ 346 if [ $# -ne 3 ]; then 347 err 3 'USAGE: _find_processes procname interpreter psargs' 348 fi 349 _procname=$1 350 _interpreter=$2 351 _psargs=$3 352 353 _pref= 354 if [ $_interpreter != "." ]; then # an interpreted script 355 read _interp < $_procname # read interpreter name 356 _interp=${_interp#\#!} # strip #! 357 set -- $_interp 358 if [ $_interpreter != $1 ]; then 359 warn "\$command_interpreter $_interpreter != $1" 360 fi 361 _interp="$* $_procname" # cleanup spaces, add _procname 362 _fp_args='_argv' 363 _fp_match='case "$_argv" in 364 ${_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# run_rc_command argument 422# Search for argument in the list of supported commands, which is: 423# "start stop restart rcvar status poll ${extra_commands}" 424# If there's a match, run ${argument}_cmd or the default method 425# (see below). 426# 427# If argument has a given prefix, then change the operation as follows: 428# Prefix Operation 429# ------ --------- 430# fast Skip the pid check, and set rc_fast=yes 431# force Set ${rcvar} to YES, and set rc_force=yes 432# 433# The following globals are used: 434# 435# Name Needed Purpose 436# ---- ------ ------- 437# provide_list (gen) list of keywords provided by current rcng file 438# 439# name y Name of script. 440# 441# command n Full path to command. 442# Not needed if ${rc_arg}_cmd is set for 443# each keyword. 444# 445# command_args n Optional args/shell directives for command. 446# 447# command_interpreter n If not empty, command is interpreted, so 448# call check_{pidfile,process}() appropriately. 449# 450# extra_commands n List of extra commands supported. 451# 452# pidfile n If set, use check_pidfile $pidfile $command, 453# otherwise use check_process $command. 454# In either case, only check if $command is set. 455# 456# procname n Process name to check for instead of $command. 457# 458# rcvar n This is checked with checkyesno to determine 459# if the action should be run. 460# 461# ${name}_chroot n Directory to chroot to before running ${command} 462# Requires /usr to be mounted. 463# 464# ${name}_chdir n Directory to cd to before running ${command} 465# (if not using ${name}_chroot). 466# 467# ${name}_flags n Arguments to call ${command} with. 468# NOTE: $flags from the parent environment 469# can be used to override this. 470# 471# ${name}_nice n Nice level to run ${command} at. 472# 473# ${name}_user n User to run ${command} as, using su(1) if not 474# using ${name}_chroot. 475# Requires /usr to be mounted. 476# 477# ${name}_group n Group to run chrooted ${command} as. 478# Requires /usr to be mounted. 479# 480# ${name}_groups n Comma separated list of supplementary groups 481# to run the chrooted ${command} with. 482# Requires /usr to be mounted. 483# 484# ${rc_arg}_cmd n If set, use this as the method when invoked; 485# Otherwise, use default command (see below) 486# 487# ${rc_arg}_precmd n If set, run just before performing the 488# ${rc_arg}_cmd method in the default 489# operation (i.e, after checking for required 490# bits and process (non)existence). 491# If this completes with a non-zero exit code, 492# don't run ${rc_arg}_cmd. 493# 494# ${rc_arg}_postcmd n If set, run just after performing the 495# ${rc_arg}_cmd method, if that method 496# returned a zero exit code. 497# 498# required_dirs n If set, check for the existence of the given 499# directories before running the default 500# (re)start command. 501# 502# required_files n If set, check for the readability of the given 503# files before running the default (re)start 504# command. 505# 506# required_vars n If set, perform checkyesno on each of the 507# listed variables before running the default 508# (re)start command. 509# 510# Default behaviour for a given argument, if no override method is 511# provided: 512# 513# Argument Default behaviour 514# -------- ----------------- 515# start if !running && checkyesno ${rcvar} 516# ${command} 517# 518# stop if ${pidfile} 519# rc_pid=$(check_pidfile $pidfile $command) 520# else 521# rc_pid=$(check_process $command) 522# kill $sig_stop $rc_pid 523# wait_for_pids $rc_pid 524# ($sig_stop defaults to TERM.) 525# 526# reload Similar to stop, except use $sig_reload instead, 527# and doesn't wait_for_pids. 528# $sig_reload defaults to HUP. 529# 530# restart Run `stop' then `start'. 531# 532# status Show if ${command} is running, etc. 533# 534# poll Wait for ${command} to exit. 535# 536# rcvar Display what rc.conf variable is used (if any). 537# 538# Variables available to methods, and after run_rc_command() has 539# completed: 540# 541# Variable Purpose 542# -------- ------- 543# rc_arg Argument to command, after fast/force processing 544# performed 545# 546# rc_flags Flags to start the default command with. 547# Defaults to ${name}_flags, unless overridden 548# by $flags from the environment. 549# This variable may be changed by the precmd method. 550# 551# rc_pid PID of command (if appropriate) 552# 553# rc_fast Not empty if "fast" was provided (q.v.) 554# 555# rc_force Not empty if "force" was provided (q.v.) 556# 557# 558dummy_rc_command() 559{ 560 rc_arg=$1 561 562 case "$rc_arg" in 563 fast*) # "fast" prefix; don't check pid 564 rc_arg=${rc_arg#fast} 565 ;; 566 force*) # "force prefix; always start 567 rc_arg=${rc_arg#force} 568 ;; 569 esac 570 set_provide_list $rc_arg $RC_CONFIGURED 571 return 0 572} 573 574run_rc_command() 575{ 576 _return=0 577 rc_arg=$1 578 if [ -z "$name" ]; then 579 err 3 'run_rc_command: $name is not set.' 580 fi 581 582 case "$rc_arg" in 583 fast*) # "fast" prefix; don't check pid 584 rc_arg=${rc_arg#fast} 585 rc_fast=yes 586 ;; 587 force*) # "force prefix; always start 588 rc_arg=${rc_arg#force} 589 rc_force=yes 590 if [ -n "${rcvar}" ]; then 591 eval ${rcvar}=YES 592 fi 593 ;; 594 esac 595 596 eval _override_command=\$${name}_program 597 if [ -n "$_override_command" ]; then 598 command=$_override_command 599 fi 600 601 _keywords="start stop restart rcvar $extra_commands" 602 rc_pid= 603 _pidcmd= 604 _procname=${procname:-${command}} 605 606 # setup pid check command if not fast 607 if [ -z "$rc_fast" -a -n "$_procname" ]; then 608 if [ -n "$pidfile" ]; then 609 _pidcmd='rc_pid=$(check_pidfile '"$pidfile $_procname $command_interpreter"')' 610 else 611 _pidcmd='rc_pid=$(check_process '"$_procname $command_interpreter"')' 612 fi 613 if [ -n "$_pidcmd" ]; then 614 _keywords="${_keywords} status poll" 615 fi 616 fi 617 618 if [ -z "$rc_arg" ]; then 619 rc_usage "$_keywords" 620 fi 621 622 if [ -n "$flags" ]; then # allow override from environment 623 rc_flags=$flags 624 else 625 eval rc_flags=\$${name}_flags 626 fi 627 eval _chdir=\$${name}_chdir _chroot=\$${name}_chroot \ 628 _nice=\$${name}_nice _user=\$${name}_user \ 629 _group=\$${name}_group _groups=\$${name}_groups 630 631 if [ -n "$_user" ]; then # unset $_user if running as that user 632 if [ "$_user" = "$(id -un)" ]; then 633 unset _user 634 fi 635 fi 636 637 # if ${rcvar} is set, and $1 is not 638 # "rcvar", then run 639 # checkyesno ${rcvar} 640 # and return if that failed 641 # 642 if [ -n "${rcvar}" -a "$rc_arg" != "rcvar" ]; then 643 if ! checkyesno ${rcvar}; then 644 set_provide_list $rc_arg $RC_DISABLED 645 return 0 646 fi 647 fi 648 649 eval $_pidcmd # determine the pid if necessary 650 651 for _elem in $_keywords; do 652 if [ "$_elem" != "$rc_arg" ]; then 653 continue 654 fi 655 656 # if there's a custom ${XXX_cmd}, 657 # run that instead of the default 658 # 659 eval _cmd=\$${rc_arg}_cmd _precmd=\$${rc_arg}_precmd \ 660 _postcmd=\$${rc_arg}_postcmd 661 if [ -n "$_cmd" ]; then 662 # if the precmd failed and force 663 # isn't set, exit 664 # 665 if [ -n "$_precmd" ]; then 666 debug "run_rc_command: evaluating ${_precmd}()." 667 eval $_precmd 668 669 _return=$? 670 check_early_term $rc_arg $_return "$rc_force" || return $(($?-1)) 671 fi 672 673 if [ -n "$_cmd" ]; then 674 debug "run_rc_command: evaluating ${_cmd}()." 675 eval $_cmd 676 _return=$? 677 check_early_term $rc_arg $_return "$rc_force" || return $(($?-1)) 678 fi 679 680 if [ -n "$_postcmd" ]; then 681 debug "run_rc_command: evaluating ${_postcmd}()." 682 eval $_postcmd 683 _return=$? 684 check_early_term $rc_arg $_return "" || return $(($?-1)) 685 fi 686 set_provide_list $rc_arg $_return 687 adjust_return_code $_return 688 return $? 689 fi 690 691 case "$rc_arg" in # default operations... 692 693 status) 694 if [ -n "$rc_pid" ]; then 695 echo "${name} is running as pid $rc_pid." 696 else 697 echo "${name} is not running." 698 return 1 699 fi 700 ;; 701 702 start) 703 if [ -n "$rc_pid" ]; then 704 echo "${name} already running? (pid=$rc_pid)." 705 exit 1 706 fi 707 708 if [ ! -x $command ]; then 709 info "run_rc_command: cannot run ($command)." 710 set_provide_list $rc_arg $RC_FAILED 711 adjust_return_code $RC_FAILED 712 return $? 713 fi 714 715 # check for required variables, 716 # directories, and files 717 # 718 for _f in $required_vars; do 719 if ! checkyesno $_f; then 720 warn "\$${_f} is not set." 721 if [ -z "$rc_force" ]; then 722 set_provide_list $rc_arg $RC_FAILED 723 adjust_return_code $RC_FAILED 724 return $? 725 fi 726 fi 727 done 728 for _f in $required_dirs; do 729 if [ ! -d "${_f}/." ]; then 730 warn "${_f} is not a directory." 731 if [ -z "$rc_force" ]; then 732 set_provide_list $rc_arg $RC_FAILED 733 adjust_return_code $RC_FAILED 734 return $? 735 fi 736 fi 737 done 738 for _f in $required_files; do 739 if [ ! -r "${_f}" ]; then 740 warn "${_f} is not readable." 741 if [ -z "$rc_force" ]; then 742 set_provide_list $rc_arg $RC_FAILED 743 adjust_return_code $RC_FAILED 744 return $? 745 fi 746 fi 747 done 748 749 # if the precmd failed and force 750 # isn't set, exit 751 # 752 if [ -n "${_precmd}" ]; then 753 debug "run_rc_command: evaluating ${_precmd}()." 754 eval $_precmd 755 _return=$? 756 check_early_term $rc_arg $_return "$rc_force" || return $(($?-1)) 757 fi 758 759 # setup the command to run, and run it 760 # 761 echo "Starting ${name}." 762 if [ -n "$_chroot" ]; then 763 _doit="\ 764${_nice:+nice -n $_nice }\ 765chroot ${_user:+-u $_user }${_group:+-g $_group }${_groups:+-G $_groups }\ 766$_chroot $command $rc_flags $command_args" 767 else 768 _doit="\ 769${_chdir:+cd $_chdir; }\ 770${_nice:+nice -n $_nice }\ 771$command $rc_flags $command_args" 772 if [ -n "$_user" ]; then 773 _doit="su -m $_user -c 'sh -c \"$_doit\"'" 774 fi 775 fi 776 777 # if the cmd failed and force 778 # isn't set, exit 779 # 780 debug "run_rc_command: _doit: $_doit" 781 eval $_doit 782 _return=$? 783 check_early_term $rc_arg $_return "$rc_force" || return $(($?-1)) 784 # finally, run postcmd 785 # 786 if [ -n "${_postcmd}" ]; then 787 debug "run_rc_command: evaluating ${_postcmd}()." 788 eval $_postcmd 789 fi 790 ;; 791 792 stop) 793 if [ -z "$rc_pid" ]; then 794 if [ -n "$pidfile" ]; then 795 echo \ 796 "${name} not running? (check $pidfile)." 797 else 798 echo "${name} not running?" 799 fi 800 set_provide_list $rc_arg $RC_STOPPED 801 exit 1 802 fi 803 804 # if the precmd failed and force 805 # isn't set, exit 806 # 807 if [ -n $_precmd ]; then 808 eval $_precmd 809 _return=$? 810 check_early_term $rc_arg $_return "$rc_force" || return $(($?-1)) 811 fi 812 813 # send the signal to stop 814 # 815 echo "Stopping ${name}." 816 _doit="kill -${sig_stop:-TERM} $rc_pid" 817 if [ -n "$_user" ]; then 818 _doit="su -m $_user -c 'sh -c \"$_doit\"'" 819 fi 820 821 # if the stop cmd failed and force 822 # isn't set, exit 823 # 824 eval $_doit 825 _return=$? 826 check_early_term $rc_arg $_return "$rc_force" || return $(($?-1)) 827 # wait for the command to exit, 828 # and run postcmd. 829 sleep 0.1 830 wait_for_pids $rc_pid 831 if [ -n "$_postcmd" ]; then 832 eval $_postcmd 833 _return=$? 834 fi 835 ;; 836 837 reload) 838 if [ -z "$rc_pid" ]; then 839 if [ -n "$pidfile" ]; then 840 echo \ 841 "${name} not running? (check $pidfile)." 842 else 843 echo "${name} not running?" 844 fi 845 set_provide_list $rc_arg $RC_FAILED 846 exit 1 847 fi 848 echo "Reloading ${name} config files." 849 if [ -n "$_precmd" ]; then 850 eval $_precmd 851 _return=$? 852 check_early_term $rc_arg $_return "$rc_force" || return $(($?-1)) 853 fi 854 _doit="kill -${sig_reload:-HUP} $rc_pid" 855 if [ -n "$_user" ]; then 856 _doit="su -m $_user -c 'sh -c \"$_doit\"'" 857 fi 858 eval $_doit 859 _return=$? 860 check_early_term $rc_arg $_return "$rc_force" || return $(($?-1)) 861 if [ -n "$_postcmd" ]; then 862 eval $_postcmd 863 _return=$? 864 fi 865 ;; 866 867 restart) 868 if [ -n "$_precmd" ]; then 869 eval $_precmd 870 _return=$? 871 check_early_term $rc_arg $_return "$rc_force" || return $(($?-1)) 872 fi 873 # prevent restart being called more 874 # than once by any given script 875 # 876 if [ -n "$_rc_restart_done" ]; then 877 return 0 878 fi 879 _rc_restart_done=YES 880 881 ( $0 ${rc_force:+force}stop ) 882 $0 ${rc_force:+force}start 883 _return=$? 884 885 if [ -n "$_postcmd" ]; then 886 eval $_postcmd 887 adjust_return_code $? 888 _return=$? 889 fi 890 # Do not set_provide_list(), the start command above 891 # will have done it for us and we do not know the 892 # actual RC code to base a setting on here. 893 # 894 return $_return 895 ;; 896 897 poll) 898 if [ -n "$rc_pid" ]; then 899 wait_for_pids $rc_pid 900 fi 901 ;; 902 903 rcvar) 904 echo "# $name" 905 if [ -n "$rcvar" ]; then 906 if checkyesno ${rcvar}; then 907 echo "\$${rcvar}=YES" 908 else 909 echo "\$${rcvar}=NO" 910 fi 911 fi 912 ;; 913 914 *) 915 rc_usage "$_keywords" 916 ;; 917 918 esac 919 set_provide_list $rc_arg $_return 920 adjust_return_code $_return 921 return $? 922 done 923 924 echo 1>&2 "$0: unknown directive '$rc_arg'." 925 rc_usage "$_keywords" 926 exit 1 927} 928 929# 930# run_rc_script file arg 931# Start the script `file' with `arg', and correctly handle the 932# return value from the script. If `file' ends with `.sh', it's 933# sourced into the current environment. If `file' appears to be 934# a backup or scratch file, ignore it. Otherwise if it's 935# executable run as a child process. 936# 937run_rc_script() 938{ 939 _file=$1 940 _arg=$2 941 if [ -z "$_file" -o -z "$_arg" ]; then 942 err 3 'USAGE: run_rc_script file arg' 943 fi 944 945 trap "echo 'Reboot interrupted'; exit 1" 3 946 947 unset name command command_args command_interpreter \ 948 extra_commands pidfile procname \ 949 rcvar required_dirs required_files required_vars 950 eval unset ${_arg}_cmd ${_arg}_precmd ${_arg}_postcmd 951 952 case "$_file" in 953 *.sh) # run in current shell 954 set $_arg ; . $_file 955 ;; 956 *[~#]|*.OLD|*.orig) # scratch file; skip 957 warn "Ignoring scratch file $_file" 958 ;; 959 *) # run in subshell 960 if [ -x $_file ]; then 961 if [ -n "$rc_fast_and_loose" ]; then 962 set $_arg ; . $_file 963 else 964 ( trap "echo 'Reboot interrupted'; exit 1" 3 965 set $_arg ; . $_file ) 966 fi 967 fi 968 ;; 969 esac 970} 971 972# 973# load_rc_config 974# Source in the configuration file for a given command. 975# 976load_rc_config() 977{ 978 _command=$1 979 if [ -z "$_command" ]; then 980 err 3 'USAGE: load_rc_config command' 981 fi 982 983 if [ -z "$_rc_conf_loaded" ]; then 984 if [ -r /etc/defaults/rc.conf ]; then 985 debug "Sourcing /etc/defaults/rc.conf" 986 . /etc/defaults/rc.conf 987 source_rc_confs 988 elif [ -r /etc/rc.conf ]; then 989 debug "Sourcing /etc/rc.conf (/etc/defaults/rc.conf doesn't exist)." 990 . /etc/rc.conf 991 fi 992 _rc_conf_loaded=YES 993 fi 994 if [ -f /etc/rc.conf.d/"$_command" ]; then 995 debug "Sourcing /etc/rc.conf.d/${_command}" 996 . /etc/rc.conf.d/"$_command" 997 fi 998 999 # XXX - Deprecated variable name support 1000 # 1001 [ -n "$portmap_enable" ] && rpcbind_enable="$portmap_enable" 1002 [ -n "$portmap_program" ] && rpcbind_program="$portmap_program" 1003 [ -n "$portmap_flags" ] && rpcbind_flags="$portmap_flags" 1004 [ -n "$single_mountd_enable" ] && mountd_enable="$single_mountd_enable" 1005 [ -n "$dhcp_program" ] && dhclient_program="$dhcp_program" 1006 [ -n "$dhcp_flags" ] && dhclient_flags="$dhcp_flags" 1007 1008} 1009 1010# 1011# rc_usage commands 1012# Print a usage string for $0, with `commands' being a list of 1013# valid commands. 1014# 1015rc_usage() 1016{ 1017 echo -n 1>&2 "Usage: $0 [fast|force](" 1018 1019 _sep= 1020 for _elem in $*; do 1021 echo -n 1>&2 "$_sep$_elem" 1022 _sep="|" 1023 done 1024 echo 1>&2 ")" 1025 exit 1 1026} 1027 1028# 1029# err exitval message 1030# Display message to stderr and log to the syslog, and exit with exitval. 1031# 1032err() 1033{ 1034 exitval=$1 1035 shift 1036 1037 if [ -x /usr/bin/logger ]; then 1038 logger "$0: ERROR: $*" 1039 fi 1040 echo 1>&2 "$0: ERROR: $*" 1041 exit $exitval 1042} 1043 1044# 1045# warn message 1046# Display message to stderr and log to the syslog. 1047# 1048warn() 1049{ 1050 if [ -x /usr/bin/logger ]; then 1051 logger "$0: WARNING: $*" 1052 fi 1053 echo 1>&2 "$0: WARNING: $*" 1054} 1055 1056# 1057# info message 1058# Display informational message to stdout and log to syslog. 1059# 1060info() 1061{ 1062 case ${rc_info} in 1063 [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1) 1064 if [ -x /usr/bin/logger ]; then 1065 logger "$0: INFO: $*" 1066 fi 1067 echo "$0: INFO: $*" 1068 ;; 1069 esac 1070} 1071 1072# 1073# debug message 1074# If debugging is enabled in rc.conf output message to stderr. 1075# BEWARE that you don't call any subroutine that itself calls this 1076# function. 1077# 1078debug() 1079{ 1080 case ${rc_debug} in 1081 [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1) 1082 if [ -x /usr/bin/logger ]; then 1083 logger "$0: INFO: $*" 1084 fi 1085 echo 1>&2 "$0: DEBUG: $*" 1086 ;; 1087 esac 1088} 1089 1090# 1091# backup_file action file cur backup 1092# Make a backup copy of `file' into `cur', and save the previous 1093# version of `cur' as `backup' or use rcs for archiving. 1094# 1095# This routine checks the value of the backup_uses_rcs variable, 1096# which can be either YES or NO. 1097# 1098# The `action' keyword can be one of the following: 1099# 1100# add `file' is now being backed up (and is possibly 1101# being reentered into the backups system). `cur' 1102# is created and RCS files, if necessary, are 1103# created as well. 1104# 1105# update `file' has changed and needs to be backed up. 1106# If `cur' exists, it is copied to to `back' or 1107# checked into RCS (if the repository file is old), 1108# and then `file' is copied to `cur'. Another RCS 1109# check in done here if RCS is being used. 1110# 1111# remove `file' is no longer being tracked by the backups 1112# system. If RCS is not being used, `cur' is moved 1113# to `back', otherwise an empty file is checked in, 1114# and then `cur' is removed. 1115# 1116# 1117backup_file() 1118{ 1119 _action=$1 1120 _cpfile=$2 1121 _cur=$3 1122 _back=$4 1123 1124 if checkyesno backup_uses_rcs; then 1125 _msg0="backup archive" 1126 _msg1="update" 1127 1128 # ensure that history file is not locked 1129 if [ -f $_cur,v ]; then 1130 rcs -q -u -U -M $_cur 1131 fi 1132 1133 # ensure after switching to rcs that the 1134 # current backup is not lost 1135 if [ -f $_cur ]; then 1136 # no archive, or current newer than archive 1137 if [ ! -f $_cur,v -o $_cur -nt $_cur,v ]; then 1138 ci -q -f -u -t-"$_msg0" -m"$_msg1" $_cur 1139 rcs -q -kb -U $_cur 1140 co -q -f -u $_cur 1141 fi 1142 fi 1143 1144 case $_action in 1145 add|update) 1146 cp -p $_cpfile $_cur 1147 ci -q -f -u -t-"$_msg0" -m"$_msg1" $_cur 1148 rcs -q -kb -U $_cur 1149 co -q -f -u $_cur 1150 chown root:wheel $_cur $_cur,v 1151 ;; 1152 remove) 1153 cp /dev/null $_cur 1154 ci -q -f -u -t-"$_msg0" -m"$_msg1" $_cur 1155 rcs -q -kb -U $_cur 1156 chown root:wheel $_cur $_cur,v 1157 rm $_cur 1158 ;; 1159 esac 1160 else 1161 case $_action in 1162 add|update) 1163 if [ -f $_cur ]; then 1164 cp -p $_cur $_back 1165 fi 1166 cp -p $_cpfile $_cur 1167 chown root:wheel $_cur 1168 ;; 1169 remove) 1170 mv -f $_cur $_back 1171 ;; 1172 esac 1173 fi 1174} 1175