rc.subr revision 288291
1164640Sflz# $NetBSD: rc.subr,v 1.67 2006/10/07 11:25:15 elad Exp $
298186Sgordon# $FreeBSD: head/etc/rc.subr 288291 2015-09-27 04:03:11Z adrian $
378344Sobrien#
4157473Sflz# Copyright (c) 1997-2004 The NetBSD Foundation, Inc.
578344Sobrien# All rights reserved.
678344Sobrien#
778344Sobrien# This code is derived from software contributed to The NetBSD Foundation
878344Sobrien# by Luke Mewburn.
978344Sobrien#
1078344Sobrien# Redistribution and use in source and binary forms, with or without
1178344Sobrien# modification, are permitted provided that the following conditions
1278344Sobrien# are met:
1378344Sobrien# 1. Redistributions of source code must retain the above copyright
1478344Sobrien#    notice, this list of conditions and the following disclaimer.
1578344Sobrien# 2. Redistributions in binary form must reproduce the above copyright
1678344Sobrien#    notice, this list of conditions and the following disclaimer in the
1778344Sobrien#    documentation and/or other materials provided with the distribution.
1878344Sobrien#
1978344Sobrien# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2078344Sobrien# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2178344Sobrien# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2278344Sobrien# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2378344Sobrien# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2478344Sobrien# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2578344Sobrien# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2678344Sobrien# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2778344Sobrien# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2878344Sobrien# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2978344Sobrien# POSSIBILITY OF SUCH DAMAGE.
3078344Sobrien#
3178344Sobrien# rc.subr
3278344Sobrien#	functions used by various rc scripts
3378344Sobrien#
3478344Sobrien
35169668Smtm: ${RC_PID:=$$}; export RC_PID
36157473Sflz
3778344Sobrien#
3898186Sgordon#	Operating System dependent/independent variables
3998186Sgordon#
4098186Sgordon
41131550Scpercivaif [ -z "${_rc_subr_loaded}" ]; then
42131550Scperciva
43131550Scperciva_rc_subr_loaded="YES"
44131550Scperciva
4598186SgordonSYSCTL="/sbin/sysctl"
4698186SgordonSYSCTL_N="${SYSCTL} -n"
47202988SemasteSYSCTL_W="${SYSCTL}"
48124832SmtmID="/usr/bin/id"
49124832SmtmIDCMD="if [ -x $ID ]; then $ID -un; fi"
50161435SyarPS="/bin/ps -ww"
51161435SyarJID=`$PS -p $$ -o jid=`
5298186Sgordon
5398186Sgordon#
5478344Sobrien#	functions
5578344Sobrien#	---------
5678344Sobrien
57264243Sdteske# list_vars pattern
58264243Sdteske#	List vars matching pattern.
59264243Sdteske# 
60264243Sdteskelist_vars()
61264243Sdteske{
62264243Sdteske	set | { while read LINE; do
63264243Sdteske		var="${LINE%%=*}"
64264243Sdteske		case "$var" in
65264243Sdteske		"$LINE"|*[!a-zA-Z0-9_]*) continue ;;
66264243Sdteske		$1) echo $var
67264243Sdteske		esac
68264243Sdteske	done; }
69264243Sdteske}
70264243Sdteske
71272393Shrs# set_rcvar [var] [defval] [desc]
72272393Shrs#
73272393Shrs#	Echo or define a rc.conf(5) variable name.  Global variable
74272393Shrs#	$rcvars is used.
75272393Shrs#
76272393Shrs#	If no argument is specified, echo "${name}_enable".
77272393Shrs#
78272393Shrs#	If only a var is specified, echo "${var}_enable".
79272393Shrs#
80272393Shrs#	If var and defval are specified, the ${var} is defined as
81272393Shrs#	rc.conf(5) variable and the default value is ${defvar}.  An
82272393Shrs#	optional argument $desc can also be specified to add a
83272393Shrs#	description for that.
84272393Shrs#
85272393Shrsset_rcvar()
86272393Shrs{
87272393Shrs	local _var
88272393Shrs
89272393Shrs	case $# in
90272393Shrs	0)	echo ${name}_enable ;;
91272393Shrs	1)	echo ${1}_enable ;;
92272393Shrs	*)
93272393Shrs		debug "set_rcvar: \$$1=$2 is added" \
94272393Shrs		    " as a rc.conf(5) variable."
95272393Shrs		_var=$1
96272393Shrs		rcvars="${rcvars# } $_var"
97272393Shrs		eval ${_var}_defval=\"$2\"
98272393Shrs		shift 2
99272393Shrs		eval ${_var}_desc=\"$*\"
100272393Shrs	;;
101272393Shrs	esac
102272393Shrs}
103272393Shrs
104197144Shrs# set_rcvar_obsolete oldvar [newvar] [msg]
105197144Shrs#	Define obsolete variable.
106197144Shrs#	Global variable $rcvars_obsolete is used.
10798186Sgordon#
108197144Shrsset_rcvar_obsolete()
109197144Shrs{
110197144Shrs	local _var
111197144Shrs	_var=$1
112272393Shrs	debug "set_rcvar_obsolete: \$$1(old) -> \$$2(new) is defined"
113197144Shrs
114197144Shrs	rcvars_obsolete="${rcvars_obsolete# } $1"
115197144Shrs	eval ${1}_newvar=\"$2\"
116197144Shrs	shift 2
117197144Shrs	eval ${_var}_obsolete_msg=\"$*\"
118197144Shrs}
119197144Shrs
120197144Shrs#
121231667Sdougb# force_depend script [rcvar]
12298186Sgordon#	Force a service to start. Intended for use by services
123231667Sdougb#	to resolve dependency issues.
12498186Sgordon#	$1 - filename of script, in /etc/rc.d, to run
125231667Sdougb#	$2 - name of the script's rcvar (minus the _enable)
12698186Sgordon#
12798186Sgordonforce_depend()
12898186Sgordon{
129231667Sdougb	local _depend _dep_rcvar
130231667Sdougb
13198186Sgordon	_depend="$1"
132231667Sdougb	_dep_rcvar="${2:-$1}_enable"
13398186Sgordon
134231667Sdougb	[ -n "$rc_fast" ] && ! checkyesno always_force_depends &&
135231667Sdougb	    checkyesno $_dep_rcvar && return 0
136231667Sdougb
137231667Sdougb	/etc/rc.d/${_depend} forcestatus >/dev/null 2>&1 && return 0
138231667Sdougb
13998186Sgordon	info "${name} depends on ${_depend}, which will be forced to start."
140146490Sschweikh	if ! /etc/rc.d/${_depend} forcestart; then
14198186Sgordon		warn "Unable to force ${_depend}. It may already be running."
14298186Sgordon		return 1
14398186Sgordon	fi
14498186Sgordon}
14598186Sgordon
14698186Sgordon#
14778344Sobrien# checkyesno var
14878344Sobrien#	Test $1 variable, and warn if not set to YES or NO.
14978344Sobrien#	Return 0 if it's "yes" (et al), nonzero otherwise.
15078344Sobrien#
15178344Sobriencheckyesno()
15278344Sobrien{
15378344Sobrien	eval _value=\$${1}
15498186Sgordon	debug "checkyesno: $1 is set to $_value."
15578344Sobrien	case $_value in
15678344Sobrien
15778344Sobrien		#	"yes", "true", "on", or "1"
15878344Sobrien	[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
15978344Sobrien		return 0
16078344Sobrien		;;
16178344Sobrien
16278344Sobrien		#	"no", "false", "off", or "0"
16378344Sobrien	[Nn][Oo]|[Ff][Aa][Ll][Ss][Ee]|[Oo][Ff][Ff]|0)
16478344Sobrien		return 1
16578344Sobrien		;;
16678344Sobrien	*)
167229822Sdougb		warn "\$${1} is not set properly - see rc.conf(5)."
16878344Sobrien		return 1
16978344Sobrien		;;
17078344Sobrien	esac
17178344Sobrien}
17278344Sobrien
173157473Sflz#
17498186Sgordon# reverse_list list
17598186Sgordon#	print the list in reverse order
17678344Sobrien#
17798186Sgordonreverse_list()
17898186Sgordon{
17998186Sgordon	_revlist=
180126286Smtm	for _revfile; do
18198186Sgordon		_revlist="$_revfile $_revlist"
18298186Sgordon	done
18398186Sgordon	echo $_revlist
18498186Sgordon}
18598186Sgordon
186169668Smtm# stop_boot always
187169668Smtm#	If booting directly to multiuser or $always is enabled,
188169668Smtm#	send SIGTERM to the parent (/etc/rc) to abort the boot.
189169668Smtm#	Otherwise just exit.
19078344Sobrien#
191169668Smtmstop_boot()
192169668Smtm{
193169668Smtm	local always
194169668Smtm
195178776Smaxim	case $1 in
196178776Smaxim		#	"yes", "true", "on", or "1"
197178770Smtm        [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
198169668Smtm		always=true
199178770Smtm		;;
200178770Smtm	*)
201169668Smtm		always=false
202178770Smtm		;;
203178775Smaxim	esac
204169668Smtm	if [ "$autoboot" = yes -o "$always" = true ]; then
205169668Smtm		echo "ERROR: ABORTING BOOT (sending SIGTERM to parent)!"
206169668Smtm		kill -TERM ${RC_PID}
207169668Smtm	fi
208169668Smtm	exit 1
209169668Smtm}
210169668Smtm
211169668Smtm#
21298186Sgordon# mount_critical_filesystems type
21398186Sgordon#	Go through the list of critical filesystems as provided in
21498186Sgordon#	the rc.conf(5) variable $critical_filesystems_${type}, checking
21598186Sgordon#	each one to see if it is mounted, and if it is not, mounting it.
21698186Sgordon#
21778344Sobrienmount_critical_filesystems()
21878344Sobrien{
21998186Sgordon	eval _fslist=\$critical_filesystems_${1}
22078344Sobrien	for _fs in $_fslist; do
22178344Sobrien		mount | (
222126285Smtm			_ismounted=false
22378344Sobrien			while read what _on on _type type; do
22478344Sobrien				if [ $on = $_fs ]; then
225126285Smtm					_ismounted=true
22678344Sobrien				fi
22778344Sobrien			done
228126285Smtm			if $_ismounted; then
229126285Smtm				:
230126285Smtm			else
23178344Sobrien				mount $_fs >/dev/null 2>&1
23278344Sobrien			fi
23398186Sgordon		)
23478344Sobrien	done
23578344Sobrien}
23678344Sobrien
23778344Sobrien#
23898186Sgordon# check_pidfile pidfile procname [interpreter]
23998186Sgordon#	Parses the first line of pidfile for a PID, and ensures
24078344Sobrien#	that the process is running and matches procname.
24198186Sgordon#	Prints the matching PID upon success, nothing otherwise.
24298186Sgordon#	interpreter is optional; see _find_processes() for details.
24378344Sobrien#
24478344Sobriencheck_pidfile()
24578344Sobrien{
24678344Sobrien	_pidfile=$1
24778344Sobrien	_procname=$2
24898186Sgordon	_interpreter=$3
24978344Sobrien	if [ -z "$_pidfile" -o -z "$_procname" ]; then
25098186Sgordon		err 3 'USAGE: check_pidfile pidfile procname [interpreter]'
25178344Sobrien	fi
25278344Sobrien	if [ ! -f $_pidfile ]; then
253131061Smtm		debug "pid file ($_pidfile): not readable."
25478344Sobrien		return
25578344Sobrien	fi
25678344Sobrien	read _pid _junk < $_pidfile
25778344Sobrien	if [ -z "$_pid" ]; then
258139949Skeramida		debug "pid file ($_pidfile): no pid in file."
25978344Sobrien		return
26078344Sobrien	fi
26198186Sgordon	_find_processes $_procname ${_interpreter:-.} '-p '"$_pid"
26278344Sobrien}
26378344Sobrien
26478344Sobrien#
26598186Sgordon# check_process procname [interpreter]
26678344Sobrien#	Ensures that a process (or processes) named procname is running.
26798186Sgordon#	Prints a list of matching PIDs.
26898186Sgordon#	interpreter is optional; see _find_processes() for details.
26978344Sobrien#
27078344Sobriencheck_process()
27178344Sobrien{
27278344Sobrien	_procname=$1
27398186Sgordon	_interpreter=$2
27478344Sobrien	if [ -z "$_procname" ]; then
27598186Sgordon		err 3 'USAGE: check_process procname [interpreter]'
27678344Sobrien	fi
27798186Sgordon	_find_processes $_procname ${_interpreter:-.} '-ax'
27898186Sgordon}
27998186Sgordon
28098186Sgordon#
28198186Sgordon# _find_processes procname interpreter psargs
28298186Sgordon#	Search for procname in the output of ps generated by psargs.
28398186Sgordon#	Prints the PIDs of any matching processes, space separated.
28498186Sgordon#
28598186Sgordon#	If interpreter == ".", check the following variations of procname
28698186Sgordon#	against the first word of each command:
28798186Sgordon#		procname
28898186Sgordon#		`basename procname`
28998186Sgordon#		`basename procname` + ":"
29098186Sgordon#		"(" + `basename procname` + ")"
291155719Sceri#		"[" + `basename procname` + "]"
29298186Sgordon#
29398186Sgordon#	If interpreter != ".", read the first line of procname, remove the
29498186Sgordon#	leading #!, normalise whitespace, append procname, and attempt to
29598186Sgordon#	match that against each command, either as is, or with extra words
296157841Sflz#	at the end.  As an alternative, to deal with interpreted daemons
297157841Sflz#	using perl, the basename of the interpreter plus a colon is also
298157841Sflz#	tried as the prefix to procname.
29998186Sgordon#
30098186Sgordon_find_processes()
30198186Sgordon{
30298186Sgordon	if [ $# -ne 3 ]; then
30398186Sgordon		err 3 'USAGE: _find_processes procname interpreter psargs'
30498186Sgordon	fi
30598186Sgordon	_procname=$1
30698186Sgordon	_interpreter=$2
30798186Sgordon	_psargs=$3
30898186Sgordon
30978344Sobrien	_pref=
31098186Sgordon	if [ $_interpreter != "." ]; then	# an interpreted script
311242183Screes		_script="${_chroot}${_chroot:+/}$_procname"
312242183Screes		if [ -r "$_script" ]; then
313170282Syar			read _interp < $_script	# read interpreter name
314170282Syar			case "$_interp" in
315170282Syar			\#!*)
316170282Syar				_interp=${_interp#\#!}	# strip #!
317170282Syar				set -- $_interp
318170282Syar				case $1 in
319170282Syar				*/bin/env)
320170282Syar					shift	# drop env to get real name
321170282Syar					;;
322170282Syar				esac
323170282Syar				if [ $_interpreter != $1 ]; then
324170282Syar					warn "\$command_interpreter $_interpreter != $1"
325170282Syar				fi
326170282Syar				;;
327170282Syar			*)
328170282Syar				warn "no shebang line in $_script"
329170282Syar				set -- $_interpreter
330170282Syar				;;
331170282Syar			esac
332170282Syar		else
333170282Syar			warn "cannot read shebang line from $_script"
334170282Syar			set -- $_interpreter
33578344Sobrien		fi
33698186Sgordon		_interp="$* $_procname"		# cleanup spaces, add _procname
337157841Sflz		_interpbn=${1##*/}
33898186Sgordon		_fp_args='_argv'
33998186Sgordon		_fp_match='case "$_argv" in
340245250Ssmh		    ${_interp}|"${_interp} "*|"[${_interpbn}]"|"${_interpbn}: ${_procname}"*)'
34198186Sgordon	else					# a normal daemon
34298186Sgordon		_procnamebn=${_procname##*/}
34398186Sgordon		_fp_args='_arg0 _argv'
34498186Sgordon		_fp_match='case "$_arg0" in
345151426Sjhb		    $_procname|$_procnamebn|${_procnamebn}:|"(${_procnamebn})"|"[${_procnamebn}]")'
34698186Sgordon	fi
34798186Sgordon
348161435Syar	_proccheck="\
349161436Syar		$PS 2>/dev/null -o pid= -o jid= -o command= $_psargs"' |
350157657Sflz		while read _npid _jid '"$_fp_args"'; do
351161436Syar			'"$_fp_match"'
352157657Sflz				if [ "$JID" -eq "$_jid" ];
353157657Sflz				then echo -n "$_pref$_npid";
354157657Sflz				_pref=" ";
355157657Sflz				fi
35698186Sgordon				;;
35798186Sgordon			esac
35898186Sgordon		done'
35998186Sgordon
360114272Smtm#	debug "in _find_processes: proccheck is ($_proccheck)."
36198186Sgordon	eval $_proccheck
36298186Sgordon}
36398186Sgordon
364264243Sdteske# sort_lite [-b] [-n] [-k POS] [-t SEP]
365264243Sdteske#	A lite version of sort(1) (supporting a few options) that can be used
366264243Sdteske#	before the real sort(1) is available (e.g., in scripts that run prior
367264243Sdteske#	to mountcritremote). Requires only shell built-in functionality.
36898186Sgordon#
369264243Sdteskesort_lite()
370264243Sdteske{
371264243Sdteske	local funcname=sort_lite
372264243Sdteske	local sort_sep="$IFS" sort_ignore_leading_space=
373264243Sdteske	local sort_field=0 sort_strict_fields= sort_numeric=
374264243Sdteske	local nitems=0 skip_leading=0 trim=
375264243Sdteske
376264243Sdteske	local OPTIND flag
377264243Sdteske	while getopts bnk:t: flag; do
378264243Sdteske		case "$flag" in
379264243Sdteske		b) sort_ignore_leading_space=1 ;;
380264243Sdteske		n) sort_numeric=1 sort_ignore_leading_space=1 ;;
381264243Sdteske		k) sort_field="${OPTARG%%,*}" ;; # only up to first comma
382264243Sdteske			# NB: Unlike sort(1) only one POS allowed
383264243Sdteske		t) sort_sep="$OPTARG"
384264243Sdteske		   if [ ${#sort_sep} -gt 1 ]; then
385264243Sdteske		   	echo "$funcname: multi-character tab \`$sort_sep'" >&2
386264243Sdteske		   	return 1
387264243Sdteske		   fi
388264243Sdteske		   sort_strict_fields=1
389264243Sdteske		   ;;
390264243Sdteske		\?) return 1 ;;
391264243Sdteske		esac
392264243Sdteske	done
393264243Sdteske	shift $(( $OPTIND - 1 ))
394264243Sdteske
395264243Sdteske	# Create transformation pattern to trim leading text if desired
396264243Sdteske	case "$sort_field" in
397264243Sdteske	""|[!0-9]*|*[!0-9.]*)
398264243Sdteske		echo "$funcname: invalid sort field \`$sort_field'" >&2
399264243Sdteske		return 1
400264243Sdteske		;;
401264243Sdteske	*.*)
402264243Sdteske		skip_leading=${sort_field#*.} sort_field=${sort_field%%.*}
403264243Sdteske		while [ ${skip_leading:-0} -gt 1 ] 2> /dev/null; do
404264243Sdteske			trim="$trim?" skip_leading=$(( $skip_leading - 1 ))
405264243Sdteske		done
406264243Sdteske	esac
407264243Sdteske
408264243Sdteske	# Copy input to series of local numbered variables
409264243Sdteske	# NB: IFS of NULL preserves leading whitespace
410264243Sdteske	local LINE
411264243Sdteske	while IFS= read -r LINE || [ "$LINE" ]; do
412264243Sdteske		nitems=$(( $nitems + 1 ))
413264243Sdteske		local src_$nitems="$LINE"
414264243Sdteske	done
415264243Sdteske
416264243Sdteske	#
417264243Sdteske	# Sort numbered locals using insertion sort
418264243Sdteske	#
419264243Sdteske	local curitem curitem_orig curitem_mod curitem_haskey
420264243Sdteske	local dest dest_orig dest_mod dest_haskey
421264243Sdteske	local d gt n
422264243Sdteske	local i=1 
423264243Sdteske	while [ $i -le $nitems ]; do
424264243Sdteske		curitem_haskey=1 # Assume sort field (-k POS) exists
425264243Sdteske		eval curitem=\"\$src_$i\"
426264243Sdteske		curitem_mod="$curitem" # for modified comparison
427264243Sdteske		curitem_orig="$curitem" # for original comparison
428264243Sdteske
429264243Sdteske		# Trim leading whitespace if desired
430264243Sdteske		if [ "$sort_ignore_leading_space" ]; then
431264243Sdteske			while case "$curitem_orig" in
432264243Sdteske				[$IFS]*) : ;; *) false; esac
433264243Sdteske			do
434264243Sdteske				curitem_orig="${curitem_orig#?}"
435264243Sdteske			done
436264243Sdteske			curitem_mod="$curitem_orig"
437264243Sdteske		fi
438264243Sdteske
439264243Sdteske		# Shift modified comparison value if sort field (-k POS) is > 1
440264243Sdteske		n=$sort_field
441264243Sdteske		while [ $n -gt 1 ]; do
442264243Sdteske			case "$curitem_mod" in
443264243Sdteske			*[$sort_sep]*)
444264243Sdteske				# Cut text up-to (and incl.) first separator
445264243Sdteske				curitem_mod="${curitem_mod#*[$sort_sep]}"
446264243Sdteske
447264243Sdteske				# Skip NULLs unless strict field splitting
448264243Sdteske				[ "$sort_strict_fields" ] ||
449264243Sdteske					[ "${curitem_mod%%[$sort_sep]*}" ] ||
450264243Sdteske					[ $n -eq 2 ] ||
451264243Sdteske					continue
452264243Sdteske				;;
453264243Sdteske			*)
454264243Sdteske				# Asked for a field that doesn't exist
455264243Sdteske				curitem_haskey= break
456264243Sdteske			esac
457264243Sdteske			n=$(( $n - 1 ))
458264243Sdteske		done
459264243Sdteske
460264243Sdteske		# Trim trailing words if sort field >= 1
461264243Sdteske		[ $sort_field -ge 1 -a "$sort_numeric" ] &&
462264243Sdteske			curitem_mod="${curitem_mod%%[$sort_sep]*}"
463264243Sdteske
464264243Sdteske		# Apply optional trim (-k POS.TRIM) to cut leading characters
465264243Sdteske		curitem_mod="${curitem_mod#$trim}"
466264243Sdteske
467264243Sdteske		# Determine the type of modified comparison to use initially
468264243Sdteske		# NB: Prefer numerical if requested but fallback to standard
469264243Sdteske		case "$curitem_mod" in
470264243Sdteske		""|[!0-9]*) # NULL or begins with non-number
471264243Sdteske			gt=">"
472264243Sdteske			[ "$sort_numeric" ] && curitem_mod=0
473264243Sdteske			;;
474264243Sdteske		*)
475264243Sdteske			if [ "$sort_numeric" ]; then
476264243Sdteske				gt="-gt"
477264243Sdteske				curitem_mod="${curitem_mod%%[!0-9]*}"
478264243Sdteske					# NB: trailing non-digits removed
479264243Sdteske					# otherwise numeric comparison fails
480264243Sdteske			else
481264243Sdteske				gt=">"
482264243Sdteske			fi
483264243Sdteske		esac
484264243Sdteske
485264243Sdteske		# If first time through, short-circuit below position-search
486264243Sdteske		if [ $i -le 1 ]; then
487264243Sdteske			d=0
488264243Sdteske		else
489264243Sdteske			d=1
490264243Sdteske		fi
491264243Sdteske
492264243Sdteske		#
493264243Sdteske		# Find appropriate element position
494264243Sdteske		#
495264243Sdteske		while [ $d -gt 0 ]
496264243Sdteske		do
497264243Sdteske			dest_haskey=$curitem_haskey
498264243Sdteske			eval dest=\"\$dest_$d\"
499264243Sdteske			dest_mod="$dest" # for modified comparison
500264243Sdteske			dest_orig="$dest" # for original comparison
501264243Sdteske
502264243Sdteske			# Trim leading whitespace if desired
503264243Sdteske			if [ "$sort_ignore_leading_space" ]; then
504264243Sdteske				while case "$dest_orig" in
505264243Sdteske					[$IFS]*) : ;; *) false; esac
506264243Sdteske				do
507264243Sdteske					dest_orig="${dest_orig#?}"
508264243Sdteske				done
509264243Sdteske				dest_mod="$dest_orig"
510264243Sdteske			fi
511264243Sdteske
512264243Sdteske			# Shift modified value if sort field (-k POS) is > 1
513264243Sdteske			n=$sort_field
514264243Sdteske			while [ $n -gt 1 ]; do
515264243Sdteske				case "$dest_mod" in
516264243Sdteske				*[$sort_sep]*)
517264243Sdteske					# Cut text up-to (and incl.) 1st sep
518264243Sdteske					dest_mod="${dest_mod#*[$sort_sep]}"
519264243Sdteske
520264243Sdteske					# Skip NULLs unless strict fields
521264243Sdteske					[ "$sort_strict_fields" ] ||
522264243Sdteske					    [ "${dest_mod%%[$sort_sep]*}" ] ||
523264243Sdteske					    [ $n -eq 2 ] ||
524264243Sdteske					    continue
525264243Sdteske					;;
526264243Sdteske				*)
527264243Sdteske					# Asked for a field that doesn't exist
528264243Sdteske					dest_haskey= break
529264243Sdteske				esac
530264243Sdteske				n=$(( $n - 1 ))
531264243Sdteske			done
532264243Sdteske
533264243Sdteske			# Trim trailing words if sort field >= 1
534264243Sdteske			[ $sort_field -ge 1 -a "$sort_numeric" ] &&
535264243Sdteske				dest_mod="${dest_mod%%[$sort_sep]*}"
536264243Sdteske
537264243Sdteske			# Apply optional trim (-k POS.TRIM), cut leading chars
538264243Sdteske			dest_mod="${dest_mod#$trim}"
539264243Sdteske
540264243Sdteske			# Determine type of modified comparison to use
541264243Sdteske			# NB: Prefer numerical if requested, fallback to std
542264243Sdteske			case "$dest_mod" in
543264243Sdteske			""|[!0-9]*) # NULL or begins with non-number
544264243Sdteske				gt=">"
545264243Sdteske				[ "$sort_numeric" ] && dest_mod=0
546264243Sdteske				;;
547264243Sdteske			*)
548264243Sdteske				if [ "$sort_numeric" ]; then
549264243Sdteske					gt="-gt"
550264243Sdteske					dest_mod="${dest_mod%%[!0-9]*}"
551264243Sdteske						# NB: kill trailing non-digits
552264243Sdteske						# for numeric comparison safety
553264243Sdteske				else
554264243Sdteske					gt=">"
555264243Sdteske				fi
556264243Sdteske			esac
557264243Sdteske
558264243Sdteske			# Break if we've found the proper element position
559264243Sdteske			if [ "$curitem_haskey" -a "$dest_haskey" ]; then
560264243Sdteske				if [ "$dest_mod" = "$curitem_mod" ]; then
561264243Sdteske					[ "$dest_orig" ">" "$curitem_orig" ] &&
562264243Sdteske						break
563264243Sdteske				elif [ "$dest_mod" $gt "$curitem_mod" ] \
564264243Sdteske					2> /dev/null
565264243Sdteske				then
566264243Sdteske					break
567264243Sdteske				fi
568264243Sdteske			else
569264243Sdteske				[ "$dest_orig" ">" "$curitem_orig" ] && break
570264243Sdteske			fi
571264243Sdteske
572264243Sdteske			# Break if we've hit the end
573264243Sdteske			[ $d -ge $i ] && break
574264243Sdteske
575264243Sdteske			d=$(( $d + 1 ))
576264243Sdteske		done
577264243Sdteske
578264243Sdteske		# Shift remaining positions forward, making room for new item
579264243Sdteske		n=$i
580264243Sdteske		while [ $n -ge $d ]; do
581264243Sdteske			# Shift destination item forward one placement
582264243Sdteske			eval dest_$(( $n + 1 ))=\"\$dest_$n\"
583264243Sdteske			n=$(( $n - 1 ))
584264243Sdteske		done
585264243Sdteske
586264243Sdteske		# Place the element
587264243Sdteske		if [ $i -eq 1 ]; then
588264243Sdteske			local dest_1="$curitem"
589264243Sdteske		else
590264243Sdteske			local dest_$d="$curitem"
591264243Sdteske		fi
592264243Sdteske
593264243Sdteske		i=$(( $i + 1 ))
594264243Sdteske	done
595264243Sdteske
596264243Sdteske	# Print sorted results
597264243Sdteske	d=1
598264243Sdteske	while [ $d -le $nitems ]; do
599264243Sdteske		eval echo \"\$dest_$d\"
600264243Sdteske		d=$(( $d + 1 ))
601264243Sdteske	done
602264243Sdteske}
603264243Sdteske
604264243Sdteske#
60598186Sgordon# wait_for_pids pid [pid ...]
60698186Sgordon#	spins until none of the pids exist
60798186Sgordon#
60898186Sgordonwait_for_pids()
60998186Sgordon{
610206248Sdougb	local _list _prefix _nlist _j
611206248Sdougb
612126286Smtm	_list="$@"
61398186Sgordon	if [ -z "$_list" ]; then
61498186Sgordon		return
61598186Sgordon	fi
61698186Sgordon	_prefix=
61798186Sgordon	while true; do
61898186Sgordon		_nlist="";
61998186Sgordon		for _j in $_list; do
62098186Sgordon			if kill -0 $_j 2>/dev/null; then
62198186Sgordon				_nlist="${_nlist}${_nlist:+ }$_j"
622206248Sdougb				[ -n "$_prefix" ] && sleep 1
62398186Sgordon			fi
62498186Sgordon		done
62598186Sgordon		if [ -z "$_nlist" ]; then
62698186Sgordon			break
62778344Sobrien		fi
62898186Sgordon		_list=$_nlist
62998186Sgordon		echo -n ${_prefix:-"Waiting for PIDS: "}$_list
63098186Sgordon		_prefix=", "
631206248Sdougb		pwait $_list 2>/dev/null
63278344Sobrien	done
63398186Sgordon	if [ -n "$_prefix" ]; then
63498186Sgordon		echo "."
63598186Sgordon	fi
63678344Sobrien}
63778344Sobrien
63878344Sobrien#
639220962Sdougb# get_pidfile_from_conf string file
640220962Sdougb#
641220962Sdougb#	Takes a string to search for in the specified file.
642220962Sdougb#	Ignores lines with traditional comment characters.
643220962Sdougb#
644220962Sdougb# Example:
645220962Sdougb#
646220962Sdougb# if get_pidfile_from_conf string file; then
647220962Sdougb#	pidfile="$_pidfile_from_conf"
648220962Sdougb# else
649220962Sdougb#	pidfile='appropriate default'
650220962Sdougb# fi
651220962Sdougb#
652220962Sdougbget_pidfile_from_conf()
653220962Sdougb{
654220963Sdougb	if [ -z "$1" -o -z "$2" ]; then
655220963Sdougb		err 3 "USAGE: get_pidfile_from_conf string file ($name)"
656220963Sdougb	fi
657220963Sdougb
658220962Sdougb	local string file line
659220962Sdougb
660220962Sdougb	string="$1" ; file="$2"
661220962Sdougb
662220963Sdougb	if [ ! -s "$file" ]; then
663220963Sdougb		err 3 "get_pidfile_from_conf: $file does not exist ($name)"
664220962Sdougb	fi
665220962Sdougb
666220962Sdougb	while read line; do
667220962Sdougb		case "$line" in
668220962Sdougb		*[#\;]*${string}*)	continue ;;
669220962Sdougb		*${string}*)		break ;;
670220962Sdougb		esac
671220962Sdougb	done < $file
672220962Sdougb
673220962Sdougb	if [ -n "$line" ]; then
674220962Sdougb		line=${line#*/}
675220962Sdougb		_pidfile_from_conf="/${line%%[\"\;]*}"
676220962Sdougb	else
677220962Sdougb		return 1
678220962Sdougb	fi
679220962Sdougb}
680220962Sdougb
681220962Sdougb#
682197947Sdougb# check_startmsgs
683197947Sdougb#	If rc_quiet is set (usually as a result of using faststart at
684197947Sdougb#	boot time) check if rc_startmsgs is enabled.
685197947Sdougb#
686197947Sdougbcheck_startmsgs()
687197947Sdougb{
688197947Sdougb	if [ -n "$rc_quiet" ]; then
689197947Sdougb		checkyesno rc_startmsgs
690197947Sdougb	else
691197947Sdougb		return 0
692197947Sdougb	fi
693197947Sdougb}
694197947Sdougb
695197947Sdougb#
69698186Sgordon# run_rc_command argument
69798186Sgordon#	Search for argument in the list of supported commands, which is:
69898186Sgordon#		"start stop restart rcvar status poll ${extra_commands}"
69998186Sgordon#	If there's a match, run ${argument}_cmd or the default method
70098186Sgordon#	(see below).
70178344Sobrien#
70298186Sgordon#	If argument has a given prefix, then change the operation as follows:
70398186Sgordon#		Prefix	Operation
70478344Sobrien#		------	---------
705175676Smtm#		fast	Skip the pid check, and set rc_fast=yes, rc_quiet=yes
70698186Sgordon#		force	Set ${rcvar} to YES, and set rc_force=yes
707126303Smtm#		one	Set ${rcvar} to YES
708175676Smtm#		quiet	Don't output some diagnostics, and set rc_quiet=yes
70978344Sobrien#
71078344Sobrien#	The following globals are used:
71178344Sobrien#
71298186Sgordon#	Name		Needed	Purpose
71398186Sgordon#	----		------	-------
71478344Sobrien#	name		y	Name of script.
71578344Sobrien#
71678344Sobrien#	command		n	Full path to command.
71798186Sgordon#				Not needed if ${rc_arg}_cmd is set for
71878344Sobrien#				each keyword.
71978344Sobrien#
72078344Sobrien#	command_args	n	Optional args/shell directives for command.
72178344Sobrien#
72298186Sgordon#	command_interpreter n	If not empty, command is interpreted, so
72398186Sgordon#				call check_{pidfile,process}() appropriately.
72498186Sgordon#
725197144Shrs#	desc		n	Description of script.
726197144Shrs#
72778344Sobrien#	extra_commands	n	List of extra commands supported.
72878344Sobrien#
72998186Sgordon#	pidfile		n	If set, use check_pidfile $pidfile $command,
73098186Sgordon#				otherwise use check_process $command.
73198186Sgordon#				In either case, only check if $command is set.
73278344Sobrien#
73398186Sgordon#	procname	n	Process name to check for instead of $command.
73498186Sgordon#
73578344Sobrien#	rcvar		n	This is checked with checkyesno to determine
73678344Sobrien#				if the action should be run.
73778344Sobrien#
738157653Sflz#	${name}_program	n	Full path to command.
739157653Sflz#				Meant to be used in /etc/rc.conf to override
740157653Sflz#				${command}.
741157653Sflz#
74278344Sobrien#	${name}_chroot	n	Directory to chroot to before running ${command}
74398186Sgordon#				Requires /usr to be mounted.
74478344Sobrien#
74578344Sobrien#	${name}_chdir	n	Directory to cd to before running ${command}
74678344Sobrien#				(if not using ${name}_chroot).
74778344Sobrien#
74878344Sobrien#	${name}_flags	n	Arguments to call ${command} with.
74978344Sobrien#				NOTE:	$flags from the parent environment
75078344Sobrien#					can be used to override this.
75178344Sobrien#
752272974Shrs#	${name}_env	n	Environment variables to run ${command} with.
753272974Shrs#
754242184Shrs#	${name}_fib	n	Routing table number to run ${command} with.
755242184Shrs#
75678344Sobrien#	${name}_nice	n	Nice level to run ${command} at.
75778344Sobrien#
75878344Sobrien#	${name}_user	n	User to run ${command} as, using su(1) if not
75978344Sobrien#				using ${name}_chroot.
76098186Sgordon#				Requires /usr to be mounted.
76178344Sobrien#
76278344Sobrien#	${name}_group	n	Group to run chrooted ${command} as.
76398186Sgordon#				Requires /usr to be mounted.
76478344Sobrien#
76598186Sgordon#	${name}_groups	n	Comma separated list of supplementary groups
76698186Sgordon#				to run the chrooted ${command} with.
76798186Sgordon#				Requires /usr to be mounted.
76878344Sobrien#
769272974Shrs#	${name}_prepend	n	Command added before ${command}.
770272974Shrs#
771288291Sadrian#	${name}_login_class n	Login class to use, else "daemon".
772288291Sadrian#
77398186Sgordon#	${rc_arg}_cmd	n	If set, use this as the method when invoked;
77478344Sobrien#				Otherwise, use default command (see below)
77578344Sobrien#
77698186Sgordon#	${rc_arg}_precmd n	If set, run just before performing the
77798186Sgordon#				${rc_arg}_cmd method in the default
77898186Sgordon#				operation (i.e, after checking for required
77998186Sgordon#				bits and process (non)existence).
78078344Sobrien#				If this completes with a non-zero exit code,
78198186Sgordon#				don't run ${rc_arg}_cmd.
78278344Sobrien#
78398186Sgordon#	${rc_arg}_postcmd n	If set, run just after performing the
78498186Sgordon#				${rc_arg}_cmd method, if that method
78598186Sgordon#				returned a zero exit code.
78698186Sgordon#
78778344Sobrien#	required_dirs	n	If set, check for the existence of the given
788165565Syar#				directories before running a (re)start command.
78978344Sobrien#
79078344Sobrien#	required_files	n	If set, check for the readability of the given
791165565Syar#				files before running a (re)start command.
79278344Sobrien#
793165565Syar#	required_modules n	If set, ensure the given kernel modules are
794165565Syar#				loaded before running a (re)start command.
795165565Syar#				The check and possible loads are actually
796165565Syar#				done after start_precmd so that the modules
797165565Syar#				aren't loaded in vain, should the precmd
798165565Syar#				return a non-zero status to indicate a error.
799165565Syar#				If a word in the list looks like "foo:bar",
800165565Syar#				"foo" is the KLD file name and "bar" is the
801165565Syar#				module name.  If a word looks like "foo~bar",
802165565Syar#				"foo" is the KLD file name and "bar" is a
803165565Syar#				egrep(1) pattern matching the module name.
804165565Syar#				Otherwise the module name is assumed to be
805165565Syar#				the same as the KLD file name, which is most
806165565Syar#				common.  See load_kld().
807165565Syar#
80878344Sobrien#	required_vars	n	If set, perform checkyesno on each of the
80978344Sobrien#				listed variables before running the default
81078344Sobrien#				(re)start command.
81178344Sobrien#
81298186Sgordon#	Default behaviour for a given argument, if no override method is
81398186Sgordon#	provided:
81478344Sobrien#
81598186Sgordon#	Argument	Default behaviour
81698186Sgordon#	--------	-----------------
81778344Sobrien#	start		if !running && checkyesno ${rcvar}
81878344Sobrien#				${command}
81978344Sobrien#
82078344Sobrien#	stop		if ${pidfile}
82198186Sgordon#				rc_pid=$(check_pidfile $pidfile $command)
82278344Sobrien#			else
82398186Sgordon#				rc_pid=$(check_process $command)
82498186Sgordon#			kill $sig_stop $rc_pid
82598186Sgordon#			wait_for_pids $rc_pid
82698186Sgordon#			($sig_stop defaults to TERM.)
82778344Sobrien#
82898186Sgordon#	reload		Similar to stop, except use $sig_reload instead,
82998186Sgordon#			and doesn't wait_for_pids.
83078344Sobrien#			$sig_reload defaults to HUP.
831151685Syar#			Note that `reload' isn't provided by default,
832151685Syar#			it should be enabled via $extra_commands.
83378344Sobrien#
83478344Sobrien#	restart		Run `stop' then `start'.
83578344Sobrien#
83698186Sgordon#	status		Show if ${command} is running, etc.
83778344Sobrien#
83898186Sgordon#	poll		Wait for ${command} to exit.
83998186Sgordon#
84098186Sgordon#	rcvar		Display what rc.conf variable is used (if any).
84198186Sgordon#
842255809Sdes#	enabled		Return true if the service is enabled.
843255809Sdes#
84498186Sgordon#	Variables available to methods, and after run_rc_command() has
84598186Sgordon#	completed:
84698186Sgordon#
84798186Sgordon#	Variable	Purpose
84898186Sgordon#	--------	-------
849126303Smtm#	rc_arg		Argument to command, after fast/force/one processing
85098186Sgordon#			performed
85198186Sgordon#
85298186Sgordon#	rc_flags	Flags to start the default command with.
85398186Sgordon#			Defaults to ${name}_flags, unless overridden
85498186Sgordon#			by $flags from the environment.
85598186Sgordon#			This variable may be changed by the precmd method.
85698186Sgordon#
85798186Sgordon#	rc_pid		PID of command (if appropriate)
85898186Sgordon#
85998186Sgordon#	rc_fast		Not empty if "fast" was provided (q.v.)
86098186Sgordon#
86198186Sgordon#	rc_force	Not empty if "force" was provided (q.v.)
86298186Sgordon#
863175676Smtm#	rc_quiet	Not empty if "quiet" was provided
86498186Sgordon#
865175676Smtm#
86678344Sobrienrun_rc_command()
86778344Sobrien{
868116097Smtm	_return=0
86998186Sgordon	rc_arg=$1
87078344Sobrien	if [ -z "$name" ]; then
87198186Sgordon		err 3 'run_rc_command: $name is not set.'
87278344Sobrien	fi
87378344Sobrien
874132892Smtm	# Don't repeat the first argument when passing additional command-
875132892Smtm	# line arguments to the command subroutines.
876132892Smtm	#
877132892Smtm	shift 1
878132892Smtm	rc_extra_args="$*"
879132892Smtm
880126303Smtm	_rc_prefix=
88198186Sgordon	case "$rc_arg" in
88278344Sobrien	fast*)				# "fast" prefix; don't check pid
88398186Sgordon		rc_arg=${rc_arg#fast}
88498186Sgordon		rc_fast=yes
885175676Smtm		rc_quiet=yes
88678344Sobrien		;;
887198216Sed	force*)				# "force" prefix; always run
88898186Sgordon		rc_force=yes
889126303Smtm		_rc_prefix=force
890126303Smtm		rc_arg=${rc_arg#${_rc_prefix}}
89178344Sobrien		if [ -n "${rcvar}" ]; then
89278344Sobrien			eval ${rcvar}=YES
89378344Sobrien		fi
89478344Sobrien		;;
895126303Smtm	one*)				# "one" prefix; set ${rcvar}=yes
896126303Smtm		_rc_prefix=one
897126303Smtm		rc_arg=${rc_arg#${_rc_prefix}}
898126303Smtm		if [ -n "${rcvar}" ]; then
899126303Smtm			eval ${rcvar}=YES
900126303Smtm		fi
901126303Smtm		;;
902175676Smtm	quiet*)				# "quiet" prefix; omit some messages
903175676Smtm		_rc_prefix=quiet
904175676Smtm		rc_arg=${rc_arg#${_rc_prefix}}
905175676Smtm		rc_quiet=yes
906175676Smtm		;;
90778344Sobrien	esac
90878344Sobrien
909161530Sflz	eval _override_command=\$${name}_program
910198162Sdougb	command=${_override_command:-$command}
911161530Sflz
912255809Sdes	_keywords="start stop restart rcvar enabled $extra_commands"
91398186Sgordon	rc_pid=
91478344Sobrien	_pidcmd=
91598186Sgordon	_procname=${procname:-${command}}
91698186Sgordon
917131135Smtm					# setup pid check command
918131135Smtm	if [ -n "$_procname" ]; then
91978344Sobrien		if [ -n "$pidfile" ]; then
92098186Sgordon			_pidcmd='rc_pid=$(check_pidfile '"$pidfile $_procname $command_interpreter"')'
92198186Sgordon		else
92298186Sgordon			_pidcmd='rc_pid=$(check_process '"$_procname $command_interpreter"')'
92378344Sobrien		fi
92478344Sobrien		if [ -n "$_pidcmd" ]; then
92598186Sgordon			_keywords="${_keywords} status poll"
92678344Sobrien		fi
92778344Sobrien	fi
92878344Sobrien
92998186Sgordon	if [ -z "$rc_arg" ]; then
930150796Syar		rc_usage $_keywords
93178344Sobrien	fi
93278344Sobrien
933255809Sdes	if [ "$rc_arg" = "enabled" ] ; then
934255809Sdes		checkyesno ${rcvar}
935255809Sdes		return $?
936255809Sdes	fi
937255809Sdes
93878344Sobrien	if [ -n "$flags" ]; then	# allow override from environment
93998186Sgordon		rc_flags=$flags
94078344Sobrien	else
94198186Sgordon		eval rc_flags=\$${name}_flags
94278344Sobrien	fi
94398186Sgordon	eval _chdir=\$${name}_chdir	_chroot=\$${name}_chroot \
94498186Sgordon	    _nice=\$${name}_nice	_user=\$${name}_user \
945242184Shrs	    _group=\$${name}_group	_groups=\$${name}_groups \
946272974Shrs	    _fib=\$${name}_fib		_env=\$${name}_env \
947288291Sadrian	    _prepend=\$${name}_prepend	_login_class=\${${name}_login_class:-daemon}
94878344Sobrien
94998186Sgordon	if [ -n "$_user" ]; then	# unset $_user if running as that user
950124832Smtm		if [ "$_user" = "$(eval $IDCMD)" ]; then
95198186Sgordon			unset _user
95298186Sgordon		fi
95398186Sgordon	fi
95498186Sgordon
955230374Sdougb	[ -z "$autoboot" ] && eval $_pidcmd	# determine the pid if necessary
956179870Smtm
957179870Smtm	for _elem in $_keywords; do
958179870Smtm		if [ "$_elem" != "$rc_arg" ]; then
959179870Smtm			continue
960179870Smtm		fi
961206686Sdougb					# if ${rcvar} is set, $1 is not "rcvar"
962206686Sdougb					# and ${rc_pid} is not set, then run
96378344Sobrien					#	checkyesno ${rcvar}
96478344Sobrien					# and return if that failed
96578344Sobrien					#
966220760Sdougb		if [ -n "${rcvar}" -a "$rc_arg" != "rcvar" -a "$rc_arg" != "stop" ] ||
967220760Sdougb		    [ -n "${rcvar}" -a "$rc_arg" = "stop" -a -z "${rc_pid}" ]; then
968179870Smtm			if ! checkyesno ${rcvar}; then
969179870Smtm				if [ -n "${rc_quiet}" ]; then
970179870Smtm					return 0
971179870Smtm				fi
972179870Smtm				echo -n "Cannot '${rc_arg}' $name. Set ${rcvar} to "
973179870Smtm				echo -n "YES in /etc/rc.conf or use 'one${rc_arg}' "
974179870Smtm				echo "instead of '${rc_arg}'."
975175676Smtm				return 0
976175676Smtm			fi
97778344Sobrien		fi
97878344Sobrien
97978344Sobrien					# if there's a custom ${XXX_cmd},
98078344Sobrien					# run that instead of the default
98178344Sobrien					#
982165565Syar		eval _cmd=\$${rc_arg}_cmd \
983165565Syar		     _precmd=\$${rc_arg}_precmd \
984165565Syar		     _postcmd=\$${rc_arg}_postcmd
985165565Syar
98678344Sobrien		if [ -n "$_cmd" ]; then
987165565Syar			_run_rc_precmd || return 1
988165565Syar			_run_rc_doit "$_cmd $rc_extra_args" || return 1
989165565Syar			_run_rc_postcmd
990116097Smtm			return $_return
99178344Sobrien		fi
99278344Sobrien
99398186Sgordon		case "$rc_arg" in	# default operations...
99478344Sobrien
99578344Sobrien		status)
996165565Syar			_run_rc_precmd || return 1
99798186Sgordon			if [ -n "$rc_pid" ]; then
99898186Sgordon				echo "${name} is running as pid $rc_pid."
99978344Sobrien			else
100078344Sobrien				echo "${name} is not running."
100178344Sobrien				return 1
100278344Sobrien			fi
1003165565Syar			_run_rc_postcmd
100478344Sobrien			;;
100578344Sobrien
100678344Sobrien		start)
1007131135Smtm			if [ -z "$rc_fast" -a -n "$rc_pid" ]; then
1008243324Shrs				if [ -z "$rc_quiet" ]; then
1009243324Shrs					echo 1>&2 "${name} already running? " \
1010243324Shrs					    "(pid=$rc_pid)."
1011243324Shrs				fi
1012153152Syar				return 1
101378344Sobrien			fi
101478344Sobrien
1015242183Screes			if [ ! -x "${_chroot}${_chroot:+/}${command}" ]; then
1016160667Syar				warn "run_rc_command: cannot run $command"
1017153152Syar				return 1
101878344Sobrien			fi
101978344Sobrien
1020179946Smtm			if ! _run_rc_precmd; then
1021179946Smtm				warn "failed precmd routine for ${name}"
1022179946Smtm				return 1
1023179946Smtm			fi
102478344Sobrien
1025160668Syar					# setup the full command to run
102678344Sobrien					#
1027197947Sdougb			check_startmsgs && echo "Starting ${name}."
102878344Sobrien			if [ -n "$_chroot" ]; then
102978344Sobrien				_doit="\
103078344Sobrien${_nice:+nice -n $_nice }\
1031242184Shrs${_fib:+setfib -F $_fib }\
1032272974Shrs${_env:+env $_env }\
103378344Sobrienchroot ${_user:+-u $_user }${_group:+-g $_group }${_groups:+-G $_groups }\
103498186Sgordon$_chroot $command $rc_flags $command_args"
103578344Sobrien			else
103678344Sobrien				_doit="\
1037161396Syar${_chdir:+cd $_chdir && }\
1038242184Shrs${_fib:+setfib -F $_fib }\
1039272974Shrs${_env:+env $_env }\
104098186Sgordon$command $rc_flags $command_args"
104198186Sgordon				if [ -n "$_user" ]; then
104298186Sgordon				    _doit="su -m $_user -c 'sh -c \"$_doit\"'"
104398186Sgordon				fi
1044161396Syar				if [ -n "$_nice" ]; then
1045161396Syar					if [ -z "$_user" ]; then
1046161396Syar						_doit="sh -c \"$_doit\""
1047201036Sdougb					fi
1048161396Syar					_doit="nice -n $_nice $_doit"
1049161396Syar				fi
1050272974Shrs				if [ -n "$_prepend" ]; then
1051272974Shrs					_doit="$_prepend $_doit"
1052272974Shrs				fi
105378344Sobrien			fi
105498186Sgordon
1055288291Sadrian					# Prepend default limits
1056288291Sadrian			_doit="limits -C $_login_class $_doit"
1057288291Sadrian
1058165565Syar					# run the full command
105998186Sgordon					#
1060179946Smtm			if ! _run_rc_doit "$_doit"; then
1061179946Smtm				warn "failed to start ${name}"
1062179946Smtm				return 1
1063179946Smtm			fi
106498186Sgordon
106598186Sgordon					# finally, run postcmd
106698186Sgordon					#
1067165565Syar			_run_rc_postcmd
106878344Sobrien			;;
106978344Sobrien
107078344Sobrien		stop)
107198186Sgordon			if [ -z "$rc_pid" ]; then
1072153152Syar				[ -n "$rc_fast" ] && return 0
1073165565Syar				_run_rc_notrunning
1074153152Syar				return 1
107578344Sobrien			fi
107678344Sobrien
1077165565Syar			_run_rc_precmd || return 1
107898186Sgordon
107998186Sgordon					# send the signal to stop
108098186Sgordon					#
108178344Sobrien			echo "Stopping ${name}."
1082165565Syar			_doit=$(_run_rc_killcmd "${sig_stop:-TERM}")
1083165565Syar			_run_rc_doit "$_doit" || return 1
108498186Sgordon
108598186Sgordon					# wait for the command to exit,
108698186Sgordon					# and run postcmd.
108798186Sgordon			wait_for_pids $rc_pid
1088165565Syar
1089165565Syar			_run_rc_postcmd
109078344Sobrien			;;
109178344Sobrien
109278344Sobrien		reload)
109398186Sgordon			if [ -z "$rc_pid" ]; then
1094165565Syar				_run_rc_notrunning
1095153152Syar				return 1
109678344Sobrien			fi
1097165565Syar
1098165565Syar			_run_rc_precmd || return 1
1099165565Syar
1100165565Syar			_doit=$(_run_rc_killcmd "${sig_reload:-HUP}")
1101165565Syar			_run_rc_doit "$_doit" || return 1
1102165565Syar
1103165565Syar			_run_rc_postcmd
110478344Sobrien			;;
110578344Sobrien
110678344Sobrien		restart)
110778344Sobrien					# prevent restart being called more
110878344Sobrien					# than once by any given script
110978344Sobrien					#
1110126285Smtm			if ${_rc_restart_done:-false}; then
111178344Sobrien				return 0
111278344Sobrien			fi
1113126285Smtm			_rc_restart_done=true
111478344Sobrien
1115165565Syar			_run_rc_precmd || return 1
1116165565Syar
1117165565Syar			# run those in a subshell to keep global variables
1118152519Syar			( run_rc_command ${_rc_prefix}stop $rc_extra_args )
1119165565Syar			( run_rc_command ${_rc_prefix}start $rc_extra_args )
1120165565Syar			_return=$?
1121165565Syar			[ $_return -ne 0 ] && [ -z "$rc_force" ] && return 1
112298186Sgordon
1123165565Syar			_run_rc_postcmd
112478344Sobrien			;;
112578344Sobrien
112698186Sgordon		poll)
1127165565Syar			_run_rc_precmd || return 1
112898186Sgordon			if [ -n "$rc_pid" ]; then
112998186Sgordon				wait_for_pids $rc_pid
113098186Sgordon			fi
1131165565Syar			_run_rc_postcmd
113298186Sgordon			;;
113398186Sgordon
113478344Sobrien		rcvar)
1135197144Shrs			echo -n "# $name"
1136197144Shrs			if [ -n "$desc" ]; then
1137197144Shrs				echo " : $desc"
1138197144Shrs			else
1139197144Shrs				echo ""
1140197144Shrs			fi
1141197144Shrs			echo "#"
1142272393Shrs			# Get unique vars in $rcvar $rcvars
1143272393Shrs			for _v in $rcvar $rcvars; do
1144197144Shrs				case $v in
1145197144Shrs				$_v\ *|\ *$_v|*\ $_v\ *) ;;
1146197144Shrs				*)	v="${v# } $_v" ;;
1147197144Shrs				esac
1148197144Shrs			done
1149197144Shrs
1150197144Shrs			# Display variables.
1151197144Shrs			for _v in $v; do
1152197144Shrs				if [ -z "$_v" ]; then
1153197144Shrs					continue
115478344Sobrien				fi
1155197144Shrs
1156197144Shrs				eval _desc=\$${_v}_desc
1157197144Shrs				eval _defval=\$${_v}_defval
1158197144Shrs				_h="-"
1159197144Shrs
1160197144Shrs				eval echo \"$_v=\\\"\$$_v\\\"\"
1161197144Shrs				# decode multiple lines of _desc
1162197144Shrs				while [ -n "$_desc" ]; do
1163197144Shrs					case $_desc in
1164197144Shrs					*^^*)
1165197144Shrs						echo "# $_h ${_desc%%^^*}"
1166197144Shrs						_desc=${_desc#*^^}
1167197144Shrs						_h=" "
1168197144Shrs						;;
1169197144Shrs					*)
1170197144Shrs						echo "# $_h ${_desc}"
1171197144Shrs						break
1172197144Shrs						;;
1173197144Shrs					esac
1174197144Shrs				done
1175197144Shrs				echo "#   (default: \"$_defval\")"
1176197144Shrs			done
1177197144Shrs			echo ""
117878344Sobrien			;;
117978344Sobrien
118078344Sobrien		*)
1181150796Syar			rc_usage $_keywords
118278344Sobrien			;;
118378344Sobrien
118478344Sobrien		esac
1185116097Smtm		return $_return
118678344Sobrien	done
118778344Sobrien
118898186Sgordon	echo 1>&2 "$0: unknown directive '$rc_arg'."
1189150796Syar	rc_usage $_keywords
1190153152Syar	# not reached
119178344Sobrien}
119278344Sobrien
119378344Sobrien#
1194165565Syar# Helper functions for run_rc_command: common code.
1195165565Syar# They use such global variables besides the exported rc_* ones:
1196165565Syar#
1197165565Syar#	name	       R/W
1198165565Syar#	------------------
1199165565Syar#	_precmd		R
1200165565Syar#	_postcmd	R
1201165565Syar#	_return		W
1202165565Syar#
1203165565Syar_run_rc_precmd()
1204165565Syar{
1205165565Syar	check_required_before "$rc_arg" || return 1
1206165565Syar
1207165565Syar	if [ -n "$_precmd" ]; then
1208165565Syar		debug "run_rc_command: ${rc_arg}_precmd: $_precmd $rc_extra_args"
1209165565Syar		eval "$_precmd $rc_extra_args"
1210165565Syar		_return=$?
1211165565Syar
1212165565Syar		# If precmd failed and force isn't set, request exit.
1213165565Syar		if [ $_return -ne 0 ] && [ -z "$rc_force" ]; then
1214165565Syar			return 1
1215165565Syar		fi
1216165565Syar	fi
1217165565Syar
1218165565Syar	check_required_after "$rc_arg" || return 1
1219165565Syar
1220165565Syar	return 0
1221165565Syar}
1222165565Syar
1223165565Syar_run_rc_postcmd()
1224165565Syar{
1225165565Syar	if [ -n "$_postcmd" ]; then
1226165565Syar		debug "run_rc_command: ${rc_arg}_postcmd: $_postcmd $rc_extra_args"
1227165565Syar		eval "$_postcmd $rc_extra_args"
1228165565Syar		_return=$?
1229165565Syar	fi
1230165565Syar	return 0
1231165565Syar}
1232165565Syar
1233165565Syar_run_rc_doit()
1234165565Syar{
1235165565Syar	debug "run_rc_command: doit: $*"
1236165565Syar	eval "$@"
1237165565Syar	_return=$?
1238165565Syar
1239165565Syar	# If command failed and force isn't set, request exit.
1240165565Syar	if [ $_return -ne 0 ] && [ -z "$rc_force" ]; then
1241165565Syar		return 1
1242165565Syar	fi
1243165565Syar
1244165565Syar	return 0
1245165565Syar}
1246165565Syar
1247165565Syar_run_rc_notrunning()
1248165565Syar{
1249165565Syar	local _pidmsg
1250165565Syar
1251165565Syar	if [ -n "$pidfile" ]; then
1252165565Syar		_pidmsg=" (check $pidfile)."
1253165565Syar	else
1254165565Syar		_pidmsg=
1255165565Syar	fi
1256165565Syar	echo 1>&2 "${name} not running?${_pidmsg}"
1257165565Syar}
1258165565Syar
1259165565Syar_run_rc_killcmd()
1260165565Syar{
1261165565Syar	local _cmd
1262165565Syar
1263165565Syar	_cmd="kill -$1 $rc_pid"
1264165565Syar	if [ -n "$_user" ]; then
1265165565Syar		_cmd="su -m ${_user} -c 'sh -c \"${_cmd}\"'"
1266165565Syar	fi
1267165565Syar	echo "$_cmd"
1268165565Syar}
1269165565Syar
1270165565Syar#
127178344Sobrien# run_rc_script file arg
127278344Sobrien#	Start the script `file' with `arg', and correctly handle the
1273201038Sdougb#	return value from the script.
1274286303Sngie#	If `file' ends with `.sh' and lives in /etc/rc.d, ignore it as it's
1275286303Sngie#	an old-style startup file.
1276286303Sngie#	If `file' ends with `.sh' and does not live in /etc/rc.d, it's sourced
1277286303Sngie#	into the current environment if $rc_fast_and_loose is set; otherwise
1278286303Sngie#	it is run as a child process.
1279201038Sdougb#	If `file' appears to be a backup or scratch file, ignore it.
1280201038Sdougb#	Otherwise if it is executable run as a child process.
128178344Sobrien#
128278344Sobrienrun_rc_script()
128378344Sobrien{
128478344Sobrien	_file=$1
128578344Sobrien	_arg=$2
128678344Sobrien	if [ -z "$_file" -o -z "$_arg" ]; then
128778344Sobrien		err 3 'USAGE: run_rc_script file arg'
128878344Sobrien	fi
128978344Sobrien
129098186Sgordon	unset	name command command_args command_interpreter \
129198186Sgordon		extra_commands pidfile procname \
1292272393Shrs		rcvar rcvars rcvars_obsolete required_dirs required_files \
1293197144Shrs		required_vars
129498186Sgordon	eval unset ${_arg}_cmd ${_arg}_precmd ${_arg}_postcmd
129598186Sgordon
129678344Sobrien	case "$_file" in
1297193118Sdougb	/etc/rc.d/*.sh)			# no longer allowed in the base
1298193118Sdougb		warn "Ignoring old-style startup script $_file"
129978344Sobrien		;;
1300153105Sdougb	*[~#]|*.OLD|*.bak|*.orig|*,v)	# scratch file; skip
130198186Sgordon		warn "Ignoring scratch file $_file"
130298186Sgordon		;;
130378344Sobrien	*)				# run in subshell
130498186Sgordon		if [ -x $_file ]; then
130598186Sgordon			if [ -n "$rc_fast_and_loose" ]; then
1306146490Sschweikh				set $_arg; . $_file
130798186Sgordon			else
1308231888Sdelphij				( trap "echo Script $_file interrupted >&2 ; kill -QUIT $$" 3
1309231888Sdelphij				  trap "echo Script $_file interrupted >&2 ; exit 1" 2
1310231888Sdelphij				  trap "echo Script $_file running >&2" 29
1311146490Sschweikh				  set $_arg; . $_file )
131298186Sgordon			fi
131398186Sgordon		fi
131478344Sobrien		;;
131578344Sobrien	esac
131678344Sobrien}
131778344Sobrien
131878344Sobrien#
1319157653Sflz# load_rc_config name
1320157653Sflz#	Source in the configuration file for a given name.
132178344Sobrien#
132278344Sobrienload_rc_config()
132378344Sobrien{
1324270698Shrs	local _name _rcvar_val _var _defval _v _msg _new _d
1325157653Sflz	_name=$1
132678344Sobrien
1327219612Sdougb	if ${_rc_conf_loaded:-false}; then
1328219612Sdougb		:
1329219612Sdougb	else
133098186Sgordon		if [ -r /etc/defaults/rc.conf ]; then
133198186Sgordon			debug "Sourcing /etc/defaults/rc.conf"
133298186Sgordon			. /etc/defaults/rc.conf
133398186Sgordon			source_rc_confs
133498186Sgordon		elif [ -r /etc/rc.conf ]; then
133598186Sgordon			debug "Sourcing /etc/rc.conf (/etc/defaults/rc.conf doesn't exist)."
133698186Sgordon			. /etc/rc.conf
133798186Sgordon		fi
1338126285Smtm		_rc_conf_loaded=true
133998186Sgordon	fi
1340179872Smtm
1341275359Sdes	# If a service name was specified, attempt to load
1342275359Sdes	# service-specific configuration
1343275359Sdes	if [ -n "$_name" ] ; then
1344286163Sjilles		for _d in /etc ${local_startup}; do
1345286163Sjilles			_d=${_d%/rc.d}
1346275359Sdes			if [ -f ${_d}/rc.conf.d/"$_name" ]; then
1347275359Sdes				debug "Sourcing ${_d}/rc.conf.d/$_name"
1348275359Sdes				. ${_d}/rc.conf.d/"$_name"
1349275359Sdes			elif [ -d ${_d}/rc.conf.d/"$_name" ] ; then
1350275359Sdes				local _rc
1351275359Sdes				for _rc in ${_d}/rc.conf.d/"$_name"/* ; do
1352275359Sdes					if [ -f "$_rc" ] ; then
1353275359Sdes						debug "Sourcing $_rc"
1354275359Sdes						. "$_rc"
1355275359Sdes					fi
1356275359Sdes				done
1357275359Sdes			fi
1358275359Sdes		done
1359275359Sdes	fi
1360270698Shrs
1361197144Shrs	# Set defaults if defined.
1362272393Shrs	for _var in $rcvar $rcvars; do
1363223227Sjilles		eval _defval=\$${_var}_defval
1364197144Shrs		if [ -n "$_defval" ]; then
1365197144Shrs			eval : \${$_var:=\$${_var}_defval}
1366197144Shrs		fi
1367197144Shrs	done
1368197144Shrs
1369197144Shrs	# check obsolete rc.conf variables
1370197144Shrs	for _var in $rcvars_obsolete; do
1371223227Sjilles		eval _v=\$$_var
1372223227Sjilles		eval _msg=\$${_var}_obsolete_msg
1373223227Sjilles		eval _new=\$${_var}_newvar
1374197144Shrs		case $_v in
1375197144Shrs		"")
1376197144Shrs			;;
1377197144Shrs		*)
1378197144Shrs			if [ -z "$_new" ]; then
1379197144Shrs				_msg="Ignored."
1380197144Shrs			else
1381197144Shrs				eval $_new=\"\$$_var\"
1382197144Shrs				if [ -z "$_msg" ]; then
1383197144Shrs					_msg="Use \$$_new instead."
1384197144Shrs				fi
1385197144Shrs			fi
1386197144Shrs			warn "\$$_var is obsolete.  $_msg"
1387197144Shrs			;;
1388197144Shrs		esac
1389197144Shrs	done
139078344Sobrien}
1391201036Sdougb
1392157473Sflz#
1393157653Sflz# load_rc_config_var name var
1394157653Sflz#	Read the rc.conf(5) var for name and set in the
1395157473Sflz#	current shell, using load_rc_config in a subshell to prevent
1396157473Sflz#	unwanted side effects from other variable assignments.
1397157473Sflz#
1398157473Sflzload_rc_config_var()
1399157473Sflz{
1400157473Sflz	if [ $# -ne 2 ]; then
1401157653Sflz		err 3 'USAGE: load_rc_config_var name var'
1402157473Sflz	fi
1403157473Sflz	eval $(eval '(
1404157473Sflz		load_rc_config '$1' >/dev/null;
1405157473Sflz                if [ -n "${'$2'}" -o "${'$2'-UNSET}" != "UNSET" ]; then
1406157473Sflz			echo '$2'=\'\''${'$2'}\'\'';
1407157473Sflz		fi
1408157473Sflz	)' )
1409157473Sflz}
141078344Sobrien
141178344Sobrien#
141278344Sobrien# rc_usage commands
141378344Sobrien#	Print a usage string for $0, with `commands' being a list of
141478344Sobrien#	valid commands.
141578344Sobrien#
141678344Sobrienrc_usage()
141778344Sobrien{
1418230007Srea	echo -n 1>&2 "Usage: $0 [fast|force|one|quiet]("
141978344Sobrien
142078344Sobrien	_sep=
1421126286Smtm	for _elem; do
142278344Sobrien		echo -n 1>&2 "$_sep$_elem"
142378344Sobrien		_sep="|"
142478344Sobrien	done
142578344Sobrien	echo 1>&2 ")"
142678344Sobrien	exit 1
142778344Sobrien}
142878344Sobrien
142978344Sobrien#
143078344Sobrien# err exitval message
143178344Sobrien#	Display message to stderr and log to the syslog, and exit with exitval.
143278344Sobrien#
143378344Sobrienerr()
143478344Sobrien{
143578344Sobrien	exitval=$1
143678344Sobrien	shift
143778344Sobrien
1438106643Sgordon	if [ -x /usr/bin/logger ]; then
1439106643Sgordon		logger "$0: ERROR: $*"
1440106643Sgordon	fi
1441106643Sgordon	echo 1>&2 "$0: ERROR: $*"
144278344Sobrien	exit $exitval
144378344Sobrien}
144478344Sobrien
144578344Sobrien#
144678344Sobrien# warn message
144778344Sobrien#	Display message to stderr and log to the syslog.
144878344Sobrien#
144978344Sobrienwarn()
145078344Sobrien{
1451106643Sgordon	if [ -x /usr/bin/logger ]; then
1452106643Sgordon		logger "$0: WARNING: $*"
1453106643Sgordon	fi
1454106643Sgordon	echo 1>&2 "$0: WARNING: $*"
145578344Sobrien}
145698186Sgordon
145798186Sgordon#
145898186Sgordon# info message
145998186Sgordon#	Display informational message to stdout and log to syslog.
146098186Sgordon#
146198186Sgordoninfo()
146298186Sgordon{
1463119170Smtm	case ${rc_info} in
1464119170Smtm	[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
1465119170Smtm		if [ -x /usr/bin/logger ]; then
1466119170Smtm			logger "$0: INFO: $*"
1467119170Smtm		fi
1468119170Smtm		echo "$0: INFO: $*"
1469119170Smtm		;;
1470119170Smtm	esac
147198186Sgordon}
147298186Sgordon
147398186Sgordon#
147498186Sgordon# debug message
1475106643Sgordon#	If debugging is enabled in rc.conf output message to stderr.
147698186Sgordon#	BEWARE that you don't call any subroutine that itself calls this
147798186Sgordon#	function.
147898186Sgordon#
147998186Sgordondebug()
148098186Sgordon{
148198186Sgordon	case ${rc_debug} in
148298186Sgordon	[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
1483106700Sgordon		if [ -x /usr/bin/logger ]; then
1484162947Syar			logger "$0: DEBUG: $*"
1485106700Sgordon		fi
1486146490Sschweikh		echo 1>&2 "$0: DEBUG: $*"
148798186Sgordon		;;
148898186Sgordon	esac
148998186Sgordon}
149098186Sgordon
149198186Sgordon#
149298186Sgordon# backup_file action file cur backup
149398186Sgordon#	Make a backup copy of `file' into `cur', and save the previous
149498186Sgordon#	version of `cur' as `backup' or use rcs for archiving.
149598186Sgordon#
149698186Sgordon#	This routine checks the value of the backup_uses_rcs variable,
149798186Sgordon#	which can be either YES or NO.
149898186Sgordon#
149998186Sgordon#	The `action' keyword can be one of the following:
150098186Sgordon#
150198186Sgordon#	add		`file' is now being backed up (and is possibly
150298186Sgordon#			being reentered into the backups system).  `cur'
150398186Sgordon#			is created and RCS files, if necessary, are
150498186Sgordon#			created as well.
150598186Sgordon#
150698186Sgordon#	update		`file' has changed and needs to be backed up.
150798186Sgordon#			If `cur' exists, it is copied to to `back' or
150898186Sgordon#			checked into RCS (if the repository file is old),
150998186Sgordon#			and then `file' is copied to `cur'.  Another RCS
151098186Sgordon#			check in done here if RCS is being used.
151198186Sgordon#
151298186Sgordon#	remove		`file' is no longer being tracked by the backups
151398186Sgordon#			system.  If RCS is not being used, `cur' is moved
151498186Sgordon#			to `back', otherwise an empty file is checked in,
151598186Sgordon#			and then `cur' is removed.
151698186Sgordon#
151798186Sgordon#
151898186Sgordonbackup_file()
151998186Sgordon{
152098186Sgordon	_action=$1
152198186Sgordon	_file=$2
152298186Sgordon	_cur=$3
152398186Sgordon	_back=$4
152498186Sgordon
152598186Sgordon	if checkyesno backup_uses_rcs; then
152698186Sgordon		_msg0="backup archive"
152798186Sgordon		_msg1="update"
152898186Sgordon
152998186Sgordon		# ensure that history file is not locked
153098186Sgordon		if [ -f $_cur,v ]; then
153198186Sgordon			rcs -q -u -U -M $_cur
153298186Sgordon		fi
153398186Sgordon
153498186Sgordon		# ensure after switching to rcs that the
153598186Sgordon		# current backup is not lost
153698186Sgordon		if [ -f $_cur ]; then
153798186Sgordon			# no archive, or current newer than archive
153898186Sgordon			if [ ! -f $_cur,v -o $_cur -nt $_cur,v ]; then
153998186Sgordon				ci -q -f -u -t-"$_msg0" -m"$_msg1" $_cur
154098186Sgordon				rcs -q -kb -U $_cur
154198186Sgordon				co -q -f -u $_cur
154298186Sgordon			fi
154398186Sgordon		fi
154498186Sgordon
154598186Sgordon		case $_action in
154698186Sgordon		add|update)
154798186Sgordon			cp -p $_file $_cur
154898186Sgordon			ci -q -f -u -t-"$_msg0" -m"$_msg1" $_cur
154998186Sgordon			rcs -q -kb -U $_cur
155098186Sgordon			co -q -f -u $_cur
155198186Sgordon			chown root:wheel $_cur $_cur,v
155298186Sgordon			;;
155398186Sgordon		remove)
155498186Sgordon			cp /dev/null $_cur
155598186Sgordon			ci -q -f -u -t-"$_msg0" -m"$_msg1" $_cur
155698186Sgordon			rcs -q -kb -U $_cur
155798186Sgordon			chown root:wheel $_cur $_cur,v
155898186Sgordon			rm $_cur
155998186Sgordon			;;
156098186Sgordon		esac
156198186Sgordon	else
156298186Sgordon		case $_action in
156398186Sgordon		add|update)
156498186Sgordon			if [ -f $_cur ]; then
156598186Sgordon				cp -p $_cur $_back
156698186Sgordon			fi
156798186Sgordon			cp -p $_file $_cur
156898186Sgordon			chown root:wheel $_cur
156998186Sgordon			;;
157098186Sgordon		remove)
157198186Sgordon			mv -f $_cur $_back
157298186Sgordon			;;
157398186Sgordon		esac
157498186Sgordon	fi
157598186Sgordon}
1576119166Smtm
1577123344Smtm# make_symlink src link
1578123344Smtm#	Make a symbolic link 'link' to src from basedir. If the
1579123344Smtm#	directory in which link is to be created does not exist
1580123344Smtm#	a warning will be displayed and an error will be returned.
1581229783Suqs#	Returns 0 on success, 1 otherwise.
1582119166Smtm#
1583123344Smtmmake_symlink()
1584119166Smtm{
1585123344Smtm	local src link linkdir _me
1586123344Smtm	src="$1"
1587123344Smtm	link="$2"
1588123344Smtm	linkdir="`dirname $link`"
1589123344Smtm	_me="make_symlink()"
1590119166Smtm
1591123344Smtm	if [ -z "$src" -o -z "$link" ]; then
1592123344Smtm		warn "$_me: requires two arguments."
1593119166Smtm		return 1
1594119166Smtm	fi
1595123344Smtm	if [ ! -d "$linkdir" ]; then
1596160667Syar		warn "$_me: the directory $linkdir does not exist."
1597119166Smtm		return 1
1598119166Smtm	fi
1599146490Sschweikh	if ! ln -sf $src $link; then
1600123344Smtm		warn "$_me: unable to make a symbolic link from $link to $src"
1601119166Smtm		return 1
1602119166Smtm	fi
1603119166Smtm	return 0
1604119166Smtm}
1605119166Smtm
1606119166Smtm# devfs_rulesets_from_file file
1607119166Smtm#	Reads a set of devfs commands from file, and creates
1608119166Smtm#	the specified rulesets with their rules. Returns non-zero
1609119166Smtm#	if there was an error.
1610119166Smtm#
1611119166Smtmdevfs_rulesets_from_file()
1612119166Smtm{
1613248820Savg	local file _err _me _opts
1614119166Smtm	file="$1"
1615119166Smtm	_me="devfs_rulesets_from_file"
1616119166Smtm	_err=0
1617119166Smtm
1618119166Smtm	if [ -z "$file" ]; then
1619119166Smtm		warn "$_me: you must specify a file"
1620119166Smtm		return 1
1621119166Smtm	fi
1622119166Smtm	if [ ! -e "$file" ]; then
1623119166Smtm		debug "$_me: no such file ($file)"
1624119166Smtm		return 0
1625119166Smtm	fi
1626248820Savg
1627248820Savg	# Disable globbing so that the rule patterns are not expanded
1628248820Savg	# by accident with matching filesystem entries.
1629248820Savg	_opts=$-; set -f
1630248820Savg
1631119166Smtm	debug "reading rulesets from file ($file)"
1632119166Smtm	{ while read line
1633119166Smtm	do
1634119166Smtm		case $line in
1635119166Smtm		\#*)
1636119166Smtm			continue
1637119166Smtm			;;
1638119166Smtm		\[*\]*)
1639119166Smtm			rulenum=`expr "$line" : "\[.*=\([0-9]*\)\]"`
1640119166Smtm			if [ -z "$rulenum" ]; then
1641119166Smtm				warn "$_me: cannot extract rule number ($line)"
1642119166Smtm				_err=1
1643119166Smtm				break
1644119166Smtm			fi
1645119166Smtm			rulename=`expr "$line" : "\[\(.*\)=[0-9]*\]"`
1646119166Smtm			if [ -z "$rulename" ]; then
1647119166Smtm				warn "$_me: cannot extract rule name ($line)"
1648119166Smtm				_err=1
1649119166Smtm				break;
1650119166Smtm			fi
1651119166Smtm			eval $rulename=\$rulenum
1652119166Smtm			debug "found ruleset: $rulename=$rulenum"
1653146490Sschweikh			if ! /sbin/devfs rule -s $rulenum delset; then
1654119166Smtm				_err=1
1655119166Smtm				break
1656119166Smtm			fi
1657119166Smtm			;;
1658119166Smtm		*)
1659119166Smtm			rulecmd="${line%%"\#*"}"
1660119166Smtm			# evaluate the command incase it includes
1661119166Smtm			# other rules
1662119166Smtm			if [ -n "$rulecmd" ]; then
1663119166Smtm				debug "adding rule ($rulecmd)"
1664119166Smtm				if ! eval /sbin/devfs rule -s $rulenum $rulecmd
1665119166Smtm				then
1666119166Smtm					_err=1
1667119166Smtm					break
1668119166Smtm				fi
1669119166Smtm			fi
1670119166Smtm			;;
1671119166Smtm		esac
1672119166Smtm		if [ $_err -ne 0 ]; then
1673119166Smtm			debug "error in $_me"
1674119166Smtm			break
1675119166Smtm		fi
1676119166Smtm	done } < $file
1677248820Savg	case $_opts in *f*) ;; *) set +f ;; esac
1678119166Smtm	return $_err
1679119166Smtm}
1680119166Smtm
1681119166Smtm# devfs_init_rulesets
1682119166Smtm#	Initializes rulesets from configuration files. Returns
1683119166Smtm#	non-zero if there was an error.
1684119166Smtm#
1685119166Smtmdevfs_init_rulesets()
1686119166Smtm{
1687119166Smtm	local file _me
1688119166Smtm	_me="devfs_init_rulesets"
1689119166Smtm
1690119166Smtm	# Go through this only once
1691119166Smtm	if [ -n "$devfs_rulesets_init" ]; then
1692119166Smtm		debug "$_me: devfs rulesets already initialized"
1693119166Smtm		return
1694119166Smtm	fi
1695146490Sschweikh	for file in $devfs_rulesets; do
1696217090Sjh		if ! devfs_rulesets_from_file $file; then
1697217090Sjh			warn "$_me: could not read rules from $file"
1698217090Sjh			return 1
1699217090Sjh		fi
1700119166Smtm	done
1701119166Smtm	devfs_rulesets_init=1
1702119166Smtm	debug "$_me: devfs rulesets initialized"
1703119166Smtm	return 0
1704119166Smtm}
1705119166Smtm
1706119166Smtm# devfs_set_ruleset ruleset [dir]
1707151619Smaxim#	Sets the default ruleset of dir to ruleset. The ruleset argument
1708119166Smtm#	must be a ruleset name as specified in devfs.rules(5) file.
1709119166Smtm#	Returns non-zero if it could not set it successfully.
1710119166Smtm#
1711119166Smtmdevfs_set_ruleset()
1712119166Smtm{
1713119166Smtm	local devdir rs _me
1714119166Smtm	[ -n "$1" ] && eval rs=\$$1 || rs=
1715119166Smtm	[ -n "$2" ] && devdir="-m "$2"" || devdir=
1716119166Smtm	_me="devfs_set_ruleset"
1717119166Smtm
1718119166Smtm	if [ -z "$rs" ]; then
1719119166Smtm		warn "$_me: you must specify a ruleset number"
1720119166Smtm		return 1
1721119166Smtm	fi
1722119166Smtm	debug "$_me: setting ruleset ($rs) on mount-point (${devdir#-m })"
1723146490Sschweikh	if ! /sbin/devfs $devdir ruleset $rs; then
1724119166Smtm		warn "$_me: unable to set ruleset $rs to ${devdir#-m }"
1725119166Smtm		return 1
1726119166Smtm	fi
1727119166Smtm	return 0
1728119166Smtm}
1729119166Smtm
1730119166Smtm# devfs_apply_ruleset ruleset [dir]
1731119166Smtm#	Apply ruleset number $ruleset to the devfs mountpoint $dir.
1732119166Smtm#	The ruleset argument must be a ruleset name as specified
1733119166Smtm#	in a devfs.rules(5) file.  Returns 0 on success or non-zero
1734119166Smtm#	if it could not apply the ruleset.
1735119166Smtm#
1736119166Smtmdevfs_apply_ruleset()
1737119166Smtm{
1738119166Smtm	local devdir rs _me
1739119166Smtm	[ -n "$1" ] && eval rs=\$$1 || rs=
1740119166Smtm	[ -n "$2" ] && devdir="-m "$2"" || devdir=
1741119166Smtm	_me="devfs_apply_ruleset"
1742119166Smtm
1743119166Smtm	if [ -z "$rs" ]; then
1744119166Smtm		warn "$_me: you must specify a ruleset"
1745119166Smtm		return 1
1746119166Smtm	fi
1747119166Smtm	debug "$_me: applying ruleset ($rs) to mount-point (${devdir#-m })"
1748146490Sschweikh	if ! /sbin/devfs $devdir rule -s $rs applyset; then
1749119166Smtm		warn "$_me: unable to apply ruleset $rs to ${devdir#-m }"
1750119166Smtm		return 1
1751119166Smtm	fi
1752119166Smtm	return 0
1753119166Smtm}
1754119166Smtm
1755119166Smtm# devfs_domount dir [ruleset]
1756119166Smtm#	Mount devfs on dir. If ruleset is specified it is set
1757119166Smtm#	on the mount-point. It must also be a ruleset name as specified
1758119166Smtm#	in a devfs.rules(5) file. Returns 0 on success.
1759119166Smtm#
1760119166Smtmdevfs_domount()
1761119166Smtm{
1762119166Smtm	local devdir rs _me
1763119166Smtm	devdir="$1"
1764119166Smtm	[ -n "$2" ] && rs=$2 || rs=
1765119166Smtm	_me="devfs_domount()"
1766119166Smtm
1767119166Smtm	if [ -z "$devdir" ]; then
1768119166Smtm		warn "$_me: you must specify a mount-point"
1769119166Smtm		return 1
1770119166Smtm	fi
1771119166Smtm	debug "$_me: mount-point is ($devdir), ruleset is ($rs)"
1772146490Sschweikh	if ! mount -t devfs dev "$devdir"; then
1773119166Smtm		warn "$_me: Unable to mount devfs on $devdir"
1774119166Smtm		return 1
1775119166Smtm	fi
1776119166Smtm	if [ -n "$rs" ]; then
1777119166Smtm		devfs_init_rulesets
1778119166Smtm		devfs_set_ruleset $rs $devdir
1779124797Scperciva		devfs -m $devdir rule applyset
1780119166Smtm	fi
1781119166Smtm	return 0
1782119166Smtm}
1783119166Smtm
1784127345Sbrooks# Provide a function for normalizing the mounting of memory
1785127345Sbrooks# filesystems.  This should allow the rest of the code here to remain
1786127345Sbrooks# as close as possible between 5-current and 4-stable.
1787127345Sbrooks#   $1 = size
1788127345Sbrooks#   $2 = mount point
1789137451Skeramida#   $3 = (optional) extra mdmfs flags
1790146490Sschweikhmount_md()
1791146490Sschweikh{
1792127345Sbrooks	if [ -n "$3" ]; then
1793137451Skeramida		flags="$3"
1794127345Sbrooks	fi
1795149421Syar	/sbin/mdmfs $flags -s $1 md $2
1796127345Sbrooks}
1797131550Scperciva
1798159828Syar# Code common to scripts that need to load a kernel module
1799159828Syar# if it isn't in the kernel yet. Syntax:
1800160666Syar#   load_kld [-e regex] [-m module] file
1801159828Syar# where -e or -m chooses the way to check if the module
1802159828Syar# is already loaded:
1803160666Syar#   regex is egrep'd in the output from `kldstat -v',
1804160666Syar#   module is passed to `kldstat -m'.
1805160666Syar# The default way is as though `-m file' were specified.
1806159828Syarload_kld()
1807159828Syar{
1808159828Syar	local _loaded _mod _opt _re
1809159828Syar
1810159828Syar	while getopts "e:m:" _opt; do
1811159828Syar		case "$_opt" in
1812159828Syar		e) _re="$OPTARG" ;;
1813159828Syar		m) _mod="$OPTARG" ;;
1814160666Syar		*) err 3 'USAGE: load_kld [-e regex] [-m module] file' ;;
1815159828Syar		esac
1816159828Syar	done
1817159828Syar	shift $(($OPTIND - 1))
1818160666Syar	if [ $# -ne 1 ]; then
1819160666Syar		err 3 'USAGE: load_kld [-e regex] [-m module] file'
1820160666Syar	fi
1821159828Syar	_mod=${_mod:-$1}
1822159828Syar	_loaded=false
1823159828Syar	if [ -n "$_re" ]; then
1824159828Syar		if kldstat -v | egrep -q -e "$_re"; then
1825159828Syar			_loaded=true
1826159828Syar		fi
1827159828Syar	else
1828159828Syar		if kldstat -q -m "$_mod"; then
1829159828Syar			_loaded=true
1830159828Syar		fi
1831159828Syar	fi
1832159828Syar	if ! $_loaded; then
1833159828Syar		if ! kldload "$1"; then
1834159828Syar			warn "Unable to load kernel module $1"
1835159828Syar			return 1
1836160666Syar		else
1837160666Syar			info "$1 kernel module loaded."
1838159828Syar		fi
1839160666Syar	else
1840160666Syar		debug "load_kld: $1 kernel module already loaded."
1841159828Syar	fi
1842159828Syar	return 0
1843159828Syar}
1844159828Syar
1845264243Sdteske# ltr str src dst [var]
1846149049Spjd#	Change every $src in $str to $dst.
1847149049Spjd#	Useful when /usr is not yet mounted and we cannot use tr(1), sed(1) nor
1848264243Sdteske#	awk(1). If var is non-NULL, set it to the result.
1849149049Spjdltr()
1850149049Spjd{
1851264243Sdteske	local _str _src _dst _out _com _var
1852264243Sdteske	_str="$1"
1853264243Sdteske	_src="$2"
1854264243Sdteske	_dst="$3"
1855264243Sdteske	_var="$4"
1856149049Spjd	_out=""
1857149049Spjd
1858264243Sdteske	local IFS="${_src}"
1859149049Spjd	for _com in ${_str}; do
1860149049Spjd		if [ -z "${_out}" ]; then
1861149049Spjd			_out="${_com}"
1862149049Spjd		else
1863149049Spjd			_out="${_out}${_dst}${_com}"
1864149049Spjd		fi
1865149049Spjd	done
1866264243Sdteske	if [ -n "${_var}" ]; then
1867264243Sdteske		setvar "${_var}" "${_out}"
1868264243Sdteske	else
1869264243Sdteske		echo "${_out}"
1870264243Sdteske	fi
1871149049Spjd}
1872149049Spjd
1873149050Spjd# Creates a list of providers for GELI encryption.
1874149050Spjdgeli_make_list()
1875149050Spjd{
1876149050Spjd	local devices devices2
1877149050Spjd	local provider mountpoint type options rest
1878149050Spjd
1879149050Spjd	# Create list of GELI providers from fstab.
1880149050Spjd	while read provider mountpoint type options rest ; do
1881155570Sflz		case ":${options}" in
1882155570Sflz		:*noauto*)
1883155570Sflz			noauto=yes
1884155570Sflz			;;
1885155570Sflz		*)
1886155570Sflz			noauto=no
1887155570Sflz			;;
1888155570Sflz		esac
1889155570Sflz
1890149050Spjd		case ":${provider}" in
1891149050Spjd		:#*)
1892149050Spjd			continue
1893149050Spjd			;;
1894149050Spjd		*.eli)
1895149050Spjd			# Skip swap devices.
1896155570Sflz			if [ "${type}" = "swap" -o "${options}" = "sw" -o "${noauto}" = "yes" ]; then
1897149050Spjd				continue
1898149050Spjd			fi
1899149050Spjd			devices="${devices} ${provider}"
1900149050Spjd			;;
1901149050Spjd		esac
1902149050Spjd	done < /etc/fstab
1903149050Spjd
1904149050Spjd	# Append providers from geli_devices.
1905149050Spjd	devices="${devices} ${geli_devices}"
1906149050Spjd
1907149050Spjd	for provider in ${devices}; do
1908149050Spjd		provider=${provider%.eli}
1909149050Spjd		provider=${provider#/dev/}
1910149050Spjd		devices2="${devices2} ${provider}"
1911149050Spjd	done
1912149050Spjd
1913149050Spjd	echo ${devices2}
1914149050Spjd}
1915149050Spjd
1916153027Sdougb# Find scripts in local_startup directories that use the old syntax
1917153027Sdougb#
1918238416Skevlofind_local_scripts_old() {
1919153027Sdougb	zlist=''
1920153027Sdougb	slist=''
1921153027Sdougb	for dir in ${local_startup}; do
1922153027Sdougb		if [ -d "${dir}" ]; then
1923153027Sdougb			for file in ${dir}/[0-9]*.sh; do
1924153027Sdougb				grep '^# PROVIDE:' $file >/dev/null 2>&1 &&
1925153027Sdougb				    continue
1926153027Sdougb				zlist="$zlist $file"
1927153027Sdougb			done
1928227366Sjilles			for file in ${dir}/[!0-9]*.sh; do
1929153027Sdougb				grep '^# PROVIDE:' $file >/dev/null 2>&1 &&
1930153027Sdougb				    continue
1931153027Sdougb				slist="$slist $file"
1932153027Sdougb			done
1933153027Sdougb		fi
1934153027Sdougb	done
1935153027Sdougb}
1936153027Sdougb
1937238416Skevlofind_local_scripts_new() {
1938153027Sdougb	local_rc=''
1939153027Sdougb	for dir in ${local_startup}; do
1940153027Sdougb		if [ -d "${dir}" ]; then
1941153297Sdougb			for file in `grep -l '^# PROVIDE:' ${dir}/* 2>/dev/null`; do
1942153027Sdougb				case "$file" in
1943153027Sdougb				*.sample) ;;
1944153027Sdougb				*)	if [ -x "$file" ]; then
1945153027Sdougb						local_rc="${local_rc} ${file}"
1946153027Sdougb					fi
1947153027Sdougb					;;
1948153027Sdougb				esac
1949153027Sdougb			done
1950153027Sdougb		fi
1951153027Sdougb	done
1952153027Sdougb}
1953153027Sdougb
1954165565Syar# check_required_{before|after} command
1955165565Syar#	Check for things required by the command before and after its precmd,
1956165565Syar#	respectively.  The two separate functions are needed because some
1957165565Syar#	conditions should prevent precmd from being run while other things
1958165565Syar#	depend on precmd having already been run.
1959165565Syar#
1960165565Syarcheck_required_before()
1961165565Syar{
1962165565Syar	local _f
1963165565Syar
1964165565Syar	case "$1" in
1965165565Syar	start)
1966165565Syar		for _f in $required_vars; do
1967165565Syar			if ! checkyesno $_f; then
1968165565Syar				warn "\$${_f} is not enabled."
1969165565Syar				if [ -z "$rc_force" ]; then
1970165565Syar					return 1
1971165565Syar				fi
1972165565Syar			fi
1973165565Syar		done
1974165565Syar
1975165565Syar		for _f in $required_dirs; do
1976165565Syar			if [ ! -d "${_f}/." ]; then
1977165565Syar				warn "${_f} is not a directory."
1978165565Syar				if [ -z "$rc_force" ]; then
1979165565Syar					return 1
1980165565Syar				fi
1981165565Syar			fi
1982165565Syar		done
1983165565Syar
1984165565Syar		for _f in $required_files; do
1985165565Syar			if [ ! -r "${_f}" ]; then
1986165565Syar				warn "${_f} is not readable."
1987165565Syar				if [ -z "$rc_force" ]; then
1988165565Syar					return 1
1989165565Syar				fi
1990165565Syar			fi
1991165565Syar		done
1992165565Syar		;;
1993165565Syar	esac
1994165565Syar
1995165565Syar	return 0
1996165565Syar}
1997165565Syar
1998165565Syarcheck_required_after()
1999165565Syar{
2000165565Syar	local _f _args
2001165565Syar
2002165565Syar	case "$1" in
2003165565Syar	start)
2004165565Syar		for _f in $required_modules; do
2005165565Syar			case "${_f}" in
2006165565Syar				*~*)	_args="-e ${_f#*~} ${_f%%~*}" ;;
2007165565Syar				*:*)	_args="-m ${_f#*:} ${_f%%:*}" ;;
2008165565Syar				*)	_args="${_f}" ;;
2009165565Syar			esac
2010165565Syar			if ! load_kld ${_args}; then
2011165565Syar				if [ -z "$rc_force" ]; then
2012165565Syar					return 1
2013165565Syar				fi
2014165565Syar			fi
2015165565Syar		done
2016165565Syar		;;
2017165565Syar	esac
2018165565Syar
2019165565Syar	return 0
2020165565Syar}
2021165565Syar
2022271545Shrs# check_jail mib
2023271545Shrs#	Return true if security.jail.$mib exists and set to 1.
2024271545Shrs
2025271545Shrscheck_jail()
2026271545Shrs{
2027271545Shrs	local _mib _v
2028271545Shrs
2029271545Shrs	_mib=$1
2030271545Shrs	if _v=$(${SYSCTL_N} "security.jail.$_mib" 2> /dev/null); then
2031271545Shrs		case $_v in
2032271545Shrs		1)	return 0;;
2033271545Shrs		esac
2034271545Shrs	fi
2035271545Shrs	return 1
2036271545Shrs}
2037271545Shrs
2038222996Shrs# check_kern_features mib
2039222996Shrs#	Return existence of kern.features.* sysctl MIB as true or
2040222996Shrs#	false.  The result will be cached in $_rc_cache_kern_features_
2041222996Shrs#	namespace.  "0" means the kern.features.X exists.
2042222996Shrs
2043222996Shrscheck_kern_features()
2044222996Shrs{
2045222996Shrs	local _v
2046222996Shrs
2047222996Shrs	[ -n "$1" ] || return 1;
2048223292Sjilles	eval _v=\$_rc_cache_kern_features_$1
2049222996Shrs	[ -n "$_v" ] && return "$_v";
2050222996Shrs
2051222996Shrs	if ${SYSCTL_N} kern.features.$1 > /dev/null 2>&1; then
2052222996Shrs		eval _rc_cache_kern_features_$1=0
2053222996Shrs		return 0
2054222996Shrs	else
2055222996Shrs		eval _rc_cache_kern_features_$1=1
2056222996Shrs		return 1
2057222996Shrs	fi
2058222996Shrs}
2059222996Shrs
2060243184Shrs# check_namevarlist var
2061243184Shrs#	Return "0" if ${name}_var is reserved in rc.subr.
2062243184Shrs
2063272976Shrs_rc_namevarlist="program chroot chdir env flags fib nice user group groups prepend"
2064243184Shrscheck_namevarlist()
2065243184Shrs{
2066243184Shrs	local _v
2067243184Shrs
2068243184Shrs	for _v in $_rc_namevarlist; do
2069243184Shrs	case $1 in
2070243184Shrs	$_v)	return 0 ;;
2071243184Shrs	esac
2072243184Shrs	done
2073243184Shrs
2074243184Shrs	return 1
2075243184Shrs}
2076243184Shrs
2077197144Shrs# _echoonce var msg mode
2078197144Shrs#	mode=0: Echo $msg if ${$var} is empty.
2079197144Shrs#	        After doing echo, a string is set to ${$var}.
2080197144Shrs#
2081197144Shrs#	mode=1: Echo $msg if ${$var} is a string with non-zero length.
2082197144Shrs#
2083197144Shrs_echoonce()
2084197144Shrs{
2085197144Shrs	local _var _msg _mode
2086223227Sjilles	eval _var=\$$1
2087197144Shrs	_msg=$2
2088197144Shrs	_mode=$3
2089197144Shrs
2090197144Shrs	case $_mode in
2091197144Shrs	1)	[ -n "$_var" ] && echo "$_msg" ;;
2092197144Shrs	*)	[ -z "$_var" ] && echo -n "$_msg" && eval "$1=finished" ;;
2093197144Shrs	esac
2094197144Shrs}
2095197144Shrs
2096223298Sjillesfi # [ -z "${_rc_subr_loaded}" ]
2097223298Sjilles
2098157841Sflz_rc_subr_loaded=:
2099