xref: /freebsd/libexec/rc/rc.subr (revision 535af610)
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="/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" ]; 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			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