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