rc.subr revision 223227
1# $NetBSD: rc.subr,v 1.67 2006/10/07 11:25:15 elad Exp $
2# $FreeBSD: head/etc/rc.subr 223227 2011-06-18 11:05:30Z jilles $
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	# Set defaults if defined.
1064	for _var in $rcvar $rcvars; do
1065		eval _defval=\$${_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		eval _v=\$$_var
1074		eval _msg=\$${_var}_obsolete_msg
1075		eval _new=\$${_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# check_kern_features mib
1738#	Return existence of kern.features.* sysctl MIB as true or
1739#	false.  The result will be cached in $_rc_cache_kern_features_
1740#	namespace.  "0" means the kern.features.X exists.
1741
1742check_kern_features()
1743{
1744	local _v
1745
1746	[ -n "$1" ] || return 1;
1747	_v=`eval echo "\\$_rc_cache_kern_features_$1"`
1748	[ -n "$_v" ] && return "$_v";
1749
1750	if ${SYSCTL_N} kern.features.$1 > /dev/null 2>&1; then
1751		eval _rc_cache_kern_features_$1=0
1752		return 0
1753	else
1754		eval _rc_cache_kern_features_$1=1
1755		return 1
1756	fi
1757}
1758
1759# _echoonce var msg mode
1760#	mode=0: Echo $msg if ${$var} is empty.
1761#	        After doing echo, a string is set to ${$var}.
1762#
1763#	mode=1: Echo $msg if ${$var} is a string with non-zero length.
1764#
1765_echoonce()
1766{
1767	local _var _msg _mode
1768	eval _var=\$$1
1769	_msg=$2
1770	_mode=$3
1771
1772	case $_mode in
1773	1)	[ -n "$_var" ] && echo "$_msg" ;;
1774	*)	[ -z "$_var" ] && echo -n "$_msg" && eval "$1=finished" ;;
1775	esac
1776}
1777
1778_rc_subr_loaded=:
1779