Annotation of src/etc/rc.subr, Revision 1.23
1.23 ! lukem 1: # $NetBSD: rc.subr,v 1.22 2000/08/17 11:07:10 lukem Exp $
1.11 lukem 2: #
3: # Copyright (c) 1997-2000 The NetBSD Foundation, Inc.
4: # All rights reserved.
5: #
6: # This code is derived from software contributed to The NetBSD Foundation
7: # by Luke Mewburn.
8: #
9: # Redistribution and use in source and binary forms, with or without
10: # modification, are permitted provided that the following conditions
11: # are met:
12: # 1. Redistributions of source code must retain the above copyright
13: # notice, this list of conditions and the following disclaimer.
14: # 2. Redistributions in binary form must reproduce the above copyright
15: # notice, this list of conditions and the following disclaimer in the
16: # documentation and/or other materials provided with the distribution.
17: # 3. All advertising materials mentioning features or use of this software
18: # must display the following acknowledgement:
19: # This product includes software developed by the NetBSD
20: # Foundation, Inc. and its contributors.
21: # 4. Neither the name of The NetBSD Foundation nor the names of its
22: # contributors may be used to endorse or promote products derived
23: # from this software without specific prior written permission.
24: #
25: # THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
26: # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27: # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28: # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
29: # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30: # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31: # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32: # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33: # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34: # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35: # POSSIBILITY OF SUCH DAMAGE.
36: #
37: # rc.subr
38: # functions used by various rc scripts
39: #
40:
41: #
42: # functions
43: # ---------
1.1 cjs 44:
1.5 lukem 45: #
1.11 lukem 46: # checkyesno var
1.5 lukem 47: # Test $1 variable, and warn if not set to YES or NO.
1.11 lukem 48: # Return 0 if it's "yes" (et al), nonzero otherwise.
1.5 lukem 49: #
1.11 lukem 50: checkyesno()
51: {
52: eval _value=\$${1}
53: case $_value in
1.4 lukem 54:
55: # "yes", "true", "on", or "1"
56: [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
57: return 0
1.3 lukem 58: ;;
1.4 lukem 59:
60: # "no", "false", "off", or "0"
61: [Nn][Oo]|[Ff][Aa][Ll][Ss][Ee]|[Oo][Ff][Ff]|0)
62: return 1
1.3 lukem 63: ;;
64: *)
1.11 lukem 65: warn "\$${1} is not set properly."
1.4 lukem 66: return 1
1.3 lukem 67: ;;
68: esac
1.6 mellon 69: }
70:
71: #
72: # mount_critical_filesystems
73: # Go through the list of critical filesystems, checking each one
74: # to see if it is mounted, and if it is not, mounting it.
75: #
1.11 lukem 76: mount_critical_filesystems()
77: {
1.10 drochner 78: if [ $1 = local ]; then
79: _fslist=$critical_filesystems_beforenet
80: else
81: _fslist=$critical_filesystems
82: fi
1.17 lukem 83: for _fs in $_fslist; do
1.6 mellon 84: mount | (
1.17 lukem 85: _ismounted=no
1.6 mellon 86: while read what _on on _type type; do
1.17 lukem 87: if [ $on = $_fs ]; then
88: _ismounted=yes
1.6 mellon 89: fi
90: done
1.17 lukem 91: if [ $_ismounted = no ]; then
92: mount $_fs >/dev/null 2>&1
1.6 mellon 93: fi
94: )
95: done
1.7 cjs 96: }
97:
1.11 lukem 98: #
99: # check_pidfile pidfile procname
100: # Parses the first line of pidfile for a pid, and ensures
101: # that the process is running and matches procname.
102: # Prints the matching pid upon success, nothing otherwise.
103: #
104: check_pidfile()
105: {
106: _pidfile=$1
107: _procname=$2
108: if [ -z "$_pidfile" -o -z "$_procname" ]; then
109: err 3 'USAGE: check_pidfile pidfile procname'
110: fi
111: if [ ! -f $_pidfile ]; then
112: return
113: fi
114: read _pid _junk < $_pidfile
115: if [ -z "$_pid" ]; then
116: return
117: fi
118: _procnamebn=`basename $_procname`
119: ps -p $_pid -o 'pid,command' | while read _npid _arg0 _argv; do
120: if [ "$_npid" = "PID" ]; then
121: continue
122: fi
1.15 lukem 123: if [ "$_arg0" = "$_procname" \
124: -o "$_arg0" = "$_procnamebn" \
125: -o "$_arg0" = "${_procnamebn}:" \
126: -o "$_arg0" = "(${_procnamebn})" ]; then
1.11 lukem 127: echo $_npid
128: return
129: fi
130: done
131: }
132:
133: #
134: # check_process procname
135: # Ensures that a process (or processes) named procname is running.
136: # Prints a list of matching pids.
137: #
138: check_process()
139: {
140: _procname=$1
141: if [ -z "$_procname" ]; then
142: err 3 'USAGE: check_process procname'
143: fi
144: _procnamebn=`basename $_procname`
145: _pref=
146: ps -ax -o 'pid,command' | while read _npid _arg0 _argv; do
147: if [ "$_npid" = "PID" ]; then
148: continue
149: fi
1.15 lukem 150: if [ "$_arg0" = "$_procname" \
151: -o "$_arg0" = "$_procnamebn" \
152: -o "$_arg0" = "${_procnamebn}:" \
153: -o "$_arg0" = "(${_procnamebn})" ]; then
1.11 lukem 154: echo -n "$_pref$_npid"
155: _pref=" "
156: fi
157: done
158: }
159:
160: #
1.16 lukem 161: # run_rc_command arg
162: # Search for arg in the list of supported commands, which is:
163: # "start stop restart rcvar status ${extra_commands}"
1.11 lukem 164: # If there's a match, run ${arg}_cmd or the default command (see below).
165: #
1.16 lukem 166: # If arg has a given prefix, then change the operation as follows:
1.11 lukem 167: # prefix operation
168: # ------ ---------
169: # fast Skip the pid check.
170: # force Set ${rcvar} to YES.
171: #
172: # The following globals are used:
173: # name needed function
174: # ---- ------ --------
175: # name y Name of script.
176: # command n Full path to command.
177: # Not needed if ${arg}_cmd is set for
178: # each keyword.
179: # command_args n Optional args/shell directives for command.
1.16 lukem 180: # extra_commands n List of extra commands supported.
1.11 lukem 181: # pidfile n If set, use check_pidfile $pidfile, else if
182: # $command is set, use check_process $command.
1.16 lukem 183: # rcvar n If the default command is being run, this is
1.11 lukem 184: # checked with checkyesno to determine if
185: # the action should be run.
186: # If this variable isn't set, ${name} is checked
187: # instead.
1.22 lukem 188: # ${name}_chroot n Directory to chroot to before running ${command}
189: # ${name}_chdir n Directory to cd to before running ${command}
190: # (if not using ${name}_chroot).
1.11 lukem 191: # ${name}_flags n Arguments to call ${command} with.
192: # NOTE: if $flags is set (e.g, from the parent
193: # environment), it overrides this.
1.23 ! lukem 194: # ${name}_nice n Nice level to run ${command} at.
1.22 lukem 195: # ${name}_user n User to run ${command} as, using su(1) if not
196: # using ${name}_chroot.
197: # ${name}_group n Group to run chrooted ${command} as.
198: # ${name}_groups n Group list to run chrooted ${command} with.
1.11 lukem 199: # ${_arg}_cmd n If set, use this as the action when invoked;
200: # $_arg is available to the action to use.
201: # Otherwise, use default command (see below)
202: # NOTE: checkyesno ${rcvar} is NOT performed
203: # for ${_arg}_cmd; use ${_arg}_precmd to
204: # do this.
205: # ${_arg}_precmd n If set, run just before performing the main
206: # action in the default command (i.e, after
207: # checking for required bits and process
208: # (non)existance).
209: # If this completes with a non-zero exit code,
210: # don't run ${_arg}_cmd.
211: # required_dirs n If set, check for the existence of the given
212: # directories before running the default
213: # (re)start command.
214: # required_files n If set, check for the readability of the given
215: # files before running the default (re)start
216: # command.
217: # required_vars n If set, perform checkyesno on each of the
218: # listed variables before running the default
219: # (re)start command.
220: #
221: # Default commands for a given arg:
222: # arg default
223: # --- -------
224: # status Show if ${command} is running, etc.
225: # start if !running && checkyesno ${rcvar}
226: # ${command}
227: # stop if ${pidfile}
228: # kill $sig_stop `check_pidfile $pidfile`
229: # else
230: # kill $sig_stop `check_process $command`
231: # $sig_stop defaults to TERM.
232: # reload As stop, except use $sig_reload instead.
233: # $sig_reload defaults to HUP.
234: # restart Run `stop' then `start'.
235: #
236: run_rc_command()
237: {
238: _arg=$1
239: _ckvar=${rcvar:-$name}
240: if [ -z "$_ckvar" ]; then
241: err 3 'neither $rcvar or $name is set.'
242: fi
243:
244: case "$_arg" in
245: fast*)
246: _arg=${_arg#fast}
247: _rc_fast_run=YES
248: ;;
249: force*)
250: _arg=${_arg#force}
251: eval ${_ckvar}=YES
252: ;;
253: esac
254:
1.16 lukem 255: _keywords="start stop restart rcvar $extra_commands"
1.17 lukem 256: _pid=
1.11 lukem 257: _pidcmd=
258: if [ -z "$_rc_fast_run" ]; then
259: if [ -n "$pidfile" ]; then
260: _pidcmd='_pid=`check_pidfile '$pidfile' '$command'`'
261: elif [ -n "$command" ]; then
262: _pidcmd='_pid=`check_process '$command'`'
263: fi
264: if [ -n "$_pidcmd" ]; then
265: _keywords="${_keywords} status"
266: fi
267: fi
268:
269: if [ -z "$_arg" ]; then
270: rc_usage "$_keywords"
271: fi
272:
1.17 lukem 273: if [ -n "$flags" ]; then # allow override from environment
1.11 lukem 274: _flags=$flags
275: else
276: eval _flags=\$${name}_flags
277: fi
1.18 lukem 278: eval _chdir=\$${name}_chdir
1.22 lukem 279: eval _chroot=\$${name}_chroot
1.18 lukem 280: eval _nice=\$${name}_nice
281: eval _user=\$${name}_user
1.22 lukem 282: eval _group=\$${name}_group
283: eval _groups=\$${name}_groups
1.11 lukem 284:
285: eval $_pidcmd
286:
287: for _elem in $_keywords; do
288: if [ "$_elem" != "$_arg" ]; then
289: continue
290: fi
291:
292: eval _cmd=\$${_arg}_cmd
293: eval _precmd=\$${_arg}_precmd
294: if [ -n "$_cmd" ]; then
295: eval $_precmd || return 1
296: eval $_cmd
297: return 0
298: fi
299:
300: case "$_arg" in
301:
302: status)
303: if [ -n "$_pid" ]; then
304: echo "${name} is running as pid $_pid."
305: else
306: echo "${name} is not running."
307: fi
308: ;;
309:
310: start)
311: if [ -n "$_pid" ]; then
312: echo "${name} already running? (pid=$_pid)."
313: exit 1
314: fi
315:
316: if ! checkyesno ${_ckvar} || [ ! -x $command ]; then
317: return 0
318: fi
319:
320: for _f in $required_vars; do
321: if ! checkyesno $_f; then
322: warn \
323: "\$${_f} is not set; ${name} not started."
324: return 1
325: fi
326: done
327: for _f in $required_dirs; do
328: if [ ! -d "${_f}/." ]; then
329: warn \
330: "${_f} is not a directory; ${name} not started."
331: return 1
332: fi
333: done
334: for _f in $required_files; do
335: if [ ! -r "${_f}" ]; then
336: warn \
337: "${_f} is not readable; ${name} not started."
338: return 1
339: fi
340: done
341:
342: eval $_precmd || return 1
343: echo "Starting ${name}."
1.22 lukem 344: if [ -n "$_chroot" ]; then
345: _doit="\
1.23 ! lukem 346: ${_nice:+nice -n $_nice }\
1.22 lukem 347: chroot ${_user:+-u $_user }${_group:+-g $_group }${_groups:+-G $_groups }\
348: $_chroot $command $_flags $command_args"
349: else
350: _doit="\
1.18 lukem 351: ${_user:+su -m $_user -c 'sh -c \"}\
352: ${_chdir:+cd $_chdir; }\
353: ${_nice:+nice -n $_nice }\
354: $command $_flags $command_args\
355: ${_user:+\"'}"
1.22 lukem 356: fi
1.18 lukem 357: eval $_doit
1.11 lukem 358: ;;
359:
360: stop)
361: if [ -z "$_pid" ]; then
362: if checkyesno ${_ckvar}; then
363: if [ -n "$pidfile" ]; then
364: echo \
365: "${name} not running? (check $pidfile)."
366: else
367: echo "${name} not running?"
368: fi
369: exit 1
370: fi
371: return 0
372: fi
373:
374: eval $_precmd || return 1
375: echo "Stopping ${name}."
1.18 lukem 376: _doit=\
377: "${_user:+su -m $_user -c '}kill -${sig_stop:-TERM} $_pid${_user:+'}"
378: eval $_doit
1.11 lukem 379: ;;
380:
381: reload)
382: if [ -z "$_pid" ]; then
383: if checkyesno ${_ckvar}; then
384: if [ -n "$pidfile" ]; then
385: echo \
386: "${name} not running? (check $pidfile)."
387: else
388: echo "${name} not running?"
389: fi
390: exit 1
391: fi
392: return 0
393: fi
394: echo "Reloading ${name} config files."
395: eval $_precmd || return 1
1.18 lukem 396: _doit=\
397: "${_user:+su -m $_user -c '}kill -${sig_reload:-HUP} $_pid${_user:+'}"
398: eval $_doit
1.11 lukem 399: ;;
400:
401: restart)
402: if ! checkyesno ${_ckvar}; then
403: return 0
404: fi
405: eval $_precmd || return 1
406: ( $0 stop )
407: sleep 1
408: $0 start
409:
410: ;;
411:
412: rcvar)
413: echo "# $name"
414: if checkyesno ${_ckvar}; then
415: echo "\$${_ckvar}=YES"
416: else
417: echo "\$${_ckvar}=NO"
418: fi
419: ;;
420:
421: *)
422: rc_usage "$_keywords"
423: ;;
424:
425: esac
426: return 0
427: done
428:
429: echo 1>&2 "$0: unknown directive '$_arg'."
430: rc_usage "$_keywords"
431: exit 1
432: }
433:
434: #
435: # run_rc_script file arg
436: # Start the script `file' with `arg', and correctly handle the
1.17 lukem 437: # return value from the script. If `file' ends with `.sh', it's
438: # sourced into the current environment. Otherwise it's run as
1.11 lukem 439: # a child process.
1.17 lukem 440: #
1.11 lukem 441: # Note: because `.sh' files are sourced into the current environment
442: # run_rc_command shouldn't be used because its difficult to ensure
443: # that the global variable state before and after the sourcing of
444: # the .sh file won't adversely affect other scripts.
445: #
446: run_rc_script()
447: {
448: _file=$1
449: _arg=$2
450: if [ -z "$_file" -o -z "$_arg" ]; then
451: err 3 'USAGE: run_rc_script file arg'
452: fi
453:
454: case "$_file" in
1.17 lukem 455: *.sh) # run in current shell
1.11 lukem 456: set $_arg ; . $_file
457: ;;
1.17 lukem 458: *) # run in subshell
1.11 lukem 459: ( set $_arg ; . $_file )
460: ;;
461: esac
462: }
1.19 lukem 463:
464: #
465: # load_rc_config
466: # Source in the configuration file for a given command.
467: #
468: load_rc_config()
469: {
470: _command=$1
471: if [ -z "$_command" ]; then
472: err 3 'USAGE: load_rc_config command'
473: fi
474:
475: . /etc/rc.conf
1.20 fvdl 476: if [ -f /etc/rc.conf.d/"$_command" ]; then
477: . /etc/rc.conf.d/"$_command"
478: fi
1.19 lukem 479: }
480:
1.11 lukem 481:
482: #
483: # rc_usage commands
484: # Print a usage string for $0, with `commands' being a list of
485: # valid commands.
486: #
487: rc_usage()
488: {
489: echo -n 1>&2 "Usage: $0 [fast|force]("
490:
491: _sep=
492: for _elem in $*; do
493: echo -n 1>&2 "$_sep$_elem"
494: _sep="|"
495: done
496: echo 1>&2 ")"
497: exit 1
498: }
499:
500: #
501: # err exitval message
502: # Display message to stderr and log to the syslog, and exit with exitval.
503: #
504: err()
505: {
506: exitval=$1
507: shift
508:
1.21 lukem 509: logger "$0: ERROR: $*"
510: echo 1>&2 "$0: ERROR: $*"
1.11 lukem 511: exit $exitval
512: }
513:
514: #
515: # warn message
516: # Display message to stderr and log to the syslog.
517: #
518: warn()
519: {
1.21 lukem 520: logger "$0: WARNING: $*"
521: echo 1>&2 "$0: WARNING: $*"
1.1 cjs 522: }
CVSweb <webmaster@jp.NetBSD.org>