1# $NetBSD: rc.subr,v 1.67 2006/10/07 11:25:15 elad Exp $ 2# 3# Copyright (c) 1997-2004 The NetBSD Foundation, Inc. 4# All rights reserved. 5# 6# This code is derived from software contributed to The NetBSD Foundation 7# by Luke Mewburn. 8# 9# Redistribution and use in source and binary forms, with or without 10# modification, are permitted provided that the following conditions 11# are met: 12# 1. Redistributions of source code must retain the above copyright 13# notice, this list of conditions and the following disclaimer. 14# 2. Redistributions in binary form must reproduce the above copyright 15# notice, this list of conditions and the following disclaimer in the 16# documentation and/or other materials provided with the distribution. 17# 18# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 19# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28# POSSIBILITY OF SUCH DAMAGE. 29# 30# rc.subr 31# functions used by various rc scripts 32# 33 34: ${RC_PID:=$$}; export RC_PID 35 36# 37# Operating System dependent/independent variables 38# 39 40if [ -n "${_rc_subr_loaded}" ]; then 41 return 42fi 43 44_rc_subr_loaded="YES" 45 46SYSCTL="/sbin/sysctl" 47SYSCTL_N="${SYSCTL} -n" 48SYSCTL_W="${SYSCTL}" 49PROTECT="/usr/bin/protect" 50ID="/usr/bin/id" 51IDCMD="if [ -x $ID ]; then $ID -un; fi" 52PS="/bin/ps -ww" 53SERVICE=/usr/sbin/service 54JAIL_CMD=/usr/sbin/jail 55_svcj_generic_params="path=/ mount.nodevfs host=inherit" 56JID=0 57CPUSET="/bin/cpuset" 58 59# Cache the services that we loaded with load_rc_config. 60_loaded_services="" 61 62# rc_service provides the path to the service script that we are executing. 63# This is not being set here in an execution context, necessarily, so it's 64# really just a reasonable guess, and it will get overwritten later if 65# we are executing from some other means than direct execution by service(8) 66# or manual invocation of the service script. The prime example of this is 67# during system startup, all rc scripts will be invoked via /etc/rc, so 68# run_rc_script will overwrite rc_service with the file being sourced. 69rc_service="$0" 70 71# 72# functions 73# --------- 74 75# is_verified file 76# if VERIEXEC is active check that $file is verified 77# 78VERIEXEC="/sbin/veriexec" 79if test -x $VERIEXEC && $VERIEXEC -i active > /dev/null 2>&1; then 80 is_verified() { $VERIEXEC -x $1; } 81else 82 is_verified() { return 0; } 83fi 84 85# indicate that we have vdot 86_VDOT_SH=: 87 88# current state of O_VERIFY 89o_verify() 90{ 91 case $(echo $(set -o)) in 92 *verify" "off*) echo off;; 93 *verify" "on*) echo on;; 94 esac 95} 96 97## 98# o_verify_set want [save] 99# 100# record current state of verify in $save 101# and set it to $want if different 102# 103o_verify_set() { 104 local x=$(o_verify) 105 106 [ -z "$x" ] && return 0 107 [ -z "$2" ] || eval $2=$x 108 [ "$x" = "$1" ] && return 0 109 case "$1" in 110 on) 111 set -o verify 112 ;; 113 off) 114 set +o verify 115 ;; 116 esac 117} 118 119# for unverified files 120dotted= 121dot() 122{ 123 local f verify 124 125 o_verify_set off verify 126 for f in "$@"; do 127 if [ -f $f -a -s $f ]; then 128 dotted="$dotted $f" 129 . $f 130 fi 131 done 132 o_verify_set $verify 133} 134 135# try for verified, fallback to safe 136sdot() 137{ 138 local f 139 140 for f in "$@"; do 141 [ -f $f -a -s $f ] || continue 142 vdot $f || safe_dot $f 143 done 144} 145 146# convenience function - skip if not verified 147vdot() 148{ 149 local f rc=0 verify 150 151 o_verify_set on verify 152 for f in "$@"; do 153 [ -f $f -a -s $f ] || continue 154 if is_verified $f 2> /dev/null; then 155 dotted="$dotted $f" 156 . $f 157 else 158 rc=80 # EAUTH 159 fi 160 done 161 o_verify_set $verify 162 return $rc 163} 164 165# Exists [test] file ... 166# report the first "file" that passes "test" (default -s). 167Exists() 168{ 169 local f _t=-s 170 171 while :; do 172 : 1=$1 173 case "$1" in 174 -?) 175 _t=$1 176 shift 177 ;; 178 *) 179 break 180 ;; 181 esac 182 done 183 184 for f in "$@"; do 185 [ $_t $f ] || continue 186 echo $f 187 return 0 188 done 189 return 1 190} 191 192# do we have $1 (could be a function) 193have() 194{ 195 type "$1" > /dev/null 2>&1 196} 197 198# provide consistent means of logging progress 199rc_log() 200{ 201 date "+@ %s [%Y-%m-%d %H:%M:%S %Z] $*" 202} 203 204# only rc_log if tracing enabled 205# and $level >= $RC_LEVEL 206rc_trace() 207{ 208 local level=$1; shift 209 local cf=/etc/rc.conf.d/rc_trace 210 211 if [ -z "$RC_LEVEL" ]; then 212 [ -f $cf ] || return 213 RC_LEVEL=0 # existence is 0 at least 214 sdot $cf # allow override 215 fi 216 [ ${RC_LEVEL:-0} -ge ${level:-0} ] || return 217 rc_log "$@" 218} 219 220# list_vars pattern 221# List variables matching glob pattern. 222# 223list_vars() 224{ 225 # Localize 'set' option below. 226 local - _s 227 local IFS=$'\n' line varname 228 229 # Disable path expansion temporarily in unquoted 'for' parameters below. 230 _s=$(set +o) 231 set -o noglob 232 233 for line in $(set); do 234 varname="${line%%=*}" 235 236 case "$varname" in 237 "$line"|*[!a-zA-Z0-9_]*) 238 continue 239 ;; 240 $1) 241 echo $varname 242 ;; 243 esac 244 done 245 eval $_s 246} 247 248# set_rcvar [var] [defval] [desc] 249# 250# Echo or define a rc.conf(5) variable name. Global variable 251# $rcvars is used. 252# 253# If no argument is specified, echo "${name}_enable". 254# 255# If only a var is specified, echo "${var}_enable". 256# 257# If var and defval are specified, the ${var} is defined as 258# rc.conf(5) variable and the default value is ${defvar}. An 259# optional argument $desc can also be specified to add a 260# description for that. 261# 262set_rcvar() 263{ 264 local _var 265 266 case $# in 267 0) echo ${name}_enable ;; 268 1) echo ${1}_enable ;; 269 *) 270 debug "set_rcvar: \$$1=$2 is added" \ 271 " as a rc.conf(5) variable." 272 _var=$1 273 rcvars="${rcvars# } $_var" 274 eval ${_var}_defval=\"$2\" 275 shift 2 276 eval ${_var}_desc=\"$*\" 277 ;; 278 esac 279} 280 281# set_rcvar_obsolete oldvar [newvar] [msg] 282# Define obsolete variable. 283# Global variable $rcvars_obsolete is used. 284# 285set_rcvar_obsolete() 286{ 287 local _var 288 _var=$1 289 debug "set_rcvar_obsolete: \$$1(old) -> \$$2(new) is defined" 290 291 rcvars_obsolete="${rcvars_obsolete# } $1" 292 eval ${1}_newvar=\"$2\" 293 shift 2 294 eval ${_var}_obsolete_msg=\"$*\" 295} 296 297# expandpath str 298# Apply pathname expansion to str. 299# 300expandpath() 301{ 302 local _s 303 304 _s=$(set +o) 305 set +o noglob 306 echo $1 307 eval $_s 308} 309 310# 311# force_depend script [rcvar] 312# Force a service to start. Intended for use by services 313# to resolve dependency issues. 314# $1 - filename of script, in /etc/rc.d, to run 315# $2 - name of the script's rcvar (minus the _enable) 316# 317force_depend() 318{ 319 local _depend _dep_rcvar 320 321 _depend="$1" 322 _dep_rcvar="${2:-$1}_enable" 323 324 [ -n "$rc_fast" ] && ! checkyesno always_force_depends && 325 checkyesno $_dep_rcvar && return 0 326 327 /etc/rc.d/${_depend} forcestatus >/dev/null 2>&1 && return 0 328 329 info "${name} depends on ${_depend}, which will be forced to start." 330 if ! /etc/rc.d/${_depend} forcestart; then 331 warn "Unable to force ${_depend}. It may already be running." 332 return 1 333 fi 334} 335 336# 337# checkyesno var 338# Test $1 variable, and warn if not set to YES or NO. 339# Return 0 if it's "yes" (et al), nonzero otherwise. 340# 341checkyesno() 342{ 343 eval _value=\$${1} 344 debug "checkyesno: $1 is set to $_value." 345 case $_value in 346 347 # "yes", "true", "on", or "1" 348 [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1) 349 return 0 350 ;; 351 352 # "no", "false", "off", or "0" 353 [Nn][Oo]|[Ff][Aa][Ll][Ss][Ee]|[Oo][Ff][Ff]|0) 354 return 1 355 ;; 356 *) 357 warn "\$${1} is not set properly - see rc.conf(5)." 358 return 1 359 ;; 360 esac 361} 362 363# 364# reverse_list list 365# print the list in reverse order 366# 367reverse_list() 368{ 369 _revlist= 370 for _revfile; do 371 _revlist="$_revfile $_revlist" 372 done 373 echo $_revlist 374} 375 376# stop_boot always 377# If booting directly to multiuser or $always is enabled, 378# send SIGTERM to the parent (/etc/rc) to abort the boot. 379# Otherwise just exit. 380# 381stop_boot() 382{ 383 local always 384 385 case $1 in 386 # "yes", "true", "on", or "1" 387 [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1) 388 always=true 389 ;; 390 *) 391 always=false 392 ;; 393 esac 394 if [ "$autoboot" = yes -o "$always" = true ]; then 395 echo "ERROR: ABORTING BOOT (sending SIGTERM to parent)!" 396 kill -TERM ${RC_PID} 397 fi 398 exit 1 399} 400 401# 402# mount_critical_filesystems type 403# Go through the list of critical filesystems as provided in 404# the rc.conf(5) variable $critical_filesystems_${type}, checking 405# each one to see if it is mounted, and if it is not, mounting it. 406# 407mount_critical_filesystems() 408{ 409 eval _fslist=\$critical_filesystems_${1} 410 for _fs in $_fslist; do 411 mount | ( 412 _ismounted=false 413 while read what _on on _type type; do 414 if [ $on = $_fs ]; then 415 _ismounted=true 416 fi 417 done 418 if $_ismounted; then 419 : 420 else 421 mount $_fs >/dev/null 2>&1 422 fi 423 ) 424 done 425} 426 427# 428# check_pidfile pidfile procname [interpreter] 429# Parses the first line of pidfile for a PID, and ensures 430# that the process is running and matches procname. 431# Prints the matching PID upon success, nothing otherwise. 432# interpreter is optional; see _find_processes() for details. 433# 434check_pidfile() 435{ 436 _pidfile=$1 437 _procname=$2 438 _interpreter=$3 439 if [ -z "$_pidfile" -o -z "$_procname" ]; then 440 err 3 'USAGE: check_pidfile pidfile procname [interpreter]' 441 fi 442 if [ ! -f $_pidfile ]; then 443 debug "pid file ($_pidfile): not readable." 444 return 445 fi 446 read _pid _junk < $_pidfile 447 if [ -z "$_pid" ]; then 448 debug "pid file ($_pidfile): no pid in file." 449 return 450 fi 451 _find_processes $_procname ${_interpreter:-.} '-p '"$_pid" 452} 453 454# 455# check_process procname [interpreter] 456# Ensures that a process (or processes) named procname is running. 457# Prints a list of matching PIDs. 458# interpreter is optional; see _find_processes() for details. 459# 460check_process() 461{ 462 _procname=$1 463 _interpreter=$2 464 if [ -z "$_procname" ]; then 465 err 3 'USAGE: check_process procname [interpreter]' 466 fi 467 _find_processes $_procname ${_interpreter:-.} '-ax' 468} 469 470# 471# _find_processes procname interpreter psargs 472# Search for procname in the output of ps generated by psargs. 473# Prints the PIDs of any matching processes, space separated. 474# 475# If interpreter == ".", check the following variations of procname 476# against the first word of each command: 477# procname 478# `basename procname` 479# `basename procname` + ":" 480# "(" + `basename procname` + ")" 481# "[" + `basename procname` + "]" 482# 483# If interpreter != ".", read the first line of procname, remove the 484# leading #!, normalise whitespace, append procname, and attempt to 485# match that against each command, either as is, or with extra words 486# at the end. As an alternative, to deal with interpreted daemons 487# using perl, the basename of the interpreter plus a colon is also 488# tried as the prefix to procname. 489# 490_find_processes() 491{ 492 if [ $# -ne 3 ]; then 493 err 3 'USAGE: _find_processes procname interpreter psargs' 494 fi 495 _procname=$1 496 _interpreter=$2 497 _psargs=$3 498 499 _pref= 500 if [ $_interpreter != "." ]; then # an interpreted script 501 _script="${_chroot}${_chroot:+/}$_procname" 502 if [ -r "$_script" ]; then 503 read _interp < $_script # read interpreter name 504 case "$_interp" in 505 \#!*) 506 _interp=${_interp#\#!} # strip #! 507 set -- $_interp 508 case $1 in 509 */bin/env) 510 shift # drop env to get real name 511 ;; 512 esac 513 if [ $_interpreter != $1 ]; then 514 warn "\$command_interpreter $_interpreter != $1" 515 fi 516 ;; 517 *) 518 warn "no shebang line in $_script" 519 set -- $_interpreter 520 ;; 521 esac 522 else 523 warn "cannot read shebang line from $_script" 524 set -- $_interpreter 525 fi 526 _interp="$* $_procname" # cleanup spaces, add _procname 527 _interpbn=${1##*/} 528 _fp_args='_argv' 529 _fp_match='case "$_argv" in 530 ${_interp}|"${_interp} "*|"[${_interpbn}]"|"${_interpbn}: ${_procname}"*)' 531 else # a normal daemon 532 _procnamebn=${_procname##*/} 533 _fp_args='_arg0 _argv' 534 _fp_match='case "$_arg0" in 535 $_procname|$_procnamebn|${_procnamebn}:|"(${_procnamebn})"|"[${_procnamebn}]")' 536 fi 537 538 if checkyesno ${name}_svcj && [ "${_rc_svcj}" != jailing ]; then 539 JID=$(/usr/sbin/jls -j svcj-${name} jid 2>/dev/null) 540 541 case ${JID} in 542 ''|*[!0-9]*) 543 # svcj-jail doesn't exist, fallback to host-check 544 JID=0 545 ;; 546 esac 547 fi 548 _proccheck="\ 549 $PS 2>/dev/null -o pid= -o jid= -o command= $_psargs"' | 550 while read _npid _jid '"$_fp_args"'; do 551 '"$_fp_match"' 552 if [ "$JID" -eq "$_jid" ]; 553 then echo -n "$_pref$_npid"; 554 _pref=" "; 555 fi 556 ;; 557 esac 558 done' 559 560# debug "in _find_processes: proccheck is ($_proccheck)." 561 eval $_proccheck 562} 563 564# sort_lite [-b] [-n] [-k POS] [-t SEP] 565# A lite version of sort(1) (supporting a few options) that can be used 566# before the real sort(1) is available (e.g., in scripts that run prior 567# to mountcritremote). Requires only shell built-in functionality. 568# 569sort_lite() 570{ 571 local funcname=sort_lite 572 local sort_sep="$IFS" sort_ignore_leading_space= 573 local sort_field=0 sort_strict_fields= sort_numeric= 574 local nitems=0 skip_leading=0 trim= 575 576 local OPTIND flag 577 while getopts bnk:t: flag; do 578 case "$flag" in 579 b) sort_ignore_leading_space=1 ;; 580 n) sort_numeric=1 sort_ignore_leading_space=1 ;; 581 k) sort_field="${OPTARG%%,*}" ;; # only up to first comma 582 # NB: Unlike sort(1) only one POS allowed 583 t) sort_sep="$OPTARG" 584 if [ ${#sort_sep} -gt 1 ]; then 585 echo "$funcname: multi-character tab \`$sort_sep'" >&2 586 return 1 587 fi 588 sort_strict_fields=1 589 ;; 590 \?) return 1 ;; 591 esac 592 done 593 shift $(( $OPTIND - 1 )) 594 595 # Create transformation pattern to trim leading text if desired 596 case "$sort_field" in 597 ""|[!0-9]*|*[!0-9.]*) 598 echo "$funcname: invalid sort field \`$sort_field'" >&2 599 return 1 600 ;; 601 *.*) 602 skip_leading=${sort_field#*.} sort_field=${sort_field%%.*} 603 while [ ${skip_leading:-0} -gt 1 ] 2> /dev/null; do 604 trim="$trim?" skip_leading=$(( $skip_leading - 1 )) 605 done 606 esac 607 608 # Copy input to series of local numbered variables 609 # NB: IFS of NULL preserves leading whitespace 610 local LINE 611 while IFS= read -r LINE || [ "$LINE" ]; do 612 nitems=$(( $nitems + 1 )) 613 local src_$nitems="$LINE" 614 done 615 616 # 617 # Sort numbered locals using insertion sort 618 # 619 local curitem curitem_orig curitem_mod curitem_haskey 620 local dest dest_orig dest_mod dest_haskey 621 local d gt n 622 local i=1 623 while [ $i -le $nitems ]; do 624 curitem_haskey=1 # Assume sort field (-k POS) exists 625 eval curitem=\"\$src_$i\" 626 curitem_mod="$curitem" # for modified comparison 627 curitem_orig="$curitem" # for original comparison 628 629 # Trim leading whitespace if desired 630 if [ "$sort_ignore_leading_space" ]; then 631 while case "$curitem_orig" in 632 [$IFS]*) : ;; *) false; esac 633 do 634 curitem_orig="${curitem_orig#?}" 635 done 636 curitem_mod="$curitem_orig" 637 fi 638 639 # Shift modified comparison value if sort field (-k POS) is > 1 640 n=$sort_field 641 while [ $n -gt 1 ]; do 642 case "$curitem_mod" in 643 *[$sort_sep]*) 644 # Cut text up-to (and incl.) first separator 645 curitem_mod="${curitem_mod#*[$sort_sep]}" 646 647 # Skip NULLs unless strict field splitting 648 [ "$sort_strict_fields" ] || 649 [ "${curitem_mod%%[$sort_sep]*}" ] || 650 [ $n -eq 2 ] || 651 continue 652 ;; 653 *) 654 # Asked for a field that doesn't exist 655 curitem_haskey= break 656 esac 657 n=$(( $n - 1 )) 658 done 659 660 # Trim trailing words if sort field >= 1 661 [ $sort_field -ge 1 -a "$sort_numeric" ] && 662 curitem_mod="${curitem_mod%%[$sort_sep]*}" 663 664 # Apply optional trim (-k POS.TRIM) to cut leading characters 665 curitem_mod="${curitem_mod#$trim}" 666 667 # Determine the type of modified comparison to use initially 668 # NB: Prefer numerical if requested but fallback to standard 669 case "$curitem_mod" in 670 ""|[!0-9]*) # NULL or begins with non-number 671 gt=">" 672 [ "$sort_numeric" ] && curitem_mod=0 673 ;; 674 *) 675 if [ "$sort_numeric" ]; then 676 gt="-gt" 677 curitem_mod="${curitem_mod%%[!0-9]*}" 678 # NB: trailing non-digits removed 679 # otherwise numeric comparison fails 680 else 681 gt=">" 682 fi 683 esac 684 685 # If first time through, short-circuit below position-search 686 if [ $i -le 1 ]; then 687 d=0 688 else 689 d=1 690 fi 691 692 # 693 # Find appropriate element position 694 # 695 while [ $d -gt 0 ] 696 do 697 dest_haskey=$curitem_haskey 698 eval dest=\"\$dest_$d\" 699 dest_mod="$dest" # for modified comparison 700 dest_orig="$dest" # for original comparison 701 702 # Trim leading whitespace if desired 703 if [ "$sort_ignore_leading_space" ]; then 704 while case "$dest_orig" in 705 [$IFS]*) : ;; *) false; esac 706 do 707 dest_orig="${dest_orig#?}" 708 done 709 dest_mod="$dest_orig" 710 fi 711 712 # Shift modified value if sort field (-k POS) is > 1 713 n=$sort_field 714 while [ $n -gt 1 ]; do 715 case "$dest_mod" in 716 *[$sort_sep]*) 717 # Cut text up-to (and incl.) 1st sep 718 dest_mod="${dest_mod#*[$sort_sep]}" 719 720 # Skip NULLs unless strict fields 721 [ "$sort_strict_fields" ] || 722 [ "${dest_mod%%[$sort_sep]*}" ] || 723 [ $n -eq 2 ] || 724 continue 725 ;; 726 *) 727 # Asked for a field that doesn't exist 728 dest_haskey= break 729 esac 730 n=$(( $n - 1 )) 731 done 732 733 # Trim trailing words if sort field >= 1 734 [ $sort_field -ge 1 -a "$sort_numeric" ] && 735 dest_mod="${dest_mod%%[$sort_sep]*}" 736 737 # Apply optional trim (-k POS.TRIM), cut leading chars 738 dest_mod="${dest_mod#$trim}" 739 740 # Determine type of modified comparison to use 741 # NB: Prefer numerical if requested, fallback to std 742 case "$dest_mod" in 743 ""|[!0-9]*) # NULL or begins with non-number 744 gt=">" 745 [ "$sort_numeric" ] && dest_mod=0 746 ;; 747 *) 748 if [ "$sort_numeric" ]; then 749 gt="-gt" 750 dest_mod="${dest_mod%%[!0-9]*}" 751 # NB: kill trailing non-digits 752 # for numeric comparison safety 753 else 754 gt=">" 755 fi 756 esac 757 758 # Break if we've found the proper element position 759 if [ "$curitem_haskey" -a "$dest_haskey" ]; then 760 if [ "$dest_mod" = "$curitem_mod" ]; then 761 [ "$dest_orig" ">" "$curitem_orig" ] && 762 break 763 elif [ "$dest_mod" $gt "$curitem_mod" ] \ 764 2> /dev/null 765 then 766 break 767 fi 768 else 769 [ "$dest_orig" ">" "$curitem_orig" ] && break 770 fi 771 772 # Break if we've hit the end 773 [ $d -ge $i ] && break 774 775 d=$(( $d + 1 )) 776 done 777 778 # Shift remaining positions forward, making room for new item 779 n=$i 780 while [ $n -ge $d ]; do 781 # Shift destination item forward one placement 782 eval dest_$(( $n + 1 ))=\"\$dest_$n\" 783 n=$(( $n - 1 )) 784 done 785 786 # Place the element 787 if [ $i -eq 1 ]; then 788 local dest_1="$curitem" 789 else 790 local dest_$d="$curitem" 791 fi 792 793 i=$(( $i + 1 )) 794 done 795 796 # Print sorted results 797 d=1 798 while [ $d -le $nitems ]; do 799 eval echo \"\$dest_$d\" 800 d=$(( $d + 1 )) 801 done 802} 803 804# 805# wait_for_pids pid [pid ...] 806# spins until none of the pids exist 807# 808wait_for_pids() 809{ 810 local _list _prefix _nlist _j 811 812 _list="$@" 813 if [ -z "$_list" ]; then 814 return 815 fi 816 _prefix= 817 while true; do 818 _nlist=""; 819 for _j in $_list; do 820 if kill -0 $_j 2>/dev/null; then 821 _nlist="${_nlist}${_nlist:+ }$_j" 822 [ -n "$_prefix" ] && sleep 1 823 fi 824 done 825 if [ -z "$_nlist" ]; then 826 break 827 fi 828 _list=$_nlist 829 echo -n ${_prefix:-"Waiting for PIDS: "}$_list 830 _prefix=", " 831 pwait $_list 2>/dev/null 832 done 833 if [ -n "$_prefix" ]; then 834 echo "." 835 fi 836} 837 838# 839# get_pidfile_from_conf string file 840# 841# Takes a string to search for in the specified file. 842# Ignores lines with traditional comment characters. 843# 844# Example: 845# 846# if get_pidfile_from_conf string file; then 847# pidfile="$_pidfile_from_conf" 848# else 849# pidfile='appropriate default' 850# fi 851# 852get_pidfile_from_conf() 853{ 854 if [ -z "$1" -o -z "$2" ]; then 855 err 3 "USAGE: get_pidfile_from_conf string file ($name)" 856 fi 857 858 local string file line 859 860 string="$1" ; file="$2" 861 862 if [ ! -s "$file" ]; then 863 err 3 "get_pidfile_from_conf: $file does not exist ($name)" 864 fi 865 866 while read line; do 867 case "$line" in 868 *[#\;]*${string}*) continue ;; 869 *${string}*) break ;; 870 esac 871 done < $file 872 873 if [ -n "$line" ]; then 874 line=${line#*/} 875 _pidfile_from_conf="/${line%%[\"\;]*}" 876 else 877 return 1 878 fi 879} 880 881# 882# check_startmsgs 883# If rc_quiet is set (usually as a result of using faststart at 884# boot time) check if rc_startmsgs is enabled. 885# 886check_startmsgs() 887{ 888 if [ -n "$rc_quiet" ]; then 889 checkyesno rc_startmsgs 890 else 891 return 0 892 fi 893} 894 895# 896# startmsg 897# Preferred method to use when displaying start messages in lieu of echo. 898# 899startmsg() 900{ 901 check_startmsgs && echo "$@" 902} 903 904# 905# run_rc_command argument 906# Search for argument in the list of supported commands, which is: 907# "start stop restart rcvar status poll ${extra_commands}" 908# If there's a match, run ${argument}_cmd or the default method 909# (see below). 910# 911# If argument has a given prefix, then change the operation as follows: 912# Prefix Operation 913# ------ --------- 914# fast Skip the pid check, and set rc_fast=yes, rc_quiet=yes 915# force Set ${rcvar} to YES, and set rc_force=yes 916# one Set ${rcvar} to YES 917# quiet Don't output some diagnostics, and set rc_quiet=yes 918# 919# The following globals are used: 920# 921# Name Needed Purpose 922# ---- ------ ------- 923# name y Name of script. 924# 925# command n Full path to command. 926# Not needed if ${rc_arg}_cmd is set for 927# each keyword. 928# 929# command_args n Optional args/shell directives for command. 930# 931# command_interpreter n If not empty, command is interpreted, so 932# call check_{pidfile,process}() appropriately. 933# 934# desc n Description of script. 935# 936# extra_commands n List of extra commands supported. 937# 938# pidfile n If set, use check_pidfile $pidfile $command, 939# otherwise use check_process $command. 940# In either case, only check if $command is set. 941# 942# procname n Process name to check for instead of $command. 943# 944# rcvar n This is checked with checkyesno to determine 945# if the action should be run. 946# 947# ${name}_program n Full path to command. 948# Meant to be used in /etc/rc.conf to override 949# ${command}. 950# 951# ${name}_chroot n Directory to chroot to before running ${command} 952# Requires /usr to be mounted. 953# 954# ${name}_chdir n Directory to cd to before running ${command} 955# (if not using ${name}_chroot). 956# 957# ${name}_cpuset n A list of CPUs to run ${command} on. 958# Requires /usr to be mounted. 959# 960# ${name}_flags n Arguments to call ${command} with. 961# NOTE: $flags from the parent environment 962# can be used to override this. 963# 964# ${name}_env n Environment variables to run ${command} with. 965# 966# ${name}_env_file n File to source variables to run ${command} with. 967# 968# ${name}_fib n Routing table number to run ${command} with. 969# 970# ${name}_nice n Nice level to run ${command} at. 971# 972# ${name}_oomprotect n Don't kill ${command} when swap space is exhausted. 973# 974# ${name}_umask n The file creation mask to run ${command} with. 975# 976# ${name}_user n User to run ${command} as, using su(1) if not 977# using ${name}_chroot. 978# Requires /usr to be mounted. 979# 980# ${name}_group n Group to run chrooted ${command} as. 981# Requires /usr to be mounted. 982# 983# ${name}_groups n Comma separated list of supplementary groups 984# to run the chrooted ${command} with. 985# Requires /usr to be mounted. 986# 987# ${name}_prepend n Command added before ${command}. 988# 989# ${name}_setup n Command executed during start, restart and 990# reload before ${rc_arg}_precmd is run. 991# 992# ${name}_login_class n Login class to use, else "daemon". 993# 994# ${name}_limits n limits(1) to apply to ${command}. 995# 996# ${name}_offcmd n If set, run during start 997# if a service is not enabled. 998# 999# ${rc_arg}_cmd n If set, use this as the method when invoked; 1000# Otherwise, use default command (see below) 1001# 1002# ${rc_arg}_precmd n If set, run just before performing the 1003# ${rc_arg}_cmd method in the default 1004# operation (i.e, after checking for required 1005# bits and process (non)existence). 1006# If this completes with a non-zero exit code, 1007# don't run ${rc_arg}_cmd. 1008# 1009# ${rc_arg}_postcmd n If set, run just after performing the 1010# ${rc_arg}_cmd method, if that method 1011# returned a zero exit code. 1012# 1013# required_dirs n If set, check for the existence of the given 1014# directories before running a (re)start command. 1015# 1016# required_files n If set, check for the readability of the given 1017# files before running a (re)start command. 1018# 1019# required_modules n If set, ensure the given kernel modules are 1020# loaded before running a (re)start command. 1021# The check and possible loads are actually 1022# done after start_precmd so that the modules 1023# aren't loaded in vain, should the precmd 1024# return a non-zero status to indicate a error. 1025# If a word in the list looks like "foo:bar", 1026# "foo" is the KLD file name and "bar" is the 1027# module name. If a word looks like "foo~bar", 1028# "foo" is the KLD file name and "bar" is a 1029# egrep(1) pattern matching the module name. 1030# Otherwise the module name is assumed to be 1031# the same as the KLD file name, which is most 1032# common. See load_kld(). 1033# 1034# required_vars n If set, perform checkyesno on each of the 1035# listed variables before running the default 1036# (re)start command. 1037# 1038# Default behaviour for a given argument, if no override method is 1039# provided: 1040# 1041# Argument Default behaviour 1042# -------- ----------------- 1043# start if !running && checkyesno ${rcvar} 1044# ${command} 1045# 1046# stop if ${pidfile} 1047# rc_pid=$(check_pidfile $pidfile $command) 1048# else 1049# rc_pid=$(check_process $command) 1050# kill $sig_stop $rc_pid 1051# wait_for_pids $rc_pid 1052# ($sig_stop defaults to TERM.) 1053# 1054# reload Similar to stop, except use $sig_reload instead, 1055# and don't wait_for_pids. 1056# $sig_reload defaults to HUP. 1057# Note that `reload' isn't provided by default, 1058# it should be enabled via $extra_commands. 1059# 1060# restart Run `stop' then `start'. 1061# 1062# status Show if ${command} is running, etc. 1063# 1064# poll Wait for ${command} to exit. 1065# 1066# rcvar Display what rc.conf variable is used (if any). 1067# 1068# enabled Return true if the service is enabled. 1069# 1070# describe Show the service's description 1071# 1072# extracommands Show the service's extra commands 1073# 1074# Variables available to methods, and after run_rc_command() has 1075# completed: 1076# 1077# Variable Purpose 1078# -------- ------- 1079# rc_arg Argument to command, after fast/force/one processing 1080# performed 1081# 1082# rc_flags Flags to start the default command with. 1083# Defaults to ${name}_flags, unless overridden 1084# by $flags from the environment. 1085# This variable may be changed by the precmd method. 1086# 1087# rc_service Path to the service being executed, in case the service 1088# needs to re-invoke itself. 1089# 1090# rc_pid PID of command (if appropriate) 1091# 1092# rc_fast Not empty if "fast" was provided (q.v.) 1093# 1094# rc_force Not empty if "force" was provided (q.v.) 1095# 1096# rc_quiet Not empty if "quiet" was provided 1097# 1098# 1099run_rc_command() 1100{ 1101 _return=0 1102 rc_arg=$1 1103 if [ -z "$name" ]; then 1104 err 3 'run_rc_command: $name is not set.' 1105 fi 1106 1107 DebugOn rc:all rc:all:$rc_arg rc:$name rc:$name:$rc_arg $name:$rc_arg 1108 1109 # Don't repeat the first argument when passing additional command- 1110 # line arguments to the command subroutines. 1111 # 1112 shift 1 1113 rc_extra_args="$*" 1114 1115 _rc_prefix= 1116 case "$rc_arg" in 1117 fast*) # "fast" prefix; don't check pid 1118 rc_arg=${rc_arg#fast} 1119 rc_fast=yes 1120 rc_quiet=yes 1121 ;; 1122 force*) # "force" prefix; always run 1123 rc_force=yes 1124 _rc_prefix=force 1125 rc_arg=${rc_arg#${_rc_prefix}} 1126 if [ -n "${rcvar}" ]; then 1127 eval ${rcvar}=YES 1128 fi 1129 ;; 1130 one*) # "one" prefix; set ${rcvar}=yes 1131 _rc_prefix=one 1132 rc_arg=${rc_arg#${_rc_prefix}} 1133 if [ -n "${rcvar}" ]; then 1134 eval ${rcvar}=YES 1135 fi 1136 ;; 1137 quiet*) # "quiet" prefix; omit some messages 1138 _rc_prefix=quiet 1139 rc_arg=${rc_arg#${_rc_prefix}} 1140 rc_quiet=yes 1141 ;; 1142 esac 1143 1144 eval _override_command=\$${name}_program 1145 command=${_override_command:-$command} 1146 1147 _keywords="start stop restart rcvar enable disable delete enabled describe extracommands $extra_commands" 1148 rc_pid= 1149 _pidcmd= 1150 _procname=${procname:-${command}} 1151 1152 eval _cpuset=\$${name}_cpuset 1153 1154 # Loose validation of the configured cpuset; just make sure it starts 1155 # with a number. There have also been cases in the past where a hyphen 1156 # in a service name has caused eval errors, which trickle down into 1157 # various variables; don't let a situation like that break a bunch of 1158 # services just because of cpuset(1). 1159 case "$_cpuset" in 1160 [0-9]*) ;; 1161 *) _cpuset="" ;; 1162 esac 1163 1164 _cpusetcmd= 1165 if [ -n "$_cpuset" ]; then 1166 _cpusetcmd="$CPUSET -l $_cpuset" 1167 fi 1168 1169 # If a specific jail has a specific svcj request, honor it (YES/NO). 1170 # If not (variable empty), evaluate the global svcj catch-all. 1171 # A global YES can be overriden by a specific NO, and a global NO is overriden 1172 # by a specific YES. 1173 eval _svcj=\$${name}_svcj 1174 if [ -z "$_svcj" ]; then 1175 _svcj=${svcj_all_enable} 1176 if [ -z "$_svcj" ]; then 1177 eval ${name}_svcj=NO 1178 fi 1179 fi 1180 1181 # setup pid check command 1182 if [ -n "$_procname" ]; then 1183 if [ -n "$pidfile" ]; then 1184 _pidcmd='rc_pid=$(check_pidfile '"$pidfile $_procname $command_interpreter"')' 1185 else 1186 _pidcmd='rc_pid=$(check_process '"$_procname $command_interpreter"')' 1187 fi 1188 _keywords="${_keywords} status poll" 1189 else 1190 if [ ! -z "${status_cmd}" ] 1191 then 1192 _keywords="${_keywords} status" 1193 fi 1194 fi 1195 1196 if [ -z "$rc_arg" ]; then 1197 rc_usage $_keywords 1198 fi 1199 1200 if [ "$rc_arg" = "enabled" ] ; then 1201 checkyesno ${rcvar} 1202 return $? 1203 fi 1204 1205 if [ -n "$flags" ]; then # allow override from environment 1206 rc_flags=$flags 1207 else 1208 eval rc_flags=\$${name}_flags 1209 fi 1210 eval _chdir=\$${name}_chdir _chroot=\$${name}_chroot \ 1211 _nice=\$${name}_nice _user=\$${name}_user \ 1212 _group=\$${name}_group _groups=\$${name}_groups \ 1213 _fib=\$${name}_fib _env=\$${name}_env \ 1214 _prepend=\$${name}_prepend _login_class=\${${name}_login_class:-daemon} \ 1215 _limits=\$${name}_limits _oomprotect=\$${name}_oomprotect \ 1216 _setup=\$${name}_setup _env_file=\$${name}_env_file \ 1217 _umask=\$${name}_umask _svcj_options=\$${name}_svcj_options \ 1218 _svcj_ipaddrs=\$${name}_svcj_ipaddrs 1219 1220 if [ -n "$_env_file" ] && [ -r "${_env_file}" ]; then # load env from file 1221 set -a 1222 . $_env_file 1223 set +a 1224 fi 1225 1226 if [ -n "$_user" ]; then # unset $_user if running as that user 1227 if [ "$_user" = "$(eval $IDCMD)" ]; then 1228 unset _user 1229 fi 1230 fi 1231 1232 _svcj_ip4_addrs="" 1233 _svcj_ip6_addrs="" 1234 _svcj_cmd_options="" 1235 1236 if [ -n "$_svcj_ipaddrs" ]; then 1237 _svcj_ip="new" 1238 1239 for addr in $_svcj_ipaddrs; do 1240 case $addr in 1241 *:*) _svcj_ip6_addrs="$addr,${_svcj_ip6_addrs}" ;; 1242 *) _svcj_ip4_addrs="$addr,${_svcj_ip4_addrs}" ;; 1243 esac 1244 done 1245 else 1246 _svcj_ip="inherit" 1247 fi 1248 1249 if check_kern_features inet; then 1250 _svcj_ip4="ip4=${_svcj_ip}" 1251 if [ -n "$_svcj_ip4_addrs" ]; then 1252 _svcj_cmd_options="ip4.addr=${_svcj_ip4_addrs%*,} ${_svcj_cmd_options}" 1253 fi 1254 else 1255 if [ -n "$_svcj_ip4_addrs" ]; then 1256 warn "$rc_service: ${name}_svcj_ipaddrs contains at least one IPv4 address, but IPv4 is not enabled in the kernel; IPv4 addresses will be ignored." 1257 fi 1258 fi 1259 1260 if check_kern_features inet6; then 1261 _svcj_ip6="ip6=${_svcj_ip}" 1262 if [ -n "$_svcj_ip6_addrs" ]; then 1263 _svcj_cmd_options="ip6.addr=${_svcj_ip6_addrs%*,} ${_svcj_cmd_options}" 1264 fi 1265 else 1266 if [ -n "$_svcj_ip6_addrs" ]; then 1267 warn "$rc_service: ${name}_svcj_ipaddrs contains at least one IPv6 address, but IPv6 is not enabled in the kernel; IPv6 addresses will be ignored." 1268 fi 1269 fi 1270 1271 if [ -n "$_svcj_options" ]; then # translate service jail options 1272 _svcj_sysvipc_x=0 1273 for _svcj_option in $_svcj_options; do 1274 case "$_svcj_option" in 1275 mlock) 1276 _svcj_cmd_options="allow.mlock ${_svcj_cmd_options}" 1277 ;; 1278 netv4) 1279 _svcj_cmd_options="${_svcj_ip4} allow.reserved_ports ${_svcj_cmd_options}" 1280 ;; 1281 netv6) 1282 _svcj_cmd_options="${_svcj_ip6} allow.reserved_ports ${_svcj_cmd_options}" 1283 ;; 1284 net_basic) 1285 _svcj_cmd_options="${_svcj_ip4} ${_svcj_ip6} allow.reserved_ports ${_svcj_cmd_options}" 1286 ;; 1287 net_raw) 1288 _svcj_cmd_options="allow.raw_sockets ${_svcj_cmd_options}" 1289 ;; 1290 net_all) 1291 _svcj_cmd_options="allow.socket_af allow.raw_sockets allow.reserved_ports ${_svcj_ip4} ${_svcj_ip6} ${_svcj_cmd_options}" 1292 ;; 1293 nfsd) 1294 _svcj_cmd_options="allow.nfsd enforce_statfs=1 ${_svcj_cmd_options}" 1295 ;; 1296 routing) 1297 _svcj_cmd_options="allow.routing ${_svcj_cmd_options}" 1298 ;; 1299 settime) 1300 _svcj_cmd_options="allow.settime ${_svcj_cmd_options}" 1301 ;; 1302 sysvipc) 1303 _svcj_sysvipc_x=$((${_svcj_sysvipc_x} + 1)) 1304 _svcj_cmd_options="sysvmsg=inherit sysvsem=inherit sysvshm=inherit ${_svcj_cmd_options}" 1305 ;; 1306 sysvipcnew) 1307 _svcj_sysvipc_x=$((${_svcj_sysvipc_x} + 1)) 1308 _svcj_cmd_options="sysvmsg=new sysvsem=new sysvshm=new ${_svcj_cmd_options}" 1309 ;; 1310 vmm) 1311 _svcj_cmd_options="allow.vmm ${_svcj_cmd_options}" 1312 ;; 1313 *) 1314 echo ${name}: unknown service jail option: $_svcj_option 1315 ;; 1316 esac 1317 done 1318 if [ ${_svcj_sysvipc_x} -gt 1 ]; then 1319 echo -n "ERROR: more than one sysvipc option is " 1320 echo "specified in ${name}_svcj_options: $_svcj_options" 1321 return 1 1322 fi 1323 fi 1324 1325 [ -z "$autoboot" ] && eval $_pidcmd # determine the pid if necessary 1326 1327 for _elem in $_keywords; do 1328 if [ "$_elem" != "$rc_arg" ]; then 1329 continue 1330 fi 1331 # if ${rcvar} is set, $1 is not "rcvar", "describe", 1332 # "enable", "delete" or "status", and ${rc_pid} is 1333 # not set, run: 1334 # checkyesno ${rcvar} 1335 # and return if that failed 1336 # 1337 if [ -n "${rcvar}" -a "$rc_arg" != "rcvar" -a "$rc_arg" != "stop" \ 1338 -a "$rc_arg" != "delete" -a "$rc_arg" != "enable" \ 1339 -a "$rc_arg" != "describe" -a "$rc_arg" != "status" ] || 1340 [ -n "${rcvar}" -a "$rc_arg" = "stop" -a -z "${rc_pid}" ]; then 1341 if ! checkyesno ${rcvar}; then 1342 [ "$rc_arg" = "start" ] && _run_rc_offcmd 1343 if [ -z "${rc_quiet}" ]; then 1344 echo -n "Cannot '${rc_arg}' $name. Set ${rcvar} to " 1345 echo -n "YES in /etc/rc.conf or use 'one${rc_arg}' " 1346 echo "instead of '${rc_arg}'." 1347 fi 1348 return 0 1349 fi 1350 fi 1351 1352 if [ $rc_arg = "start" -a -z "$rc_fast" -a -n "$rc_pid" ]; then 1353 if [ -z "$rc_quiet" ]; then 1354 echo 1>&2 "${name} already running? " \ 1355 "(pid=$rc_pid)." 1356 fi 1357 return 1 1358 fi 1359 1360 # if there's a custom ${XXX_cmd}, 1361 # run that instead of the default 1362 # 1363 eval _cmd=\$${rc_arg}_cmd \ 1364 _precmd=\$${rc_arg}_precmd \ 1365 _postcmd=\$${rc_arg}_postcmd 1366 1367 if [ -n "$_cmd" ]; then 1368 if [ "$_cmd" != : ]; then 1369 rc_trace 1 "$_cmd" 1370 fi 1371 if [ -n "$_env" ]; then 1372 eval "export -- $_env" 1373 fi 1374 1375 if [ "${_rc_svcj}" != jailing ]; then 1376 # service can redefine all so 1377 # check for valid setup target 1378 if [ "$rc_arg" = 'start' -o \ 1379 "$rc_arg" = 'restart' -o \ 1380 "$rc_arg" = 'reload' ]; then 1381 _run_rc_setup || \ 1382 warn "failed to setup ${name}" 1383 fi 1384 _run_rc_precmd || return 1 1385 fi 1386 if ! checkyesno ${name}_svcj; then 1387 _run_rc_doit "$_cpusetcmd $_cmd $rc_extra_args" || return 1 1388 else 1389 case "$rc_arg" in 1390 start) 1391 if [ "${_rc_svcj}" != jailing ]; then 1392 _return=1 1393 _do_jailing=1 1394 1395 if check_jail jailed; then 1396 if [ $(${SYSCTL_N} security.jail.children.max) -eq 0 ]; then 1397 echo ERROR: jail parameter children.max is set to 0, can not create a new service jail. 1398 _do_jailing=0 1399 else 1400 _free_jails=$(($(${SYSCTL_N} security.jail.children.max) - $(${SYSCTL_N} security.jail.children.cur))) 1401 if [ ${_free_jails} -eq 0 ]; then 1402 echo ERROR: max number of jail children reached, can not create a new service jail. 1403 _do_jailing=0 1404 1405 fi 1406 fi 1407 fi 1408 if [ ${_do_jailing} -eq 1 ]; then 1409 $JAIL_CMD -c $_svcj_generic_params $_svcj_cmd_options \ 1410 exec.start="${SERVICE} -E _rc_svcj=jailing ${name} ${_rc_prefix}start $rc_extra_args" \ 1411 exec.stop="${SERVICE} -E _rc_svcj=jailing ${name} ${_rc_prefix}stop $rc_extra_args" \ 1412 exec.consolelog="/var/log/svcj_${name}_console.log" \ 1413 name=svcj-${name} && _return=0 1414 fi 1415 else 1416 _run_rc_doit "$_cpusetcmd $_cmd $rc_extra_args" || _return=1 1417 fi 1418 ;; 1419 stop) 1420 if [ "${_rc_svcj}" != jailing ]; then 1421 $SERVICE -E _rc_svcj=jailing -j svcj-${name} ${name} ${_rc_prefix}stop $rc_extra_args || _return=1 1422 $JAIL_CMD -r svcj-${name} 2>/dev/null 1423 else 1424 _run_rc_doit "$_cpusetcmd $_cmd $rc_extra_args" || _return=1 1425 fi 1426 ;; 1427 restart|status) ;; # no special case needed for svcj or handled somewhere else 1428 *) 1429 eval _rc_svcj_extra_cmd=\$${name}_${rc_arg}_svcj_enable 1430 : ${_rc_svcj_extra_cmd:=NO} 1431 if checkyesno _rc_svcj_extra_cmd && [ "${_rc_svcj}" != jailing ]; then 1432 $SERVICE -v -E _rc_svcj=jailing -j svcj-${name} ${name} ${_rc_prefix}${rc_arg} $rc_extra_args || _return=1 1433 else 1434 _run_rc_doit "$_cpusetcmd $_cmd $rc_extra_args" || _return=1 1435 fi 1436 ;; 1437 esac 1438 fi 1439 if [ "${_rc_svcj}" != jailing ]; then 1440 _run_rc_postcmd 1441 fi 1442 return $_return 1443 fi 1444 1445 case "$rc_arg" in # default operations... 1446 1447 describe) 1448 if [ -n "$desc" ]; then 1449 echo "$desc" 1450 fi 1451 ;; 1452 1453 extracommands) 1454 echo "$extra_commands" 1455 ;; 1456 1457 enable) 1458 _out=$(write_rcvar "$rcvar" "YES") && 1459 echo "$name enabled in $_out" 1460 ;; 1461 1462 disable) 1463 _out=$(write_rcvar "$rcvar" "NO") && 1464 echo "$name disabled in $_out" 1465 ;; 1466 1467 delete) 1468 delete_rcvar "$rcvar" 1469 ;; 1470 1471 status) 1472 _run_rc_precmd || return 1 1473 if [ -n "$rc_pid" ]; then 1474 echo "${name} is running as pid $rc_pid." 1475 else 1476 echo "${name} is not running." 1477 return 1 1478 fi 1479 _run_rc_postcmd 1480 ;; 1481 1482 start) 1483 if [ ! -x "${_chroot}${_chroot:+/}${command}" ]; then 1484 warn "run_rc_command: cannot run $command" 1485 return 1 1486 fi 1487 1488 if [ "${_rc_svcj}" != jailing ]; then 1489 _run_rc_setup || warn "failed to setup ${name}" 1490 1491 if ! _run_rc_precmd; then 1492 warn "failed precmd routine for ${name}" 1493 return 1 1494 fi 1495 fi 1496 1497 if checkyesno ${name}_svcj; then 1498 if [ "${_rc_svcj}" != jailing ]; then 1499 if check_jail jailed; then 1500 if [ $(${SYSCTL_N} security.jail.children.max) -eq 0 ]; then 1501 echo ERROR: jail parameter children.max is set to 0, can not create a new service jail. 1502 return 1 1503 else 1504 _free_jails=$(($(${SYSCTL_N} security.jail.children.max) - $(${SYSCTL_N} security.jail.children.cur))) 1505 if [ ${_free_jails} -eq 0 ]; then 1506 echo ERROR: max number of jail children reached, can not create a new service jail. 1507 return 1 1508 fi 1509 fi 1510 fi 1511 $JAIL_CMD -c $_svcj_generic_params $_svcj_cmd_options\ 1512 exec.start="${SERVICE} -E _rc_svcj=jailing ${name} ${_rc_prefix}start $rc_extra_args" \ 1513 exec.stop="${SERVICE} -E _rc_svcj=jailing ${name} ${_rc_prefix}stop $rc_extra_args" \ 1514 exec.consolelog="/var/log/svcj_${name}_console.log" \ 1515 name=svcj-${name} || return 1 1516 fi 1517 fi 1518 1519 # setup the full command to run 1520 # 1521 startmsg "Starting ${name}." 1522 if [ -n "$_chroot" ]; then 1523 _cd= 1524 _doit="\ 1525${_nice:+nice -n $_nice }\ 1526$_cpusetcmd \ 1527${_fib:+setfib -F $_fib }\ 1528${_env:+env $_env }\ 1529chroot ${_user:+-u $_user }${_group:+-g $_group }${_groups:+-G $_groups }\ 1530$_chroot $command $rc_flags $command_args" 1531 else 1532 _cd="${_chdir:+cd $_chdir && }" 1533 _doit="\ 1534${_fib:+setfib -F $_fib }\ 1535${_env:+env $_env }\ 1536$_cpusetcmd $command $rc_flags $command_args" 1537 if [ -n "$_user" ]; then 1538 _doit="su -m $_user -c 'sh -c \"$_doit\"'" 1539 fi 1540 if [ -n "$_nice" ]; then 1541 if [ -z "$_user" ]; then 1542 _doit="sh -c \"$_doit\"" 1543 fi 1544 _doit="nice -n $_nice $_doit" 1545 fi 1546 if [ -n "$_prepend" ]; then 1547 _doit="$_prepend $_doit" 1548 fi 1549 fi 1550 1551 # Prepend default limits 1552 _doit="$_cd limits -C $_login_class $_limits $_doit" 1553 1554 local _really_run_it=true 1555 if checkyesno ${name}_svcj; then 1556 if [ "${_rc_svcj}" != jailing ]; then 1557 _really_run_it=false 1558 fi 1559 fi 1560 1561 if [ "$_really_run_it" = true ]; then 1562 # run the full command 1563 # 1564 if ! _run_rc_doit "$_doit"; then 1565 warn "failed to start ${name}" 1566 return 1 1567 fi 1568 fi 1569 1570 if [ "${_rc_svcj}" != jailing ]; then 1571 # finally, run postcmd 1572 # 1573 _run_rc_postcmd 1574 fi 1575 ;; 1576 1577 stop) 1578 if [ -z "$rc_pid" ]; then 1579 [ -n "$rc_fast" ] && return 0 1580 _run_rc_notrunning 1581 return 1 1582 fi 1583 1584 _run_rc_precmd || return 1 1585 1586 # send the signal to stop 1587 # 1588 echo "Stopping ${name}." 1589 _doit=$(_run_rc_killcmd "${sig_stop:-TERM}") 1590 _run_rc_doit "$_doit" || return 1 1591 1592 # wait for the command to exit, 1593 # and run postcmd. 1594 wait_for_pids $rc_pid 1595 1596 if checkyesno ${name}_svcj; then 1597 # remove service jail 1598 $JAIL_CMD -r svcj-${name} 2>/dev/null 1599 fi 1600 1601 _run_rc_postcmd 1602 ;; 1603 1604 reload) 1605 if [ -z "$rc_pid" ]; then 1606 _run_rc_notrunning 1607 return 1 1608 fi 1609 1610 _run_rc_setup || warn "failed to setup ${name}" 1611 1612 _run_rc_precmd || return 1 1613 1614 _doit=$(_run_rc_killcmd "${sig_reload:-HUP}") 1615 _run_rc_doit "$_doit" || return 1 1616 1617 _run_rc_postcmd 1618 ;; 1619 1620 restart) 1621 _run_rc_setup || warn "failed to setup ${name}" 1622 1623 # prevent restart being called more 1624 # than once by any given script 1625 # 1626 if ${_rc_restart_done:-false}; then 1627 return 0 1628 fi 1629 _rc_restart_done=true 1630 1631 _run_rc_precmd || return 1 1632 1633 # run those in a subshell to keep global variables 1634 ( run_rc_command ${_rc_prefix}stop $rc_extra_args ) 1635 ( run_rc_command ${_rc_prefix}start $rc_extra_args ) 1636 _return=$? 1637 [ $_return -ne 0 ] && [ -z "$rc_force" ] && return 1 1638 1639 _run_rc_postcmd 1640 ;; 1641 1642 poll) 1643 _run_rc_precmd || return 1 1644 if [ -n "$rc_pid" ]; then 1645 wait_for_pids $rc_pid 1646 fi 1647 _run_rc_postcmd 1648 ;; 1649 1650 rcvar) 1651 echo -n "# $name" 1652 if [ -n "$desc" ]; then 1653 echo " : $desc" 1654 else 1655 echo "" 1656 fi 1657 echo "#" 1658 # Get unique vars in $rcvar $rcvars 1659 for _v in $rcvar $rcvars; do 1660 case $v in 1661 $_v\ *|\ *$_v|*\ $_v\ *) ;; 1662 *) v="${v# } $_v" ;; 1663 esac 1664 done 1665 1666 # Display variables. 1667 for _v in $v; do 1668 if [ -z "$_v" ]; then 1669 continue 1670 fi 1671 1672 eval _desc=\$${_v}_desc 1673 eval _defval=\$${_v}_defval 1674 _h="-" 1675 1676 eval echo \"$_v=\\\"\$$_v\\\"\" 1677 # decode multiple lines of _desc 1678 while [ -n "$_desc" ]; do 1679 case $_desc in 1680 *^^*) 1681 echo "# $_h ${_desc%%^^*}" 1682 _desc=${_desc#*^^} 1683 _h=" " 1684 ;; 1685 *) 1686 echo "# $_h ${_desc}" 1687 break 1688 ;; 1689 esac 1690 done 1691 echo "# (default: \"$_defval\")" 1692 done 1693 echo "" 1694 ;; 1695 1696 *) 1697 rc_usage $_keywords 1698 ;; 1699 1700 esac 1701 1702 # Apply protect(1) to the PID if ${name}_oomprotect is set. 1703 case "$rc_arg" in 1704 start) 1705 # We cannot use protect(1) inside jails. 1706 if [ -n "$_oomprotect" ] && [ -f "${PROTECT}" ] && 1707 [ "$(sysctl -n security.jail.jailed)" -eq 0 ]; then 1708 [ -z "${rc_pid}" ] && eval $_pidcmd 1709 case $_oomprotect in 1710 [Aa][Ll][Ll]) 1711 ${PROTECT} -d -i -p ${rc_pid} 1712 ;; 1713 [Yy][Ee][Ss]) 1714 ${PROTECT} -p ${rc_pid} 1715 ;; 1716 esac 1717 fi 1718 ;; 1719 esac 1720 1721 return $_return 1722 done 1723 1724 echo 1>&2 "$0: unknown directive '$rc_arg'." 1725 rc_usage $_keywords 1726 # not reached 1727} 1728 1729# 1730# Helper functions for run_rc_command: common code. 1731# They use such global variables besides the exported rc_* ones: 1732# 1733# name R/W 1734# ------------------ 1735# _offcmd R 1736# _precmd R 1737# _postcmd R 1738# _return W 1739# _setup R 1740# 1741_run_rc_offcmd() 1742{ 1743 eval _offcmd=\$${name}_offcmd 1744 if [ -n "$_offcmd" ]; then 1745 if [ -n "$_env" ]; then 1746 eval "export -- $_env" 1747 fi 1748 debug "run_rc_command: ${name}_offcmd: $_offcmd $rc_extra_args" 1749 eval "$_offcmd $rc_extra_args" 1750 _return=$? 1751 fi 1752 return 0 1753} 1754 1755_run_rc_precmd() 1756{ 1757 check_required_before "$rc_arg" || return 1 1758 1759 if [ -n "$_precmd" ]; then 1760 debug "run_rc_command: ${rc_arg}_precmd: $_precmd $rc_extra_args" 1761 eval "$_precmd $rc_extra_args" 1762 _return=$? 1763 1764 # If precmd failed and force isn't set, request exit. 1765 if [ $_return -ne 0 ] && [ -z "$rc_force" ]; then 1766 return 1 1767 fi 1768 fi 1769 1770 check_required_after "$rc_arg" || return 1 1771 1772 return 0 1773} 1774 1775_run_rc_postcmd() 1776{ 1777 if [ -n "$_postcmd" ]; then 1778 debug "run_rc_command: ${rc_arg}_postcmd: $_postcmd $rc_extra_args" 1779 eval "$_postcmd $rc_extra_args" 1780 _return=$? 1781 fi 1782 return 0 1783} 1784 1785_run_rc_setup() 1786{ 1787 # prevent multiple execution on restart => stop/start split 1788 if ! ${_rc_restart_done:-false} && [ -n "$_setup" ]; then 1789 debug "run_rc_command: ${rc_arg}_setup: $_setup" 1790 eval "$_setup" 1791 _return=$? 1792 if [ $_return -ne 0 ]; then 1793 return 1 1794 fi 1795 fi 1796 return 0 1797} 1798 1799_run_rc_doit() 1800{ 1801 local _m _s 1802 1803 debug "run_rc_command: doit: $*" 1804 _m=$(umask) 1805 ${_umask:+umask ${_umask}} 1806 1807 # Disable pathname expansion temporarily for run_rc_command. 1808 _s=$(set +o) 1809 set -o noglob 1810 eval "$@" 1811 _return=$? 1812 umask ${_m} 1813 eval $_s 1814 1815 # If command failed and force isn't set, request exit. 1816 if [ $_return -ne 0 ] && [ -z "$rc_force" ]; then 1817 return 1 1818 fi 1819 1820 return 0 1821} 1822 1823_run_rc_notrunning() 1824{ 1825 local _pidmsg 1826 1827 if [ -n "$pidfile" ]; then 1828 _pidmsg=" (check $pidfile)." 1829 else 1830 _pidmsg= 1831 fi 1832 echo 1>&2 "${name} not running?${_pidmsg}" 1833} 1834 1835_run_rc_killcmd() 1836{ 1837 local _cmd 1838 1839 _cmd="kill -$1 $rc_pid" 1840 if [ -n "$_user" ]; then 1841 _cmd="su -m ${_user} -c 'sh -c \"${_cmd}\"'" 1842 fi 1843 echo "$_cmd" 1844} 1845 1846# 1847# run_rc_script file arg 1848# Start the script `file' with `arg', and correctly handle the 1849# return value from the script. 1850# If `file' ends with `.sh' and lives in /etc/rc.d, ignore it as it's 1851# an old-style startup file. 1852# If `file' appears to be a backup or scratch file, ignore it. 1853# Otherwise if it is executable run as a child process. 1854# 1855run_rc_script() 1856{ 1857 _file=$1 1858 _arg=$2 1859 if [ -z "$_file" -o -z "$_arg" ]; then 1860 err 3 'USAGE: run_rc_script file arg' 1861 fi 1862 1863 unset name command command_args command_interpreter \ 1864 extra_commands pidfile procname \ 1865 rcvar rcvars rcvars_obsolete required_dirs required_files \ 1866 required_vars 1867 eval unset ${_arg}_cmd ${_arg}_precmd ${_arg}_postcmd 1868 1869 rc_trace 0 "$_file $_arg" 1870 # don't use it if we don't trust it 1871 is_verified $_file || return 1872 1873 rc_service="$_file" 1874 case "$_file" in 1875 /etc/rc.d/*.sh) # no longer allowed in the base 1876 warn "Ignoring old-style startup script $_file" 1877 ;; 1878 *[~#]|*.OLD|*.bak|*.orig|*,v) # scratch file; skip 1879 warn "Ignoring scratch file $_file" 1880 ;; 1881 *) # run in subshell 1882 if [ -x $_file ]; then 1883 DebugOn $_file $_file:$_arg rc:${_file##*/} rc:${_file##*/}:$_arg ${_file##*/} ${_file##*/}:$_arg 1884 1885 if [ -n "$rc_boottrace" ]; then 1886 boottrace_fn "$_file" "$_arg" 1887 else 1888 ( trap "echo Script $_file interrupted >&2 ; kill -QUIT $$" 3 1889 trap "echo Script $_file interrupted >&2 ; exit 1" 2 1890 trap "echo Script $_file running >&2" 29 1891 set $_arg; . $_file ) 1892 fi 1893 DebugOff rc=$? $_file $_file:$_arg rc:${_file##*/} rc:${_file##*/}:$_arg ${_file##*/} ${_file##*/}:$_arg 1894 fi 1895 ;; 1896 esac 1897} 1898 1899# 1900# run_rc_scripts [options] file [...] 1901# 1902# Call `run_rc_script' for each "file" unless already listed in 1903# $_rc_elem_done. 1904# 1905# Options: 1906# 1907# --arg "arg" 1908# Pass "arg" to `run_rc_script' default is $_boot. 1909# 1910# --break "marker" 1911# If any "file" matches "marker" stop processing. 1912# 1913_rc_elem_done= 1914run_rc_scripts() 1915{ 1916 local _arg=${_boot} 1917 local _rc_elem 1918 local _rc_breaks= 1919 1920 while :; do 1921 case "$1" in 1922 --arg) 1923 _arg="$2" 1924 shift 2 1925 ;; 1926 --break) 1927 _rc_breaks="$_rc_breaks $2" 1928 shift 2 1929 ;; 1930 *) 1931 break 1932 ;; 1933 esac 1934 done 1935 for _rc_elem in "$@"; do 1936 : _rc_elem=$_rc_elem 1937 case " $_rc_elem_done " in 1938 *" $_rc_elem "*) 1939 continue 1940 ;; 1941 esac 1942 run_rc_script ${_rc_elem} ${_arg} 1943 _rc_elem_done="$_rc_elem_done $_rc_elem" 1944 case " $_rc_breaks " in 1945 *" ${_rc_elem##*/} "*) 1946 break 1947 ;; 1948 esac 1949 done 1950} 1951 1952boottrace_fn() 1953{ 1954 local _file _arg 1955 _file=$1 1956 _arg=$2 1957 1958 _boot="${_boot}" rc_fast="${rc_fast}" autoboot="${autoboot}" \ 1959 $boottrace_cmd "$_file" "$_arg" 1960} 1961 1962# 1963# load_rc_config [service] 1964# Source in the configuration file(s) for a given service. 1965# If no service is specified, only the global configuration 1966# file(s) will be loaded. 1967# 1968load_rc_config() 1969{ 1970 local _name _rcvar_val _var _defval _v _msg _new _d _dot 1971 _name=$1 1972 _dot=${load_rc_config_reader:-dot} 1973 1974 case "$_dot" in 1975 dot|[sv]dot) 1976 ;; 1977 *) warn "Ignoring invalid load_rc_config_reader" 1978 _dot=dot 1979 ;; 1980 esac 1981 case "$1" in 1982 -s|--safe) 1983 _dot=sdot 1984 _name=$2 1985 shift 1986 ;; 1987 -v|--verify) 1988 _dot=vdot 1989 _name=$2 1990 shift 1991 ;; 1992 esac 1993 1994 DebugOn rc:$_name $_name 1995 1996 if ${_rc_conf_loaded:-false}; then 1997 : 1998 else 1999 if [ -r /etc/defaults/rc.conf ]; then 2000 debug "Sourcing /etc/defaults/rc.conf" 2001 $_dot /etc/defaults/rc.conf 2002 source_rc_confs 2003 elif [ -r /etc/rc.conf ]; then 2004 debug "Sourcing /etc/rc.conf (/etc/defaults/rc.conf doesn't exist)." 2005 $_dot /etc/rc.conf 2006 fi 2007 _rc_conf_loaded=true 2008 fi 2009 2010 # If a service name was specified, attempt to load 2011 # service-specific configuration 2012 if [ -n "$_name" ] ; then 2013 _loaded_services="${_loaded_services} ${_name}" 2014 for _d in /etc ${local_startup}; do 2015 _d=${_d%/rc.d} 2016 if [ -f ${_d}/rc.conf.d/"$_name" ]; then 2017 debug "Sourcing ${_d}/rc.conf.d/$_name" 2018 $_dot ${_d}/rc.conf.d/"$_name" 2019 elif [ -d ${_d}/rc.conf.d/"$_name" ] ; then 2020 local _rc 2021 for _rc in ${_d}/rc.conf.d/"$_name"/* ; do 2022 if [ -f "$_rc" ] ; then 2023 debug "Sourcing $_rc" 2024 $_dot "$_rc" 2025 fi 2026 done 2027 fi 2028 done 2029 fi 2030 2031 # Set defaults if defined. 2032 for _var in $rcvar $rcvars; do 2033 eval _defval=\$${_var}_defval 2034 if [ -n "$_defval" ]; then 2035 eval : \${$_var:=\$${_var}_defval} 2036 fi 2037 done 2038 2039 # check obsolete rc.conf variables 2040 for _var in $rcvars_obsolete; do 2041 eval _v=\$$_var 2042 eval _msg=\$${_var}_obsolete_msg 2043 eval _new=\$${_var}_newvar 2044 case $_v in 2045 "") 2046 ;; 2047 *) 2048 if [ -z "$_new" ]; then 2049 _msg="Ignored." 2050 else 2051 eval $_new=\"\$$_var\" 2052 if [ -z "$_msg" ]; then 2053 _msg="Use \$$_new instead." 2054 fi 2055 fi 2056 warn "\$$_var is obsolete. $_msg" 2057 ;; 2058 esac 2059 done 2060} 2061 2062# 2063# load_rc_config_var name var 2064# Read the rc.conf(5) var for name and set in the 2065# current shell, using load_rc_config in a subshell to prevent 2066# unwanted side effects from other variable assignments. 2067# 2068load_rc_config_var() 2069{ 2070 if [ $# -ne 2 ]; then 2071 err 3 'USAGE: load_rc_config_var name var' 2072 fi 2073 eval $(eval '( 2074 load_rc_config '$1' >/dev/null; 2075 if [ -n "${'$2'}" -o "${'$2'-UNSET}" != "UNSET" ]; then 2076 echo '$2'=\'\''${'$2'}\'\''; 2077 fi 2078 )' ) 2079} 2080 2081# 2082# rc_usage commands 2083# Print a usage string for $0, with `commands' being a list of 2084# valid commands. 2085# 2086rc_usage() 2087{ 2088 echo -n 1>&2 "Usage: $0 [fast|force|one|quiet](" 2089 2090 _sep= 2091 for _elem; do 2092 echo -n 1>&2 "$_sep$_elem" 2093 _sep="|" 2094 done 2095 echo 1>&2 ")" 2096 exit 1 2097} 2098 2099# 2100# err exitval message 2101# Display message to stderr and log to the syslog, and exit with exitval. 2102# 2103err() 2104{ 2105 exitval=$1 2106 shift 2107 2108 if [ -x /usr/bin/logger ]; then 2109 logger "$0: ERROR: $*" 2110 fi 2111 echo 1>&2 "$0: ERROR: $*" 2112 exit $exitval 2113} 2114 2115# 2116# warn message 2117# Display message to stderr and log to the syslog. 2118# 2119warn() 2120{ 2121 if [ -x /usr/bin/logger ]; then 2122 logger "$0: WARNING: $*" 2123 fi 2124 echo 1>&2 "$0: WARNING: $*" 2125} 2126 2127# 2128# info message 2129# Display informational message to stdout and log to syslog. 2130# 2131info() 2132{ 2133 case ${rc_info} in 2134 [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1) 2135 if [ -x /usr/bin/logger ]; then 2136 logger "$0: INFO: $*" 2137 fi 2138 echo "$0: INFO: $*" 2139 ;; 2140 esac 2141} 2142 2143# 2144# debug message 2145# If debugging is enabled in rc.conf output message to stderr. 2146# BEWARE that you don't call any subroutine that itself calls this 2147# function. 2148# 2149debug() 2150{ 2151 case ${rc_debug} in 2152 [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1) 2153 if [ -x /usr/bin/logger ]; then 2154 logger "$0: DEBUG: $*" 2155 fi 2156 echo 1>&2 "$0: DEBUG: $*" 2157 ;; 2158 esac 2159} 2160 2161# 2162# backup_file action file cur backup 2163# Make a backup copy of `file' into `cur', and save the previous 2164# version of `cur' as `backup'. 2165# 2166# The `action' keyword can be one of the following: 2167# 2168# add `file' is now being backed up (and is possibly 2169# being reentered into the backups system). `cur' 2170# is created. 2171# 2172# update `file' has changed and needs to be backed up. 2173# If `cur' exists, it is copied to `back' 2174# and then `file' is copied to `cur'. 2175# 2176# remove `file' is no longer being tracked by the backups 2177# system. `cur' is moved `back'. 2178# 2179# 2180backup_file() 2181{ 2182 _action=$1 2183 _file=$2 2184 _cur=$3 2185 _back=$4 2186 2187 case $_action in 2188 add|update) 2189 if [ -f $_cur ]; then 2190 cp -p $_cur $_back 2191 fi 2192 cp -p $_file $_cur 2193 chown root:wheel $_cur 2194 ;; 2195 remove) 2196 mv -f $_cur $_back 2197 ;; 2198 esac 2199} 2200 2201# make_symlink src link 2202# Make a symbolic link 'link' to src from basedir. If the 2203# directory in which link is to be created does not exist 2204# a warning will be displayed and an error will be returned. 2205# Returns 0 on success, 1 otherwise. 2206# 2207make_symlink() 2208{ 2209 local src link linkdir _me 2210 src="$1" 2211 link="$2" 2212 linkdir="`dirname $link`" 2213 _me="make_symlink()" 2214 2215 if [ -z "$src" -o -z "$link" ]; then 2216 warn "$_me: requires two arguments." 2217 return 1 2218 fi 2219 if [ ! -d "$linkdir" ]; then 2220 warn "$_me: the directory $linkdir does not exist." 2221 return 1 2222 fi 2223 if ! ln -sf $src $link; then 2224 warn "$_me: unable to make a symbolic link from $link to $src" 2225 return 1 2226 fi 2227 return 0 2228} 2229 2230# devfs_rulesets_from_file file 2231# Reads a set of devfs commands from file, and creates 2232# the specified rulesets with their rules. Returns non-zero 2233# if there was an error. 2234# 2235devfs_rulesets_from_file() 2236{ 2237 local file _err _me _opts 2238 file="$1" 2239 _me="devfs_rulesets_from_file" 2240 _err=0 2241 2242 if [ -z "$file" ]; then 2243 warn "$_me: you must specify a file" 2244 return 1 2245 fi 2246 if [ ! -e "$file" ]; then 2247 debug "$_me: no such file ($file)" 2248 return 0 2249 fi 2250 2251 # Disable globbing so that the rule patterns are not expanded 2252 # by accident with matching filesystem entries. 2253 _opts=$-; set -f 2254 2255 debug "reading rulesets from file ($file)" 2256 { while read line 2257 do 2258 case $line in 2259 \#*) 2260 continue 2261 ;; 2262 \[*\]*) 2263 rulenum=`expr "$line" : "\[.*=\([0-9]*\)\]"` 2264 if [ -z "$rulenum" ]; then 2265 warn "$_me: cannot extract rule number ($line)" 2266 _err=1 2267 break 2268 fi 2269 rulename=`expr "$line" : "\[\(.*\)=[0-9]*\]"` 2270 if [ -z "$rulename" ]; then 2271 warn "$_me: cannot extract rule name ($line)" 2272 _err=1 2273 break; 2274 fi 2275 eval $rulename=\$rulenum 2276 debug "found ruleset: $rulename=$rulenum" 2277 if ! /sbin/devfs rule -s $rulenum delset; then 2278 _err=1 2279 break 2280 fi 2281 ;; 2282 *) 2283 rulecmd="${line%%"\#*"}" 2284 # evaluate the command incase it includes 2285 # other rules 2286 if [ -n "$rulecmd" ]; then 2287 debug "adding rule ($rulecmd)" 2288 if ! eval /sbin/devfs rule -s $rulenum $rulecmd 2289 then 2290 _err=1 2291 break 2292 fi 2293 fi 2294 ;; 2295 esac 2296 if [ $_err -ne 0 ]; then 2297 debug "error in $_me" 2298 break 2299 fi 2300 done } < $file 2301 case $_opts in *f*) ;; *) set +f ;; esac 2302 return $_err 2303} 2304 2305# devfs_init_rulesets 2306# Initializes rulesets from configuration files. Returns 2307# non-zero if there was an error. 2308# 2309devfs_init_rulesets() 2310{ 2311 local file _me 2312 _me="devfs_init_rulesets" 2313 2314 # Go through this only once 2315 if [ -n "$devfs_rulesets_init" ]; then 2316 debug "$_me: devfs rulesets already initialized" 2317 return 2318 fi 2319 for file in $devfs_rulesets; do 2320 if ! devfs_rulesets_from_file $file; then 2321 warn "$_me: could not read rules from $file" 2322 return 1 2323 fi 2324 done 2325 devfs_rulesets_init=1 2326 debug "$_me: devfs rulesets initialized" 2327 return 0 2328} 2329 2330# devfs_set_ruleset ruleset [dir] 2331# Sets the default ruleset of dir to ruleset. The ruleset argument 2332# must be a ruleset name as specified in devfs.rules(5) file. 2333# Returns non-zero if it could not set it successfully. 2334# 2335devfs_set_ruleset() 2336{ 2337 local devdir rs _me 2338 [ -n "$1" ] && eval rs=\$$1 || rs= 2339 [ -n "$2" ] && devdir="-m "$2"" || devdir= 2340 _me="devfs_set_ruleset" 2341 2342 if [ -z "$rs" ]; then 2343 warn "$_me: you must specify a ruleset number" 2344 return 1 2345 fi 2346 debug "$_me: setting ruleset ($rs) on mount-point (${devdir#-m })" 2347 if ! /sbin/devfs $devdir ruleset $rs; then 2348 warn "$_me: unable to set ruleset $rs to ${devdir#-m }" 2349 return 1 2350 fi 2351 return 0 2352} 2353 2354# devfs_apply_ruleset ruleset [dir] 2355# Apply ruleset number $ruleset to the devfs mountpoint $dir. 2356# The ruleset argument must be a ruleset name as specified 2357# in a devfs.rules(5) file. Returns 0 on success or non-zero 2358# if it could not apply the ruleset. 2359# 2360devfs_apply_ruleset() 2361{ 2362 local devdir rs _me 2363 [ -n "$1" ] && eval rs=\$$1 || rs= 2364 [ -n "$2" ] && devdir="-m "$2"" || devdir= 2365 _me="devfs_apply_ruleset" 2366 2367 if [ -z "$rs" ]; then 2368 warn "$_me: you must specify a ruleset" 2369 return 1 2370 fi 2371 debug "$_me: applying ruleset ($rs) to mount-point (${devdir#-m })" 2372 if ! /sbin/devfs $devdir rule -s $rs applyset; then 2373 warn "$_me: unable to apply ruleset $rs to ${devdir#-m }" 2374 return 1 2375 fi 2376 return 0 2377} 2378 2379# devfs_domount dir [ruleset] 2380# Mount devfs on dir. If ruleset is specified it is set 2381# on the mount-point. It must also be a ruleset name as specified 2382# in a devfs.rules(5) file. Returns 0 on success. 2383# 2384devfs_domount() 2385{ 2386 local devdir rs _me 2387 devdir="$1" 2388 [ -n "$2" ] && rs=$2 || rs= 2389 _me="devfs_domount()" 2390 2391 if [ -z "$devdir" ]; then 2392 warn "$_me: you must specify a mount-point" 2393 return 1 2394 fi 2395 debug "$_me: mount-point is ($devdir), ruleset is ($rs)" 2396 if ! mount -t devfs dev "$devdir"; then 2397 warn "$_me: Unable to mount devfs on $devdir" 2398 return 1 2399 fi 2400 if [ -n "$rs" ]; then 2401 devfs_init_rulesets 2402 devfs_set_ruleset $rs $devdir 2403 devfs -m $devdir rule applyset 2404 fi 2405 return 0 2406} 2407 2408# Provide a function for normalizing the mounting of memory 2409# filesystems. This should allow the rest of the code here to remain 2410# as close as possible between 5-current and 4-stable. 2411# $1 = size 2412# $2 = mount point 2413# $3 = (optional) extra mdmfs flags 2414mount_md() 2415{ 2416 if [ -n "$3" ]; then 2417 flags="$3" 2418 fi 2419 /sbin/mdmfs $flags -s $1 ${mfs_type} $2 2420} 2421 2422# Code common to scripts that need to load a kernel module 2423# if it isn't in the kernel yet. Syntax: 2424# load_kld [-e regex] [-m module] file 2425# where -e or -m chooses the way to check if the module 2426# is already loaded: 2427# regex is egrep'd in the output from `kldstat -v', 2428# module is passed to `kldstat -m'. 2429# The default way is as though `-m file' were specified. 2430load_kld() 2431{ 2432 local _loaded _mod _opt _re 2433 2434 while getopts "e:m:" _opt; do 2435 case "$_opt" in 2436 e) _re="$OPTARG" ;; 2437 m) _mod="$OPTARG" ;; 2438 *) err 3 'USAGE: load_kld [-e regex] [-m module] file' ;; 2439 esac 2440 done 2441 shift $(($OPTIND - 1)) 2442 if [ $# -ne 1 ]; then 2443 err 3 'USAGE: load_kld [-e regex] [-m module] file' 2444 fi 2445 _mod=${_mod:-$1} 2446 _loaded=false 2447 if [ -n "$_re" ]; then 2448 if kldstat -v | egrep -q -e "$_re"; then 2449 _loaded=true 2450 fi 2451 else 2452 if kldstat -q -m "$_mod"; then 2453 _loaded=true 2454 fi 2455 fi 2456 if ! $_loaded; then 2457 if ! kldload "$1"; then 2458 warn "Unable to load kernel module $1" 2459 return 1 2460 else 2461 info "$1 kernel module loaded." 2462 if [ -f "/etc/sysctl.kld.d/$1.conf" ]; then 2463 sysctl -f "/etc/sysctl.kld.d/$1.conf" 2464 fi 2465 fi 2466 else 2467 debug "load_kld: $1 kernel module already loaded." 2468 fi 2469 return 0 2470} 2471 2472# ltr str src dst [var] 2473# Change every $src in $str to $dst. 2474# Useful when /usr is not yet mounted and we cannot use tr(1), sed(1) nor 2475# awk(1). If var is non-NULL, set it to the result. 2476ltr() 2477{ 2478 local _str _src _dst _out _com _var 2479 _str="$1" 2480 _src="$2" 2481 _dst="$3" 2482 _var="$4" 2483 _out="" 2484 2485 local IFS="${_src}" 2486 for _com in ${_str}; do 2487 if [ -z "${_out}" ]; then 2488 _out="${_com}" 2489 else 2490 _out="${_out}${_dst}${_com}" 2491 fi 2492 done 2493 if [ -n "${_var}" ]; then 2494 setvar "${_var}" "${_out}" 2495 else 2496 echo "${_out}" 2497 fi 2498} 2499 2500# Creates a list of providers for GELI encryption. 2501geli_make_list() 2502{ 2503 local devices devices2 2504 local provider mountpoint type options rest 2505 2506 # Create list of GELI providers from fstab. 2507 while read provider mountpoint type options rest ; do 2508 case ":${options}" in 2509 :*noauto*) 2510 noauto=yes 2511 ;; 2512 *) 2513 noauto=no 2514 ;; 2515 esac 2516 2517 case ":${provider}" in 2518 :#*) 2519 continue 2520 ;; 2521 *.eli) 2522 # Skip swap devices. 2523 if [ "${type}" = "swap" -o "${options}" = "sw" -o "${noauto}" = "yes" ]; then 2524 continue 2525 fi 2526 devices="${devices} ${provider}" 2527 ;; 2528 esac 2529 done < /etc/fstab 2530 2531 # Append providers from geli_devices. 2532 devices="${devices} ${geli_devices}" 2533 2534 for provider in ${devices}; do 2535 provider=${provider%.eli} 2536 provider=${provider#/dev/} 2537 devices2="${devices2} ${provider}" 2538 done 2539 2540 echo ${devices2} 2541} 2542 2543# Originally, root mount hold had to be released before mounting 2544# the root filesystem. This delayed the boot, so it was changed 2545# to only wait if the root device isn't readily available. This 2546# can result in rc scripts executing before all the devices - such 2547# as graid(8), or USB disks - can be accessed. This function can 2548# be used to explicitly wait for root mount holds to be released. 2549root_hold_wait() 2550{ 2551 local wait waited holders 2552 2553 waited=0 2554 while true; do 2555 holders="$(sysctl -n vfs.root_mount_hold)" 2556 if [ -z "${holders}" ]; then 2557 break; 2558 fi 2559 if [ ${waited} -eq 0 ]; then 2560 echo -n "Waiting ${root_hold_delay}s" \ 2561 "for the root mount holders: ${holders}" 2562 else 2563 echo -n . 2564 fi 2565 if [ ${waited} -ge ${root_hold_delay} ]; then 2566 echo 2567 break 2568 fi 2569 sleep 1 2570 waited=$(($waited + 1)) 2571 done 2572} 2573 2574# Find scripts in local_startup directories that use the old syntax 2575# 2576find_local_scripts_old() { 2577 zlist='' 2578 slist='' 2579 for dir in ${local_startup}; do 2580 if [ -d "${dir}" ]; then 2581 for file in ${dir}/[0-9]*.sh; do 2582 grep '^# PROVIDE:' $file >/dev/null 2>&1 && 2583 continue 2584 zlist="$zlist $file" 2585 done 2586 for file in ${dir}/[!0-9]*.sh; do 2587 grep '^# PROVIDE:' $file >/dev/null 2>&1 && 2588 continue 2589 slist="$slist $file" 2590 done 2591 fi 2592 done 2593} 2594 2595find_local_scripts_new() { 2596 local_rc='' 2597 for dir in ${local_startup}; do 2598 if [ -d "${dir}" ]; then 2599 for file in `grep -l '^# PROVIDE:' ${dir}/* 2>/dev/null`; do 2600 case "$file" in 2601 *.sample|*.pkgsave) ;; 2602 *) if [ -x "$file" ]; then 2603 local_rc="${local_rc} ${file}" 2604 fi 2605 ;; 2606 esac 2607 done 2608 fi 2609 done 2610} 2611 2612find_system_scripts() { 2613 system_rc='' 2614 for file in /etc/rc.d/*; do 2615 case "${file##*/}" in 2616 *.pkgsave) ;; 2617 *) if [ -x "$file" ]; then 2618 system_rc="${system_rc} ${file}" 2619 fi 2620 ;; 2621 esac 2622 done 2623} 2624 2625# check_required_{before|after} command 2626# Check for things required by the command before and after its precmd, 2627# respectively. The two separate functions are needed because some 2628# conditions should prevent precmd from being run while other things 2629# depend on precmd having already been run. 2630# 2631check_required_before() 2632{ 2633 local _f 2634 2635 case "$1" in 2636 start) 2637 for _f in $required_vars; do 2638 if ! checkyesno $_f; then 2639 warn "\$${_f} is not enabled." 2640 if [ -z "$rc_force" ]; then 2641 return 1 2642 fi 2643 fi 2644 done 2645 2646 for _f in $required_dirs; do 2647 if [ ! -d "${_f}/." ]; then 2648 warn "${_f} is not a directory." 2649 if [ -z "$rc_force" ]; then 2650 return 1 2651 fi 2652 fi 2653 done 2654 2655 for _f in $required_files; do 2656 if [ ! -r "${_f}" ]; then 2657 warn "${_f} is not readable." 2658 if [ -z "$rc_force" ]; then 2659 return 1 2660 fi 2661 fi 2662 done 2663 ;; 2664 esac 2665 2666 return 0 2667} 2668 2669check_required_after() 2670{ 2671 local _f _args 2672 2673 case "$1" in 2674 start) 2675 for _f in $required_modules; do 2676 case "${_f}" in 2677 *~*) _args="-e ${_f#*~} ${_f%%~*}" ;; 2678 *:*) _args="-m ${_f#*:} ${_f%%:*}" ;; 2679 *) _args="${_f}" ;; 2680 esac 2681 if ! load_kld ${_args}; then 2682 if [ -z "$rc_force" ]; then 2683 return 1 2684 fi 2685 fi 2686 done 2687 ;; 2688 esac 2689 2690 return 0 2691} 2692 2693# check_jail mib 2694# Return true if security.jail.$mib exists and set to 1. 2695 2696check_jail() 2697{ 2698 local _mib _v 2699 2700 _mib=$1 2701 if _v=$(${SYSCTL_N} "security.jail.$_mib" 2> /dev/null); then 2702 case $_v in 2703 1) return 0;; 2704 esac 2705 fi 2706 return 1 2707} 2708 2709# check_kern_features mib 2710# Return existence of kern.features.* sysctl MIB as true or 2711# false. The result will be cached in $_rc_cache_kern_features_ 2712# namespace. "0" means the kern.features.X exists. 2713 2714check_kern_features() 2715{ 2716 local _v 2717 2718 [ -n "$1" ] || return 1; 2719 eval _v=\$_rc_cache_kern_features_$1 2720 [ -n "$_v" ] && return "$_v"; 2721 2722 if ${SYSCTL_N} kern.features.$1 > /dev/null 2>&1; then 2723 eval _rc_cache_kern_features_$1=0 2724 return 0 2725 else 2726 eval _rc_cache_kern_features_$1=1 2727 return 1 2728 fi 2729} 2730 2731# check_namevarlist var 2732# Return "0" if ${name}_var is reserved in rc.subr. 2733 2734_rc_namevarlist="program chroot chdir env flags fib nice user group groups prepend setup" 2735check_namevarlist() 2736{ 2737 local _v 2738 2739 for _v in $_rc_namevarlist; do 2740 case $1 in 2741 $_v) return 0 ;; 2742 esac 2743 done 2744 2745 return 1 2746} 2747 2748# _echoonce var msg mode 2749# mode=0: Echo $msg if ${$var} is empty. 2750# After doing echo, a string is set to ${$var}. 2751# 2752# mode=1: Echo $msg if ${$var} is a string with non-zero length. 2753# 2754_echoonce() 2755{ 2756 local _var _msg _mode 2757 eval _var=\$$1 2758 _msg=$2 2759 _mode=$3 2760 2761 case $_mode in 2762 1) [ -n "$_var" ] && echo "$_msg" ;; 2763 *) [ -z "$_var" ] && echo -n "$_msg" && eval "$1=finished" ;; 2764 esac 2765} 2766 2767# _find_rcvar var 2768# Find the rc.conf file (other than /etc/defaults/rc.conf) that sets $var. 2769_find_rcvar() 2770{ 2771 local _var _dir _files 2772 2773 [ -n "$1" ] || return 1 2774 _var="$1"; shift 2775 2776 _files="/etc/rc.conf" 2777 for _dir in /etc ${local_startup}; do 2778 for _name in $_loaded_services; do 2779 _files="${_dir%/rc.d}/rc.conf.d/${_name} ${_files}" 2780 done 2781 done 2782 2783 /usr/bin/grep 2>/dev/null -rl "^${_var}=" $_files | /usr/bin/head -1 2784} 2785 2786# write_rcvar var value 2787# Add or replace the rc var $var with the value $value. 2788# Look for a current setting of $var in /etc/rc.conf or /etc/rc.conf.d/$name, 2789# and if found, modify it there; otherwise, append to /etc/rc.conf. 2790write_rcvar() 2791{ 2792 local _var _value _file _dir 2793 2794 [ -n "$1" ] || return 1 2795 _var="$1"; shift 2796 [ -n "$1" ] || return 1 2797 _value="$1"; shift 2798 2799 _file="$(_find_rcvar "$_var")" 2800 if [ -n "$_file" ]; then 2801 local _=$'\01' 2802 /usr/bin/sed -i '' "s${_}^${_var}=.*${_}${_var}=\"$_value\"${_}" "$_file" 2803 echo $_file 2804 return 2805 fi 2806 2807 for _dir in /etc ${local_startup}; do 2808 _file="${_dir%/rc.d}/rc.conf.d/${name}" 2809 if [ -f "$_file" ]; then 2810 echo "${_var}=\"${_value}\"" >>"$_file" 2811 echo "$_file" 2812 return 2813 fi 2814 done 2815 2816 echo "${_var}=\"${_value}\"" >>/etc/rc.conf 2817 echo "/etc/rc.conf" 2818} 2819 2820# delete_rcvar var 2821# Remove the rc var $var. 2822# Look for a current setting of $var in /etc/rc.conf or /etc/rc.conf.d/$name, 2823# and if found, remove it. If service_delete_empty is enabled, and the 2824# resulting file is empty, also delete the file. 2825delete_rcvar() 2826{ 2827 local _var _files 2828 2829 [ -n "$1" ] || return 1 2830 _var="$1"; shift 2831 2832 _file="$(_find_rcvar "$_var")" 2833 if [ -n "$_file" ]; then 2834 /usr/bin/sed -i '' "/^${_var}=/d" "$_file" 2835 echo "$_var deleted in $_file" 2836 2837 if checkyesno service_delete_empty && [ ! -s "$_file" ]; then 2838 /bin/rm -f "$_file" 2839 echo "Empty file $_file removed" 2840 fi 2841 fi 2842} 2843 2844# If the loader env variable rc.debug is set, turn on debugging. rc.conf will 2845# still override this, but /etc/defaults/rc.conf can't unconditionally set this 2846# since it would undo what we've done here. 2847if kenv -q rc.debug > /dev/null ; then 2848 rc_debug=YES 2849fi 2850 2851boottrace_cmd=`command -v boottrace` 2852if [ -n "$boottrace_cmd" ] && [ "`${SYSCTL_N} -q kern.boottrace.enabled`" = "1" ]; then 2853 rc_boottrace=YES 2854fi 2855 2856SED=${SED:-$(Exists -x /usr/bin/sed /rescue/sed)} 2857 2858# Allow for local additions and overrides. 2859# Use vdot to ensure the file has not been tampered with. 2860vdot /etc/local.rc.subr 2861 2862# Avoid noise - when we do not have /usr mounted, 2863# and we cannot use safe_dot without sed. 2864if ! have basename; then 2865 basename() 2866 { 2867 local b=${1%$2} 2868 echo ${b##*/} 2869 } 2870 tty() 2871 { 2872 return 0 2873 } 2874 # we cannot use safe_dot without sed 2875 [ -z "$SED" ] && _SAFE_EVAL_SH=: 2876fi 2877# safe_eval.sh provides safe_dot - for untrusted files 2878$_SAFE_EVAL_SH vdot /libexec/safe_eval.sh 2879$_DEBUG_SH vdot /libexec/debug.sh 2880 2881# Ensure we can still operate if debug.sh and 2882# safe_eval.sh are not found. 2883if ! have DebugOn; then 2884 DebugOn() { return 0; } 2885 DebugOff() { 2886 local _rc=0 2887 while : 2888 do 2889 case "$1" in 2890 -[eo]) shift;; # ignore it 2891 rc=*) eval "_$1"; shift;; 2892 *) break;; 2893 esac 2894 done 2895 return $_rc 2896 } 2897fi 2898if ! have safe_dot; then 2899 safe_dot() { dot "$@"; } 2900fi 2901