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