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