xref: /freebsd/libexec/rc/rc.subr (revision 2e3f49888ec8851bafb22011533217487764fdb0)
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", "delete" or "status", and ${rc_pid} is
1045					# not set, run:
1046					#	checkyesno ${rcvar}
1047					# and return if that failed
1048					#
1049		if [ -n "${rcvar}" -a "$rc_arg" != "rcvar" -a "$rc_arg" != "stop" \
1050		    -a "$rc_arg" != "delete" -a "$rc_arg" != "enable" \
1051		    -a "$rc_arg" != "describe" -a "$rc_arg" != "status" ] ||
1052		    [ -n "${rcvar}" -a "$rc_arg" = "stop" -a -z "${rc_pid}" ]; then
1053			if ! checkyesno ${rcvar}; then
1054				if [ -n "${rc_quiet}" ]; then
1055					return 0
1056				fi
1057				echo -n "Cannot '${rc_arg}' $name. Set ${rcvar} to "
1058				echo -n "YES in /etc/rc.conf or use 'one${rc_arg}' "
1059				echo "instead of '${rc_arg}'."
1060				return 0
1061			fi
1062		fi
1063
1064		if [ $rc_arg = "start" -a -z "$rc_fast" -a -n "$rc_pid" ]; then
1065			if [ -z "$rc_quiet" ]; then
1066				echo 1>&2 "${name} already running? " \
1067				    "(pid=$rc_pid)."
1068			fi
1069			return 1
1070		fi
1071
1072					# if there's a custom ${XXX_cmd},
1073					# run that instead of the default
1074					#
1075		eval _cmd=\$${rc_arg}_cmd \
1076		     _precmd=\$${rc_arg}_precmd \
1077		     _postcmd=\$${rc_arg}_postcmd
1078
1079		if [ -n "$_cmd" ]; then
1080			if [ -n "$_env" ]; then
1081				eval "export -- $_env"
1082			fi
1083			_run_rc_precmd || return 1
1084			_run_rc_doit "$_cpusetcmd $_cmd $rc_extra_args" || return 1
1085			_run_rc_postcmd
1086			return $_return
1087		fi
1088
1089		case "$rc_arg" in	# default operations...
1090
1091		describe)
1092			if [ -n "$desc" ]; then
1093				echo "$desc"
1094			fi
1095			;;
1096
1097		extracommands)
1098			echo "$extra_commands"
1099			;;
1100
1101		enable)
1102			_out=$(/usr/sbin/sysrc -vs "$name" "$rcvar=YES") &&
1103				echo "$name enabled in ${_out%%:*}"
1104			;;
1105
1106		disable)
1107			_out=$(/usr/sbin/sysrc -vs "$name" "$rcvar=NO") &&
1108				echo "$name disabled in ${_out%%:*}"
1109			;;
1110
1111		delete)
1112			_files=
1113			for _file in $(sysrc -lEs "$name"); do
1114				_out=$(sysrc -Fif $_file "$rcvar") && _files="$_files $_file"
1115			done
1116			/usr/sbin/sysrc -x "$rcvar" && echo "$rcvar deleted in ${_files# }"
1117				# delete file in rc.conf.d if desired and empty.
1118			checkyesno service_delete_empty || _files=
1119			for _file in $_files; do
1120				[ "$_file" = "${_file#*/rc.conf.d/}" ] && continue
1121				[ $(/usr/bin/stat -f%z $_file) -gt 0 ] && continue
1122				/bin/rm "$_file" && echo "Empty file $_file removed"
1123			done
1124			;;
1125
1126		status)
1127			_run_rc_precmd || return 1
1128			if [ -n "$rc_pid" ]; then
1129				echo "${name} is running as pid $rc_pid."
1130			else
1131				echo "${name} is not running."
1132				return 1
1133			fi
1134			_run_rc_postcmd
1135			;;
1136
1137		start)
1138			if [ ! -x "${_chroot}${_chroot:+/}${command}" ]; then
1139				warn "run_rc_command: cannot run $command"
1140				return 1
1141			fi
1142
1143			if ! _run_rc_precmd; then
1144				warn "failed precmd routine for ${name}"
1145				return 1
1146			fi
1147
1148					# setup the full command to run
1149					#
1150			startmsg "Starting ${name}."
1151			if [ -n "$_chroot" ]; then
1152				_cd=
1153				_doit="\
1154${_nice:+nice -n $_nice }\
1155$_cpusetcmd \
1156${_fib:+setfib -F $_fib }\
1157${_env:+env $_env }\
1158chroot ${_user:+-u $_user }${_group:+-g $_group }${_groups:+-G $_groups }\
1159$_chroot $command $rc_flags $command_args"
1160			else
1161				_cd="${_chdir:+cd $_chdir && }"
1162				_doit="\
1163${_fib:+setfib -F $_fib }\
1164${_env:+env $_env }\
1165$_cpusetcmd $command $rc_flags $command_args"
1166				if [ -n "$_user" ]; then
1167				    _doit="su -m $_user -c 'sh -c \"$_doit\"'"
1168				fi
1169				if [ -n "$_nice" ]; then
1170					if [ -z "$_user" ]; then
1171						_doit="sh -c \"$_doit\""
1172					fi
1173					_doit="nice -n $_nice $_doit"
1174				fi
1175				if [ -n "$_prepend" ]; then
1176					_doit="$_prepend $_doit"
1177				fi
1178			fi
1179
1180			if [ -n "$_setup" ]; then
1181				if ! _run_rc_doit "$_setup"; then
1182					warn "failed to setup ${name}"
1183				fi
1184			fi
1185
1186					# Prepend default limits
1187			_doit="$_cd limits -C $_login_class $_limits $_doit"
1188
1189					# run the full command
1190					#
1191			if ! _run_rc_doit "$_doit"; then
1192				warn "failed to start ${name}"
1193				return 1
1194			fi
1195
1196					# finally, run postcmd
1197					#
1198			_run_rc_postcmd
1199			;;
1200
1201		stop)
1202			if [ -z "$rc_pid" ]; then
1203				[ -n "$rc_fast" ] && return 0
1204				_run_rc_notrunning
1205				return 1
1206			fi
1207
1208			_run_rc_precmd || return 1
1209
1210					# send the signal to stop
1211					#
1212			echo "Stopping ${name}."
1213			_doit=$(_run_rc_killcmd "${sig_stop:-TERM}")
1214			_run_rc_doit "$_doit" || return 1
1215
1216					# wait for the command to exit,
1217					# and run postcmd.
1218			wait_for_pids $rc_pid
1219
1220			_run_rc_postcmd
1221			;;
1222
1223		reload)
1224			if [ -z "$rc_pid" ]; then
1225				_run_rc_notrunning
1226				return 1
1227			fi
1228
1229			_run_rc_precmd || return 1
1230
1231			_doit=$(_run_rc_killcmd "${sig_reload:-HUP}")
1232			_run_rc_doit "$_doit" || return 1
1233
1234			_run_rc_postcmd
1235			;;
1236
1237		restart)
1238					# prevent restart being called more
1239					# than once by any given script
1240					#
1241			if ${_rc_restart_done:-false}; then
1242				return 0
1243			fi
1244			_rc_restart_done=true
1245
1246			_run_rc_precmd || return 1
1247
1248			# run those in a subshell to keep global variables
1249			( run_rc_command ${_rc_prefix}stop $rc_extra_args )
1250			( run_rc_command ${_rc_prefix}start $rc_extra_args )
1251			_return=$?
1252			[ $_return -ne 0 ] && [ -z "$rc_force" ] && return 1
1253
1254			_run_rc_postcmd
1255			;;
1256
1257		poll)
1258			_run_rc_precmd || return 1
1259			if [ -n "$rc_pid" ]; then
1260				wait_for_pids $rc_pid
1261			fi
1262			_run_rc_postcmd
1263			;;
1264
1265		rcvar)
1266			echo -n "# $name"
1267			if [ -n "$desc" ]; then
1268				echo " : $desc"
1269			else
1270				echo ""
1271			fi
1272			echo "#"
1273			# Get unique vars in $rcvar $rcvars
1274			for _v in $rcvar $rcvars; do
1275				case $v in
1276				$_v\ *|\ *$_v|*\ $_v\ *) ;;
1277				*)	v="${v# } $_v" ;;
1278				esac
1279			done
1280
1281			# Display variables.
1282			for _v in $v; do
1283				if [ -z "$_v" ]; then
1284					continue
1285				fi
1286
1287				eval _desc=\$${_v}_desc
1288				eval _defval=\$${_v}_defval
1289				_h="-"
1290
1291				eval echo \"$_v=\\\"\$$_v\\\"\"
1292				# decode multiple lines of _desc
1293				while [ -n "$_desc" ]; do
1294					case $_desc in
1295					*^^*)
1296						echo "# $_h ${_desc%%^^*}"
1297						_desc=${_desc#*^^}
1298						_h=" "
1299						;;
1300					*)
1301						echo "# $_h ${_desc}"
1302						break
1303						;;
1304					esac
1305				done
1306				echo "#   (default: \"$_defval\")"
1307			done
1308			echo ""
1309			;;
1310
1311		*)
1312			rc_usage $_keywords
1313			;;
1314
1315		esac
1316
1317		# Apply protect(1) to the PID if ${name}_oomprotect is set.
1318		case "$rc_arg" in
1319		start)
1320			# We cannot use protect(1) inside jails.
1321			if [ -n "$_oomprotect" ] && [ -f "${PROTECT}" ] &&
1322			    [ "$(sysctl -n security.jail.jailed)" -eq 0 ]; then
1323				[ -z "${rc_pid}" ] && eval $_pidcmd
1324				case $_oomprotect in
1325				[Aa][Ll][Ll])
1326					${PROTECT} -d -i -p ${rc_pid}
1327					;;
1328				[Yy][Ee][Ss])
1329					${PROTECT} -p ${rc_pid}
1330					;;
1331				esac
1332			fi
1333		;;
1334		esac
1335
1336		return $_return
1337	done
1338
1339	echo 1>&2 "$0: unknown directive '$rc_arg'."
1340	rc_usage $_keywords
1341	# not reached
1342}
1343
1344#
1345# Helper functions for run_rc_command: common code.
1346# They use such global variables besides the exported rc_* ones:
1347#
1348#	name	       R/W
1349#	------------------
1350#	_precmd		R
1351#	_postcmd	R
1352#	_return		W
1353#
1354_run_rc_precmd()
1355{
1356	check_required_before "$rc_arg" || return 1
1357
1358	if [ -n "$_precmd" ]; then
1359		debug "run_rc_command: ${rc_arg}_precmd: $_precmd $rc_extra_args"
1360		eval "$_precmd $rc_extra_args"
1361		_return=$?
1362
1363		# If precmd failed and force isn't set, request exit.
1364		if [ $_return -ne 0 ] && [ -z "$rc_force" ]; then
1365			return 1
1366		fi
1367	fi
1368
1369	check_required_after "$rc_arg" || return 1
1370
1371	return 0
1372}
1373
1374_run_rc_postcmd()
1375{
1376	if [ -n "$_postcmd" ]; then
1377		debug "run_rc_command: ${rc_arg}_postcmd: $_postcmd $rc_extra_args"
1378		eval "$_postcmd $rc_extra_args"
1379		_return=$?
1380	fi
1381	return 0
1382}
1383
1384_run_rc_doit()
1385{
1386	local _m
1387
1388	debug "run_rc_command: doit: $*"
1389	_m=$(umask)
1390	${_umask:+umask ${_umask}}
1391	eval "$@"
1392	_return=$?
1393	umask ${_m}
1394
1395	# If command failed and force isn't set, request exit.
1396	if [ $_return -ne 0 ] && [ -z "$rc_force" ]; then
1397		return 1
1398	fi
1399
1400	return 0
1401}
1402
1403_run_rc_notrunning()
1404{
1405	local _pidmsg
1406
1407	if [ -n "$pidfile" ]; then
1408		_pidmsg=" (check $pidfile)."
1409	else
1410		_pidmsg=
1411	fi
1412	echo 1>&2 "${name} not running?${_pidmsg}"
1413}
1414
1415_run_rc_killcmd()
1416{
1417	local _cmd
1418
1419	_cmd="kill -$1 $rc_pid"
1420	if [ -n "$_user" ]; then
1421		_cmd="su -m ${_user} -c 'sh -c \"${_cmd}\"'"
1422	fi
1423	echo "$_cmd"
1424}
1425
1426#
1427# run_rc_script file arg
1428#	Start the script `file' with `arg', and correctly handle the
1429#	return value from the script.
1430#	If `file' ends with `.sh' and lives in /etc/rc.d, ignore it as it's
1431#	an old-style startup file.
1432#	If `file' ends with `.sh' and does not live in /etc/rc.d, it's sourced
1433#	into the current environment if $rc_fast_and_loose is set; otherwise
1434#	it is run as a child process.
1435#	If `file' appears to be a backup or scratch file, ignore it.
1436#	Otherwise if it is executable run as a child process.
1437#
1438run_rc_script()
1439{
1440	_file=$1
1441	_arg=$2
1442	if [ -z "$_file" -o -z "$_arg" ]; then
1443		err 3 'USAGE: run_rc_script file arg'
1444	fi
1445
1446	unset	name command command_args command_interpreter \
1447		extra_commands pidfile procname \
1448		rcvar rcvars rcvars_obsolete required_dirs required_files \
1449		required_vars
1450	eval unset ${_arg}_cmd ${_arg}_precmd ${_arg}_postcmd
1451
1452	rc_service="$_file"
1453	case "$_file" in
1454	/etc/rc.d/*.sh)			# no longer allowed in the base
1455		warn "Ignoring old-style startup script $_file"
1456		;;
1457	*[~#]|*.OLD|*.bak|*.orig|*,v)	# scratch file; skip
1458		warn "Ignoring scratch file $_file"
1459		;;
1460	*)				# run in subshell
1461		if [ -x $_file ]; then
1462			if [ -n "$rc_boottrace" ]; then
1463				boottrace_fn "$_file" "$_arg"
1464			elif [ -n "$rc_fast_and_loose" ]; then
1465				set $_arg; . $_file
1466			else
1467				( trap "echo Script $_file interrupted >&2 ; kill -QUIT $$" 3
1468				  trap "echo Script $_file interrupted >&2 ; exit 1" 2
1469				  trap "echo Script $_file running >&2" 29
1470				  set $_arg; . $_file )
1471			fi
1472		fi
1473		;;
1474	esac
1475}
1476
1477boottrace_fn()
1478{
1479	local _file _arg
1480	_file=$1
1481	_arg=$2
1482
1483	if [ -n "$rc_fast_and_loose" ]; then
1484		boottrace_sysctl "$_file start"
1485		set $_arg; . $_file
1486		boottrace_sysctl "$_file done"
1487	else
1488		$boottrace_cmd "$_file" "$_arg"
1489	fi
1490}
1491
1492boottrace_sysctl()
1493{
1494	${SYSCTL} kern.boottrace.boottrace="$1"
1495}
1496
1497#
1498# load_rc_config [service]
1499#	Source in the configuration file(s) for a given service.
1500#	If no service is specified, only the global configuration
1501#	file(s) will be loaded.
1502#
1503load_rc_config()
1504{
1505	local _name _rcvar_val _var _defval _v _msg _new _d
1506	_name=$1
1507
1508	if ${_rc_conf_loaded:-false}; then
1509		:
1510	else
1511		if [ -r /etc/defaults/rc.conf ]; then
1512			debug "Sourcing /etc/defaults/rc.conf"
1513			. /etc/defaults/rc.conf
1514			source_rc_confs
1515		elif [ -r /etc/rc.conf ]; then
1516			debug "Sourcing /etc/rc.conf (/etc/defaults/rc.conf doesn't exist)."
1517			. /etc/rc.conf
1518		fi
1519		_rc_conf_loaded=true
1520	fi
1521
1522	# If a service name was specified, attempt to load
1523	# service-specific configuration
1524	if [ -n "$_name" ] ; then
1525		for _d in /etc ${local_startup}; do
1526			_d=${_d%/rc.d}
1527			if [ -f ${_d}/rc.conf.d/"$_name" ]; then
1528				debug "Sourcing ${_d}/rc.conf.d/$_name"
1529				. ${_d}/rc.conf.d/"$_name"
1530			elif [ -d ${_d}/rc.conf.d/"$_name" ] ; then
1531				local _rc
1532				for _rc in ${_d}/rc.conf.d/"$_name"/* ; do
1533					if [ -f "$_rc" ] ; then
1534						debug "Sourcing $_rc"
1535						. "$_rc"
1536					fi
1537				done
1538			fi
1539		done
1540	fi
1541
1542	# Set defaults if defined.
1543	for _var in $rcvar $rcvars; do
1544		eval _defval=\$${_var}_defval
1545		if [ -n "$_defval" ]; then
1546			eval : \${$_var:=\$${_var}_defval}
1547		fi
1548	done
1549
1550	# check obsolete rc.conf variables
1551	for _var in $rcvars_obsolete; do
1552		eval _v=\$$_var
1553		eval _msg=\$${_var}_obsolete_msg
1554		eval _new=\$${_var}_newvar
1555		case $_v in
1556		"")
1557			;;
1558		*)
1559			if [ -z "$_new" ]; then
1560				_msg="Ignored."
1561			else
1562				eval $_new=\"\$$_var\"
1563				if [ -z "$_msg" ]; then
1564					_msg="Use \$$_new instead."
1565				fi
1566			fi
1567			warn "\$$_var is obsolete.  $_msg"
1568			;;
1569		esac
1570	done
1571}
1572
1573#
1574# load_rc_config_var name var
1575#	Read the rc.conf(5) var for name and set in the
1576#	current shell, using load_rc_config in a subshell to prevent
1577#	unwanted side effects from other variable assignments.
1578#
1579load_rc_config_var()
1580{
1581	if [ $# -ne 2 ]; then
1582		err 3 'USAGE: load_rc_config_var name var'
1583	fi
1584	eval $(eval '(
1585		load_rc_config '$1' >/dev/null;
1586		if [ -n "${'$2'}" -o "${'$2'-UNSET}" != "UNSET" ]; then
1587			echo '$2'=\'\''${'$2'}\'\'';
1588		fi
1589	)' )
1590}
1591
1592#
1593# rc_usage commands
1594#	Print a usage string for $0, with `commands' being a list of
1595#	valid commands.
1596#
1597rc_usage()
1598{
1599	echo -n 1>&2 "Usage: $0 [fast|force|one|quiet]("
1600
1601	_sep=
1602	for _elem; do
1603		echo -n 1>&2 "$_sep$_elem"
1604		_sep="|"
1605	done
1606	echo 1>&2 ")"
1607	exit 1
1608}
1609
1610#
1611# err exitval message
1612#	Display message to stderr and log to the syslog, and exit with exitval.
1613#
1614err()
1615{
1616	exitval=$1
1617	shift
1618
1619	if [ -x /usr/bin/logger ]; then
1620		logger "$0: ERROR: $*"
1621	fi
1622	echo 1>&2 "$0: ERROR: $*"
1623	exit $exitval
1624}
1625
1626#
1627# warn message
1628#	Display message to stderr and log to the syslog.
1629#
1630warn()
1631{
1632	if [ -x /usr/bin/logger ]; then
1633		logger "$0: WARNING: $*"
1634	fi
1635	echo 1>&2 "$0: WARNING: $*"
1636}
1637
1638#
1639# info message
1640#	Display informational message to stdout and log to syslog.
1641#
1642info()
1643{
1644	case ${rc_info} in
1645	[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
1646		if [ -x /usr/bin/logger ]; then
1647			logger "$0: INFO: $*"
1648		fi
1649		echo "$0: INFO: $*"
1650		;;
1651	esac
1652}
1653
1654#
1655# debug message
1656#	If debugging is enabled in rc.conf output message to stderr.
1657#	BEWARE that you don't call any subroutine that itself calls this
1658#	function.
1659#
1660debug()
1661{
1662	case ${rc_debug} in
1663	[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
1664		if [ -x /usr/bin/logger ]; then
1665			logger "$0: DEBUG: $*"
1666		fi
1667		echo 1>&2 "$0: DEBUG: $*"
1668		;;
1669	esac
1670}
1671
1672#
1673# backup_file action file cur backup
1674#	Make a backup copy of `file' into `cur', and save the previous
1675#	version of `cur' as `backup'.
1676#
1677#	The `action' keyword can be one of the following:
1678#
1679#	add		`file' is now being backed up (and is possibly
1680#			being reentered into the backups system).  `cur'
1681#			is created.
1682#
1683#	update		`file' has changed and needs to be backed up.
1684#			If `cur' exists, it is copied to `back'
1685#			and then `file' is copied to `cur'.
1686#
1687#	remove		`file' is no longer being tracked by the backups
1688#			system.  `cur' is moved `back'.
1689#
1690#
1691backup_file()
1692{
1693	_action=$1
1694	_file=$2
1695	_cur=$3
1696	_back=$4
1697
1698	case $_action in
1699	add|update)
1700		if [ -f $_cur ]; then
1701			cp -p $_cur $_back
1702		fi
1703		cp -p $_file $_cur
1704		chown root:wheel $_cur
1705		;;
1706	remove)
1707		mv -f $_cur $_back
1708		;;
1709	esac
1710}
1711
1712# make_symlink src link
1713#	Make a symbolic link 'link' to src from basedir. If the
1714#	directory in which link is to be created does not exist
1715#	a warning will be displayed and an error will be returned.
1716#	Returns 0 on success, 1 otherwise.
1717#
1718make_symlink()
1719{
1720	local src link linkdir _me
1721	src="$1"
1722	link="$2"
1723	linkdir="`dirname $link`"
1724	_me="make_symlink()"
1725
1726	if [ -z "$src" -o -z "$link" ]; then
1727		warn "$_me: requires two arguments."
1728		return 1
1729	fi
1730	if [ ! -d "$linkdir" ]; then
1731		warn "$_me: the directory $linkdir does not exist."
1732		return 1
1733	fi
1734	if ! ln -sf $src $link; then
1735		warn "$_me: unable to make a symbolic link from $link to $src"
1736		return 1
1737	fi
1738	return 0
1739}
1740
1741# devfs_rulesets_from_file file
1742#	Reads a set of devfs commands from file, and creates
1743#	the specified rulesets with their rules. Returns non-zero
1744#	if there was an error.
1745#
1746devfs_rulesets_from_file()
1747{
1748	local file _err _me _opts
1749	file="$1"
1750	_me="devfs_rulesets_from_file"
1751	_err=0
1752
1753	if [ -z "$file" ]; then
1754		warn "$_me: you must specify a file"
1755		return 1
1756	fi
1757	if [ ! -e "$file" ]; then
1758		debug "$_me: no such file ($file)"
1759		return 0
1760	fi
1761
1762	# Disable globbing so that the rule patterns are not expanded
1763	# by accident with matching filesystem entries.
1764	_opts=$-; set -f
1765
1766	debug "reading rulesets from file ($file)"
1767	{ while read line
1768	do
1769		case $line in
1770		\#*)
1771			continue
1772			;;
1773		\[*\]*)
1774			rulenum=`expr "$line" : "\[.*=\([0-9]*\)\]"`
1775			if [ -z "$rulenum" ]; then
1776				warn "$_me: cannot extract rule number ($line)"
1777				_err=1
1778				break
1779			fi
1780			rulename=`expr "$line" : "\[\(.*\)=[0-9]*\]"`
1781			if [ -z "$rulename" ]; then
1782				warn "$_me: cannot extract rule name ($line)"
1783				_err=1
1784				break;
1785			fi
1786			eval $rulename=\$rulenum
1787			debug "found ruleset: $rulename=$rulenum"
1788			if ! /sbin/devfs rule -s $rulenum delset; then
1789				_err=1
1790				break
1791			fi
1792			;;
1793		*)
1794			rulecmd="${line%%"\#*"}"
1795			# evaluate the command incase it includes
1796			# other rules
1797			if [ -n "$rulecmd" ]; then
1798				debug "adding rule ($rulecmd)"
1799				if ! eval /sbin/devfs rule -s $rulenum $rulecmd
1800				then
1801					_err=1
1802					break
1803				fi
1804			fi
1805			;;
1806		esac
1807		if [ $_err -ne 0 ]; then
1808			debug "error in $_me"
1809			break
1810		fi
1811	done } < $file
1812	case $_opts in *f*) ;; *) set +f ;; esac
1813	return $_err
1814}
1815
1816# devfs_init_rulesets
1817#	Initializes rulesets from configuration files. Returns
1818#	non-zero if there was an error.
1819#
1820devfs_init_rulesets()
1821{
1822	local file _me
1823	_me="devfs_init_rulesets"
1824
1825	# Go through this only once
1826	if [ -n "$devfs_rulesets_init" ]; then
1827		debug "$_me: devfs rulesets already initialized"
1828		return
1829	fi
1830	for file in $devfs_rulesets; do
1831		if ! devfs_rulesets_from_file $file; then
1832			warn "$_me: could not read rules from $file"
1833			return 1
1834		fi
1835	done
1836	devfs_rulesets_init=1
1837	debug "$_me: devfs rulesets initialized"
1838	return 0
1839}
1840
1841# devfs_set_ruleset ruleset [dir]
1842#	Sets the default ruleset of dir to ruleset. The ruleset argument
1843#	must be a ruleset name as specified in devfs.rules(5) file.
1844#	Returns non-zero if it could not set it successfully.
1845#
1846devfs_set_ruleset()
1847{
1848	local devdir rs _me
1849	[ -n "$1" ] && eval rs=\$$1 || rs=
1850	[ -n "$2" ] && devdir="-m "$2"" || devdir=
1851	_me="devfs_set_ruleset"
1852
1853	if [ -z "$rs" ]; then
1854		warn "$_me: you must specify a ruleset number"
1855		return 1
1856	fi
1857	debug "$_me: setting ruleset ($rs) on mount-point (${devdir#-m })"
1858	if ! /sbin/devfs $devdir ruleset $rs; then
1859		warn "$_me: unable to set ruleset $rs to ${devdir#-m }"
1860		return 1
1861	fi
1862	return 0
1863}
1864
1865# devfs_apply_ruleset ruleset [dir]
1866#	Apply ruleset number $ruleset to the devfs mountpoint $dir.
1867#	The ruleset argument must be a ruleset name as specified
1868#	in a devfs.rules(5) file.  Returns 0 on success or non-zero
1869#	if it could not apply the ruleset.
1870#
1871devfs_apply_ruleset()
1872{
1873	local devdir rs _me
1874	[ -n "$1" ] && eval rs=\$$1 || rs=
1875	[ -n "$2" ] && devdir="-m "$2"" || devdir=
1876	_me="devfs_apply_ruleset"
1877
1878	if [ -z "$rs" ]; then
1879		warn "$_me: you must specify a ruleset"
1880		return 1
1881	fi
1882	debug "$_me: applying ruleset ($rs) to mount-point (${devdir#-m })"
1883	if ! /sbin/devfs $devdir rule -s $rs applyset; then
1884		warn "$_me: unable to apply ruleset $rs to ${devdir#-m }"
1885		return 1
1886	fi
1887	return 0
1888}
1889
1890# devfs_domount dir [ruleset]
1891#	Mount devfs on dir. If ruleset is specified it is set
1892#	on the mount-point. It must also be a ruleset name as specified
1893#	in a devfs.rules(5) file. Returns 0 on success.
1894#
1895devfs_domount()
1896{
1897	local devdir rs _me
1898	devdir="$1"
1899	[ -n "$2" ] && rs=$2 || rs=
1900	_me="devfs_domount()"
1901
1902	if [ -z "$devdir" ]; then
1903		warn "$_me: you must specify a mount-point"
1904		return 1
1905	fi
1906	debug "$_me: mount-point is ($devdir), ruleset is ($rs)"
1907	if ! mount -t devfs dev "$devdir"; then
1908		warn "$_me: Unable to mount devfs on $devdir"
1909		return 1
1910	fi
1911	if [ -n "$rs" ]; then
1912		devfs_init_rulesets
1913		devfs_set_ruleset $rs $devdir
1914		devfs -m $devdir rule applyset
1915	fi
1916	return 0
1917}
1918
1919# Provide a function for normalizing the mounting of memory
1920# filesystems.  This should allow the rest of the code here to remain
1921# as close as possible between 5-current and 4-stable.
1922#   $1 = size
1923#   $2 = mount point
1924#   $3 = (optional) extra mdmfs flags
1925mount_md()
1926{
1927	if [ -n "$3" ]; then
1928		flags="$3"
1929	fi
1930	/sbin/mdmfs $flags -s $1 ${mfs_type} $2
1931}
1932
1933# Code common to scripts that need to load a kernel module
1934# if it isn't in the kernel yet. Syntax:
1935#   load_kld [-e regex] [-m module] file
1936# where -e or -m chooses the way to check if the module
1937# is already loaded:
1938#   regex is egrep'd in the output from `kldstat -v',
1939#   module is passed to `kldstat -m'.
1940# The default way is as though `-m file' were specified.
1941load_kld()
1942{
1943	local _loaded _mod _opt _re
1944
1945	while getopts "e:m:" _opt; do
1946		case "$_opt" in
1947		e) _re="$OPTARG" ;;
1948		m) _mod="$OPTARG" ;;
1949		*) err 3 'USAGE: load_kld [-e regex] [-m module] file' ;;
1950		esac
1951	done
1952	shift $(($OPTIND - 1))
1953	if [ $# -ne 1 ]; then
1954		err 3 'USAGE: load_kld [-e regex] [-m module] file'
1955	fi
1956	_mod=${_mod:-$1}
1957	_loaded=false
1958	if [ -n "$_re" ]; then
1959		if kldstat -v | egrep -q -e "$_re"; then
1960			_loaded=true
1961		fi
1962	else
1963		if kldstat -q -m "$_mod"; then
1964			_loaded=true
1965		fi
1966	fi
1967	if ! $_loaded; then
1968		if ! kldload "$1"; then
1969			warn "Unable to load kernel module $1"
1970			return 1
1971		else
1972			info "$1 kernel module loaded."
1973			if [ -f "/etc/sysctl.kld.d/$1.conf" ]; then
1974				sysctl -f "/etc/sysctl.kld.d/$1.conf"
1975			fi
1976		fi
1977	else
1978		debug "load_kld: $1 kernel module already loaded."
1979	fi
1980	return 0
1981}
1982
1983# ltr str src dst [var]
1984#	Change every $src in $str to $dst.
1985#	Useful when /usr is not yet mounted and we cannot use tr(1), sed(1) nor
1986#	awk(1). If var is non-NULL, set it to the result.
1987ltr()
1988{
1989	local _str _src _dst _out _com _var
1990	_str="$1"
1991	_src="$2"
1992	_dst="$3"
1993	_var="$4"
1994	_out=""
1995
1996	local IFS="${_src}"
1997	for _com in ${_str}; do
1998		if [ -z "${_out}" ]; then
1999			_out="${_com}"
2000		else
2001			_out="${_out}${_dst}${_com}"
2002		fi
2003	done
2004	if [ -n "${_var}" ]; then
2005		setvar "${_var}" "${_out}"
2006	else
2007		echo "${_out}"
2008	fi
2009}
2010
2011# Creates a list of providers for GELI encryption.
2012geli_make_list()
2013{
2014	local devices devices2
2015	local provider mountpoint type options rest
2016
2017	# Create list of GELI providers from fstab.
2018	while read provider mountpoint type options rest ; do
2019		case ":${options}" in
2020		:*noauto*)
2021			noauto=yes
2022			;;
2023		*)
2024			noauto=no
2025			;;
2026		esac
2027
2028		case ":${provider}" in
2029		:#*)
2030			continue
2031			;;
2032		*.eli)
2033			# Skip swap devices.
2034			if [ "${type}" = "swap" -o "${options}" = "sw" -o "${noauto}" = "yes" ]; then
2035				continue
2036			fi
2037			devices="${devices} ${provider}"
2038			;;
2039		esac
2040	done < /etc/fstab
2041
2042	# Append providers from geli_devices.
2043	devices="${devices} ${geli_devices}"
2044
2045	for provider in ${devices}; do
2046		provider=${provider%.eli}
2047		provider=${provider#/dev/}
2048		devices2="${devices2} ${provider}"
2049	done
2050
2051	echo ${devices2}
2052}
2053
2054# Originally, root mount hold had to be released before mounting
2055# the root filesystem.  This delayed the boot, so it was changed
2056# to only wait if the root device isn't readily available.  This
2057# can result in rc scripts executing before all the devices - such
2058# as graid(8), or USB disks - can be accessed.  This function can
2059# be used to explicitly wait for root mount holds to be released.
2060root_hold_wait()
2061{
2062	local wait waited holders
2063
2064	waited=0
2065	while true; do
2066		holders="$(sysctl -n vfs.root_mount_hold)"
2067		if [ -z "${holders}" ]; then
2068			break;
2069		fi
2070		if [ ${waited} -eq 0 ]; then
2071			echo -n "Waiting ${root_hold_delay}s" \
2072			"for the root mount holders: ${holders}"
2073		else
2074			echo -n .
2075		fi
2076		if [ ${waited} -ge ${root_hold_delay} ]; then
2077			echo
2078			break
2079		fi
2080		sleep 1
2081		waited=$(($waited + 1))
2082	done
2083}
2084
2085# Find scripts in local_startup directories that use the old syntax
2086#
2087find_local_scripts_old() {
2088	zlist=''
2089	slist=''
2090	for dir in ${local_startup}; do
2091		if [ -d "${dir}" ]; then
2092			for file in ${dir}/[0-9]*.sh; do
2093				grep '^# PROVIDE:' $file >/dev/null 2>&1 &&
2094				    continue
2095				zlist="$zlist $file"
2096			done
2097			for file in ${dir}/[!0-9]*.sh; do
2098				grep '^# PROVIDE:' $file >/dev/null 2>&1 &&
2099				    continue
2100				slist="$slist $file"
2101			done
2102		fi
2103	done
2104}
2105
2106find_local_scripts_new() {
2107	local_rc=''
2108	for dir in ${local_startup}; do
2109		if [ -d "${dir}" ]; then
2110			for file in `grep -l '^# PROVIDE:' ${dir}/* 2>/dev/null`; do
2111				case "$file" in
2112				*.sample|*.pkgsave) ;;
2113				*)	if [ -x "$file" ]; then
2114						local_rc="${local_rc} ${file}"
2115					fi
2116					;;
2117				esac
2118			done
2119		fi
2120	done
2121}
2122
2123find_system_scripts() {
2124	system_rc=''
2125	for file in /etc/rc.d/*; do
2126		case "${file##*/}" in
2127		*.pkgsave) ;;
2128		*)	if [ -x "$file" ]; then
2129				system_rc="${system_rc} ${file}"
2130			fi
2131			;;
2132		esac
2133	done
2134}
2135
2136# check_required_{before|after} command
2137#	Check for things required by the command before and after its precmd,
2138#	respectively.  The two separate functions are needed because some
2139#	conditions should prevent precmd from being run while other things
2140#	depend on precmd having already been run.
2141#
2142check_required_before()
2143{
2144	local _f
2145
2146	case "$1" in
2147	start)
2148		for _f in $required_vars; do
2149			if ! checkyesno $_f; then
2150				warn "\$${_f} is not enabled."
2151				if [ -z "$rc_force" ]; then
2152					return 1
2153				fi
2154			fi
2155		done
2156
2157		for _f in $required_dirs; do
2158			if [ ! -d "${_f}/." ]; then
2159				warn "${_f} is not a directory."
2160				if [ -z "$rc_force" ]; then
2161					return 1
2162				fi
2163			fi
2164		done
2165
2166		for _f in $required_files; do
2167			if [ ! -r "${_f}" ]; then
2168				warn "${_f} is not readable."
2169				if [ -z "$rc_force" ]; then
2170					return 1
2171				fi
2172			fi
2173		done
2174		;;
2175	esac
2176
2177	return 0
2178}
2179
2180check_required_after()
2181{
2182	local _f _args
2183
2184	case "$1" in
2185	start)
2186		for _f in $required_modules; do
2187			case "${_f}" in
2188				*~*)	_args="-e ${_f#*~} ${_f%%~*}" ;;
2189				*:*)	_args="-m ${_f#*:} ${_f%%:*}" ;;
2190				*)	_args="${_f}" ;;
2191			esac
2192			if ! load_kld ${_args}; then
2193				if [ -z "$rc_force" ]; then
2194					return 1
2195				fi
2196			fi
2197		done
2198		;;
2199	esac
2200
2201	return 0
2202}
2203
2204# check_jail mib
2205#	Return true if security.jail.$mib exists and set to 1.
2206
2207check_jail()
2208{
2209	local _mib _v
2210
2211	_mib=$1
2212	if _v=$(${SYSCTL_N} "security.jail.$_mib" 2> /dev/null); then
2213		case $_v in
2214		1)	return 0;;
2215		esac
2216	fi
2217	return 1
2218}
2219
2220# check_kern_features mib
2221#	Return existence of kern.features.* sysctl MIB as true or
2222#	false.  The result will be cached in $_rc_cache_kern_features_
2223#	namespace.  "0" means the kern.features.X exists.
2224
2225check_kern_features()
2226{
2227	local _v
2228
2229	[ -n "$1" ] || return 1;
2230	eval _v=\$_rc_cache_kern_features_$1
2231	[ -n "$_v" ] && return "$_v";
2232
2233	if ${SYSCTL_N} kern.features.$1 > /dev/null 2>&1; then
2234		eval _rc_cache_kern_features_$1=0
2235		return 0
2236	else
2237		eval _rc_cache_kern_features_$1=1
2238		return 1
2239	fi
2240}
2241
2242# check_namevarlist var
2243#	Return "0" if ${name}_var is reserved in rc.subr.
2244
2245_rc_namevarlist="program chroot chdir env flags fib nice user group groups prepend setup"
2246check_namevarlist()
2247{
2248	local _v
2249
2250	for _v in $_rc_namevarlist; do
2251	case $1 in
2252	$_v)	return 0 ;;
2253	esac
2254	done
2255
2256	return 1
2257}
2258
2259# _echoonce var msg mode
2260#	mode=0: Echo $msg if ${$var} is empty.
2261#	        After doing echo, a string is set to ${$var}.
2262#
2263#	mode=1: Echo $msg if ${$var} is a string with non-zero length.
2264#
2265_echoonce()
2266{
2267	local _var _msg _mode
2268	eval _var=\$$1
2269	_msg=$2
2270	_mode=$3
2271
2272	case $_mode in
2273	1)	[ -n "$_var" ] && echo "$_msg" ;;
2274	*)	[ -z "$_var" ] && echo -n "$_msg" && eval "$1=finished" ;;
2275	esac
2276}
2277
2278# If the loader env variable rc.debug is set, turn on debugging. rc.conf will
2279# still override this, but /etc/defaults/rc.conf can't unconditionally set this
2280# since it would undo what we've done here.
2281if kenv -q rc.debug > /dev/null ; then
2282	rc_debug=YES
2283fi
2284
2285boottrace_cmd=`command -v boottrace`
2286if [ -n "$boottrace_cmd" ] && [ "`${SYSCTL_N} -q kern.boottrace.enabled`" = "1" ]; then
2287	rc_boottrace=YES
2288fi
2289