Deleted Added
full compact
rc.subr (197790) rc.subr (197947)
1# $NetBSD: rc.subr,v 1.67 2006/10/07 11:25:15 elad Exp $
1# $NetBSD: rc.subr,v 1.67 2006/10/07 11:25:15 elad Exp $
2# $FreeBSD: head/etc/rc.subr 197790 2009-10-05 20:11:33Z hrs $
2# $FreeBSD: head/etc/rc.subr 197947 2009-10-10 22:17:03Z dougb $
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# 3. All advertising materials mentioning features or use of this software
19# must display the following acknowledgement:
20# This product includes software developed by the NetBSD
21# Foundation, Inc. and its contributors.
22# 4. Neither the name of The NetBSD Foundation nor the names of its
23# contributors may be used to endorse or promote products derived
24# from this software without specific prior written permission.
25#
26# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36# POSSIBILITY OF SUCH DAMAGE.
37#
38# rc.subr
39# functions used by various rc scripts
40#
41
42: ${rcvar_manpage:='rc.conf(5)'}
43: ${RC_PID:=$$}; export RC_PID
44
45#
46# Operating System dependent/independent variables
47#
48
49if [ -z "${_rc_subr_loaded}" ]; then
50
51_rc_subr_loaded="YES"
52
53SYSCTL="/sbin/sysctl"
54SYSCTL_N="${SYSCTL} -n"
55CMD_OSTYPE="${SYSCTL_N} kern.ostype"
56OSTYPE=`${CMD_OSTYPE}`
57ID="/usr/bin/id"
58IDCMD="if [ -x $ID ]; then $ID -un; fi"
59PS="/bin/ps -ww"
60JID=`$PS -p $$ -o jid=`
61
62case ${OSTYPE} in
63FreeBSD)
64 SYSCTL_W="${SYSCTL}"
65 ;;
66NetBSD)
67 SYSCTL_W="${SYSCTL} -w"
68 ;;
69esac
70
71#
72# functions
73# ---------
74
75# set_rcvar [var] [defval] [desc]
76#
77# Echo or define a rc.conf(5) variable name. Global variable
78# $rcvars is used.
79#
80# If no argument is specified, echo "${name}_enable".
81#
82# If only a var is specified, echo "${var}_enable".
83#
84# If var and defval are specified, the ${var} is defined as
85# rc.conf(5) variable and the default value is ${defvar}. An
86# optional argument $desc can also be specified to add a
87# description for that.
88#
89set_rcvar()
90{
91 case $# in
92 0)
93 echo ${name}_enable
94 ;;
95 1)
96 echo ${1}_enable
97 ;;
98 *)
99 debug "rcvar_define: \$$1=$2 is added" \
100 " as a rc.conf(5) variable."
101
102 local _var
103 _var=$1
104 rcvars="${rcvars# } $_var"
105 eval ${_var}_defval=\"$2\"
106 shift 2
107 # encode multiple lines of _desc
108 for l in "$@"; do
109 eval ${_var}_desc=\"\${${_var}_desc#^^}^^$l\"
110 done
111 eval ${_var}_desc=\"\${${_var}_desc#^^}\"
112 ;;
113 esac
114}
115
116# set_rcvar_obsolete oldvar [newvar] [msg]
117# Define obsolete variable.
118# Global variable $rcvars_obsolete is used.
119#
120set_rcvar_obsolete()
121{
122 local _var
123 _var=$1
124 debug "rcvar_obsolete: \$$1(old) -> \$$2(new) is defined"
125
126 rcvars_obsolete="${rcvars_obsolete# } $1"
127 eval ${1}_newvar=\"$2\"
128 shift 2
129 eval ${_var}_obsolete_msg=\"$*\"
130}
131
132#
133# force_depend script
134# Force a service to start. Intended for use by services
135# to resolve dependency issues. It is assumed the caller
136# has check to make sure this call is necessary
137# $1 - filename of script, in /etc/rc.d, to run
138#
139force_depend()
140{
141 _depend="$1"
142
143 info "${name} depends on ${_depend}, which will be forced to start."
144 if ! /etc/rc.d/${_depend} forcestart; then
145 warn "Unable to force ${_depend}. It may already be running."
146 return 1
147 fi
148 return 0
149}
150
151#
152# checkyesno var
153# Test $1 variable, and warn if not set to YES or NO.
154# Return 0 if it's "yes" (et al), nonzero otherwise.
155#
156checkyesno()
157{
158 eval _value=\$${1}
159 debug "checkyesno: $1 is set to $_value."
160 case $_value in
161
162 # "yes", "true", "on", or "1"
163 [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
164 return 0
165 ;;
166
167 # "no", "false", "off", or "0"
168 [Nn][Oo]|[Ff][Aa][Ll][Ss][Ee]|[Oo][Ff][Ff]|0)
169 return 1
170 ;;
171 *)
172 warn "\$${1} is not set properly - see ${rcvar_manpage}."
173 return 1
174 ;;
175 esac
176}
177
178#
179# reverse_list list
180# print the list in reverse order
181#
182reverse_list()
183{
184 _revlist=
185 for _revfile; do
186 _revlist="$_revfile $_revlist"
187 done
188 echo $_revlist
189}
190
191# stop_boot always
192# If booting directly to multiuser or $always is enabled,
193# send SIGTERM to the parent (/etc/rc) to abort the boot.
194# Otherwise just exit.
195#
196stop_boot()
197{
198 local always
199
200 case $1 in
201 # "yes", "true", "on", or "1"
202 [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
203 always=true
204 ;;
205 *)
206 always=false
207 ;;
208 esac
209 if [ "$autoboot" = yes -o "$always" = true ]; then
210 echo "ERROR: ABORTING BOOT (sending SIGTERM to parent)!"
211 kill -TERM ${RC_PID}
212 fi
213 exit 1
214}
215
216#
217# mount_critical_filesystems type
218# Go through the list of critical filesystems as provided in
219# the rc.conf(5) variable $critical_filesystems_${type}, checking
220# each one to see if it is mounted, and if it is not, mounting it.
221#
222mount_critical_filesystems()
223{
224 eval _fslist=\$critical_filesystems_${1}
225 for _fs in $_fslist; do
226 mount | (
227 _ismounted=false
228 while read what _on on _type type; do
229 if [ $on = $_fs ]; then
230 _ismounted=true
231 fi
232 done
233 if $_ismounted; then
234 :
235 else
236 mount $_fs >/dev/null 2>&1
237 fi
238 )
239 done
240}
241
242#
243# check_pidfile pidfile procname [interpreter]
244# Parses the first line of pidfile for a PID, and ensures
245# that the process is running and matches procname.
246# Prints the matching PID upon success, nothing otherwise.
247# interpreter is optional; see _find_processes() for details.
248#
249check_pidfile()
250{
251 _pidfile=$1
252 _procname=$2
253 _interpreter=$3
254 if [ -z "$_pidfile" -o -z "$_procname" ]; then
255 err 3 'USAGE: check_pidfile pidfile procname [interpreter]'
256 fi
257 if [ ! -f $_pidfile ]; then
258 debug "pid file ($_pidfile): not readable."
259 return
260 fi
261 read _pid _junk < $_pidfile
262 if [ -z "$_pid" ]; then
263 debug "pid file ($_pidfile): no pid in file."
264 return
265 fi
266 _find_processes $_procname ${_interpreter:-.} '-p '"$_pid"
267}
268
269#
270# check_process procname [interpreter]
271# Ensures that a process (or processes) named procname is running.
272# Prints a list of matching PIDs.
273# interpreter is optional; see _find_processes() for details.
274#
275check_process()
276{
277 _procname=$1
278 _interpreter=$2
279 if [ -z "$_procname" ]; then
280 err 3 'USAGE: check_process procname [interpreter]'
281 fi
282 _find_processes $_procname ${_interpreter:-.} '-ax'
283}
284
285#
286# _find_processes procname interpreter psargs
287# Search for procname in the output of ps generated by psargs.
288# Prints the PIDs of any matching processes, space separated.
289#
290# If interpreter == ".", check the following variations of procname
291# against the first word of each command:
292# procname
293# `basename procname`
294# `basename procname` + ":"
295# "(" + `basename procname` + ")"
296# "[" + `basename procname` + "]"
297#
298# If interpreter != ".", read the first line of procname, remove the
299# leading #!, normalise whitespace, append procname, and attempt to
300# match that against each command, either as is, or with extra words
301# at the end. As an alternative, to deal with interpreted daemons
302# using perl, the basename of the interpreter plus a colon is also
303# tried as the prefix to procname.
304#
305_find_processes()
306{
307 if [ $# -ne 3 ]; then
308 err 3 'USAGE: _find_processes procname interpreter psargs'
309 fi
310 _procname=$1
311 _interpreter=$2
312 _psargs=$3
313
314 _pref=
315 if [ $_interpreter != "." ]; then # an interpreted script
316 _script=${_chroot}${_chroot:+"/"}$_procname
317 if [ -r $_script ]; then
318 read _interp < $_script # read interpreter name
319 case "$_interp" in
320 \#!*)
321 _interp=${_interp#\#!} # strip #!
322 set -- $_interp
323 case $1 in
324 */bin/env)
325 shift # drop env to get real name
326 ;;
327 esac
328 if [ $_interpreter != $1 ]; then
329 warn "\$command_interpreter $_interpreter != $1"
330 fi
331 ;;
332 *)
333 warn "no shebang line in $_script"
334 set -- $_interpreter
335 ;;
336 esac
337 else
338 warn "cannot read shebang line from $_script"
339 set -- $_interpreter
340 fi
341 _interp="$* $_procname" # cleanup spaces, add _procname
342 _interpbn=${1##*/}
343 _fp_args='_argv'
344 _fp_match='case "$_argv" in
345 ${_interp}|"${_interp} "*|"${_interpbn}: ${_procname}"*)'
346 else # a normal daemon
347 _procnamebn=${_procname##*/}
348 _fp_args='_arg0 _argv'
349 _fp_match='case "$_arg0" in
350 $_procname|$_procnamebn|${_procnamebn}:|"(${_procnamebn})"|"[${_procnamebn}]")'
351 fi
352
353 _proccheck="\
354 $PS 2>/dev/null -o pid= -o jid= -o command= $_psargs"' |
355 while read _npid _jid '"$_fp_args"'; do
356 '"$_fp_match"'
357 if [ "$JID" -eq "$_jid" ];
358 then echo -n "$_pref$_npid";
359 _pref=" ";
360 fi
361 ;;
362 esac
363 done'
364
365# debug "in _find_processes: proccheck is ($_proccheck)."
366 eval $_proccheck
367}
368
369#
370# wait_for_pids pid [pid ...]
371# spins until none of the pids exist
372#
373wait_for_pids()
374{
375 _list="$@"
376 if [ -z "$_list" ]; then
377 return
378 fi
379 _prefix=
380 while true; do
381 _nlist="";
382 for _j in $_list; do
383 if kill -0 $_j 2>/dev/null; then
384 _nlist="${_nlist}${_nlist:+ }$_j"
385 fi
386 done
387 if [ -z "$_nlist" ]; then
388 break
389 fi
390 _list=$_nlist
391 echo -n ${_prefix:-"Waiting for PIDS: "}$_list
392 _prefix=", "
393 sleep 2
394 done
395 if [ -n "$_prefix" ]; then
396 echo "."
397 fi
398}
399
400#
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# 3. All advertising materials mentioning features or use of this software
19# must display the following acknowledgement:
20# This product includes software developed by the NetBSD
21# Foundation, Inc. and its contributors.
22# 4. Neither the name of The NetBSD Foundation nor the names of its
23# contributors may be used to endorse or promote products derived
24# from this software without specific prior written permission.
25#
26# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36# POSSIBILITY OF SUCH DAMAGE.
37#
38# rc.subr
39# functions used by various rc scripts
40#
41
42: ${rcvar_manpage:='rc.conf(5)'}
43: ${RC_PID:=$$}; export RC_PID
44
45#
46# Operating System dependent/independent variables
47#
48
49if [ -z "${_rc_subr_loaded}" ]; then
50
51_rc_subr_loaded="YES"
52
53SYSCTL="/sbin/sysctl"
54SYSCTL_N="${SYSCTL} -n"
55CMD_OSTYPE="${SYSCTL_N} kern.ostype"
56OSTYPE=`${CMD_OSTYPE}`
57ID="/usr/bin/id"
58IDCMD="if [ -x $ID ]; then $ID -un; fi"
59PS="/bin/ps -ww"
60JID=`$PS -p $$ -o jid=`
61
62case ${OSTYPE} in
63FreeBSD)
64 SYSCTL_W="${SYSCTL}"
65 ;;
66NetBSD)
67 SYSCTL_W="${SYSCTL} -w"
68 ;;
69esac
70
71#
72# functions
73# ---------
74
75# set_rcvar [var] [defval] [desc]
76#
77# Echo or define a rc.conf(5) variable name. Global variable
78# $rcvars is used.
79#
80# If no argument is specified, echo "${name}_enable".
81#
82# If only a var is specified, echo "${var}_enable".
83#
84# If var and defval are specified, the ${var} is defined as
85# rc.conf(5) variable and the default value is ${defvar}. An
86# optional argument $desc can also be specified to add a
87# description for that.
88#
89set_rcvar()
90{
91 case $# in
92 0)
93 echo ${name}_enable
94 ;;
95 1)
96 echo ${1}_enable
97 ;;
98 *)
99 debug "rcvar_define: \$$1=$2 is added" \
100 " as a rc.conf(5) variable."
101
102 local _var
103 _var=$1
104 rcvars="${rcvars# } $_var"
105 eval ${_var}_defval=\"$2\"
106 shift 2
107 # encode multiple lines of _desc
108 for l in "$@"; do
109 eval ${_var}_desc=\"\${${_var}_desc#^^}^^$l\"
110 done
111 eval ${_var}_desc=\"\${${_var}_desc#^^}\"
112 ;;
113 esac
114}
115
116# set_rcvar_obsolete oldvar [newvar] [msg]
117# Define obsolete variable.
118# Global variable $rcvars_obsolete is used.
119#
120set_rcvar_obsolete()
121{
122 local _var
123 _var=$1
124 debug "rcvar_obsolete: \$$1(old) -> \$$2(new) is defined"
125
126 rcvars_obsolete="${rcvars_obsolete# } $1"
127 eval ${1}_newvar=\"$2\"
128 shift 2
129 eval ${_var}_obsolete_msg=\"$*\"
130}
131
132#
133# force_depend script
134# Force a service to start. Intended for use by services
135# to resolve dependency issues. It is assumed the caller
136# has check to make sure this call is necessary
137# $1 - filename of script, in /etc/rc.d, to run
138#
139force_depend()
140{
141 _depend="$1"
142
143 info "${name} depends on ${_depend}, which will be forced to start."
144 if ! /etc/rc.d/${_depend} forcestart; then
145 warn "Unable to force ${_depend}. It may already be running."
146 return 1
147 fi
148 return 0
149}
150
151#
152# checkyesno var
153# Test $1 variable, and warn if not set to YES or NO.
154# Return 0 if it's "yes" (et al), nonzero otherwise.
155#
156checkyesno()
157{
158 eval _value=\$${1}
159 debug "checkyesno: $1 is set to $_value."
160 case $_value in
161
162 # "yes", "true", "on", or "1"
163 [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
164 return 0
165 ;;
166
167 # "no", "false", "off", or "0"
168 [Nn][Oo]|[Ff][Aa][Ll][Ss][Ee]|[Oo][Ff][Ff]|0)
169 return 1
170 ;;
171 *)
172 warn "\$${1} is not set properly - see ${rcvar_manpage}."
173 return 1
174 ;;
175 esac
176}
177
178#
179# reverse_list list
180# print the list in reverse order
181#
182reverse_list()
183{
184 _revlist=
185 for _revfile; do
186 _revlist="$_revfile $_revlist"
187 done
188 echo $_revlist
189}
190
191# stop_boot always
192# If booting directly to multiuser or $always is enabled,
193# send SIGTERM to the parent (/etc/rc) to abort the boot.
194# Otherwise just exit.
195#
196stop_boot()
197{
198 local always
199
200 case $1 in
201 # "yes", "true", "on", or "1"
202 [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
203 always=true
204 ;;
205 *)
206 always=false
207 ;;
208 esac
209 if [ "$autoboot" = yes -o "$always" = true ]; then
210 echo "ERROR: ABORTING BOOT (sending SIGTERM to parent)!"
211 kill -TERM ${RC_PID}
212 fi
213 exit 1
214}
215
216#
217# mount_critical_filesystems type
218# Go through the list of critical filesystems as provided in
219# the rc.conf(5) variable $critical_filesystems_${type}, checking
220# each one to see if it is mounted, and if it is not, mounting it.
221#
222mount_critical_filesystems()
223{
224 eval _fslist=\$critical_filesystems_${1}
225 for _fs in $_fslist; do
226 mount | (
227 _ismounted=false
228 while read what _on on _type type; do
229 if [ $on = $_fs ]; then
230 _ismounted=true
231 fi
232 done
233 if $_ismounted; then
234 :
235 else
236 mount $_fs >/dev/null 2>&1
237 fi
238 )
239 done
240}
241
242#
243# check_pidfile pidfile procname [interpreter]
244# Parses the first line of pidfile for a PID, and ensures
245# that the process is running and matches procname.
246# Prints the matching PID upon success, nothing otherwise.
247# interpreter is optional; see _find_processes() for details.
248#
249check_pidfile()
250{
251 _pidfile=$1
252 _procname=$2
253 _interpreter=$3
254 if [ -z "$_pidfile" -o -z "$_procname" ]; then
255 err 3 'USAGE: check_pidfile pidfile procname [interpreter]'
256 fi
257 if [ ! -f $_pidfile ]; then
258 debug "pid file ($_pidfile): not readable."
259 return
260 fi
261 read _pid _junk < $_pidfile
262 if [ -z "$_pid" ]; then
263 debug "pid file ($_pidfile): no pid in file."
264 return
265 fi
266 _find_processes $_procname ${_interpreter:-.} '-p '"$_pid"
267}
268
269#
270# check_process procname [interpreter]
271# Ensures that a process (or processes) named procname is running.
272# Prints a list of matching PIDs.
273# interpreter is optional; see _find_processes() for details.
274#
275check_process()
276{
277 _procname=$1
278 _interpreter=$2
279 if [ -z "$_procname" ]; then
280 err 3 'USAGE: check_process procname [interpreter]'
281 fi
282 _find_processes $_procname ${_interpreter:-.} '-ax'
283}
284
285#
286# _find_processes procname interpreter psargs
287# Search for procname in the output of ps generated by psargs.
288# Prints the PIDs of any matching processes, space separated.
289#
290# If interpreter == ".", check the following variations of procname
291# against the first word of each command:
292# procname
293# `basename procname`
294# `basename procname` + ":"
295# "(" + `basename procname` + ")"
296# "[" + `basename procname` + "]"
297#
298# If interpreter != ".", read the first line of procname, remove the
299# leading #!, normalise whitespace, append procname, and attempt to
300# match that against each command, either as is, or with extra words
301# at the end. As an alternative, to deal with interpreted daemons
302# using perl, the basename of the interpreter plus a colon is also
303# tried as the prefix to procname.
304#
305_find_processes()
306{
307 if [ $# -ne 3 ]; then
308 err 3 'USAGE: _find_processes procname interpreter psargs'
309 fi
310 _procname=$1
311 _interpreter=$2
312 _psargs=$3
313
314 _pref=
315 if [ $_interpreter != "." ]; then # an interpreted script
316 _script=${_chroot}${_chroot:+"/"}$_procname
317 if [ -r $_script ]; then
318 read _interp < $_script # read interpreter name
319 case "$_interp" in
320 \#!*)
321 _interp=${_interp#\#!} # strip #!
322 set -- $_interp
323 case $1 in
324 */bin/env)
325 shift # drop env to get real name
326 ;;
327 esac
328 if [ $_interpreter != $1 ]; then
329 warn "\$command_interpreter $_interpreter != $1"
330 fi
331 ;;
332 *)
333 warn "no shebang line in $_script"
334 set -- $_interpreter
335 ;;
336 esac
337 else
338 warn "cannot read shebang line from $_script"
339 set -- $_interpreter
340 fi
341 _interp="$* $_procname" # cleanup spaces, add _procname
342 _interpbn=${1##*/}
343 _fp_args='_argv'
344 _fp_match='case "$_argv" in
345 ${_interp}|"${_interp} "*|"${_interpbn}: ${_procname}"*)'
346 else # a normal daemon
347 _procnamebn=${_procname##*/}
348 _fp_args='_arg0 _argv'
349 _fp_match='case "$_arg0" in
350 $_procname|$_procnamebn|${_procnamebn}:|"(${_procnamebn})"|"[${_procnamebn}]")'
351 fi
352
353 _proccheck="\
354 $PS 2>/dev/null -o pid= -o jid= -o command= $_psargs"' |
355 while read _npid _jid '"$_fp_args"'; do
356 '"$_fp_match"'
357 if [ "$JID" -eq "$_jid" ];
358 then echo -n "$_pref$_npid";
359 _pref=" ";
360 fi
361 ;;
362 esac
363 done'
364
365# debug "in _find_processes: proccheck is ($_proccheck)."
366 eval $_proccheck
367}
368
369#
370# wait_for_pids pid [pid ...]
371# spins until none of the pids exist
372#
373wait_for_pids()
374{
375 _list="$@"
376 if [ -z "$_list" ]; then
377 return
378 fi
379 _prefix=
380 while true; do
381 _nlist="";
382 for _j in $_list; do
383 if kill -0 $_j 2>/dev/null; then
384 _nlist="${_nlist}${_nlist:+ }$_j"
385 fi
386 done
387 if [ -z "$_nlist" ]; then
388 break
389 fi
390 _list=$_nlist
391 echo -n ${_prefix:-"Waiting for PIDS: "}$_list
392 _prefix=", "
393 sleep 2
394 done
395 if [ -n "$_prefix" ]; then
396 echo "."
397 fi
398}
399
400#
401# check_startmsgs
402# If rc_quiet is set (usually as a result of using faststart at
403# boot time) check if rc_startmsgs is enabled.
404#
405check_startmsgs()
406{
407 if [ -n "$rc_quiet" ]; then
408 checkyesno rc_startmsgs
409 else
410 return 0
411 fi
412}
413
414#
401# run_rc_command argument
402# Search for argument in the list of supported commands, which is:
403# "start stop restart rcvar status poll ${extra_commands}"
404# If there's a match, run ${argument}_cmd or the default method
405# (see below).
406#
407# If argument has a given prefix, then change the operation as follows:
408# Prefix Operation
409# ------ ---------
410# fast Skip the pid check, and set rc_fast=yes, rc_quiet=yes
411# force Set ${rcvar} to YES, and set rc_force=yes
412# one Set ${rcvar} to YES
413# quiet Don't output some diagnostics, and set rc_quiet=yes
414#
415# The following globals are used:
416#
417# Name Needed Purpose
418# ---- ------ -------
419# name y Name of script.
420#
421# command n Full path to command.
422# Not needed if ${rc_arg}_cmd is set for
423# each keyword.
424#
425# command_args n Optional args/shell directives for command.
426#
427# command_interpreter n If not empty, command is interpreted, so
428# call check_{pidfile,process}() appropriately.
429#
430# desc n Description of script.
431#
432# extra_commands n List of extra commands supported.
433#
434# pidfile n If set, use check_pidfile $pidfile $command,
435# otherwise use check_process $command.
436# In either case, only check if $command is set.
437#
438# procname n Process name to check for instead of $command.
439#
440# rcvar n This is checked with checkyesno to determine
441# if the action should be run.
442#
443# ${name}_program n Full path to command.
444# Meant to be used in /etc/rc.conf to override
445# ${command}.
446#
447# ${name}_chroot n Directory to chroot to before running ${command}
448# Requires /usr to be mounted.
449#
450# ${name}_chdir n Directory to cd to before running ${command}
451# (if not using ${name}_chroot).
452#
453# ${name}_flags n Arguments to call ${command} with.
454# NOTE: $flags from the parent environment
455# can be used to override this.
456#
457# ${name}_nice n Nice level to run ${command} at.
458#
459# ${name}_user n User to run ${command} as, using su(1) if not
460# using ${name}_chroot.
461# Requires /usr to be mounted.
462#
463# ${name}_group n Group to run chrooted ${command} as.
464# Requires /usr to be mounted.
465#
466# ${name}_groups n Comma separated list of supplementary groups
467# to run the chrooted ${command} with.
468# Requires /usr to be mounted.
469#
470# ${rc_arg}_cmd n If set, use this as the method when invoked;
471# Otherwise, use default command (see below)
472#
473# ${rc_arg}_precmd n If set, run just before performing the
474# ${rc_arg}_cmd method in the default
475# operation (i.e, after checking for required
476# bits and process (non)existence).
477# If this completes with a non-zero exit code,
478# don't run ${rc_arg}_cmd.
479#
480# ${rc_arg}_postcmd n If set, run just after performing the
481# ${rc_arg}_cmd method, if that method
482# returned a zero exit code.
483#
484# required_dirs n If set, check for the existence of the given
485# directories before running a (re)start command.
486#
487# required_files n If set, check for the readability of the given
488# files before running a (re)start command.
489#
490# required_modules n If set, ensure the given kernel modules are
491# loaded before running a (re)start command.
492# The check and possible loads are actually
493# done after start_precmd so that the modules
494# aren't loaded in vain, should the precmd
495# return a non-zero status to indicate a error.
496# If a word in the list looks like "foo:bar",
497# "foo" is the KLD file name and "bar" is the
498# module name. If a word looks like "foo~bar",
499# "foo" is the KLD file name and "bar" is a
500# egrep(1) pattern matching the module name.
501# Otherwise the module name is assumed to be
502# the same as the KLD file name, which is most
503# common. See load_kld().
504#
505# required_vars n If set, perform checkyesno on each of the
506# listed variables before running the default
507# (re)start command.
508#
509# Default behaviour for a given argument, if no override method is
510# provided:
511#
512# Argument Default behaviour
513# -------- -----------------
514# start if !running && checkyesno ${rcvar}
515# ${command}
516#
517# stop if ${pidfile}
518# rc_pid=$(check_pidfile $pidfile $command)
519# else
520# rc_pid=$(check_process $command)
521# kill $sig_stop $rc_pid
522# wait_for_pids $rc_pid
523# ($sig_stop defaults to TERM.)
524#
525# reload Similar to stop, except use $sig_reload instead,
526# and doesn't wait_for_pids.
527# $sig_reload defaults to HUP.
528# Note that `reload' isn't provided by default,
529# it should be enabled via $extra_commands.
530#
531# restart Run `stop' then `start'.
532#
533# status Show if ${command} is running, etc.
534#
535# poll Wait for ${command} to exit.
536#
537# rcvar Display what rc.conf variable is used (if any).
538#
539# Variables available to methods, and after run_rc_command() has
540# completed:
541#
542# Variable Purpose
543# -------- -------
544# rc_arg Argument to command, after fast/force/one processing
545# performed
546#
547# rc_flags Flags to start the default command with.
548# Defaults to ${name}_flags, unless overridden
549# by $flags from the environment.
550# This variable may be changed by the precmd method.
551#
552# rc_pid PID of command (if appropriate)
553#
554# rc_fast Not empty if "fast" was provided (q.v.)
555#
556# rc_force Not empty if "force" was provided (q.v.)
557#
558# rc_quiet Not empty if "quiet" was provided
559#
560#
561run_rc_command()
562{
563 _return=0
564 rc_arg=$1
565 if [ -z "$name" ]; then
566 err 3 'run_rc_command: $name is not set.'
567 fi
568
569 # Don't repeat the first argument when passing additional command-
570 # line arguments to the command subroutines.
571 #
572 shift 1
573 rc_extra_args="$*"
574
575 _rc_prefix=
576 case "$rc_arg" in
577 fast*) # "fast" prefix; don't check pid
578 rc_arg=${rc_arg#fast}
579 rc_fast=yes
580 rc_quiet=yes
581 ;;
582 force*) # "force prefix; always run
583 rc_force=yes
584 _rc_prefix=force
585 rc_arg=${rc_arg#${_rc_prefix}}
586 if [ -n "${rcvar}" ]; then
587 eval ${rcvar}=YES
588 fi
589 ;;
590 one*) # "one" prefix; set ${rcvar}=yes
591 _rc_prefix=one
592 rc_arg=${rc_arg#${_rc_prefix}}
593 if [ -n "${rcvar}" ]; then
594 eval ${rcvar}=YES
595 fi
596 ;;
597 quiet*) # "quiet" prefix; omit some messages
598 _rc_prefix=quiet
599 rc_arg=${rc_arg#${_rc_prefix}}
600 rc_quiet=yes
601 ;;
602 esac
603
604 eval _override_command=\$${name}_program
605 command=${command:+${_override_command:-$command}}
606
607 _keywords="start stop restart rcvar $extra_commands"
608 rc_pid=
609 _pidcmd=
610 _procname=${procname:-${command}}
611
612 # setup pid check command
613 if [ -n "$_procname" ]; then
614 if [ -n "$pidfile" ]; then
615 _pidcmd='rc_pid=$(check_pidfile '"$pidfile $_procname $command_interpreter"')'
616 else
617 _pidcmd='rc_pid=$(check_process '"$_procname $command_interpreter"')'
618 fi
619 if [ -n "$_pidcmd" ]; then
620 _keywords="${_keywords} status poll"
621 fi
622 fi
623
624 if [ -z "$rc_arg" ]; then
625 rc_usage $_keywords
626 fi
627
628 if [ -n "$flags" ]; then # allow override from environment
629 rc_flags=$flags
630 else
631 eval rc_flags=\$${name}_flags
632 fi
633 eval _chdir=\$${name}_chdir _chroot=\$${name}_chroot \
634 _nice=\$${name}_nice _user=\$${name}_user \
635 _group=\$${name}_group _groups=\$${name}_groups
636
637 if [ -n "$_user" ]; then # unset $_user if running as that user
638 if [ "$_user" = "$(eval $IDCMD)" ]; then
639 unset _user
640 fi
641 fi
642
643 eval $_pidcmd # determine the pid if necessary
644
645 for _elem in $_keywords; do
646 if [ "$_elem" != "$rc_arg" ]; then
647 continue
648 fi
649 # if ${rcvar} is set, and $1 is not
650 # "rcvar", then run
651 # checkyesno ${rcvar}
652 # and return if that failed
653 #
654 if [ -n "${rcvar}" -a "$rc_arg" != "rcvar" ]; then
655 if ! checkyesno ${rcvar}; then
656 if [ -n "${rc_quiet}" ]; then
657 return 0
658 fi
659 echo -n "Cannot '${rc_arg}' $name. Set ${rcvar} to "
660 echo -n "YES in /etc/rc.conf or use 'one${rc_arg}' "
661 echo "instead of '${rc_arg}'."
662 return 0
663 fi
664 fi
665
666 # if there's a custom ${XXX_cmd},
667 # run that instead of the default
668 #
669 eval _cmd=\$${rc_arg}_cmd \
670 _precmd=\$${rc_arg}_precmd \
671 _postcmd=\$${rc_arg}_postcmd
672
673 if [ -n "$_cmd" ]; then
674 _run_rc_precmd || return 1
675 _run_rc_doit "$_cmd $rc_extra_args" || return 1
676 _run_rc_postcmd
677 return $_return
678 fi
679
680 case "$rc_arg" in # default operations...
681
682 status)
683 _run_rc_precmd || return 1
684 if [ -n "$rc_pid" ]; then
685 echo "${name} is running as pid $rc_pid."
686 else
687 echo "${name} is not running."
688 return 1
689 fi
690 _run_rc_postcmd
691 ;;
692
693 start)
694 if [ -z "$rc_fast" -a -n "$rc_pid" ]; then
695 echo 1>&2 "${name} already running? (pid=$rc_pid)."
696 return 1
697 fi
698
699 if [ ! -x ${_chroot}${_chroot:+"/"}${command} ]; then
700 warn "run_rc_command: cannot run $command"
701 return 1
702 fi
703
704 if ! _run_rc_precmd; then
705 warn "failed precmd routine for ${name}"
706 return 1
707 fi
708
709 # setup the full command to run
710 #
415# run_rc_command argument
416# Search for argument in the list of supported commands, which is:
417# "start stop restart rcvar status poll ${extra_commands}"
418# If there's a match, run ${argument}_cmd or the default method
419# (see below).
420#
421# If argument has a given prefix, then change the operation as follows:
422# Prefix Operation
423# ------ ---------
424# fast Skip the pid check, and set rc_fast=yes, rc_quiet=yes
425# force Set ${rcvar} to YES, and set rc_force=yes
426# one Set ${rcvar} to YES
427# quiet Don't output some diagnostics, and set rc_quiet=yes
428#
429# The following globals are used:
430#
431# Name Needed Purpose
432# ---- ------ -------
433# name y Name of script.
434#
435# command n Full path to command.
436# Not needed if ${rc_arg}_cmd is set for
437# each keyword.
438#
439# command_args n Optional args/shell directives for command.
440#
441# command_interpreter n If not empty, command is interpreted, so
442# call check_{pidfile,process}() appropriately.
443#
444# desc n Description of script.
445#
446# extra_commands n List of extra commands supported.
447#
448# pidfile n If set, use check_pidfile $pidfile $command,
449# otherwise use check_process $command.
450# In either case, only check if $command is set.
451#
452# procname n Process name to check for instead of $command.
453#
454# rcvar n This is checked with checkyesno to determine
455# if the action should be run.
456#
457# ${name}_program n Full path to command.
458# Meant to be used in /etc/rc.conf to override
459# ${command}.
460#
461# ${name}_chroot n Directory to chroot to before running ${command}
462# Requires /usr to be mounted.
463#
464# ${name}_chdir n Directory to cd to before running ${command}
465# (if not using ${name}_chroot).
466#
467# ${name}_flags n Arguments to call ${command} with.
468# NOTE: $flags from the parent environment
469# can be used to override this.
470#
471# ${name}_nice n Nice level to run ${command} at.
472#
473# ${name}_user n User to run ${command} as, using su(1) if not
474# using ${name}_chroot.
475# Requires /usr to be mounted.
476#
477# ${name}_group n Group to run chrooted ${command} as.
478# Requires /usr to be mounted.
479#
480# ${name}_groups n Comma separated list of supplementary groups
481# to run the chrooted ${command} with.
482# Requires /usr to be mounted.
483#
484# ${rc_arg}_cmd n If set, use this as the method when invoked;
485# Otherwise, use default command (see below)
486#
487# ${rc_arg}_precmd n If set, run just before performing the
488# ${rc_arg}_cmd method in the default
489# operation (i.e, after checking for required
490# bits and process (non)existence).
491# If this completes with a non-zero exit code,
492# don't run ${rc_arg}_cmd.
493#
494# ${rc_arg}_postcmd n If set, run just after performing the
495# ${rc_arg}_cmd method, if that method
496# returned a zero exit code.
497#
498# required_dirs n If set, check for the existence of the given
499# directories before running a (re)start command.
500#
501# required_files n If set, check for the readability of the given
502# files before running a (re)start command.
503#
504# required_modules n If set, ensure the given kernel modules are
505# loaded before running a (re)start command.
506# The check and possible loads are actually
507# done after start_precmd so that the modules
508# aren't loaded in vain, should the precmd
509# return a non-zero status to indicate a error.
510# If a word in the list looks like "foo:bar",
511# "foo" is the KLD file name and "bar" is the
512# module name. If a word looks like "foo~bar",
513# "foo" is the KLD file name and "bar" is a
514# egrep(1) pattern matching the module name.
515# Otherwise the module name is assumed to be
516# the same as the KLD file name, which is most
517# common. See load_kld().
518#
519# required_vars n If set, perform checkyesno on each of the
520# listed variables before running the default
521# (re)start command.
522#
523# Default behaviour for a given argument, if no override method is
524# provided:
525#
526# Argument Default behaviour
527# -------- -----------------
528# start if !running && checkyesno ${rcvar}
529# ${command}
530#
531# stop if ${pidfile}
532# rc_pid=$(check_pidfile $pidfile $command)
533# else
534# rc_pid=$(check_process $command)
535# kill $sig_stop $rc_pid
536# wait_for_pids $rc_pid
537# ($sig_stop defaults to TERM.)
538#
539# reload Similar to stop, except use $sig_reload instead,
540# and doesn't wait_for_pids.
541# $sig_reload defaults to HUP.
542# Note that `reload' isn't provided by default,
543# it should be enabled via $extra_commands.
544#
545# restart Run `stop' then `start'.
546#
547# status Show if ${command} is running, etc.
548#
549# poll Wait for ${command} to exit.
550#
551# rcvar Display what rc.conf variable is used (if any).
552#
553# Variables available to methods, and after run_rc_command() has
554# completed:
555#
556# Variable Purpose
557# -------- -------
558# rc_arg Argument to command, after fast/force/one processing
559# performed
560#
561# rc_flags Flags to start the default command with.
562# Defaults to ${name}_flags, unless overridden
563# by $flags from the environment.
564# This variable may be changed by the precmd method.
565#
566# rc_pid PID of command (if appropriate)
567#
568# rc_fast Not empty if "fast" was provided (q.v.)
569#
570# rc_force Not empty if "force" was provided (q.v.)
571#
572# rc_quiet Not empty if "quiet" was provided
573#
574#
575run_rc_command()
576{
577 _return=0
578 rc_arg=$1
579 if [ -z "$name" ]; then
580 err 3 'run_rc_command: $name is not set.'
581 fi
582
583 # Don't repeat the first argument when passing additional command-
584 # line arguments to the command subroutines.
585 #
586 shift 1
587 rc_extra_args="$*"
588
589 _rc_prefix=
590 case "$rc_arg" in
591 fast*) # "fast" prefix; don't check pid
592 rc_arg=${rc_arg#fast}
593 rc_fast=yes
594 rc_quiet=yes
595 ;;
596 force*) # "force prefix; always run
597 rc_force=yes
598 _rc_prefix=force
599 rc_arg=${rc_arg#${_rc_prefix}}
600 if [ -n "${rcvar}" ]; then
601 eval ${rcvar}=YES
602 fi
603 ;;
604 one*) # "one" prefix; set ${rcvar}=yes
605 _rc_prefix=one
606 rc_arg=${rc_arg#${_rc_prefix}}
607 if [ -n "${rcvar}" ]; then
608 eval ${rcvar}=YES
609 fi
610 ;;
611 quiet*) # "quiet" prefix; omit some messages
612 _rc_prefix=quiet
613 rc_arg=${rc_arg#${_rc_prefix}}
614 rc_quiet=yes
615 ;;
616 esac
617
618 eval _override_command=\$${name}_program
619 command=${command:+${_override_command:-$command}}
620
621 _keywords="start stop restart rcvar $extra_commands"
622 rc_pid=
623 _pidcmd=
624 _procname=${procname:-${command}}
625
626 # setup pid check command
627 if [ -n "$_procname" ]; then
628 if [ -n "$pidfile" ]; then
629 _pidcmd='rc_pid=$(check_pidfile '"$pidfile $_procname $command_interpreter"')'
630 else
631 _pidcmd='rc_pid=$(check_process '"$_procname $command_interpreter"')'
632 fi
633 if [ -n "$_pidcmd" ]; then
634 _keywords="${_keywords} status poll"
635 fi
636 fi
637
638 if [ -z "$rc_arg" ]; then
639 rc_usage $_keywords
640 fi
641
642 if [ -n "$flags" ]; then # allow override from environment
643 rc_flags=$flags
644 else
645 eval rc_flags=\$${name}_flags
646 fi
647 eval _chdir=\$${name}_chdir _chroot=\$${name}_chroot \
648 _nice=\$${name}_nice _user=\$${name}_user \
649 _group=\$${name}_group _groups=\$${name}_groups
650
651 if [ -n "$_user" ]; then # unset $_user if running as that user
652 if [ "$_user" = "$(eval $IDCMD)" ]; then
653 unset _user
654 fi
655 fi
656
657 eval $_pidcmd # determine the pid if necessary
658
659 for _elem in $_keywords; do
660 if [ "$_elem" != "$rc_arg" ]; then
661 continue
662 fi
663 # if ${rcvar} is set, and $1 is not
664 # "rcvar", then run
665 # checkyesno ${rcvar}
666 # and return if that failed
667 #
668 if [ -n "${rcvar}" -a "$rc_arg" != "rcvar" ]; then
669 if ! checkyesno ${rcvar}; then
670 if [ -n "${rc_quiet}" ]; then
671 return 0
672 fi
673 echo -n "Cannot '${rc_arg}' $name. Set ${rcvar} to "
674 echo -n "YES in /etc/rc.conf or use 'one${rc_arg}' "
675 echo "instead of '${rc_arg}'."
676 return 0
677 fi
678 fi
679
680 # if there's a custom ${XXX_cmd},
681 # run that instead of the default
682 #
683 eval _cmd=\$${rc_arg}_cmd \
684 _precmd=\$${rc_arg}_precmd \
685 _postcmd=\$${rc_arg}_postcmd
686
687 if [ -n "$_cmd" ]; then
688 _run_rc_precmd || return 1
689 _run_rc_doit "$_cmd $rc_extra_args" || return 1
690 _run_rc_postcmd
691 return $_return
692 fi
693
694 case "$rc_arg" in # default operations...
695
696 status)
697 _run_rc_precmd || return 1
698 if [ -n "$rc_pid" ]; then
699 echo "${name} is running as pid $rc_pid."
700 else
701 echo "${name} is not running."
702 return 1
703 fi
704 _run_rc_postcmd
705 ;;
706
707 start)
708 if [ -z "$rc_fast" -a -n "$rc_pid" ]; then
709 echo 1>&2 "${name} already running? (pid=$rc_pid)."
710 return 1
711 fi
712
713 if [ ! -x ${_chroot}${_chroot:+"/"}${command} ]; then
714 warn "run_rc_command: cannot run $command"
715 return 1
716 fi
717
718 if ! _run_rc_precmd; then
719 warn "failed precmd routine for ${name}"
720 return 1
721 fi
722
723 # setup the full command to run
724 #
711 _show_startmsgs=1
712 if [ -n "${rc_quiet}" ]; then
713 if ! checkyesno rc_startmsgs; then
714 unset _show_startmsgs
715 fi
716 fi
717 [ -n "$_show_startmsgs" ] && echo "Starting ${name}."
725 check_startmsgs && echo "Starting ${name}."
718 if [ -n "$_chroot" ]; then
719 _doit="\
720${_nice:+nice -n $_nice }\
721chroot ${_user:+-u $_user }${_group:+-g $_group }${_groups:+-G $_groups }\
722$_chroot $command $rc_flags $command_args"
723 else
724 _doit="\
725${_chdir:+cd $_chdir && }\
726$command $rc_flags $command_args"
727 if [ -n "$_user" ]; then
728 _doit="su -m $_user -c 'sh -c \"$_doit\"'"
729 fi
730 if [ -n "$_nice" ]; then
731 if [ -z "$_user" ]; then
732 _doit="sh -c \"$_doit\""
733 fi
734 _doit="nice -n $_nice $_doit"
735 fi
736 fi
737
738 # run the full command
739 #
740 if ! _run_rc_doit "$_doit"; then
741 warn "failed to start ${name}"
742 return 1
743 fi
744
745 # finally, run postcmd
746 #
747 _run_rc_postcmd
748 ;;
749
750 stop)
751 if [ -z "$rc_pid" ]; then
752 [ -n "$rc_fast" ] && return 0
753 _run_rc_notrunning
754 return 1
755 fi
756
757 _run_rc_precmd || return 1
758
759 # send the signal to stop
760 #
761 echo "Stopping ${name}."
762 _doit=$(_run_rc_killcmd "${sig_stop:-TERM}")
763 _run_rc_doit "$_doit" || return 1
764
765 # wait for the command to exit,
766 # and run postcmd.
767 wait_for_pids $rc_pid
768
769 _run_rc_postcmd
770 ;;
771
772 reload)
773 if [ -z "$rc_pid" ]; then
774 _run_rc_notrunning
775 return 1
776 fi
777
778 _run_rc_precmd || return 1
779
780 _doit=$(_run_rc_killcmd "${sig_reload:-HUP}")
781 _run_rc_doit "$_doit" || return 1
782
783 _run_rc_postcmd
784 ;;
785
786 restart)
787 # prevent restart being called more
788 # than once by any given script
789 #
790 if ${_rc_restart_done:-false}; then
791 return 0
792 fi
793 _rc_restart_done=true
794
795 _run_rc_precmd || return 1
796
797 # run those in a subshell to keep global variables
798 ( run_rc_command ${_rc_prefix}stop $rc_extra_args )
799 ( run_rc_command ${_rc_prefix}start $rc_extra_args )
800 _return=$?
801 [ $_return -ne 0 ] && [ -z "$rc_force" ] && return 1
802
803 _run_rc_postcmd
804 ;;
805
806 poll)
807 _run_rc_precmd || return 1
808 if [ -n "$rc_pid" ]; then
809 wait_for_pids $rc_pid
810 fi
811 _run_rc_postcmd
812 ;;
813
814 rcvar)
815 echo -n "# $name"
816 if [ -n "$desc" ]; then
817 echo " : $desc"
818 else
819 echo ""
820 fi
821 echo "#"
822 # Get unique vars in $rcvar $rcvars
823 for _v in $rcvar $rcvars; do
824 case $v in
825 $_v\ *|\ *$_v|*\ $_v\ *) ;;
826 *) v="${v# } $_v" ;;
827 esac
828 done
829
830 # Display variables.
831 for _v in $v; do
832 if [ -z "$_v" ]; then
833 continue
834 fi
835
836 eval _desc=\$${_v}_desc
837 eval _defval=\$${_v}_defval
838 _h="-"
839
840 eval echo \"$_v=\\\"\$$_v\\\"\"
841 # decode multiple lines of _desc
842 while [ -n "$_desc" ]; do
843 case $_desc in
844 *^^*)
845 echo "# $_h ${_desc%%^^*}"
846 _desc=${_desc#*^^}
847 _h=" "
848 ;;
849 *)
850 echo "# $_h ${_desc}"
851 break
852 ;;
853 esac
854 done
855 echo "# (default: \"$_defval\")"
856 done
857 echo ""
858 ;;
859
860 *)
861 rc_usage $_keywords
862 ;;
863
864 esac
865 return $_return
866 done
867
868 echo 1>&2 "$0: unknown directive '$rc_arg'."
869 rc_usage $_keywords
870 # not reached
871}
872
873#
874# Helper functions for run_rc_command: common code.
875# They use such global variables besides the exported rc_* ones:
876#
877# name R/W
878# ------------------
879# _precmd R
880# _postcmd R
881# _return W
882#
883_run_rc_precmd()
884{
885 check_required_before "$rc_arg" || return 1
886
887 if [ -n "$_precmd" ]; then
888 debug "run_rc_command: ${rc_arg}_precmd: $_precmd $rc_extra_args"
889 eval "$_precmd $rc_extra_args"
890 _return=$?
891
892 # If precmd failed and force isn't set, request exit.
893 if [ $_return -ne 0 ] && [ -z "$rc_force" ]; then
894 return 1
895 fi
896 fi
897
898 check_required_after "$rc_arg" || return 1
899
900 return 0
901}
902
903_run_rc_postcmd()
904{
905 if [ -n "$_postcmd" ]; then
906 debug "run_rc_command: ${rc_arg}_postcmd: $_postcmd $rc_extra_args"
907 eval "$_postcmd $rc_extra_args"
908 _return=$?
909 fi
910 return 0
911}
912
913_run_rc_doit()
914{
915 debug "run_rc_command: doit: $*"
916 eval "$@"
917 _return=$?
918
919 # If command failed and force isn't set, request exit.
920 if [ $_return -ne 0 ] && [ -z "$rc_force" ]; then
921 return 1
922 fi
923
924 return 0
925}
926
927_run_rc_notrunning()
928{
929 local _pidmsg
930
931 if [ -n "$pidfile" ]; then
932 _pidmsg=" (check $pidfile)."
933 else
934 _pidmsg=
935 fi
936 echo 1>&2 "${name} not running?${_pidmsg}"
937}
938
939_run_rc_killcmd()
940{
941 local _cmd
942
943 _cmd="kill -$1 $rc_pid"
944 if [ -n "$_user" ]; then
945 _cmd="su -m ${_user} -c 'sh -c \"${_cmd}\"'"
946 fi
947 echo "$_cmd"
948}
949
950#
951# run_rc_script file arg
952# Start the script `file' with `arg', and correctly handle the
953# return value from the script. If `file' ends with `.sh', it's
954# sourced into the current environment. If `file' appears to be
955# a backup or scratch file, ignore it. Otherwise if it's
956# executable run as a child process.
957#
958run_rc_script()
959{
960 _file=$1
961 _arg=$2
962 if [ -z "$_file" -o -z "$_arg" ]; then
963 err 3 'USAGE: run_rc_script file arg'
964 fi
965
966 unset name command command_args command_interpreter \
967 extra_commands pidfile procname \
968 rcvar rcvars rcvars_obsolete required_dirs required_files \
969 required_vars
970 eval unset ${_arg}_cmd ${_arg}_precmd ${_arg}_postcmd
971
972 case "$_file" in
973 /etc/rc.d/*.sh) # no longer allowed in the base
974 warn "Ignoring old-style startup script $_file"
975 ;;
976 *[~#]|*.OLD|*.bak|*.orig|*,v) # scratch file; skip
977 warn "Ignoring scratch file $_file"
978 ;;
979 *) # run in subshell
980 if [ -x $_file ]; then
981 if [ -n "$rc_fast_and_loose" ]; then
982 set $_arg; . $_file
983 else
984 ( trap "echo Script $_file interrupted; kill -QUIT $$" 3
985 trap "echo Script $_file interrupted; exit 1" 2
986 trap "echo Script $_file running" 29
987 set $_arg; . $_file )
988 fi
989 fi
990 ;;
991 esac
992}
993
994#
995# load_rc_config name
996# Source in the configuration file for a given name.
997#
998load_rc_config()
999{
1000 local _name _var _defval _v _msg _new
1001 _name=$1
1002 if [ -z "$_name" ]; then
1003 err 3 'USAGE: load_rc_config name'
1004 fi
1005
1006 if ${_rc_conf_loaded:-false}; then
1007 :
1008 else
1009 if [ -r /etc/defaults/rc.conf ]; then
1010 debug "Sourcing /etc/defaults/rc.conf"
1011 . /etc/defaults/rc.conf
1012 source_rc_confs
1013 elif [ -r /etc/rc.conf ]; then
1014 debug "Sourcing /etc/rc.conf (/etc/defaults/rc.conf doesn't exist)."
1015 . /etc/rc.conf
1016 fi
1017 _rc_conf_loaded=true
1018 fi
1019 if [ -f /etc/rc.conf.d/"$_name" ]; then
1020 debug "Sourcing /etc/rc.conf.d/${_name}"
1021 . /etc/rc.conf.d/"$_name"
1022 fi
1023
1024 # Old variable names support
1025 #
1026 [ -n "$enable_quotas" ] && quota_enable="$enable_quotas"
1027
1028 # Set defaults if defined.
1029 for _var in $rcvar $rcvars; do
1030 _defval=`eval echo "\\\$${_var}_defval"`
1031 if [ -n "$_defval" ]; then
1032 eval : \${$_var:=\$${_var}_defval}
1033 fi
1034 done
1035
1036 # check obsolete rc.conf variables
1037 for _var in $rcvars_obsolete; do
1038 _v=`eval echo \\$$_var`
1039 _msg=`eval echo \\$${_var}_obsolete_msg`
1040 _new=`eval echo \\$${_var}_newvar`
1041 case $_v in
1042 "")
1043 ;;
1044 *)
1045 if [ -z "$_new" ]; then
1046 _msg="Ignored."
1047 else
1048 eval $_new=\"\$$_var\"
1049 if [ -z "$_msg" ]; then
1050 _msg="Use \$$_new instead."
1051 fi
1052 fi
1053 warn "\$$_var is obsolete. $_msg"
1054 ;;
1055 esac
1056 done
1057}
1058
1059#
1060# load_rc_config_var name var
1061# Read the rc.conf(5) var for name and set in the
1062# current shell, using load_rc_config in a subshell to prevent
1063# unwanted side effects from other variable assignments.
1064#
1065load_rc_config_var()
1066{
1067 if [ $# -ne 2 ]; then
1068 err 3 'USAGE: load_rc_config_var name var'
1069 fi
1070 eval $(eval '(
1071 load_rc_config '$1' >/dev/null;
1072 if [ -n "${'$2'}" -o "${'$2'-UNSET}" != "UNSET" ]; then
1073 echo '$2'=\'\''${'$2'}\'\'';
1074 fi
1075 )' )
1076}
1077
1078#
1079# rc_usage commands
1080# Print a usage string for $0, with `commands' being a list of
1081# valid commands.
1082#
1083rc_usage()
1084{
1085 echo -n 1>&2 "Usage: $0 [fast|force|one]("
1086
1087 _sep=
1088 for _elem; do
1089 echo -n 1>&2 "$_sep$_elem"
1090 _sep="|"
1091 done
1092 echo 1>&2 ")"
1093 exit 1
1094}
1095
1096#
1097# err exitval message
1098# Display message to stderr and log to the syslog, and exit with exitval.
1099#
1100err()
1101{
1102 exitval=$1
1103 shift
1104
1105 if [ -x /usr/bin/logger ]; then
1106 logger "$0: ERROR: $*"
1107 fi
1108 echo 1>&2 "$0: ERROR: $*"
1109 exit $exitval
1110}
1111
1112#
1113# warn message
1114# Display message to stderr and log to the syslog.
1115#
1116warn()
1117{
1118 if [ -x /usr/bin/logger ]; then
1119 logger "$0: WARNING: $*"
1120 fi
1121 echo 1>&2 "$0: WARNING: $*"
1122}
1123
1124#
1125# info message
1126# Display informational message to stdout and log to syslog.
1127#
1128info()
1129{
1130 case ${rc_info} in
1131 [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
1132 if [ -x /usr/bin/logger ]; then
1133 logger "$0: INFO: $*"
1134 fi
1135 echo "$0: INFO: $*"
1136 ;;
1137 esac
1138}
1139
1140#
1141# debug message
1142# If debugging is enabled in rc.conf output message to stderr.
1143# BEWARE that you don't call any subroutine that itself calls this
1144# function.
1145#
1146debug()
1147{
1148 case ${rc_debug} in
1149 [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
1150 if [ -x /usr/bin/logger ]; then
1151 logger "$0: DEBUG: $*"
1152 fi
1153 echo 1>&2 "$0: DEBUG: $*"
1154 ;;
1155 esac
1156}
1157
1158#
1159# backup_file action file cur backup
1160# Make a backup copy of `file' into `cur', and save the previous
1161# version of `cur' as `backup' or use rcs for archiving.
1162#
1163# This routine checks the value of the backup_uses_rcs variable,
1164# which can be either YES or NO.
1165#
1166# The `action' keyword can be one of the following:
1167#
1168# add `file' is now being backed up (and is possibly
1169# being reentered into the backups system). `cur'
1170# is created and RCS files, if necessary, are
1171# created as well.
1172#
1173# update `file' has changed and needs to be backed up.
1174# If `cur' exists, it is copied to to `back' or
1175# checked into RCS (if the repository file is old),
1176# and then `file' is copied to `cur'. Another RCS
1177# check in done here if RCS is being used.
1178#
1179# remove `file' is no longer being tracked by the backups
1180# system. If RCS is not being used, `cur' is moved
1181# to `back', otherwise an empty file is checked in,
1182# and then `cur' is removed.
1183#
1184#
1185backup_file()
1186{
1187 _action=$1
1188 _file=$2
1189 _cur=$3
1190 _back=$4
1191
1192 if checkyesno backup_uses_rcs; then
1193 _msg0="backup archive"
1194 _msg1="update"
1195
1196 # ensure that history file is not locked
1197 if [ -f $_cur,v ]; then
1198 rcs -q -u -U -M $_cur
1199 fi
1200
1201 # ensure after switching to rcs that the
1202 # current backup is not lost
1203 if [ -f $_cur ]; then
1204 # no archive, or current newer than archive
1205 if [ ! -f $_cur,v -o $_cur -nt $_cur,v ]; then
1206 ci -q -f -u -t-"$_msg0" -m"$_msg1" $_cur
1207 rcs -q -kb -U $_cur
1208 co -q -f -u $_cur
1209 fi
1210 fi
1211
1212 case $_action in
1213 add|update)
1214 cp -p $_file $_cur
1215 ci -q -f -u -t-"$_msg0" -m"$_msg1" $_cur
1216 rcs -q -kb -U $_cur
1217 co -q -f -u $_cur
1218 chown root:wheel $_cur $_cur,v
1219 ;;
1220 remove)
1221 cp /dev/null $_cur
1222 ci -q -f -u -t-"$_msg0" -m"$_msg1" $_cur
1223 rcs -q -kb -U $_cur
1224 chown root:wheel $_cur $_cur,v
1225 rm $_cur
1226 ;;
1227 esac
1228 else
1229 case $_action in
1230 add|update)
1231 if [ -f $_cur ]; then
1232 cp -p $_cur $_back
1233 fi
1234 cp -p $_file $_cur
1235 chown root:wheel $_cur
1236 ;;
1237 remove)
1238 mv -f $_cur $_back
1239 ;;
1240 esac
1241 fi
1242}
1243
1244# make_symlink src link
1245# Make a symbolic link 'link' to src from basedir. If the
1246# directory in which link is to be created does not exist
1247# a warning will be displayed and an error will be returned.
1248# Returns 0 on sucess, 1 otherwise.
1249#
1250make_symlink()
1251{
1252 local src link linkdir _me
1253 src="$1"
1254 link="$2"
1255 linkdir="`dirname $link`"
1256 _me="make_symlink()"
1257
1258 if [ -z "$src" -o -z "$link" ]; then
1259 warn "$_me: requires two arguments."
1260 return 1
1261 fi
1262 if [ ! -d "$linkdir" ]; then
1263 warn "$_me: the directory $linkdir does not exist."
1264 return 1
1265 fi
1266 if ! ln -sf $src $link; then
1267 warn "$_me: unable to make a symbolic link from $link to $src"
1268 return 1
1269 fi
1270 return 0
1271}
1272
1273# devfs_rulesets_from_file file
1274# Reads a set of devfs commands from file, and creates
1275# the specified rulesets with their rules. Returns non-zero
1276# if there was an error.
1277#
1278devfs_rulesets_from_file()
1279{
1280 local file _err _me
1281 file="$1"
1282 _me="devfs_rulesets_from_file"
1283 _err=0
1284
1285 if [ -z "$file" ]; then
1286 warn "$_me: you must specify a file"
1287 return 1
1288 fi
1289 if [ ! -e "$file" ]; then
1290 debug "$_me: no such file ($file)"
1291 return 0
1292 fi
1293 debug "reading rulesets from file ($file)"
1294 { while read line
1295 do
1296 case $line in
1297 \#*)
1298 continue
1299 ;;
1300 \[*\]*)
1301 rulenum=`expr "$line" : "\[.*=\([0-9]*\)\]"`
1302 if [ -z "$rulenum" ]; then
1303 warn "$_me: cannot extract rule number ($line)"
1304 _err=1
1305 break
1306 fi
1307 rulename=`expr "$line" : "\[\(.*\)=[0-9]*\]"`
1308 if [ -z "$rulename" ]; then
1309 warn "$_me: cannot extract rule name ($line)"
1310 _err=1
1311 break;
1312 fi
1313 eval $rulename=\$rulenum
1314 debug "found ruleset: $rulename=$rulenum"
1315 if ! /sbin/devfs rule -s $rulenum delset; then
1316 _err=1
1317 break
1318 fi
1319 ;;
1320 *)
1321 rulecmd="${line%%"\#*"}"
1322 # evaluate the command incase it includes
1323 # other rules
1324 if [ -n "$rulecmd" ]; then
1325 debug "adding rule ($rulecmd)"
1326 if ! eval /sbin/devfs rule -s $rulenum $rulecmd
1327 then
1328 _err=1
1329 break
1330 fi
1331 fi
1332 ;;
1333 esac
1334 if [ $_err -ne 0 ]; then
1335 debug "error in $_me"
1336 break
1337 fi
1338 done } < $file
1339 return $_err
1340}
1341
1342# devfs_init_rulesets
1343# Initializes rulesets from configuration files. Returns
1344# non-zero if there was an error.
1345#
1346devfs_init_rulesets()
1347{
1348 local file _me
1349 _me="devfs_init_rulesets"
1350
1351 # Go through this only once
1352 if [ -n "$devfs_rulesets_init" ]; then
1353 debug "$_me: devfs rulesets already initialized"
1354 return
1355 fi
1356 for file in $devfs_rulesets; do
1357 devfs_rulesets_from_file $file || return 1
1358 done
1359 devfs_rulesets_init=1
1360 debug "$_me: devfs rulesets initialized"
1361 return 0
1362}
1363
1364# devfs_set_ruleset ruleset [dir]
1365# Sets the default ruleset of dir to ruleset. The ruleset argument
1366# must be a ruleset name as specified in devfs.rules(5) file.
1367# Returns non-zero if it could not set it successfully.
1368#
1369devfs_set_ruleset()
1370{
1371 local devdir rs _me
1372 [ -n "$1" ] && eval rs=\$$1 || rs=
1373 [ -n "$2" ] && devdir="-m "$2"" || devdir=
1374 _me="devfs_set_ruleset"
1375
1376 if [ -z "$rs" ]; then
1377 warn "$_me: you must specify a ruleset number"
1378 return 1
1379 fi
1380 debug "$_me: setting ruleset ($rs) on mount-point (${devdir#-m })"
1381 if ! /sbin/devfs $devdir ruleset $rs; then
1382 warn "$_me: unable to set ruleset $rs to ${devdir#-m }"
1383 return 1
1384 fi
1385 return 0
1386}
1387
1388# devfs_apply_ruleset ruleset [dir]
1389# Apply ruleset number $ruleset to the devfs mountpoint $dir.
1390# The ruleset argument must be a ruleset name as specified
1391# in a devfs.rules(5) file. Returns 0 on success or non-zero
1392# if it could not apply the ruleset.
1393#
1394devfs_apply_ruleset()
1395{
1396 local devdir rs _me
1397 [ -n "$1" ] && eval rs=\$$1 || rs=
1398 [ -n "$2" ] && devdir="-m "$2"" || devdir=
1399 _me="devfs_apply_ruleset"
1400
1401 if [ -z "$rs" ]; then
1402 warn "$_me: you must specify a ruleset"
1403 return 1
1404 fi
1405 debug "$_me: applying ruleset ($rs) to mount-point (${devdir#-m })"
1406 if ! /sbin/devfs $devdir rule -s $rs applyset; then
1407 warn "$_me: unable to apply ruleset $rs to ${devdir#-m }"
1408 return 1
1409 fi
1410 return 0
1411}
1412
1413# devfs_domount dir [ruleset]
1414# Mount devfs on dir. If ruleset is specified it is set
1415# on the mount-point. It must also be a ruleset name as specified
1416# in a devfs.rules(5) file. Returns 0 on success.
1417#
1418devfs_domount()
1419{
1420 local devdir rs _me
1421 devdir="$1"
1422 [ -n "$2" ] && rs=$2 || rs=
1423 _me="devfs_domount()"
1424
1425 if [ -z "$devdir" ]; then
1426 warn "$_me: you must specify a mount-point"
1427 return 1
1428 fi
1429 debug "$_me: mount-point is ($devdir), ruleset is ($rs)"
1430 if ! mount -t devfs dev "$devdir"; then
1431 warn "$_me: Unable to mount devfs on $devdir"
1432 return 1
1433 fi
1434 if [ -n "$rs" ]; then
1435 devfs_init_rulesets
1436 devfs_set_ruleset $rs $devdir
1437 devfs -m $devdir rule applyset
1438 fi
1439 return 0
1440}
1441
1442# devfs_mount_jail dir [ruleset]
1443# Mounts a devfs file system appropriate for jails
1444# on the directory dir. If ruleset is specified, the ruleset
1445# it names will be used instead. If present, ruleset must
1446# be the name of a ruleset as defined in a devfs.rules(5) file.
1447# This function returns non-zero if an error occurs.
1448#
1449devfs_mount_jail()
1450{
1451 local jdev rs _me
1452 jdev="$1"
1453 [ -n "$2" ] && rs=$2 || rs="devfsrules_jail"
1454 _me="devfs_mount_jail"
1455
1456 devfs_init_rulesets
1457 if ! devfs_domount "$jdev" $rs; then
1458 warn "$_me: devfs was not mounted on $jdev"
1459 return 1
1460 fi
1461 return 0
1462}
1463
1464# Provide a function for normalizing the mounting of memory
1465# filesystems. This should allow the rest of the code here to remain
1466# as close as possible between 5-current and 4-stable.
1467# $1 = size
1468# $2 = mount point
1469# $3 = (optional) extra mdmfs flags
1470mount_md()
1471{
1472 if [ -n "$3" ]; then
1473 flags="$3"
1474 fi
1475 /sbin/mdmfs $flags -s $1 md $2
1476}
1477
1478# Code common to scripts that need to load a kernel module
1479# if it isn't in the kernel yet. Syntax:
1480# load_kld [-e regex] [-m module] file
1481# where -e or -m chooses the way to check if the module
1482# is already loaded:
1483# regex is egrep'd in the output from `kldstat -v',
1484# module is passed to `kldstat -m'.
1485# The default way is as though `-m file' were specified.
1486load_kld()
1487{
1488 local _loaded _mod _opt _re
1489
1490 while getopts "e:m:" _opt; do
1491 case "$_opt" in
1492 e) _re="$OPTARG" ;;
1493 m) _mod="$OPTARG" ;;
1494 *) err 3 'USAGE: load_kld [-e regex] [-m module] file' ;;
1495 esac
1496 done
1497 shift $(($OPTIND - 1))
1498 if [ $# -ne 1 ]; then
1499 err 3 'USAGE: load_kld [-e regex] [-m module] file'
1500 fi
1501 _mod=${_mod:-$1}
1502 _loaded=false
1503 if [ -n "$_re" ]; then
1504 if kldstat -v | egrep -q -e "$_re"; then
1505 _loaded=true
1506 fi
1507 else
1508 if kldstat -q -m "$_mod"; then
1509 _loaded=true
1510 fi
1511 fi
1512 if ! $_loaded; then
1513 if ! kldload "$1"; then
1514 warn "Unable to load kernel module $1"
1515 return 1
1516 else
1517 info "$1 kernel module loaded."
1518 fi
1519 else
1520 debug "load_kld: $1 kernel module already loaded."
1521 fi
1522 return 0
1523}
1524
1525# ltr str src dst
1526# Change every $src in $str to $dst.
1527# Useful when /usr is not yet mounted and we cannot use tr(1), sed(1) nor
1528# awk(1).
1529ltr()
1530{
1531 local _str _src _dst _out _com
1532 _str=$1
1533 _src=$2
1534 _dst=$3
1535 _out=""
1536
1537 IFS=${_src}
1538 for _com in ${_str}; do
1539 if [ -z "${_out}" ]; then
1540 _out="${_com}"
1541 else
1542 _out="${_out}${_dst}${_com}"
1543 fi
1544 done
1545 echo "${_out}"
1546}
1547
1548# Creates a list of providers for GELI encryption.
1549geli_make_list()
1550{
1551 local devices devices2
1552 local provider mountpoint type options rest
1553
1554 # Create list of GELI providers from fstab.
1555 while read provider mountpoint type options rest ; do
1556 case ":${options}" in
1557 :*noauto*)
1558 noauto=yes
1559 ;;
1560 *)
1561 noauto=no
1562 ;;
1563 esac
1564
1565 case ":${provider}" in
1566 :#*)
1567 continue
1568 ;;
1569 *.eli)
1570 # Skip swap devices.
1571 if [ "${type}" = "swap" -o "${options}" = "sw" -o "${noauto}" = "yes" ]; then
1572 continue
1573 fi
1574 devices="${devices} ${provider}"
1575 ;;
1576 esac
1577 done < /etc/fstab
1578
1579 # Append providers from geli_devices.
1580 devices="${devices} ${geli_devices}"
1581
1582 for provider in ${devices}; do
1583 provider=${provider%.eli}
1584 provider=${provider#/dev/}
1585 devices2="${devices2} ${provider}"
1586 done
1587
1588 echo ${devices2}
1589}
1590
1591# Find scripts in local_startup directories that use the old syntax
1592#
1593find_local_scripts_old () {
1594 zlist=''
1595 slist=''
1596 for dir in ${local_startup}; do
1597 if [ -d "${dir}" ]; then
1598 for file in ${dir}/[0-9]*.sh; do
1599 grep '^# PROVIDE:' $file >/dev/null 2>&1 &&
1600 continue
1601 zlist="$zlist $file"
1602 done
1603 for file in ${dir}/[^0-9]*.sh; do
1604 grep '^# PROVIDE:' $file >/dev/null 2>&1 &&
1605 continue
1606 slist="$slist $file"
1607 done
1608 fi
1609 done
1610}
1611
1612find_local_scripts_new () {
1613 local_rc=''
1614 for dir in ${local_startup}; do
1615 if [ -d "${dir}" ]; then
1616 for file in `grep -l '^# PROVIDE:' ${dir}/* 2>/dev/null`; do
1617 case "$file" in
1618 *.sample) ;;
1619 *) if [ -x "$file" ]; then
1620 local_rc="${local_rc} ${file}"
1621 fi
1622 ;;
1623 esac
1624 done
1625 fi
1626 done
1627}
1628
1629# check_required_{before|after} command
1630# Check for things required by the command before and after its precmd,
1631# respectively. The two separate functions are needed because some
1632# conditions should prevent precmd from being run while other things
1633# depend on precmd having already been run.
1634#
1635check_required_before()
1636{
1637 local _f
1638
1639 case "$1" in
1640 start)
1641 for _f in $required_vars; do
1642 if ! checkyesno $_f; then
1643 warn "\$${_f} is not enabled."
1644 if [ -z "$rc_force" ]; then
1645 return 1
1646 fi
1647 fi
1648 done
1649
1650 for _f in $required_dirs; do
1651 if [ ! -d "${_f}/." ]; then
1652 warn "${_f} is not a directory."
1653 if [ -z "$rc_force" ]; then
1654 return 1
1655 fi
1656 fi
1657 done
1658
1659 for _f in $required_files; do
1660 if [ ! -r "${_f}" ]; then
1661 warn "${_f} is not readable."
1662 if [ -z "$rc_force" ]; then
1663 return 1
1664 fi
1665 fi
1666 done
1667 ;;
1668 esac
1669
1670 return 0
1671}
1672
1673check_required_after()
1674{
1675 local _f _args
1676
1677 case "$1" in
1678 start)
1679 for _f in $required_modules; do
1680 case "${_f}" in
1681 *~*) _args="-e ${_f#*~} ${_f%%~*}" ;;
1682 *:*) _args="-m ${_f#*:} ${_f%%:*}" ;;
1683 *) _args="${_f}" ;;
1684 esac
1685 if ! load_kld ${_args}; then
1686 if [ -z "$rc_force" ]; then
1687 return 1
1688 fi
1689 fi
1690 done
1691 ;;
1692 esac
1693
1694 return 0
1695}
1696
1697fi
1698
1699# _echoonce var msg mode
1700# mode=0: Echo $msg if ${$var} is empty.
1701# After doing echo, a string is set to ${$var}.
1702#
1703# mode=1: Echo $msg if ${$var} is a string with non-zero length.
1704#
1705_echoonce()
1706{
1707 local _var _msg _mode
1708 _var=`eval echo \\$$1`
1709 _msg=$2
1710 _mode=$3
1711
1712 case $_mode in
1713 1) [ -n "$_var" ] && echo "$_msg" ;;
1714 *) [ -z "$_var" ] && echo -n "$_msg" && eval "$1=finished" ;;
1715 esac
1716}
1717
1718_rc_subr_loaded=:
726 if [ -n "$_chroot" ]; then
727 _doit="\
728${_nice:+nice -n $_nice }\
729chroot ${_user:+-u $_user }${_group:+-g $_group }${_groups:+-G $_groups }\
730$_chroot $command $rc_flags $command_args"
731 else
732 _doit="\
733${_chdir:+cd $_chdir && }\
734$command $rc_flags $command_args"
735 if [ -n "$_user" ]; then
736 _doit="su -m $_user -c 'sh -c \"$_doit\"'"
737 fi
738 if [ -n "$_nice" ]; then
739 if [ -z "$_user" ]; then
740 _doit="sh -c \"$_doit\""
741 fi
742 _doit="nice -n $_nice $_doit"
743 fi
744 fi
745
746 # run the full command
747 #
748 if ! _run_rc_doit "$_doit"; then
749 warn "failed to start ${name}"
750 return 1
751 fi
752
753 # finally, run postcmd
754 #
755 _run_rc_postcmd
756 ;;
757
758 stop)
759 if [ -z "$rc_pid" ]; then
760 [ -n "$rc_fast" ] && return 0
761 _run_rc_notrunning
762 return 1
763 fi
764
765 _run_rc_precmd || return 1
766
767 # send the signal to stop
768 #
769 echo "Stopping ${name}."
770 _doit=$(_run_rc_killcmd "${sig_stop:-TERM}")
771 _run_rc_doit "$_doit" || return 1
772
773 # wait for the command to exit,
774 # and run postcmd.
775 wait_for_pids $rc_pid
776
777 _run_rc_postcmd
778 ;;
779
780 reload)
781 if [ -z "$rc_pid" ]; then
782 _run_rc_notrunning
783 return 1
784 fi
785
786 _run_rc_precmd || return 1
787
788 _doit=$(_run_rc_killcmd "${sig_reload:-HUP}")
789 _run_rc_doit "$_doit" || return 1
790
791 _run_rc_postcmd
792 ;;
793
794 restart)
795 # prevent restart being called more
796 # than once by any given script
797 #
798 if ${_rc_restart_done:-false}; then
799 return 0
800 fi
801 _rc_restart_done=true
802
803 _run_rc_precmd || return 1
804
805 # run those in a subshell to keep global variables
806 ( run_rc_command ${_rc_prefix}stop $rc_extra_args )
807 ( run_rc_command ${_rc_prefix}start $rc_extra_args )
808 _return=$?
809 [ $_return -ne 0 ] && [ -z "$rc_force" ] && return 1
810
811 _run_rc_postcmd
812 ;;
813
814 poll)
815 _run_rc_precmd || return 1
816 if [ -n "$rc_pid" ]; then
817 wait_for_pids $rc_pid
818 fi
819 _run_rc_postcmd
820 ;;
821
822 rcvar)
823 echo -n "# $name"
824 if [ -n "$desc" ]; then
825 echo " : $desc"
826 else
827 echo ""
828 fi
829 echo "#"
830 # Get unique vars in $rcvar $rcvars
831 for _v in $rcvar $rcvars; do
832 case $v in
833 $_v\ *|\ *$_v|*\ $_v\ *) ;;
834 *) v="${v# } $_v" ;;
835 esac
836 done
837
838 # Display variables.
839 for _v in $v; do
840 if [ -z "$_v" ]; then
841 continue
842 fi
843
844 eval _desc=\$${_v}_desc
845 eval _defval=\$${_v}_defval
846 _h="-"
847
848 eval echo \"$_v=\\\"\$$_v\\\"\"
849 # decode multiple lines of _desc
850 while [ -n "$_desc" ]; do
851 case $_desc in
852 *^^*)
853 echo "# $_h ${_desc%%^^*}"
854 _desc=${_desc#*^^}
855 _h=" "
856 ;;
857 *)
858 echo "# $_h ${_desc}"
859 break
860 ;;
861 esac
862 done
863 echo "# (default: \"$_defval\")"
864 done
865 echo ""
866 ;;
867
868 *)
869 rc_usage $_keywords
870 ;;
871
872 esac
873 return $_return
874 done
875
876 echo 1>&2 "$0: unknown directive '$rc_arg'."
877 rc_usage $_keywords
878 # not reached
879}
880
881#
882# Helper functions for run_rc_command: common code.
883# They use such global variables besides the exported rc_* ones:
884#
885# name R/W
886# ------------------
887# _precmd R
888# _postcmd R
889# _return W
890#
891_run_rc_precmd()
892{
893 check_required_before "$rc_arg" || return 1
894
895 if [ -n "$_precmd" ]; then
896 debug "run_rc_command: ${rc_arg}_precmd: $_precmd $rc_extra_args"
897 eval "$_precmd $rc_extra_args"
898 _return=$?
899
900 # If precmd failed and force isn't set, request exit.
901 if [ $_return -ne 0 ] && [ -z "$rc_force" ]; then
902 return 1
903 fi
904 fi
905
906 check_required_after "$rc_arg" || return 1
907
908 return 0
909}
910
911_run_rc_postcmd()
912{
913 if [ -n "$_postcmd" ]; then
914 debug "run_rc_command: ${rc_arg}_postcmd: $_postcmd $rc_extra_args"
915 eval "$_postcmd $rc_extra_args"
916 _return=$?
917 fi
918 return 0
919}
920
921_run_rc_doit()
922{
923 debug "run_rc_command: doit: $*"
924 eval "$@"
925 _return=$?
926
927 # If command failed and force isn't set, request exit.
928 if [ $_return -ne 0 ] && [ -z "$rc_force" ]; then
929 return 1
930 fi
931
932 return 0
933}
934
935_run_rc_notrunning()
936{
937 local _pidmsg
938
939 if [ -n "$pidfile" ]; then
940 _pidmsg=" (check $pidfile)."
941 else
942 _pidmsg=
943 fi
944 echo 1>&2 "${name} not running?${_pidmsg}"
945}
946
947_run_rc_killcmd()
948{
949 local _cmd
950
951 _cmd="kill -$1 $rc_pid"
952 if [ -n "$_user" ]; then
953 _cmd="su -m ${_user} -c 'sh -c \"${_cmd}\"'"
954 fi
955 echo "$_cmd"
956}
957
958#
959# run_rc_script file arg
960# Start the script `file' with `arg', and correctly handle the
961# return value from the script. If `file' ends with `.sh', it's
962# sourced into the current environment. If `file' appears to be
963# a backup or scratch file, ignore it. Otherwise if it's
964# executable run as a child process.
965#
966run_rc_script()
967{
968 _file=$1
969 _arg=$2
970 if [ -z "$_file" -o -z "$_arg" ]; then
971 err 3 'USAGE: run_rc_script file arg'
972 fi
973
974 unset name command command_args command_interpreter \
975 extra_commands pidfile procname \
976 rcvar rcvars rcvars_obsolete required_dirs required_files \
977 required_vars
978 eval unset ${_arg}_cmd ${_arg}_precmd ${_arg}_postcmd
979
980 case "$_file" in
981 /etc/rc.d/*.sh) # no longer allowed in the base
982 warn "Ignoring old-style startup script $_file"
983 ;;
984 *[~#]|*.OLD|*.bak|*.orig|*,v) # scratch file; skip
985 warn "Ignoring scratch file $_file"
986 ;;
987 *) # run in subshell
988 if [ -x $_file ]; then
989 if [ -n "$rc_fast_and_loose" ]; then
990 set $_arg; . $_file
991 else
992 ( trap "echo Script $_file interrupted; kill -QUIT $$" 3
993 trap "echo Script $_file interrupted; exit 1" 2
994 trap "echo Script $_file running" 29
995 set $_arg; . $_file )
996 fi
997 fi
998 ;;
999 esac
1000}
1001
1002#
1003# load_rc_config name
1004# Source in the configuration file for a given name.
1005#
1006load_rc_config()
1007{
1008 local _name _var _defval _v _msg _new
1009 _name=$1
1010 if [ -z "$_name" ]; then
1011 err 3 'USAGE: load_rc_config name'
1012 fi
1013
1014 if ${_rc_conf_loaded:-false}; then
1015 :
1016 else
1017 if [ -r /etc/defaults/rc.conf ]; then
1018 debug "Sourcing /etc/defaults/rc.conf"
1019 . /etc/defaults/rc.conf
1020 source_rc_confs
1021 elif [ -r /etc/rc.conf ]; then
1022 debug "Sourcing /etc/rc.conf (/etc/defaults/rc.conf doesn't exist)."
1023 . /etc/rc.conf
1024 fi
1025 _rc_conf_loaded=true
1026 fi
1027 if [ -f /etc/rc.conf.d/"$_name" ]; then
1028 debug "Sourcing /etc/rc.conf.d/${_name}"
1029 . /etc/rc.conf.d/"$_name"
1030 fi
1031
1032 # Old variable names support
1033 #
1034 [ -n "$enable_quotas" ] && quota_enable="$enable_quotas"
1035
1036 # Set defaults if defined.
1037 for _var in $rcvar $rcvars; do
1038 _defval=`eval echo "\\\$${_var}_defval"`
1039 if [ -n "$_defval" ]; then
1040 eval : \${$_var:=\$${_var}_defval}
1041 fi
1042 done
1043
1044 # check obsolete rc.conf variables
1045 for _var in $rcvars_obsolete; do
1046 _v=`eval echo \\$$_var`
1047 _msg=`eval echo \\$${_var}_obsolete_msg`
1048 _new=`eval echo \\$${_var}_newvar`
1049 case $_v in
1050 "")
1051 ;;
1052 *)
1053 if [ -z "$_new" ]; then
1054 _msg="Ignored."
1055 else
1056 eval $_new=\"\$$_var\"
1057 if [ -z "$_msg" ]; then
1058 _msg="Use \$$_new instead."
1059 fi
1060 fi
1061 warn "\$$_var is obsolete. $_msg"
1062 ;;
1063 esac
1064 done
1065}
1066
1067#
1068# load_rc_config_var name var
1069# Read the rc.conf(5) var for name and set in the
1070# current shell, using load_rc_config in a subshell to prevent
1071# unwanted side effects from other variable assignments.
1072#
1073load_rc_config_var()
1074{
1075 if [ $# -ne 2 ]; then
1076 err 3 'USAGE: load_rc_config_var name var'
1077 fi
1078 eval $(eval '(
1079 load_rc_config '$1' >/dev/null;
1080 if [ -n "${'$2'}" -o "${'$2'-UNSET}" != "UNSET" ]; then
1081 echo '$2'=\'\''${'$2'}\'\'';
1082 fi
1083 )' )
1084}
1085
1086#
1087# rc_usage commands
1088# Print a usage string for $0, with `commands' being a list of
1089# valid commands.
1090#
1091rc_usage()
1092{
1093 echo -n 1>&2 "Usage: $0 [fast|force|one]("
1094
1095 _sep=
1096 for _elem; do
1097 echo -n 1>&2 "$_sep$_elem"
1098 _sep="|"
1099 done
1100 echo 1>&2 ")"
1101 exit 1
1102}
1103
1104#
1105# err exitval message
1106# Display message to stderr and log to the syslog, and exit with exitval.
1107#
1108err()
1109{
1110 exitval=$1
1111 shift
1112
1113 if [ -x /usr/bin/logger ]; then
1114 logger "$0: ERROR: $*"
1115 fi
1116 echo 1>&2 "$0: ERROR: $*"
1117 exit $exitval
1118}
1119
1120#
1121# warn message
1122# Display message to stderr and log to the syslog.
1123#
1124warn()
1125{
1126 if [ -x /usr/bin/logger ]; then
1127 logger "$0: WARNING: $*"
1128 fi
1129 echo 1>&2 "$0: WARNING: $*"
1130}
1131
1132#
1133# info message
1134# Display informational message to stdout and log to syslog.
1135#
1136info()
1137{
1138 case ${rc_info} in
1139 [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
1140 if [ -x /usr/bin/logger ]; then
1141 logger "$0: INFO: $*"
1142 fi
1143 echo "$0: INFO: $*"
1144 ;;
1145 esac
1146}
1147
1148#
1149# debug message
1150# If debugging is enabled in rc.conf output message to stderr.
1151# BEWARE that you don't call any subroutine that itself calls this
1152# function.
1153#
1154debug()
1155{
1156 case ${rc_debug} in
1157 [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
1158 if [ -x /usr/bin/logger ]; then
1159 logger "$0: DEBUG: $*"
1160 fi
1161 echo 1>&2 "$0: DEBUG: $*"
1162 ;;
1163 esac
1164}
1165
1166#
1167# backup_file action file cur backup
1168# Make a backup copy of `file' into `cur', and save the previous
1169# version of `cur' as `backup' or use rcs for archiving.
1170#
1171# This routine checks the value of the backup_uses_rcs variable,
1172# which can be either YES or NO.
1173#
1174# The `action' keyword can be one of the following:
1175#
1176# add `file' is now being backed up (and is possibly
1177# being reentered into the backups system). `cur'
1178# is created and RCS files, if necessary, are
1179# created as well.
1180#
1181# update `file' has changed and needs to be backed up.
1182# If `cur' exists, it is copied to to `back' or
1183# checked into RCS (if the repository file is old),
1184# and then `file' is copied to `cur'. Another RCS
1185# check in done here if RCS is being used.
1186#
1187# remove `file' is no longer being tracked by the backups
1188# system. If RCS is not being used, `cur' is moved
1189# to `back', otherwise an empty file is checked in,
1190# and then `cur' is removed.
1191#
1192#
1193backup_file()
1194{
1195 _action=$1
1196 _file=$2
1197 _cur=$3
1198 _back=$4
1199
1200 if checkyesno backup_uses_rcs; then
1201 _msg0="backup archive"
1202 _msg1="update"
1203
1204 # ensure that history file is not locked
1205 if [ -f $_cur,v ]; then
1206 rcs -q -u -U -M $_cur
1207 fi
1208
1209 # ensure after switching to rcs that the
1210 # current backup is not lost
1211 if [ -f $_cur ]; then
1212 # no archive, or current newer than archive
1213 if [ ! -f $_cur,v -o $_cur -nt $_cur,v ]; then
1214 ci -q -f -u -t-"$_msg0" -m"$_msg1" $_cur
1215 rcs -q -kb -U $_cur
1216 co -q -f -u $_cur
1217 fi
1218 fi
1219
1220 case $_action in
1221 add|update)
1222 cp -p $_file $_cur
1223 ci -q -f -u -t-"$_msg0" -m"$_msg1" $_cur
1224 rcs -q -kb -U $_cur
1225 co -q -f -u $_cur
1226 chown root:wheel $_cur $_cur,v
1227 ;;
1228 remove)
1229 cp /dev/null $_cur
1230 ci -q -f -u -t-"$_msg0" -m"$_msg1" $_cur
1231 rcs -q -kb -U $_cur
1232 chown root:wheel $_cur $_cur,v
1233 rm $_cur
1234 ;;
1235 esac
1236 else
1237 case $_action in
1238 add|update)
1239 if [ -f $_cur ]; then
1240 cp -p $_cur $_back
1241 fi
1242 cp -p $_file $_cur
1243 chown root:wheel $_cur
1244 ;;
1245 remove)
1246 mv -f $_cur $_back
1247 ;;
1248 esac
1249 fi
1250}
1251
1252# make_symlink src link
1253# Make a symbolic link 'link' to src from basedir. If the
1254# directory in which link is to be created does not exist
1255# a warning will be displayed and an error will be returned.
1256# Returns 0 on sucess, 1 otherwise.
1257#
1258make_symlink()
1259{
1260 local src link linkdir _me
1261 src="$1"
1262 link="$2"
1263 linkdir="`dirname $link`"
1264 _me="make_symlink()"
1265
1266 if [ -z "$src" -o -z "$link" ]; then
1267 warn "$_me: requires two arguments."
1268 return 1
1269 fi
1270 if [ ! -d "$linkdir" ]; then
1271 warn "$_me: the directory $linkdir does not exist."
1272 return 1
1273 fi
1274 if ! ln -sf $src $link; then
1275 warn "$_me: unable to make a symbolic link from $link to $src"
1276 return 1
1277 fi
1278 return 0
1279}
1280
1281# devfs_rulesets_from_file file
1282# Reads a set of devfs commands from file, and creates
1283# the specified rulesets with their rules. Returns non-zero
1284# if there was an error.
1285#
1286devfs_rulesets_from_file()
1287{
1288 local file _err _me
1289 file="$1"
1290 _me="devfs_rulesets_from_file"
1291 _err=0
1292
1293 if [ -z "$file" ]; then
1294 warn "$_me: you must specify a file"
1295 return 1
1296 fi
1297 if [ ! -e "$file" ]; then
1298 debug "$_me: no such file ($file)"
1299 return 0
1300 fi
1301 debug "reading rulesets from file ($file)"
1302 { while read line
1303 do
1304 case $line in
1305 \#*)
1306 continue
1307 ;;
1308 \[*\]*)
1309 rulenum=`expr "$line" : "\[.*=\([0-9]*\)\]"`
1310 if [ -z "$rulenum" ]; then
1311 warn "$_me: cannot extract rule number ($line)"
1312 _err=1
1313 break
1314 fi
1315 rulename=`expr "$line" : "\[\(.*\)=[0-9]*\]"`
1316 if [ -z "$rulename" ]; then
1317 warn "$_me: cannot extract rule name ($line)"
1318 _err=1
1319 break;
1320 fi
1321 eval $rulename=\$rulenum
1322 debug "found ruleset: $rulename=$rulenum"
1323 if ! /sbin/devfs rule -s $rulenum delset; then
1324 _err=1
1325 break
1326 fi
1327 ;;
1328 *)
1329 rulecmd="${line%%"\#*"}"
1330 # evaluate the command incase it includes
1331 # other rules
1332 if [ -n "$rulecmd" ]; then
1333 debug "adding rule ($rulecmd)"
1334 if ! eval /sbin/devfs rule -s $rulenum $rulecmd
1335 then
1336 _err=1
1337 break
1338 fi
1339 fi
1340 ;;
1341 esac
1342 if [ $_err -ne 0 ]; then
1343 debug "error in $_me"
1344 break
1345 fi
1346 done } < $file
1347 return $_err
1348}
1349
1350# devfs_init_rulesets
1351# Initializes rulesets from configuration files. Returns
1352# non-zero if there was an error.
1353#
1354devfs_init_rulesets()
1355{
1356 local file _me
1357 _me="devfs_init_rulesets"
1358
1359 # Go through this only once
1360 if [ -n "$devfs_rulesets_init" ]; then
1361 debug "$_me: devfs rulesets already initialized"
1362 return
1363 fi
1364 for file in $devfs_rulesets; do
1365 devfs_rulesets_from_file $file || return 1
1366 done
1367 devfs_rulesets_init=1
1368 debug "$_me: devfs rulesets initialized"
1369 return 0
1370}
1371
1372# devfs_set_ruleset ruleset [dir]
1373# Sets the default ruleset of dir to ruleset. The ruleset argument
1374# must be a ruleset name as specified in devfs.rules(5) file.
1375# Returns non-zero if it could not set it successfully.
1376#
1377devfs_set_ruleset()
1378{
1379 local devdir rs _me
1380 [ -n "$1" ] && eval rs=\$$1 || rs=
1381 [ -n "$2" ] && devdir="-m "$2"" || devdir=
1382 _me="devfs_set_ruleset"
1383
1384 if [ -z "$rs" ]; then
1385 warn "$_me: you must specify a ruleset number"
1386 return 1
1387 fi
1388 debug "$_me: setting ruleset ($rs) on mount-point (${devdir#-m })"
1389 if ! /sbin/devfs $devdir ruleset $rs; then
1390 warn "$_me: unable to set ruleset $rs to ${devdir#-m }"
1391 return 1
1392 fi
1393 return 0
1394}
1395
1396# devfs_apply_ruleset ruleset [dir]
1397# Apply ruleset number $ruleset to the devfs mountpoint $dir.
1398# The ruleset argument must be a ruleset name as specified
1399# in a devfs.rules(5) file. Returns 0 on success or non-zero
1400# if it could not apply the ruleset.
1401#
1402devfs_apply_ruleset()
1403{
1404 local devdir rs _me
1405 [ -n "$1" ] && eval rs=\$$1 || rs=
1406 [ -n "$2" ] && devdir="-m "$2"" || devdir=
1407 _me="devfs_apply_ruleset"
1408
1409 if [ -z "$rs" ]; then
1410 warn "$_me: you must specify a ruleset"
1411 return 1
1412 fi
1413 debug "$_me: applying ruleset ($rs) to mount-point (${devdir#-m })"
1414 if ! /sbin/devfs $devdir rule -s $rs applyset; then
1415 warn "$_me: unable to apply ruleset $rs to ${devdir#-m }"
1416 return 1
1417 fi
1418 return 0
1419}
1420
1421# devfs_domount dir [ruleset]
1422# Mount devfs on dir. If ruleset is specified it is set
1423# on the mount-point. It must also be a ruleset name as specified
1424# in a devfs.rules(5) file. Returns 0 on success.
1425#
1426devfs_domount()
1427{
1428 local devdir rs _me
1429 devdir="$1"
1430 [ -n "$2" ] && rs=$2 || rs=
1431 _me="devfs_domount()"
1432
1433 if [ -z "$devdir" ]; then
1434 warn "$_me: you must specify a mount-point"
1435 return 1
1436 fi
1437 debug "$_me: mount-point is ($devdir), ruleset is ($rs)"
1438 if ! mount -t devfs dev "$devdir"; then
1439 warn "$_me: Unable to mount devfs on $devdir"
1440 return 1
1441 fi
1442 if [ -n "$rs" ]; then
1443 devfs_init_rulesets
1444 devfs_set_ruleset $rs $devdir
1445 devfs -m $devdir rule applyset
1446 fi
1447 return 0
1448}
1449
1450# devfs_mount_jail dir [ruleset]
1451# Mounts a devfs file system appropriate for jails
1452# on the directory dir. If ruleset is specified, the ruleset
1453# it names will be used instead. If present, ruleset must
1454# be the name of a ruleset as defined in a devfs.rules(5) file.
1455# This function returns non-zero if an error occurs.
1456#
1457devfs_mount_jail()
1458{
1459 local jdev rs _me
1460 jdev="$1"
1461 [ -n "$2" ] && rs=$2 || rs="devfsrules_jail"
1462 _me="devfs_mount_jail"
1463
1464 devfs_init_rulesets
1465 if ! devfs_domount "$jdev" $rs; then
1466 warn "$_me: devfs was not mounted on $jdev"
1467 return 1
1468 fi
1469 return 0
1470}
1471
1472# Provide a function for normalizing the mounting of memory
1473# filesystems. This should allow the rest of the code here to remain
1474# as close as possible between 5-current and 4-stable.
1475# $1 = size
1476# $2 = mount point
1477# $3 = (optional) extra mdmfs flags
1478mount_md()
1479{
1480 if [ -n "$3" ]; then
1481 flags="$3"
1482 fi
1483 /sbin/mdmfs $flags -s $1 md $2
1484}
1485
1486# Code common to scripts that need to load a kernel module
1487# if it isn't in the kernel yet. Syntax:
1488# load_kld [-e regex] [-m module] file
1489# where -e or -m chooses the way to check if the module
1490# is already loaded:
1491# regex is egrep'd in the output from `kldstat -v',
1492# module is passed to `kldstat -m'.
1493# The default way is as though `-m file' were specified.
1494load_kld()
1495{
1496 local _loaded _mod _opt _re
1497
1498 while getopts "e:m:" _opt; do
1499 case "$_opt" in
1500 e) _re="$OPTARG" ;;
1501 m) _mod="$OPTARG" ;;
1502 *) err 3 'USAGE: load_kld [-e regex] [-m module] file' ;;
1503 esac
1504 done
1505 shift $(($OPTIND - 1))
1506 if [ $# -ne 1 ]; then
1507 err 3 'USAGE: load_kld [-e regex] [-m module] file'
1508 fi
1509 _mod=${_mod:-$1}
1510 _loaded=false
1511 if [ -n "$_re" ]; then
1512 if kldstat -v | egrep -q -e "$_re"; then
1513 _loaded=true
1514 fi
1515 else
1516 if kldstat -q -m "$_mod"; then
1517 _loaded=true
1518 fi
1519 fi
1520 if ! $_loaded; then
1521 if ! kldload "$1"; then
1522 warn "Unable to load kernel module $1"
1523 return 1
1524 else
1525 info "$1 kernel module loaded."
1526 fi
1527 else
1528 debug "load_kld: $1 kernel module already loaded."
1529 fi
1530 return 0
1531}
1532
1533# ltr str src dst
1534# Change every $src in $str to $dst.
1535# Useful when /usr is not yet mounted and we cannot use tr(1), sed(1) nor
1536# awk(1).
1537ltr()
1538{
1539 local _str _src _dst _out _com
1540 _str=$1
1541 _src=$2
1542 _dst=$3
1543 _out=""
1544
1545 IFS=${_src}
1546 for _com in ${_str}; do
1547 if [ -z "${_out}" ]; then
1548 _out="${_com}"
1549 else
1550 _out="${_out}${_dst}${_com}"
1551 fi
1552 done
1553 echo "${_out}"
1554}
1555
1556# Creates a list of providers for GELI encryption.
1557geli_make_list()
1558{
1559 local devices devices2
1560 local provider mountpoint type options rest
1561
1562 # Create list of GELI providers from fstab.
1563 while read provider mountpoint type options rest ; do
1564 case ":${options}" in
1565 :*noauto*)
1566 noauto=yes
1567 ;;
1568 *)
1569 noauto=no
1570 ;;
1571 esac
1572
1573 case ":${provider}" in
1574 :#*)
1575 continue
1576 ;;
1577 *.eli)
1578 # Skip swap devices.
1579 if [ "${type}" = "swap" -o "${options}" = "sw" -o "${noauto}" = "yes" ]; then
1580 continue
1581 fi
1582 devices="${devices} ${provider}"
1583 ;;
1584 esac
1585 done < /etc/fstab
1586
1587 # Append providers from geli_devices.
1588 devices="${devices} ${geli_devices}"
1589
1590 for provider in ${devices}; do
1591 provider=${provider%.eli}
1592 provider=${provider#/dev/}
1593 devices2="${devices2} ${provider}"
1594 done
1595
1596 echo ${devices2}
1597}
1598
1599# Find scripts in local_startup directories that use the old syntax
1600#
1601find_local_scripts_old () {
1602 zlist=''
1603 slist=''
1604 for dir in ${local_startup}; do
1605 if [ -d "${dir}" ]; then
1606 for file in ${dir}/[0-9]*.sh; do
1607 grep '^# PROVIDE:' $file >/dev/null 2>&1 &&
1608 continue
1609 zlist="$zlist $file"
1610 done
1611 for file in ${dir}/[^0-9]*.sh; do
1612 grep '^# PROVIDE:' $file >/dev/null 2>&1 &&
1613 continue
1614 slist="$slist $file"
1615 done
1616 fi
1617 done
1618}
1619
1620find_local_scripts_new () {
1621 local_rc=''
1622 for dir in ${local_startup}; do
1623 if [ -d "${dir}" ]; then
1624 for file in `grep -l '^# PROVIDE:' ${dir}/* 2>/dev/null`; do
1625 case "$file" in
1626 *.sample) ;;
1627 *) if [ -x "$file" ]; then
1628 local_rc="${local_rc} ${file}"
1629 fi
1630 ;;
1631 esac
1632 done
1633 fi
1634 done
1635}
1636
1637# check_required_{before|after} command
1638# Check for things required by the command before and after its precmd,
1639# respectively. The two separate functions are needed because some
1640# conditions should prevent precmd from being run while other things
1641# depend on precmd having already been run.
1642#
1643check_required_before()
1644{
1645 local _f
1646
1647 case "$1" in
1648 start)
1649 for _f in $required_vars; do
1650 if ! checkyesno $_f; then
1651 warn "\$${_f} is not enabled."
1652 if [ -z "$rc_force" ]; then
1653 return 1
1654 fi
1655 fi
1656 done
1657
1658 for _f in $required_dirs; do
1659 if [ ! -d "${_f}/." ]; then
1660 warn "${_f} is not a directory."
1661 if [ -z "$rc_force" ]; then
1662 return 1
1663 fi
1664 fi
1665 done
1666
1667 for _f in $required_files; do
1668 if [ ! -r "${_f}" ]; then
1669 warn "${_f} is not readable."
1670 if [ -z "$rc_force" ]; then
1671 return 1
1672 fi
1673 fi
1674 done
1675 ;;
1676 esac
1677
1678 return 0
1679}
1680
1681check_required_after()
1682{
1683 local _f _args
1684
1685 case "$1" in
1686 start)
1687 for _f in $required_modules; do
1688 case "${_f}" in
1689 *~*) _args="-e ${_f#*~} ${_f%%~*}" ;;
1690 *:*) _args="-m ${_f#*:} ${_f%%:*}" ;;
1691 *) _args="${_f}" ;;
1692 esac
1693 if ! load_kld ${_args}; then
1694 if [ -z "$rc_force" ]; then
1695 return 1
1696 fi
1697 fi
1698 done
1699 ;;
1700 esac
1701
1702 return 0
1703}
1704
1705fi
1706
1707# _echoonce var msg mode
1708# mode=0: Echo $msg if ${$var} is empty.
1709# After doing echo, a string is set to ${$var}.
1710#
1711# mode=1: Echo $msg if ${$var} is a string with non-zero length.
1712#
1713_echoonce()
1714{
1715 local _var _msg _mode
1716 _var=`eval echo \\$$1`
1717 _msg=$2
1718 _mode=$3
1719
1720 case $_mode in
1721 1) [ -n "$_var" ] && echo "$_msg" ;;
1722 *) [ -z "$_var" ] && echo -n "$_msg" && eval "$1=finished" ;;
1723 esac
1724}
1725
1726_rc_subr_loaded=: