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.11 2004/05/31 17:50:39 dillon 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}_enable 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 eval _value=\$${1} 223 debug "checkyesno: $1 is set to $_value." 224 case $_value in 225 226 # "yes", "true", "on", or "1" 227 [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1) 228 return 0 229 ;; 230 231 # "no", "false", "off", or "0" 232 [Nn][Oo]|[Ff][Aa][Ll][Ss][Ee]|[Oo][Ff][Ff]|0) 233 return 1 234 ;; 235 *) 236 warn "\$${1} is not set properly - see rc.conf(5)." 237 return 1 238 ;; 239 esac 240} 241 242# reverse_list list 243# print the list in reverse order 244# 245reverse_list() 246{ 247 _revlist= 248 for _revfile in $*; do 249 _revlist="$_revfile $_revlist" 250 done 251 echo $_revlist 252} 253 254# 255# mount_critical_filesystems type 256# Go through the list of critical filesystems as provided in 257# the rc.conf(5) variable $critical_filesystems_${type}, checking 258# each one to see if it is mounted, and if it is not, mounting it. 259# 260mount_critical_filesystems() 261{ 262 eval _fslist=\$critical_filesystems_${1} 263 for _fs in $_fslist; do 264 mount | ( 265 _ismounted=no 266 while read what _on on _type type; do 267 if [ $on = $_fs ]; then 268 _ismounted=yes 269 fi 270 done 271 if [ $_ismounted = no ]; then 272 mount $_fs >/dev/null 2>&1 273 fi 274 ) 275 done 276} 277 278# 279# check_pidfile pidfile procname [interpreter] 280# Parses the first line of pidfile for a PID, and ensures 281# that the process is running and matches procname. 282# Prints the matching PID upon success, nothing otherwise. 283# interpreter is optional; see _find_processes() for details. 284# 285check_pidfile() 286{ 287 _pidfile=$1 288 _procname=$2 289 _interpreter=$3 290 if [ -z "$_pidfile" -o -z "$_procname" ]; then 291 err 3 'USAGE: check_pidfile pidfile procname [interpreter]' 292 fi 293 if [ ! -f $_pidfile ]; then 294 debug "pid file {$_pidfile): not readable." 295 return 296 fi 297 read _pid _junk < $_pidfile 298 if [ -z "$_pid" ]; then 299 debug "pid file {$_pidfile): no pid in file." 300 return 301 fi 302 _find_processes $_procname ${_interpreter:-.} '-p '"$_pid" 303} 304 305# 306# check_process procname [interpreter] 307# Ensures that a process (or processes) named procname is running. 308# Prints a list of matching PIDs. 309# interpreter is optional; see _find_processes() for details. 310# 311check_process() 312{ 313 _procname=$1 314 _interpreter=$2 315 if [ -z "$_procname" ]; then 316 err 3 'USAGE: check_process procname [interpreter]' 317 fi 318 _find_processes $_procname ${_interpreter:-.} '-ax' 319} 320 321# 322# _find_processes procname interpreter psargs 323# Search for procname in the output of ps generated by psargs. 324# Prints the PIDs of any matching processes, space separated. 325# 326# If interpreter == ".", check the following variations of procname 327# against the first word of each command: 328# procname 329# `basename procname` 330# `basename procname` + ":" 331# "(" + `basename procname` + ")" 332# 333# If interpreter != ".", read the first line of procname, remove the 334# leading #!, normalise whitespace, append procname, and attempt to 335# match that against each command, either as is, or with extra words 336# at the end. 337# 338_find_processes() 339{ 340 if [ $# -ne 3 ]; then 341 err 3 'USAGE: _find_processes procname interpreter psargs' 342 fi 343 _procname=$1 344 _interpreter=$2 345 _psargs=$3 346 347 _pref= 348 if [ $_interpreter != "." ]; then # an interpreted script 349 read _interp < $_procname # read interpreter name 350 _interp=${_interp#\#!} # strip #! 351 set -- $_interp 352 if [ $_interpreter != $1 ]; then 353 warn "\$command_interpreter $_interpreter != $1" 354 fi 355 _interp="$* $_procname" # cleanup spaces, add _procname 356 _fp_args='_argv' 357 _fp_match='case "$_argv" in 358 ${_interp}|"${_interp} "*)' 359 else # a normal daemon 360 _procnamebn=${_procname##*/} 361 _fp_args='_arg0 _argv' 362 _fp_match='case "$_arg0" in 363 $_procname|$_procnamebn|${_procnamebn}:|"(${_procnamebn})")' 364 fi 365 366 _proccheck=' 367 ps -o "pid,command" '"$_psargs"' | 368 while read _npid '"$_fp_args"'; do 369 case "$_npid" in 370 PID) 371 continue ;; 372 esac ; '"$_fp_match"' 373 echo -n "$_pref$_npid" ; 374 _pref=" " 375 ;; 376 esac 377 done' 378 379# debug "in _find_processes: proccheck is ($_proccheck)." 380 eval $_proccheck 381} 382 383# 384# wait_for_pids pid [pid ...] 385# spins until none of the pids exist 386# 387wait_for_pids() 388{ 389 _list=$* 390 if [ -z "$_list" ]; then 391 return 392 fi 393 _prefix= 394 while true; do 395 _nlist=""; 396 for _j in $_list; do 397 if kill -0 $_j 2>/dev/null; then 398 _nlist="${_nlist}${_nlist:+ }$_j" 399 fi 400 done 401 if [ -z "$_nlist" ]; then 402 break 403 fi 404 _list=$_nlist 405 echo -n ${_prefix:-"Waiting for PIDS: "}$_list 406 _prefix=", " 407 sleep 2 408 done 409 if [ -n "$_prefix" ]; then 410 echo "." 411 fi 412} 413 414# 415# run_rc_command argument 416# Search for argument in the list of supported commands, which is: 417# "start stop restart rcvar status poll ${extra_commands}" 418# If there's a match, run ${argument}_cmd or the default method 419# (see below). 420# 421# If argument has a given prefix, then change the operation as follows: 422# Prefix Operation 423# ------ --------- 424# fast Skip the pid check, and set rc_fast=yes 425# force Set ${rcvar} to YES, and set rc_force=yes 426# 427# The following globals are used: 428# 429# Name Needed Purpose 430# ---- ------ ------- 431# provide_list (gen) list of keywords provided by current rcng file 432# 433# name y Name of script. 434# 435# command n Full path to command. 436# Not needed if ${rc_arg}_cmd is set for 437# each keyword. 438# 439# command_args n Optional args/shell directives for command. 440# 441# command_interpreter n If not empty, command is interpreted, so 442# call check_{pidfile,process}() appropriately. 443# 444# extra_commands n List of extra commands supported. 445# 446# pidfile n If set, use check_pidfile $pidfile $command, 447# otherwise use check_process $command. 448# In either case, only check if $command is set. 449# 450# procname n Process name to check for instead of $command. 451# 452# rcvar n This is checked with checkyesno to determine 453# if the action should be run. 454# 455# ${name}_chroot n Directory to chroot to before running ${command} 456# Requires /usr to be mounted. 457# 458# ${name}_chdir n Directory to cd to before running ${command} 459# (if not using ${name}_chroot). 460# 461# ${name}_flags n Arguments to call ${command} with. 462# NOTE: $flags from the parent environment 463# can be used to override this. 464# 465# ${name}_nice n Nice level to run ${command} at. 466# 467# ${name}_user n User to run ${command} as, using su(1) if not 468# using ${name}_chroot. 469# Requires /usr to be mounted. 470# 471# ${name}_group n Group to run chrooted ${command} as. 472# Requires /usr to be mounted. 473# 474# ${name}_groups n Comma separated list of supplementary groups 475# to run the chrooted ${command} with. 476# Requires /usr to be mounted. 477# 478# ${rc_arg}_cmd n If set, use this as the method when invoked; 479# Otherwise, use default command (see below) 480# 481# ${rc_arg}_precmd n If set, run just before performing the 482# ${rc_arg}_cmd method in the default 483# operation (i.e, after checking for required 484# bits and process (non)existence). 485# If this completes with a non-zero exit code, 486# don't run ${rc_arg}_cmd. 487# 488# ${rc_arg}_postcmd n If set, run just after performing the 489# ${rc_arg}_cmd method, if that method 490# returned a zero exit code. 491# 492# required_dirs n If set, check for the existence of the given 493# directories before running the default 494# (re)start command. 495# 496# required_files n If set, check for the readability of the given 497# files before running the default (re)start 498# command. 499# 500# required_vars n If set, perform checkyesno on each of the 501# listed variables before running the default 502# (re)start command. 503# 504# Default behaviour for a given argument, if no override method is 505# provided: 506# 507# Argument Default behaviour 508# -------- ----------------- 509# start if !running && checkyesno ${rcvar} 510# ${command} 511# 512# stop if ${pidfile} 513# rc_pid=$(check_pidfile $pidfile $command) 514# else 515# rc_pid=$(check_process $command) 516# kill $sig_stop $rc_pid 517# wait_for_pids $rc_pid 518# ($sig_stop defaults to TERM.) 519# 520# reload Similar to stop, except use $sig_reload instead, 521# and doesn't wait_for_pids. 522# $sig_reload defaults to HUP. 523# 524# restart Run `stop' then `start'. 525# 526# status Show if ${command} is running, etc. 527# 528# poll Wait for ${command} to exit. 529# 530# rcvar Display what rc.conf variable is used (if any). 531# 532# Variables available to methods, and after run_rc_command() has 533# completed: 534# 535# Variable Purpose 536# -------- ------- 537# rc_arg Argument to command, after fast/force processing 538# performed 539# 540# rc_flags Flags to start the default command with. 541# Defaults to ${name}_flags, unless overridden 542# by $flags from the environment. 543# This variable may be changed by the precmd method. 544# 545# rc_pid PID of command (if appropriate) 546# 547# rc_fast Not empty if "fast" was provided (q.v.) 548# 549# rc_force Not empty if "force" was provided (q.v.) 550# 551# 552dummy_rc_command() 553{ 554 rc_arg=$1 555 556 case "$rc_arg" in 557 fast*) # "fast" prefix; don't check pid 558 rc_arg=${rc_arg#fast} 559 ;; 560 force*) # "force prefix; always start 561 rc_arg=${rc_arg#force} 562 ;; 563 esac 564 set_provide_list $rc_arg $RC_CONFIGURED 565 return 0 566} 567 568run_rc_command() 569{ 570 _return=0 571 rc_arg=$1 572 if [ -z "$name" ]; then 573 err 3 'run_rc_command: $name is not set.' 574 fi 575 576 case "$rc_arg" in 577 fast*) # "fast" prefix; don't check pid 578 rc_arg=${rc_arg#fast} 579 rc_fast=yes 580 ;; 581 force*) # "force prefix; always start 582 rc_arg=${rc_arg#force} 583 rc_force=yes 584 if [ -n "${rcvar}" ]; then 585 eval ${rcvar}=YES 586 fi 587 ;; 588 esac 589 590 eval _overide_command=\$${name}_program 591 if [ -n "$_overide_command" ]; then 592 command=$_overide_command 593 fi 594 595 _keywords="start stop restart rcvar $extra_commands" 596 rc_pid= 597 _pidcmd= 598 _procname=${procname:-${command}} 599 600 # setup pid check command if not fast 601 if [ -z "$rc_fast" -a -n "$_procname" ]; then 602 if [ -n "$pidfile" ]; then 603 _pidcmd='rc_pid=$(check_pidfile '"$pidfile $_procname $command_interpreter"')' 604 else 605 _pidcmd='rc_pid=$(check_process '"$_procname $command_interpreter"')' 606 fi 607 if [ -n "$_pidcmd" ]; then 608 _keywords="${_keywords} status poll" 609 fi 610 fi 611 612 if [ -z "$rc_arg" ]; then 613 rc_usage "$_keywords" 614 fi 615 616 if [ -n "$flags" ]; then # allow override from environment 617 rc_flags=$flags 618 else 619 eval rc_flags=\$${name}_flags 620 fi 621 eval _chdir=\$${name}_chdir _chroot=\$${name}_chroot \ 622 _nice=\$${name}_nice _user=\$${name}_user \ 623 _group=\$${name}_group _groups=\$${name}_groups 624 625 if [ -n "$_user" ]; then # unset $_user if running as that user 626 if [ "$_user" = "$(id -un)" ]; then 627 unset _user 628 fi 629 fi 630 631 # if ${rcvar} is set, and $1 is not 632 # "rcvar", then run 633 # checkyesno ${rcvar} 634 # and return if that failed 635 # 636 if [ -n "${rcvar}" -a "$rc_arg" != "rcvar" ]; then 637 if ! checkyesno ${rcvar}; then 638 set_provide_list $rc_arg $RC_DISABLED 639 return 0 640 fi 641 fi 642 643 eval $_pidcmd # determine the pid if necessary 644 645 for _elem in $_keywords; do 646 if [ "$_elem" != "$rc_arg" ]; then 647 continue 648 fi 649 650 # if there's a custom ${XXX_cmd}, 651 # run that instead of the default 652 # 653 eval _cmd=\$${rc_arg}_cmd _precmd=\$${rc_arg}_precmd \ 654 _postcmd=\$${rc_arg}_postcmd 655 if [ -n "$_cmd" ]; then 656 # if the precmd failed and force 657 # isn't set, exit 658 # 659 if [ -n "$_precmd" ]; then 660 debug "run_rc_command: evaluating ${_precmd}()." 661 eval $_precmd 662 663 _return=$? 664 check_early_term $rc_arg $_return "$rc_force" || return $(($?-1)) 665 fi 666 667 if [ -n "$_cmd" ]; then 668 debug "run_rc_command: evaluating ${_cmd}()." 669 eval $_cmd 670 _return=$? 671 check_early_term $rc_arg $_return "$rc_force" || return $(($?-1)) 672 fi 673 674 if [ -n "$_postcmd" ]; then 675 debug "run_rc_command: evaluating ${_postcmd}()." 676 eval $_postcmd 677 _return=$? 678 check_early_term $rc_arg $_return "" || return $(($?-1)) 679 fi 680 set_provide_list $rc_arg $_return 681 adjust_return_code $_return 682 return $? 683 fi 684 685 case "$rc_arg" in # default operations... 686 687 status) 688 if [ -n "$rc_pid" ]; then 689 echo "${name} is running as pid $rc_pid." 690 else 691 echo "${name} is not running." 692 return 1 693 fi 694 ;; 695 696 start) 697 if [ -n "$rc_pid" ]; then 698 echo "${name} already running? (pid=$rc_pid)." 699 exit 1 700 fi 701 702 if [ ! -x $command ]; then 703 info "run_rc_command: cannot run ($command)." 704 set_provide_list $rc_arg $RC_FAILED 705 adjust_return_code $RC_FAILED 706 return $? 707 fi 708 709 # check for required variables, 710 # directories, and files 711 # 712 for _f in $required_vars; do 713 if ! checkyesno $_f; then 714 warn "\$${_f} is not set." 715 if [ -z "$rc_force" ]; then 716 set_provide_list $rc_arg $RC_FAILED 717 adjust_return_code $RC_FAILED 718 return $? 719 fi 720 fi 721 done 722 for _f in $required_dirs; do 723 if [ ! -d "${_f}/." ]; then 724 warn "${_f} is not a directory." 725 if [ -z "$rc_force" ]; then 726 set_provide_list $rc_arg $RC_FAILED 727 adjust_return_code $RC_FAILED 728 return $? 729 fi 730 fi 731 done 732 for _f in $required_files; do 733 if [ ! -r "${_f}" ]; then 734 warn "${_f} is not readable." 735 if [ -z "$rc_force" ]; then 736 set_provide_list $rc_arg $RC_FAILED 737 adjust_return_code $RC_FAILED 738 return $? 739 fi 740 fi 741 done 742 743 # if the precmd failed and force 744 # isn't set, exit 745 # 746 if [ -n "${_precmd}" ]; then 747 debug "run_rc_command: evaluating ${_precmd}()." 748 eval $_precmd 749 _return=$? 750 check_early_term $rc_arg $_return "$rc_force" || return $(($?-1)) 751 fi 752 753 # setup the command to run, and run it 754 # 755 echo "Starting ${name}." 756 if [ -n "$_chroot" ]; then 757 _doit="\ 758${_nice:+nice -n $_nice }\ 759chroot ${_user:+-u $_user }${_group:+-g $_group }${_groups:+-G $_groups }\ 760$_chroot $command $rc_flags $command_args" 761 else 762 _doit="\ 763${_chdir:+cd $_chdir; }\ 764${_nice:+nice -n $_nice }\ 765$command $rc_flags $command_args" 766 if [ -n "$_user" ]; then 767 _doit="su -m $_user -c 'sh -c \"$_doit\"'" 768 fi 769 fi 770 771 # if the cmd failed and force 772 # isn't set, exit 773 # 774 debug "run_rc_command: _doit: $_doit" 775 eval $_doit 776 _return=$? 777 check_early_term $rc_arg $_return "$rc_force" || return $(($?-1)) 778 # finally, run postcmd 779 # 780 if [ -n "${_postcmd}" ]; then 781 debug "run_rc_command: evaluating ${_postcmd}()." 782 eval $_postcmd 783 fi 784 ;; 785 786 stop) 787 if [ -z "$rc_pid" ]; then 788 if [ -n "$pidfile" ]; then 789 echo \ 790 "${name} not running? (check $pidfile)." 791 else 792 echo "${name} not running?" 793 fi 794 set_provide_list $rc_arg $RC_STOPPED 795 exit 1 796 fi 797 798 # if the precmd failed and force 799 # isn't set, exit 800 # 801 if [ -n $_precmd ]; then 802 eval $_precmd 803 _return=$? 804 check_early_term $rc_arg $_return "$rc_force" || return $(($?-1)) 805 fi 806 807 # send the signal to stop 808 # 809 echo "Stopping ${name}." 810 _doit="kill -${sig_stop:-TERM} $rc_pid" 811 if [ -n "$_user" ]; then 812 _doit="su -m $_user -c 'sh -c \"$_doit\"'" 813 fi 814 815 # if the stop cmd failed and force 816 # isn't set, exit 817 # 818 eval $_doit 819 _return=$? 820 check_early_term $rc_arg $_return "$rc_force" || return $(($?-1)) 821 # wait for the command to exit, 822 # and run postcmd. 823 sleep 0.1 824 wait_for_pids $rc_pid 825 if [ -n "$_postcmd" ]; then 826 eval $_postcmd 827 _return=$? 828 fi 829 ;; 830 831 reload) 832 if [ -z "$rc_pid" ]; then 833 if [ -n "$pidfile" ]; then 834 echo \ 835 "${name} not running? (check $pidfile)." 836 else 837 echo "${name} not running?" 838 fi 839 set_provide_list $rc_arg $RC_FAILED 840 exit 1 841 fi 842 echo "Reloading ${name} config files." 843 if [ -n "$_precmd" ]; then 844 eval $_precmd 845 _return=$? 846 check_early_term $rc_arg $_return "$rc_force" || return $(($?-1)) 847 fi 848 _doit="kill -${sig_reload:-HUP} $rc_pid" 849 if [ -n "$_user" ]; then 850 _doit="su -m $_user -c 'sh -c \"$_doit\"'" 851 fi 852 eval $_doit 853 _return=$? 854 check_early_term $rc_arg $_return "$rc_force" || return $(($?-1)) 855 if [ -n "$_postcmd" ]; then 856 eval $_postcmd 857 _return=$? 858 fi 859 ;; 860 861 restart) 862 if [ -n "$_precmd" ]; then 863 eval $_precmd 864 _return=$? 865 check_early_term $rc_arg $_return "$rc_force" || return $(($?-1)) 866 fi 867 # prevent restart being called more 868 # than once by any given script 869 # 870 if [ -n "$_rc_restart_done" ]; then 871 return 0 872 fi 873 _rc_restart_done=YES 874 875 ( $0 ${rc_force:+force}stop ) 876 $0 ${rc_force:+force}start 877 _return=$? 878 879 if [ -n "$_postcmd" ]; then 880 eval $_postcmd 881 adjust_return_code $? 882 _return=$? 883 fi 884 # Do not set_provide_list(), the start command above 885 # will have done it for us and we do not know the 886 # actual RC code to base a setting on here. 887 # 888 return $_return 889 ;; 890 891 poll) 892 if [ -n "$rc_pid" ]; then 893 wait_for_pids $rc_pid 894 fi 895 ;; 896 897 rcvar) 898 echo "# $name" 899 if [ -n "$rcvar" ]; then 900 if checkyesno ${rcvar}; then 901 echo "\$${rcvar}=YES" 902 else 903 echo "\$${rcvar}=NO" 904 fi 905 fi 906 ;; 907 908 *) 909 rc_usage "$_keywords" 910 ;; 911 912 esac 913 set_provide_list $rc_arg $_return 914 adjust_return_code $_return 915 return $? 916 done 917 918 echo 1>&2 "$0: unknown directive '$rc_arg'." 919 rc_usage "$_keywords" 920 exit 1 921} 922 923# 924# run_rc_script file arg 925# Start the script `file' with `arg', and correctly handle the 926# return value from the script. If `file' ends with `.sh', it's 927# sourced into the current environment. If `file' appears to be 928# a backup or scratch file, ignore it. Otherwise if it's 929# executable run as a child process. 930# 931run_rc_script() 932{ 933 _file=$1 934 _arg=$2 935 if [ -z "$_file" -o -z "$_arg" ]; then 936 err 3 'USAGE: run_rc_script file arg' 937 fi 938 939 trap "echo 'Reboot interrupted'; exit 1" 3 940 941 unset name command command_args command_interpreter \ 942 extra_commands pidfile procname \ 943 rcvar required_dirs required_files required_vars 944 eval unset ${_arg}_cmd ${_arg}_precmd ${_arg}_postcmd 945 946 case "$_file" in 947 *.sh) # run in current shell 948 set $_arg ; . $_file 949 ;; 950 *[~#]|*.OLD|*.orig) # scratch file; skip 951 warn "Ignoring scratch file $_file" 952 ;; 953 *) # run in subshell 954 if [ -x $_file ]; then 955 if [ -n "$rc_fast_and_loose" ]; then 956 set $_arg ; . $_file 957 else 958 ( trap "echo 'Reboot interrupted'; exit 1" 3 959 set $_arg ; . $_file ) 960 fi 961 fi 962 ;; 963 esac 964} 965 966# 967# load_rc_config 968# Source in the configuration file for a given command. 969# 970load_rc_config() 971{ 972 _command=$1 973 if [ -z "$_command" ]; then 974 err 3 'USAGE: load_rc_config command' 975 fi 976 977 if [ -z "$_rc_conf_loaded" ]; then 978 if [ -r /etc/defaults/rc.conf ]; then 979 debug "Sourcing /etc/defaults/rc.conf" 980 . /etc/defaults/rc.conf 981 source_rc_confs 982 elif [ -r /etc/rc.conf ]; then 983 debug "Sourcing /etc/rc.conf (/etc/defaults/rc.conf doesn't exist)." 984 . /etc/rc.conf 985 fi 986 _rc_conf_loaded=YES 987 fi 988 if [ -f /etc/rc.conf.d/"$_command" ]; then 989 debug "Sourcing /etc/rc.conf.d/${_command}" 990 . /etc/rc.conf.d/"$_command" 991 fi 992 993 # XXX - Deprecated variable name support 994 # 995 [ -n "$portmap_enable" ] && rpcbind_enable="$portmap_enable" 996 [ -n "$portmap_program" ] && rpcbind_program="$portmap_program" 997 [ -n "$portmap_flags" ] && rpcbind_flags="$portmap_flags" 998 [ -n "$single_mountd_enable" ] && mountd_enable="$single_mountd_enable" 999 [ -n "$xntpd_enable" ] && ntpd_enable="$xntpd_enable" 1000 [ -n "$xntpd_program" ] && ntpd_program="$xntpd_program" 1001 [ -n "$xntpd_flags" ] && ntpd_flags="$xntpd_flags" 1002 [ -n "$dhcp_program" ] && dhclient_program="$dhcp_program" 1003 [ -n "$dhcp_flags" ] && dhclient_flags="$dhcp_flags" 1004 1005} 1006 1007# 1008# rc_usage commands 1009# Print a usage string for $0, with `commands' being a list of 1010# valid commands. 1011# 1012rc_usage() 1013{ 1014 echo -n 1>&2 "Usage: $0 [fast|force](" 1015 1016 _sep= 1017 for _elem in $*; do 1018 echo -n 1>&2 "$_sep$_elem" 1019 _sep="|" 1020 done 1021 echo 1>&2 ")" 1022 exit 1 1023} 1024 1025# 1026# err exitval message 1027# Display message to stderr and log to the syslog, and exit with exitval. 1028# 1029err() 1030{ 1031 exitval=$1 1032 shift 1033 1034 if [ -x /usr/bin/logger ]; then 1035 logger "$0: ERROR: $*" 1036 fi 1037 echo 1>&2 "$0: ERROR: $*" 1038 exit $exitval 1039} 1040 1041# 1042# warn message 1043# Display message to stderr and log to the syslog. 1044# 1045warn() 1046{ 1047 if [ -x /usr/bin/logger ]; then 1048 logger "$0: WARNING: $*" 1049 fi 1050 echo 1>&2 "$0: WARNING: $*" 1051} 1052 1053# 1054# info message 1055# Display informational message to stdout and log to syslog. 1056# 1057info() 1058{ 1059 if [ -x /usr/bin/logger ]; then 1060 logger "$0: INFO: $*" 1061 fi 1062 echo "$0: INFO: $*" 1063} 1064 1065# 1066# debug message 1067# If debugging is enabled in rc.conf output message to stderr. 1068# BEWARE that you don't call any subroutine that itself calls this 1069# function. 1070# 1071debug() 1072{ 1073 case ${rc_debug} in 1074 [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1) 1075 if [ -x /usr/bin/logger ]; then 1076 logger "$0: INFO: $*" 1077 fi 1078 echo 1>&2 "$0: DEBUG: $*" 1079 ;; 1080 esac 1081} 1082 1083# 1084# backup_file action file cur backup 1085# Make a backup copy of `file' into `cur', and save the previous 1086# version of `cur' as `backup' or use rcs for archiving. 1087# 1088# This routine checks the value of the backup_uses_rcs variable, 1089# which can be either YES or NO. 1090# 1091# The `action' keyword can be one of the following: 1092# 1093# add `file' is now being backed up (and is possibly 1094# being reentered into the backups system). `cur' 1095# is created and RCS files, if necessary, are 1096# created as well. 1097# 1098# update `file' has changed and needs to be backed up. 1099# If `cur' exists, it is copied to to `back' or 1100# checked into RCS (if the repository file is old), 1101# and then `file' is copied to `cur'. Another RCS 1102# check in done here if RCS is being used. 1103# 1104# remove `file' is no longer being tracked by the backups 1105# system. If RCS is not being used, `cur' is moved 1106# to `back', otherwise an empty file is checked in, 1107# and then `cur' is removed. 1108# 1109# 1110backup_file() 1111{ 1112 _action=$1 1113 _cpfile=$2 1114 _cur=$3 1115 _back=$4 1116 1117 if checkyesno backup_uses_rcs; then 1118 _msg0="backup archive" 1119 _msg1="update" 1120 1121 # ensure that history file is not locked 1122 if [ -f $_cur,v ]; then 1123 rcs -q -u -U -M $_cur 1124 fi 1125 1126 # ensure after switching to rcs that the 1127 # current backup is not lost 1128 if [ -f $_cur ]; then 1129 # no archive, or current newer than archive 1130 if [ ! -f $_cur,v -o $_cur -nt $_cur,v ]; then 1131 ci -q -f -u -t-"$_msg0" -m"$_msg1" $_cur 1132 rcs -q -kb -U $_cur 1133 co -q -f -u $_cur 1134 fi 1135 fi 1136 1137 case $_action in 1138 add|update) 1139 cp -p $_cpfile $_cur 1140 ci -q -f -u -t-"$_msg0" -m"$_msg1" $_cur 1141 rcs -q -kb -U $_cur 1142 co -q -f -u $_cur 1143 chown root:wheel $_cur $_cur,v 1144 ;; 1145 remove) 1146 cp /dev/null $_cur 1147 ci -q -f -u -t-"$_msg0" -m"$_msg1" $_cur 1148 rcs -q -kb -U $_cur 1149 chown root:wheel $_cur $_cur,v 1150 rm $_cur 1151 ;; 1152 esac 1153 else 1154 case $_action in 1155 add|update) 1156 if [ -f $_cur ]; then 1157 cp -p $_cur $_back 1158 fi 1159 cp -p $_cpfile $_cur 1160 chown root:wheel $_cur 1161 ;; 1162 remove) 1163 mv -f $_cur $_back 1164 ;; 1165 esac 1166 fi 1167} 1168