rc.subr revision 220962
1# $NetBSD: rc.subr,v 1.67 2006/10/07 11:25:15 elad Exp $
2# $FreeBSD: head/etc/rc.subr 220962 2011-04-23 04:26:31Z 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	local string file line
403
404	string="$1" ; file="$2"
405
406	if [ -z "$string" -o -z "$file" ] || [ ! -s "$file" ]; then
407		err 3 'USAGE: get_pidfile_from_conf string file'
408	fi
409
410	while read line; do
411		case "$line" in
412		*[#\;]*${string}*)	continue ;;
413		*${string}*)		break ;;
414		esac
415	done < $file
416
417	if [ -n "$line" ]; then
418		line=${line#*/}
419		_pidfile_from_conf="/${line%%[\"\;]*}"
420	else
421		return 1
422	fi
423}
424
425#
426# check_startmsgs
427#	If rc_quiet is set (usually as a result of using faststart at
428#	boot time) check if rc_startmsgs is enabled.
429#
430check_startmsgs()
431{
432	if [ -n "$rc_quiet" ]; then
433		checkyesno rc_startmsgs
434	else
435		return 0
436	fi
437}
438
439#
440# run_rc_command argument
441#	Search for argument in the list of supported commands, which is:
442#		"start stop restart rcvar status poll ${extra_commands}"
443#	If there's a match, run ${argument}_cmd or the default method
444#	(see below).
445#
446#	If argument has a given prefix, then change the operation as follows:
447#		Prefix	Operation
448#		------	---------
449#		fast	Skip the pid check, and set rc_fast=yes, rc_quiet=yes
450#		force	Set ${rcvar} to YES, and set rc_force=yes
451#		one	Set ${rcvar} to YES
452#		quiet	Don't output some diagnostics, and set rc_quiet=yes
453#
454#	The following globals are used:
455#
456#	Name		Needed	Purpose
457#	----		------	-------
458#	name		y	Name of script.
459#
460#	command		n	Full path to command.
461#				Not needed if ${rc_arg}_cmd is set for
462#				each keyword.
463#
464#	command_args	n	Optional args/shell directives for command.
465#
466#	command_interpreter n	If not empty, command is interpreted, so
467#				call check_{pidfile,process}() appropriately.
468#
469#	desc		n	Description of script.
470#
471#	extra_commands	n	List of extra commands supported.
472#
473#	pidfile		n	If set, use check_pidfile $pidfile $command,
474#				otherwise use check_process $command.
475#				In either case, only check if $command is set.
476#
477#	procname	n	Process name to check for instead of $command.
478#
479#	rcvar		n	This is checked with checkyesno to determine
480#				if the action should be run.
481#
482#	${name}_program	n	Full path to command.
483#				Meant to be used in /etc/rc.conf to override
484#				${command}.
485#
486#	${name}_chroot	n	Directory to chroot to before running ${command}
487#				Requires /usr to be mounted.
488#
489#	${name}_chdir	n	Directory to cd to before running ${command}
490#				(if not using ${name}_chroot).
491#
492#	${name}_flags	n	Arguments to call ${command} with.
493#				NOTE:	$flags from the parent environment
494#					can be used to override this.
495#
496#	${name}_nice	n	Nice level to run ${command} at.
497#
498#	${name}_user	n	User to run ${command} as, using su(1) if not
499#				using ${name}_chroot.
500#				Requires /usr to be mounted.
501#
502#	${name}_group	n	Group to run chrooted ${command} as.
503#				Requires /usr to be mounted.
504#
505#	${name}_groups	n	Comma separated list of supplementary groups
506#				to run the chrooted ${command} with.
507#				Requires /usr to be mounted.
508#
509#	${rc_arg}_cmd	n	If set, use this as the method when invoked;
510#				Otherwise, use default command (see below)
511#
512#	${rc_arg}_precmd n	If set, run just before performing the
513#				${rc_arg}_cmd method in the default
514#				operation (i.e, after checking for required
515#				bits and process (non)existence).
516#				If this completes with a non-zero exit code,
517#				don't run ${rc_arg}_cmd.
518#
519#	${rc_arg}_postcmd n	If set, run just after performing the
520#				${rc_arg}_cmd method, if that method
521#				returned a zero exit code.
522#
523#	required_dirs	n	If set, check for the existence of the given
524#				directories before running a (re)start command.
525#
526#	required_files	n	If set, check for the readability of the given
527#				files before running a (re)start command.
528#
529#	required_modules n	If set, ensure the given kernel modules are
530#				loaded before running a (re)start command.
531#				The check and possible loads are actually
532#				done after start_precmd so that the modules
533#				aren't loaded in vain, should the precmd
534#				return a non-zero status to indicate a error.
535#				If a word in the list looks like "foo:bar",
536#				"foo" is the KLD file name and "bar" is the
537#				module name.  If a word looks like "foo~bar",
538#				"foo" is the KLD file name and "bar" is a
539#				egrep(1) pattern matching the module name.
540#				Otherwise the module name is assumed to be
541#				the same as the KLD file name, which is most
542#				common.  See load_kld().
543#
544#	required_vars	n	If set, perform checkyesno on each of the
545#				listed variables before running the default
546#				(re)start command.
547#
548#	Default behaviour for a given argument, if no override method is
549#	provided:
550#
551#	Argument	Default behaviour
552#	--------	-----------------
553#	start		if !running && checkyesno ${rcvar}
554#				${command}
555#
556#	stop		if ${pidfile}
557#				rc_pid=$(check_pidfile $pidfile $command)
558#			else
559#				rc_pid=$(check_process $command)
560#			kill $sig_stop $rc_pid
561#			wait_for_pids $rc_pid
562#			($sig_stop defaults to TERM.)
563#
564#	reload		Similar to stop, except use $sig_reload instead,
565#			and doesn't wait_for_pids.
566#			$sig_reload defaults to HUP.
567#			Note that `reload' isn't provided by default,
568#			it should be enabled via $extra_commands.
569#
570#	restart		Run `stop' then `start'.
571#
572#	status		Show if ${command} is running, etc.
573#
574#	poll		Wait for ${command} to exit.
575#
576#	rcvar		Display what rc.conf variable is used (if any).
577#
578#	Variables available to methods, and after run_rc_command() has
579#	completed:
580#
581#	Variable	Purpose
582#	--------	-------
583#	rc_arg		Argument to command, after fast/force/one processing
584#			performed
585#
586#	rc_flags	Flags to start the default command with.
587#			Defaults to ${name}_flags, unless overridden
588#			by $flags from the environment.
589#			This variable may be changed by the precmd method.
590#
591#	rc_pid		PID of command (if appropriate)
592#
593#	rc_fast		Not empty if "fast" was provided (q.v.)
594#
595#	rc_force	Not empty if "force" was provided (q.v.)
596#
597#	rc_quiet	Not empty if "quiet" was provided
598#
599#
600run_rc_command()
601{
602	_return=0
603	rc_arg=$1
604	if [ -z "$name" ]; then
605		err 3 'run_rc_command: $name is not set.'
606	fi
607
608	# Don't repeat the first argument when passing additional command-
609	# line arguments to the command subroutines.
610	#
611	shift 1
612	rc_extra_args="$*"
613
614	_rc_prefix=
615	case "$rc_arg" in
616	fast*)				# "fast" prefix; don't check pid
617		rc_arg=${rc_arg#fast}
618		rc_fast=yes
619		rc_quiet=yes
620		;;
621	force*)				# "force" prefix; always run
622		rc_force=yes
623		_rc_prefix=force
624		rc_arg=${rc_arg#${_rc_prefix}}
625		if [ -n "${rcvar}" ]; then
626			eval ${rcvar}=YES
627		fi
628		;;
629	one*)				# "one" prefix; set ${rcvar}=yes
630		_rc_prefix=one
631		rc_arg=${rc_arg#${_rc_prefix}}
632		if [ -n "${rcvar}" ]; then
633			eval ${rcvar}=YES
634		fi
635		;;
636	quiet*)				# "quiet" prefix; omit some messages
637		_rc_prefix=quiet
638		rc_arg=${rc_arg#${_rc_prefix}}
639		rc_quiet=yes
640		;;
641	esac
642
643	eval _override_command=\$${name}_program
644	command=${_override_command:-$command}
645
646	_keywords="start stop restart rcvar $extra_commands"
647	rc_pid=
648	_pidcmd=
649	_procname=${procname:-${command}}
650
651					# setup pid check command
652	if [ -n "$_procname" ]; then
653		if [ -n "$pidfile" ]; then
654			_pidcmd='rc_pid=$(check_pidfile '"$pidfile $_procname $command_interpreter"')'
655		else
656			_pidcmd='rc_pid=$(check_process '"$_procname $command_interpreter"')'
657		fi
658		if [ -n "$_pidcmd" ]; then
659			_keywords="${_keywords} status poll"
660		fi
661	fi
662
663	if [ -z "$rc_arg" ]; then
664		rc_usage $_keywords
665	fi
666
667	if [ -n "$flags" ]; then	# allow override from environment
668		rc_flags=$flags
669	else
670		eval rc_flags=\$${name}_flags
671	fi
672	eval _chdir=\$${name}_chdir	_chroot=\$${name}_chroot \
673	    _nice=\$${name}_nice	_user=\$${name}_user \
674	    _group=\$${name}_group	_groups=\$${name}_groups
675
676	if [ -n "$_user" ]; then	# unset $_user if running as that user
677		if [ "$_user" = "$(eval $IDCMD)" ]; then
678			unset _user
679		fi
680	fi
681
682	eval $_pidcmd			# determine the pid if necessary
683
684	for _elem in $_keywords; do
685		if [ "$_elem" != "$rc_arg" ]; then
686			continue
687		fi
688					# if ${rcvar} is set, $1 is not "rcvar"
689					# and ${rc_pid} is not set, then run
690					#	checkyesno ${rcvar}
691					# and return if that failed
692					#
693		if [ -n "${rcvar}" -a "$rc_arg" != "rcvar" -a "$rc_arg" != "stop" ] ||
694		    [ -n "${rcvar}" -a "$rc_arg" = "stop" -a -z "${rc_pid}" ]; then
695			if ! checkyesno ${rcvar}; then
696				if [ -n "${rc_quiet}" ]; then
697					return 0
698				fi
699				echo -n "Cannot '${rc_arg}' $name. Set ${rcvar} to "
700				echo -n "YES in /etc/rc.conf or use 'one${rc_arg}' "
701				echo "instead of '${rc_arg}'."
702				return 0
703			fi
704		fi
705
706					# if there's a custom ${XXX_cmd},
707					# run that instead of the default
708					#
709		eval _cmd=\$${rc_arg}_cmd \
710		     _precmd=\$${rc_arg}_precmd \
711		     _postcmd=\$${rc_arg}_postcmd
712
713		if [ -n "$_cmd" ]; then
714			_run_rc_precmd || return 1
715			_run_rc_doit "$_cmd $rc_extra_args" || return 1
716			_run_rc_postcmd
717			return $_return
718		fi
719
720		case "$rc_arg" in	# default operations...
721
722		status)
723			_run_rc_precmd || return 1
724			if [ -n "$rc_pid" ]; then
725				echo "${name} is running as pid $rc_pid."
726			else
727				echo "${name} is not running."
728				return 1
729			fi
730			_run_rc_postcmd
731			;;
732
733		start)
734			if [ -z "$rc_fast" -a -n "$rc_pid" ]; then
735				echo 1>&2 "${name} already running? (pid=$rc_pid)."
736				return 1
737			fi
738
739			if [ ! -x ${_chroot}${_chroot:+"/"}${command} ]; then
740				warn "run_rc_command: cannot run $command"
741				return 1
742			fi
743
744			if ! _run_rc_precmd; then
745				warn "failed precmd routine for ${name}"
746				return 1
747			fi
748
749					# setup the full command to run
750					#
751			check_startmsgs && echo "Starting ${name}."
752			if [ -n "$_chroot" ]; then
753				_doit="\
754${_nice:+nice -n $_nice }\
755chroot ${_user:+-u $_user }${_group:+-g $_group }${_groups:+-G $_groups }\
756$_chroot $command $rc_flags $command_args"
757			else
758				_doit="\
759${_chdir:+cd $_chdir && }\
760$command $rc_flags $command_args"
761				if [ -n "$_user" ]; then
762				    _doit="su -m $_user -c 'sh -c \"$_doit\"'"
763				fi
764				if [ -n "$_nice" ]; then
765					if [ -z "$_user" ]; then
766						_doit="sh -c \"$_doit\""
767					fi
768					_doit="nice -n $_nice $_doit"
769				fi
770			fi
771
772					# run the full command
773					#
774			if ! _run_rc_doit "$_doit"; then
775				warn "failed to start ${name}"
776				return 1
777			fi
778
779					# finally, run postcmd
780					#
781			_run_rc_postcmd
782			;;
783
784		stop)
785			if [ -z "$rc_pid" ]; then
786				[ -n "$rc_fast" ] && return 0
787				_run_rc_notrunning
788				return 1
789			fi
790
791			_run_rc_precmd || return 1
792
793					# send the signal to stop
794					#
795			echo "Stopping ${name}."
796			_doit=$(_run_rc_killcmd "${sig_stop:-TERM}")
797			_run_rc_doit "$_doit" || return 1
798
799					# wait for the command to exit,
800					# and run postcmd.
801			wait_for_pids $rc_pid
802
803			_run_rc_postcmd
804			;;
805
806		reload)
807			if [ -z "$rc_pid" ]; then
808				_run_rc_notrunning
809				return 1
810			fi
811
812			_run_rc_precmd || return 1
813
814			_doit=$(_run_rc_killcmd "${sig_reload:-HUP}")
815			_run_rc_doit "$_doit" || return 1
816
817			_run_rc_postcmd
818			;;
819
820		restart)
821					# prevent restart being called more
822					# than once by any given script
823					#
824			if ${_rc_restart_done:-false}; then
825				return 0
826			fi
827			_rc_restart_done=true
828
829			_run_rc_precmd || return 1
830
831			# run those in a subshell to keep global variables
832			( run_rc_command ${_rc_prefix}stop $rc_extra_args )
833			( run_rc_command ${_rc_prefix}start $rc_extra_args )
834			_return=$?
835			[ $_return -ne 0 ] && [ -z "$rc_force" ] && return 1
836
837			_run_rc_postcmd
838			;;
839
840		poll)
841			_run_rc_precmd || return 1
842			if [ -n "$rc_pid" ]; then
843				wait_for_pids $rc_pid
844			fi
845			_run_rc_postcmd
846			;;
847
848		rcvar)
849			echo -n "# $name"
850			if [ -n "$desc" ]; then
851				echo " : $desc"
852			else
853				echo ""
854			fi
855			echo "#"
856			# Get unique vars in $rcvar $rcvars
857			for _v in $rcvar $rcvars; do
858				case $v in
859				$_v\ *|\ *$_v|*\ $_v\ *) ;;
860				*)	v="${v# } $_v" ;;
861				esac
862			done
863
864			# Display variables.
865			for _v in $v; do
866				if [ -z "$_v" ]; then
867					continue
868				fi
869
870				eval _desc=\$${_v}_desc
871				eval _defval=\$${_v}_defval
872				_h="-"
873
874				eval echo \"$_v=\\\"\$$_v\\\"\"
875				# decode multiple lines of _desc
876				while [ -n "$_desc" ]; do
877					case $_desc in
878					*^^*)
879						echo "# $_h ${_desc%%^^*}"
880						_desc=${_desc#*^^}
881						_h=" "
882						;;
883					*)
884						echo "# $_h ${_desc}"
885						break
886						;;
887					esac
888				done
889				echo "#   (default: \"$_defval\")"
890			done
891			echo ""
892			;;
893
894		*)
895			rc_usage $_keywords
896			;;
897
898		esac
899		return $_return
900	done
901
902	echo 1>&2 "$0: unknown directive '$rc_arg'."
903	rc_usage $_keywords
904	# not reached
905}
906
907#
908# Helper functions for run_rc_command: common code.
909# They use such global variables besides the exported rc_* ones:
910#
911#	name	       R/W
912#	------------------
913#	_precmd		R
914#	_postcmd	R
915#	_return		W
916#
917_run_rc_precmd()
918{
919	check_required_before "$rc_arg" || return 1
920
921	if [ -n "$_precmd" ]; then
922		debug "run_rc_command: ${rc_arg}_precmd: $_precmd $rc_extra_args"
923		eval "$_precmd $rc_extra_args"
924		_return=$?
925
926		# If precmd failed and force isn't set, request exit.
927		if [ $_return -ne 0 ] && [ -z "$rc_force" ]; then
928			return 1
929		fi
930	fi
931
932	check_required_after "$rc_arg" || return 1
933
934	return 0
935}
936
937_run_rc_postcmd()
938{
939	if [ -n "$_postcmd" ]; then
940		debug "run_rc_command: ${rc_arg}_postcmd: $_postcmd $rc_extra_args"
941		eval "$_postcmd $rc_extra_args"
942		_return=$?
943	fi
944	return 0
945}
946
947_run_rc_doit()
948{
949	debug "run_rc_command: doit: $*"
950	eval "$@"
951	_return=$?
952
953	# If command failed and force isn't set, request exit.
954	if [ $_return -ne 0 ] && [ -z "$rc_force" ]; then
955		return 1
956	fi
957
958	return 0
959}
960
961_run_rc_notrunning()
962{
963	local _pidmsg
964
965	if [ -n "$pidfile" ]; then
966		_pidmsg=" (check $pidfile)."
967	else
968		_pidmsg=
969	fi
970	echo 1>&2 "${name} not running?${_pidmsg}"
971}
972
973_run_rc_killcmd()
974{
975	local _cmd
976
977	_cmd="kill -$1 $rc_pid"
978	if [ -n "$_user" ]; then
979		_cmd="su -m ${_user} -c 'sh -c \"${_cmd}\"'"
980	fi
981	echo "$_cmd"
982}
983
984#
985# run_rc_script file arg
986#	Start the script `file' with `arg', and correctly handle the
987#	return value from the script.
988#	If `file' ends with `.sh', it's sourced into the current environment
989#	when $rc_fast_and_loose is set, otherwise it is run as a child process.
990#	If `file' appears to be a backup or scratch file, ignore it.
991#	Otherwise if it is executable run as a child process.
992#
993run_rc_script()
994{
995	_file=$1
996	_arg=$2
997	if [ -z "$_file" -o -z "$_arg" ]; then
998		err 3 'USAGE: run_rc_script file arg'
999	fi
1000
1001	unset	name command command_args command_interpreter \
1002		extra_commands pidfile procname \
1003		rcvar rcvars rcvars_obsolete required_dirs required_files \
1004		required_vars
1005	eval unset ${_arg}_cmd ${_arg}_precmd ${_arg}_postcmd
1006
1007	case "$_file" in
1008	/etc/rc.d/*.sh)			# no longer allowed in the base
1009		warn "Ignoring old-style startup script $_file"
1010		;;
1011	*[~#]|*.OLD|*.bak|*.orig|*,v)	# scratch file; skip
1012		warn "Ignoring scratch file $_file"
1013		;;
1014	*)				# run in subshell
1015		if [ -x $_file ]; then
1016			if [ -n "$rc_fast_and_loose" ]; then
1017				set $_arg; . $_file
1018			else
1019				( trap "echo Script $_file interrupted; kill -QUIT $$" 3
1020				  trap "echo Script $_file interrupted; exit 1" 2
1021				  trap "echo Script $_file running" 29
1022				  set $_arg; . $_file )
1023			fi
1024		fi
1025		;;
1026	esac
1027}
1028
1029#
1030# load_rc_config name
1031#	Source in the configuration file for a given name.
1032#
1033load_rc_config()
1034{
1035	local _name _var _defval _v _msg _new
1036	_name=$1
1037	if [ -z "$_name" ]; then
1038		err 3 'USAGE: load_rc_config name'
1039	fi
1040
1041	if ${_rc_conf_loaded:-false}; then
1042		:
1043	else
1044		if [ -r /etc/defaults/rc.conf ]; then
1045			debug "Sourcing /etc/defaults/rc.conf"
1046			. /etc/defaults/rc.conf
1047			source_rc_confs
1048		elif [ -r /etc/rc.conf ]; then
1049			debug "Sourcing /etc/rc.conf (/etc/defaults/rc.conf doesn't exist)."
1050			. /etc/rc.conf
1051		fi
1052		_rc_conf_loaded=true
1053	fi
1054	if [ -f /etc/rc.conf.d/"$_name" ]; then
1055		debug "Sourcing /etc/rc.conf.d/${_name}"
1056		. /etc/rc.conf.d/"$_name"
1057	fi
1058
1059	# Old variable name support -- Remove before 9.0-RELEASE
1060	#
1061	[ -n "$enable_quotas" ] && err 1 "enable_quotas is deprecated, use quota_enable"
1062
1063	# Set defaults if defined.
1064	for _var in $rcvar $rcvars; do
1065		_defval=`eval echo "\\\$${_var}_defval"`
1066		if [ -n "$_defval" ]; then
1067			eval : \${$_var:=\$${_var}_defval}
1068		fi
1069	done
1070
1071	# check obsolete rc.conf variables
1072	for _var in $rcvars_obsolete; do
1073		_v=`eval echo \\$$_var`
1074		_msg=`eval echo \\$${_var}_obsolete_msg`
1075		_new=`eval echo \\$${_var}_newvar`
1076		case $_v in
1077		"")
1078			;;
1079		*)
1080			if [ -z "$_new" ]; then
1081				_msg="Ignored."
1082			else
1083				eval $_new=\"\$$_var\"
1084				if [ -z "$_msg" ]; then
1085					_msg="Use \$$_new instead."
1086				fi
1087			fi
1088			warn "\$$_var is obsolete.  $_msg"
1089			;;
1090		esac
1091	done
1092}
1093
1094#
1095# load_rc_config_var name var
1096#	Read the rc.conf(5) var for name and set in the
1097#	current shell, using load_rc_config in a subshell to prevent
1098#	unwanted side effects from other variable assignments.
1099#
1100load_rc_config_var()
1101{
1102	if [ $# -ne 2 ]; then
1103		err 3 'USAGE: load_rc_config_var name var'
1104	fi
1105	eval $(eval '(
1106		load_rc_config '$1' >/dev/null;
1107                if [ -n "${'$2'}" -o "${'$2'-UNSET}" != "UNSET" ]; then
1108			echo '$2'=\'\''${'$2'}\'\'';
1109		fi
1110	)' )
1111}
1112
1113#
1114# rc_usage commands
1115#	Print a usage string for $0, with `commands' being a list of
1116#	valid commands.
1117#
1118rc_usage()
1119{
1120	echo -n 1>&2 "Usage: $0 [fast|force|one]("
1121
1122	_sep=
1123	for _elem; do
1124		echo -n 1>&2 "$_sep$_elem"
1125		_sep="|"
1126	done
1127	echo 1>&2 ")"
1128	exit 1
1129}
1130
1131#
1132# err exitval message
1133#	Display message to stderr and log to the syslog, and exit with exitval.
1134#
1135err()
1136{
1137	exitval=$1
1138	shift
1139
1140	if [ -x /usr/bin/logger ]; then
1141		logger "$0: ERROR: $*"
1142	fi
1143	echo 1>&2 "$0: ERROR: $*"
1144	exit $exitval
1145}
1146
1147#
1148# warn message
1149#	Display message to stderr and log to the syslog.
1150#
1151warn()
1152{
1153	if [ -x /usr/bin/logger ]; then
1154		logger "$0: WARNING: $*"
1155	fi
1156	echo 1>&2 "$0: WARNING: $*"
1157}
1158
1159#
1160# info message
1161#	Display informational message to stdout and log to syslog.
1162#
1163info()
1164{
1165	case ${rc_info} in
1166	[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
1167		if [ -x /usr/bin/logger ]; then
1168			logger "$0: INFO: $*"
1169		fi
1170		echo "$0: INFO: $*"
1171		;;
1172	esac
1173}
1174
1175#
1176# debug message
1177#	If debugging is enabled in rc.conf output message to stderr.
1178#	BEWARE that you don't call any subroutine that itself calls this
1179#	function.
1180#
1181debug()
1182{
1183	case ${rc_debug} in
1184	[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
1185		if [ -x /usr/bin/logger ]; then
1186			logger "$0: DEBUG: $*"
1187		fi
1188		echo 1>&2 "$0: DEBUG: $*"
1189		;;
1190	esac
1191}
1192
1193#
1194# backup_file action file cur backup
1195#	Make a backup copy of `file' into `cur', and save the previous
1196#	version of `cur' as `backup' or use rcs for archiving.
1197#
1198#	This routine checks the value of the backup_uses_rcs variable,
1199#	which can be either YES or NO.
1200#
1201#	The `action' keyword can be one of the following:
1202#
1203#	add		`file' is now being backed up (and is possibly
1204#			being reentered into the backups system).  `cur'
1205#			is created and RCS files, if necessary, are
1206#			created as well.
1207#
1208#	update		`file' has changed and needs to be backed up.
1209#			If `cur' exists, it is copied to to `back' or
1210#			checked into RCS (if the repository file is old),
1211#			and then `file' is copied to `cur'.  Another RCS
1212#			check in done here if RCS is being used.
1213#
1214#	remove		`file' is no longer being tracked by the backups
1215#			system.  If RCS is not being used, `cur' is moved
1216#			to `back', otherwise an empty file is checked in,
1217#			and then `cur' is removed.
1218#
1219#
1220backup_file()
1221{
1222	_action=$1
1223	_file=$2
1224	_cur=$3
1225	_back=$4
1226
1227	if checkyesno backup_uses_rcs; then
1228		_msg0="backup archive"
1229		_msg1="update"
1230
1231		# ensure that history file is not locked
1232		if [ -f $_cur,v ]; then
1233			rcs -q -u -U -M $_cur
1234		fi
1235
1236		# ensure after switching to rcs that the
1237		# current backup is not lost
1238		if [ -f $_cur ]; then
1239			# no archive, or current newer than archive
1240			if [ ! -f $_cur,v -o $_cur -nt $_cur,v ]; then
1241				ci -q -f -u -t-"$_msg0" -m"$_msg1" $_cur
1242				rcs -q -kb -U $_cur
1243				co -q -f -u $_cur
1244			fi
1245		fi
1246
1247		case $_action in
1248		add|update)
1249			cp -p $_file $_cur
1250			ci -q -f -u -t-"$_msg0" -m"$_msg1" $_cur
1251			rcs -q -kb -U $_cur
1252			co -q -f -u $_cur
1253			chown root:wheel $_cur $_cur,v
1254			;;
1255		remove)
1256			cp /dev/null $_cur
1257			ci -q -f -u -t-"$_msg0" -m"$_msg1" $_cur
1258			rcs -q -kb -U $_cur
1259			chown root:wheel $_cur $_cur,v
1260			rm $_cur
1261			;;
1262		esac
1263	else
1264		case $_action in
1265		add|update)
1266			if [ -f $_cur ]; then
1267				cp -p $_cur $_back
1268			fi
1269			cp -p $_file $_cur
1270			chown root:wheel $_cur
1271			;;
1272		remove)
1273			mv -f $_cur $_back
1274			;;
1275		esac
1276	fi
1277}
1278
1279# make_symlink src link
1280#	Make a symbolic link 'link' to src from basedir. If the
1281#	directory in which link is to be created does not exist
1282#	a warning will be displayed and an error will be returned.
1283#	Returns 0 on sucess, 1 otherwise.
1284#
1285make_symlink()
1286{
1287	local src link linkdir _me
1288	src="$1"
1289	link="$2"
1290	linkdir="`dirname $link`"
1291	_me="make_symlink()"
1292
1293	if [ -z "$src" -o -z "$link" ]; then
1294		warn "$_me: requires two arguments."
1295		return 1
1296	fi
1297	if [ ! -d "$linkdir" ]; then
1298		warn "$_me: the directory $linkdir does not exist."
1299		return 1
1300	fi
1301	if ! ln -sf $src $link; then
1302		warn "$_me: unable to make a symbolic link from $link to $src"
1303		return 1
1304	fi
1305	return 0
1306}
1307
1308# devfs_rulesets_from_file file
1309#	Reads a set of devfs commands from file, and creates
1310#	the specified rulesets with their rules. Returns non-zero
1311#	if there was an error.
1312#
1313devfs_rulesets_from_file()
1314{
1315	local file _err _me
1316	file="$1"
1317	_me="devfs_rulesets_from_file"
1318	_err=0
1319
1320	if [ -z "$file" ]; then
1321		warn "$_me: you must specify a file"
1322		return 1
1323	fi
1324	if [ ! -e "$file" ]; then
1325		debug "$_me: no such file ($file)"
1326		return 0
1327	fi
1328	debug "reading rulesets from file ($file)"
1329	{ while read line
1330	do
1331		case $line in
1332		\#*)
1333			continue
1334			;;
1335		\[*\]*)
1336			rulenum=`expr "$line" : "\[.*=\([0-9]*\)\]"`
1337			if [ -z "$rulenum" ]; then
1338				warn "$_me: cannot extract rule number ($line)"
1339				_err=1
1340				break
1341			fi
1342			rulename=`expr "$line" : "\[\(.*\)=[0-9]*\]"`
1343			if [ -z "$rulename" ]; then
1344				warn "$_me: cannot extract rule name ($line)"
1345				_err=1
1346				break;
1347			fi
1348			eval $rulename=\$rulenum
1349			debug "found ruleset: $rulename=$rulenum"
1350			if ! /sbin/devfs rule -s $rulenum delset; then
1351				_err=1
1352				break
1353			fi
1354			;;
1355		*)
1356			rulecmd="${line%%"\#*"}"
1357			# evaluate the command incase it includes
1358			# other rules
1359			if [ -n "$rulecmd" ]; then
1360				debug "adding rule ($rulecmd)"
1361				if ! eval /sbin/devfs rule -s $rulenum $rulecmd
1362				then
1363					_err=1
1364					break
1365				fi
1366			fi
1367			;;
1368		esac
1369		if [ $_err -ne 0 ]; then
1370			debug "error in $_me"
1371			break
1372		fi
1373	done } < $file
1374	return $_err
1375}
1376
1377# devfs_init_rulesets
1378#	Initializes rulesets from configuration files. Returns
1379#	non-zero if there was an error.
1380#
1381devfs_init_rulesets()
1382{
1383	local file _me
1384	_me="devfs_init_rulesets"
1385
1386	# Go through this only once
1387	if [ -n "$devfs_rulesets_init" ]; then
1388		debug "$_me: devfs rulesets already initialized"
1389		return
1390	fi
1391	for file in $devfs_rulesets; do
1392		if ! devfs_rulesets_from_file $file; then
1393			warn "$_me: could not read rules from $file"
1394			return 1
1395		fi
1396	done
1397	devfs_rulesets_init=1
1398	debug "$_me: devfs rulesets initialized"
1399	return 0
1400}
1401
1402# devfs_set_ruleset ruleset [dir]
1403#	Sets the default ruleset of dir to ruleset. The ruleset argument
1404#	must be a ruleset name as specified in devfs.rules(5) file.
1405#	Returns non-zero if it could not set it successfully.
1406#
1407devfs_set_ruleset()
1408{
1409	local devdir rs _me
1410	[ -n "$1" ] && eval rs=\$$1 || rs=
1411	[ -n "$2" ] && devdir="-m "$2"" || devdir=
1412	_me="devfs_set_ruleset"
1413
1414	if [ -z "$rs" ]; then
1415		warn "$_me: you must specify a ruleset number"
1416		return 1
1417	fi
1418	debug "$_me: setting ruleset ($rs) on mount-point (${devdir#-m })"
1419	if ! /sbin/devfs $devdir ruleset $rs; then
1420		warn "$_me: unable to set ruleset $rs to ${devdir#-m }"
1421		return 1
1422	fi
1423	return 0
1424}
1425
1426# devfs_apply_ruleset ruleset [dir]
1427#	Apply ruleset number $ruleset to the devfs mountpoint $dir.
1428#	The ruleset argument must be a ruleset name as specified
1429#	in a devfs.rules(5) file.  Returns 0 on success or non-zero
1430#	if it could not apply the ruleset.
1431#
1432devfs_apply_ruleset()
1433{
1434	local devdir rs _me
1435	[ -n "$1" ] && eval rs=\$$1 || rs=
1436	[ -n "$2" ] && devdir="-m "$2"" || devdir=
1437	_me="devfs_apply_ruleset"
1438
1439	if [ -z "$rs" ]; then
1440		warn "$_me: you must specify a ruleset"
1441		return 1
1442	fi
1443	debug "$_me: applying ruleset ($rs) to mount-point (${devdir#-m })"
1444	if ! /sbin/devfs $devdir rule -s $rs applyset; then
1445		warn "$_me: unable to apply ruleset $rs to ${devdir#-m }"
1446		return 1
1447	fi
1448	return 0
1449}
1450
1451# devfs_domount dir [ruleset]
1452#	Mount devfs on dir. If ruleset is specified it is set
1453#	on the mount-point. It must also be a ruleset name as specified
1454#	in a devfs.rules(5) file. Returns 0 on success.
1455#
1456devfs_domount()
1457{
1458	local devdir rs _me
1459	devdir="$1"
1460	[ -n "$2" ] && rs=$2 || rs=
1461	_me="devfs_domount()"
1462
1463	if [ -z "$devdir" ]; then
1464		warn "$_me: you must specify a mount-point"
1465		return 1
1466	fi
1467	debug "$_me: mount-point is ($devdir), ruleset is ($rs)"
1468	if ! mount -t devfs dev "$devdir"; then
1469		warn "$_me: Unable to mount devfs on $devdir"
1470		return 1
1471	fi
1472	if [ -n "$rs" ]; then
1473		devfs_init_rulesets
1474		devfs_set_ruleset $rs $devdir
1475		devfs -m $devdir rule applyset
1476	fi
1477	return 0
1478}
1479
1480# devfs_mount_jail dir [ruleset]
1481#	Mounts a devfs file system appropriate for jails
1482#	on the directory dir. If ruleset is specified, the ruleset
1483#	it names will be used instead.  If present, ruleset must
1484#	be the name of a ruleset as defined in a devfs.rules(5) file.
1485#	This function returns non-zero if an error occurs.
1486#
1487devfs_mount_jail()
1488{
1489	local jdev rs _me
1490	jdev="$1"
1491	[ -n "$2" ] && rs=$2 || rs="devfsrules_jail"
1492	_me="devfs_mount_jail"
1493
1494	devfs_init_rulesets
1495	if ! devfs_domount "$jdev" $rs; then
1496		warn "$_me: devfs was not mounted on $jdev"
1497		return 1
1498	fi
1499	return 0
1500}
1501
1502# Provide a function for normalizing the mounting of memory
1503# filesystems.  This should allow the rest of the code here to remain
1504# as close as possible between 5-current and 4-stable.
1505#   $1 = size
1506#   $2 = mount point
1507#   $3 = (optional) extra mdmfs flags
1508mount_md()
1509{
1510	if [ -n "$3" ]; then
1511		flags="$3"
1512	fi
1513	/sbin/mdmfs $flags -s $1 md $2
1514}
1515
1516# Code common to scripts that need to load a kernel module
1517# if it isn't in the kernel yet. Syntax:
1518#   load_kld [-e regex] [-m module] file
1519# where -e or -m chooses the way to check if the module
1520# is already loaded:
1521#   regex is egrep'd in the output from `kldstat -v',
1522#   module is passed to `kldstat -m'.
1523# The default way is as though `-m file' were specified.
1524load_kld()
1525{
1526	local _loaded _mod _opt _re
1527
1528	while getopts "e:m:" _opt; do
1529		case "$_opt" in
1530		e) _re="$OPTARG" ;;
1531		m) _mod="$OPTARG" ;;
1532		*) err 3 'USAGE: load_kld [-e regex] [-m module] file' ;;
1533		esac
1534	done
1535	shift $(($OPTIND - 1))
1536	if [ $# -ne 1 ]; then
1537		err 3 'USAGE: load_kld [-e regex] [-m module] file'
1538	fi
1539	_mod=${_mod:-$1}
1540	_loaded=false
1541	if [ -n "$_re" ]; then
1542		if kldstat -v | egrep -q -e "$_re"; then
1543			_loaded=true
1544		fi
1545	else
1546		if kldstat -q -m "$_mod"; then
1547			_loaded=true
1548		fi
1549	fi
1550	if ! $_loaded; then
1551		if ! kldload "$1"; then
1552			warn "Unable to load kernel module $1"
1553			return 1
1554		else
1555			info "$1 kernel module loaded."
1556		fi
1557	else
1558		debug "load_kld: $1 kernel module already loaded."
1559	fi
1560	return 0
1561}
1562
1563# ltr str src dst
1564#	Change every $src in $str to $dst.
1565#	Useful when /usr is not yet mounted and we cannot use tr(1), sed(1) nor
1566#	awk(1).
1567ltr()
1568{
1569	local _str _src _dst _out _com
1570	_str=$1
1571	_src=$2
1572	_dst=$3
1573	_out=""
1574
1575	IFS=${_src}
1576	for _com in ${_str}; do
1577		if [ -z "${_out}" ]; then
1578			_out="${_com}"
1579		else
1580			_out="${_out}${_dst}${_com}"
1581		fi
1582	done
1583	echo "${_out}"
1584}
1585
1586# Creates a list of providers for GELI encryption.
1587geli_make_list()
1588{
1589	local devices devices2
1590	local provider mountpoint type options rest
1591
1592	# Create list of GELI providers from fstab.
1593	while read provider mountpoint type options rest ; do
1594		case ":${options}" in
1595		:*noauto*)
1596			noauto=yes
1597			;;
1598		*)
1599			noauto=no
1600			;;
1601		esac
1602
1603		case ":${provider}" in
1604		:#*)
1605			continue
1606			;;
1607		*.eli)
1608			# Skip swap devices.
1609			if [ "${type}" = "swap" -o "${options}" = "sw" -o "${noauto}" = "yes" ]; then
1610				continue
1611			fi
1612			devices="${devices} ${provider}"
1613			;;
1614		esac
1615	done < /etc/fstab
1616
1617	# Append providers from geli_devices.
1618	devices="${devices} ${geli_devices}"
1619
1620	for provider in ${devices}; do
1621		provider=${provider%.eli}
1622		provider=${provider#/dev/}
1623		devices2="${devices2} ${provider}"
1624	done
1625
1626	echo ${devices2}
1627}
1628
1629# Find scripts in local_startup directories that use the old syntax
1630#
1631find_local_scripts_old () {
1632	zlist=''
1633	slist=''
1634	for dir in ${local_startup}; do
1635		if [ -d "${dir}" ]; then
1636			for file in ${dir}/[0-9]*.sh; do
1637				grep '^# PROVIDE:' $file >/dev/null 2>&1 &&
1638				    continue
1639				zlist="$zlist $file"
1640			done
1641			for file in ${dir}/[^0-9]*.sh; do
1642				grep '^# PROVIDE:' $file >/dev/null 2>&1 &&
1643				    continue
1644				slist="$slist $file"
1645			done
1646		fi
1647	done
1648}
1649
1650find_local_scripts_new () {
1651	local_rc=''
1652	for dir in ${local_startup}; do
1653		if [ -d "${dir}" ]; then
1654			for file in `grep -l '^# PROVIDE:' ${dir}/* 2>/dev/null`; do
1655				case "$file" in
1656				*.sample) ;;
1657				*)	if [ -x "$file" ]; then
1658						local_rc="${local_rc} ${file}"
1659					fi
1660					;;
1661				esac
1662			done
1663		fi
1664	done
1665}
1666
1667# check_required_{before|after} command
1668#	Check for things required by the command before and after its precmd,
1669#	respectively.  The two separate functions are needed because some
1670#	conditions should prevent precmd from being run while other things
1671#	depend on precmd having already been run.
1672#
1673check_required_before()
1674{
1675	local _f
1676
1677	case "$1" in
1678	start)
1679		for _f in $required_vars; do
1680			if ! checkyesno $_f; then
1681				warn "\$${_f} is not enabled."
1682				if [ -z "$rc_force" ]; then
1683					return 1
1684				fi
1685			fi
1686		done
1687
1688		for _f in $required_dirs; do
1689			if [ ! -d "${_f}/." ]; then
1690				warn "${_f} is not a directory."
1691				if [ -z "$rc_force" ]; then
1692					return 1
1693				fi
1694			fi
1695		done
1696
1697		for _f in $required_files; do
1698			if [ ! -r "${_f}" ]; then
1699				warn "${_f} is not readable."
1700				if [ -z "$rc_force" ]; then
1701					return 1
1702				fi
1703			fi
1704		done
1705		;;
1706	esac
1707
1708	return 0
1709}
1710
1711check_required_after()
1712{
1713	local _f _args
1714
1715	case "$1" in
1716	start)
1717		for _f in $required_modules; do
1718			case "${_f}" in
1719				*~*)	_args="-e ${_f#*~} ${_f%%~*}" ;;
1720				*:*)	_args="-m ${_f#*:} ${_f%%:*}" ;;
1721				*)	_args="${_f}" ;;
1722			esac
1723			if ! load_kld ${_args}; then
1724				if [ -z "$rc_force" ]; then
1725					return 1
1726				fi
1727			fi
1728		done
1729		;;
1730	esac
1731
1732	return 0
1733}
1734
1735fi
1736
1737# _echoonce var msg mode
1738#	mode=0: Echo $msg if ${$var} is empty.
1739#	        After doing echo, a string is set to ${$var}.
1740#
1741#	mode=1: Echo $msg if ${$var} is a string with non-zero length.
1742#
1743_echoonce()
1744{
1745	local _var _msg _mode
1746	_var=`eval echo \\$$1`
1747	_msg=$2
1748	_mode=$3
1749
1750	case $_mode in
1751	1)	[ -n "$_var" ] && echo "$_msg" ;;
1752	*)	[ -z "$_var" ] && echo -n "$_msg" && eval "$1=finished" ;;
1753	esac
1754}
1755
1756_rc_subr_loaded=:
1757