Annotation of src/etc/rc.subr, Revision 1.16
1.16 ! lukem 1: # $NetBSD: rc.subr,v 1.15 2000/04/28 01:40:09 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
83: for fs in $_fslist; do
1.6 mellon 84: mount | (
85: ismounted=no
86: while read what _on on _type type; do
87: if [ $on = $fs ]; then
88: ismounted=yes
89: fi
90: done
91: if [ $ismounted = no ]; then
92: mount $fs >/dev/null 2>&1
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.
188: # ${name}_flags n Arguments to call ${command} with.
189: # NOTE: if $flags is set (e.g, from the parent
190: # environment), it overrides this.
191: # ${_arg}_cmd n If set, use this as the action when invoked;
192: # $_arg is available to the action to use.
193: # Otherwise, use default command (see below)
194: # NOTE: checkyesno ${rcvar} is NOT performed
195: # for ${_arg}_cmd; use ${_arg}_precmd to
196: # do this.
197: # ${_arg}_precmd n If set, run just before performing the main
198: # action in the default command (i.e, after
199: # checking for required bits and process
200: # (non)existance).
201: # If this completes with a non-zero exit code,
202: # don't run ${_arg}_cmd.
203: # required_dirs n If set, check for the existence of the given
204: # directories before running the default
205: # (re)start command.
206: # required_files n If set, check for the readability of the given
207: # files before running the default (re)start
208: # command.
209: # required_vars n If set, perform checkyesno on each of the
210: # listed variables before running the default
211: # (re)start command.
212: #
213: # Default commands for a given arg:
214: # arg default
215: # --- -------
216: # status Show if ${command} is running, etc.
217: # start if !running && checkyesno ${rcvar}
218: # ${command}
219: # stop if ${pidfile}
220: # kill $sig_stop `check_pidfile $pidfile`
221: # else
222: # kill $sig_stop `check_process $command`
223: # $sig_stop defaults to TERM.
224: # reload As stop, except use $sig_reload instead.
225: # $sig_reload defaults to HUP.
226: # restart Run `stop' then `start'.
227: #
228: run_rc_command()
229: {
230: _arg=$1
231: _ckvar=${rcvar:-$name}
232: if [ -z "$_ckvar" ]; then
233: err 3 'neither $rcvar or $name is set.'
234: fi
235:
236: case "$_arg" in
237: fast*)
238: _arg=${_arg#fast}
239: _rc_fast_run=YES
240: ;;
241: force*)
242: _arg=${_arg#force}
243: eval ${_ckvar}=YES
244: ;;
245: esac
246:
1.16 ! lukem 247: _keywords="start stop restart rcvar $extra_commands"
1.11 lukem 248: _pidcmd=
249: if [ -z "$_rc_fast_run" ]; then
250: if [ -n "$pidfile" ]; then
251: _pidcmd='_pid=`check_pidfile '$pidfile' '$command'`'
252: elif [ -n "$command" ]; then
253: _pidcmd='_pid=`check_process '$command'`'
254: fi
255: if [ -n "$_pidcmd" ]; then
256: _keywords="${_keywords} status"
257: fi
258: fi
259:
260: if [ -z "$_arg" ]; then
261: rc_usage "$_keywords"
262: fi
263:
264: if [ -n "$flags" ]; then
265: _flags=$flags
266: else
267: eval _flags=\$${name}_flags
268: fi
269:
270: eval $_pidcmd
271:
272: for _elem in $_keywords; do
273: if [ "$_elem" != "$_arg" ]; then
274: continue
275: fi
276:
277: eval _cmd=\$${_arg}_cmd
278: eval _precmd=\$${_arg}_precmd
279: if [ -n "$_cmd" ]; then
280: eval $_precmd || return 1
281: eval $_cmd
282: return 0
283: fi
284:
285: case "$_arg" in
286:
287: status)
288: if [ -n "$_pid" ]; then
289: echo "${name} is running as pid $_pid."
290: else
291: echo "${name} is not running."
292: fi
293: ;;
294:
295: start)
296: if [ -n "$_pid" ]; then
297: echo "${name} already running? (pid=$_pid)."
298: exit 1
299: fi
300:
301: if ! checkyesno ${_ckvar} || [ ! -x $command ]; then
302: return 0
303: fi
304:
305: for _f in $required_vars; do
306: if ! checkyesno $_f; then
307: warn \
308: "\$${_f} is not set; ${name} not started."
309: return 1
310: fi
311: done
312: for _f in $required_dirs; do
313: if [ ! -d "${_f}/." ]; then
314: warn \
315: "${_f} is not a directory; ${name} not started."
316: return 1
317: fi
318: done
319: for _f in $required_files; do
320: if [ ! -r "${_f}" ]; then
321: warn \
322: "${_f} is not readable; ${name} not started."
323: return 1
324: fi
325: done
326:
327: eval $_precmd || return 1
328: echo "Starting ${name}."
329: eval $command $_flags $command_args
330: ;;
331:
332: stop)
333: if [ -z "$_pid" ]; then
334: if checkyesno ${_ckvar}; then
335: if [ -n "$pidfile" ]; then
336: echo \
337: "${name} not running? (check $pidfile)."
338: else
339: echo "${name} not running?"
340: fi
341: exit 1
342: fi
343: return 0
344: fi
345:
346: eval $_precmd || return 1
347: echo "Stopping ${name}."
348: kill -${sig_stop:-TERM} $_pid
349: ;;
350:
351: reload)
352: if [ -z "$_pid" ]; then
353: if checkyesno ${_ckvar}; then
354: if [ -n "$pidfile" ]; then
355: echo \
356: "${name} not running? (check $pidfile)."
357: else
358: echo "${name} not running?"
359: fi
360: exit 1
361: fi
362: return 0
363: fi
364: echo "Reloading ${name} config files."
365: eval $_precmd || return 1
366: kill -${sig_reload:-HUP} $_pid
367: ;;
368:
369: restart)
370: if ! checkyesno ${_ckvar}; then
371: return 0
372: fi
373: eval $_precmd || return 1
374: ( $0 stop )
375: sleep 1
376: $0 start
377:
378: ;;
379:
380: rcvar)
381: echo "# $name"
382: if checkyesno ${_ckvar}; then
383: echo "\$${_ckvar}=YES"
384: else
385: echo "\$${_ckvar}=NO"
386: fi
387: ;;
388:
389: *)
390: rc_usage "$_keywords"
391: ;;
392:
393: esac
394: return 0
395: done
396:
397: echo 1>&2 "$0: unknown directive '$_arg'."
398: rc_usage "$_keywords"
399: exit 1
400: }
401:
402: #
403: # run_rc_script file arg
404: # Start the script `file' with `arg', and correctly handle the
405: # return value from the script. If `file' ends with `.sh', it's
406: # sourced into the current environment. Otherwise it's run as
407: # a child process.
408: # Note: because `.sh' files are sourced into the current environment
409: # run_rc_command shouldn't be used because its difficult to ensure
410: # that the global variable state before and after the sourcing of
411: # the .sh file won't adversely affect other scripts.
412: #
413: run_rc_script()
414: {
415: _file=$1
416: _arg=$2
417: if [ -z "$_file" -o -z "$_arg" ]; then
418: err 3 'USAGE: run_rc_script file arg'
419: fi
420:
421: _narg=$_arg
422: case "$_narg" in
423: fast*)
424: _narg=${_narg#fast}
425: ;;
426: force*)
427: _narg=${_narg#force}
428: ;;
429: esac
430: eval ${_narg}_precmd=""
431: eval ${_narg}_cmd=""
432:
433: case "$_file" in
434: *.sh) # run in current shell
435: set $_arg ; . $_file
436: ;;
437: *) # run in subshell
438: ( set $_arg ; . $_file )
439: ;;
440: esac
441: }
442:
443: #
444: # rc_usage commands
445: # Print a usage string for $0, with `commands' being a list of
446: # valid commands.
447: #
448: rc_usage()
449: {
450: echo -n 1>&2 "Usage: $0 [fast|force]("
451:
452: _sep=
453: for _elem in $*; do
454: echo -n 1>&2 "$_sep$_elem"
455: _sep="|"
456: done
457: echo 1>&2 ")"
458: exit 1
459: }
460:
461: #
462: # err exitval message
463: # Display message to stderr and log to the syslog, and exit with exitval.
464: #
465: err()
466: {
467: exitval=$1
468: shift
469:
470: logger "$0: ERROR $*"
471: echo 1>&2 "$0: ERROR $*"
472: exit $exitval
473: }
474:
475: #
476: # warn message
477: # Display message to stderr and log to the syslog.
478: #
479: warn()
480: {
481: logger "$0: WARNING $*"
482: echo 1>&2 "$0: WARNING $*"
1.1 cjs 483: }
CVSweb <webmaster@jp.NetBSD.org>