rc.subr revision 220963
1# $NetBSD: rc.subr,v 1.67 2006/10/07 11:25:15 elad Exp $
2# $FreeBSD: head/etc/rc.subr 220963 2011-04-23 05:24:17Z dougb $
3#
4# Copyright (c) 1997-2004 The NetBSD Foundation, Inc.
5# All rights reserved.
6#
7# This code is derived from software contributed to The NetBSD Foundation
8# by Luke Mewburn.
9#
10# Redistribution and use in source and binary forms, with or without
11# modification, are permitted provided that the following conditions
12# are met:
13# 1. Redistributions of source code must retain the above copyright
14#    notice, this list of conditions and the following disclaimer.
15# 2. Redistributions in binary form must reproduce the above copyright
16#    notice, this list of conditions and the following disclaimer in the
17#    documentation and/or other materials provided with the distribution.
18#
19# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29# POSSIBILITY OF SUCH DAMAGE.
30#
31# rc.subr
32#	functions used by various rc scripts
33#
34
35: ${rcvar_manpage:='rc.conf(5)'}
36: ${RC_PID:=$$}; export RC_PID
37
38#
39#	Operating System dependent/independent variables
40#
41
42if [ -z "${_rc_subr_loaded}" ]; then
43
44_rc_subr_loaded="YES"
45
46SYSCTL="/sbin/sysctl"
47SYSCTL_N="${SYSCTL} -n"
48SYSCTL_W="${SYSCTL}"
49ID="/usr/bin/id"
50IDCMD="if [ -x $ID ]; then $ID -un; fi"
51PS="/bin/ps -ww"
52JID=`$PS -p $$ -o jid=`
53
54#
55#	functions
56#	---------
57
58# set_rcvar [var] [defval] [desc]
59#
60#	Echo or define a rc.conf(5) variable name.  Global variable
61#	$rcvars is used.
62#
63#	If no argument is specified, echo "${name}_enable".
64#
65#	If only a var is specified, echo "${var}_enable".
66#
67#	If var and defval are specified, the ${var} is defined as
68#	rc.conf(5) variable and the default value is ${defvar}.  An
69#	optional argument $desc can also be specified to add a
70#	description for that.
71#
72set_rcvar()
73{
74	case $# in
75	0)
76		echo ${name}_enable
77		;;
78	1)
79		echo ${1}_enable
80		;;
81	*)
82		debug "rcvar_define: \$$1=$2 is added" \
83		    " as a rc.conf(5) variable."
84
85		local _var
86		_var=$1
87		rcvars="${rcvars# } $_var"
88		eval ${_var}_defval=\"$2\"
89		shift 2
90		# encode multiple lines of _desc
91		for l in "$@"; do
92			eval ${_var}_desc=\"\${${_var}_desc#^^}^^$l\"
93		done
94		eval ${_var}_desc=\"\${${_var}_desc#^^}\"
95		;;
96	esac
97}
98
99# set_rcvar_obsolete oldvar [newvar] [msg]
100#	Define obsolete variable.
101#	Global variable $rcvars_obsolete is used.
102#
103set_rcvar_obsolete()
104{
105	local _var
106	_var=$1
107	debug "rcvar_obsolete: \$$1(old) -> \$$2(new) is defined"
108
109	rcvars_obsolete="${rcvars_obsolete# } $1"
110	eval ${1}_newvar=\"$2\"
111	shift 2
112	eval ${_var}_obsolete_msg=\"$*\"
113}
114
115#
116# force_depend script
117#	Force a service to start. Intended for use by services
118#	to resolve dependency issues. It is assumed the caller
119#	has check to make sure this call is necessary
120#	$1 - filename of script, in /etc/rc.d, to run
121#
122force_depend()
123{
124	_depend="$1"
125
126	info "${name} depends on ${_depend}, which will be forced to start."
127	if ! /etc/rc.d/${_depend} forcestart; then
128		warn "Unable to force ${_depend}. It may already be running."
129		return 1
130	fi
131	return 0
132}
133
134#
135# checkyesno var
136#	Test $1 variable, and warn if not set to YES or NO.
137#	Return 0 if it's "yes" (et al), nonzero otherwise.
138#
139checkyesno()
140{
141	eval _value=\$${1}
142	debug "checkyesno: $1 is set to $_value."
143	case $_value in
144
145		#	"yes", "true", "on", or "1"
146	[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
147		return 0
148		;;
149
150		#	"no", "false", "off", or "0"
151	[Nn][Oo]|[Ff][Aa][Ll][Ss][Ee]|[Oo][Ff][Ff]|0)
152		return 1
153		;;
154	*)
155		warn "\$${1} is not set properly - see ${rcvar_manpage}."
156		return 1
157		;;
158	esac
159}
160
161#
162# reverse_list list
163#	print the list in reverse order
164#
165reverse_list()
166{
167	_revlist=
168	for _revfile; do
169		_revlist="$_revfile $_revlist"
170	done
171	echo $_revlist
172}
173
174# stop_boot always
175#	If booting directly to multiuser or $always is enabled,
176#	send SIGTERM to the parent (/etc/rc) to abort the boot.
177#	Otherwise just exit.
178#
179stop_boot()
180{
181	local always
182
183	case $1 in
184		#	"yes", "true", "on", or "1"
185        [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
186		always=true
187		;;
188	*)
189		always=false
190		;;
191	esac
192	if [ "$autoboot" = yes -o "$always" = true ]; then
193		echo "ERROR: ABORTING BOOT (sending SIGTERM to parent)!"
194		kill -TERM ${RC_PID}
195	fi
196	exit 1
197}
198
199#
200# mount_critical_filesystems type
201#	Go through the list of critical filesystems as provided in
202#	the rc.conf(5) variable $critical_filesystems_${type}, checking
203#	each one to see if it is mounted, and if it is not, mounting it.
204#
205mount_critical_filesystems()
206{
207	eval _fslist=\$critical_filesystems_${1}
208	for _fs in $_fslist; do
209		mount | (
210			_ismounted=false
211			while read what _on on _type type; do
212				if [ $on = $_fs ]; then
213					_ismounted=true
214				fi
215			done
216			if $_ismounted; then
217				:
218			else
219				mount $_fs >/dev/null 2>&1
220			fi
221		)
222	done
223}
224
225#
226# check_pidfile pidfile procname [interpreter]
227#	Parses the first line of pidfile for a PID, and ensures
228#	that the process is running and matches procname.
229#	Prints the matching PID upon success, nothing otherwise.
230#	interpreter is optional; see _find_processes() for details.
231#
232check_pidfile()
233{
234	_pidfile=$1
235	_procname=$2
236	_interpreter=$3
237	if [ -z "$_pidfile" -o -z "$_procname" ]; then
238		err 3 'USAGE: check_pidfile pidfile procname [interpreter]'
239	fi
240	if [ ! -f $_pidfile ]; then
241		debug "pid file ($_pidfile): not readable."
242		return
243	fi
244	read _pid _junk < $_pidfile
245	if [ -z "$_pid" ]; then
246		debug "pid file ($_pidfile): no pid in file."
247		return
248	fi
249	_find_processes $_procname ${_interpreter:-.} '-p '"$_pid"
250}
251
252#
253# check_process procname [interpreter]
254#	Ensures that a process (or processes) named procname is running.
255#	Prints a list of matching PIDs.
256#	interpreter is optional; see _find_processes() for details.
257#
258check_process()
259{
260	_procname=$1
261	_interpreter=$2
262	if [ -z "$_procname" ]; then
263		err 3 'USAGE: check_process procname [interpreter]'
264	fi
265	_find_processes $_procname ${_interpreter:-.} '-ax'
266}
267
268#
269# _find_processes procname interpreter psargs
270#	Search for procname in the output of ps generated by psargs.
271#	Prints the PIDs of any matching processes, space separated.
272#
273#	If interpreter == ".", check the following variations of procname
274#	against the first word of each command:
275#		procname
276#		`basename procname`
277#		`basename procname` + ":"
278#		"(" + `basename procname` + ")"
279#		"[" + `basename procname` + "]"
280#
281#	If interpreter != ".", read the first line of procname, remove the
282#	leading #!, normalise whitespace, append procname, and attempt to
283#	match that against each command, either as is, or with extra words
284#	at the end.  As an alternative, to deal with interpreted daemons
285#	using perl, the basename of the interpreter plus a colon is also
286#	tried as the prefix to procname.
287#
288_find_processes()
289{
290	if [ $# -ne 3 ]; then
291		err 3 'USAGE: _find_processes procname interpreter psargs'
292	fi
293	_procname=$1
294	_interpreter=$2
295	_psargs=$3
296
297	_pref=
298	if [ $_interpreter != "." ]; then	# an interpreted script
299		_script=${_chroot}${_chroot:+"/"}$_procname
300		if [ -r $_script ]; then
301			read _interp < $_script	# read interpreter name
302			case "$_interp" in
303			\#!*)
304				_interp=${_interp#\#!}	# strip #!
305				set -- $_interp
306				case $1 in
307				*/bin/env)
308					shift	# drop env to get real name
309					;;
310				esac
311				if [ $_interpreter != $1 ]; then
312					warn "\$command_interpreter $_interpreter != $1"
313				fi
314				;;
315			*)
316				warn "no shebang line in $_script"
317				set -- $_interpreter
318				;;
319			esac
320		else
321			warn "cannot read shebang line from $_script"
322			set -- $_interpreter
323		fi
324		_interp="$* $_procname"		# cleanup spaces, add _procname
325		_interpbn=${1##*/}
326		_fp_args='_argv'
327		_fp_match='case "$_argv" in
328		    ${_interp}|"${_interp} "*|"${_interpbn}: ${_procname}"*)'
329	else					# a normal daemon
330		_procnamebn=${_procname##*/}
331		_fp_args='_arg0 _argv'
332		_fp_match='case "$_arg0" in
333		    $_procname|$_procnamebn|${_procnamebn}:|"(${_procnamebn})"|"[${_procnamebn}]")'
334	fi
335
336	_proccheck="\
337		$PS 2>/dev/null -o pid= -o jid= -o command= $_psargs"' |
338		while read _npid _jid '"$_fp_args"'; do
339			'"$_fp_match"'
340				if [ "$JID" -eq "$_jid" ];
341				then echo -n "$_pref$_npid";
342				_pref=" ";
343				fi
344				;;
345			esac
346		done'
347
348#	debug "in _find_processes: proccheck is ($_proccheck)."
349	eval $_proccheck
350}
351
352#
353# wait_for_pids pid [pid ...]
354#	spins until none of the pids exist
355#
356wait_for_pids()
357{
358	local _list _prefix _nlist _j
359
360	_list="$@"
361	if [ -z "$_list" ]; then
362		return
363	fi
364	_prefix=
365	while true; do
366		_nlist="";
367		for _j in $_list; do
368			if kill -0 $_j 2>/dev/null; then
369				_nlist="${_nlist}${_nlist:+ }$_j"
370				[ -n "$_prefix" ] && sleep 1
371			fi
372		done
373		if [ -z "$_nlist" ]; then
374			break
375		fi
376		_list=$_nlist
377		echo -n ${_prefix:-"Waiting for PIDS: "}$_list
378		_prefix=", "
379		pwait $_list 2>/dev/null
380	done
381	if [ -n "$_prefix" ]; then
382		echo "."
383	fi
384}
385
386#
387# get_pidfile_from_conf string file
388#
389#	Takes a string to search for in the specified file.
390#	Ignores lines with traditional comment characters.
391#
392# Example:
393#
394# if get_pidfile_from_conf string file; then
395#	pidfile="$_pidfile_from_conf"
396# else
397#	pidfile='appropriate default'
398# fi
399#
400get_pidfile_from_conf()
401{
402	if [ -z "$1" -o -z "$2" ]; then
403		err 3 "USAGE: get_pidfile_from_conf string file ($name)"
404	fi
405
406	local string file line
407
408	string="$1" ; file="$2"
409
410	if [ ! -s "$file" ]; then
411		err 3 "get_pidfile_from_conf: $file does not exist ($name)"
412	fi
413
414	while read line; do
415		case "$line" in
416		*[#\;]*${string}*)	continue ;;
417		*${string}*)		break ;;
418		esac
419	done < $file
420
421	if [ -n "$line" ]; then
422		line=${line#*/}
423		_pidfile_from_conf="/${line%%[\"\;]*}"
424	else
425		return 1
426	fi
427}
428
429#
430# check_startmsgs
431#	If rc_quiet is set (usually as a result of using faststart at
432#	boot time) check if rc_startmsgs is enabled.
433#
434check_startmsgs()
435{
436	if [ -n "$rc_quiet" ]; then
437		checkyesno rc_startmsgs
438	else
439		return 0
440	fi
441}
442
443#
444# run_rc_command argument
445#	Search for argument in the list of supported commands, which is:
446#		"start stop restart rcvar status poll ${extra_commands}"
447#	If there's a match, run ${argument}_cmd or the default method
448#	(see below).
449#
450#	If argument has a given prefix, then change the operation as follows:
451#		Prefix	Operation
452#		------	---------
453#		fast	Skip the pid check, and set rc_fast=yes, rc_quiet=yes
454#		force	Set ${rcvar} to YES, and set rc_force=yes
455#		one	Set ${rcvar} to YES
456#		quiet	Don't output some diagnostics, and set rc_quiet=yes
457#
458#	The following globals are used:
459#
460#	Name		Needed	Purpose
461#	----		------	-------
462#	name		y	Name of script.
463#
464#	command		n	Full path to command.
465#				Not needed if ${rc_arg}_cmd is set for
466#				each keyword.
467#
468#	command_args	n	Optional args/shell directives for command.
469#
470#	command_interpreter n	If not empty, command is interpreted, so
471#				call check_{pidfile,process}() appropriately.
472#
473#	desc		n	Description of script.
474#
475#	extra_commands	n	List of extra commands supported.
476#
477#	pidfile		n	If set, use check_pidfile $pidfile $command,
478#				otherwise use check_process $command.
479#				In either case, only check if $command is set.
480#
481#	procname	n	Process name to check for instead of $command.
482#
483#	rcvar		n	This is checked with checkyesno to determine
484#				if the action should be run.
485#
486#	${name}_program	n	Full path to command.
487#				Meant to be used in /etc/rc.conf to override
488#				${command}.
489#
490#	${name}_chroot	n	Directory to chroot to before running ${command}
491#				Requires /usr to be mounted.
492#
493#	${name}_chdir	n	Directory to cd to before running ${command}
494#				(if not using ${name}_chroot).
495#
496#	${name}_flags	n	Arguments to call ${command} with.
497#				NOTE:	$flags from the parent environment
498#					can be used to override this.
499#
500#	${name}_nice	n	Nice level to run ${command} at.
501#
502#	${name}_user	n	User to run ${command} as, using su(1) if not
503#				using ${name}_chroot.
504#				Requires /usr to be mounted.
505#
506#	${name}_group	n	Group to run chrooted ${command} as.
507#				Requires /usr to be mounted.
508#
509#	${name}_groups	n	Comma separated list of supplementary groups
510#				to run the chrooted ${command} with.
511#				Requires /usr to be mounted.
512#
513#	${rc_arg}_cmd	n	If set, use this as the method when invoked;
514#				Otherwise, use default command (see below)
515#
516#	${rc_arg}_precmd n	If set, run just before performing the
517#				${rc_arg}_cmd method in the default
518#				operation (i.e, after checking for required
519#				bits and process (non)existence).
520#				If this completes with a non-zero exit code,
521#				don't run ${rc_arg}_cmd.
522#
523#	${rc_arg}_postcmd n	If set, run just after performing the
524#				${rc_arg}_cmd method, if that method
525#				returned a zero exit code.
526#
527#	required_dirs	n	If set, check for the existence of the given
528#				directories before running a (re)start command.
529#
530#	required_files	n	If set, check for the readability of the given
531#				files before running a (re)start command.
532#
533#	required_modules n	If set, ensure the given kernel modules are
534#				loaded before running a (re)start command.
535#				The check and possible loads are actually
536#				done after start_precmd so that the modules
537#				aren't loaded in vain, should the precmd
538#				return a non-zero status to indicate a error.
539#				If a word in the list looks like "foo:bar",
540#				"foo" is the KLD file name and "bar" is the
541#				module name.  If a word looks like "foo~bar",
542#				"foo" is the KLD file name and "bar" is a
543#				egrep(1) pattern matching the module name.
544#				Otherwise the module name is assumed to be
545#				the same as the KLD file name, which is most
546#				common.  See load_kld().
547#
548#	required_vars	n	If set, perform checkyesno on each of the
549#				listed variables before running the default
550#				(re)start command.
551#
552#	Default behaviour for a given argument, if no override method is
553#	provided:
554#
555#	Argument	Default behaviour
556#	--------	-----------------
557#	start		if !running && checkyesno ${rcvar}
558#				${command}
559#
560#	stop		if ${pidfile}
561#				rc_pid=$(check_pidfile $pidfile $command)
562#			else
563#				rc_pid=$(check_process $command)
564#			kill $sig_stop $rc_pid
565#			wait_for_pids $rc_pid
566#			($sig_stop defaults to TERM.)
567#
568#	reload		Similar to stop, except use $sig_reload instead,
569#			and doesn't wait_for_pids.
570#			$sig_reload defaults to HUP.
571#			Note that `reload' isn't provided by default,
572#			it should be enabled via $extra_commands.
573#
574#	restart		Run `stop' then `start'.
575#
576#	status		Show if ${command} is running, etc.
577#
578#	poll		Wait for ${command} to exit.
579#
580#	rcvar		Display what rc.conf variable is used (if any).
581#
582#	Variables available to methods, and after run_rc_command() has
583#	completed:
584#
585#	Variable	Purpose
586#	--------	-------
587#	rc_arg		Argument to command, after fast/force/one processing
588#			performed
589#
590#	rc_flags	Flags to start the default command with.
591#			Defaults to ${name}_flags, unless overridden
592#			by $flags from the environment.
593#			This variable may be changed by the precmd method.
594#
595#	rc_pid		PID of command (if appropriate)
596#
597#	rc_fast		Not empty if "fast" was provided (q.v.)
598#
599#	rc_force	Not empty if "force" was provided (q.v.)
600#
601#	rc_quiet	Not empty if "quiet" was provided
602#
603#
604run_rc_command()
605{
606	_return=0
607	rc_arg=$1
608	if [ -z "$name" ]; then
609		err 3 'run_rc_command: $name is not set.'
610	fi
611
612	# Don't repeat the first argument when passing additional command-
613	# line arguments to the command subroutines.
614	#
615	shift 1
616	rc_extra_args="$*"
617
618	_rc_prefix=
619	case "$rc_arg" in
620	fast*)				# "fast" prefix; don't check pid
621		rc_arg=${rc_arg#fast}
622		rc_fast=yes
623		rc_quiet=yes
624		;;
625	force*)				# "force" prefix; always run
626		rc_force=yes
627		_rc_prefix=force
628		rc_arg=${rc_arg#${_rc_prefix}}
629		if [ -n "${rcvar}" ]; then
630			eval ${rcvar}=YES
631		fi
632		;;
633	one*)				# "one" prefix; set ${rcvar}=yes
634		_rc_prefix=one
635		rc_arg=${rc_arg#${_rc_prefix}}
636		if [ -n "${rcvar}" ]; then
637			eval ${rcvar}=YES
638		fi
639		;;
640	quiet*)				# "quiet" prefix; omit some messages
641		_rc_prefix=quiet
642		rc_arg=${rc_arg#${_rc_prefix}}
643		rc_quiet=yes
644		;;
645	esac
646
647	eval _override_command=\$${name}_program
648	command=${_override_command:-$command}
649
650	_keywords="start stop restart rcvar $extra_commands"
651	rc_pid=
652	_pidcmd=
653	_procname=${procname:-${command}}
654
655					# setup pid check command
656	if [ -n "$_procname" ]; then
657		if [ -n "$pidfile" ]; then
658			_pidcmd='rc_pid=$(check_pidfile '"$pidfile $_procname $command_interpreter"')'
659		else
660			_pidcmd='rc_pid=$(check_process '"$_procname $command_interpreter"')'
661		fi
662		if [ -n "$_pidcmd" ]; then
663			_keywords="${_keywords} status poll"
664		fi
665	fi
666
667	if [ -z "$rc_arg" ]; then
668		rc_usage $_keywords
669	fi
670
671	if [ -n "$flags" ]; then	# allow override from environment
672		rc_flags=$flags
673	else
674		eval rc_flags=\$${name}_flags
675	fi
676	eval _chdir=\$${name}_chdir	_chroot=\$${name}_chroot \
677	    _nice=\$${name}_nice	_user=\$${name}_user \
678	    _group=\$${name}_group	_groups=\$${name}_groups
679
680	if [ -n "$_user" ]; then	# unset $_user if running as that user
681		if [ "$_user" = "$(eval $IDCMD)" ]; then
682			unset _user
683		fi
684	fi
685
686	eval $_pidcmd			# determine the pid if necessary
687
688	for _elem in $_keywords; do
689		if [ "$_elem" != "$rc_arg" ]; then
690			continue
691		fi
692					# if ${rcvar} is set, $1 is not "rcvar"
693					# and ${rc_pid} is not set, then run
694					#	checkyesno ${rcvar}
695					# and return if that failed
696					#
697		if [ -n "${rcvar}" -a "$rc_arg" != "rcvar" -a "$rc_arg" != "stop" ] ||
698		    [ -n "${rcvar}" -a "$rc_arg" = "stop" -a -z "${rc_pid}" ]; then
699			if ! checkyesno ${rcvar}; then
700				if [ -n "${rc_quiet}" ]; then
701					return 0
702				fi
703				echo -n "Cannot '${rc_arg}' $name. Set ${rcvar} to "
704				echo -n "YES in /etc/rc.conf or use 'one${rc_arg}' "
705				echo "instead of '${rc_arg}'."
706				return 0
707			fi
708		fi
709
710					# if there's a custom ${XXX_cmd},
711					# run that instead of the default
712					#
713		eval _cmd=\$${rc_arg}_cmd \
714		     _precmd=\$${rc_arg}_precmd \
715		     _postcmd=\$${rc_arg}_postcmd
716
717		if [ -n "$_cmd" ]; then
718			_run_rc_precmd || return 1
719			_run_rc_doit "$_cmd $rc_extra_args" || return 1
720			_run_rc_postcmd
721			return $_return
722		fi
723
724		case "$rc_arg" in	# default operations...
725
726		status)
727			_run_rc_precmd || return 1
728			if [ -n "$rc_pid" ]; then
729				echo "${name} is running as pid $rc_pid."
730			else
731				echo "${name} is not running."
732				return 1
733			fi
734			_run_rc_postcmd
735			;;
736
737		start)
738			if [ -z "$rc_fast" -a -n "$rc_pid" ]; then
739				echo 1>&2 "${name} already running? (pid=$rc_pid)."
740				return 1
741			fi
742
743			if [ ! -x ${_chroot}${_chroot:+"/"}${command} ]; then
744				warn "run_rc_command: cannot run $command"
745				return 1
746			fi
747
748			if ! _run_rc_precmd; then
749				warn "failed precmd routine for ${name}"
750				return 1
751			fi
752
753					# setup the full command to run
754					#
755			check_startmsgs && echo "Starting ${name}."
756			if [ -n "$_chroot" ]; then
757				_doit="\
758${_nice:+nice -n $_nice }\
759chroot ${_user:+-u $_user }${_group:+-g $_group }${_groups:+-G $_groups }\
760$_chroot $command $rc_flags $command_args"
761			else
762				_doit="\
763${_chdir:+cd $_chdir && }\
764$command $rc_flags $command_args"
765				if [ -n "$_user" ]; then
766				    _doit="su -m $_user -c 'sh -c \"$_doit\"'"
767				fi
768				if [ -n "$_nice" ]; then
769					if [ -z "$_user" ]; then
770						_doit="sh -c \"$_doit\""
771					fi
772					_doit="nice -n $_nice $_doit"
773				fi
774			fi
775
776					# run the full command
777					#
778			if ! _run_rc_doit "$_doit"; then
779				warn "failed to start ${name}"
780				return 1
781			fi
782
783					# finally, run postcmd
784					#
785			_run_rc_postcmd
786			;;
787
788		stop)
789			if [ -z "$rc_pid" ]; then
790				[ -n "$rc_fast" ] && return 0
791				_run_rc_notrunning
792				return 1
793			fi
794
795			_run_rc_precmd || return 1
796
797					# send the signal to stop
798					#
799			echo "Stopping ${name}."
800			_doit=$(_run_rc_killcmd "${sig_stop:-TERM}")
801			_run_rc_doit "$_doit" || return 1
802
803					# wait for the command to exit,
804					# and run postcmd.
805			wait_for_pids $rc_pid
806
807			_run_rc_postcmd
808			;;
809
810		reload)
811			if [ -z "$rc_pid" ]; then
812				_run_rc_notrunning
813				return 1
814			fi
815
816			_run_rc_precmd || return 1
817
818			_doit=$(_run_rc_killcmd "${sig_reload:-HUP}")
819			_run_rc_doit "$_doit" || return 1
820
821			_run_rc_postcmd
822			;;
823
824		restart)
825					# prevent restart being called more
826					# than once by any given script
827					#
828			if ${_rc_restart_done:-false}; then
829				return 0
830			fi
831			_rc_restart_done=true
832
833			_run_rc_precmd || return 1
834
835			# run those in a subshell to keep global variables
836			( run_rc_command ${_rc_prefix}stop $rc_extra_args )
837			( run_rc_command ${_rc_prefix}start $rc_extra_args )
838			_return=$?
839			[ $_return -ne 0 ] && [ -z "$rc_force" ] && return 1
840
841			_run_rc_postcmd
842			;;
843
844		poll)
845			_run_rc_precmd || return 1
846			if [ -n "$rc_pid" ]; then
847				wait_for_pids $rc_pid
848			fi
849			_run_rc_postcmd
850			;;
851
852		rcvar)
853			echo -n "# $name"
854			if [ -n "$desc" ]; then
855				echo " : $desc"
856			else
857				echo ""
858			fi
859			echo "#"
860			# Get unique vars in $rcvar $rcvars
861			for _v in $rcvar $rcvars; do
862				case $v in
863				$_v\ *|\ *$_v|*\ $_v\ *) ;;
864				*)	v="${v# } $_v" ;;
865				esac
866			done
867
868			# Display variables.
869			for _v in $v; do
870				if [ -z "$_v" ]; then
871					continue
872				fi
873
874				eval _desc=\$${_v}_desc
875				eval _defval=\$${_v}_defval
876				_h="-"
877
878				eval echo \"$_v=\\\"\$$_v\\\"\"
879				# decode multiple lines of _desc
880				while [ -n "$_desc" ]; do
881					case $_desc in
882					*^^*)
883						echo "# $_h ${_desc%%^^*}"
884						_desc=${_desc#*^^}
885						_h=" "
886						;;
887					*)
888						echo "# $_h ${_desc}"
889						break
890						;;
891					esac
892				done
893				echo "#   (default: \"$_defval\")"
894			done
895			echo ""
896			;;
897
898		*)
899			rc_usage $_keywords
900			;;
901
902		esac
903		return $_return
904	done
905
906	echo 1>&2 "$0: unknown directive '$rc_arg'."
907	rc_usage $_keywords
908	# not reached
909}
910
911#
912# Helper functions for run_rc_command: common code.
913# They use such global variables besides the exported rc_* ones:
914#
915#	name	       R/W
916#	------------------
917#	_precmd		R
918#	_postcmd	R
919#	_return		W
920#
921_run_rc_precmd()
922{
923	check_required_before "$rc_arg" || return 1
924
925	if [ -n "$_precmd" ]; then
926		debug "run_rc_command: ${rc_arg}_precmd: $_precmd $rc_extra_args"
927		eval "$_precmd $rc_extra_args"
928		_return=$?
929
930		# If precmd failed and force isn't set, request exit.
931		if [ $_return -ne 0 ] && [ -z "$rc_force" ]; then
932			return 1
933		fi
934	fi
935
936	check_required_after "$rc_arg" || return 1
937
938	return 0
939}
940
941_run_rc_postcmd()
942{
943	if [ -n "$_postcmd" ]; then
944		debug "run_rc_command: ${rc_arg}_postcmd: $_postcmd $rc_extra_args"
945		eval "$_postcmd $rc_extra_args"
946		_return=$?
947	fi
948	return 0
949}
950
951_run_rc_doit()
952{
953	debug "run_rc_command: doit: $*"
954	eval "$@"
955	_return=$?
956
957	# If command failed and force isn't set, request exit.
958	if [ $_return -ne 0 ] && [ -z "$rc_force" ]; then
959		return 1
960	fi
961
962	return 0
963}
964
965_run_rc_notrunning()
966{
967	local _pidmsg
968
969	if [ -n "$pidfile" ]; then
970		_pidmsg=" (check $pidfile)."
971	else
972		_pidmsg=
973	fi
974	echo 1>&2 "${name} not running?${_pidmsg}"
975}
976
977_run_rc_killcmd()
978{
979	local _cmd
980
981	_cmd="kill -$1 $rc_pid"
982	if [ -n "$_user" ]; then
983		_cmd="su -m ${_user} -c 'sh -c \"${_cmd}\"'"
984	fi
985	echo "$_cmd"
986}
987
988#
989# run_rc_script file arg
990#	Start the script `file' with `arg', and correctly handle the
991#	return value from the script.
992#	If `file' ends with `.sh', it's sourced into the current environment
993#	when $rc_fast_and_loose is set, otherwise it is run as a child process.
994#	If `file' appears to be a backup or scratch file, ignore it.
995#	Otherwise if it is executable run as a child process.
996#
997run_rc_script()
998{
999	_file=$1
1000	_arg=$2
1001	if [ -z "$_file" -o -z "$_arg" ]; then
1002		err 3 'USAGE: run_rc_script file arg'
1003	fi
1004
1005	unset	name command command_args command_interpreter \
1006		extra_commands pidfile procname \
1007		rcvar rcvars rcvars_obsolete required_dirs required_files \
1008		required_vars
1009	eval unset ${_arg}_cmd ${_arg}_precmd ${_arg}_postcmd
1010
1011	case "$_file" in
1012	/etc/rc.d/*.sh)			# no longer allowed in the base
1013		warn "Ignoring old-style startup script $_file"
1014		;;
1015	*[~#]|*.OLD|*.bak|*.orig|*,v)	# scratch file; skip
1016		warn "Ignoring scratch file $_file"
1017		;;
1018	*)				# run in subshell
1019		if [ -x $_file ]; then
1020			if [ -n "$rc_fast_and_loose" ]; then
1021				set $_arg; . $_file
1022			else
1023				( trap "echo Script $_file interrupted; kill -QUIT $$" 3
1024				  trap "echo Script $_file interrupted; exit 1" 2
1025				  trap "echo Script $_file running" 29
1026				  set $_arg; . $_file )
1027			fi
1028		fi
1029		;;
1030	esac
1031}
1032
1033#
1034# load_rc_config name
1035#	Source in the configuration file for a given name.
1036#
1037load_rc_config()
1038{
1039	local _name _var _defval _v _msg _new
1040	_name=$1
1041	if [ -z "$_name" ]; then
1042		err 3 'USAGE: load_rc_config name'
1043	fi
1044
1045	if ${_rc_conf_loaded:-false}; then
1046		:
1047	else
1048		if [ -r /etc/defaults/rc.conf ]; then
1049			debug "Sourcing /etc/defaults/rc.conf"
1050			. /etc/defaults/rc.conf
1051			source_rc_confs
1052		elif [ -r /etc/rc.conf ]; then
1053			debug "Sourcing /etc/rc.conf (/etc/defaults/rc.conf doesn't exist)."
1054			. /etc/rc.conf
1055		fi
1056		_rc_conf_loaded=true
1057	fi
1058	if [ -f /etc/rc.conf.d/"$_name" ]; then
1059		debug "Sourcing /etc/rc.conf.d/${_name}"
1060		. /etc/rc.conf.d/"$_name"
1061	fi
1062
1063	# Old variable name support -- Remove before 9.0-RELEASE
1064	#
1065	[ -n "$enable_quotas" ] && err 1 "enable_quotas is deprecated, use quota_enable"
1066
1067	# Set defaults if defined.
1068	for _var in $rcvar $rcvars; do
1069		_defval=`eval echo "\\\$${_var}_defval"`
1070		if [ -n "$_defval" ]; then
1071			eval : \${$_var:=\$${_var}_defval}
1072		fi
1073	done
1074
1075	# check obsolete rc.conf variables
1076	for _var in $rcvars_obsolete; do
1077		_v=`eval echo \\$$_var`
1078		_msg=`eval echo \\$${_var}_obsolete_msg`
1079		_new=`eval echo \\$${_var}_newvar`
1080		case $_v in
1081		"")
1082			;;
1083		*)
1084			if [ -z "$_new" ]; then
1085				_msg="Ignored."
1086			else
1087				eval $_new=\"\$$_var\"
1088				if [ -z "$_msg" ]; then
1089					_msg="Use \$$_new instead."
1090				fi
1091			fi
1092			warn "\$$_var is obsolete.  $_msg"
1093			;;
1094		esac
1095	done
1096}
1097
1098#
1099# load_rc_config_var name var
1100#	Read the rc.conf(5) var for name and set in the
1101#	current shell, using load_rc_config in a subshell to prevent
1102#	unwanted side effects from other variable assignments.
1103#
1104load_rc_config_var()
1105{
1106	if [ $# -ne 2 ]; then
1107		err 3 'USAGE: load_rc_config_var name var'
1108	fi
1109	eval $(eval '(
1110		load_rc_config '$1' >/dev/null;
1111                if [ -n "${'$2'}" -o "${'$2'-UNSET}" != "UNSET" ]; then
1112			echo '$2'=\'\''${'$2'}\'\'';
1113		fi
1114	)' )
1115}
1116
1117#
1118# rc_usage commands
1119#	Print a usage string for $0, with `commands' being a list of
1120#	valid commands.
1121#
1122rc_usage()
1123{
1124	echo -n 1>&2 "Usage: $0 [fast|force|one]("
1125
1126	_sep=
1127	for _elem; do
1128		echo -n 1>&2 "$_sep$_elem"
1129		_sep="|"
1130	done
1131	echo 1>&2 ")"
1132	exit 1
1133}
1134
1135#
1136# err exitval message
1137#	Display message to stderr and log to the syslog, and exit with exitval.
1138#
1139err()
1140{
1141	exitval=$1
1142	shift
1143
1144	if [ -x /usr/bin/logger ]; then
1145		logger "$0: ERROR: $*"
1146	fi
1147	echo 1>&2 "$0: ERROR: $*"
1148	exit $exitval
1149}
1150
1151#
1152# warn message
1153#	Display message to stderr and log to the syslog.
1154#
1155warn()
1156{
1157	if [ -x /usr/bin/logger ]; then
1158		logger "$0: WARNING: $*"
1159	fi
1160	echo 1>&2 "$0: WARNING: $*"
1161}
1162
1163#
1164# info message
1165#	Display informational message to stdout and log to syslog.
1166#
1167info()
1168{
1169	case ${rc_info} in
1170	[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
1171		if [ -x /usr/bin/logger ]; then
1172			logger "$0: INFO: $*"
1173		fi
1174		echo "$0: INFO: $*"
1175		;;
1176	esac
1177}
1178
1179#
1180# debug message
1181#	If debugging is enabled in rc.conf output message to stderr.
1182#	BEWARE that you don't call any subroutine that itself calls this
1183#	function.
1184#
1185debug()
1186{
1187	case ${rc_debug} in
1188	[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
1189		if [ -x /usr/bin/logger ]; then
1190			logger "$0: DEBUG: $*"
1191		fi
1192		echo 1>&2 "$0: DEBUG: $*"
1193		;;
1194	esac
1195}
1196
1197#
1198# backup_file action file cur backup
1199#	Make a backup copy of `file' into `cur', and save the previous
1200#	version of `cur' as `backup' or use rcs for archiving.
1201#
1202#	This routine checks the value of the backup_uses_rcs variable,
1203#	which can be either YES or NO.
1204#
1205#	The `action' keyword can be one of the following:
1206#
1207#	add		`file' is now being backed up (and is possibly
1208#			being reentered into the backups system).  `cur'
1209#			is created and RCS files, if necessary, are
1210#			created as well.
1211#
1212#	update		`file' has changed and needs to be backed up.
1213#			If `cur' exists, it is copied to to `back' or
1214#			checked into RCS (if the repository file is old),
1215#			and then `file' is copied to `cur'.  Another RCS
1216#			check in done here if RCS is being used.
1217#
1218#	remove		`file' is no longer being tracked by the backups
1219#			system.  If RCS is not being used, `cur' is moved
1220#			to `back', otherwise an empty file is checked in,
1221#			and then `cur' is removed.
1222#
1223#
1224backup_file()
1225{
1226	_action=$1
1227	_file=$2
1228	_cur=$3
1229	_back=$4
1230
1231	if checkyesno backup_uses_rcs; then
1232		_msg0="backup archive"
1233		_msg1="update"
1234
1235		# ensure that history file is not locked
1236		if [ -f $_cur,v ]; then
1237			rcs -q -u -U -M $_cur
1238		fi
1239
1240		# ensure after switching to rcs that the
1241		# current backup is not lost
1242		if [ -f $_cur ]; then
1243			# no archive, or current newer than archive
1244			if [ ! -f $_cur,v -o $_cur -nt $_cur,v ]; then
1245				ci -q -f -u -t-"$_msg0" -m"$_msg1" $_cur
1246				rcs -q -kb -U $_cur
1247				co -q -f -u $_cur
1248			fi
1249		fi
1250
1251		case $_action in
1252		add|update)
1253			cp -p $_file $_cur
1254			ci -q -f -u -t-"$_msg0" -m"$_msg1" $_cur
1255			rcs -q -kb -U $_cur
1256			co -q -f -u $_cur
1257			chown root:wheel $_cur $_cur,v
1258			;;
1259		remove)
1260			cp /dev/null $_cur
1261			ci -q -f -u -t-"$_msg0" -m"$_msg1" $_cur
1262			rcs -q -kb -U $_cur
1263			chown root:wheel $_cur $_cur,v
1264			rm $_cur
1265			;;
1266		esac
1267	else
1268		case $_action in
1269		add|update)
1270			if [ -f $_cur ]; then
1271				cp -p $_cur $_back
1272			fi
1273			cp -p $_file $_cur
1274			chown root:wheel $_cur
1275			;;
1276		remove)
1277			mv -f $_cur $_back
1278			;;
1279		esac
1280	fi
1281}
1282
1283# make_symlink src link
1284#	Make a symbolic link 'link' to src from basedir. If the
1285#	directory in which link is to be created does not exist
1286#	a warning will be displayed and an error will be returned.
1287#	Returns 0 on sucess, 1 otherwise.
1288#
1289make_symlink()
1290{
1291	local src link linkdir _me
1292	src="$1"
1293	link="$2"
1294	linkdir="`dirname $link`"
1295	_me="make_symlink()"
1296
1297	if [ -z "$src" -o -z "$link" ]; then
1298		warn "$_me: requires two arguments."
1299		return 1
1300	fi
1301	if [ ! -d "$linkdir" ]; then
1302		warn "$_me: the directory $linkdir does not exist."
1303		return 1
1304	fi
1305	if ! ln -sf $src $link; then
1306		warn "$_me: unable to make a symbolic link from $link to $src"
1307		return 1
1308	fi
1309	return 0
1310}
1311
1312# devfs_rulesets_from_file file
1313#	Reads a set of devfs commands from file, and creates
1314#	the specified rulesets with their rules. Returns non-zero
1315#	if there was an error.
1316#
1317devfs_rulesets_from_file()
1318{
1319	local file _err _me
1320	file="$1"
1321	_me="devfs_rulesets_from_file"
1322	_err=0
1323
1324	if [ -z "$file" ]; then
1325		warn "$_me: you must specify a file"
1326		return 1
1327	fi
1328	if [ ! -e "$file" ]; then
1329		debug "$_me: no such file ($file)"
1330		return 0
1331	fi
1332	debug "reading rulesets from file ($file)"
1333	{ while read line
1334	do
1335		case $line in
1336		\#*)
1337			continue
1338			;;
1339		\[*\]*)
1340			rulenum=`expr "$line" : "\[.*=\([0-9]*\)\]"`
1341			if [ -z "$rulenum" ]; then
1342				warn "$_me: cannot extract rule number ($line)"
1343				_err=1
1344				break
1345			fi
1346			rulename=`expr "$line" : "\[\(.*\)=[0-9]*\]"`
1347			if [ -z "$rulename" ]; then
1348				warn "$_me: cannot extract rule name ($line)"
1349				_err=1
1350				break;
1351			fi
1352			eval $rulename=\$rulenum
1353			debug "found ruleset: $rulename=$rulenum"
1354			if ! /sbin/devfs rule -s $rulenum delset; then
1355				_err=1
1356				break
1357			fi
1358			;;
1359		*)
1360			rulecmd="${line%%"\#*"}"
1361			# evaluate the command incase it includes
1362			# other rules
1363			if [ -n "$rulecmd" ]; then
1364				debug "adding rule ($rulecmd)"
1365				if ! eval /sbin/devfs rule -s $rulenum $rulecmd
1366				then
1367					_err=1
1368					break
1369				fi
1370			fi
1371			;;
1372		esac
1373		if [ $_err -ne 0 ]; then
1374			debug "error in $_me"
1375			break
1376		fi
1377	done } < $file
1378	return $_err
1379}
1380
1381# devfs_init_rulesets
1382#	Initializes rulesets from configuration files. Returns
1383#	non-zero if there was an error.
1384#
1385devfs_init_rulesets()
1386{
1387	local file _me
1388	_me="devfs_init_rulesets"
1389
1390	# Go through this only once
1391	if [ -n "$devfs_rulesets_init" ]; then
1392		debug "$_me: devfs rulesets already initialized"
1393		return
1394	fi
1395	for file in $devfs_rulesets; do
1396		if ! devfs_rulesets_from_file $file; then
1397			warn "$_me: could not read rules from $file"
1398			return 1
1399		fi
1400	done
1401	devfs_rulesets_init=1
1402	debug "$_me: devfs rulesets initialized"
1403	return 0
1404}
1405
1406# devfs_set_ruleset ruleset [dir]
1407#	Sets the default ruleset of dir to ruleset. The ruleset argument
1408#	must be a ruleset name as specified in devfs.rules(5) file.
1409#	Returns non-zero if it could not set it successfully.
1410#
1411devfs_set_ruleset()
1412{
1413	local devdir rs _me
1414	[ -n "$1" ] && eval rs=\$$1 || rs=
1415	[ -n "$2" ] && devdir="-m "$2"" || devdir=
1416	_me="devfs_set_ruleset"
1417
1418	if [ -z "$rs" ]; then
1419		warn "$_me: you must specify a ruleset number"
1420		return 1
1421	fi
1422	debug "$_me: setting ruleset ($rs) on mount-point (${devdir#-m })"
1423	if ! /sbin/devfs $devdir ruleset $rs; then
1424		warn "$_me: unable to set ruleset $rs to ${devdir#-m }"
1425		return 1
1426	fi
1427	return 0
1428}
1429
1430# devfs_apply_ruleset ruleset [dir]
1431#	Apply ruleset number $ruleset to the devfs mountpoint $dir.
1432#	The ruleset argument must be a ruleset name as specified
1433#	in a devfs.rules(5) file.  Returns 0 on success or non-zero
1434#	if it could not apply the ruleset.
1435#
1436devfs_apply_ruleset()
1437{
1438	local devdir rs _me
1439	[ -n "$1" ] && eval rs=\$$1 || rs=
1440	[ -n "$2" ] && devdir="-m "$2"" || devdir=
1441	_me="devfs_apply_ruleset"
1442
1443	if [ -z "$rs" ]; then
1444		warn "$_me: you must specify a ruleset"
1445		return 1
1446	fi
1447	debug "$_me: applying ruleset ($rs) to mount-point (${devdir#-m })"
1448	if ! /sbin/devfs $devdir rule -s $rs applyset; then
1449		warn "$_me: unable to apply ruleset $rs to ${devdir#-m }"
1450		return 1
1451	fi
1452	return 0
1453}
1454
1455# devfs_domount dir [ruleset]
1456#	Mount devfs on dir. If ruleset is specified it is set
1457#	on the mount-point. It must also be a ruleset name as specified
1458#	in a devfs.rules(5) file. Returns 0 on success.
1459#
1460devfs_domount()
1461{
1462	local devdir rs _me
1463	devdir="$1"
1464	[ -n "$2" ] && rs=$2 || rs=
1465	_me="devfs_domount()"
1466
1467	if [ -z "$devdir" ]; then
1468		warn "$_me: you must specify a mount-point"
1469		return 1
1470	fi
1471	debug "$_me: mount-point is ($devdir), ruleset is ($rs)"
1472	if ! mount -t devfs dev "$devdir"; then
1473		warn "$_me: Unable to mount devfs on $devdir"
1474		return 1
1475	fi
1476	if [ -n "$rs" ]; then
1477		devfs_init_rulesets
1478		devfs_set_ruleset $rs $devdir
1479		devfs -m $devdir rule applyset
1480	fi
1481	return 0
1482}
1483
1484# devfs_mount_jail dir [ruleset]
1485#	Mounts a devfs file system appropriate for jails
1486#	on the directory dir. If ruleset is specified, the ruleset
1487#	it names will be used instead.  If present, ruleset must
1488#	be the name of a ruleset as defined in a devfs.rules(5) file.
1489#	This function returns non-zero if an error occurs.
1490#
1491devfs_mount_jail()
1492{
1493	local jdev rs _me
1494	jdev="$1"
1495	[ -n "$2" ] && rs=$2 || rs="devfsrules_jail"
1496	_me="devfs_mount_jail"
1497
1498	devfs_init_rulesets
1499	if ! devfs_domount "$jdev" $rs; then
1500		warn "$_me: devfs was not mounted on $jdev"
1501		return 1
1502	fi
1503	return 0
1504}
1505
1506# Provide a function for normalizing the mounting of memory
1507# filesystems.  This should allow the rest of the code here to remain
1508# as close as possible between 5-current and 4-stable.
1509#   $1 = size
1510#   $2 = mount point
1511#   $3 = (optional) extra mdmfs flags
1512mount_md()
1513{
1514	if [ -n "$3" ]; then
1515		flags="$3"
1516	fi
1517	/sbin/mdmfs $flags -s $1 md $2
1518}
1519
1520# Code common to scripts that need to load a kernel module
1521# if it isn't in the kernel yet. Syntax:
1522#   load_kld [-e regex] [-m module] file
1523# where -e or -m chooses the way to check if the module
1524# is already loaded:
1525#   regex is egrep'd in the output from `kldstat -v',
1526#   module is passed to `kldstat -m'.
1527# The default way is as though `-m file' were specified.
1528load_kld()
1529{
1530	local _loaded _mod _opt _re
1531
1532	while getopts "e:m:" _opt; do
1533		case "$_opt" in
1534		e) _re="$OPTARG" ;;
1535		m) _mod="$OPTARG" ;;
1536		*) err 3 'USAGE: load_kld [-e regex] [-m module] file' ;;
1537		esac
1538	done
1539	shift $(($OPTIND - 1))
1540	if [ $# -ne 1 ]; then
1541		err 3 'USAGE: load_kld [-e regex] [-m module] file'
1542	fi
1543	_mod=${_mod:-$1}
1544	_loaded=false
1545	if [ -n "$_re" ]; then
1546		if kldstat -v | egrep -q -e "$_re"; then
1547			_loaded=true
1548		fi
1549	else
1550		if kldstat -q -m "$_mod"; then
1551			_loaded=true
1552		fi
1553	fi
1554	if ! $_loaded; then
1555		if ! kldload "$1"; then
1556			warn "Unable to load kernel module $1"
1557			return 1
1558		else
1559			info "$1 kernel module loaded."
1560		fi
1561	else
1562		debug "load_kld: $1 kernel module already loaded."
1563	fi
1564	return 0
1565}
1566
1567# ltr str src dst
1568#	Change every $src in $str to $dst.
1569#	Useful when /usr is not yet mounted and we cannot use tr(1), sed(1) nor
1570#	awk(1).
1571ltr()
1572{
1573	local _str _src _dst _out _com
1574	_str=$1
1575	_src=$2
1576	_dst=$3
1577	_out=""
1578
1579	IFS=${_src}
1580	for _com in ${_str}; do
1581		if [ -z "${_out}" ]; then
1582			_out="${_com}"
1583		else
1584			_out="${_out}${_dst}${_com}"
1585		fi
1586	done
1587	echo "${_out}"
1588}
1589
1590# Creates a list of providers for GELI encryption.
1591geli_make_list()
1592{
1593	local devices devices2
1594	local provider mountpoint type options rest
1595
1596	# Create list of GELI providers from fstab.
1597	while read provider mountpoint type options rest ; do
1598		case ":${options}" in
1599		:*noauto*)
1600			noauto=yes
1601			;;
1602		*)
1603			noauto=no
1604			;;
1605		esac
1606
1607		case ":${provider}" in
1608		:#*)
1609			continue
1610			;;
1611		*.eli)
1612			# Skip swap devices.
1613			if [ "${type}" = "swap" -o "${options}" = "sw" -o "${noauto}" = "yes" ]; then
1614				continue
1615			fi
1616			devices="${devices} ${provider}"
1617			;;
1618		esac
1619	done < /etc/fstab
1620
1621	# Append providers from geli_devices.
1622	devices="${devices} ${geli_devices}"
1623
1624	for provider in ${devices}; do
1625		provider=${provider%.eli}
1626		provider=${provider#/dev/}
1627		devices2="${devices2} ${provider}"
1628	done
1629
1630	echo ${devices2}
1631}
1632
1633# Find scripts in local_startup directories that use the old syntax
1634#
1635find_local_scripts_old () {
1636	zlist=''
1637	slist=''
1638	for dir in ${local_startup}; do
1639		if [ -d "${dir}" ]; then
1640			for file in ${dir}/[0-9]*.sh; do
1641				grep '^# PROVIDE:' $file >/dev/null 2>&1 &&
1642				    continue
1643				zlist="$zlist $file"
1644			done
1645			for file in ${dir}/[^0-9]*.sh; do
1646				grep '^# PROVIDE:' $file >/dev/null 2>&1 &&
1647				    continue
1648				slist="$slist $file"
1649			done
1650		fi
1651	done
1652}
1653
1654find_local_scripts_new () {
1655	local_rc=''
1656	for dir in ${local_startup}; do
1657		if [ -d "${dir}" ]; then
1658			for file in `grep -l '^# PROVIDE:' ${dir}/* 2>/dev/null`; do
1659				case "$file" in
1660				*.sample) ;;
1661				*)	if [ -x "$file" ]; then
1662						local_rc="${local_rc} ${file}"
1663					fi
1664					;;
1665				esac
1666			done
1667		fi
1668	done
1669}
1670
1671# check_required_{before|after} command
1672#	Check for things required by the command before and after its precmd,
1673#	respectively.  The two separate functions are needed because some
1674#	conditions should prevent precmd from being run while other things
1675#	depend on precmd having already been run.
1676#
1677check_required_before()
1678{
1679	local _f
1680
1681	case "$1" in
1682	start)
1683		for _f in $required_vars; do
1684			if ! checkyesno $_f; then
1685				warn "\$${_f} is not enabled."
1686				if [ -z "$rc_force" ]; then
1687					return 1
1688				fi
1689			fi
1690		done
1691
1692		for _f in $required_dirs; do
1693			if [ ! -d "${_f}/." ]; then
1694				warn "${_f} is not a directory."
1695				if [ -z "$rc_force" ]; then
1696					return 1
1697				fi
1698			fi
1699		done
1700
1701		for _f in $required_files; do
1702			if [ ! -r "${_f}" ]; then
1703				warn "${_f} is not readable."
1704				if [ -z "$rc_force" ]; then
1705					return 1
1706				fi
1707			fi
1708		done
1709		;;
1710	esac
1711
1712	return 0
1713}
1714
1715check_required_after()
1716{
1717	local _f _args
1718
1719	case "$1" in
1720	start)
1721		for _f in $required_modules; do
1722			case "${_f}" in
1723				*~*)	_args="-e ${_f#*~} ${_f%%~*}" ;;
1724				*:*)	_args="-m ${_f#*:} ${_f%%:*}" ;;
1725				*)	_args="${_f}" ;;
1726			esac
1727			if ! load_kld ${_args}; then
1728				if [ -z "$rc_force" ]; then
1729					return 1
1730				fi
1731			fi
1732		done
1733		;;
1734	esac
1735
1736	return 0
1737}
1738
1739fi
1740
1741# _echoonce var msg mode
1742#	mode=0: Echo $msg if ${$var} is empty.
1743#	        After doing echo, a string is set to ${$var}.
1744#
1745#	mode=1: Echo $msg if ${$var} is a string with non-zero length.
1746#
1747_echoonce()
1748{
1749	local _var _msg _mode
1750	_var=`eval echo \\$$1`
1751	_msg=$2
1752	_mode=$3
1753
1754	case $_mode in
1755	1)	[ -n "$_var" ] && echo "$_msg" ;;
1756	*)	[ -z "$_var" ] && echo -n "$_msg" && eval "$1=finished" ;;
1757	esac
1758}
1759
1760_rc_subr_loaded=:
1761