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