xref: /freebsd/libexec/rc/rc.subr (revision 22cf89c938886d14f5796fc49f9f020c23ea8eaf)
1# $NetBSD: rc.subr,v 1.67 2006/10/07 11:25:15 elad Exp $
2#
3# Copyright (c) 1997-2004 The NetBSD Foundation, Inc.
4# All rights reserved.
5#
6# This code is derived from software contributed to The NetBSD Foundation
7# by Luke Mewburn.
8#
9# Redistribution and use in source and binary forms, with or without
10# modification, are permitted provided that the following conditions
11# are met:
12# 1. Redistributions of source code must retain the above copyright
13#    notice, this list of conditions and the following disclaimer.
14# 2. Redistributions in binary form must reproduce the above copyright
15#    notice, this list of conditions and the following disclaimer in the
16#    documentation and/or other materials provided with the distribution.
17#
18# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
19# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
20# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
22# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28# POSSIBILITY OF SUCH DAMAGE.
29#
30# rc.subr
31#	functions used by various rc scripts
32#
33
34: ${RC_PID:=$$}; export RC_PID
35
36#
37#	Operating System dependent/independent variables
38#
39
40if [ -n "${_rc_subr_loaded}" ]; then
41	return
42fi
43
44_rc_subr_loaded="YES"
45
46SYSCTL="/sbin/sysctl"
47SYSCTL_N="${SYSCTL} -n"
48SYSCTL_W="${SYSCTL}"
49PROTECT="/usr/bin/protect"
50ID="/usr/bin/id"
51IDCMD="if [ -x $ID ]; then $ID -un; fi"
52PS="/bin/ps -ww"
53JID=0
54CPUSET="/bin/cpuset"
55
56# rc_service provides the path to the service script that we are executing.
57# This is not being set here in an execution context, necessarily, so it's
58# really just a reasonable guess, and it will get overwritten later if
59# we are executing from some other means than direct execution by service(8)
60# or manual invocation of the service script.  The prime example of this is
61# during system startup, all rc scripts will be invoked via /etc/rc, so
62# run_rc_script will overwrite rc_service with the file being sourced.
63rc_service="$0"
64
65#
66#	functions
67#	---------
68
69# list_vars pattern
70#	List variables matching glob pattern.
71#
72list_vars()
73{
74	# Localize 'set' option below.
75	local -
76	local IFS=$'\n' line varname
77
78	# Disable path expansion in unquoted 'for' parameters below.
79	set -o noglob
80
81	for line in $(set); do
82		varname="${line%%=*}"
83
84		case "$varname" in
85		"$line"|*[!a-zA-Z0-9_]*)
86			continue
87			;;
88		$1)
89			echo $varname
90			;;
91		esac
92	done
93}
94
95# set_rcvar [var] [defval] [desc]
96#
97#	Echo or define a rc.conf(5) variable name.  Global variable
98#	$rcvars is used.
99#
100#	If no argument is specified, echo "${name}_enable".
101#
102#	If only a var is specified, echo "${var}_enable".
103#
104#	If var and defval are specified, the ${var} is defined as
105#	rc.conf(5) variable and the default value is ${defvar}.  An
106#	optional argument $desc can also be specified to add a
107#	description for that.
108#
109set_rcvar()
110{
111	local _var
112
113	case $# in
114	0)	echo ${name}_enable ;;
115	1)	echo ${1}_enable ;;
116	*)
117		debug "set_rcvar: \$$1=$2 is added" \
118		    " as a rc.conf(5) variable."
119		_var=$1
120		rcvars="${rcvars# } $_var"
121		eval ${_var}_defval=\"$2\"
122		shift 2
123		eval ${_var}_desc=\"$*\"
124	;;
125	esac
126}
127
128# set_rcvar_obsolete oldvar [newvar] [msg]
129#	Define obsolete variable.
130#	Global variable $rcvars_obsolete is used.
131#
132set_rcvar_obsolete()
133{
134	local _var
135	_var=$1
136	debug "set_rcvar_obsolete: \$$1(old) -> \$$2(new) is defined"
137
138	rcvars_obsolete="${rcvars_obsolete# } $1"
139	eval ${1}_newvar=\"$2\"
140	shift 2
141	eval ${_var}_obsolete_msg=\"$*\"
142}
143
144#
145# force_depend script [rcvar]
146#	Force a service to start. Intended for use by services
147#	to resolve dependency issues.
148#	$1 - filename of script, in /etc/rc.d, to run
149#	$2 - name of the script's rcvar (minus the _enable)
150#
151force_depend()
152{
153	local _depend _dep_rcvar
154
155	_depend="$1"
156	_dep_rcvar="${2:-$1}_enable"
157
158	[ -n "$rc_fast" ] && ! checkyesno always_force_depends &&
159	    checkyesno $_dep_rcvar && return 0
160
161	/etc/rc.d/${_depend} forcestatus >/dev/null 2>&1 && return 0
162
163	info "${name} depends on ${_depend}, which will be forced to start."
164	if ! /etc/rc.d/${_depend} forcestart; then
165		warn "Unable to force ${_depend}. It may already be running."
166		return 1
167	fi
168}
169
170#
171# checkyesno var
172#	Test $1 variable, and warn if not set to YES or NO.
173#	Return 0 if it's "yes" (et al), nonzero otherwise.
174#
175checkyesno()
176{
177	eval _value=\$${1}
178	debug "checkyesno: $1 is set to $_value."
179	case $_value in
180
181		#	"yes", "true", "on", or "1"
182	[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
183		return 0
184		;;
185
186		#	"no", "false", "off", or "0"
187	[Nn][Oo]|[Ff][Aa][Ll][Ss][Ee]|[Oo][Ff][Ff]|0)
188		return 1
189		;;
190	*)
191		warn "\$${1} is not set properly - see rc.conf(5)."
192		return 1
193		;;
194	esac
195}
196
197#
198# reverse_list list
199#	print the list in reverse order
200#
201reverse_list()
202{
203	_revlist=
204	for _revfile; do
205		_revlist="$_revfile $_revlist"
206	done
207	echo $_revlist
208}
209
210# stop_boot always
211#	If booting directly to multiuser or $always is enabled,
212#	send SIGTERM to the parent (/etc/rc) to abort the boot.
213#	Otherwise just exit.
214#
215stop_boot()
216{
217	local always
218
219	case $1 in
220		#	"yes", "true", "on", or "1"
221        [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
222		always=true
223		;;
224	*)
225		always=false
226		;;
227	esac
228	if [ "$autoboot" = yes -o "$always" = true ]; then
229		echo "ERROR: ABORTING BOOT (sending SIGTERM to parent)!"
230		kill -TERM ${RC_PID}
231	fi
232	exit 1
233}
234
235#
236# mount_critical_filesystems type
237#	Go through the list of critical filesystems as provided in
238#	the rc.conf(5) variable $critical_filesystems_${type}, checking
239#	each one to see if it is mounted, and if it is not, mounting it.
240#
241mount_critical_filesystems()
242{
243	eval _fslist=\$critical_filesystems_${1}
244	for _fs in $_fslist; do
245		mount | (
246			_ismounted=false
247			while read what _on on _type type; do
248				if [ $on = $_fs ]; then
249					_ismounted=true
250				fi
251			done
252			if $_ismounted; then
253				:
254			else
255				mount $_fs >/dev/null 2>&1
256			fi
257		)
258	done
259}
260
261#
262# check_pidfile pidfile procname [interpreter]
263#	Parses the first line of pidfile for a PID, and ensures
264#	that the process is running and matches procname.
265#	Prints the matching PID upon success, nothing otherwise.
266#	interpreter is optional; see _find_processes() for details.
267#
268check_pidfile()
269{
270	_pidfile=$1
271	_procname=$2
272	_interpreter=$3
273	if [ -z "$_pidfile" -o -z "$_procname" ]; then
274		err 3 'USAGE: check_pidfile pidfile procname [interpreter]'
275	fi
276	if [ ! -f $_pidfile ]; then
277		debug "pid file ($_pidfile): not readable."
278		return
279	fi
280	read _pid _junk < $_pidfile
281	if [ -z "$_pid" ]; then
282		debug "pid file ($_pidfile): no pid in file."
283		return
284	fi
285	_find_processes $_procname ${_interpreter:-.} '-p '"$_pid"
286}
287
288#
289# check_process procname [interpreter]
290#	Ensures that a process (or processes) named procname is running.
291#	Prints a list of matching PIDs.
292#	interpreter is optional; see _find_processes() for details.
293#
294check_process()
295{
296	_procname=$1
297	_interpreter=$2
298	if [ -z "$_procname" ]; then
299		err 3 'USAGE: check_process procname [interpreter]'
300	fi
301	_find_processes $_procname ${_interpreter:-.} '-ax'
302}
303
304#
305# _find_processes procname interpreter psargs
306#	Search for procname in the output of ps generated by psargs.
307#	Prints the PIDs of any matching processes, space separated.
308#
309#	If interpreter == ".", check the following variations of procname
310#	against the first word of each command:
311#		procname
312#		`basename procname`
313#		`basename procname` + ":"
314#		"(" + `basename procname` + ")"
315#		"[" + `basename procname` + "]"
316#
317#	If interpreter != ".", read the first line of procname, remove the
318#	leading #!, normalise whitespace, append procname, and attempt to
319#	match that against each command, either as is, or with extra words
320#	at the end.  As an alternative, to deal with interpreted daemons
321#	using perl, the basename of the interpreter plus a colon is also
322#	tried as the prefix to procname.
323#
324_find_processes()
325{
326	if [ $# -ne 3 ]; then
327		err 3 'USAGE: _find_processes procname interpreter psargs'
328	fi
329	_procname=$1
330	_interpreter=$2
331	_psargs=$3
332
333	_pref=
334	if [ $_interpreter != "." ]; then	# an interpreted script
335		_script="${_chroot}${_chroot:+/}$_procname"
336		if [ -r "$_script" ]; then
337			read _interp < $_script	# read interpreter name
338			case "$_interp" in
339			\#!*)
340				_interp=${_interp#\#!}	# strip #!
341				set -- $_interp
342				case $1 in
343				*/bin/env)
344					shift	# drop env to get real name
345					;;
346				esac
347				if [ $_interpreter != $1 ]; then
348					warn "\$command_interpreter $_interpreter != $1"
349				fi
350				;;
351			*)
352				warn "no shebang line in $_script"
353				set -- $_interpreter
354				;;
355			esac
356		else
357			warn "cannot read shebang line from $_script"
358			set -- $_interpreter
359		fi
360		_interp="$* $_procname"		# cleanup spaces, add _procname
361		_interpbn=${1##*/}
362		_fp_args='_argv'
363		_fp_match='case "$_argv" in
364		    ${_interp}|"${_interp} "*|"[${_interpbn}]"|"${_interpbn}: ${_procname}"*)'
365	else					# a normal daemon
366		_procnamebn=${_procname##*/}
367		_fp_args='_arg0 _argv'
368		_fp_match='case "$_arg0" in
369		    $_procname|$_procnamebn|${_procnamebn}:|"(${_procnamebn})"|"[${_procnamebn}]")'
370	fi
371
372	_proccheck="\
373		$PS 2>/dev/null -o pid= -o jid= -o command= $_psargs"' |
374		while read _npid _jid '"$_fp_args"'; do
375			'"$_fp_match"'
376				if [ "$JID" -eq "$_jid" ];
377				then echo -n "$_pref$_npid";
378				_pref=" ";
379				fi
380				;;
381			esac
382		done'
383
384#	debug "in _find_processes: proccheck is ($_proccheck)."
385	eval $_proccheck
386}
387
388# sort_lite [-b] [-n] [-k POS] [-t SEP]
389#	A lite version of sort(1) (supporting a few options) that can be used
390#	before the real sort(1) is available (e.g., in scripts that run prior
391#	to mountcritremote). Requires only shell built-in functionality.
392#
393sort_lite()
394{
395	local funcname=sort_lite
396	local sort_sep="$IFS" sort_ignore_leading_space=
397	local sort_field=0 sort_strict_fields= sort_numeric=
398	local nitems=0 skip_leading=0 trim=
399
400	local OPTIND flag
401	while getopts bnk:t: flag; do
402		case "$flag" in
403		b) sort_ignore_leading_space=1 ;;
404		n) sort_numeric=1 sort_ignore_leading_space=1 ;;
405		k) sort_field="${OPTARG%%,*}" ;; # only up to first comma
406			# NB: Unlike sort(1) only one POS allowed
407		t) sort_sep="$OPTARG"
408		   if [ ${#sort_sep} -gt 1 ]; then
409		   	echo "$funcname: multi-character tab \`$sort_sep'" >&2
410		   	return 1
411		   fi
412		   sort_strict_fields=1
413		   ;;
414		\?) return 1 ;;
415		esac
416	done
417	shift $(( $OPTIND - 1 ))
418
419	# Create transformation pattern to trim leading text if desired
420	case "$sort_field" in
421	""|[!0-9]*|*[!0-9.]*)
422		echo "$funcname: invalid sort field \`$sort_field'" >&2
423		return 1
424		;;
425	*.*)
426		skip_leading=${sort_field#*.} sort_field=${sort_field%%.*}
427		while [ ${skip_leading:-0} -gt 1 ] 2> /dev/null; do
428			trim="$trim?" skip_leading=$(( $skip_leading - 1 ))
429		done
430	esac
431
432	# Copy input to series of local numbered variables
433	# NB: IFS of NULL preserves leading whitespace
434	local LINE
435	while IFS= read -r LINE || [ "$LINE" ]; do
436		nitems=$(( $nitems + 1 ))
437		local src_$nitems="$LINE"
438	done
439
440	#
441	# Sort numbered locals using insertion sort
442	#
443	local curitem curitem_orig curitem_mod curitem_haskey
444	local dest dest_orig dest_mod dest_haskey
445	local d gt n
446	local i=1
447	while [ $i -le $nitems ]; do
448		curitem_haskey=1 # Assume sort field (-k POS) exists
449		eval curitem=\"\$src_$i\"
450		curitem_mod="$curitem" # for modified comparison
451		curitem_orig="$curitem" # for original comparison
452
453		# Trim leading whitespace if desired
454		if [ "$sort_ignore_leading_space" ]; then
455			while case "$curitem_orig" in
456				[$IFS]*) : ;; *) false; esac
457			do
458				curitem_orig="${curitem_orig#?}"
459			done
460			curitem_mod="$curitem_orig"
461		fi
462
463		# Shift modified comparison value if sort field (-k POS) is > 1
464		n=$sort_field
465		while [ $n -gt 1 ]; do
466			case "$curitem_mod" in
467			*[$sort_sep]*)
468				# Cut text up-to (and incl.) first separator
469				curitem_mod="${curitem_mod#*[$sort_sep]}"
470
471				# Skip NULLs unless strict field splitting
472				[ "$sort_strict_fields" ] ||
473					[ "${curitem_mod%%[$sort_sep]*}" ] ||
474					[ $n -eq 2 ] ||
475					continue
476				;;
477			*)
478				# Asked for a field that doesn't exist
479				curitem_haskey= break
480			esac
481			n=$(( $n - 1 ))
482		done
483
484		# Trim trailing words if sort field >= 1
485		[ $sort_field -ge 1 -a "$sort_numeric" ] &&
486			curitem_mod="${curitem_mod%%[$sort_sep]*}"
487
488		# Apply optional trim (-k POS.TRIM) to cut leading characters
489		curitem_mod="${curitem_mod#$trim}"
490
491		# Determine the type of modified comparison to use initially
492		# NB: Prefer numerical if requested but fallback to standard
493		case "$curitem_mod" in
494		""|[!0-9]*) # NULL or begins with non-number
495			gt=">"
496			[ "$sort_numeric" ] && curitem_mod=0
497			;;
498		*)
499			if [ "$sort_numeric" ]; then
500				gt="-gt"
501				curitem_mod="${curitem_mod%%[!0-9]*}"
502					# NB: trailing non-digits removed
503					# otherwise numeric comparison fails
504			else
505				gt=">"
506			fi
507		esac
508
509		# If first time through, short-circuit below position-search
510		if [ $i -le 1 ]; then
511			d=0
512		else
513			d=1
514		fi
515
516		#
517		# Find appropriate element position
518		#
519		while [ $d -gt 0 ]
520		do
521			dest_haskey=$curitem_haskey
522			eval dest=\"\$dest_$d\"
523			dest_mod="$dest" # for modified comparison
524			dest_orig="$dest" # for original comparison
525
526			# Trim leading whitespace if desired
527			if [ "$sort_ignore_leading_space" ]; then
528				while case "$dest_orig" in
529					[$IFS]*) : ;; *) false; esac
530				do
531					dest_orig="${dest_orig#?}"
532				done
533				dest_mod="$dest_orig"
534			fi
535
536			# Shift modified value if sort field (-k POS) is > 1
537			n=$sort_field
538			while [ $n -gt 1 ]; do
539				case "$dest_mod" in
540				*[$sort_sep]*)
541					# Cut text up-to (and incl.) 1st sep
542					dest_mod="${dest_mod#*[$sort_sep]}"
543
544					# Skip NULLs unless strict fields
545					[ "$sort_strict_fields" ] ||
546					    [ "${dest_mod%%[$sort_sep]*}" ] ||
547					    [ $n -eq 2 ] ||
548					    continue
549					;;
550				*)
551					# Asked for a field that doesn't exist
552					dest_haskey= break
553				esac
554				n=$(( $n - 1 ))
555			done
556
557			# Trim trailing words if sort field >= 1
558			[ $sort_field -ge 1 -a "$sort_numeric" ] &&
559				dest_mod="${dest_mod%%[$sort_sep]*}"
560
561			# Apply optional trim (-k POS.TRIM), cut leading chars
562			dest_mod="${dest_mod#$trim}"
563
564			# Determine type of modified comparison to use
565			# NB: Prefer numerical if requested, fallback to std
566			case "$dest_mod" in
567			""|[!0-9]*) # NULL or begins with non-number
568				gt=">"
569				[ "$sort_numeric" ] && dest_mod=0
570				;;
571			*)
572				if [ "$sort_numeric" ]; then
573					gt="-gt"
574					dest_mod="${dest_mod%%[!0-9]*}"
575						# NB: kill trailing non-digits
576						# for numeric comparison safety
577				else
578					gt=">"
579				fi
580			esac
581
582			# Break if we've found the proper element position
583			if [ "$curitem_haskey" -a "$dest_haskey" ]; then
584				if [ "$dest_mod" = "$curitem_mod" ]; then
585					[ "$dest_orig" ">" "$curitem_orig" ] &&
586						break
587				elif [ "$dest_mod" $gt "$curitem_mod" ] \
588					2> /dev/null
589				then
590					break
591				fi
592			else
593				[ "$dest_orig" ">" "$curitem_orig" ] && break
594			fi
595
596			# Break if we've hit the end
597			[ $d -ge $i ] && break
598
599			d=$(( $d + 1 ))
600		done
601
602		# Shift remaining positions forward, making room for new item
603		n=$i
604		while [ $n -ge $d ]; do
605			# Shift destination item forward one placement
606			eval dest_$(( $n + 1 ))=\"\$dest_$n\"
607			n=$(( $n - 1 ))
608		done
609
610		# Place the element
611		if [ $i -eq 1 ]; then
612			local dest_1="$curitem"
613		else
614			local dest_$d="$curitem"
615		fi
616
617		i=$(( $i + 1 ))
618	done
619
620	# Print sorted results
621	d=1
622	while [ $d -le $nitems ]; do
623		eval echo \"\$dest_$d\"
624		d=$(( $d + 1 ))
625	done
626}
627
628#
629# wait_for_pids pid [pid ...]
630#	spins until none of the pids exist
631#
632wait_for_pids()
633{
634	local _list _prefix _nlist _j
635
636	_list="$@"
637	if [ -z "$_list" ]; then
638		return
639	fi
640	_prefix=
641	while true; do
642		_nlist="";
643		for _j in $_list; do
644			if kill -0 $_j 2>/dev/null; then
645				_nlist="${_nlist}${_nlist:+ }$_j"
646				[ -n "$_prefix" ] && sleep 1
647			fi
648		done
649		if [ -z "$_nlist" ]; then
650			break
651		fi
652		_list=$_nlist
653		echo -n ${_prefix:-"Waiting for PIDS: "}$_list
654		_prefix=", "
655		pwait $_list 2>/dev/null
656	done
657	if [ -n "$_prefix" ]; then
658		echo "."
659	fi
660}
661
662#
663# get_pidfile_from_conf string file
664#
665#	Takes a string to search for in the specified file.
666#	Ignores lines with traditional comment characters.
667#
668# Example:
669#
670# if get_pidfile_from_conf string file; then
671#	pidfile="$_pidfile_from_conf"
672# else
673#	pidfile='appropriate default'
674# fi
675#
676get_pidfile_from_conf()
677{
678	if [ -z "$1" -o -z "$2" ]; then
679		err 3 "USAGE: get_pidfile_from_conf string file ($name)"
680	fi
681
682	local string file line
683
684	string="$1" ; file="$2"
685
686	if [ ! -s "$file" ]; then
687		err 3 "get_pidfile_from_conf: $file does not exist ($name)"
688	fi
689
690	while read line; do
691		case "$line" in
692		*[#\;]*${string}*)	continue ;;
693		*${string}*)		break ;;
694		esac
695	done < $file
696
697	if [ -n "$line" ]; then
698		line=${line#*/}
699		_pidfile_from_conf="/${line%%[\"\;]*}"
700	else
701		return 1
702	fi
703}
704
705#
706# check_startmsgs
707#	If rc_quiet is set (usually as a result of using faststart at
708#	boot time) check if rc_startmsgs is enabled.
709#
710check_startmsgs()
711{
712	if [ -n "$rc_quiet" ]; then
713		checkyesno rc_startmsgs
714	else
715		return 0
716	fi
717}
718
719#
720# startmsg
721#	Preferred method to use when displaying start messages in lieu of echo.
722#
723startmsg()
724{
725	check_startmsgs && echo "$@"
726}
727
728#
729# run_rc_command argument
730#	Search for argument in the list of supported commands, which is:
731#		"start stop restart rcvar status poll ${extra_commands}"
732#	If there's a match, run ${argument}_cmd or the default method
733#	(see below).
734#
735#	If argument has a given prefix, then change the operation as follows:
736#		Prefix	Operation
737#		------	---------
738#		fast	Skip the pid check, and set rc_fast=yes, rc_quiet=yes
739#		force	Set ${rcvar} to YES, and set rc_force=yes
740#		one	Set ${rcvar} to YES
741#		quiet	Don't output some diagnostics, and set rc_quiet=yes
742#
743#	The following globals are used:
744#
745#	Name		Needed	Purpose
746#	----		------	-------
747#	name		y	Name of script.
748#
749#	command		n	Full path to command.
750#				Not needed if ${rc_arg}_cmd is set for
751#				each keyword.
752#
753#	command_args	n	Optional args/shell directives for command.
754#
755#	command_interpreter n	If not empty, command is interpreted, so
756#				call check_{pidfile,process}() appropriately.
757#
758#	desc		n	Description of script.
759#
760#	extra_commands	n	List of extra commands supported.
761#
762#	pidfile		n	If set, use check_pidfile $pidfile $command,
763#				otherwise use check_process $command.
764#				In either case, only check if $command is set.
765#
766#	procname	n	Process name to check for instead of $command.
767#
768#	rcvar		n	This is checked with checkyesno to determine
769#				if the action should be run.
770#
771#	${name}_program	n	Full path to command.
772#				Meant to be used in /etc/rc.conf to override
773#				${command}.
774#
775#	${name}_chroot	n	Directory to chroot to before running ${command}
776#				Requires /usr to be mounted.
777#
778#	${name}_chdir	n	Directory to cd to before running ${command}
779#				(if not using ${name}_chroot).
780#
781#	${name}_cpuset	n	A list of CPUs to run ${command} on.
782#				Requires /usr to be mounted.
783#
784#	${name}_flags	n	Arguments to call ${command} with.
785#				NOTE:	$flags from the parent environment
786#					can be used to override this.
787#
788#	${name}_env	n	Environment variables to run ${command} with.
789#
790#	${name}_env_file n	File to source variables to run ${command} with.
791#
792#	${name}_fib	n	Routing table number to run ${command} with.
793#
794#	${name}_nice	n	Nice level to run ${command} at.
795#
796#	${name}_oomprotect n	Don't kill ${command} when swap space is exhausted.
797#
798#	${name}_umask	n	The file creation mask to run ${command} with.
799#
800#	${name}_user	n	User to run ${command} as, using su(1) if not
801#				using ${name}_chroot.
802#				Requires /usr to be mounted.
803#
804#	${name}_group	n	Group to run chrooted ${command} as.
805#				Requires /usr to be mounted.
806#
807#	${name}_groups	n	Comma separated list of supplementary groups
808#				to run the chrooted ${command} with.
809#				Requires /usr to be mounted.
810#
811#	${name}_prepend	n	Command added before ${command}.
812#
813#	${name}_setup	n	Command executed before ${command}.
814#
815#	${name}_login_class n	Login class to use, else "daemon".
816#
817#	${name}_limits	n	limits(1) to apply to ${command}.
818#
819#	${rc_arg}_cmd	n	If set, use this as the method when invoked;
820#				Otherwise, use default command (see below)
821#
822#	${rc_arg}_precmd n	If set, run just before performing the
823#				${rc_arg}_cmd method in the default
824#				operation (i.e, after checking for required
825#				bits and process (non)existence).
826#				If this completes with a non-zero exit code,
827#				don't run ${rc_arg}_cmd.
828#
829#	${rc_arg}_postcmd n	If set, run just after performing the
830#				${rc_arg}_cmd method, if that method
831#				returned a zero exit code.
832#
833#	required_dirs	n	If set, check for the existence of the given
834#				directories before running a (re)start command.
835#
836#	required_files	n	If set, check for the readability of the given
837#				files before running a (re)start command.
838#
839#	required_modules n	If set, ensure the given kernel modules are
840#				loaded before running a (re)start command.
841#				The check and possible loads are actually
842#				done after start_precmd so that the modules
843#				aren't loaded in vain, should the precmd
844#				return a non-zero status to indicate a error.
845#				If a word in the list looks like "foo:bar",
846#				"foo" is the KLD file name and "bar" is the
847#				module name.  If a word looks like "foo~bar",
848#				"foo" is the KLD file name and "bar" is a
849#				egrep(1) pattern matching the module name.
850#				Otherwise the module name is assumed to be
851#				the same as the KLD file name, which is most
852#				common.  See load_kld().
853#
854#	required_vars	n	If set, perform checkyesno on each of the
855#				listed variables before running the default
856#				(re)start command.
857#
858#	Default behaviour for a given argument, if no override method is
859#	provided:
860#
861#	Argument	Default behaviour
862#	--------	-----------------
863#	start		if !running && checkyesno ${rcvar}
864#				${command}
865#
866#	stop		if ${pidfile}
867#				rc_pid=$(check_pidfile $pidfile $command)
868#			else
869#				rc_pid=$(check_process $command)
870#			kill $sig_stop $rc_pid
871#			wait_for_pids $rc_pid
872#			($sig_stop defaults to TERM.)
873#
874#	reload		Similar to stop, except use $sig_reload instead,
875#			and don't wait_for_pids.
876#			$sig_reload defaults to HUP.
877#			Note that `reload' isn't provided by default,
878#			it should be enabled via $extra_commands.
879#
880#	restart		Run `stop' then `start'.
881#
882#	status		Show if ${command} is running, etc.
883#
884#	poll		Wait for ${command} to exit.
885#
886#	rcvar		Display what rc.conf variable is used (if any).
887#
888#	enabled		Return true if the service is enabled.
889#
890#	describe	Show the service's description
891#
892#	extracommands	Show the service's extra commands
893#
894#	Variables available to methods, and after run_rc_command() has
895#	completed:
896#
897#	Variable	Purpose
898#	--------	-------
899#	rc_arg		Argument to command, after fast/force/one processing
900#			performed
901#
902#	rc_flags	Flags to start the default command with.
903#			Defaults to ${name}_flags, unless overridden
904#			by $flags from the environment.
905#			This variable may be changed by the precmd method.
906#
907#	rc_service	Path to the service being executed, in case the service
908#			needs to re-invoke itself.
909#
910#	rc_pid		PID of command (if appropriate)
911#
912#	rc_fast		Not empty if "fast" was provided (q.v.)
913#
914#	rc_force	Not empty if "force" was provided (q.v.)
915#
916#	rc_quiet	Not empty if "quiet" was provided
917#
918#
919run_rc_command()
920{
921	_return=0
922	rc_arg=$1
923	if [ -z "$name" ]; then
924		err 3 'run_rc_command: $name is not set.'
925	fi
926
927	# Don't repeat the first argument when passing additional command-
928	# line arguments to the command subroutines.
929	#
930	shift 1
931	rc_extra_args="$*"
932
933	_rc_prefix=
934	case "$rc_arg" in
935	fast*)				# "fast" prefix; don't check pid
936		rc_arg=${rc_arg#fast}
937		rc_fast=yes
938		rc_quiet=yes
939		;;
940	force*)				# "force" prefix; always run
941		rc_force=yes
942		_rc_prefix=force
943		rc_arg=${rc_arg#${_rc_prefix}}
944		if [ -n "${rcvar}" ]; then
945			eval ${rcvar}=YES
946		fi
947		;;
948	one*)				# "one" prefix; set ${rcvar}=yes
949		_rc_prefix=one
950		rc_arg=${rc_arg#${_rc_prefix}}
951		if [ -n "${rcvar}" ]; then
952			eval ${rcvar}=YES
953		fi
954		;;
955	quiet*)				# "quiet" prefix; omit some messages
956		_rc_prefix=quiet
957		rc_arg=${rc_arg#${_rc_prefix}}
958		rc_quiet=yes
959		;;
960	esac
961
962	eval _override_command=\$${name}_program
963	command=${_override_command:-$command}
964
965	_keywords="start stop restart rcvar enable disable delete enabled describe extracommands $extra_commands"
966	rc_pid=
967	_pidcmd=
968	_procname=${procname:-${command}}
969
970	eval _cpuset=\$${name}_cpuset
971
972	# Loose validation of the configured cpuset; just make sure it starts
973	# with a number.  There have also been cases in the past where a hyphen
974	# in a service name has caused eval errors, which trickle down into
975	# various variables; don't let a situation like that break a bunch of
976	# services just because of cpuset(1).
977	case "$_cpuset" in
978	[0-9]*)	;;
979	*)	_cpuset="" ;;
980	esac
981
982	_cpusetcmd=
983	if [ -n "$_cpuset" ]; then
984		_cpusetcmd="$CPUSET -l $_cpuset"
985	fi
986
987					# setup pid check command
988	if [ -n "$_procname" ]; then
989		if [ -n "$pidfile" ]; then
990			_pidcmd='rc_pid=$(check_pidfile '"$pidfile $_procname $command_interpreter"')'
991		else
992			_pidcmd='rc_pid=$(check_process '"$_procname $command_interpreter"')'
993		fi
994		_keywords="${_keywords} status poll"
995	else
996		if [ ! -z "${status_cmd}" ]
997		then
998			_keywords="${_keywords} status"
999		fi
1000	fi
1001
1002	if [ -z "$rc_arg" ]; then
1003		rc_usage $_keywords
1004	fi
1005
1006	if [ "$rc_arg" = "enabled" ] ; then
1007		checkyesno ${rcvar}
1008		return $?
1009	fi
1010
1011	if [ -n "$flags" ]; then	# allow override from environment
1012		rc_flags=$flags
1013	else
1014		eval rc_flags=\$${name}_flags
1015	fi
1016	eval _chdir=\$${name}_chdir	_chroot=\$${name}_chroot \
1017	    _nice=\$${name}_nice	_user=\$${name}_user \
1018	    _group=\$${name}_group	_groups=\$${name}_groups \
1019	    _fib=\$${name}_fib		_env=\$${name}_env \
1020	    _prepend=\$${name}_prepend	_login_class=\${${name}_login_class:-daemon} \
1021	    _limits=\$${name}_limits	_oomprotect=\$${name}_oomprotect \
1022	    _setup=\$${name}_setup	_env_file=\$${name}_env_file \
1023	    _umask=\$${name}_umask
1024
1025	if [ -n "$_env_file" ] && [ -r "${_env_file}" ]; then	# load env from file
1026		set -a
1027		. $_env_file
1028		set +a
1029	fi
1030
1031	if [ -n "$_user" ]; then	# unset $_user if running as that user
1032		if [ "$_user" = "$(eval $IDCMD)" ]; then
1033			unset _user
1034		fi
1035	fi
1036
1037	[ -z "$autoboot" ] && eval $_pidcmd	# determine the pid if necessary
1038
1039	for _elem in $_keywords; do
1040		if [ "$_elem" != "$rc_arg" ]; then
1041			continue
1042		fi
1043					# if ${rcvar} is set, $1 is not "rcvar", "describe",
1044					# "enable" or "delete", and ${rc_pid} is not set, run:
1045					#	checkyesno ${rcvar}
1046					# and return if that failed
1047					#
1048		if [ -n "${rcvar}" -a "$rc_arg" != "rcvar" -a "$rc_arg" != "stop" \
1049		    -a "$rc_arg" != "delete" -a "$rc_arg" != "enable" \
1050		    -a "$rc_arg" != "describe" ] ||
1051		    [ -n "${rcvar}" -a "$rc_arg" = "stop" -a -z "${rc_pid}" ]; then
1052			if ! checkyesno ${rcvar}; then
1053				if [ -n "${rc_quiet}" ]; then
1054					return 0
1055				fi
1056				echo -n "Cannot '${rc_arg}' $name. Set ${rcvar} to "
1057				echo -n "YES in /etc/rc.conf or use 'one${rc_arg}' "
1058				echo "instead of '${rc_arg}'."
1059				return 0
1060			fi
1061		fi
1062
1063		if [ $rc_arg = "start" -a -z "$rc_fast" -a -n "$rc_pid" ]; then
1064			if [ -z "$rc_quiet" ]; then
1065				echo 1>&2 "${name} already running? " \
1066				    "(pid=$rc_pid)."
1067			fi
1068			return 1
1069		fi
1070
1071					# if there's a custom ${XXX_cmd},
1072					# run that instead of the default
1073					#
1074		eval _cmd=\$${rc_arg}_cmd \
1075		     _precmd=\$${rc_arg}_precmd \
1076		     _postcmd=\$${rc_arg}_postcmd
1077
1078		if [ -n "$_cmd" ]; then
1079			if [ -n "$_env" ]; then
1080				eval "export -- $_env"
1081			fi
1082			_run_rc_precmd || return 1
1083			_run_rc_doit "$_cpusetcmd $_cmd $rc_extra_args" || return 1
1084			_run_rc_postcmd
1085			return $_return
1086		fi
1087
1088		case "$rc_arg" in	# default operations...
1089
1090		describe)
1091			if [ -n "$desc" ]; then
1092				echo "$desc"
1093			fi
1094			;;
1095
1096		extracommands)
1097			echo "$extra_commands"
1098			;;
1099
1100		enable)
1101			_out=$(/usr/sbin/sysrc -vs "$name" "$rcvar=YES") &&
1102				echo "$name enabled in ${_out%%:*}"
1103			;;
1104
1105		disable)
1106			_out=$(/usr/sbin/sysrc -vs "$name" "$rcvar=NO") &&
1107				echo "$name disabled in ${_out%%:*}"
1108			;;
1109
1110		delete)
1111			_files=
1112			for _file in $(sysrc -lEs "$name"); do
1113				_out=$(sysrc -Fif $_file "$rcvar") && _files="$_files $_file"
1114			done
1115			/usr/sbin/sysrc -x "$rcvar" && echo "$rcvar deleted in ${_files# }"
1116				# delete file in rc.conf.d if desired and empty.
1117			checkyesno service_delete_empty || _files=
1118			for _file in $_files; do
1119				[ "$_file" = "${_file#*/rc.conf.d/}" ] && continue
1120				[ $(/usr/bin/stat -f%z $_file) -gt 0 ] && continue
1121				/bin/rm "$_file" && echo "Empty file $_file removed"
1122			done
1123			;;
1124
1125		status)
1126			_run_rc_precmd || return 1
1127			if [ -n "$rc_pid" ]; then
1128				echo "${name} is running as pid $rc_pid."
1129			else
1130				echo "${name} is not running."
1131				return 1
1132			fi
1133			_run_rc_postcmd
1134			;;
1135
1136		start)
1137			if [ ! -x "${_chroot}${_chroot:+/}${command}" ]; then
1138				warn "run_rc_command: cannot run $command"
1139				return 1
1140			fi
1141
1142			if ! _run_rc_precmd; then
1143				warn "failed precmd routine for ${name}"
1144				return 1
1145			fi
1146
1147					# setup the full command to run
1148					#
1149			startmsg "Starting ${name}."
1150			if [ -n "$_chroot" ]; then
1151				_cd=
1152				_doit="\
1153${_nice:+nice -n $_nice }\
1154$_cpusetcmd \
1155${_fib:+setfib -F $_fib }\
1156${_env:+env $_env }\
1157chroot ${_user:+-u $_user }${_group:+-g $_group }${_groups:+-G $_groups }\
1158$_chroot $command $rc_flags $command_args"
1159			else
1160				_cd="${_chdir:+cd $_chdir && }"
1161				_doit="\
1162${_fib:+setfib -F $_fib }\
1163${_env:+env $_env }\
1164$_cpusetcmd $command $rc_flags $command_args"
1165				if [ -n "$_user" ]; then
1166				    _doit="su -m $_user -c 'sh -c \"$_doit\"'"
1167				fi
1168				if [ -n "$_nice" ]; then
1169					if [ -z "$_user" ]; then
1170						_doit="sh -c \"$_doit\""
1171					fi
1172					_doit="nice -n $_nice $_doit"
1173				fi
1174				if [ -n "$_prepend" ]; then
1175					_doit="$_prepend $_doit"
1176				fi
1177			fi
1178
1179			if [ -n "$_setup" ]; then
1180				if ! _run_rc_doit "$_setup"; then
1181					warn "failed to setup ${name}"
1182				fi
1183			fi
1184
1185					# Prepend default limits
1186			_doit="$_cd limits -C $_login_class $_limits $_doit"
1187
1188					# run the full command
1189					#
1190			if ! _run_rc_doit "$_doit"; then
1191				warn "failed to start ${name}"
1192				return 1
1193			fi
1194
1195					# finally, run postcmd
1196					#
1197			_run_rc_postcmd
1198			;;
1199
1200		stop)
1201			if [ -z "$rc_pid" ]; then
1202				[ -n "$rc_fast" ] && return 0
1203				_run_rc_notrunning
1204				return 1
1205			fi
1206
1207			_run_rc_precmd || return 1
1208
1209					# send the signal to stop
1210					#
1211			echo "Stopping ${name}."
1212			_doit=$(_run_rc_killcmd "${sig_stop:-TERM}")
1213			_run_rc_doit "$_doit" || return 1
1214
1215					# wait for the command to exit,
1216					# and run postcmd.
1217			wait_for_pids $rc_pid
1218
1219			_run_rc_postcmd
1220			;;
1221
1222		reload)
1223			if [ -z "$rc_pid" ]; then
1224				_run_rc_notrunning
1225				return 1
1226			fi
1227
1228			_run_rc_precmd || return 1
1229
1230			_doit=$(_run_rc_killcmd "${sig_reload:-HUP}")
1231			_run_rc_doit "$_doit" || return 1
1232
1233			_run_rc_postcmd
1234			;;
1235
1236		restart)
1237					# prevent restart being called more
1238					# than once by any given script
1239					#
1240			if ${_rc_restart_done:-false}; then
1241				return 0
1242			fi
1243			_rc_restart_done=true
1244
1245			_run_rc_precmd || return 1
1246
1247			# run those in a subshell to keep global variables
1248			( run_rc_command ${_rc_prefix}stop $rc_extra_args )
1249			( run_rc_command ${_rc_prefix}start $rc_extra_args )
1250			_return=$?
1251			[ $_return -ne 0 ] && [ -z "$rc_force" ] && return 1
1252
1253			_run_rc_postcmd
1254			;;
1255
1256		poll)
1257			_run_rc_precmd || return 1
1258			if [ -n "$rc_pid" ]; then
1259				wait_for_pids $rc_pid
1260			fi
1261			_run_rc_postcmd
1262			;;
1263
1264		rcvar)
1265			echo -n "# $name"
1266			if [ -n "$desc" ]; then
1267				echo " : $desc"
1268			else
1269				echo ""
1270			fi
1271			echo "#"
1272			# Get unique vars in $rcvar $rcvars
1273			for _v in $rcvar $rcvars; do
1274				case $v in
1275				$_v\ *|\ *$_v|*\ $_v\ *) ;;
1276				*)	v="${v# } $_v" ;;
1277				esac
1278			done
1279
1280			# Display variables.
1281			for _v in $v; do
1282				if [ -z "$_v" ]; then
1283					continue
1284				fi
1285
1286				eval _desc=\$${_v}_desc
1287				eval _defval=\$${_v}_defval
1288				_h="-"
1289
1290				eval echo \"$_v=\\\"\$$_v\\\"\"
1291				# decode multiple lines of _desc
1292				while [ -n "$_desc" ]; do
1293					case $_desc in
1294					*^^*)
1295						echo "# $_h ${_desc%%^^*}"
1296						_desc=${_desc#*^^}
1297						_h=" "
1298						;;
1299					*)
1300						echo "# $_h ${_desc}"
1301						break
1302						;;
1303					esac
1304				done
1305				echo "#   (default: \"$_defval\")"
1306			done
1307			echo ""
1308			;;
1309
1310		*)
1311			rc_usage $_keywords
1312			;;
1313
1314		esac
1315
1316		# Apply protect(1) to the PID if ${name}_oomprotect is set.
1317		case "$rc_arg" in
1318		start)
1319			# We cannot use protect(1) inside jails.
1320			if [ -n "$_oomprotect" ] && [ -f "${PROTECT}" ] &&
1321			    [ "$(sysctl -n security.jail.jailed)" -eq 0 ]; then
1322				[ -z "${rc_pid}" ] && eval $_pidcmd
1323				case $_oomprotect in
1324				[Aa][Ll][Ll])
1325					${PROTECT} -d -i -p ${rc_pid}
1326					;;
1327				[Yy][Ee][Ss])
1328					${PROTECT} -p ${rc_pid}
1329					;;
1330				esac
1331			fi
1332		;;
1333		esac
1334
1335		return $_return
1336	done
1337
1338	echo 1>&2 "$0: unknown directive '$rc_arg'."
1339	rc_usage $_keywords
1340	# not reached
1341}
1342
1343#
1344# Helper functions for run_rc_command: common code.
1345# They use such global variables besides the exported rc_* ones:
1346#
1347#	name	       R/W
1348#	------------------
1349#	_precmd		R
1350#	_postcmd	R
1351#	_return		W
1352#
1353_run_rc_precmd()
1354{
1355	check_required_before "$rc_arg" || return 1
1356
1357	if [ -n "$_precmd" ]; then
1358		debug "run_rc_command: ${rc_arg}_precmd: $_precmd $rc_extra_args"
1359		eval "$_precmd $rc_extra_args"
1360		_return=$?
1361
1362		# If precmd failed and force isn't set, request exit.
1363		if [ $_return -ne 0 ] && [ -z "$rc_force" ]; then
1364			return 1
1365		fi
1366	fi
1367
1368	check_required_after "$rc_arg" || return 1
1369
1370	return 0
1371}
1372
1373_run_rc_postcmd()
1374{
1375	if [ -n "$_postcmd" ]; then
1376		debug "run_rc_command: ${rc_arg}_postcmd: $_postcmd $rc_extra_args"
1377		eval "$_postcmd $rc_extra_args"
1378		_return=$?
1379	fi
1380	return 0
1381}
1382
1383_run_rc_doit()
1384{
1385	local _m
1386
1387	debug "run_rc_command: doit: $*"
1388	_m=$(umask)
1389	${_umask:+umask ${_umask}}
1390	eval "$@"
1391	_return=$?
1392	umask ${_m}
1393
1394	# If command failed and force isn't set, request exit.
1395	if [ $_return -ne 0 ] && [ -z "$rc_force" ]; then
1396		return 1
1397	fi
1398
1399	return 0
1400}
1401
1402_run_rc_notrunning()
1403{
1404	local _pidmsg
1405
1406	if [ -n "$pidfile" ]; then
1407		_pidmsg=" (check $pidfile)."
1408	else
1409		_pidmsg=
1410	fi
1411	echo 1>&2 "${name} not running?${_pidmsg}"
1412}
1413
1414_run_rc_killcmd()
1415{
1416	local _cmd
1417
1418	_cmd="kill -$1 $rc_pid"
1419	if [ -n "$_user" ]; then
1420		_cmd="su -m ${_user} -c 'sh -c \"${_cmd}\"'"
1421	fi
1422	echo "$_cmd"
1423}
1424
1425#
1426# run_rc_script file arg
1427#	Start the script `file' with `arg', and correctly handle the
1428#	return value from the script.
1429#	If `file' ends with `.sh' and lives in /etc/rc.d, ignore it as it's
1430#	an old-style startup file.
1431#	If `file' ends with `.sh' and does not live in /etc/rc.d, it's sourced
1432#	into the current environment if $rc_fast_and_loose is set; otherwise
1433#	it is run as a child process.
1434#	If `file' appears to be a backup or scratch file, ignore it.
1435#	Otherwise if it is executable run as a child process.
1436#
1437run_rc_script()
1438{
1439	_file=$1
1440	_arg=$2
1441	if [ -z "$_file" -o -z "$_arg" ]; then
1442		err 3 'USAGE: run_rc_script file arg'
1443	fi
1444
1445	unset	name command command_args command_interpreter \
1446		extra_commands pidfile procname \
1447		rcvar rcvars rcvars_obsolete required_dirs required_files \
1448		required_vars
1449	eval unset ${_arg}_cmd ${_arg}_precmd ${_arg}_postcmd
1450
1451	rc_service="$_file"
1452	case "$_file" in
1453	/etc/rc.d/*.sh)			# no longer allowed in the base
1454		warn "Ignoring old-style startup script $_file"
1455		;;
1456	*[~#]|*.OLD|*.bak|*.orig|*,v)	# scratch file; skip
1457		warn "Ignoring scratch file $_file"
1458		;;
1459	*)				# run in subshell
1460		if [ -x $_file ]; then
1461			if [ -n "$rc_boottrace" ]; then
1462				boottrace_fn "$_file" "$_arg"
1463			elif [ -n "$rc_fast_and_loose" ]; then
1464				set $_arg; . $_file
1465			else
1466				( trap "echo Script $_file interrupted >&2 ; kill -QUIT $$" 3
1467				  trap "echo Script $_file interrupted >&2 ; exit 1" 2
1468				  trap "echo Script $_file running >&2" 29
1469				  set $_arg; . $_file )
1470			fi
1471		fi
1472		;;
1473	esac
1474}
1475
1476boottrace_fn()
1477{
1478	local _file _arg
1479	_file=$1
1480	_arg=$2
1481
1482	if [ -n "$rc_fast_and_loose" ]; then
1483		boottrace_sysctl "$_file start"
1484		set $_arg; . $_file
1485		boottrace_sysctl "$_file done"
1486	else
1487		$boottrace_cmd "$_file" "$_arg"
1488	fi
1489}
1490
1491boottrace_sysctl()
1492{
1493	${SYSCTL} kern.boottrace.boottrace="$1"
1494}
1495
1496#
1497# load_rc_config [service]
1498#	Source in the configuration file(s) for a given service.
1499#	If no service is specified, only the global configuration
1500#	file(s) will be loaded.
1501#
1502load_rc_config()
1503{
1504	local _name _rcvar_val _var _defval _v _msg _new _d
1505	_name=$1
1506
1507	if ${_rc_conf_loaded:-false}; then
1508		:
1509	else
1510		if [ -r /etc/defaults/rc.conf ]; then
1511			debug "Sourcing /etc/defaults/rc.conf"
1512			. /etc/defaults/rc.conf
1513			source_rc_confs
1514		elif [ -r /etc/rc.conf ]; then
1515			debug "Sourcing /etc/rc.conf (/etc/defaults/rc.conf doesn't exist)."
1516			. /etc/rc.conf
1517		fi
1518		_rc_conf_loaded=true
1519	fi
1520
1521	# If a service name was specified, attempt to load
1522	# service-specific configuration
1523	if [ -n "$_name" ] ; then
1524		for _d in /etc ${local_startup}; do
1525			_d=${_d%/rc.d}
1526			if [ -f ${_d}/rc.conf.d/"$_name" ]; then
1527				debug "Sourcing ${_d}/rc.conf.d/$_name"
1528				. ${_d}/rc.conf.d/"$_name"
1529			elif [ -d ${_d}/rc.conf.d/"$_name" ] ; then
1530				local _rc
1531				for _rc in ${_d}/rc.conf.d/"$_name"/* ; do
1532					if [ -f "$_rc" ] ; then
1533						debug "Sourcing $_rc"
1534						. "$_rc"
1535					fi
1536				done
1537			fi
1538		done
1539	fi
1540
1541	# Set defaults if defined.
1542	for _var in $rcvar $rcvars; do
1543		eval _defval=\$${_var}_defval
1544		if [ -n "$_defval" ]; then
1545			eval : \${$_var:=\$${_var}_defval}
1546		fi
1547	done
1548
1549	# check obsolete rc.conf variables
1550	for _var in $rcvars_obsolete; do
1551		eval _v=\$$_var
1552		eval _msg=\$${_var}_obsolete_msg
1553		eval _new=\$${_var}_newvar
1554		case $_v in
1555		"")
1556			;;
1557		*)
1558			if [ -z "$_new" ]; then
1559				_msg="Ignored."
1560			else
1561				eval $_new=\"\$$_var\"
1562				if [ -z "$_msg" ]; then
1563					_msg="Use \$$_new instead."
1564				fi
1565			fi
1566			warn "\$$_var is obsolete.  $_msg"
1567			;;
1568		esac
1569	done
1570}
1571
1572#
1573# load_rc_config_var name var
1574#	Read the rc.conf(5) var for name and set in the
1575#	current shell, using load_rc_config in a subshell to prevent
1576#	unwanted side effects from other variable assignments.
1577#
1578load_rc_config_var()
1579{
1580	if [ $# -ne 2 ]; then
1581		err 3 'USAGE: load_rc_config_var name var'
1582	fi
1583	eval $(eval '(
1584		load_rc_config '$1' >/dev/null;
1585                if [ -n "${'$2'}" -o "${'$2'-UNSET}" != "UNSET" ]; then
1586			echo '$2'=\'\''${'$2'}\'\'';
1587		fi
1588	)' )
1589}
1590
1591#
1592# rc_usage commands
1593#	Print a usage string for $0, with `commands' being a list of
1594#	valid commands.
1595#
1596rc_usage()
1597{
1598	echo -n 1>&2 "Usage: $0 [fast|force|one|quiet]("
1599
1600	_sep=
1601	for _elem; do
1602		echo -n 1>&2 "$_sep$_elem"
1603		_sep="|"
1604	done
1605	echo 1>&2 ")"
1606	exit 1
1607}
1608
1609#
1610# err exitval message
1611#	Display message to stderr and log to the syslog, and exit with exitval.
1612#
1613err()
1614{
1615	exitval=$1
1616	shift
1617
1618	if [ -x /usr/bin/logger ]; then
1619		logger "$0: ERROR: $*"
1620	fi
1621	echo 1>&2 "$0: ERROR: $*"
1622	exit $exitval
1623}
1624
1625#
1626# warn message
1627#	Display message to stderr and log to the syslog.
1628#
1629warn()
1630{
1631	if [ -x /usr/bin/logger ]; then
1632		logger "$0: WARNING: $*"
1633	fi
1634	echo 1>&2 "$0: WARNING: $*"
1635}
1636
1637#
1638# info message
1639#	Display informational message to stdout and log to syslog.
1640#
1641info()
1642{
1643	case ${rc_info} in
1644	[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
1645		if [ -x /usr/bin/logger ]; then
1646			logger "$0: INFO: $*"
1647		fi
1648		echo "$0: INFO: $*"
1649		;;
1650	esac
1651}
1652
1653#
1654# debug message
1655#	If debugging is enabled in rc.conf output message to stderr.
1656#	BEWARE that you don't call any subroutine that itself calls this
1657#	function.
1658#
1659debug()
1660{
1661	case ${rc_debug} in
1662	[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
1663		if [ -x /usr/bin/logger ]; then
1664			logger "$0: DEBUG: $*"
1665		fi
1666		echo 1>&2 "$0: DEBUG: $*"
1667		;;
1668	esac
1669}
1670
1671#
1672# backup_file action file cur backup
1673#	Make a backup copy of `file' into `cur', and save the previous
1674#	version of `cur' as `backup'.
1675#
1676#	The `action' keyword can be one of the following:
1677#
1678#	add		`file' is now being backed up (and is possibly
1679#			being reentered into the backups system).  `cur'
1680#			is created.
1681#
1682#	update		`file' has changed and needs to be backed up.
1683#			If `cur' exists, it is copied to `back'
1684#			and then `file' is copied to `cur'.
1685#
1686#	remove		`file' is no longer being tracked by the backups
1687#			system.  `cur' is moved `back'.
1688#
1689#
1690backup_file()
1691{
1692	_action=$1
1693	_file=$2
1694	_cur=$3
1695	_back=$4
1696
1697	case $_action in
1698	add|update)
1699		if [ -f $_cur ]; then
1700			cp -p $_cur $_back
1701		fi
1702		cp -p $_file $_cur
1703		chown root:wheel $_cur
1704		;;
1705	remove)
1706		mv -f $_cur $_back
1707		;;
1708	esac
1709}
1710
1711# make_symlink src link
1712#	Make a symbolic link 'link' to src from basedir. If the
1713#	directory in which link is to be created does not exist
1714#	a warning will be displayed and an error will be returned.
1715#	Returns 0 on success, 1 otherwise.
1716#
1717make_symlink()
1718{
1719	local src link linkdir _me
1720	src="$1"
1721	link="$2"
1722	linkdir="`dirname $link`"
1723	_me="make_symlink()"
1724
1725	if [ -z "$src" -o -z "$link" ]; then
1726		warn "$_me: requires two arguments."
1727		return 1
1728	fi
1729	if [ ! -d "$linkdir" ]; then
1730		warn "$_me: the directory $linkdir does not exist."
1731		return 1
1732	fi
1733	if ! ln -sf $src $link; then
1734		warn "$_me: unable to make a symbolic link from $link to $src"
1735		return 1
1736	fi
1737	return 0
1738}
1739
1740# devfs_rulesets_from_file file
1741#	Reads a set of devfs commands from file, and creates
1742#	the specified rulesets with their rules. Returns non-zero
1743#	if there was an error.
1744#
1745devfs_rulesets_from_file()
1746{
1747	local file _err _me _opts
1748	file="$1"
1749	_me="devfs_rulesets_from_file"
1750	_err=0
1751
1752	if [ -z "$file" ]; then
1753		warn "$_me: you must specify a file"
1754		return 1
1755	fi
1756	if [ ! -e "$file" ]; then
1757		debug "$_me: no such file ($file)"
1758		return 0
1759	fi
1760
1761	# Disable globbing so that the rule patterns are not expanded
1762	# by accident with matching filesystem entries.
1763	_opts=$-; set -f
1764
1765	debug "reading rulesets from file ($file)"
1766	{ while read line
1767	do
1768		case $line in
1769		\#*)
1770			continue
1771			;;
1772		\[*\]*)
1773			rulenum=`expr "$line" : "\[.*=\([0-9]*\)\]"`
1774			if [ -z "$rulenum" ]; then
1775				warn "$_me: cannot extract rule number ($line)"
1776				_err=1
1777				break
1778			fi
1779			rulename=`expr "$line" : "\[\(.*\)=[0-9]*\]"`
1780			if [ -z "$rulename" ]; then
1781				warn "$_me: cannot extract rule name ($line)"
1782				_err=1
1783				break;
1784			fi
1785			eval $rulename=\$rulenum
1786			debug "found ruleset: $rulename=$rulenum"
1787			if ! /sbin/devfs rule -s $rulenum delset; then
1788				_err=1
1789				break
1790			fi
1791			;;
1792		*)
1793			rulecmd="${line%%"\#*"}"
1794			# evaluate the command incase it includes
1795			# other rules
1796			if [ -n "$rulecmd" ]; then
1797				debug "adding rule ($rulecmd)"
1798				if ! eval /sbin/devfs rule -s $rulenum $rulecmd
1799				then
1800					_err=1
1801					break
1802				fi
1803			fi
1804			;;
1805		esac
1806		if [ $_err -ne 0 ]; then
1807			debug "error in $_me"
1808			break
1809		fi
1810	done } < $file
1811	case $_opts in *f*) ;; *) set +f ;; esac
1812	return $_err
1813}
1814
1815# devfs_init_rulesets
1816#	Initializes rulesets from configuration files. Returns
1817#	non-zero if there was an error.
1818#
1819devfs_init_rulesets()
1820{
1821	local file _me
1822	_me="devfs_init_rulesets"
1823
1824	# Go through this only once
1825	if [ -n "$devfs_rulesets_init" ]; then
1826		debug "$_me: devfs rulesets already initialized"
1827		return
1828	fi
1829	for file in $devfs_rulesets; do
1830		if ! devfs_rulesets_from_file $file; then
1831			warn "$_me: could not read rules from $file"
1832			return 1
1833		fi
1834	done
1835	devfs_rulesets_init=1
1836	debug "$_me: devfs rulesets initialized"
1837	return 0
1838}
1839
1840# devfs_set_ruleset ruleset [dir]
1841#	Sets the default ruleset of dir to ruleset. The ruleset argument
1842#	must be a ruleset name as specified in devfs.rules(5) file.
1843#	Returns non-zero if it could not set it successfully.
1844#
1845devfs_set_ruleset()
1846{
1847	local devdir rs _me
1848	[ -n "$1" ] && eval rs=\$$1 || rs=
1849	[ -n "$2" ] && devdir="-m "$2"" || devdir=
1850	_me="devfs_set_ruleset"
1851
1852	if [ -z "$rs" ]; then
1853		warn "$_me: you must specify a ruleset number"
1854		return 1
1855	fi
1856	debug "$_me: setting ruleset ($rs) on mount-point (${devdir#-m })"
1857	if ! /sbin/devfs $devdir ruleset $rs; then
1858		warn "$_me: unable to set ruleset $rs to ${devdir#-m }"
1859		return 1
1860	fi
1861	return 0
1862}
1863
1864# devfs_apply_ruleset ruleset [dir]
1865#	Apply ruleset number $ruleset to the devfs mountpoint $dir.
1866#	The ruleset argument must be a ruleset name as specified
1867#	in a devfs.rules(5) file.  Returns 0 on success or non-zero
1868#	if it could not apply the ruleset.
1869#
1870devfs_apply_ruleset()
1871{
1872	local devdir rs _me
1873	[ -n "$1" ] && eval rs=\$$1 || rs=
1874	[ -n "$2" ] && devdir="-m "$2"" || devdir=
1875	_me="devfs_apply_ruleset"
1876
1877	if [ -z "$rs" ]; then
1878		warn "$_me: you must specify a ruleset"
1879		return 1
1880	fi
1881	debug "$_me: applying ruleset ($rs) to mount-point (${devdir#-m })"
1882	if ! /sbin/devfs $devdir rule -s $rs applyset; then
1883		warn "$_me: unable to apply ruleset $rs to ${devdir#-m }"
1884		return 1
1885	fi
1886	return 0
1887}
1888
1889# devfs_domount dir [ruleset]
1890#	Mount devfs on dir. If ruleset is specified it is set
1891#	on the mount-point. It must also be a ruleset name as specified
1892#	in a devfs.rules(5) file. Returns 0 on success.
1893#
1894devfs_domount()
1895{
1896	local devdir rs _me
1897	devdir="$1"
1898	[ -n "$2" ] && rs=$2 || rs=
1899	_me="devfs_domount()"
1900
1901	if [ -z "$devdir" ]; then
1902		warn "$_me: you must specify a mount-point"
1903		return 1
1904	fi
1905	debug "$_me: mount-point is ($devdir), ruleset is ($rs)"
1906	if ! mount -t devfs dev "$devdir"; then
1907		warn "$_me: Unable to mount devfs on $devdir"
1908		return 1
1909	fi
1910	if [ -n "$rs" ]; then
1911		devfs_init_rulesets
1912		devfs_set_ruleset $rs $devdir
1913		devfs -m $devdir rule applyset
1914	fi
1915	return 0
1916}
1917
1918# Provide a function for normalizing the mounting of memory
1919# filesystems.  This should allow the rest of the code here to remain
1920# as close as possible between 5-current and 4-stable.
1921#   $1 = size
1922#   $2 = mount point
1923#   $3 = (optional) extra mdmfs flags
1924mount_md()
1925{
1926	if [ -n "$3" ]; then
1927		flags="$3"
1928	fi
1929	/sbin/mdmfs $flags -s $1 ${mfs_type} $2
1930}
1931
1932# Code common to scripts that need to load a kernel module
1933# if it isn't in the kernel yet. Syntax:
1934#   load_kld [-e regex] [-m module] file
1935# where -e or -m chooses the way to check if the module
1936# is already loaded:
1937#   regex is egrep'd in the output from `kldstat -v',
1938#   module is passed to `kldstat -m'.
1939# The default way is as though `-m file' were specified.
1940load_kld()
1941{
1942	local _loaded _mod _opt _re
1943
1944	while getopts "e:m:" _opt; do
1945		case "$_opt" in
1946		e) _re="$OPTARG" ;;
1947		m) _mod="$OPTARG" ;;
1948		*) err 3 'USAGE: load_kld [-e regex] [-m module] file' ;;
1949		esac
1950	done
1951	shift $(($OPTIND - 1))
1952	if [ $# -ne 1 ]; then
1953		err 3 'USAGE: load_kld [-e regex] [-m module] file'
1954	fi
1955	_mod=${_mod:-$1}
1956	_loaded=false
1957	if [ -n "$_re" ]; then
1958		if kldstat -v | egrep -q -e "$_re"; then
1959			_loaded=true
1960		fi
1961	else
1962		if kldstat -q -m "$_mod"; then
1963			_loaded=true
1964		fi
1965	fi
1966	if ! $_loaded; then
1967		if ! kldload "$1"; then
1968			warn "Unable to load kernel module $1"
1969			return 1
1970		else
1971			info "$1 kernel module loaded."
1972			if [ -f "/etc/sysctl.kld.d/$1.conf" ]; then
1973				sysctl -f "/etc/sysctl.kld.d/$1.conf"
1974			fi
1975		fi
1976	else
1977		debug "load_kld: $1 kernel module already loaded."
1978	fi
1979	return 0
1980}
1981
1982# ltr str src dst [var]
1983#	Change every $src in $str to $dst.
1984#	Useful when /usr is not yet mounted and we cannot use tr(1), sed(1) nor
1985#	awk(1). If var is non-NULL, set it to the result.
1986ltr()
1987{
1988	local _str _src _dst _out _com _var
1989	_str="$1"
1990	_src="$2"
1991	_dst="$3"
1992	_var="$4"
1993	_out=""
1994
1995	local IFS="${_src}"
1996	for _com in ${_str}; do
1997		if [ -z "${_out}" ]; then
1998			_out="${_com}"
1999		else
2000			_out="${_out}${_dst}${_com}"
2001		fi
2002	done
2003	if [ -n "${_var}" ]; then
2004		setvar "${_var}" "${_out}"
2005	else
2006		echo "${_out}"
2007	fi
2008}
2009
2010# Creates a list of providers for GELI encryption.
2011geli_make_list()
2012{
2013	local devices devices2
2014	local provider mountpoint type options rest
2015
2016	# Create list of GELI providers from fstab.
2017	while read provider mountpoint type options rest ; do
2018		case ":${options}" in
2019		:*noauto*)
2020			noauto=yes
2021			;;
2022		*)
2023			noauto=no
2024			;;
2025		esac
2026
2027		case ":${provider}" in
2028		:#*)
2029			continue
2030			;;
2031		*.eli)
2032			# Skip swap devices.
2033			if [ "${type}" = "swap" -o "${options}" = "sw" -o "${noauto}" = "yes" ]; then
2034				continue
2035			fi
2036			devices="${devices} ${provider}"
2037			;;
2038		esac
2039	done < /etc/fstab
2040
2041	# Append providers from geli_devices.
2042	devices="${devices} ${geli_devices}"
2043
2044	for provider in ${devices}; do
2045		provider=${provider%.eli}
2046		provider=${provider#/dev/}
2047		devices2="${devices2} ${provider}"
2048	done
2049
2050	echo ${devices2}
2051}
2052
2053# Originally, root mount hold had to be released before mounting
2054# the root filesystem.  This delayed the boot, so it was changed
2055# to only wait if the root device isn't readily available.  This
2056# can result in rc scripts executing before all the devices - such
2057# as graid(8), or USB disks - can be accessed.  This function can
2058# be used to explicitly wait for root mount holds to be released.
2059root_hold_wait()
2060{
2061	local wait waited holders
2062
2063	waited=0
2064	while true; do
2065		holders="$(sysctl -n vfs.root_mount_hold)"
2066		if [ -z "${holders}" ]; then
2067			break;
2068		fi
2069		if [ ${waited} -eq 0 ]; then
2070			echo -n "Waiting ${root_hold_delay}s" \
2071			"for the root mount holders: ${holders}"
2072		else
2073			echo -n .
2074		fi
2075		if [ ${waited} -ge ${root_hold_delay} ]; then
2076			echo
2077			break
2078		fi
2079		sleep 1
2080		waited=$(($waited + 1))
2081	done
2082}
2083
2084# Find scripts in local_startup directories that use the old syntax
2085#
2086find_local_scripts_old() {
2087	zlist=''
2088	slist=''
2089	for dir in ${local_startup}; do
2090		if [ -d "${dir}" ]; then
2091			for file in ${dir}/[0-9]*.sh; do
2092				grep '^# PROVIDE:' $file >/dev/null 2>&1 &&
2093				    continue
2094				zlist="$zlist $file"
2095			done
2096			for file in ${dir}/[!0-9]*.sh; do
2097				grep '^# PROVIDE:' $file >/dev/null 2>&1 &&
2098				    continue
2099				slist="$slist $file"
2100			done
2101		fi
2102	done
2103}
2104
2105find_local_scripts_new() {
2106	local_rc=''
2107	for dir in ${local_startup}; do
2108		if [ -d "${dir}" ]; then
2109			for file in `grep -l '^# PROVIDE:' ${dir}/* 2>/dev/null`; do
2110				case "$file" in
2111				*.sample|*.pkgsave) ;;
2112				*)	if [ -x "$file" ]; then
2113						local_rc="${local_rc} ${file}"
2114					fi
2115					;;
2116				esac
2117			done
2118		fi
2119	done
2120}
2121
2122find_system_scripts() {
2123	system_rc=''
2124	for file in /etc/rc.d/*; do
2125		case "${file##*/}" in
2126		*.pkgsave) ;;
2127		*)	if [ -x "$file" ]; then
2128				system_rc="${system_rc} ${file}"
2129			fi
2130			;;
2131		esac
2132	done
2133}
2134
2135# check_required_{before|after} command
2136#	Check for things required by the command before and after its precmd,
2137#	respectively.  The two separate functions are needed because some
2138#	conditions should prevent precmd from being run while other things
2139#	depend on precmd having already been run.
2140#
2141check_required_before()
2142{
2143	local _f
2144
2145	case "$1" in
2146	start)
2147		for _f in $required_vars; do
2148			if ! checkyesno $_f; then
2149				warn "\$${_f} is not enabled."
2150				if [ -z "$rc_force" ]; then
2151					return 1
2152				fi
2153			fi
2154		done
2155
2156		for _f in $required_dirs; do
2157			if [ ! -d "${_f}/." ]; then
2158				warn "${_f} is not a directory."
2159				if [ -z "$rc_force" ]; then
2160					return 1
2161				fi
2162			fi
2163		done
2164
2165		for _f in $required_files; do
2166			if [ ! -r "${_f}" ]; then
2167				warn "${_f} is not readable."
2168				if [ -z "$rc_force" ]; then
2169					return 1
2170				fi
2171			fi
2172		done
2173		;;
2174	esac
2175
2176	return 0
2177}
2178
2179check_required_after()
2180{
2181	local _f _args
2182
2183	case "$1" in
2184	start)
2185		for _f in $required_modules; do
2186			case "${_f}" in
2187				*~*)	_args="-e ${_f#*~} ${_f%%~*}" ;;
2188				*:*)	_args="-m ${_f#*:} ${_f%%:*}" ;;
2189				*)	_args="${_f}" ;;
2190			esac
2191			if ! load_kld ${_args}; then
2192				if [ -z "$rc_force" ]; then
2193					return 1
2194				fi
2195			fi
2196		done
2197		;;
2198	esac
2199
2200	return 0
2201}
2202
2203# check_jail mib
2204#	Return true if security.jail.$mib exists and set to 1.
2205
2206check_jail()
2207{
2208	local _mib _v
2209
2210	_mib=$1
2211	if _v=$(${SYSCTL_N} "security.jail.$_mib" 2> /dev/null); then
2212		case $_v in
2213		1)	return 0;;
2214		esac
2215	fi
2216	return 1
2217}
2218
2219# check_kern_features mib
2220#	Return existence of kern.features.* sysctl MIB as true or
2221#	false.  The result will be cached in $_rc_cache_kern_features_
2222#	namespace.  "0" means the kern.features.X exists.
2223
2224check_kern_features()
2225{
2226	local _v
2227
2228	[ -n "$1" ] || return 1;
2229	eval _v=\$_rc_cache_kern_features_$1
2230	[ -n "$_v" ] && return "$_v";
2231
2232	if ${SYSCTL_N} kern.features.$1 > /dev/null 2>&1; then
2233		eval _rc_cache_kern_features_$1=0
2234		return 0
2235	else
2236		eval _rc_cache_kern_features_$1=1
2237		return 1
2238	fi
2239}
2240
2241# check_namevarlist var
2242#	Return "0" if ${name}_var is reserved in rc.subr.
2243
2244_rc_namevarlist="program chroot chdir env flags fib nice user group groups prepend setup"
2245check_namevarlist()
2246{
2247	local _v
2248
2249	for _v in $_rc_namevarlist; do
2250	case $1 in
2251	$_v)	return 0 ;;
2252	esac
2253	done
2254
2255	return 1
2256}
2257
2258# _echoonce var msg mode
2259#	mode=0: Echo $msg if ${$var} is empty.
2260#	        After doing echo, a string is set to ${$var}.
2261#
2262#	mode=1: Echo $msg if ${$var} is a string with non-zero length.
2263#
2264_echoonce()
2265{
2266	local _var _msg _mode
2267	eval _var=\$$1
2268	_msg=$2
2269	_mode=$3
2270
2271	case $_mode in
2272	1)	[ -n "$_var" ] && echo "$_msg" ;;
2273	*)	[ -z "$_var" ] && echo -n "$_msg" && eval "$1=finished" ;;
2274	esac
2275}
2276
2277# If the loader env variable rc.debug is set, turn on debugging. rc.conf will
2278# still override this, but /etc/defaults/rc.conf can't unconditionally set this
2279# since it would undo what we've done here.
2280if kenv -q rc.debug > /dev/null ; then
2281	rc_debug=YES
2282fi
2283
2284boottrace_cmd=`command -v boottrace`
2285if [ -n "$boottrace_cmd" ] && [ "`${SYSCTL_N} -q kern.boottrace.enabled`" = "1" ]; then
2286	rc_boottrace=YES
2287fi
2288