rc.subr revision 175676
10SN/A# $NetBSD: rc.subr,v 1.67 2006/10/07 11:25:15 elad Exp $
26073SN/A# $FreeBSD: head/etc/rc.subr 175676 2008-01-26 11:22:12Z mtm $
30SN/A#
40SN/A# Copyright (c) 1997-2004 The NetBSD Foundation, Inc.
50SN/A# All rights reserved.
60SN/A#
72362SN/A# This code is derived from software contributed to The NetBSD Foundation
80SN/A# by Luke Mewburn.
92362SN/A#
100SN/A# Redistribution and use in source and binary forms, with or without
110SN/A# modification, are permitted provided that the following conditions
120SN/A# are met:
130SN/A# 1. Redistributions of source code must retain the above copyright
140SN/A#    notice, this list of conditions and the following disclaimer.
150SN/A# 2. Redistributions in binary form must reproduce the above copyright
160SN/A#    notice, this list of conditions and the following disclaimer in the
170SN/A#    documentation and/or other materials provided with the distribution.
180SN/A# 3. All advertising materials mentioning features or use of this software
190SN/A#    must display the following acknowledgement:
200SN/A#        This product includes software developed by the NetBSD
212362SN/A#        Foundation, Inc. and its contributors.
222362SN/A# 4. Neither the name of The NetBSD Foundation nor the names of its
232362SN/A#    contributors may be used to endorse or promote products derived
240SN/A#    from this software without specific prior written permission.
250SN/A#
260SN/A# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
270SN/A# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
280SN/A# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
290SN/A# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
300SN/A# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
310SN/A# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
320SN/A# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
330SN/A# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
340SN/A# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
350SN/A# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
360SN/A# POSSIBILITY OF SUCH DAMAGE.
370SN/A#
380SN/A# rc.subr
390SN/A#	functions used by various rc scripts
400SN/A#
410SN/A
420SN/A: ${rcvar_manpage:='rc.conf(5)'}
430SN/A: ${RC_PID:=$$}; export RC_PID
440SN/A
450SN/A#
460SN/A#	Operating System dependent/independent variables
470SN/A#
480SN/A
4913344Sredestadif [ -z "${_rc_subr_loaded}" ]; then
500SN/A
510SN/A_rc_subr_loaded="YES"
520SN/A
530SN/ASYSCTL="/sbin/sysctl"
540SN/ASYSCTL_N="${SYSCTL} -n"
550SN/ACMD_OSTYPE="${SYSCTL_N} kern.ostype"
560SN/AOSTYPE=`${CMD_OSTYPE}`
570SN/AID="/usr/bin/id"
580SN/AIDCMD="if [ -x $ID ]; then $ID -un; fi"
590SN/APS="/bin/ps -ww"
600SN/AJID=`$PS -p $$ -o jid=`
610SN/A
620SN/Acase ${OSTYPE} in
630SN/AFreeBSD)
640SN/A	SYSCTL_W="${SYSCTL}"
650SN/A	;;
660SN/ANetBSD)
670SN/A	SYSCTL_W="${SYSCTL} -w"
680SN/A	;;
690SN/Aesac
700SN/A
710SN/A#
720SN/A#	functions
730SN/A#	---------
740SN/A
750SN/A#
760SN/A# set_rcvar base_var
770SN/A#	Set the variable name enabling a specific service.
78524SN/A#	FreeBSD uses ${service}_enable, while NetBSD uses
790SN/A#	just the name of the service. For example:
800SN/A#	FreeBSD: sendmail_enable="YES"
810SN/A#	NetBSD : sendmail="YES"
820SN/A#	$1 - if $name is not the base to work of off, specify
830SN/A#	     a different one
840SN/A#
850SN/Aset_rcvar()
860SN/A{
870SN/A	if [ -z "$1" ]; then
880SN/A		base_var=${name}
890SN/A	else
900SN/A		base_var="$1"
910SN/A	fi
920SN/A
930SN/A	case ${OSTYPE} in
940SN/A	FreeBSD)
950SN/A		echo ${base_var}_enable
960SN/A		;;
970SN/A	NetBSD)
980SN/A		echo ${base_var}
990SN/A		;;
1000SN/A	*)
1010SN/A		echo 'XXX'
1020SN/A		;;
1030SN/A	esac
1040SN/A}
1050SN/A
1060SN/A#
1070SN/A# force_depend script
1080SN/A#	Force a service to start. Intended for use by services
1090SN/A#	to resolve dependency issues. It is assumed the caller
1100SN/A#	has check to make sure this call is necessary
1110SN/A#	$1 - filename of script, in /etc/rc.d, to run
1120SN/A#
1130SN/Aforce_depend()
1140SN/A{
1150SN/A	_depend="$1"
1160SN/A
1170SN/A	info "${name} depends on ${_depend}, which will be forced to start."
1180SN/A	if ! /etc/rc.d/${_depend} forcestart; then
1190SN/A		warn "Unable to force ${_depend}. It may already be running."
120524SN/A		return 1
1210SN/A	fi
1220SN/A	return 0
1230SN/A}
124524SN/A
1250SN/A#
1260SN/A# checkyesno var
1270SN/A#	Test $1 variable, and warn if not set to YES or NO.
1280SN/A#	Return 0 if it's "yes" (et al), nonzero otherwise.
1290SN/A#
1300SN/Acheckyesno()
1310SN/A{
1320SN/A	eval _value=\$${1}
1330SN/A	debug "checkyesno: $1 is set to $_value."
1340SN/A	case $_value in
1350SN/A
1360SN/A		#	"yes", "true", "on", or "1"
1370SN/A	[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
1380SN/A		return 0
1390SN/A		;;
1400SN/A
1410SN/A		#	"no", "false", "off", or "0"
1420SN/A	[Nn][Oo]|[Ff][Aa][Ll][Ss][Ee]|[Oo][Ff][Ff]|0)
1430SN/A		return 1
1440SN/A		;;
1450SN/A	*)
1460SN/A		warn "\$${1} is not set properly - see ${rcvar_manpage}."
1470SN/A		return 1
1480SN/A		;;
1490SN/A	esac
1500SN/A}
1510SN/A
1520SN/A#
153524SN/A# reverse_list list
1540SN/A#	print the list in reverse order
1550SN/A#
1560SN/Areverse_list()
1570SN/A{
1580SN/A	_revlist=
1590SN/A	for _revfile; do
1600SN/A		_revlist="$_revfile $_revlist"
1610SN/A	done
1620SN/A	echo $_revlist
1630SN/A}
1640SN/A
1650SN/A# stop_boot always
1660SN/A#	If booting directly to multiuser or $always is enabled,
1670SN/A#	send SIGTERM to the parent (/etc/rc) to abort the boot.
1680SN/A#	Otherwise just exit.
1690SN/A#
1700SN/Astop_boot()
1710SN/A{
1720SN/A	local always
1730SN/A
1742494SN/A	if [ -n "$1" ] && checkyesno $1; then
1750SN/A		always=true
1762494SN/A	else
1770SN/A		always=false
1780SN/A	fi
1790SN/A	if [ "$autoboot" = yes -o "$always" = true ]; then
1800SN/A		echo "ERROR: ABORTING BOOT (sending SIGTERM to parent)!"
1810SN/A		kill -TERM ${RC_PID}
1822494SN/A	fi
1832494SN/A	exit 1
1842494SN/A}
1850SN/A
1860SN/A#
1870SN/A# mount_critical_filesystems type
1880SN/A#	Go through the list of critical filesystems as provided in
1890SN/A#	the rc.conf(5) variable $critical_filesystems_${type}, checking
1909197SN/A#	each one to see if it is mounted, and if it is not, mounting it.
1915934SN/A#
1929197SN/Amount_critical_filesystems()
1932494SN/A{
1942494SN/A	eval _fslist=\$critical_filesystems_${1}
1950SN/A	for _fs in $_fslist; do
1960SN/A		mount | (
1970SN/A			_ismounted=false
1980SN/A			while read what _on on _type type; do
1990SN/A				if [ $on = $_fs ]; then
2000SN/A					_ismounted=true
2010SN/A				fi
2020SN/A			done
2030SN/A			if $_ismounted; then
2040SN/A				:
2050SN/A			else
2060SN/A				mount $_fs >/dev/null 2>&1
2070SN/A			fi
2080SN/A		)
2090SN/A	done
2100SN/A}
2110SN/A
2120SN/A#
2130SN/A# check_pidfile pidfile procname [interpreter]
2140SN/A#	Parses the first line of pidfile for a PID, and ensures
2150SN/A#	that the process is running and matches procname.
2162494SN/A#	Prints the matching PID upon success, nothing otherwise.
2172494SN/A#	interpreter is optional; see _find_processes() for details.
2180SN/A#
2190SN/Acheck_pidfile()
2200SN/A{
2210SN/A	_pidfile=$1
2220SN/A	_procname=$2
2230SN/A	_interpreter=$3
2240SN/A	if [ -z "$_pidfile" -o -z "$_procname" ]; then
2250SN/A		err 3 'USAGE: check_pidfile pidfile procname [interpreter]'
2260SN/A	fi
2270SN/A	if [ ! -f $_pidfile ]; then
2280SN/A		debug "pid file ($_pidfile): not readable."
229524SN/A		return
230524SN/A	fi
231524SN/A	read _pid _junk < $_pidfile
232524SN/A	if [ -z "$_pid" ]; then
233524SN/A		debug "pid file ($_pidfile): no pid in file."
234524SN/A		return
235524SN/A	fi
236524SN/A	_find_processes $_procname ${_interpreter:-.} '-p '"$_pid"
237524SN/A}
238524SN/A
239524SN/A#
2400SN/A# check_process procname [interpreter]
241524SN/A#	Ensures that a process (or processes) named procname is running.
2420SN/A#	Prints a list of matching PIDs.
2430SN/A#	interpreter is optional; see _find_processes() for details.
2440SN/A#
2450SN/Acheck_process()
2460SN/A{
2470SN/A	_procname=$1
248524SN/A	_interpreter=$2
249524SN/A	if [ -z "$_procname" ]; then
250524SN/A		err 3 'USAGE: check_process procname [interpreter]'
251524SN/A	fi
2520SN/A	_find_processes $_procname ${_interpreter:-.} '-ax'
2530SN/A}
254524SN/A
2550SN/A#
2560SN/A# _find_processes procname interpreter psargs
2570SN/A#	Search for procname in the output of ps generated by psargs.
2580SN/A#	Prints the PIDs of any matching processes, space separated.
2590SN/A#
2600SN/A#	If interpreter == ".", check the following variations of procname
2610SN/A#	against the first word of each command:
2620SN/A#		procname
2630SN/A#		`basename procname`
2640SN/A#		`basename procname` + ":"
265524SN/A#		"(" + `basename procname` + ")"
266524SN/A#		"[" + `basename procname` + "]"
267524SN/A#
268524SN/A#	If interpreter != ".", read the first line of procname, remove the
269524SN/A#	leading #!, normalise whitespace, append procname, and attempt to
270524SN/A#	match that against each command, either as is, or with extra words
271524SN/A#	at the end.  As an alternative, to deal with interpreted daemons
272524SN/A#	using perl, the basename of the interpreter plus a colon is also
273524SN/A#	tried as the prefix to procname.
274524SN/A#
275524SN/A_find_processes()
276524SN/A{
277524SN/A	if [ $# -ne 3 ]; then
278524SN/A		err 3 'USAGE: _find_processes procname interpreter psargs'
279524SN/A	fi
280524SN/A	_procname=$1
281524SN/A	_interpreter=$2
282524SN/A	_psargs=$3
283524SN/A
284524SN/A	_pref=
285524SN/A	if [ $_interpreter != "." ]; then	# an interpreted script
286524SN/A		_script=${_chroot}${_chroot:+"/"}$_procname
287524SN/A		if [ -r $_script ]; then
288524SN/A			read _interp < $_script	# read interpreter name
289524SN/A			case "$_interp" in
290524SN/A			\#!*)
291524SN/A				_interp=${_interp#\#!}	# strip #!
292524SN/A				set -- $_interp
293524SN/A				case $1 in
294524SN/A				*/bin/env)
295524SN/A					shift	# drop env to get real name
296524SN/A					;;
297524SN/A				esac
298524SN/A				if [ $_interpreter != $1 ]; then
299524SN/A					warn "\$command_interpreter $_interpreter != $1"
300524SN/A				fi
3010SN/A				;;
3020SN/A			*)
3030SN/A				warn "no shebang line in $_script"
304524SN/A				set -- $_interpreter
305524SN/A				;;
3064216SN/A			esac
3070SN/A		else
3080SN/A			warn "cannot read shebang line from $_script"
3090SN/A			set -- $_interpreter
3104216SN/A		fi
3110SN/A		_interp="$* $_procname"		# cleanup spaces, add _procname
3120SN/A		_interpbn=${1##*/}
3130SN/A		_fp_args='_argv'
314524SN/A		_fp_match='case "$_argv" in
315524SN/A		    ${_interp}|"${_interp} "*|"${_interpbn}: ${_procname}"*)'
3164216SN/A	else					# a normal daemon
3170SN/A		_procnamebn=${_procname##*/}
3180SN/A		_fp_args='_arg0 _argv'
3190SN/A		_fp_match='case "$_arg0" in
3204216SN/A		    $_procname|$_procnamebn|${_procnamebn}:|"(${_procnamebn})"|"[${_procnamebn}]")'
3210SN/A	fi
3220SN/A
3230SN/A	_proccheck="\
3244216SN/A		$PS 2>/dev/null -o pid= -o jid= -o command= $_psargs"' |
3250SN/A		while read _npid _jid '"$_fp_args"'; do
3260SN/A			'"$_fp_match"'
3270SN/A				if [ "$JID" -eq "$_jid" ];
3284216SN/A				then echo -n "$_pref$_npid";
329524SN/A				_pref=" ";
3300SN/A				fi
3310SN/A				;;
3320SN/A			esac
3334216SN/A		done'
3340SN/A
3350SN/A#	debug "in _find_processes: proccheck is ($_proccheck)."
3360SN/A	eval $_proccheck
3374216SN/A}
3380SN/A
3390SN/A#
3400SN/A# wait_for_pids pid [pid ...]
3414216SN/A#	spins until none of the pids exist
3420SN/A#
3430SN/Await_for_pids()
3440SN/A{
3454216SN/A	_list="$@"
3460SN/A	if [ -z "$_list" ]; then
3470SN/A		return
3480SN/A	fi
3490SN/A	_prefix=
3500SN/A	while true; do
3510SN/A		_nlist="";
3520SN/A		for _j in $_list; do
3530SN/A			if kill -0 $_j 2>/dev/null; then
3540SN/A				_nlist="${_nlist}${_nlist:+ }$_j"
3550SN/A			fi
3560SN/A		done
3570SN/A		if [ -z "$_nlist" ]; then
3580SN/A			break
3590SN/A		fi
3600SN/A		_list=$_nlist
3610SN/A		echo -n ${_prefix:-"Waiting for PIDS: "}$_list
3620SN/A		_prefix=", "
3630SN/A		sleep 2
3640SN/A	done
3650SN/A	if [ -n "$_prefix" ]; then
3660SN/A		echo "."
3670SN/A	fi
3680SN/A}
3690SN/A
3700SN/A#
3710SN/A# run_rc_command argument
3720SN/A#	Search for argument in the list of supported commands, which is:
3730SN/A#		"start stop restart rcvar status poll ${extra_commands}"
3740SN/A#	If there's a match, run ${argument}_cmd or the default method
3750SN/A#	(see below).
3760SN/A#
3770SN/A#	If argument has a given prefix, then change the operation as follows:
3780SN/A#		Prefix	Operation
3790SN/A#		------	---------
3800SN/A#		fast	Skip the pid check, and set rc_fast=yes, rc_quiet=yes
3810SN/A#		force	Set ${rcvar} to YES, and set rc_force=yes
3820SN/A#		one	Set ${rcvar} to YES
3830SN/A#		quiet	Don't output some diagnostics, and set rc_quiet=yes
3844439SN/A#
3850SN/A#	The following globals are used:
3860SN/A#
3874439SN/A#	Name		Needed	Purpose
3880SN/A#	----		------	-------
3890SN/A#	name		y	Name of script.
3900SN/A#
3910SN/A#	command		n	Full path to command.
3920SN/A#				Not needed if ${rc_arg}_cmd is set for
3930SN/A#				each keyword.
3940SN/A#
3950SN/A#	command_args	n	Optional args/shell directives for command.
3960SN/A#
3970SN/A#	command_interpreter n	If not empty, command is interpreted, so
3980SN/A#				call check_{pidfile,process}() appropriately.
3990SN/A#
4000SN/A#	extra_commands	n	List of extra commands supported.
4010SN/A#
4020SN/A#	pidfile		n	If set, use check_pidfile $pidfile $command,
4030SN/A#				otherwise use check_process $command.
4040SN/A#				In either case, only check if $command is set.
4050SN/A#
4060SN/A#	procname	n	Process name to check for instead of $command.
4070SN/A#
4080SN/A#	rcvar		n	This is checked with checkyesno to determine
4090SN/A#				if the action should be run.
4100SN/A#
411#	${name}_program	n	Full path to command.
412#				Meant to be used in /etc/rc.conf to override
413#				${command}.
414#
415#	${name}_chroot	n	Directory to chroot to before running ${command}
416#				Requires /usr to be mounted.
417#
418#	${name}_chdir	n	Directory to cd to before running ${command}
419#				(if not using ${name}_chroot).
420#
421#	${name}_flags	n	Arguments to call ${command} with.
422#				NOTE:	$flags from the parent environment
423#					can be used to override this.
424#
425#	${name}_nice	n	Nice level to run ${command} at.
426#
427#	${name}_user	n	User to run ${command} as, using su(1) if not
428#				using ${name}_chroot.
429#				Requires /usr to be mounted.
430#
431#	${name}_group	n	Group to run chrooted ${command} as.
432#				Requires /usr to be mounted.
433#
434#	${name}_groups	n	Comma separated list of supplementary groups
435#				to run the chrooted ${command} with.
436#				Requires /usr to be mounted.
437#
438#	${rc_arg}_cmd	n	If set, use this as the method when invoked;
439#				Otherwise, use default command (see below)
440#
441#	${rc_arg}_precmd n	If set, run just before performing the
442#				${rc_arg}_cmd method in the default
443#				operation (i.e, after checking for required
444#				bits and process (non)existence).
445#				If this completes with a non-zero exit code,
446#				don't run ${rc_arg}_cmd.
447#
448#	${rc_arg}_postcmd n	If set, run just after performing the
449#				${rc_arg}_cmd method, if that method
450#				returned a zero exit code.
451#
452#	required_dirs	n	If set, check for the existence of the given
453#				directories before running a (re)start command.
454#
455#	required_files	n	If set, check for the readability of the given
456#				files before running a (re)start command.
457#
458#	required_modules n	If set, ensure the given kernel modules are
459#				loaded before running a (re)start command.
460#				The check and possible loads are actually
461#				done after start_precmd so that the modules
462#				aren't loaded in vain, should the precmd
463#				return a non-zero status to indicate a error.
464#				If a word in the list looks like "foo:bar",
465#				"foo" is the KLD file name and "bar" is the
466#				module name.  If a word looks like "foo~bar",
467#				"foo" is the KLD file name and "bar" is a
468#				egrep(1) pattern matching the module name.
469#				Otherwise the module name is assumed to be
470#				the same as the KLD file name, which is most
471#				common.  See load_kld().
472#
473#	required_vars	n	If set, perform checkyesno on each of the
474#				listed variables before running the default
475#				(re)start command.
476#
477#	Default behaviour for a given argument, if no override method is
478#	provided:
479#
480#	Argument	Default behaviour
481#	--------	-----------------
482#	start		if !running && checkyesno ${rcvar}
483#				${command}
484#
485#	stop		if ${pidfile}
486#				rc_pid=$(check_pidfile $pidfile $command)
487#			else
488#				rc_pid=$(check_process $command)
489#			kill $sig_stop $rc_pid
490#			wait_for_pids $rc_pid
491#			($sig_stop defaults to TERM.)
492#
493#	reload		Similar to stop, except use $sig_reload instead,
494#			and doesn't wait_for_pids.
495#			$sig_reload defaults to HUP.
496#			Note that `reload' isn't provided by default,
497#			it should be enabled via $extra_commands.
498#
499#	restart		Run `stop' then `start'.
500#
501#	status		Show if ${command} is running, etc.
502#
503#	poll		Wait for ${command} to exit.
504#
505#	rcvar		Display what rc.conf variable is used (if any).
506#
507#	Variables available to methods, and after run_rc_command() has
508#	completed:
509#
510#	Variable	Purpose
511#	--------	-------
512#	rc_arg		Argument to command, after fast/force/one processing
513#			performed
514#
515#	rc_flags	Flags to start the default command with.
516#			Defaults to ${name}_flags, unless overridden
517#			by $flags from the environment.
518#			This variable may be changed by the precmd method.
519#
520#	rc_pid		PID of command (if appropriate)
521#
522#	rc_fast		Not empty if "fast" was provided (q.v.)
523#
524#	rc_force	Not empty if "force" was provided (q.v.)
525#
526#	rc_quiet	Not empty if "quiet" was provided
527#
528#
529run_rc_command()
530{
531	_return=0
532	rc_arg=$1
533	if [ -z "$name" ]; then
534		err 3 'run_rc_command: $name is not set.'
535	fi
536
537	# Don't repeat the first argument when passing additional command-
538	# line arguments to the command subroutines.
539	#
540	shift 1
541	rc_extra_args="$*"
542
543	_rc_prefix=
544	case "$rc_arg" in
545	fast*)				# "fast" prefix; don't check pid
546		rc_arg=${rc_arg#fast}
547		rc_fast=yes
548		rc_quiet=yes
549		;;
550	force*)				# "force prefix; always run
551		rc_force=yes
552		_rc_prefix=force
553		rc_arg=${rc_arg#${_rc_prefix}}
554		if [ -n "${rcvar}" ]; then
555			eval ${rcvar}=YES
556		fi
557		;;
558	one*)				# "one" prefix; set ${rcvar}=yes
559		_rc_prefix=one
560		rc_arg=${rc_arg#${_rc_prefix}}
561		if [ -n "${rcvar}" ]; then
562			eval ${rcvar}=YES
563		fi
564		;;
565	quiet*)				# "quiet" prefix; omit some messages
566		_rc_prefix=quiet
567		rc_arg=${rc_arg#${_rc_prefix}}
568		rc_quiet=yes
569		;;
570	esac
571
572	eval _override_command=\$${name}_program
573	command=${command:+${_override_command:-$command}}
574
575	_keywords="start stop restart rcvar $extra_commands"
576	rc_pid=
577	_pidcmd=
578	_procname=${procname:-${command}}
579
580					# setup pid check command
581	if [ -n "$_procname" ]; then
582		if [ -n "$pidfile" ]; then
583			_pidcmd='rc_pid=$(check_pidfile '"$pidfile $_procname $command_interpreter"')'
584		else
585			_pidcmd='rc_pid=$(check_process '"$_procname $command_interpreter"')'
586		fi
587		if [ -n "$_pidcmd" ]; then
588			_keywords="${_keywords} status poll"
589		fi
590	fi
591
592	if [ -z "$rc_arg" ]; then
593		rc_usage $_keywords
594	fi
595
596	if [ -n "$flags" ]; then	# allow override from environment
597		rc_flags=$flags
598	else
599		eval rc_flags=\$${name}_flags
600	fi
601	eval _chdir=\$${name}_chdir	_chroot=\$${name}_chroot \
602	    _nice=\$${name}_nice	_user=\$${name}_user \
603	    _group=\$${name}_group	_groups=\$${name}_groups
604
605	if [ -n "$_user" ]; then	# unset $_user if running as that user
606		if [ "$_user" = "$(eval $IDCMD)" ]; then
607			unset _user
608		fi
609	fi
610
611					# if ${rcvar} is set, and $1 is not
612					# "rcvar", then run
613					#	checkyesno ${rcvar}
614					# and return if that failed
615					#
616	if [ -n "${rcvar}" -a "$rc_arg" != "rcvar" ]; then
617		if ! checkyesno ${rcvar}; then
618			if [ -n "${rc_quiet}" ]; then
619				return 0
620			fi
621			echo -n "Cannot '${rc_arg}' $name. Set ${rcvar} to "
622			echo -n "YES in /etc/rc.conf or use 'one${rc_arg}' "
623			echo "instead of '${rc_arg}'."
624			return 0
625		fi
626	fi
627
628	eval $_pidcmd			# determine the pid if necessary
629
630	for _elem in $_keywords; do
631		if [ "$_elem" != "$rc_arg" ]; then
632			continue
633		fi
634					# if there's a custom ${XXX_cmd},
635					# run that instead of the default
636					#
637		eval _cmd=\$${rc_arg}_cmd \
638		     _precmd=\$${rc_arg}_precmd \
639		     _postcmd=\$${rc_arg}_postcmd
640
641		if [ -n "$_cmd" ]; then
642			_run_rc_precmd || return 1
643			_run_rc_doit "$_cmd $rc_extra_args" || return 1
644			_run_rc_postcmd
645			return $_return
646		fi
647
648		case "$rc_arg" in	# default operations...
649
650		status)
651			_run_rc_precmd || return 1
652			if [ -n "$rc_pid" ]; then
653				echo "${name} is running as pid $rc_pid."
654			else
655				echo "${name} is not running."
656				return 1
657			fi
658			_run_rc_postcmd
659			;;
660
661		start)
662			if [ -z "$rc_fast" -a -n "$rc_pid" ]; then
663				echo 1>&2 "${name} already running? (pid=$rc_pid)."
664				return 1
665			fi
666
667			if [ ! -x ${_chroot}${_chroot:+"/"}${command} ]; then
668				warn "run_rc_command: cannot run $command"
669				return 1
670			fi
671
672			_run_rc_precmd || return 1
673
674					# setup the full command to run
675					#
676			echo "Starting ${name}."
677			if [ -n "$_chroot" ]; then
678				_doit="\
679${_nice:+nice -n $_nice }\
680chroot ${_user:+-u $_user }${_group:+-g $_group }${_groups:+-G $_groups }\
681$_chroot $command $rc_flags $command_args"
682			else
683				_doit="\
684${_chdir:+cd $_chdir && }\
685$command $rc_flags $command_args"
686				if [ -n "$_user" ]; then
687				    _doit="su -m $_user -c 'sh -c \"$_doit\"'"
688				fi
689				if [ -n "$_nice" ]; then
690					if [ -z "$_user" ]; then
691						_doit="sh -c \"$_doit\""
692					fi	
693					_doit="nice -n $_nice $_doit"
694				fi
695			fi
696
697					# run the full command
698					#
699			_run_rc_doit "$_doit" || return 1
700
701					# finally, run postcmd
702					#
703			_run_rc_postcmd
704			;;
705
706		stop)
707			if [ -z "$rc_pid" ]; then
708				[ -n "$rc_fast" ] && return 0
709				_run_rc_notrunning
710				return 1
711			fi
712
713			_run_rc_precmd || return 1
714
715					# send the signal to stop
716					#
717			echo "Stopping ${name}."
718			_doit=$(_run_rc_killcmd "${sig_stop:-TERM}")
719			_run_rc_doit "$_doit" || return 1
720
721					# wait for the command to exit,
722					# and run postcmd.
723			wait_for_pids $rc_pid
724
725			_run_rc_postcmd
726			;;
727
728		reload)
729			if [ -z "$rc_pid" ]; then
730				_run_rc_notrunning
731				return 1
732			fi
733
734			_run_rc_precmd || return 1
735
736			_doit=$(_run_rc_killcmd "${sig_reload:-HUP}")
737			_run_rc_doit "$_doit" || return 1
738
739			_run_rc_postcmd
740			;;
741
742		restart)
743					# prevent restart being called more
744					# than once by any given script
745					#
746			if ${_rc_restart_done:-false}; then
747				return 0
748			fi
749			_rc_restart_done=true
750
751			_run_rc_precmd || return 1
752
753			# run those in a subshell to keep global variables
754			( run_rc_command ${_rc_prefix}stop $rc_extra_args )
755			( run_rc_command ${_rc_prefix}start $rc_extra_args )
756			_return=$?
757			[ $_return -ne 0 ] && [ -z "$rc_force" ] && return 1
758
759			_run_rc_postcmd
760			;;
761
762		poll)
763			_run_rc_precmd || return 1
764			if [ -n "$rc_pid" ]; then
765				wait_for_pids $rc_pid
766			fi
767			_run_rc_postcmd
768			;;
769
770		rcvar)
771			echo "# $name"
772			if [ -n "$rcvar" ]; then
773				if checkyesno ${rcvar}; then
774					echo "${rcvar}=YES"
775				else
776					echo "${rcvar}=NO"
777				fi
778			fi
779			;;
780
781		*)
782			rc_usage $_keywords
783			;;
784
785		esac
786		return $_return
787	done
788
789	echo 1>&2 "$0: unknown directive '$rc_arg'."
790	rc_usage $_keywords
791	# not reached
792}
793
794#
795# Helper functions for run_rc_command: common code.
796# They use such global variables besides the exported rc_* ones:
797#
798#	name	       R/W
799#	------------------
800#	_precmd		R
801#	_postcmd	R
802#	_return		W
803#
804_run_rc_precmd()
805{
806	check_required_before "$rc_arg" || return 1
807
808	if [ -n "$_precmd" ]; then
809		debug "run_rc_command: ${rc_arg}_precmd: $_precmd $rc_extra_args"
810		eval "$_precmd $rc_extra_args"
811		_return=$?
812
813		# If precmd failed and force isn't set, request exit.
814		if [ $_return -ne 0 ] && [ -z "$rc_force" ]; then
815			return 1
816		fi
817	fi
818
819	check_required_after "$rc_arg" || return 1
820
821	return 0
822}
823
824_run_rc_postcmd()
825{
826	if [ -n "$_postcmd" ]; then
827		debug "run_rc_command: ${rc_arg}_postcmd: $_postcmd $rc_extra_args"
828		eval "$_postcmd $rc_extra_args"
829		_return=$?
830	fi
831	return 0
832}
833
834_run_rc_doit()
835{
836	debug "run_rc_command: doit: $*"
837	eval "$@"
838	_return=$?
839
840	# If command failed and force isn't set, request exit.
841	if [ $_return -ne 0 ] && [ -z "$rc_force" ]; then
842		return 1
843	fi
844
845	return 0
846}
847
848_run_rc_notrunning()
849{
850	local _pidmsg
851
852	if [ -n "$pidfile" ]; then
853		_pidmsg=" (check $pidfile)."
854	else
855		_pidmsg=
856	fi
857	echo 1>&2 "${name} not running?${_pidmsg}"
858}
859
860_run_rc_killcmd()
861{
862	local _cmd
863
864	_cmd="kill -$1 $rc_pid"
865	if [ -n "$_user" ]; then
866		_cmd="su -m ${_user} -c 'sh -c \"${_cmd}\"'"
867	fi
868	echo "$_cmd"
869}
870
871#
872# run_rc_script file arg
873#	Start the script `file' with `arg', and correctly handle the
874#	return value from the script.  If `file' ends with `.sh', it's
875#	sourced into the current environment.  If `file' appears to be
876#	a backup or scratch file, ignore it.  Otherwise if it's
877#	executable run as a child process.
878#
879run_rc_script()
880{
881	_file=$1
882	_arg=$2
883	if [ -z "$_file" -o -z "$_arg" ]; then
884		err 3 'USAGE: run_rc_script file arg'
885	fi
886
887	unset	name command command_args command_interpreter \
888		extra_commands pidfile procname \
889		rcvar required_dirs required_files required_vars
890	eval unset ${_arg}_cmd ${_arg}_precmd ${_arg}_postcmd
891
892	case "$_file" in
893	/etc/rc.d/*.sh)			# run in current shell
894		set $_arg; . $_file
895		;;
896	*[~#]|*.OLD|*.bak|*.orig|*,v)	# scratch file; skip
897		warn "Ignoring scratch file $_file"
898		;;
899	*)				# run in subshell
900		if [ -x $_file ]; then
901			if [ -n "$rc_fast_and_loose" ]; then
902				set $_arg; . $_file
903			else
904				( trap "echo Script $_file interrupted; kill -QUIT $$" 3
905				  trap "echo Script $_file interrupted; exit 1" 2
906				  set $_arg; . $_file )
907			fi
908		fi
909		;;
910	esac
911}
912
913#
914# load_rc_config name
915#	Source in the configuration file for a given name.
916#
917load_rc_config()
918{
919	_name=$1
920	if [ -z "$_name" ]; then
921		err 3 'USAGE: load_rc_config name'
922	fi
923
924	if ${_rc_conf_loaded:-false}; then
925		:
926	else
927		if [ -r /etc/defaults/rc.conf ]; then
928			debug "Sourcing /etc/defaults/rc.conf"
929			. /etc/defaults/rc.conf
930			source_rc_confs
931		elif [ -r /etc/rc.conf ]; then
932			debug "Sourcing /etc/rc.conf (/etc/defaults/rc.conf doesn't exist)."
933			. /etc/rc.conf
934		fi
935		_rc_conf_loaded=true
936	fi
937	if [ -f /etc/rc.conf.d/"$_name" ]; then
938		debug "Sourcing /etc/rc.conf.d/${_name}"
939		. /etc/rc.conf.d/"$_name"
940	fi
941}
942  
943#
944# load_rc_config_var name var
945#	Read the rc.conf(5) var for name and set in the
946#	current shell, using load_rc_config in a subshell to prevent
947#	unwanted side effects from other variable assignments.
948#
949load_rc_config_var()
950{
951	if [ $# -ne 2 ]; then
952		err 3 'USAGE: load_rc_config_var name var'
953	fi
954	eval $(eval '(
955		load_rc_config '$1' >/dev/null;
956                if [ -n "${'$2'}" -o "${'$2'-UNSET}" != "UNSET" ]; then
957			echo '$2'=\'\''${'$2'}\'\'';
958		fi
959	)' )
960}
961
962#
963# rc_usage commands
964#	Print a usage string for $0, with `commands' being a list of
965#	valid commands.
966#
967rc_usage()
968{
969	echo -n 1>&2 "Usage: $0 [fast|force|one]("
970
971	_sep=
972	for _elem; do
973		echo -n 1>&2 "$_sep$_elem"
974		_sep="|"
975	done
976	echo 1>&2 ")"
977	exit 1
978}
979
980#
981# err exitval message
982#	Display message to stderr and log to the syslog, and exit with exitval.
983#
984err()
985{
986	exitval=$1
987	shift
988
989	if [ -x /usr/bin/logger ]; then
990		logger "$0: ERROR: $*"
991	fi
992	echo 1>&2 "$0: ERROR: $*"
993	exit $exitval
994}
995
996#
997# warn message
998#	Display message to stderr and log to the syslog.
999#
1000warn()
1001{
1002	if [ -x /usr/bin/logger ]; then
1003		logger "$0: WARNING: $*"
1004	fi
1005	echo 1>&2 "$0: WARNING: $*"
1006}
1007
1008#
1009# info message
1010#	Display informational message to stdout and log to syslog.
1011#
1012info()
1013{
1014	case ${rc_info} in
1015	[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
1016		if [ -x /usr/bin/logger ]; then
1017			logger "$0: INFO: $*"
1018		fi
1019		echo "$0: INFO: $*"
1020		;;
1021	esac
1022}
1023
1024#
1025# debug message
1026#	If debugging is enabled in rc.conf output message to stderr.
1027#	BEWARE that you don't call any subroutine that itself calls this
1028#	function.
1029#
1030debug()
1031{
1032	case ${rc_debug} in
1033	[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
1034		if [ -x /usr/bin/logger ]; then
1035			logger "$0: DEBUG: $*"
1036		fi
1037		echo 1>&2 "$0: DEBUG: $*"
1038		;;
1039	esac
1040}
1041
1042#
1043# backup_file action file cur backup
1044#	Make a backup copy of `file' into `cur', and save the previous
1045#	version of `cur' as `backup' or use rcs for archiving.
1046#
1047#	This routine checks the value of the backup_uses_rcs variable,
1048#	which can be either YES or NO.
1049#
1050#	The `action' keyword can be one of the following:
1051#
1052#	add		`file' is now being backed up (and is possibly
1053#			being reentered into the backups system).  `cur'
1054#			is created and RCS files, if necessary, are
1055#			created as well.
1056#
1057#	update		`file' has changed and needs to be backed up.
1058#			If `cur' exists, it is copied to to `back' or
1059#			checked into RCS (if the repository file is old),
1060#			and then `file' is copied to `cur'.  Another RCS
1061#			check in done here if RCS is being used.
1062#
1063#	remove		`file' is no longer being tracked by the backups
1064#			system.  If RCS is not being used, `cur' is moved
1065#			to `back', otherwise an empty file is checked in,
1066#			and then `cur' is removed.
1067#
1068#
1069backup_file()
1070{
1071	_action=$1
1072	_file=$2
1073	_cur=$3
1074	_back=$4
1075
1076	if checkyesno backup_uses_rcs; then
1077		_msg0="backup archive"
1078		_msg1="update"
1079
1080		# ensure that history file is not locked
1081		if [ -f $_cur,v ]; then
1082			rcs -q -u -U -M $_cur
1083		fi
1084
1085		# ensure after switching to rcs that the
1086		# current backup is not lost
1087		if [ -f $_cur ]; then
1088			# no archive, or current newer than archive
1089			if [ ! -f $_cur,v -o $_cur -nt $_cur,v ]; then
1090				ci -q -f -u -t-"$_msg0" -m"$_msg1" $_cur
1091				rcs -q -kb -U $_cur
1092				co -q -f -u $_cur
1093			fi
1094		fi
1095
1096		case $_action in
1097		add|update)
1098			cp -p $_file $_cur
1099			ci -q -f -u -t-"$_msg0" -m"$_msg1" $_cur
1100			rcs -q -kb -U $_cur
1101			co -q -f -u $_cur
1102			chown root:wheel $_cur $_cur,v
1103			;;
1104		remove)
1105			cp /dev/null $_cur
1106			ci -q -f -u -t-"$_msg0" -m"$_msg1" $_cur
1107			rcs -q -kb -U $_cur
1108			chown root:wheel $_cur $_cur,v
1109			rm $_cur
1110			;;
1111		esac
1112	else
1113		case $_action in
1114		add|update)
1115			if [ -f $_cur ]; then
1116				cp -p $_cur $_back
1117			fi
1118			cp -p $_file $_cur
1119			chown root:wheel $_cur
1120			;;
1121		remove)
1122			mv -f $_cur $_back
1123			;;
1124		esac
1125	fi
1126}
1127
1128# make_symlink src link
1129#	Make a symbolic link 'link' to src from basedir. If the
1130#	directory in which link is to be created does not exist
1131#	a warning will be displayed and an error will be returned.
1132#	Returns 0 on sucess, 1 otherwise.
1133#
1134make_symlink()
1135{
1136	local src link linkdir _me
1137	src="$1"
1138	link="$2"
1139	linkdir="`dirname $link`"
1140	_me="make_symlink()"
1141
1142	if [ -z "$src" -o -z "$link" ]; then
1143		warn "$_me: requires two arguments."
1144		return 1
1145	fi
1146	if [ ! -d "$linkdir" ]; then
1147		warn "$_me: the directory $linkdir does not exist."
1148		return 1
1149	fi
1150	if ! ln -sf $src $link; then
1151		warn "$_me: unable to make a symbolic link from $link to $src"
1152		return 1
1153	fi
1154	return 0
1155}
1156
1157# devfs_rulesets_from_file file
1158#	Reads a set of devfs commands from file, and creates
1159#	the specified rulesets with their rules. Returns non-zero
1160#	if there was an error.
1161#
1162devfs_rulesets_from_file()
1163{
1164	local file _err _me
1165	file="$1"
1166	_me="devfs_rulesets_from_file"
1167	_err=0
1168
1169	if [ -z "$file" ]; then
1170		warn "$_me: you must specify a file"
1171		return 1
1172	fi
1173	if [ ! -e "$file" ]; then
1174		debug "$_me: no such file ($file)"
1175		return 0
1176	fi
1177	debug "reading rulesets from file ($file)"
1178	{ while read line
1179	do
1180		case $line in
1181		\#*)
1182			continue
1183			;;
1184		\[*\]*)
1185			rulenum=`expr "$line" : "\[.*=\([0-9]*\)\]"`
1186			if [ -z "$rulenum" ]; then
1187				warn "$_me: cannot extract rule number ($line)"
1188				_err=1
1189				break
1190			fi
1191			rulename=`expr "$line" : "\[\(.*\)=[0-9]*\]"`
1192			if [ -z "$rulename" ]; then
1193				warn "$_me: cannot extract rule name ($line)"
1194				_err=1
1195				break;
1196			fi
1197			eval $rulename=\$rulenum
1198			debug "found ruleset: $rulename=$rulenum"
1199			if ! /sbin/devfs rule -s $rulenum delset; then
1200				_err=1
1201				break
1202			fi
1203			;;
1204		*)
1205			rulecmd="${line%%"\#*"}"
1206			# evaluate the command incase it includes
1207			# other rules
1208			if [ -n "$rulecmd" ]; then
1209				debug "adding rule ($rulecmd)"
1210				if ! eval /sbin/devfs rule -s $rulenum $rulecmd
1211				then
1212					_err=1
1213					break
1214				fi
1215			fi
1216			;;
1217		esac
1218		if [ $_err -ne 0 ]; then
1219			debug "error in $_me"
1220			break
1221		fi
1222	done } < $file
1223	return $_err
1224}
1225
1226# devfs_init_rulesets
1227#	Initializes rulesets from configuration files. Returns
1228#	non-zero if there was an error.
1229#
1230devfs_init_rulesets()
1231{
1232	local file _me
1233	_me="devfs_init_rulesets"
1234
1235	# Go through this only once
1236	if [ -n "$devfs_rulesets_init" ]; then
1237		debug "$_me: devfs rulesets already initialized"
1238		return
1239	fi
1240	for file in $devfs_rulesets; do
1241		devfs_rulesets_from_file $file || return 1
1242	done
1243	devfs_rulesets_init=1
1244	debug "$_me: devfs rulesets initialized"
1245	return 0
1246}
1247
1248# devfs_set_ruleset ruleset [dir]
1249#	Sets the default ruleset of dir to ruleset. The ruleset argument
1250#	must be a ruleset name as specified in devfs.rules(5) file.
1251#	Returns non-zero if it could not set it successfully.
1252#
1253devfs_set_ruleset()
1254{
1255	local devdir rs _me
1256	[ -n "$1" ] && eval rs=\$$1 || rs=
1257	[ -n "$2" ] && devdir="-m "$2"" || devdir=
1258	_me="devfs_set_ruleset"
1259
1260	if [ -z "$rs" ]; then
1261		warn "$_me: you must specify a ruleset number"
1262		return 1
1263	fi
1264	debug "$_me: setting ruleset ($rs) on mount-point (${devdir#-m })"
1265	if ! /sbin/devfs $devdir ruleset $rs; then
1266		warn "$_me: unable to set ruleset $rs to ${devdir#-m }"
1267		return 1
1268	fi
1269	return 0
1270}
1271
1272# devfs_apply_ruleset ruleset [dir]
1273#	Apply ruleset number $ruleset to the devfs mountpoint $dir.
1274#	The ruleset argument must be a ruleset name as specified
1275#	in a devfs.rules(5) file.  Returns 0 on success or non-zero
1276#	if it could not apply the ruleset.
1277#
1278devfs_apply_ruleset()
1279{
1280	local devdir rs _me
1281	[ -n "$1" ] && eval rs=\$$1 || rs=
1282	[ -n "$2" ] && devdir="-m "$2"" || devdir=
1283	_me="devfs_apply_ruleset"
1284
1285	if [ -z "$rs" ]; then
1286		warn "$_me: you must specify a ruleset"
1287		return 1
1288	fi
1289	debug "$_me: applying ruleset ($rs) to mount-point (${devdir#-m })"
1290	if ! /sbin/devfs $devdir rule -s $rs applyset; then
1291		warn "$_me: unable to apply ruleset $rs to ${devdir#-m }"
1292		return 1
1293	fi
1294	return 0
1295}
1296
1297# devfs_domount dir [ruleset]
1298#	Mount devfs on dir. If ruleset is specified it is set
1299#	on the mount-point. It must also be a ruleset name as specified
1300#	in a devfs.rules(5) file. Returns 0 on success.
1301#
1302devfs_domount()
1303{
1304	local devdir rs _me
1305	devdir="$1"
1306	[ -n "$2" ] && rs=$2 || rs=
1307	_me="devfs_domount()"
1308
1309	if [ -z "$devdir" ]; then
1310		warn "$_me: you must specify a mount-point"
1311		return 1
1312	fi
1313	debug "$_me: mount-point is ($devdir), ruleset is ($rs)"
1314	if ! mount -t devfs dev "$devdir"; then
1315		warn "$_me: Unable to mount devfs on $devdir"
1316		return 1
1317	fi
1318	if [ -n "$rs" ]; then
1319		devfs_init_rulesets
1320		devfs_set_ruleset $rs $devdir
1321		devfs -m $devdir rule applyset
1322	fi
1323	return 0
1324}
1325
1326# devfs_mount_jail dir [ruleset]
1327#	Mounts a devfs file system appropriate for jails
1328#	on the directory dir. If ruleset is specified, the ruleset
1329#	it names will be used instead.  If present, ruleset must
1330#	be the name of a ruleset as defined in a devfs.rules(5) file.
1331#	This function returns non-zero if an error occurs.
1332#
1333devfs_mount_jail()
1334{
1335	local jdev rs _me
1336	jdev="$1"
1337	[ -n "$2" ] && rs=$2 || rs="devfsrules_jail"
1338	_me="devfs_mount_jail"
1339
1340	devfs_init_rulesets
1341	if ! devfs_domount "$jdev" $rs; then
1342		warn "$_me: devfs was not mounted on $jdev"
1343		return 1
1344	fi
1345	return 0
1346}
1347
1348# Provide a function for normalizing the mounting of memory
1349# filesystems.  This should allow the rest of the code here to remain
1350# as close as possible between 5-current and 4-stable.
1351#   $1 = size
1352#   $2 = mount point
1353#   $3 = (optional) extra mdmfs flags
1354mount_md()
1355{
1356	if [ -n "$3" ]; then
1357		flags="$3"
1358	fi
1359	/sbin/mdmfs $flags -s $1 md $2
1360}
1361
1362# Code common to scripts that need to load a kernel module
1363# if it isn't in the kernel yet. Syntax:
1364#   load_kld [-e regex] [-m module] file
1365# where -e or -m chooses the way to check if the module
1366# is already loaded:
1367#   regex is egrep'd in the output from `kldstat -v',
1368#   module is passed to `kldstat -m'.
1369# The default way is as though `-m file' were specified.
1370load_kld()
1371{
1372	local _loaded _mod _opt _re
1373
1374	while getopts "e:m:" _opt; do
1375		case "$_opt" in
1376		e) _re="$OPTARG" ;;
1377		m) _mod="$OPTARG" ;;
1378		*) err 3 'USAGE: load_kld [-e regex] [-m module] file' ;;
1379		esac
1380	done
1381	shift $(($OPTIND - 1))
1382	if [ $# -ne 1 ]; then
1383		err 3 'USAGE: load_kld [-e regex] [-m module] file'
1384	fi
1385	_mod=${_mod:-$1}
1386	_loaded=false
1387	if [ -n "$_re" ]; then
1388		if kldstat -v | egrep -q -e "$_re"; then
1389			_loaded=true
1390		fi
1391	else
1392		if kldstat -q -m "$_mod"; then
1393			_loaded=true
1394		fi
1395	fi
1396	if ! $_loaded; then
1397		if ! kldload "$1"; then
1398			warn "Unable to load kernel module $1"
1399			return 1
1400		else
1401			info "$1 kernel module loaded."
1402		fi
1403	else
1404		debug "load_kld: $1 kernel module already loaded."
1405	fi
1406	return 0
1407}
1408
1409# ltr str src dst
1410#	Change every $src in $str to $dst.
1411#	Useful when /usr is not yet mounted and we cannot use tr(1), sed(1) nor
1412#	awk(1).
1413ltr()
1414{
1415	local _str _src _dst _out _com
1416	_str=$1
1417	_src=$2
1418	_dst=$3
1419	_out=""
1420
1421	IFS=${_src}
1422	for _com in ${_str}; do
1423		if [ -z "${_out}" ]; then
1424			_out="${_com}"
1425		else
1426			_out="${_out}${_dst}${_com}"
1427		fi
1428	done
1429	echo "${_out}"
1430}
1431
1432# Creates a list of providers for GELI encryption.
1433geli_make_list()
1434{
1435	local devices devices2
1436	local provider mountpoint type options rest
1437
1438	# Create list of GELI providers from fstab.
1439	while read provider mountpoint type options rest ; do
1440		case ":${options}" in
1441		:*noauto*)
1442			noauto=yes
1443			;;
1444		*)
1445			noauto=no
1446			;;
1447		esac
1448
1449		case ":${provider}" in
1450		:#*)
1451			continue
1452			;;
1453		*.eli)
1454			# Skip swap devices.
1455			if [ "${type}" = "swap" -o "${options}" = "sw" -o "${noauto}" = "yes" ]; then
1456				continue
1457			fi
1458			devices="${devices} ${provider}"
1459			;;
1460		esac
1461	done < /etc/fstab
1462
1463	# Append providers from geli_devices.
1464	devices="${devices} ${geli_devices}"
1465
1466	for provider in ${devices}; do
1467		provider=${provider%.eli}
1468		provider=${provider#/dev/}
1469		devices2="${devices2} ${provider}"
1470	done
1471
1472	echo ${devices2}
1473}
1474
1475# Find scripts in local_startup directories that use the old syntax
1476#
1477find_local_scripts_old () {
1478	zlist=''
1479	slist=''
1480	for dir in ${local_startup}; do
1481		if [ -d "${dir}" ]; then
1482			for file in ${dir}/[0-9]*.sh; do
1483				grep '^# PROVIDE:' $file >/dev/null 2>&1 &&
1484				    continue
1485				zlist="$zlist $file"
1486			done
1487			for file in ${dir}/[^0-9]*.sh; do
1488				grep '^# PROVIDE:' $file >/dev/null 2>&1 &&
1489				    continue
1490				slist="$slist $file"
1491			done
1492		fi
1493	done
1494}
1495
1496find_local_scripts_new () {
1497	local_rc=''
1498	for dir in ${local_startup}; do
1499		if [ -d "${dir}" ]; then
1500			for file in `grep -l '^# PROVIDE:' ${dir}/* 2>/dev/null`; do
1501				case "$file" in
1502				*.sample) ;;
1503				*)	if [ -x "$file" ]; then
1504						local_rc="${local_rc} ${file}"
1505					fi
1506					;;
1507				esac
1508			done
1509		fi
1510	done
1511}
1512
1513# check_required_{before|after} command
1514#	Check for things required by the command before and after its precmd,
1515#	respectively.  The two separate functions are needed because some
1516#	conditions should prevent precmd from being run while other things
1517#	depend on precmd having already been run.
1518#
1519check_required_before()
1520{
1521	local _f
1522
1523	case "$1" in
1524	start)
1525		for _f in $required_vars; do
1526			if ! checkyesno $_f; then
1527				warn "\$${_f} is not enabled."
1528				if [ -z "$rc_force" ]; then
1529					return 1
1530				fi
1531			fi
1532		done
1533
1534		for _f in $required_dirs; do
1535			if [ ! -d "${_f}/." ]; then
1536				warn "${_f} is not a directory."
1537				if [ -z "$rc_force" ]; then
1538					return 1
1539				fi
1540			fi
1541		done
1542
1543		for _f in $required_files; do
1544			if [ ! -r "${_f}" ]; then
1545				warn "${_f} is not readable."
1546				if [ -z "$rc_force" ]; then
1547					return 1
1548				fi
1549			fi
1550		done
1551		;;
1552	esac
1553
1554	return 0
1555}
1556
1557check_required_after()
1558{
1559	local _f _args
1560
1561	case "$1" in
1562	start)
1563		for _f in $required_modules; do
1564			case "${_f}" in
1565				*~*)	_args="-e ${_f#*~} ${_f%%~*}" ;;
1566				*:*)	_args="-m ${_f#*:} ${_f%%:*}" ;;
1567				*)	_args="${_f}" ;;
1568			esac
1569			if ! load_kld ${_args}; then
1570				if [ -z "$rc_force" ]; then
1571					return 1
1572				fi
1573			fi
1574		done
1575		;;
1576	esac
1577
1578	return 0
1579}
1580
1581fi
1582
1583_rc_subr_loaded=:
1584