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 -opr $_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 _svcj=NO 1176 fi 1177 eval ${name}_svcj=$_svcj 1178 fi 1179 1180 # setup pid check command 1181 if [ -n "$_procname" ]; then 1182 if [ -n "$pidfile" ]; then 1183 _pidcmd='rc_pid=$(check_pidfile '"$pidfile $_procname $command_interpreter"')' 1184 else 1185 _pidcmd='rc_pid=$(check_process '"$_procname $command_interpreter"')' 1186 fi 1187 _keywords="${_keywords} status poll" 1188 else 1189 if [ ! -z "${status_cmd}" ] 1190 then 1191 _keywords="${_keywords} status" 1192 fi 1193 fi 1194 1195 if [ -z "$rc_arg" ]; then 1196 rc_usage $_keywords 1197 fi 1198 1199 if [ "$rc_arg" = "enabled" ] ; then 1200 checkyesno ${rcvar} 1201 return $? 1202 fi 1203 1204 if [ -n "$flags" ]; then # allow override from environment 1205 rc_flags=$flags 1206 else 1207 eval rc_flags=\$${name}_flags 1208 fi 1209 eval _chdir=\$${name}_chdir _chroot=\$${name}_chroot \ 1210 _nice=\$${name}_nice _user=\$${name}_user \ 1211 _group=\$${name}_group _groups=\$${name}_groups \ 1212 _fib=\$${name}_fib _env=\$${name}_env \ 1213 _prepend=\$${name}_prepend _login_class=\${${name}_login_class:-daemon} \ 1214 _limits=\$${name}_limits _oomprotect=\$${name}_oomprotect \ 1215 _setup=\$${name}_setup _env_file=\$${name}_env_file \ 1216 _umask=\$${name}_umask _svcj_options=\$${name}_svcj_options \ 1217 _svcj_ipaddrs=\$${name}_svcj_ipaddrs 1218 1219 if [ -n "$_env_file" ] && [ -r "${_env_file}" ]; then # load env from file 1220 set -a 1221 . $_env_file 1222 set +a 1223 fi 1224 1225 if [ -n "$_user" ]; then # unset $_user if running as that user 1226 if [ "$_user" = "$(eval $IDCMD)" ]; then 1227 unset _user 1228 fi 1229 fi 1230 1231 _svcj_ip4_addrs="" 1232 _svcj_ip6_addrs="" 1233 _svcj_cmd_options="" 1234 1235 if [ -n "$_svcj_ipaddrs" ]; then 1236 _svcj_ip="new" 1237 1238 for addr in $_svcj_ipaddrs; do 1239 case $addr in 1240 *:*) _svcj_ip6_addrs="$addr,${_svcj_ip6_addrs}" ;; 1241 *) _svcj_ip4_addrs="$addr,${_svcj_ip4_addrs}" ;; 1242 esac 1243 done 1244 else 1245 _svcj_ip="inherit" 1246 fi 1247 1248 if check_kern_features inet; then 1249 _svcj_ip4="ip4=${_svcj_ip}" 1250 if [ -n "$_svcj_ip4_addrs" ]; then 1251 _svcj_cmd_options="ip4.addr=${_svcj_ip4_addrs%*,} ${_svcj_cmd_options}" 1252 fi 1253 else 1254 if [ -n "$_svcj_ip4_addrs" ]; then 1255 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." 1256 fi 1257 fi 1258 1259 if check_kern_features inet6; then 1260 _svcj_ip6="ip6=${_svcj_ip}" 1261 if [ -n "$_svcj_ip6_addrs" ]; then 1262 _svcj_cmd_options="ip6.addr=${_svcj_ip6_addrs%*,} ${_svcj_cmd_options}" 1263 fi 1264 else 1265 if [ -n "$_svcj_ip6_addrs" ]; then 1266 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." 1267 fi 1268 fi 1269 1270 if [ -n "$_svcj_options" ]; then # translate service jail options 1271 _svcj_sysvipc_x=0 1272 for _svcj_option in $_svcj_options; do 1273 _opts= 1274 case "$_svcj_option" in 1275 mlock) 1276 _opts="allow.mlock" 1277 ;; 1278 netv4) 1279 _opts="${_svcj_ip4} allow.reserved_ports" 1280 ;; 1281 netv6) 1282 _opts="${_svcj_ip6} allow.reserved_ports" 1283 ;; 1284 net_basic) 1285 _opts="${_svcj_ip4} ${_svcj_ip6}" 1286 _opts="${_opts} allow.reserved_ports" 1287 ;; 1288 net_raw) 1289 _opts="allow.raw_sockets" 1290 ;; 1291 net_all) 1292 _opts="allow.socket_af" 1293 _opts="${_opts} allow.raw_sockets" 1294 _opts="${_opts} allow.reserved_ports" 1295 _opts="${_opts} ${_svcj_ip4} ${_svcj_ip6}" 1296 ;; 1297 nfsd) 1298 _opts="allow.nfsd enforce_statfs=1" 1299 ;; 1300 routing) 1301 _opts="allow.routing" 1302 ;; 1303 setaudit) 1304 _opts="allow.setaudit" 1305 ;; 1306 settime) 1307 _opts="allow.settime" 1308 ;; 1309 sysvipc) 1310 _svcj_sysvipc_x=$((${_svcj_sysvipc_x} + 1)) 1311 _opts="sysvmsg=inherit sysvsem=inherit sysvshm=inherit" 1312 ;; 1313 sysvipcnew) 1314 _svcj_sysvipc_x=$((${_svcj_sysvipc_x} + 1)) 1315 _opts="sysvmsg=new sysvsem=new sysvshm=new" 1316 ;; 1317 vmm) 1318 _opts="allow.vmm" 1319 ;; 1320 *) 1321 echo ${name}: unknown service jail option: $_svcj_option 1322 ;; 1323 esac 1324 _svcj_cmd_options="${_opts} ${_svcj_cmd_options}" 1325 done 1326 if [ ${_svcj_sysvipc_x} -gt 1 ]; then 1327 echo -n "ERROR: more than one sysvipc option is " 1328 echo "specified in ${name}_svcj_options: $_svcj_options" 1329 return 1 1330 fi 1331 fi 1332 1333 [ -z "$autoboot" ] && eval $_pidcmd # determine the pid if necessary 1334 1335 for _elem in $_keywords; do 1336 if [ "$_elem" != "$rc_arg" ]; then 1337 continue 1338 fi 1339 # if ${rcvar} is set, $1 is not "rcvar", "describe", 1340 # "enable", "delete" or "status", and ${rc_pid} is 1341 # not set, run: 1342 # checkyesno ${rcvar} 1343 # and return if that failed 1344 # 1345 if [ -n "${rcvar}" -a "$rc_arg" != "rcvar" -a "$rc_arg" != "stop" \ 1346 -a "$rc_arg" != "delete" -a "$rc_arg" != "enable" \ 1347 -a "$rc_arg" != "describe" -a "$rc_arg" != "status" ] || 1348 [ -n "${rcvar}" -a "$rc_arg" = "stop" -a -z "${rc_pid}" ]; then 1349 if ! checkyesno ${rcvar}; then 1350 [ "$rc_arg" = "start" ] && _run_rc_offcmd 1351 if [ -z "${rc_quiet}" ]; then 1352 echo -n "Cannot '${rc_arg}' $name. Set ${rcvar} to " 1353 echo -n "YES in /etc/rc.conf or use 'one${rc_arg}' " 1354 echo "instead of '${rc_arg}'." 1355 fi 1356 return 0 1357 fi 1358 fi 1359 1360 if [ $rc_arg = "start" -a -z "$rc_fast" -a -n "$rc_pid" ]; then 1361 if [ -z "$rc_quiet" ]; then 1362 echo 1>&2 "${name} already running? " \ 1363 "(pid=$rc_pid)." 1364 fi 1365 return 1 1366 fi 1367 1368 # if there's a custom ${XXX_cmd}, 1369 # run that instead of the default 1370 # 1371 eval _cmd=\$${rc_arg}_cmd \ 1372 _precmd=\$${rc_arg}_precmd \ 1373 _postcmd=\$${rc_arg}_postcmd 1374 1375 if [ -n "$_cmd" ]; then 1376 if [ "$_cmd" != : ]; then 1377 rc_trace 1 "$_cmd" 1378 fi 1379 if [ -n "$_env" ]; then 1380 eval "export -- $_env" 1381 fi 1382 1383 if [ "${_rc_svcj}" != jailing ]; then 1384 # service can redefine all so 1385 # check for valid setup target 1386 if [ "$rc_arg" = 'start' -o \ 1387 "$rc_arg" = 'restart' -o \ 1388 "$rc_arg" = 'reload' ]; then 1389 _run_rc_setup || \ 1390 warn "failed to setup ${name}" 1391 fi 1392 _run_rc_precmd || return 1 1393 fi 1394 if ! checkyesno ${name}_svcj; then 1395 _run_rc_doit "$_cmd $rc_extra_args" || return 1 1396 else 1397 case "$rc_arg" in 1398 start) 1399 if [ "${_rc_svcj}" != jailing ]; then 1400 _return=1 1401 _do_jailing=1 1402 1403 if check_jail jailed; then 1404 if [ $(${SYSCTL_N} security.jail.children.max) -eq 0 ]; then 1405 echo ERROR: jail parameter children.max is set to 0, can not create a new service jail. 1406 _do_jailing=0 1407 else 1408 _free_jails=$(($(${SYSCTL_N} security.jail.children.max) - $(${SYSCTL_N} security.jail.children.cur))) 1409 if [ ${_free_jails} -eq 0 ]; then 1410 echo ERROR: max number of jail children reached, can not create a new service jail. 1411 _do_jailing=0 1412 1413 fi 1414 fi 1415 fi 1416 if [ ${_do_jailing} -eq 1 ]; then 1417 $JAIL_CMD -c $_svcj_generic_params $_svcj_cmd_options \ 1418 exec.start="${SERVICE} -E _rc_svcj=jailing ${rc_service##*/} ${_rc_prefix}start $rc_extra_args" \ 1419 exec.stop="${SERVICE} -E _rc_svcj=jailing ${rc_service##*/} ${_rc_prefix}stop $rc_extra_args" \ 1420 exec.consolelog="/var/log/svcj_${name}_console.log" \ 1421 name=svcj-${name} && _return=0 1422 fi 1423 else 1424 _run_rc_doit "$_cmd $rc_extra_args" || _return=1 1425 fi 1426 ;; 1427 stop) 1428 if [ "${_rc_svcj}" != jailing ]; then 1429 $SERVICE -E _rc_svcj=jailing -j svcj-${name} ${rc_service##*/} ${_rc_prefix}stop $rc_extra_args || _return=1 1430 $JAIL_CMD -r svcj-${name} 2>/dev/null 1431 else 1432 _run_rc_doit "$_cmd $rc_extra_args" || _return=1 1433 fi 1434 ;; 1435 restart) 1436 if [ "${_rc_svcj}" = jailing ]; then 1437 _run_rc_doit "$_cmd $rc_extra_args" || _return=1 1438 elif /usr/sbin/jls -j svcj-${name} jid >/dev/null 2>&1; then 1439 $SERVICE -E _rc_svcj=jailing -j svcj-${name} ${rc_service##*/} ${_rc_prefix}restart $rc_extra_args || _return=1 1440 else 1441 # nothing to restart, so start it 1442 ( run_rc_command ${_rc_prefix}start $rc_extra_args ) || _return=1 1443 fi 1444 ;; 1445 status) 1446 if [ "${_rc_svcj}" != jailing ]; then 1447 $SERVICE -E _rc_svcj=jailing -j svcj-${name} ${rc_service##*/} ${_rc_prefix}status $rc_extra_args || _return=1 1448 else 1449 _run_rc_doit "$_cmd $rc_extra_args" || _return=1 1450 fi 1451 ;; 1452 *) 1453 eval _rc_svcj_extra_cmd=\$${name}_${rc_arg}_svcj_enable 1454 : ${_rc_svcj_extra_cmd:=NO} 1455 if checkyesno _rc_svcj_extra_cmd && [ "${_rc_svcj}" != jailing ]; then 1456 $SERVICE -v -E _rc_svcj=jailing -j svcj-${name} ${rc_service##*/} ${_rc_prefix}${rc_arg} $rc_extra_args || _return=1 1457 else 1458 _run_rc_doit "$_cmd $rc_extra_args" || _return=1 1459 fi 1460 ;; 1461 esac 1462 fi 1463 if [ "${_rc_svcj}" != jailing ]; then 1464 _run_rc_postcmd 1465 fi 1466 return $_return 1467 fi 1468 1469 case "$rc_arg" in # default operations... 1470 1471 describe) 1472 if [ -n "$desc" ]; then 1473 echo "$desc" 1474 fi 1475 ;; 1476 1477 extracommands) 1478 echo "$extra_commands" 1479 ;; 1480 1481 enable) 1482 _out=$(write_rcvar "$rcvar" "YES") && 1483 echo "$name enabled in $_out" 1484 ;; 1485 1486 disable) 1487 _out=$(write_rcvar "$rcvar" "NO") && 1488 echo "$name disabled in $_out" 1489 ;; 1490 1491 delete) 1492 delete_rcvar "$rcvar" 1493 ;; 1494 1495 status) 1496 _run_rc_precmd || return 1 1497 if [ -n "$rc_pid" ]; then 1498 echo "${name} is running as pid $rc_pid." 1499 else 1500 echo "${name} is not running." 1501 return 1 1502 fi 1503 _run_rc_postcmd 1504 ;; 1505 1506 start) 1507 if [ ! -x "${_chroot}${_chroot:+/}${command}" ]; then 1508 warn "run_rc_command: cannot run $command" 1509 return 1 1510 fi 1511 1512 if [ "${_rc_svcj}" != jailing ]; then 1513 _run_rc_setup || warn "failed to setup ${name}" 1514 1515 if ! _run_rc_precmd; then 1516 warn "failed precmd routine for ${name}" 1517 return 1 1518 fi 1519 fi 1520 1521 if checkyesno ${name}_svcj; then 1522 if [ "${_rc_svcj}" != jailing ]; then 1523 if check_jail jailed; then 1524 if [ $(${SYSCTL_N} security.jail.children.max) -eq 0 ]; then 1525 echo ERROR: jail parameter children.max is set to 0, can not create a new service jail. 1526 return 1 1527 else 1528 _free_jails=$(($(${SYSCTL_N} security.jail.children.max) - $(${SYSCTL_N} security.jail.children.cur))) 1529 if [ ${_free_jails} -eq 0 ]; then 1530 echo ERROR: max number of jail children reached, can not create a new service jail. 1531 return 1 1532 fi 1533 fi 1534 fi 1535 $JAIL_CMD -c $_svcj_generic_params $_svcj_cmd_options\ 1536 exec.start="${SERVICE} -E _rc_svcj=jailing ${rc_service##*/} ${_rc_prefix}start $rc_extra_args" \ 1537 exec.stop="${SERVICE} -E _rc_svcj=jailing ${rc_service##*/} ${_rc_prefix}stop $rc_extra_args" \ 1538 exec.consolelog="/var/log/svcj_${name}_console.log" \ 1539 name=svcj-${name} || return 1 1540 fi 1541 fi 1542 1543 # setup the full command to run 1544 # 1545 startmsg "Starting ${name}." 1546 if [ -n "$_chroot" ]; then 1547 _cd= 1548 _doit="\ 1549${_nice:+nice -n $_nice }\ 1550$_cpusetcmd \ 1551$_setauditcmd \ 1552${_fib:+setfib -F $_fib }\ 1553${_env:+env $_env }\ 1554chroot ${_user:+-u $_user }${_group:+-g $_group }${_groups:+-G $_groups }\ 1555$_chroot $command $rc_flags $command_args" 1556 else 1557 _cd="${_chdir:+cd $_chdir && }" 1558 _doit="\ 1559${_fib:+setfib -F $_fib }\ 1560${_env:+env $_env }\ 1561$_cpusetcmd \ 1562$_setauditcmd \ 1563$command $rc_flags $command_args" 1564 if [ -n "$_user" ]; then 1565 _doit="su -m $_user -c 'sh -c \"$_doit\"'" 1566 fi 1567 if [ -n "$_nice" ]; then 1568 if [ -z "$_user" ]; then 1569 _doit="sh -c \"$_doit\"" 1570 fi 1571 _doit="nice -n $_nice $_doit" 1572 fi 1573 if [ -n "$_prepend" ]; then 1574 _doit="$_prepend $_doit" 1575 fi 1576 fi 1577 1578 # Prepend default limits 1579 _doit="$_cd limits -C $_login_class $_limits $_doit" 1580 1581 local _really_run_it=true 1582 if checkyesno ${name}_svcj; then 1583 if [ "${_rc_svcj}" != jailing ]; then 1584 _really_run_it=false 1585 fi 1586 fi 1587 1588 if [ "$_really_run_it" = true ]; then 1589 # run the full command 1590 # 1591 if ! _run_rc_doit "$_doit"; then 1592 warn "failed to start ${name}" 1593 return 1 1594 fi 1595 fi 1596 1597 if [ "${_rc_svcj}" != jailing ]; then 1598 # finally, run postcmd 1599 # 1600 _run_rc_postcmd 1601 fi 1602 ;; 1603 1604 stop) 1605 if [ -z "$rc_pid" ]; then 1606 if checkyesno ${name}_svcj && 1607 /usr/sbin/jls -j svcj-${name} jid >/dev/null 2>&1; then 1608 $JAIL_CMD -r svcj-${name} 2>/dev/null 1609 fi 1610 [ -n "$rc_fast" ] && return 0 1611 _run_rc_notrunning 1612 return 1 1613 fi 1614 1615 _run_rc_precmd || return 1 1616 1617 # send the signal to stop 1618 # 1619 echo "Stopping ${name}." 1620 _doit=$(_run_rc_killcmd "${sig_stop:-TERM}") 1621 _run_rc_doit "$_doit" || return 1 1622 1623 # wait for the command to exit, 1624 # and run postcmd. 1625 wait_for_pids $rc_pid 1626 1627 if checkyesno ${name}_svcj; then 1628 # remove service jail 1629 $JAIL_CMD -r svcj-${name} 2>/dev/null 1630 fi 1631 1632 _run_rc_postcmd 1633 ;; 1634 1635 reload) 1636 if [ -z "$rc_pid" ]; then 1637 _run_rc_notrunning 1638 return 1 1639 fi 1640 1641 _run_rc_setup || warn "failed to setup ${name}" 1642 1643 _run_rc_precmd || return 1 1644 1645 _doit=$(_run_rc_killcmd "${sig_reload:-HUP}") 1646 _run_rc_doit "$_doit" || return 1 1647 1648 _run_rc_postcmd 1649 ;; 1650 1651 restart) 1652 _run_rc_setup || warn "failed to setup ${name}" 1653 1654 # prevent restart being called more 1655 # than once by any given script 1656 # 1657 if ${_rc_restart_done:-false}; then 1658 return 0 1659 fi 1660 _rc_restart_done=true 1661 1662 _run_rc_precmd || return 1 1663 1664 # run those in a subshell to keep global variables 1665 ( run_rc_command ${_rc_prefix}stop $rc_extra_args ) 1666 ( run_rc_command ${_rc_prefix}start $rc_extra_args ) 1667 _return=$? 1668 [ $_return -ne 0 ] && [ -z "$rc_force" ] && return 1 1669 1670 _run_rc_postcmd 1671 ;; 1672 1673 poll) 1674 _run_rc_precmd || return 1 1675 if [ -n "$rc_pid" ]; then 1676 wait_for_pids $rc_pid 1677 fi 1678 _run_rc_postcmd 1679 ;; 1680 1681 rcvar) 1682 echo -n "# $name" 1683 if [ -n "$desc" ]; then 1684 echo " : $desc" 1685 else 1686 echo "" 1687 fi 1688 echo "#" 1689 # Get unique vars in $rcvar $rcvars 1690 for _v in $rcvar $rcvars; do 1691 case $v in 1692 $_v\ *|\ *$_v|*\ $_v\ *) ;; 1693 *) v="${v# } $_v" ;; 1694 esac 1695 done 1696 1697 # Display variables. 1698 for _v in $v; do 1699 if [ -z "$_v" ]; then 1700 continue 1701 fi 1702 1703 eval _desc=\$${_v}_desc 1704 eval _defval=\$${_v}_defval 1705 _h="-" 1706 1707 eval echo \"$_v=\\\"\$$_v\\\"\" 1708 # decode multiple lines of _desc 1709 while [ -n "$_desc" ]; do 1710 case $_desc in 1711 *^^*) 1712 echo "# $_h ${_desc%%^^*}" 1713 _desc=${_desc#*^^} 1714 _h=" " 1715 ;; 1716 *) 1717 echo "# $_h ${_desc}" 1718 break 1719 ;; 1720 esac 1721 done 1722 echo "# (default: \"$_defval\")" 1723 done 1724 echo "" 1725 ;; 1726 1727 *) 1728 rc_usage $_keywords 1729 ;; 1730 1731 esac 1732 1733 # Apply protect(1) to the PID if ${name}_oomprotect is set. 1734 case "$rc_arg" in 1735 start) 1736 # We cannot use protect(1) inside jails. 1737 if [ -n "$_oomprotect" ] && [ -f "${PROTECT}" ] && 1738 ! check_jail jailed; then 1739 [ -z "${rc_pid}" ] && eval $_pidcmd 1740 case $_oomprotect in 1741 [Aa][Ll][Ll]) 1742 ${PROTECT} -d -i -p ${rc_pid} 1743 ;; 1744 [Yy][Ee][Ss]) 1745 ${PROTECT} -p ${rc_pid} 1746 ;; 1747 esac 1748 fi 1749 ;; 1750 esac 1751 1752 return $_return 1753 done 1754 1755 echo 1>&2 "$0: unknown directive '$rc_arg'." 1756 rc_usage $_keywords 1757 # not reached 1758} 1759 1760# 1761# Helper functions for run_rc_command: common code. 1762# They use such global variables besides the exported rc_* ones: 1763# 1764# name R/W 1765# ------------------ 1766# _offcmd R 1767# _precmd R 1768# _postcmd R 1769# _return W 1770# _setup R 1771# 1772_run_rc_offcmd() 1773{ 1774 eval _offcmd=\$${name}_offcmd 1775 if [ -n "$_offcmd" ]; then 1776 if [ -n "$_env" ]; then 1777 eval "export -- $_env" 1778 fi 1779 debug "run_rc_command: ${name}_offcmd: $_offcmd $rc_extra_args" 1780 eval "$_offcmd $rc_extra_args" 1781 _return=$? 1782 fi 1783 return 0 1784} 1785 1786_run_rc_precmd() 1787{ 1788 check_required_before "$rc_arg" || return 1 1789 1790 if [ -n "$_precmd" ]; then 1791 debug "run_rc_command: ${rc_arg}_precmd: $_precmd $rc_extra_args" 1792 eval "$_precmd $rc_extra_args" 1793 _return=$? 1794 1795 # If precmd failed and force isn't set, request exit. 1796 if [ $_return -ne 0 ] && [ -z "$rc_force" ]; then 1797 return 1 1798 fi 1799 fi 1800 1801 check_required_after "$rc_arg" || return 1 1802 1803 return 0 1804} 1805 1806_run_rc_postcmd() 1807{ 1808 if [ -n "$_postcmd" ]; then 1809 debug "run_rc_command: ${rc_arg}_postcmd: $_postcmd $rc_extra_args" 1810 eval "$_postcmd $rc_extra_args" 1811 _return=$? 1812 fi 1813 return 0 1814} 1815 1816_run_rc_setup() 1817{ 1818 # prevent multiple execution on restart => stop/start split 1819 if ! ${_rc_restart_done:-false} && [ -n "$_setup" ]; then 1820 debug "run_rc_command: ${rc_arg}_setup: $_setup" 1821 eval "$_setup" 1822 _return=$? 1823 if [ $_return -ne 0 ]; then 1824 return 1 1825 fi 1826 fi 1827 return 0 1828} 1829 1830_run_rc_doit() 1831{ 1832 local _m 1833 1834 debug "run_rc_command: doit: $*" 1835 _m=$(umask) 1836 ${_umask:+umask ${_umask}} 1837 eval "$@" 1838 _return=$? 1839 umask ${_m} 1840 1841 # If command failed and force isn't set, request exit. 1842 if [ $_return -ne 0 ] && [ -z "$rc_force" ]; then 1843 return 1 1844 fi 1845 1846 return 0 1847} 1848 1849_run_rc_notrunning() 1850{ 1851 local _pidmsg 1852 1853 if [ -n "$pidfile" ]; then 1854 _pidmsg=" (check $pidfile)." 1855 else 1856 _pidmsg= 1857 fi 1858 echo 1>&2 "${name} not running?${_pidmsg}" 1859} 1860 1861_run_rc_killcmd() 1862{ 1863 local _cmd 1864 1865 _cmd="kill -$1 $rc_pid" 1866 if [ -n "$_user" ]; then 1867 _cmd="su -m ${_user} -c 'sh -c \"${_cmd}\"'" 1868 fi 1869 if checkyesno ${name}_svcj && [ "${_rc_svcj}" != jailing ]; then 1870 _cmd="/usr/sbin/jexec svcj-${name} ${_cmd}" 1871 fi 1872 echo "$_cmd" 1873} 1874 1875# 1876# run_rc_script file arg 1877# Start the script `file' with `arg', and correctly handle the 1878# return value from the script. 1879# If `file' ends with `.sh' and lives in /etc/rc.d, ignore it as it's 1880# an old-style startup file. 1881# If `file' appears to be a backup or scratch file, ignore it. 1882# Otherwise if it is executable run as a child process. 1883# 1884run_rc_script() 1885{ 1886 _file=$1 1887 _arg=$2 1888 if [ -z "$_file" -o -z "$_arg" ]; then 1889 err 3 'USAGE: run_rc_script file arg' 1890 fi 1891 1892 unset name command command_args command_interpreter \ 1893 extra_commands pidfile procname \ 1894 rcvar rcvars rcvars_obsolete required_dirs required_files \ 1895 required_vars 1896 eval unset ${_arg}_cmd ${_arg}_precmd ${_arg}_postcmd 1897 1898 rc_trace 0 "$_file $_arg" 1899 # don't use it if we don't trust it 1900 is_verified $_file || return 1901 1902 rc_service="$_file" 1903 case "$_file" in 1904 /etc/rc.d/*.sh) # no longer allowed in the base 1905 warn "Ignoring old-style startup script $_file" 1906 ;; 1907 *[~#]|*.OLD|*.bak|*.orig|*,v) # scratch file; skip 1908 warn "Ignoring scratch file $_file" 1909 ;; 1910 *) # run in subshell 1911 if [ -x $_file ]; then 1912 DebugOn $_file $_file:$_arg rc:${_file##*/} rc:${_file##*/}:$_arg ${_file##*/} ${_file##*/}:$_arg 1913 1914 if [ -n "$rc_boottrace" ]; then 1915 boottrace_fn "$_file" "$_arg" 1916 else 1917 ( trap "echo Script $_file interrupted >&2 ; kill -QUIT $$" 3 1918 trap "echo Script $_file interrupted >&2 ; exit 1" 2 1919 trap "echo Script $_file running >&2" 29 1920 set $_arg; . $_file ) 1921 fi 1922 DebugOff rc=$? $_file $_file:$_arg rc:${_file##*/} rc:${_file##*/}:$_arg ${_file##*/} ${_file##*/}:$_arg 1923 fi 1924 ;; 1925 esac 1926} 1927 1928# 1929# run_rc_scripts [options] file [...] 1930# 1931# Call `run_rc_script' for each "file" unless already listed in 1932# $_rc_elem_done. 1933# 1934# Options: 1935# 1936# --arg "arg" 1937# Pass "arg" to `run_rc_script' default is $_boot. 1938# 1939# --break "marker" 1940# If any "file" matches "marker" stop processing. 1941# 1942_rc_elem_done= 1943run_rc_scripts() 1944{ 1945 local _arg=${_boot} 1946 local _rc_elem 1947 local _rc_breaks= 1948 1949 while :; do 1950 case "$1" in 1951 --arg) 1952 _arg="$2" 1953 shift 2 1954 ;; 1955 --break) 1956 _rc_breaks="$_rc_breaks $2" 1957 shift 2 1958 ;; 1959 *) 1960 break 1961 ;; 1962 esac 1963 done 1964 for _rc_elem in "$@"; do 1965 : _rc_elem=$_rc_elem 1966 case " $_rc_elem_done " in 1967 *" $_rc_elem "*) 1968 continue 1969 ;; 1970 esac 1971 run_rc_script ${_rc_elem} ${_arg} 1972 _rc_elem_done="$_rc_elem_done $_rc_elem" 1973 case " $_rc_breaks " in 1974 *" ${_rc_elem##*/} "*) 1975 break 1976 ;; 1977 esac 1978 done 1979} 1980 1981boottrace_fn() 1982{ 1983 local _file _arg 1984 _file=$1 1985 _arg=$2 1986 1987 _boot="${_boot}" rc_fast="${rc_fast}" autoboot="${autoboot}" \ 1988 $boottrace_cmd "$_file" "$_arg" 1989} 1990 1991# 1992# load_rc_config [service] 1993# Source in the configuration file(s) for a given service. 1994# If no service is specified, only the global configuration 1995# file(s) will be loaded. 1996# 1997load_rc_config() 1998{ 1999 local _name _rcvar_val _var _defval _v _msg _new _d _dot 2000 _name=$1 2001 _dot=${load_rc_config_reader:-dot} 2002 2003 case "$_dot" in 2004 dot|[sv]dot) 2005 ;; 2006 *) warn "Ignoring invalid load_rc_config_reader" 2007 _dot=dot 2008 ;; 2009 esac 2010 case "$1" in 2011 -s|--safe) 2012 _dot=sdot 2013 _name=$2 2014 shift 2015 ;; 2016 -v|--verify) 2017 _dot=vdot 2018 _name=$2 2019 shift 2020 ;; 2021 esac 2022 2023 DebugOn rc:$_name $_name 2024 2025 if ${_rc_conf_loaded:-false}; then 2026 : 2027 else 2028 if [ -r /etc/defaults/rc.conf ]; then 2029 debug "Sourcing /etc/defaults/rc.conf" 2030 $_dot /etc/defaults/rc.conf 2031 source_rc_confs 2032 elif [ -r /etc/rc.conf ]; then 2033 debug "Sourcing /etc/rc.conf (/etc/defaults/rc.conf doesn't exist)." 2034 $_dot /etc/rc.conf 2035 fi 2036 _rc_conf_loaded=true 2037 fi 2038 2039 # If a service name was specified, attempt to load 2040 # service-specific configuration 2041 if [ -n "$_name" ] ; then 2042 _loaded_services="${_loaded_services} ${_name}" 2043 for _d in /etc ${local_startup}; do 2044 _d=${_d%/rc.d} 2045 if [ -f ${_d}/rc.conf.d/"$_name" ]; then 2046 debug "Sourcing ${_d}/rc.conf.d/$_name" 2047 $_dot ${_d}/rc.conf.d/"$_name" 2048 elif [ -d ${_d}/rc.conf.d/"$_name" ] ; then 2049 local _rc 2050 for _rc in ${_d}/rc.conf.d/"$_name"/* ; do 2051 if [ -f "$_rc" ] ; then 2052 debug "Sourcing $_rc" 2053 $_dot "$_rc" 2054 fi 2055 done 2056 fi 2057 done 2058 fi 2059 2060 # Set defaults if defined. 2061 for _var in $rcvar $rcvars; do 2062 eval _defval=\$${_var}_defval 2063 if [ -n "$_defval" ]; then 2064 eval : \${$_var:=\$${_var}_defval} 2065 fi 2066 done 2067 2068 # check obsolete rc.conf variables 2069 for _var in $rcvars_obsolete; do 2070 eval _v=\$$_var 2071 eval _msg=\$${_var}_obsolete_msg 2072 eval _new=\$${_var}_newvar 2073 case $_v in 2074 "") 2075 ;; 2076 *) 2077 if [ -z "$_new" ]; then 2078 _msg="Ignored." 2079 else 2080 eval $_new=\"\$$_var\" 2081 if [ -z "$_msg" ]; then 2082 _msg="Use \$$_new instead." 2083 fi 2084 fi 2085 warn "\$$_var is obsolete. $_msg" 2086 ;; 2087 esac 2088 done 2089} 2090 2091# 2092# load_rc_config_var name var 2093# Read the rc.conf(5) var for name and set in the 2094# current shell, using load_rc_config in a subshell to prevent 2095# unwanted side effects from other variable assignments. 2096# 2097load_rc_config_var() 2098{ 2099 if [ $# -ne 2 ]; then 2100 err 3 'USAGE: load_rc_config_var name var' 2101 fi 2102 eval $(eval '( 2103 load_rc_config '$1' >/dev/null; 2104 if [ -n "${'$2'}" -o "${'$2'-UNSET}" != "UNSET" ]; then 2105 echo '$2'=\'\''${'$2'}\'\''; 2106 fi 2107 )' ) 2108} 2109 2110# 2111# rc_usage commands 2112# Print a usage string for $0, with `commands' being a list of 2113# valid commands. 2114# 2115rc_usage() 2116{ 2117 echo -n 1>&2 "Usage: $0 [fast|force|one|quiet](" 2118 2119 _sep= 2120 for _elem; do 2121 echo -n 1>&2 "$_sep$_elem" 2122 _sep="|" 2123 done 2124 echo 1>&2 ")" 2125 exit 1 2126} 2127 2128# 2129# err exitval message 2130# Display message to stderr and log to the syslog, and exit with exitval. 2131# 2132err() 2133{ 2134 exitval=$1 2135 shift 2136 2137 if [ -x /usr/bin/logger ]; then 2138 logger "$0: ERROR: $*" 2139 fi 2140 echo 1>&2 "$0: ERROR: $*" 2141 exit $exitval 2142} 2143 2144# 2145# warn message 2146# Display message to stderr and log to the syslog. 2147# 2148warn() 2149{ 2150 if [ -x /usr/bin/logger ]; then 2151 logger "$0: WARNING: $*" 2152 fi 2153 echo 1>&2 "$0: WARNING: $*" 2154} 2155 2156# 2157# info message 2158# Display informational message to stdout and log to syslog. 2159# 2160info() 2161{ 2162 case ${rc_info} in 2163 [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1) 2164 if [ -x /usr/bin/logger ]; then 2165 logger "$0: INFO: $*" 2166 fi 2167 echo "$0: INFO: $*" 2168 ;; 2169 esac 2170} 2171 2172# 2173# debug message 2174# If debugging is enabled in rc.conf output message to stderr. 2175# BEWARE that you don't call any subroutine that itself calls this 2176# function. 2177# 2178debug() 2179{ 2180 case ${rc_debug} in 2181 [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1) 2182 if [ -x /usr/bin/logger ]; then 2183 logger "$0: DEBUG: $*" 2184 fi 2185 echo 1>&2 "$0: DEBUG: $*" 2186 ;; 2187 esac 2188} 2189 2190# 2191# backup_file action file cur backup 2192# Make a backup copy of `file' into `cur', and save the previous 2193# version of `cur' as `backup'. 2194# 2195# The `action' keyword can be one of the following: 2196# 2197# add `file' is now being backed up (and is possibly 2198# being reentered into the backups system). `cur' 2199# is created. 2200# 2201# update `file' has changed and needs to be backed up. 2202# If `cur' exists, it is copied to `back' 2203# and then `file' is copied to `cur'. 2204# 2205# remove `file' is no longer being tracked by the backups 2206# system. `cur' is moved `back'. 2207# 2208# 2209backup_file() 2210{ 2211 _action=$1 2212 _file=$2 2213 _cur=$3 2214 _back=$4 2215 2216 case $_action in 2217 add|update) 2218 if [ -f $_cur ]; then 2219 cp -p $_cur $_back 2220 fi 2221 cp -p $_file $_cur 2222 chown root:wheel $_cur 2223 ;; 2224 remove) 2225 mv -f $_cur $_back 2226 ;; 2227 esac 2228} 2229 2230# make_symlink src link 2231# Make a symbolic link 'link' to src from basedir. If the 2232# directory in which link is to be created does not exist 2233# a warning will be displayed and an error will be returned. 2234# Returns 0 on success, 1 otherwise. 2235# 2236make_symlink() 2237{ 2238 local src link linkdir _me 2239 src="$1" 2240 link="$2" 2241 linkdir="`dirname $link`" 2242 _me="make_symlink()" 2243 2244 if [ -z "$src" -o -z "$link" ]; then 2245 warn "$_me: requires two arguments." 2246 return 1 2247 fi 2248 if [ ! -d "$linkdir" ]; then 2249 warn "$_me: the directory $linkdir does not exist." 2250 return 1 2251 fi 2252 if ! ln -sf $src $link; then 2253 warn "$_me: unable to make a symbolic link from $link to $src" 2254 return 1 2255 fi 2256 return 0 2257} 2258 2259# devfs_rulesets_from_file file 2260# Reads a set of devfs commands from file, and creates 2261# the specified rulesets with their rules. Returns non-zero 2262# if there was an error. 2263# 2264devfs_rulesets_from_file() 2265{ 2266 local file _err _me _opts 2267 file="$1" 2268 _me="devfs_rulesets_from_file" 2269 _err=0 2270 2271 if [ -z "$file" ]; then 2272 warn "$_me: you must specify a file" 2273 return 1 2274 fi 2275 if [ ! -e "$file" ]; then 2276 debug "$_me: no such file ($file)" 2277 return 0 2278 fi 2279 2280 # Disable globbing so that the rule patterns are not expanded 2281 # by accident with matching filesystem entries. 2282 _opts=$-; set -f 2283 2284 debug "reading rulesets from file ($file)" 2285 { while read line 2286 do 2287 case $line in 2288 \#*) 2289 continue 2290 ;; 2291 \[*\]*) 2292 rulenum=`expr "$line" : "\[.*=\([0-9]*\)\]"` 2293 if [ -z "$rulenum" ]; then 2294 warn "$_me: cannot extract rule number ($line)" 2295 _err=1 2296 break 2297 fi 2298 rulename=`expr "$line" : "\[\(.*\)=[0-9]*\]"` 2299 if [ -z "$rulename" ]; then 2300 warn "$_me: cannot extract rule name ($line)" 2301 _err=1 2302 break; 2303 fi 2304 eval $rulename=\$rulenum 2305 debug "found ruleset: $rulename=$rulenum" 2306 if ! /sbin/devfs rule -s $rulenum delset; then 2307 _err=1 2308 break 2309 fi 2310 ;; 2311 *) 2312 rulecmd="${line%%"\#*"}" 2313 # evaluate the command incase it includes 2314 # other rules 2315 if [ -n "$rulecmd" ]; then 2316 debug "adding rule ($rulecmd)" 2317 if ! eval /sbin/devfs rule -s $rulenum $rulecmd 2318 then 2319 _err=1 2320 break 2321 fi 2322 fi 2323 ;; 2324 esac 2325 if [ $_err -ne 0 ]; then 2326 debug "error in $_me" 2327 break 2328 fi 2329 done } < $file 2330 case $_opts in *f*) ;; *) set +f ;; esac 2331 return $_err 2332} 2333 2334# devfs_init_rulesets 2335# Initializes rulesets from configuration files. Returns 2336# non-zero if there was an error. 2337# 2338devfs_init_rulesets() 2339{ 2340 local file _me 2341 _me="devfs_init_rulesets" 2342 2343 # Go through this only once 2344 if [ -n "$devfs_rulesets_init" ]; then 2345 debug "$_me: devfs rulesets already initialized" 2346 return 2347 fi 2348 for file in $devfs_rulesets; do 2349 if ! devfs_rulesets_from_file $file; then 2350 warn "$_me: could not read rules from $file" 2351 return 1 2352 fi 2353 done 2354 devfs_rulesets_init=1 2355 debug "$_me: devfs rulesets initialized" 2356 return 0 2357} 2358 2359# devfs_set_ruleset ruleset [dir] 2360# Sets the default ruleset of dir to ruleset. The ruleset argument 2361# must be a ruleset name as specified in devfs.rules(5) file. 2362# Returns non-zero if it could not set it successfully. 2363# 2364devfs_set_ruleset() 2365{ 2366 local devdir rs _me 2367 [ -n "$1" ] && eval rs=\$$1 || rs= 2368 [ -n "$2" ] && devdir="-m "$2"" || devdir= 2369 _me="devfs_set_ruleset" 2370 2371 if [ -z "$rs" ]; then 2372 warn "$_me: you must specify a ruleset number" 2373 return 1 2374 fi 2375 debug "$_me: setting ruleset ($rs) on mount-point (${devdir#-m })" 2376 if ! /sbin/devfs $devdir ruleset $rs; then 2377 warn "$_me: unable to set ruleset $rs to ${devdir#-m }" 2378 return 1 2379 fi 2380 return 0 2381} 2382 2383# devfs_apply_ruleset ruleset [dir] 2384# Apply ruleset number $ruleset to the devfs mountpoint $dir. 2385# The ruleset argument must be a ruleset name as specified 2386# in a devfs.rules(5) file. Returns 0 on success or non-zero 2387# if it could not apply the ruleset. 2388# 2389devfs_apply_ruleset() 2390{ 2391 local devdir rs _me 2392 [ -n "$1" ] && eval rs=\$$1 || rs= 2393 [ -n "$2" ] && devdir="-m "$2"" || devdir= 2394 _me="devfs_apply_ruleset" 2395 2396 if [ -z "$rs" ]; then 2397 warn "$_me: you must specify a ruleset" 2398 return 1 2399 fi 2400 debug "$_me: applying ruleset ($rs) to mount-point (${devdir#-m })" 2401 if ! /sbin/devfs $devdir rule -s $rs applyset; then 2402 warn "$_me: unable to apply ruleset $rs to ${devdir#-m }" 2403 return 1 2404 fi 2405 return 0 2406} 2407 2408# devfs_domount dir [ruleset] 2409# Mount devfs on dir. If ruleset is specified it is set 2410# on the mount-point. It must also be a ruleset name as specified 2411# in a devfs.rules(5) file. Returns 0 on success. 2412# 2413devfs_domount() 2414{ 2415 local devdir rs _me 2416 devdir="$1" 2417 [ -n "$2" ] && rs=$2 || rs= 2418 _me="devfs_domount()" 2419 2420 if [ -z "$devdir" ]; then 2421 warn "$_me: you must specify a mount-point" 2422 return 1 2423 fi 2424 debug "$_me: mount-point is ($devdir), ruleset is ($rs)" 2425 if ! mount -t devfs dev "$devdir"; then 2426 warn "$_me: Unable to mount devfs on $devdir" 2427 return 1 2428 fi 2429 if [ -n "$rs" ]; then 2430 devfs_init_rulesets 2431 devfs_set_ruleset $rs $devdir 2432 devfs -m $devdir rule applyset 2433 fi 2434 return 0 2435} 2436 2437# Provide a function for normalizing the mounting of memory 2438# filesystems. This should allow the rest of the code here to remain 2439# as close as possible between 5-current and 4-stable. 2440# $1 = size 2441# $2 = mount point 2442# $3 = (optional) extra mdmfs flags 2443mount_md() 2444{ 2445 if [ -n "$3" ]; then 2446 flags="$3" 2447 fi 2448 /sbin/mdmfs $flags -s $1 ${mfs_type} $2 2449} 2450 2451# Code common to scripts that need to load a kernel module 2452# if it isn't in the kernel yet. Syntax: 2453# load_kld [-e regex | -m module] file 2454# where -e or -m chooses the way to check if the module 2455# is already loaded: 2456# -e greps the output from `kldstat -v', 2457# -m uses `kldstat -m module'. 2458# The default way is as though `-m file` was specified. 2459load_kld() 2460{ 2461 local _loaded _mod _opt _re _x 2462 2463 _x=0 2464 while getopts "e:m:" _opt; do 2465 case "$_opt" in 2466 e) _re="$OPTARG" ;; 2467 m) _mod="$OPTARG" ;; 2468 *) _x=999 ;; 2469 esac 2470 _x=$((_x + 1)) 2471 done 2472 shift $(($OPTIND - 1)) 2473 if [ $# -ne 1 ] || [ $_x -gt 1 ]; then 2474 err 3 'USAGE: load_kld [-e regex | -m module] file' 2475 fi 2476 _loaded=false 2477 if [ -n "$_re" ]; then 2478 if kldstat -v | egrep -q -e "$_re"; then 2479 _loaded=true 2480 fi 2481 elif kldstat -q -m "${_mod:-$1}"; then 2482 _loaded=true 2483 elif kldstat -q -n "$1"; then 2484 _loaded=true 2485 fi 2486 if ! $_loaded; then 2487 if ! kldload "$1"; then 2488 warn "Unable to load kernel module $1" 2489 return 1 2490 else 2491 info "$1 kernel module loaded." 2492 if [ -f "/etc/sysctl.kld.d/$1.conf" ]; then 2493 sysctl -f "/etc/sysctl.kld.d/$1.conf" 2494 fi 2495 fi 2496 else 2497 debug "load_kld: $1 kernel module already loaded." 2498 fi 2499 return 0 2500} 2501 2502# ltr str src dst [var] 2503# Change every $src in $str to $dst. 2504# Useful when /usr is not yet mounted and we cannot use tr(1), sed(1) nor 2505# awk(1). If var is non-NULL, set it to the result. 2506ltr() 2507{ 2508 local _str _src _dst _out _com _var 2509 _str="$1" 2510 _src="$2" 2511 _dst="$3" 2512 _var="$4" 2513 _out="" 2514 2515 local IFS="${_src}" 2516 for _com in ${_str}; do 2517 if [ -z "${_out}" ]; then 2518 _out="${_com}" 2519 else 2520 _out="${_out}${_dst}${_com}" 2521 fi 2522 done 2523 if [ -n "${_var}" ]; then 2524 setvar "${_var}" "${_out}" 2525 else 2526 echo "${_out}" 2527 fi 2528} 2529 2530# Creates a list of providers for GELI encryption. 2531geli_make_list() 2532{ 2533 local devices devices2 2534 local provider mountpoint type options rest 2535 2536 # Create list of GELI providers from fstab. 2537 while read provider mountpoint type options rest ; do 2538 case ":${options}" in 2539 :*noauto*) 2540 noauto=yes 2541 ;; 2542 *) 2543 noauto=no 2544 ;; 2545 esac 2546 2547 case ":${provider}" in 2548 :#*) 2549 continue 2550 ;; 2551 *.eli) 2552 # Skip swap devices. 2553 if [ "${type}" = "swap" -o "${options}" = "sw" -o "${noauto}" = "yes" ]; then 2554 continue 2555 fi 2556 devices="${devices} ${provider}" 2557 ;; 2558 esac 2559 done < /etc/fstab 2560 2561 # Append providers from geli_devices. 2562 devices="${devices} ${geli_devices}" 2563 2564 for provider in ${devices}; do 2565 provider=${provider%.eli} 2566 provider=${provider#/dev/} 2567 devices2="${devices2} ${provider}" 2568 done 2569 2570 echo ${devices2} 2571} 2572 2573# Originally, root mount hold had to be released before mounting 2574# the root filesystem. This delayed the boot, so it was changed 2575# to only wait if the root device isn't readily available. This 2576# can result in rc scripts executing before all the devices - such 2577# as graid(8), or USB disks - can be accessed. This function can 2578# be used to explicitly wait for root mount holds to be released. 2579root_hold_wait() 2580{ 2581 local wait waited holders 2582 2583 waited=0 2584 while true; do 2585 holders="$(sysctl -n vfs.root_mount_hold)" 2586 if [ -z "${holders}" ]; then 2587 break; 2588 fi 2589 if [ ${waited} -eq 0 ]; then 2590 echo -n "Waiting ${root_hold_delay}s" \ 2591 "for the root mount holders: ${holders}" 2592 else 2593 echo -n . 2594 fi 2595 if [ ${waited} -ge ${root_hold_delay} ]; then 2596 echo 2597 break 2598 fi 2599 sleep 1 2600 waited=$(($waited + 1)) 2601 done 2602} 2603 2604# Find scripts in local_startup directories that use the old syntax 2605# 2606find_local_scripts_old() { 2607 zlist='' 2608 slist='' 2609 for dir in ${local_startup}; do 2610 if [ -d "${dir}" ]; then 2611 for file in ${dir}/[0-9]*.sh; do 2612 grep '^# PROVIDE:' $file >/dev/null 2>&1 && 2613 continue 2614 zlist="$zlist $file" 2615 done 2616 for file in ${dir}/[!0-9]*.sh; do 2617 grep '^# PROVIDE:' $file >/dev/null 2>&1 && 2618 continue 2619 slist="$slist $file" 2620 done 2621 fi 2622 done 2623} 2624 2625find_local_scripts_new() { 2626 local_rc='' 2627 for dir in ${local_startup}; do 2628 if [ -d "${dir}" ]; then 2629 for file in `grep -l '^# PROVIDE:' ${dir}/* 2>/dev/null`; do 2630 case "$file" in 2631 *.sample|*.pkgsave) ;; 2632 *) if [ -x "$file" ]; then 2633 local_rc="${local_rc} ${file}" 2634 fi 2635 ;; 2636 esac 2637 done 2638 fi 2639 done 2640} 2641 2642find_system_scripts() { 2643 system_rc='' 2644 for file in /etc/rc.d/*; do 2645 case "${file##*/}" in 2646 *.pkgsave) ;; 2647 *) if [ -x "$file" ]; then 2648 system_rc="${system_rc} ${file}" 2649 fi 2650 ;; 2651 esac 2652 done 2653} 2654 2655# check_required_{before|after} command 2656# Check for things required by the command before and after its precmd, 2657# respectively. The two separate functions are needed because some 2658# conditions should prevent precmd from being run while other things 2659# depend on precmd having already been run. 2660# 2661check_required_before() 2662{ 2663 local _f 2664 2665 case "$1" in 2666 start) 2667 for _f in $required_vars; do 2668 if ! checkyesno $_f; then 2669 warn "\$${_f} is not enabled." 2670 if [ -z "$rc_force" ]; then 2671 return 1 2672 fi 2673 fi 2674 done 2675 2676 for _f in $required_dirs; do 2677 if [ ! -d "${_f}/." ]; then 2678 warn "${_f} is not a directory." 2679 if [ -z "$rc_force" ]; then 2680 return 1 2681 fi 2682 fi 2683 done 2684 2685 for _f in $required_files; do 2686 if [ ! -r "${_f}" ]; then 2687 warn "${_f} is not readable." 2688 if [ -z "$rc_force" ]; then 2689 return 1 2690 fi 2691 fi 2692 done 2693 ;; 2694 esac 2695 2696 return 0 2697} 2698 2699check_required_after() 2700{ 2701 local _f _args 2702 2703 case "$1" in 2704 start) 2705 for _f in $required_modules; do 2706 case "${_f}" in 2707 *~*) _args="-e ${_f#*~} ${_f%%~*}" ;; 2708 *:*) _args="-m ${_f#*:} ${_f%%:*}" ;; 2709 *) _args="${_f}" ;; 2710 esac 2711 if ! load_kld ${_args}; then 2712 if [ -z "$rc_force" ]; then 2713 return 1 2714 fi 2715 fi 2716 done 2717 ;; 2718 esac 2719 2720 return 0 2721} 2722 2723# check_jail mib 2724# Return true if security.jail.$mib exists and is set to 1. 2725 2726check_jail() 2727{ 2728 local _mib _v 2729 2730 _mib=$1 2731 if _v=$(${SYSCTL_N} "security.jail.$_mib" 2> /dev/null); then 2732 case $_v in 2733 1) return 0;; 2734 esac 2735 fi 2736 return 1 2737} 2738 2739# check_kern_features mib 2740# Return existence of kern.features.* sysctl MIB as true or 2741# false. The result will be cached in $_rc_cache_kern_features_ 2742# namespace. "0" means the kern.features.X exists. 2743 2744check_kern_features() 2745{ 2746 local _v 2747 2748 [ -n "$1" ] || return 1; 2749 eval _v=\$_rc_cache_kern_features_$1 2750 [ -n "$_v" ] && return "$_v"; 2751 2752 if ${SYSCTL_N} kern.features.$1 > /dev/null 2>&1; then 2753 eval _rc_cache_kern_features_$1=0 2754 return 0 2755 else 2756 eval _rc_cache_kern_features_$1=1 2757 return 1 2758 fi 2759} 2760 2761# check_namevarlist var 2762# Return "0" if ${name}_var is reserved in rc.subr. 2763 2764_rc_namevarlist="program chroot chdir env flags fib nice user group groups prepend setup" 2765check_namevarlist() 2766{ 2767 local _v 2768 2769 for _v in $_rc_namevarlist; do 2770 case $1 in 2771 $_v) return 0 ;; 2772 esac 2773 done 2774 2775 return 1 2776} 2777 2778# _echoonce var msg mode 2779# mode=0: Echo $msg if ${$var} is empty. 2780# After doing echo, a string is set to ${$var}. 2781# 2782# mode=1: Echo $msg if ${$var} is a string with non-zero length. 2783# 2784_echoonce() 2785{ 2786 local _var _msg _mode 2787 eval _var=\$$1 2788 _msg=$2 2789 _mode=$3 2790 2791 case $_mode in 2792 1) [ -n "$_var" ] && echo "$_msg" ;; 2793 *) [ -z "$_var" ] && echo -n "$_msg" && eval "$1=finished" ;; 2794 esac 2795} 2796 2797# _find_rcvar var 2798# Find the rc.conf file (other than /etc/defaults/rc.conf) that sets $var. 2799_find_rcvar() 2800{ 2801 local _var _dir _files 2802 2803 [ -n "$1" ] || return 1 2804 _var="$1"; shift 2805 2806 _files="/etc/rc.conf" 2807 for _dir in /etc ${local_startup}; do 2808 for _name in $_loaded_services; do 2809 _files="${_dir%/rc.d}/rc.conf.d/${_name} ${_files}" 2810 done 2811 done 2812 2813 /usr/bin/grep 2>/dev/null -rl "^${_var}=" $_files | /usr/bin/head -1 2814} 2815 2816# write_rcvar var value 2817# Add or replace the rc var $var with the value $value. 2818# Look for a current setting of $var in /etc/rc.conf or /etc/rc.conf.d/$name, 2819# and if found, modify it there; otherwise, append to /etc/rc.conf. 2820write_rcvar() 2821{ 2822 local _var _value _file _dir 2823 2824 [ -n "$1" ] || return 1 2825 _var="$1"; shift 2826 [ -n "$1" ] || return 1 2827 _value="$1"; shift 2828 2829 _file="$(_find_rcvar "$_var")" 2830 if [ -n "$_file" ]; then 2831 local _=$'\01' 2832 /usr/bin/sed -i '' "s${_}^${_var}=.*${_}${_var}=\"$_value\"${_}" "$_file" 2833 echo $_file 2834 return 2835 fi 2836 2837 for _dir in /etc ${local_startup}; do 2838 _file="${_dir%/rc.d}/rc.conf.d/${name}" 2839 if [ -f "$_file" ]; then 2840 echo "${_var}=\"${_value}\"" >>"$_file" 2841 echo "$_file" 2842 return 2843 fi 2844 done 2845 2846 echo "${_var}=\"${_value}\"" >>/etc/rc.conf 2847 echo "/etc/rc.conf" 2848} 2849 2850# delete_rcvar var 2851# Remove the rc var $var. 2852# Look for a current setting of $var in /etc/rc.conf or /etc/rc.conf.d/$name, 2853# and if found, remove it. If service_delete_empty is enabled, and the 2854# resulting file is empty, also delete the file. 2855delete_rcvar() 2856{ 2857 local _var _files 2858 2859 [ -n "$1" ] || return 1 2860 _var="$1"; shift 2861 2862 _file="$(_find_rcvar "$_var")" 2863 if [ -n "$_file" ]; then 2864 /usr/bin/sed -i '' "/^${_var}=/d" "$_file" 2865 echo "$_var deleted in $_file" 2866 2867 if checkyesno service_delete_empty && [ ! -s "$_file" ]; then 2868 /bin/rm -f "$_file" 2869 echo "Empty file $_file removed" 2870 fi 2871 fi 2872} 2873 2874# If the loader env variable rc.debug is set, turn on debugging. rc.conf will 2875# still override this, but /etc/defaults/rc.conf can't unconditionally set this 2876# since it would undo what we've done here. 2877if kenv -q rc.debug > /dev/null ; then 2878 rc_debug=YES 2879fi 2880 2881boottrace_cmd=`command -v boottrace` 2882if [ -n "$boottrace_cmd" ] && [ "`${SYSCTL_N} -q kern.boottrace.enabled`" = "1" ]; then 2883 rc_boottrace=YES 2884fi 2885 2886SED=${SED:-$(Exists -x /usr/bin/sed /rescue/sed)} 2887 2888# Allow for local additions and overrides. 2889# Use vdot to ensure the file has not been tampered with. 2890vdot /etc/local.rc.subr 2891 2892# Avoid noise - when we do not have /usr mounted, 2893# and we cannot use safe_dot without sed. 2894if ! have basename; then 2895 basename() 2896 { 2897 local b=${1%$2} 2898 echo ${b##*/} 2899 } 2900 tty() 2901 { 2902 return 0 2903 } 2904 # we cannot use safe_dot without sed 2905 [ -z "$SED" ] && _SAFE_EVAL_SH=: 2906fi 2907# safe_eval.sh provides safe_dot - for untrusted files 2908$_SAFE_EVAL_SH vdot /libexec/safe_eval.sh 2909$_DEBUG_SH vdot /libexec/debug.sh 2910 2911# Ensure we can still operate if debug.sh and 2912# safe_eval.sh are not found. 2913if ! have DebugOn; then 2914 DebugOn() { return 0; } 2915 DebugOff() { 2916 local _rc=0 2917 while : 2918 do 2919 case "$1" in 2920 -[eo]) shift;; # ignore it 2921 rc=*) eval "_$1"; shift;; 2922 *) break;; 2923 esac 2924 done 2925 return $_rc 2926 } 2927fi 2928if ! have safe_dot; then 2929 safe_dot() { dot "$@"; } 2930fi 2931