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