rc.subr revision 119170
1195534Sscottl# $NetBSD: rc.subr,v 1.49 2002/05/21 12:31:01 lukem Exp $
2195534Sscottl# $FreeBSD: head/etc/rc.subr 119170 2003-08-20 06:50:34Z mtm $
3195534Sscottl#
4195534Sscottl# Copyright (c) 1997-2002 The NetBSD Foundation, Inc.
5195534Sscottl# All rights reserved.
6195534Sscottl#
7195534Sscottl# This code is derived from software contributed to The NetBSD Foundation
8195534Sscottl# by Luke Mewburn.
9195534Sscottl#
10195534Sscottl# Redistribution and use in source and binary forms, with or without
11195534Sscottl# modification, are permitted provided that the following conditions
12195534Sscottl# are met:
13195534Sscottl# 1. Redistributions of source code must retain the above copyright
14195534Sscottl#    notice, this list of conditions and the following disclaimer.
15195534Sscottl# 2. Redistributions in binary form must reproduce the above copyright
16195534Sscottl#    notice, this list of conditions and the following disclaimer in the
17195534Sscottl#    documentation and/or other materials provided with the distribution.
18195534Sscottl# 3. All advertising materials mentioning features or use of this software
19195534Sscottl#    must display the following acknowledgement:
20195534Sscottl#        This product includes software developed by the NetBSD
21195534Sscottl#        Foundation, Inc. and its contributors.
22195534Sscottl# 4. Neither the name of The NetBSD Foundation nor the names of its
23195534Sscottl#    contributors may be used to endorse or promote products derived
24195534Sscottl#    from this software without specific prior written permission.
25195534Sscottl#
26195534Sscottl# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27195534Sscottl# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28195534Sscottl# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29195534Sscottl# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30195534Sscottl# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31195534Sscottl# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32195534Sscottl# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33195534Sscottl# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34195534Sscottl# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35195534Sscottl# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36195534Sscottl# POSSIBILITY OF SUCH DAMAGE.
37195534Sscottl#
38195534Sscottl# rc.subr
39195534Sscottl#	functions used by various rc scripts
40195534Sscottl#
41195534Sscottl
42195534Sscottl#
43195534Sscottl#	Operating System dependent/independent variables
44195534Sscottl#
45195534Sscottl
46195534SscottlSYSCTL="/sbin/sysctl"
47195534SscottlSYSCTL_N="${SYSCTL} -n"
48195534SscottlCMD_OSTYPE="${SYSCTL_N} kern.ostype"
49195534SscottlOSTYPE=`${CMD_OSTYPE}`
50195534Sscottl
51195534Sscottlcase ${OSTYPE} in
52195534SscottlFreeBSD)
53195534Sscottl	SYSCTL_W="${SYSCTL}"
54195534Sscottl	;;
55195534SscottlNetBSD)
56195534Sscottl	SYSCTL_W="${SYSCTL} -w"
57195534Sscottl	;;
58195534Sscottlesac
59195534Sscottl
60195534Sscottl#
61195534Sscottl#	functions
62195534Sscottl#	---------
63195534Sscottl
64195534Sscottl#
65195534Sscottl# set_rcvar base_var
66195534Sscottl#	Set the variable name enabling a specific service.
67195534Sscottl#	FreeBSD uses ${service}_enable, while NetBSD uses
68195534Sscottl#	just the name of the service. For example:
69195534Sscottl#	FreeBSD: sendmail_enable="YES"
70195534Sscottl#	NetBSD : sendmail="YES"
71216088Sken#	$1 - if $name is not the base to work of off, specify
72195534Sscottl#	     a different one
73195534Sscottl#
74208911Smjacobset_rcvar()
75195534Sscottl{
76195534Sscottl	if [ -z "$1" ]; then
77195534Sscottl		base_var=${name}
78195534Sscottl	else
79195534Sscottl		base_var="$1"
80195534Sscottl	fi
81195534Sscottl
82195534Sscottl	case ${OSTYPE} in
83195534Sscottl	FreeBSD)
84195534Sscottl		echo ${base_var}_enable
85195534Sscottl		;;
86195534Sscottl	NetBSD)
87195534Sscottl		echo ${base_var}
88208911Smjacob		;;
89208911Smjacob	*)
90208911Smjacob		echo 'XXX'
91208911Smjacob		;;
92208911Smjacob	esac
93208911Smjacob}
94208911Smjacob
95208911Smjacob#
96208911Smjacob# force_depend script
97208911Smjacob#	Force a service to start. Intended for use by services
98208911Smjacob#	to resolve dependency issues. It is assumed the caller
99208911Smjacob#	has check to make sure this call is necessary
100208911Smjacob#	$1 - filename of script, in /etc/rc.d, to run
101208911Smjacob#
102208911Smjacobforce_depend()
103195534Sscottl{
104195534Sscottl	_depend="$1"
105195534Sscottl
106195534Sscottl	info "${name} depends on ${_depend}, which will be forced to start."
107195534Sscottl	if ! /etc/rc.d/${_depend} forcestart ; then
108195534Sscottl		warn "Unable to force ${_depend}. It may already be running."
109195534Sscottl		return 1
110195534Sscottl	fi
111195534Sscottl	return 0
112195534Sscottl}
113195534Sscottl
114195534Sscottl#
115195534Sscottl# checkyesno var
116195534Sscottl#	Test $1 variable, and warn if not set to YES or NO.
117195534Sscottl#	Return 0 if it's "yes" (et al), nonzero otherwise.
118195534Sscottl#
119195534Sscottlcheckyesno()
120195534Sscottl{
121195534Sscottl	eval _value=\$${1}
122195534Sscottl	debug "checkyesno: $1 is set to $_value."
123195534Sscottl	case $_value in
124195534Sscottl
125198708Smav		#	"yes", "true", "on", or "1"
126198708Smav	[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
127195534Sscottl		return 0
128195534Sscottl		;;
129195534Sscottl
130195534Sscottl		#	"no", "false", "off", or "0"
131195534Sscottl	[Nn][Oo]|[Ff][Aa][Ll][Ss][Ee]|[Oo][Ff][Ff]|0)
132195534Sscottl		return 1
133195534Sscottl		;;
134195534Sscottl	*)
135208911Smjacob		warn "\$${1} is not set properly - see rc.conf(5)."
136195534Sscottl		return 1
137216088Sken		;;
138216088Sken	esac
139216088Sken}
140195534Sscottl
141195534Sscottl# reverse_list list
142195534Sscottl#	print the list in reverse order
143195534Sscottl#
144236613Smavreverse_list()
145195534Sscottl{
146195534Sscottl	_revlist=
147195534Sscottl	for _revfile in $*; do
148195534Sscottl		_revlist="$_revfile $_revlist"
149195534Sscottl	done
150195534Sscottl	echo $_revlist
151195534Sscottl}
152208911Smjacob
153195534Sscottl#
154216088Sken# mount_critical_filesystems type
155216088Sken#	Go through the list of critical filesystems as provided in
156216088Sken#	the rc.conf(5) variable $critical_filesystems_${type}, checking
157195534Sscottl#	each one to see if it is mounted, and if it is not, mounting it.
158195534Sscottl#
159195534Sscottlmount_critical_filesystems()
160195534Sscottl{
161236613Smav	eval _fslist=\$critical_filesystems_${1}
162195534Sscottl	for _fs in $_fslist; do
163195534Sscottl		mount | (
164195534Sscottl			_ismounted=no
165195534Sscottl			while read what _on on _type type; do
166195534Sscottl				if [ $on = $_fs ]; then
167195534Sscottl					_ismounted=yes
168195534Sscottl				fi
169236613Smav			done
170195534Sscottl			if [ $_ismounted = no ]; then
171195534Sscottl				mount $_fs >/dev/null 2>&1
172195534Sscottl			fi
173195534Sscottl		)
174195534Sscottl	done
175195534Sscottl}
176195534Sscottl
177195534Sscottl#
178195534Sscottl# check_pidfile pidfile procname [interpreter]
179195534Sscottl#	Parses the first line of pidfile for a PID, and ensures
180195534Sscottl#	that the process is running and matches procname.
181195534Sscottl#	Prints the matching PID upon success, nothing otherwise.
182195534Sscottl#	interpreter is optional; see _find_processes() for details.
183195534Sscottl#
184195534Sscottlcheck_pidfile()
185195534Sscottl{
186195534Sscottl	_pidfile=$1
187195534Sscottl	_procname=$2
188195534Sscottl	_interpreter=$3
189195534Sscottl	if [ -z "$_pidfile" -o -z "$_procname" ]; then
190195534Sscottl		err 3 'USAGE: check_pidfile pidfile procname [interpreter]'
191195534Sscottl	fi
192195534Sscottl	if [ ! -f $_pidfile ]; then
193195534Sscottl		debug "pid file {$_pidfile): not readable."
194195534Sscottl		return
195195534Sscottl	fi
196195534Sscottl	read _pid _junk < $_pidfile
197195534Sscottl	if [ -z "$_pid" ]; then
198195534Sscottl		debug "pid file {$_pidfile): no pid in file."
199195534Sscottl		return
200195534Sscottl	fi
201195534Sscottl	_find_processes $_procname ${_interpreter:-.} '-p '"$_pid"
202195534Sscottl}
203195534Sscottl
204195534Sscottl#
205195534Sscottl# check_process procname [interpreter]
206195534Sscottl#	Ensures that a process (or processes) named procname is running.
207195534Sscottl#	Prints a list of matching PIDs.
208195534Sscottl#	interpreter is optional; see _find_processes() for details.
209195534Sscottl#
210195534Sscottlcheck_process()
211195534Sscottl{
212195534Sscottl	_procname=$1
213195534Sscottl	_interpreter=$2
214195534Sscottl	if [ -z "$_procname" ]; then
215195534Sscottl		err 3 'USAGE: check_process procname [interpreter]'
216195534Sscottl	fi
217195534Sscottl	_find_processes $_procname ${_interpreter:-.} '-ax'
218195534Sscottl}
219195534Sscottl
220195534Sscottl#
221195534Sscottl# _find_processes procname interpreter psargs
222195534Sscottl#	Search for procname in the output of ps generated by psargs.
223195534Sscottl#	Prints the PIDs of any matching processes, space separated.
224195534Sscottl#
225195534Sscottl#	If interpreter == ".", check the following variations of procname
226195534Sscottl#	against the first word of each command:
227195534Sscottl#		procname
228195534Sscottl#		`basename procname`
229195534Sscottl#		`basename procname` + ":"
230195534Sscottl#		"(" + `basename procname` + ")"
231195534Sscottl#
232195534Sscottl#	If interpreter != ".", read the first line of procname, remove the
233195534Sscottl#	leading #!, normalise whitespace, append procname, and attempt to
234195534Sscottl#	match that against each command, either as is, or with extra words
235195534Sscottl#	at the end.
236195534Sscottl#
237195534Sscottl_find_processes()
238195534Sscottl{
239195534Sscottl	if [ $# -ne 3 ]; then
240195534Sscottl		err 3 'USAGE: _find_processes procname interpreter psargs'
241195534Sscottl	fi
242195534Sscottl	_procname=$1
243195534Sscottl	_interpreter=$2
244195534Sscottl	_psargs=$3
245195534Sscottl
246195534Sscottl	_pref=
247195534Sscottl	if [ $_interpreter != "." ]; then	# an interpreted script
248195534Sscottl		read _interp < $_procname	# read interpreter name
249195534Sscottl		_interp=${_interp#\#!}		# strip #!
250195534Sscottl		set -- $_interp
251195534Sscottl		if [ $_interpreter != $1 ]; then
252195534Sscottl			warn "\$command_interpreter $_interpreter != $1"
253195534Sscottl		fi
254195534Sscottl		_interp="$* $_procname"		# cleanup spaces, add _procname
255195534Sscottl		_fp_args='_argv'
256195534Sscottl		_fp_match='case "$_argv" in
257195534Sscottl		    ${_interp}|"${_interp} "*)'
258195534Sscottl	else					# a normal daemon
259195534Sscottl		_procnamebn=${_procname##*/}
260195534Sscottl		_fp_args='_arg0 _argv'
261195534Sscottl		_fp_match='case "$_arg0" in
262195534Sscottl		    $_procname|$_procnamebn|${_procnamebn}:|"(${_procnamebn})")'
263195534Sscottl	fi
264195534Sscottl
265195534Sscottl	_proccheck='
266195534Sscottl		ps -o "pid,command" '"$_psargs"' |
267195534Sscottl		while read _npid '"$_fp_args"'; do
268195534Sscottl			case "$_npid" in
269195534Sscottl			    PID)
270195534Sscottl				continue ;;
271195534Sscottl			esac ; '"$_fp_match"'
272195534Sscottl				echo -n "$_pref$_npid" ;
273195534Sscottl				_pref=" "
274195534Sscottl				;;
275195534Sscottl			esac
276195534Sscottl		done'
277195534Sscottl
278195534Sscottl#	debug "in _find_processes: proccheck is ($_proccheck)."
279195534Sscottl	eval $_proccheck
280195534Sscottl}
281195534Sscottl
282195534Sscottl#
283195534Sscottl# wait_for_pids pid [pid ...]
284195534Sscottl#	spins until none of the pids exist
285195534Sscottl#
286195534Sscottlwait_for_pids()
287195534Sscottl{
288195534Sscottl	_list=$*
289195534Sscottl	if [ -z "$_list" ]; then
290195534Sscottl		return
291195534Sscottl	fi
292195534Sscottl	_prefix=
293195534Sscottl	while true; do
294195534Sscottl		_nlist="";
295195534Sscottl		for _j in $_list; do
296195534Sscottl			if kill -0 $_j 2>/dev/null; then
297195534Sscottl				_nlist="${_nlist}${_nlist:+ }$_j"
298195534Sscottl			fi
299195534Sscottl		done
300231745Sgibbs		if [ -z "$_nlist" ]; then
301231745Sgibbs			break
302231745Sgibbs		fi
303231745Sgibbs		_list=$_nlist
304231745Sgibbs		echo -n ${_prefix:-"Waiting for PIDS: "}$_list
305231745Sgibbs		_prefix=", "
306231745Sgibbs		sleep 2
307231745Sgibbs	done
308195534Sscottl	if [ -n "$_prefix" ]; then
309195534Sscottl		echo "."
310195534Sscottl	fi
311195534Sscottl}
312195534Sscottl
313195534Sscottl#
314195534Sscottl# run_rc_command argument
315195534Sscottl#	Search for argument in the list of supported commands, which is:
316195534Sscottl#		"start stop restart rcvar status poll ${extra_commands}"
317195534Sscottl#	If there's a match, run ${argument}_cmd or the default method
318195534Sscottl#	(see below).
319195534Sscottl#
320195534Sscottl#	If argument has a given prefix, then change the operation as follows:
321195534Sscottl#		Prefix	Operation
322195534Sscottl#		------	---------
323195534Sscottl#		fast	Skip the pid check, and set rc_fast=yes
324195534Sscottl#		force	Set ${rcvar} to YES, and set rc_force=yes
325195534Sscottl#
326195534Sscottl#	The following globals are used:
327195534Sscottl#
328195534Sscottl#	Name		Needed	Purpose
329195534Sscottl#	----		------	-------
330195534Sscottl#	name		y	Name of script.
331195534Sscottl#
332195534Sscottl#	command		n	Full path to command.
333195534Sscottl#				Not needed if ${rc_arg}_cmd is set for
334195534Sscottl#				each keyword.
335195534Sscottl#
336195534Sscottl#	command_args	n	Optional args/shell directives for command.
337195534Sscottl#
338195534Sscottl#	command_interpreter n	If not empty, command is interpreted, so
339195534Sscottl#				call check_{pidfile,process}() appropriately.
340195534Sscottl#
341195534Sscottl#	extra_commands	n	List of extra commands supported.
342195534Sscottl#
343195534Sscottl#	pidfile		n	If set, use check_pidfile $pidfile $command,
344195534Sscottl#				otherwise use check_process $command.
345195534Sscottl#				In either case, only check if $command is set.
346195534Sscottl#
347195534Sscottl#	procname	n	Process name to check for instead of $command.
348195534Sscottl#
349195534Sscottl#	rcvar		n	This is checked with checkyesno to determine
350195534Sscottl#				if the action should be run.
351195534Sscottl#
352195534Sscottl#	${name}_chroot	n	Directory to chroot to before running ${command}
353195534Sscottl#				Requires /usr to be mounted.
354195534Sscottl#
355195534Sscottl#	${name}_chdir	n	Directory to cd to before running ${command}
356195534Sscottl#				(if not using ${name}_chroot).
357195534Sscottl#
358195534Sscottl#	${name}_flags	n	Arguments to call ${command} with.
359195534Sscottl#				NOTE:	$flags from the parent environment
360195534Sscottl#					can be used to override this.
361195534Sscottl#
362195534Sscottl#	${name}_nice	n	Nice level to run ${command} at.
363195534Sscottl#
364195534Sscottl#	${name}_user	n	User to run ${command} as, using su(1) if not
365195534Sscottl#				using ${name}_chroot.
366195534Sscottl#				Requires /usr to be mounted.
367195534Sscottl#
368195534Sscottl#	${name}_group	n	Group to run chrooted ${command} as.
369195534Sscottl#				Requires /usr to be mounted.
370195534Sscottl#
371195534Sscottl#	${name}_groups	n	Comma separated list of supplementary groups
372195534Sscottl#				to run the chrooted ${command} with.
373195534Sscottl#				Requires /usr to be mounted.
374195534Sscottl#
375195534Sscottl#	${rc_arg}_cmd	n	If set, use this as the method when invoked;
376195534Sscottl#				Otherwise, use default command (see below)
377195534Sscottl#
378195534Sscottl#	${rc_arg}_precmd n	If set, run just before performing the
379195534Sscottl#				${rc_arg}_cmd method in the default
380195534Sscottl#				operation (i.e, after checking for required
381195534Sscottl#				bits and process (non)existence).
382195534Sscottl#				If this completes with a non-zero exit code,
383195534Sscottl#				don't run ${rc_arg}_cmd.
384195534Sscottl#
385195534Sscottl#	${rc_arg}_postcmd n	If set, run just after performing the
386195534Sscottl#				${rc_arg}_cmd method, if that method
387195534Sscottl#				returned a zero exit code.
388195534Sscottl#
389195534Sscottl#	required_dirs	n	If set, check for the existence of the given
390195534Sscottl#				directories before running the default
391195534Sscottl#				(re)start command.
392195534Sscottl#
393195534Sscottl#	required_files	n	If set, check for the readability of the given
394195534Sscottl#				files before running the default (re)start
395195534Sscottl#				command.
396195534Sscottl#
397195534Sscottl#	required_vars	n	If set, perform checkyesno on each of the
398195534Sscottl#				listed variables before running the default
399195534Sscottl#				(re)start command.
400195534Sscottl#
401195534Sscottl#	Default behaviour for a given argument, if no override method is
402195534Sscottl#	provided:
403195534Sscottl#
404195534Sscottl#	Argument	Default behaviour
405195534Sscottl#	--------	-----------------
406195534Sscottl#	start		if !running && checkyesno ${rcvar}
407195534Sscottl#				${command}
408195534Sscottl#
409195534Sscottl#	stop		if ${pidfile}
410195534Sscottl#				rc_pid=$(check_pidfile $pidfile $command)
411195534Sscottl#			else
412195534Sscottl#				rc_pid=$(check_process $command)
413195534Sscottl#			kill $sig_stop $rc_pid
414195534Sscottl#			wait_for_pids $rc_pid
415195534Sscottl#			($sig_stop defaults to TERM.)
416195534Sscottl#
417195534Sscottl#	reload		Similar to stop, except use $sig_reload instead,
418195534Sscottl#			and doesn't wait_for_pids.
419195534Sscottl#			$sig_reload defaults to HUP.
420195534Sscottl#
421195534Sscottl#	restart		Run `stop' then `start'.
422195534Sscottl#
423195534Sscottl#	status		Show if ${command} is running, etc.
424195534Sscottl#
425195534Sscottl#	poll		Wait for ${command} to exit.
426195534Sscottl#
427195534Sscottl#	rcvar		Display what rc.conf variable is used (if any).
428195534Sscottl#
429195534Sscottl#	Variables available to methods, and after run_rc_command() has
430195534Sscottl#	completed:
431195534Sscottl#
432195534Sscottl#	Variable	Purpose
433195534Sscottl#	--------	-------
434195534Sscottl#	rc_arg		Argument to command, after fast/force processing
435195534Sscottl#			performed
436195534Sscottl#
437195534Sscottl#	rc_flags	Flags to start the default command with.
438195534Sscottl#			Defaults to ${name}_flags, unless overridden
439195534Sscottl#			by $flags from the environment.
440195534Sscottl#			This variable may be changed by the precmd method.
441195534Sscottl#
442195534Sscottl#	rc_pid		PID of command (if appropriate)
443195534Sscottl#
444195534Sscottl#	rc_fast		Not empty if "fast" was provided (q.v.)
445195534Sscottl#
446195534Sscottl#	rc_force	Not empty if "force" was provided (q.v.)
447195534Sscottl#
448195534Sscottl#
449195534Sscottlrun_rc_command()
450195534Sscottl{
451195534Sscottl	_return=0
452195534Sscottl	rc_arg=$1
453195534Sscottl	if [ -z "$name" ]; then
454195534Sscottl		err 3 'run_rc_command: $name is not set.'
455195534Sscottl	fi
456195534Sscottl
457195534Sscottl	case "$rc_arg" in
458195534Sscottl	fast*)				# "fast" prefix; don't check pid
459195534Sscottl		rc_arg=${rc_arg#fast}
460195534Sscottl		rc_fast=yes
461195534Sscottl		;;
462195534Sscottl	force*)				# "force prefix; always start
463195534Sscottl		rc_arg=${rc_arg#force}
464195534Sscottl		rc_force=yes
465195534Sscottl		if [ -n "${rcvar}" ]; then
466195534Sscottl			eval ${rcvar}=YES
467195534Sscottl		fi
468195534Sscottl		;;
469195534Sscottl	esac
470195534Sscottl
471195534Sscottl	eval _overide_command=\$${name}_program
472195534Sscottl	if [ -n "$_overide_command" ]; then
473195534Sscottl		command=$_overide_command
474195534Sscottl	fi
475195534Sscottl
476195534Sscottl	_keywords="start stop restart rcvar $extra_commands"
477195534Sscottl	rc_pid=
478216088Sken	_pidcmd=
479195534Sscottl	_procname=${procname:-${command}}
480195534Sscottl
481195534Sscottl					# setup pid check command if not fast
482195534Sscottl	if [ -z "$rc_fast" -a -n "$_procname" ]; then
483195534Sscottl		if [ -n "$pidfile" ]; then
484195534Sscottl			_pidcmd='rc_pid=$(check_pidfile '"$pidfile $_procname $command_interpreter"')'
485195534Sscottl		else
486195534Sscottl			_pidcmd='rc_pid=$(check_process '"$_procname $command_interpreter"')'
487195534Sscottl		fi
488195534Sscottl		if [ -n "$_pidcmd" ]; then
489195534Sscottl			_keywords="${_keywords} status poll"
490195534Sscottl		fi
491195534Sscottl	fi
492195534Sscottl
493195534Sscottl	if [ -z "$rc_arg" ]; then
494195534Sscottl		rc_usage "$_keywords"
495195534Sscottl	fi
496195534Sscottl
497195534Sscottl	if [ -n "$flags" ]; then	# allow override from environment
498195534Sscottl		rc_flags=$flags
499195534Sscottl	else
500195534Sscottl		eval rc_flags=\$${name}_flags
501195534Sscottl	fi
502195534Sscottl	eval _chdir=\$${name}_chdir	_chroot=\$${name}_chroot \
503195534Sscottl	    _nice=\$${name}_nice	_user=\$${name}_user \
504195534Sscottl	    _group=\$${name}_group	_groups=\$${name}_groups
505195534Sscottl
506195534Sscottl	if [ -n "$_user" ]; then	# unset $_user if running as that user
507195534Sscottl		if [ "$_user" = "$(id -un)" ]; then
508195534Sscottl			unset _user
509195534Sscottl		fi
510195534Sscottl	fi
511195534Sscottl
512195534Sscottl					# if ${rcvar} is set, and $1 is not
513195534Sscottl					# "rcvar", then run
514195534Sscottl					#	checkyesno ${rcvar}
515195534Sscottl					# and return if that failed
516195534Sscottl					#
517195534Sscottl	if [ -n "${rcvar}" -a "$rc_arg" != "rcvar" ]; then
518195534Sscottl		if ! checkyesno ${rcvar}; then
519195534Sscottl			return 0
520195534Sscottl		fi
521195534Sscottl	fi
522195534Sscottl
523195534Sscottl	eval $_pidcmd			# determine the pid if necessary
524195534Sscottl
525195534Sscottl	for _elem in $_keywords; do
526195534Sscottl		if [ "$_elem" != "$rc_arg" ]; then
527195534Sscottl			continue
528195534Sscottl		fi
529195534Sscottl
530195534Sscottl					# if there's a custom ${XXX_cmd},
531195534Sscottl					# run that instead of the default
532195534Sscottl					#
533195534Sscottl		eval _cmd=\$${rc_arg}_cmd _precmd=\$${rc_arg}_precmd \
534195534Sscottl		    _postcmd=\$${rc_arg}_postcmd
535195534Sscottl		if [ -n "$_cmd" ]; then
536195534Sscottl					# if the precmd failed and force
537195534Sscottl					# isn't set, exit
538195534Sscottl					#
539195534Sscottl			if [ -n "$_precmd" ]; then
540236283Seadler				debug "run_rc_command: evaluating ${_precmd}()."
541236283Seadler				eval $_precmd
542236283Seadler				_return=$?
543236283Seadler				[ $_return -ne 0 ] && [ -z "$rc_force" ] &&
544195534Sscottl				    return 1
545195534Sscottl			fi
546195534Sscottl
547195534Sscottl			if [ -n "$_cmd" ]; then
548195534Sscottl				debug "run_rc_command: evaluating ${_cmd}()."
549195534Sscottl				eval $_cmd
550195534Sscottl				_return=$?
551195534Sscottl				[ $_return -ne 0 ] && [ -z "$rc_force" ] &&
552195534Sscottl				    return 1
553195534Sscottl			fi
554195534Sscottl
555195534Sscottl			if [ -n "$_postcmd" ]; then
556195534Sscottl				debug "run_rc_command: evaluating ${_postcmd}()."
557195534Sscottl				 eval $_postcmd
558195534Sscottl				_return=$?
559195534Sscottl			fi
560195534Sscottl			return $_return
561195534Sscottl		fi
562195534Sscottl
563195534Sscottl		case "$rc_arg" in	# default operations...
564208911Smjacob
565208911Smjacob		status)
566208911Smjacob			if [ -n "$rc_pid" ]; then
567208911Smjacob				echo "${name} is running as pid $rc_pid."
568195534Sscottl			else
569195534Sscottl				echo "${name} is not running."
570195534Sscottl				return 1
571195534Sscottl			fi
572195534Sscottl			;;
573195534Sscottl
574195534Sscottl		start)
575195534Sscottl			if [ -n "$rc_pid" ]; then
576195534Sscottl				echo "${name} already running? (pid=$rc_pid)."
577195534Sscottl				exit 1
578195534Sscottl			fi
579195534Sscottl
580256843Smav			if [ ! -x $command ]; then
581195534Sscottl				info "run_rc_command: cannot run ($command)."
582195534Sscottl				return 0
583195534Sscottl			fi
584195534Sscottl
585195534Sscottl					# check for required variables,
586195534Sscottl					# directories, and files
587195534Sscottl					#
588195534Sscottl			for _f in $required_vars; do
589204220Smav				if ! checkyesno $_f; then
590195534Sscottl					warn "\$${_f} is not set."
591195534Sscottl					if [ -z "$rc_force" ]; then
592195534Sscottl						return 1
593195534Sscottl					fi
594195534Sscottl				fi
595204220Smav			done
596195534Sscottl			for _f in $required_dirs; do
597195534Sscottl				if [ ! -d "${_f}/." ]; then
598195534Sscottl					warn "${_f} is not a directory."
599195534Sscottl					if [ -z "$rc_force" ]; then
600195534Sscottl						return 1
601195534Sscottl					fi
602195534Sscottl				fi
603195534Sscottl			done
604195534Sscottl			for _f in $required_files; do
605195534Sscottl				if [ ! -r "${_f}" ]; then
606195534Sscottl					warn "${_f} is not readable."
607195534Sscottl					if [ -z "$rc_force" ]; then
608195534Sscottl						return 1
609195534Sscottl					fi
610195534Sscottl				fi
611195534Sscottl			done
612195534Sscottl
613195534Sscottl					# if the precmd failed and force
614195534Sscottl					# isn't set, exit
615195534Sscottl					#
616195534Sscottl			if [ -n "${_precmd}" ]; then
617195534Sscottl				debug "run_rc_command: evaluating ${_precmd}()."
618195534Sscottl				eval $_precmd
619195534Sscottl				_return=$?
620195534Sscottl				[ $_return -ne 0 ] && [ -z "$rc_force" ] &&
621195534Sscottl				    return 1
622195534Sscottl			fi
623195534Sscottl
624195534Sscottl					# setup the command to run, and run it
625195534Sscottl					#
626195534Sscottl			echo "Starting ${name}."
627195534Sscottl			if [ -n "$_chroot" ]; then
628195534Sscottl				_doit="\
629195534Sscottl${_nice:+nice -n $_nice }\
630195534Sscottlchroot ${_user:+-u $_user }${_group:+-g $_group }${_groups:+-G $_groups }\
631195534Sscottl$_chroot $command $rc_flags $command_args"
632195534Sscottl			else
633195534Sscottl				_doit="\
634195534Sscottl${_chdir:+cd $_chdir; }\
635195534Sscottl${_nice:+nice -n $_nice }\
636195534Sscottl$command $rc_flags $command_args"
637195534Sscottl				if [ -n "$_user" ]; then
638195534Sscottl				    _doit="su -m $_user -c 'sh -c \"$_doit\"'"
639195534Sscottl				fi
640195534Sscottl			fi
641236613Smav
642256843Smav					# if the cmd failed and force
643195534Sscottl					# isn't set, exit
644195534Sscottl					#
645195534Sscottl			debug "run_rc_command: _doit: $_doit"
646195534Sscottl			eval $_doit
647195534Sscottl			_return=$?
648195534Sscottl			[ $_return -ne 0 ] && [ -z "$rc_force" ] && return 1
649195534Sscottl
650195534Sscottl					# finally, run postcmd
651195534Sscottl					#
652195534Sscottl			if [ -n "${_postcmd}" ]; then
653195534Sscottl				debug "run_rc_command: evaluating ${_postcmd}()."
654195534Sscottl				eval $_postcmd
655195534Sscottl			fi
656195534Sscottl			;;
657195534Sscottl
658195534Sscottl		stop)
659195534Sscottl			if [ -z "$rc_pid" ]; then
660195534Sscottl				if [ -n "$pidfile" ]; then
661195534Sscottl					echo \
662195534Sscottl				    "${name} not running? (check $pidfile)."
663195534Sscottl				else
664195534Sscottl					echo "${name} not running?"
665203108Smav				fi
666195534Sscottl				exit 1
667195534Sscottl			fi
668195534Sscottl
669195534Sscottl					# if the precmd failed and force
670195534Sscottl					# isn't set, exit
671195534Sscottl					#
672195534Sscottl			if [ -n "$_precmd" ]; then
673195534Sscottl				eval $_precmd
674195534Sscottl				_return=$?
675195534Sscottl				[ $_return -ne 0 ] && [ -z "$rc_force" ] &&
676195534Sscottl				    return 1
677195534Sscottl			fi
678195534Sscottl
679195534Sscottl					# send the signal to stop
680195534Sscottl					#
681195534Sscottl			echo "Stopping ${name}."
682195534Sscottl			_doit="kill -${sig_stop:-TERM} $rc_pid"
683195534Sscottl			if [ -n "$_user" ]; then
684195534Sscottl				_doit="su -m $_user -c 'sh -c \"$_doit\"'"
685195534Sscottl			fi
686195534Sscottl
687195534Sscottl					# if the stop cmd failed and force
688195534Sscottl					# isn't set, exit
689195534Sscottl					#
690195534Sscottl			eval $_doit
691195534Sscottl			_return=$?
692195534Sscottl			[ $_return -ne 0 ] && [ -z "$rc_force" ] && return 1
693195534Sscottl
694195534Sscottl					# wait for the command to exit,
695195534Sscottl					# and run postcmd.
696195534Sscottl			wait_for_pids $rc_pid
697195534Sscottl			if [ -n "$_postcmd" ]; then
698195534Sscottl				eval $_postcmd
699195534Sscottl				_return=$?
700195534Sscottl			fi
701195534Sscottl			;;
702195534Sscottl
703203108Smav		reload)
704195534Sscottl			if [ -z "$rc_pid" ]; then
705195534Sscottl				if [ -n "$pidfile" ]; then
706195534Sscottl					echo \
707195534Sscottl				    "${name} not running? (check $pidfile)."
708195534Sscottl				else
709195534Sscottl					echo "${name} not running?"
710195534Sscottl				fi
711195534Sscottl				exit 1
712195534Sscottl			fi
713195534Sscottl			echo "Reloading ${name} config files."
714195534Sscottl			if [ -n "$_precmd" ]; then
715195534Sscottl				eval $_precmd
716195534Sscottl				_return=$?
717208911Smjacob				[ $_return -ne 0 ] && [ -z "$rc_force" ] &&
718195534Sscottl				    return 1
719195534Sscottl			fi
720195534Sscottl			_doit="kill -${sig_reload:-HUP} $rc_pid"
721195534Sscottl			if [ -n "$_user" ]; then
722195534Sscottl				_doit="su -m $_user -c 'sh -c \"$_doit\"'"
723195534Sscottl			fi
724195534Sscottl			eval $_doit
725236814Smav			_return=$?
726195534Sscottl			[ $_return -ne 0 ] && [ -z "$rc_force" ] && return 1
727195534Sscottl			if [ -n "$_postcmd" ]; then
728195534Sscottl				eval $_postcmd
729195534Sscottl				_return=$?
730195534Sscottl			fi
731195534Sscottl			;;
732195534Sscottl
733195534Sscottl		restart)
734195534Sscottl			if [ -n "$_precmd" ]; then
735195534Sscottl				eval $_precmd
736195534Sscottl				_return=$?
737195534Sscottl				[ $_return -ne 0 ] && [ -z "$rc_force" ] &&
738195534Sscottl				    return 1
739195534Sscottl			fi
740195534Sscottl					# prevent restart being called more
741195534Sscottl					# than once by any given script
742195534Sscottl					#
743195534Sscottl			if [ -n "$_rc_restart_done" ]; then
744195534Sscottl				return 0
745195534Sscottl			fi
746195534Sscottl			_rc_restart_done=YES
747195534Sscottl
748195534Sscottl			( $0 ${rc_force:+force}stop )
749195534Sscottl			$0 ${rc_force:+force}start
750195534Sscottl
751195534Sscottl			if [ -n "$_postcmd" ]; then
752195534Sscottl				eval $_postcmd
753195534Sscottl				_return=$?
754195534Sscottl			fi
755195534Sscottl			;;
756195534Sscottl
757195534Sscottl		poll)
758195534Sscottl			if [ -n "$rc_pid" ]; then
759195534Sscottl				wait_for_pids $rc_pid
760195534Sscottl			fi
761195534Sscottl			;;
762195534Sscottl
763195534Sscottl		rcvar)
764195534Sscottl			echo "# $name"
765195534Sscottl			if [ -n "$rcvar" ]; then
766195534Sscottl				if checkyesno ${rcvar}; then
767195534Sscottl					echo "\$${rcvar}=YES"
768195534Sscottl				else
769195534Sscottl					echo "\$${rcvar}=NO"
770195534Sscottl				fi
771195534Sscottl			fi
772195534Sscottl			;;
773195534Sscottl
774195534Sscottl		*)
775195534Sscottl			rc_usage "$_keywords"
776195534Sscottl			;;
777195534Sscottl
778195534Sscottl		esac
779195534Sscottl		return $_return
780195534Sscottl	done
781195534Sscottl
782195534Sscottl	echo 1>&2 "$0: unknown directive '$rc_arg'."
783195534Sscottl	rc_usage "$_keywords"
784195534Sscottl	exit 1
785195534Sscottl}
786195534Sscottl
787195534Sscottl#
788195534Sscottl# run_rc_script file arg
789195534Sscottl#	Start the script `file' with `arg', and correctly handle the
790195534Sscottl#	return value from the script.  If `file' ends with `.sh', it's
791195534Sscottl#	sourced into the current environment.  If `file' appears to be
792195534Sscottl#	a backup or scratch file, ignore it.  Otherwise if it's
793195534Sscottl#	executable run as a child process.
794195534Sscottl#
795195534Sscottlrun_rc_script()
796195534Sscottl{
797195534Sscottl	_file=$1
798195534Sscottl	_arg=$2
799195534Sscottl	if [ -z "$_file" -o -z "$_arg" ]; then
800195534Sscottl		err 3 'USAGE: run_rc_script file arg'
801195534Sscottl	fi
802195534Sscottl
803195534Sscottl	trap "echo 'Reboot interrupted'; exit 1" 3
804195534Sscottl
805195534Sscottl	unset	name command command_args command_interpreter \
806208911Smjacob		extra_commands pidfile procname \
807208911Smjacob		rcvar required_dirs required_files required_vars
808208911Smjacob	eval unset ${_arg}_cmd ${_arg}_precmd ${_arg}_postcmd
809208911Smjacob
810208911Smjacob	case "$_file" in
811208911Smjacob	*.sh)				# run in current shell
812208911Smjacob		set $_arg ; . $_file
813208911Smjacob		;;
814208911Smjacob	*[~#]|*.OLD|*.orig)		# scratch file; skip
815208911Smjacob		warn "Ignoring scratch file $_file"
816208911Smjacob		;;
817208911Smjacob	*)				# run in subshell
818208911Smjacob		if [ -x $_file ]; then
819208911Smjacob			if [ -n "$rc_fast_and_loose" ]; then
820216088Sken				set $_arg ; . $_file
821216088Sken			else
822208911Smjacob				( trap "echo 'Reboot interrupted'; exit 1" 3
823208911Smjacob				  set $_arg ; . $_file )
824208911Smjacob			fi
825208911Smjacob		fi
826208911Smjacob		;;
827208911Smjacob	esac
828208911Smjacob}
829195534Sscottl
830195534Sscottl#
831195534Sscottl# load_rc_config
832195534Sscottl#	Source in the configuration file for a given command.
833195534Sscottl#
834195534Sscottlload_rc_config()
835195534Sscottl{
836195534Sscottl	_command=$1
837195534Sscottl	if [ -z "$_command" ]; then
838195534Sscottl		err 3 'USAGE: load_rc_config command'
839195534Sscottl	fi
840195534Sscottl
841195534Sscottl	if [ -z "$_rc_conf_loaded" ]; then
842195534Sscottl		if [ -r /etc/defaults/rc.conf ]; then
843195534Sscottl			debug "Sourcing /etc/defaults/rc.conf"
844195534Sscottl			. /etc/defaults/rc.conf
845195534Sscottl			source_rc_confs
846195534Sscottl		elif [ -r /etc/rc.conf ]; then
847195534Sscottl			debug "Sourcing /etc/rc.conf (/etc/defaults/rc.conf doesn't exist)."
848195534Sscottl			. /etc/rc.conf
849195534Sscottl		fi
850195534Sscottl		_rc_conf_loaded=YES
851195534Sscottl	fi
852195534Sscottl	if [ -f /etc/rc.conf.d/"$_command" ]; then
853195534Sscottl		debug "Sourcing /etc/rc.conf.d/${_command}"
854216088Sken		. /etc/rc.conf.d/"$_command"
855195534Sscottl	fi
856195534Sscottl
857216088Sken	# XXX - Deprecated variable name support
858195534Sscottl	#
859216088Sken	case ${OSTYPE} in
860195534Sscottl	FreeBSD)
861195534Sscottl        	[ -n "$portmap_enable" ] && rpcbind_enable="$portmap_enable"
862216088Sken        	[ -n "$portmap_program" ] && rpcbind_program="$portmap_program"
863195534Sscottl        	[ -n "$portmap_flags" ] && rpcbind_flags="$portmap_flags"
864216088Sken        	[ -n "$single_mountd_enable" ] && mountd_enable="$single_mountd_enable"
865216088Sken        	[ -n "$xntpd_enable" ] && ntpd_enable="$xntpd_enable"
866195534Sscottl        	[ -n "$xntpd_program" ] && ntpd_program="$xntpd_program"
867195534Sscottl        	[ -n "$xntpd_flags" ] && ntpd_flags="$xntpd_flags"
868195534Sscottl		[ -n "$dhcp_program" ] && dhclient_program="$dhcp_program"
869195534Sscottl		[ -n "$dhcp_flags" ] && dhclient_flags="$dhcp_flags"
870195534Sscottl        	;;
871195534Sscottl	esac
872195534Sscottl
873195534Sscottl}
874195534Sscottl
875195534Sscottl#
876195534Sscottl# rc_usage commands
877195534Sscottl#	Print a usage string for $0, with `commands' being a list of
878195534Sscottl#	valid commands.
879195534Sscottl#
880195534Sscottlrc_usage()
881195534Sscottl{
882195534Sscottl	echo -n 1>&2 "Usage: $0 [fast|force]("
883195534Sscottl
884195534Sscottl	_sep=
885195534Sscottl	for _elem in $*; do
886195534Sscottl		echo -n 1>&2 "$_sep$_elem"
887250025Smav		_sep="|"
888195534Sscottl	done
889195534Sscottl	echo 1>&2 ")"
890195534Sscottl	exit 1
891216088Sken}
892195534Sscottl
893216088Sken#
894216088Sken# err exitval message
895216088Sken#	Display message to stderr and log to the syslog, and exit with exitval.
896249937Ssmh#
897216088Skenerr()
898216088Sken{
899216088Sken	exitval=$1
900216088Sken	shift
901216088Sken
902216088Sken	if [ -x /usr/bin/logger ]; then
903216088Sken		logger "$0: ERROR: $*"
904216088Sken	fi
905216088Sken	echo 1>&2 "$0: ERROR: $*"
906216088Sken	exit $exitval
907216088Sken}
908216088Sken
909216088Sken#
910216088Sken# warn message
911216088Sken#	Display message to stderr and log to the syslog.
912216088Sken#
913216088Skenwarn()
914216088Sken{
915216088Sken	if [ -x /usr/bin/logger ]; then
916216088Sken		logger "$0: WARNING: $*"
917216088Sken	fi
918250025Smav	echo 1>&2 "$0: WARNING: $*"
919216088Sken}
920216088Sken
921216088Sken#
922216088Sken# info message
923216088Sken#	Display informational message to stdout and log to syslog.
924195534Sscottl#
925195534Sscottlinfo()
926195534Sscottl{
927195534Sscottl	case ${rc_info} in
928195534Sscottl	[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
929195685Semaste		if [ -x /usr/bin/logger ]; then
930195685Semaste			logger "$0: INFO: $*"
931195685Semaste		fi
932195685Semaste		echo "$0: INFO: $*"
933195685Semaste		;;
934195534Sscottl	esac
935249937Ssmh}
936216088Sken
937216088Sken#
938216088Sken# debug message
939195534Sscottl#	If debugging is enabled in rc.conf output message to stderr.
940195534Sscottl#	BEWARE that you don't call any subroutine that itself calls this
941195534Sscottl#	function.
942195534Sscottl#
943195534Sscottldebug()
944195534Sscottl{
945195534Sscottl	case ${rc_debug} in
946195534Sscottl	[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
947195534Sscottl		if [ -x /usr/bin/logger ]; then
948195534Sscottl			logger "$0: INFO: $*"
949195534Sscottl		fi
950195534Sscottl        	echo 1>&2 "$0: DEBUG: $*"
951195534Sscottl		;;
952195534Sscottl	esac
953195534Sscottl}
954195534Sscottl
955195534Sscottl#
956195534Sscottl# backup_file action file cur backup
957195534Sscottl#	Make a backup copy of `file' into `cur', and save the previous
958250025Smav#	version of `cur' as `backup' or use rcs for archiving.
959195534Sscottl#
960195534Sscottl#	This routine checks the value of the backup_uses_rcs variable,
961195534Sscottl#	which can be either YES or NO.
962195534Sscottl#
963236613Smav#	The `action' keyword can be one of the following:
964195534Sscottl#
965249466Smav#	add		`file' is now being backed up (and is possibly
966195534Sscottl#			being reentered into the backups system).  `cur'
967195534Sscottl#			is created and RCS files, if necessary, are
968195534Sscottl#			created as well.
969195534Sscottl#
970195534Sscottl#	update		`file' has changed and needs to be backed up.
971195534Sscottl#			If `cur' exists, it is copied to to `back' or
972195534Sscottl#			checked into RCS (if the repository file is old),
973195534Sscottl#			and then `file' is copied to `cur'.  Another RCS
974203108Smav#			check in done here if RCS is being used.
975195534Sscottl#
976195534Sscottl#	remove		`file' is no longer being tracked by the backups
977195534Sscottl#			system.  If RCS is not being used, `cur' is moved
978252382Sscottl#			to `back', otherwise an empty file is checked in,
979195534Sscottl#			and then `cur' is removed.
980195534Sscottl#
981195534Sscottl#
982195534Sscottlbackup_file()
983195534Sscottl{
984195534Sscottl	_action=$1
985195534Sscottl	_file=$2
986195534Sscottl	_cur=$3
987195534Sscottl	_back=$4
988195534Sscottl
989195534Sscottl	if checkyesno backup_uses_rcs; then
990195534Sscottl		_msg0="backup archive"
991195534Sscottl		_msg1="update"
992195534Sscottl
993195534Sscottl		# ensure that history file is not locked
994195534Sscottl		if [ -f $_cur,v ]; then
995195534Sscottl			rcs -q -u -U -M $_cur
996203108Smav		fi
997195534Sscottl
998195534Sscottl		# ensure after switching to rcs that the
999195534Sscottl		# current backup is not lost
1000252382Sscottl		if [ -f $_cur ]; then
1001195534Sscottl			# no archive, or current newer than archive
1002195534Sscottl			if [ ! -f $_cur,v -o $_cur -nt $_cur,v ]; then
1003195534Sscottl				ci -q -f -u -t-"$_msg0" -m"$_msg1" $_cur
1004195534Sscottl				rcs -q -kb -U $_cur
1005195534Sscottl				co -q -f -u $_cur
1006195534Sscottl			fi
1007195534Sscottl		fi
1008195534Sscottl
1009195534Sscottl		case $_action in
1010195534Sscottl		add|update)
1011195534Sscottl			cp -p $_file $_cur
1012195534Sscottl			ci -q -f -u -t-"$_msg0" -m"$_msg1" $_cur
1013195534Sscottl			rcs -q -kb -U $_cur
1014195534Sscottl			co -q -f -u $_cur
1015195534Sscottl			chown root:wheel $_cur $_cur,v
1016195534Sscottl			;;
1017195534Sscottl		remove)
1018195534Sscottl			cp /dev/null $_cur
1019195534Sscottl			ci -q -f -u -t-"$_msg0" -m"$_msg1" $_cur
1020195534Sscottl			rcs -q -kb -U $_cur
1021195534Sscottl			chown root:wheel $_cur $_cur,v
1022195534Sscottl			rm $_cur
1023195534Sscottl			;;
1024195534Sscottl		esac
1025195534Sscottl	else
1026195534Sscottl		case $_action in
1027195534Sscottl		add|update)
1028195534Sscottl			if [ -f $_cur ]; then
1029195534Sscottl				cp -p $_cur $_back
1030195534Sscottl			fi
1031195534Sscottl			cp -p $_file $_cur
1032195534Sscottl			chown root:wheel $_cur
1033195534Sscottl			;;
1034195534Sscottl		remove)
1035195534Sscottl			mv -f $_cur $_back
1036195534Sscottl			;;
1037195534Sscottl		esac
1038195534Sscottl	fi
1039195534Sscottl}
1040195534Sscottl
1041195534Sscottl# devfs_link dir src link
1042195534Sscottl#	Make a symbolic link 'link' to src in chroot/dev.
1043195534Sscottl#	Returns 0 on sucess.
1044236613Smav#
1045195534Sscottldevfs_link()
1046195534Sscottl{
1047195534Sscottl	local dir src link _me
1048195534Sscottl	dir="$1"
1049195534Sscottl	src="$2"
1050195534Sscottl	link="$3"
1051195534Sscottl	_me="devfs_link"
1052195534Sscottl
1053195534Sscottl	if [ -z "$dir" -o -z "$src" -o -z "$link" ]; then
1054195534Sscottl		warn "devfs_link(): requires three arguments."
1055195534Sscottl		return 1
1056195534Sscottl	fi
1057195534Sscottl	if [ -z "$dir" ]; then
1058195534Sscottl		warn "$_me: the directory ($dir) does not exist"
1059195534Sscottl		return 1
1060195534Sscottl	fi
1061195534Sscottl	cd ${chroot}/dev
1062195534Sscottl	if ! ln -sf $src $link ; then
1063195534Sscottl		warn "$_me: unable to link $link --> $src in $dir"
1064236613Smav		return 1
1065195534Sscottl	fi
1066195534Sscottl	return 0
1067195534Sscottl}
1068195534Sscottl
1069195534Sscottl# devfs_rulesets_from_file file
1070195534Sscottl#	Reads a set of devfs commands from file, and creates
1071195534Sscottl#	the specified rulesets with their rules. Returns non-zero
1072236613Smav#	if there was an error.
1073195534Sscottl#
1074195534Sscottldevfs_rulesets_from_file()
1075195534Sscottl{
1076195534Sscottl	local file _err _me
1077195534Sscottl	file="$1"
1078195534Sscottl	_me="devfs_rulesets_from_file"
1079252382Sscottl	_err=0
1080195534Sscottl
1081195534Sscottl	if [ -z "$file" ]; then
1082236613Smav		warn "$_me: you must specify a file"
1083195534Sscottl		return 1
1084195534Sscottl	fi
1085195534Sscottl	if [ ! -e "$file" ]; then
1086195534Sscottl		debug "$_me: no such file ($file)"
1087195534Sscottl		return 0
1088195534Sscottl	fi
1089195534Sscottl	debug "reading rulesets from file ($file)"
1090195534Sscottl	{ while read line
1091216088Sken	do
1092216088Sken		case $line in
1093195534Sscottl		\#*)
1094195534Sscottl			continue
1095195534Sscottl			;;
1096195534Sscottl		\[*\]*)
1097195534Sscottl			rulenum=`expr "$line" : "\[.*=\([0-9]*\)\]"`
1098195534Sscottl			if [ -z "$rulenum" ]; then
1099195534Sscottl				warn "$_me: cannot extract rule number ($line)"
1100195534Sscottl				_err=1
1101195534Sscottl				break
1102195534Sscottl			fi
1103195534Sscottl			rulename=`expr "$line" : "\[\(.*\)=[0-9]*\]"`
1104195534Sscottl			if [ -z "$rulename" ]; then
1105195534Sscottl				warn "$_me: cannot extract rule name ($line)"
1106195534Sscottl				_err=1
1107195534Sscottl				break;
1108195534Sscottl			fi
1109252382Sscottl			eval $rulename=\$rulenum
1110195534Sscottl			debug "found ruleset: $rulename=$rulenum"
1111195534Sscottl			if ! /sbin/devfs rule -s $rulenum delset ; then
1112249466Smav				_err=1
1113249466Smav				break
1114249466Smav			fi
1115249466Smav			;;
1116195534Sscottl		*)
1117249466Smav			rulecmd="${line%%"\#*"}"
1118195534Sscottl			# evaluate the command incase it includes
1119195534Sscottl			# other rules
1120195534Sscottl			if [ -n "$rulecmd" ]; then
1121195534Sscottl				debug "adding rule ($rulecmd)"
1122195534Sscottl				if ! eval /sbin/devfs rule -s $rulenum $rulecmd
1123195534Sscottl				then
1124195534Sscottl					_err=1
1125195534Sscottl					break
1126195534Sscottl				fi
1127249466Smav			fi
1128195534Sscottl			;;
1129195534Sscottl		esac
1130195534Sscottl		if [ $_err -ne 0 ]; then
1131195534Sscottl			debug "error in $_me"
1132252382Sscottl			break
1133195534Sscottl		fi
1134195534Sscottl	done } < $file
1135195534Sscottl	return $_err
1136195534Sscottl}
1137195534Sscottl
1138195534Sscottl# devfs_init_rulesets
1139195534Sscottl#	Initializes rulesets from configuration files. Returns
1140195534Sscottl#	non-zero if there was an error.
1141208911Smjacob#
1142195534Sscottldevfs_init_rulesets()
1143195534Sscottl{
1144195534Sscottl	local file _me
1145195534Sscottl	_me="devfs_init_rulesets"
1146195534Sscottl
1147195534Sscottl	# Go through this only once
1148195534Sscottl	if [ -n "$devfs_rulesets_init" ]; then
1149195534Sscottl		debug "$_me: devfs rulesets already initialized"
1150195534Sscottl		return
1151195534Sscottl	fi
1152195534Sscottl	for file in $devfs_rulesets ; do
1153195534Sscottl		devfs_rulesets_from_file $file || return 1
1154195534Sscottl	done
1155195534Sscottl	devfs_rulesets_init=1
1156195534Sscottl	debug "$_me: devfs rulesets initialized"
1157195534Sscottl	return 0
1158195534Sscottl}
1159195534Sscottl
1160195534Sscottl# devfs_set_ruleset ruleset [dir]
1161195534Sscottl#	Sets the default ruleset of dir to ruleset. The ruleset arguement
1162249466Smav#	must be a ruleset name as specified in devfs.rules(5) file.
1163195534Sscottl#	Returns non-zero if it could not set it successfully.
1164195534Sscottl#
1165195534Sscottldevfs_set_ruleset()
1166195534Sscottl{
1167195534Sscottl	local devdir rs _me
1168208911Smjacob	[ -n "$1" ] && eval rs=\$$1 || rs=
1169208911Smjacob	[ -n "$2" ] && devdir="-m "$2"" || devdir=
1170208911Smjacob	_me="devfs_set_ruleset"
1171208911Smjacob
1172208911Smjacob	if [ -z "$rs" ]; then
1173208911Smjacob		warn "$_me: you must specify a ruleset number"
1174208911Smjacob		return 1
1175208911Smjacob	fi
1176208911Smjacob	debug "$_me: setting ruleset ($rs) on mount-point (${devdir#-m })"
1177208911Smjacob	if ! /sbin/devfs $devdir ruleset $rs ; then
1178208911Smjacob		warn "$_me: unable to set ruleset $rs to ${devdir#-m }"
1179208911Smjacob		return 1
1180208911Smjacob	fi
1181208911Smjacob	return 0
1182195534Sscottl}
1183208911Smjacob
1184216088Sken# devfs_apply_ruleset ruleset [dir]
1185195534Sscottl#	Apply ruleset number $ruleset to the devfs mountpoint $dir.
1186198748Smav#	The ruleset argument must be a ruleset name as specified
1187198748Smav#	in a devfs.rules(5) file.  Returns 0 on success or non-zero
1188198748Smav#	if it could not apply the ruleset.
1189198748Smav#
1190195534Sscottldevfs_apply_ruleset()
1191195534Sscottl{
1192249466Smav	local devdir rs _me
1193208911Smjacob	[ -n "$1" ] && eval rs=\$$1 || rs=
1194208911Smjacob	[ -n "$2" ] && devdir="-m "$2"" || devdir=
1195208911Smjacob	_me="devfs_apply_ruleset"
1196208911Smjacob
1197208911Smjacob	if [ -z "$rs" ]; then
1198208911Smjacob		warn "$_me: you must specify a ruleset"
1199208911Smjacob		return 1
1200208911Smjacob	fi
1201208911Smjacob	debug "$_me: applying ruleset ($rs) to mount-point (${devdir#-m })"
1202208911Smjacob	if ! /sbin/devfs $devdir rule -s $rs applyset ; then
1203208911Smjacob		warn "$_me: unable to apply ruleset $rs to ${devdir#-m }"
1204208911Smjacob		return 1
1205208911Smjacob	fi
1206208911Smjacob	return 0
1207249466Smav}
1208195534Sscottl
1209195534Sscottl# devfs_domount dir [ruleset]
1210195534Sscottl#	Mount devfs on dir. If ruleset is specified it is set
1211195534Sscottl#	on the mount-point. It must also be a ruleset name as specified
1212195534Sscottl#	in a devfs.rules(5) file. Returns 0 on success.
1213195534Sscottl#
1214249466Smavdevfs_domount()
1215195534Sscottl{
1216195534Sscottl	local devdir rs _me
1217195534Sscottl	devdir="$1"
1218195534Sscottl	[ -n "$2" ] && rs=$2 || rs=
1219195534Sscottl	_me="devfs_domount()"
1220195534Sscottl
1221195534Sscottl	if [ -z "$devdir" ]; then
1222195534Sscottl		warn "$_me: you must specify a mount-point"
1223195534Sscottl		return 1
1224195534Sscottl	fi
1225195534Sscottl	debug "$_me: mount-point is ($devdir), ruleset is ($rs)"
1226195534Sscottl	if ! mount -t devfs dev "$devdir" ; then
1227195534Sscottl		warn "$_me: Unable to mount devfs on $devdir"
1228195534Sscottl		return 1
1229195534Sscottl	fi
1230195534Sscottl	if [ -n "$rs" ]; then
1231195534Sscottl		devfs_init_rulesets
1232195534Sscottl		devfs_set_ruleset $rs $devdir
1233236613Smav	fi
1234195534Sscottl	return 0
1235195534Sscottl}
1236195534Sscottl
1237195534Sscottl# devfs_mount_jail dir [ruleset]
1238208911Smjacob#	Mounts a devfs file system appropriate for jails
1239208911Smjacob#	on the directory dir. If ruleset is specified, the ruleset
1240208911Smjacob#	it names will be used instead.  If present, ruleset must
1241208911Smjacob#	be the name of a ruleset as defined in a devfs.rules(5) file.
1242208911Smjacob#	This function returns non-zero if an error occurs.
1243208911Smjacob#
1244208911Smjacobdevfs_mount_jail()
1245208911Smjacob{
1246208911Smjacob	local jdev rs _me
1247208911Smjacob	jdev="$1"
1248208911Smjacob	[ -n "$2" ] && rs=$2 || rs="devfsrules_jail"
1249208911Smjacob	_me="devfs_mount_jail"
1250252382Sscottl
1251208911Smjacob	devfs_init_rulesets
1252208911Smjacob	if ! devfs_domount "$jdev" $rs ; then
1253208911Smjacob		warn "$_me: devfs was not mounted on $jdev"
1254208911Smjacob		return 1
1255249466Smav	fi
1256208911Smjacob	return 0
1257208911Smjacob}
1258208911Smjacob