Bring RCNG in from 5.x and adjust config files and scripts accordingly.
[dragonfly.git] / etc / rc.subr
1 # $NetBSD: rc.subr,v 1.49 2002/05/21 12:31:01 lukem Exp $
2 # $FreeBSD: src/etc/rc.subr,v 1.13 2003/06/09 17:31:06 mtm Exp $
3 # $DragonFly: src/etc/rc.subr,v 1.1 2003/07/24 06:35:32 dillon Exp $
4 #
5 # Copyright (c) 1997-2002 The NetBSD Foundation, Inc.
6 # All rights reserved.
7 #
8 # This code is derived from software contributed to The NetBSD Foundation
9 # by Luke Mewburn.
10 #
11 # Redistribution and use in source and binary forms, with or without
12 # modification, are permitted provided that the following conditions
13 # are met:
14 # 1. Redistributions of source code must retain the above copyright
15 #    notice, this list of conditions and the following disclaimer.
16 # 2. Redistributions in binary form must reproduce the above copyright
17 #    notice, this list of conditions and the following disclaimer in the
18 #    documentation and/or other materials provided with the distribution.
19 # 3. All advertising materials mentioning features or use of this software
20 #    must display the following acknowledgement:
21 #        This product includes software developed by the NetBSD
22 #        Foundation, Inc. and its contributors.
23 # 4. Neither the name of The NetBSD Foundation nor the names of its
24 #    contributors may be used to endorse or promote products derived
25 #    from this software without specific prior written permission.
26 #
27 # THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28 # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29 # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 # PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31 # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 # POSSIBILITY OF SUCH DAMAGE.
38 #
39 # rc.subr
40 #       functions used by various rc scripts
41 #
42
43 #
44 #       Operating System dependent/independent variables
45 #
46
47 SYSCTL="/sbin/sysctl"
48 SYSCTL_N="${SYSCTL} -n"
49 CMD_OSTYPE="${SYSCTL_N} kern.ostype"
50 OSTYPE=`${CMD_OSTYPE}`
51
52 case ${OSTYPE} in
53 DragonFly)
54         SYSCTL_W="${SYSCTL}"
55         ;;
56 FreeBSD)
57         SYSCTL_W="${SYSCTL}"
58         ;;
59 NetBSD)
60         SYSCTL_W="${SYSCTL} -w"
61         ;;
62 esac
63
64 #
65 #       functions
66 #       ---------
67
68 #
69 # set_rcvar base_var
70 #       Set the variable name enabling a specific service.
71 #       FreeBSD uses ${service}_enable, while NetBSD uses
72 #       just the name of the service. For example:
73 #       FreeBSD: sendmail_enable="YES"
74 #       NetBSD : sendmail="YES"
75 #       $1 - if $name is not the base to work of off, specify
76 #            a different one
77 #
78 set_rcvar()
79 {
80         if [ -z "$1" ]; then
81                 base_var=${name}
82         else
83                 base_var="$1"
84         fi
85
86         case ${OSTYPE} in
87         FreeBSD)
88                 echo ${base_var}_enable
89                 ;;
90         NetBSD)
91                 echo ${base_var}
92                 ;;
93         *)
94                 echo 'XXX'
95                 ;;
96         esac
97 }
98
99 #
100 # force_depend script
101 #       Force a service to start. Intended for use by services
102 #       to resolve dependency issues. It is assumed the caller
103 #       has check to make sure this call is necessary
104 #       $1 - filename of script, in /etc/rc.d, to run
105 #
106 force_depend()
107 {
108         _depend="$1"
109
110         info "${name} depends on ${_depend}, which will be forced to start."
111         if ! /etc/rc.d/${_depend} forcestart ; then
112                 warn "Unable to force ${_depend}. It may already be running."
113                 return 1
114         fi
115         return 0
116 }
117
118 #
119 # checkyesno var
120 #       Test $1 variable, and warn if not set to YES or NO.
121 #       Return 0 if it's "yes" (et al), nonzero otherwise.
122 #
123 checkyesno()
124 {
125         eval _value=\$${1}
126         debug "checkyesno: $1 is set to $_value."
127         case $_value in
128
129                 #       "yes", "true", "on", or "1"
130         [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
131                 return 0
132                 ;;
133
134                 #       "no", "false", "off", or "0"
135         [Nn][Oo]|[Ff][Aa][Ll][Ss][Ee]|[Oo][Ff][Ff]|0)
136                 return 1
137                 ;;
138         *)
139                 warn "\$${1} is not set properly - see rc.conf(5)."
140                 return 1
141                 ;;
142         esac
143 }
144
145 # reverse_list list
146 #       print the list in reverse order
147 #
148 reverse_list()
149 {
150         _revlist=
151         for _revfile in $*; do
152                 _revlist="$_revfile $_revlist"
153         done
154         echo $_revlist
155 }
156
157 #
158 # mount_critical_filesystems type
159 #       Go through the list of critical filesystems as provided in
160 #       the rc.conf(5) variable $critical_filesystems_${type}, checking
161 #       each one to see if it is mounted, and if it is not, mounting it.
162 #
163 mount_critical_filesystems()
164 {
165         eval _fslist=\$critical_filesystems_${1}
166         for _fs in $_fslist; do
167                 mount | (
168                         _ismounted=no
169                         while read what _on on _type type; do
170                                 if [ $on = $_fs ]; then
171                                         _ismounted=yes
172                                 fi
173                         done
174                         if [ $_ismounted = no ]; then
175                                 mount $_fs >/dev/null 2>&1
176                         fi
177                 )
178         done
179 }
180
181 #
182 # check_pidfile pidfile procname [interpreter]
183 #       Parses the first line of pidfile for a PID, and ensures
184 #       that the process is running and matches procname.
185 #       Prints the matching PID upon success, nothing otherwise.
186 #       interpreter is optional; see _find_processes() for details.
187 #
188 check_pidfile()
189 {
190         _pidfile=$1
191         _procname=$2
192         _interpreter=$3
193         if [ -z "$_pidfile" -o -z "$_procname" ]; then
194                 err 3 'USAGE: check_pidfile pidfile procname [interpreter]'
195         fi
196         if [ ! -f $_pidfile ]; then
197                 debug "pid file {$_pidfile): not readable."
198                 return
199         fi
200         read _pid _junk < $_pidfile
201         if [ -z "$_pid" ]; then
202                 debug "pid file {$_pidfile): no pid in file."
203                 return
204         fi
205         _find_processes $_procname ${_interpreter:-.} '-p '"$_pid"
206 }
207
208 #
209 # check_process procname [interpreter]
210 #       Ensures that a process (or processes) named procname is running.
211 #       Prints a list of matching PIDs.
212 #       interpreter is optional; see _find_processes() for details.
213 #
214 check_process()
215 {
216         _procname=$1
217         _interpreter=$2
218         if [ -z "$_procname" ]; then
219                 err 3 'USAGE: check_process procname [interpreter]'
220         fi
221         _find_processes $_procname ${_interpreter:-.} '-ax'
222 }
223
224 #
225 # _find_processes procname interpreter psargs
226 #       Search for procname in the output of ps generated by psargs.
227 #       Prints the PIDs of any matching processes, space separated.
228 #
229 #       If interpreter == ".", check the following variations of procname
230 #       against the first word of each command:
231 #               procname
232 #               `basename procname`
233 #               `basename procname` + ":"
234 #               "(" + `basename procname` + ")"
235 #
236 #       If interpreter != ".", read the first line of procname, remove the
237 #       leading #!, normalise whitespace, append procname, and attempt to
238 #       match that against each command, either as is, or with extra words
239 #       at the end.
240 #
241 _find_processes()
242 {
243         if [ $# -ne 3 ]; then
244                 err 3 'USAGE: _find_processes procname interpreter psargs'
245         fi
246         _procname=$1
247         _interpreter=$2
248         _psargs=$3
249
250         _pref=
251         if [ $_interpreter != "." ]; then       # an interpreted script
252                 read _interp < $_procname       # read interpreter name
253                 _interp=${_interp#\#!}          # strip #!
254                 set -- $_interp
255                 if [ $_interpreter != $1 ]; then
256                         warn "\$command_interpreter $_interpreter != $1"
257                 fi
258                 _interp="$* $_procname"         # cleanup spaces, add _procname
259                 _fp_args='_argv'
260                 _fp_match='case "$_argv" in
261                     ${_interp}|"${_interp} "*)'
262         else                                    # a normal daemon
263                 _procnamebn=${_procname##*/}
264                 _fp_args='_arg0 _argv'
265                 _fp_match='case "$_arg0" in
266                     $_procname|$_procnamebn|${_procnamebn}:|"(${_procnamebn})")'
267         fi
268
269         _proccheck='
270                 ps -o "pid,command" '"$_psargs"' |
271                 while read _npid '"$_fp_args"'; do
272                         case "$_npid" in
273                             PID)
274                                 continue ;;
275                         esac ; '"$_fp_match"'
276                                 echo -n "$_pref$_npid" ;
277                                 _pref=" "
278                                 ;;
279                         esac
280                 done'
281
282 #       debug "in _find_processes: proccheck is ($_proccheck)."
283         eval $_proccheck
284 }
285
286 #
287 # wait_for_pids pid [pid ...]
288 #       spins until none of the pids exist
289 #
290 wait_for_pids()
291 {
292         _list=$*
293         if [ -z "$_list" ]; then
294                 return
295         fi
296         _prefix=
297         while true; do
298                 _nlist="";
299                 for _j in $_list; do
300                         if kill -0 $_j 2>/dev/null; then
301                                 _nlist="${_nlist}${_nlist:+ }$_j"
302                         fi
303                 done
304                 if [ -z "$_nlist" ]; then
305                         break
306                 fi
307                 _list=$_nlist
308                 echo -n ${_prefix:-"Waiting for PIDS: "}$_list
309                 _prefix=", "
310                 sleep 2
311         done
312         if [ -n "$_prefix" ]; then
313                 echo "."
314         fi
315 }
316
317 #
318 # run_rc_command argument
319 #       Search for argument in the list of supported commands, which is:
320 #               "start stop restart rcvar status poll ${extra_commands}"
321 #       If there's a match, run ${argument}_cmd or the default method
322 #       (see below).
323 #
324 #       If argument has a given prefix, then change the operation as follows:
325 #               Prefix  Operation
326 #               ------  ---------
327 #               fast    Skip the pid check, and set rc_fast=yes
328 #               force   Set ${rcvar} to YES, and set rc_force=yes
329 #
330 #       The following globals are used:
331 #
332 #       Name            Needed  Purpose
333 #       ----            ------  -------
334 #       name            y       Name of script.
335 #
336 #       command         n       Full path to command.
337 #                               Not needed if ${rc_arg}_cmd is set for
338 #                               each keyword.
339 #
340 #       command_args    n       Optional args/shell directives for command.
341 #
342 #       command_interpreter n   If not empty, command is interpreted, so
343 #                               call check_{pidfile,process}() appropriately.
344 #
345 #       extra_commands  n       List of extra commands supported.
346 #
347 #       pidfile         n       If set, use check_pidfile $pidfile $command,
348 #                               otherwise use check_process $command.
349 #                               In either case, only check if $command is set.
350 #
351 #       procname        n       Process name to check for instead of $command.
352 #
353 #       rcvar           n       This is checked with checkyesno to determine
354 #                               if the action should be run.
355 #
356 #       ${name}_chroot  n       Directory to chroot to before running ${command}
357 #                               Requires /usr to be mounted.
358 #
359 #       ${name}_chdir   n       Directory to cd to before running ${command}
360 #                               (if not using ${name}_chroot).
361 #
362 #       ${name}_flags   n       Arguments to call ${command} with.
363 #                               NOTE:   $flags from the parent environment
364 #                                       can be used to override this.
365 #
366 #       ${name}_nice    n       Nice level to run ${command} at.
367 #
368 #       ${name}_user    n       User to run ${command} as, using su(1) if not
369 #                               using ${name}_chroot.
370 #                               Requires /usr to be mounted.
371 #
372 #       ${name}_group   n       Group to run chrooted ${command} as.
373 #                               Requires /usr to be mounted.
374 #
375 #       ${name}_groups  n       Comma separated list of supplementary groups
376 #                               to run the chrooted ${command} with.
377 #                               Requires /usr to be mounted.
378 #
379 #       ${rc_arg}_cmd   n       If set, use this as the method when invoked;
380 #                               Otherwise, use default command (see below)
381 #
382 #       ${rc_arg}_precmd n      If set, run just before performing the
383 #                               ${rc_arg}_cmd method in the default
384 #                               operation (i.e, after checking for required
385 #                               bits and process (non)existence).
386 #                               If this completes with a non-zero exit code,
387 #                               don't run ${rc_arg}_cmd.
388 #
389 #       ${rc_arg}_postcmd n     If set, run just after performing the
390 #                               ${rc_arg}_cmd method, if that method
391 #                               returned a zero exit code.
392 #
393 #       required_dirs   n       If set, check for the existence of the given
394 #                               directories before running the default
395 #                               (re)start command.
396 #
397 #       required_files  n       If set, check for the readability of the given
398 #                               files before running the default (re)start
399 #                               command.
400 #
401 #       required_vars   n       If set, perform checkyesno on each of the
402 #                               listed variables before running the default
403 #                               (re)start command.
404 #
405 #       Default behaviour for a given argument, if no override method is
406 #       provided:
407 #
408 #       Argument        Default behaviour
409 #       --------        -----------------
410 #       start           if !running && checkyesno ${rcvar}
411 #                               ${command}
412 #
413 #       stop            if ${pidfile}
414 #                               rc_pid=$(check_pidfile $pidfile $command)
415 #                       else
416 #                               rc_pid=$(check_process $command)
417 #                       kill $sig_stop $rc_pid
418 #                       wait_for_pids $rc_pid
419 #                       ($sig_stop defaults to TERM.)
420 #
421 #       reload          Similar to stop, except use $sig_reload instead,
422 #                       and doesn't wait_for_pids.
423 #                       $sig_reload defaults to HUP.
424 #
425 #       restart         Run `stop' then `start'.
426 #
427 #       status          Show if ${command} is running, etc.
428 #
429 #       poll            Wait for ${command} to exit.
430 #
431 #       rcvar           Display what rc.conf variable is used (if any).
432 #
433 #       Variables available to methods, and after run_rc_command() has
434 #       completed:
435 #
436 #       Variable        Purpose
437 #       --------        -------
438 #       rc_arg          Argument to command, after fast/force processing
439 #                       performed
440 #
441 #       rc_flags        Flags to start the default command with.
442 #                       Defaults to ${name}_flags, unless overridden
443 #                       by $flags from the environment.
444 #                       This variable may be changed by the precmd method.
445 #
446 #       rc_pid          PID of command (if appropriate)
447 #
448 #       rc_fast         Not empty if "fast" was provided (q.v.)
449 #
450 #       rc_force        Not empty if "force" was provided (q.v.)
451 #
452 #
453 run_rc_command()
454 {
455         _return=0
456         rc_arg=$1
457         if [ -z "$name" ]; then
458                 err 3 'run_rc_command: $name is not set.'
459         fi
460
461         case "$rc_arg" in
462         fast*)                          # "fast" prefix; don't check pid
463                 rc_arg=${rc_arg#fast}
464                 rc_fast=yes
465                 ;;
466         force*)                         # "force prefix; always start
467                 rc_arg=${rc_arg#force}
468                 rc_force=yes
469                 if [ -n "${rcvar}" ]; then
470                         eval ${rcvar}=YES
471                 fi
472                 ;;
473         esac
474
475         eval _overide_command=\$${name}_program
476         if [ -n "$_overide_command" ]; then
477                 command=$_overide_command
478         fi
479
480         _keywords="start stop restart rcvar $extra_commands"
481         rc_pid=
482         _pidcmd=
483         _procname=${procname:-${command}}
484
485                                         # setup pid check command if not fast
486         if [ -z "$rc_fast" -a -n "$_procname" ]; then
487                 if [ -n "$pidfile" ]; then
488                         _pidcmd='rc_pid=$(check_pidfile '"$pidfile $_procname $command_interpreter"')'
489                 else
490                         _pidcmd='rc_pid=$(check_process '"$_procname $command_interpreter"')'
491                 fi
492                 if [ -n "$_pidcmd" ]; then
493                         _keywords="${_keywords} status poll"
494                 fi
495         fi
496
497         if [ -z "$rc_arg" ]; then
498                 rc_usage "$_keywords"
499         fi
500
501         if [ -n "$flags" ]; then        # allow override from environment
502                 rc_flags=$flags
503         else
504                 eval rc_flags=\$${name}_flags
505         fi
506         eval _chdir=\$${name}_chdir     _chroot=\$${name}_chroot \
507             _nice=\$${name}_nice        _user=\$${name}_user \
508             _group=\$${name}_group      _groups=\$${name}_groups
509
510         if [ -n "$_user" ]; then        # unset $_user if running as that user
511                 if [ "$_user" = "$(id -un)" ]; then
512                         unset _user
513                 fi
514         fi
515
516                                         # if ${rcvar} is set, and $1 is not
517                                         # "rcvar", then run
518                                         #       checkyesno ${rcvar}
519                                         # and return if that failed
520                                         #
521         if [ -n "${rcvar}" -a "$rc_arg" != "rcvar" ]; then
522                 if ! checkyesno ${rcvar}; then
523                         return 0
524                 fi
525         fi
526
527         eval $_pidcmd                   # determine the pid if necessary
528
529         for _elem in $_keywords; do
530                 if [ "$_elem" != "$rc_arg" ]; then
531                         continue
532                 fi
533
534                                         # if there's a custom ${XXX_cmd},
535                                         # run that instead of the default
536                                         #
537                 eval _cmd=\$${rc_arg}_cmd _precmd=\$${rc_arg}_precmd \
538                     _postcmd=\$${rc_arg}_postcmd
539                 if [ -n "$_cmd" ]; then
540                                         # if the precmd failed and force
541                                         # isn't set, exit
542                                         #
543                         if [ -n "$_precmd" ]; then
544                                 debug "run_rc_command: evaluating ${_precmd}()."
545                                 eval $_precmd
546                                 _return=$?
547                                 [ $_return -ne 0 ] && [ -z "$rc_force" ] &&
548                                     return 1
549                         fi
550
551                         if [ -n "$_cmd" ]; then
552                                 debug "run_rc_command: evaluating ${_cmd}()."
553                                 eval $_cmd
554                                 _return=$?
555                                 [ $_return -ne 0 ] && [ -z "$rc_force" ] &&
556                                     return 1
557                         fi
558
559                         if [ -n "$_postcmd" ]; then
560                                 debug "run_rc_command: evaluating ${_postcmd}()."
561                                  eval $_postcmd
562                                 _return=$?
563                         fi
564                         return $_return
565                 fi
566
567                 case "$rc_arg" in       # default operations...
568
569                 status)
570                         if [ -n "$rc_pid" ]; then
571                                 echo "${name} is running as pid $rc_pid."
572                         else
573                                 echo "${name} is not running."
574                                 return 1
575                         fi
576                         ;;
577
578                 start)
579                         if [ -n "$rc_pid" ]; then
580                                 echo "${name} already running? (pid=$rc_pid)."
581                                 exit 1
582                         fi
583
584                         if [ ! -x $command ]; then
585                                 info "run_rc_command: cannot run ($command)."
586                                 return 0
587                         fi
588
589                                         # check for required variables,
590                                         # directories, and files
591                                         #
592                         for _f in $required_vars; do
593                                 if ! checkyesno $_f; then
594                                         warn "\$${_f} is not set."
595                                         if [ -z "$rc_force" ]; then
596                                                 return 1
597                                         fi
598                                 fi
599                         done
600                         for _f in $required_dirs; do
601                                 if [ ! -d "${_f}/." ]; then
602                                         warn "${_f} is not a directory."
603                                         if [ -z "$rc_force" ]; then
604                                                 return 1
605                                         fi
606                                 fi
607                         done
608                         for _f in $required_files; do
609                                 if [ ! -r "${_f}" ]; then
610                                         warn "${_f} is not readable."
611                                         if [ -z "$rc_force" ]; then
612                                                 return 1
613                                         fi
614                                 fi
615                         done
616
617                                         # if the precmd failed and force
618                                         # isn't set, exit
619                                         #
620                         if [ -n "${_precmd}" ]; then
621                                 debug "run_rc_command: evaluating ${_precmd}()."
622                                 eval $_precmd
623                                 _return=$?
624                                 [ $_return -ne 0 ] && [ -z "$rc_force" ] &&
625                                     return 1
626                         fi
627
628                                         # setup the command to run, and run it
629                                         #
630                         echo "Starting ${name}."
631                         if [ -n "$_chroot" ]; then
632                                 _doit="\
633 ${_nice:+nice -n $_nice }\
634 chroot ${_user:+-u $_user }${_group:+-g $_group }${_groups:+-G $_groups }\
635 $_chroot $command $rc_flags $command_args"
636                         else
637                                 _doit="\
638 ${_chdir:+cd $_chdir; }\
639 ${_nice:+nice -n $_nice }\
640 $command $rc_flags $command_args"
641                                 if [ -n "$_user" ]; then
642                                     _doit="su -m $_user -c 'sh -c \"$_doit\"'"
643                                 fi
644                         fi
645
646                                         # if the cmd failed and force
647                                         # isn't set, exit
648                                         #
649                         debug "run_rc_command: _doit: $_doit"
650                         eval $_doit
651                         _return=$?
652                         [ $_return -ne 0 ] && [ -z "$rc_force" ] && return 1
653
654                                         # finally, run postcmd
655                                         #
656                         if [ -n "${_postcmd}" ]; then
657                                 debug "run_rc_command: evaluating ${_postcmd}()."
658                                 eval $_postcmd
659                         fi
660                         ;;
661
662                 stop)
663                         if [ -z "$rc_pid" ]; then
664                                 if [ -n "$pidfile" ]; then
665                                         echo \
666                                     "${name} not running? (check $pidfile)."
667                                 else
668                                         echo "${name} not running?"
669                                 fi
670                                 exit 1
671                         fi
672
673                                         # if the precmd failed and force
674                                         # isn't set, exit
675                                         #
676                         if [ -n $_precmd ]; then
677                                 eval $_precmd
678                                 _return=$?
679                                 [ $_return -ne 0 ] && [ -z "$rc_force" ] &&
680                                     return 1
681                         fi
682
683                                         # send the signal to stop
684                                         #
685                         echo "Stopping ${name}."
686                         _doit="kill -${sig_stop:-TERM} $rc_pid"
687                         if [ -n "$_user" ]; then
688                                 _doit="su -m $_user -c 'sh -c \"$_doit\"'"
689                         fi
690
691                                         # if the stop cmd failed and force
692                                         # isn't set, exit
693                                         #
694                         eval $_doit
695                         _return=$?
696                         [ $_return -ne 0 ] && [ -z "$rc_force" ] && return 1
697
698                                         # wait for the command to exit,
699                                         # and run postcmd.
700                         wait_for_pids $rc_pid
701                         if [ -n "$_postcmd" ]; then
702                                 eval $_postcmd
703                                 _return=$?
704                         fi
705                         ;;
706
707                 reload)
708                         if [ -z "$rc_pid" ]; then
709                                 if [ -n "$pidfile" ]; then
710                                         echo \
711                                     "${name} not running? (check $pidfile)."
712                                 else
713                                         echo "${name} not running?"
714                                 fi
715                                 exit 1
716                         fi
717                         echo "Reloading ${name} config files."
718                         if [ -n "$_precmd" ]; then
719                                 eval $_precmd
720                                 _return=$?
721                                 [ $_return -ne 0 ] && [ -z "$rc_force" ] &&
722                                     return 1
723                         fi
724                         _doit="kill -${sig_reload:-HUP} $rc_pid"
725                         if [ -n "$_user" ]; then
726                                 _doit="su -m $_user -c 'sh -c \"$_doit\"'"
727                         fi
728                         eval $_doit
729                         _return=$?
730                         [ $_return -ne 0 ] && [ -z "$rc_force" ] && return 1
731                         if [ -n "$_postcmd" ]; then
732                                 eval $_postcmd
733                                 _return=$?
734                         fi
735                         ;;
736
737                 restart)
738                         if [ -n "$_precmd" ]; then
739                                 eval $_precmd
740                                 _return=$?
741                                 [ $_return -ne 0 ] && [ -z "$rc_force" ] &&
742                                     return 1
743                         fi
744                                         # prevent restart being called more
745                                         # than once by any given script
746                                         #
747                         if [ -n "$_rc_restart_done" ]; then
748                                 return 0
749                         fi
750                         _rc_restart_done=YES
751
752                         ( $0 ${rc_force:+force}stop )
753                         $0 ${rc_force:+force}start
754
755                         if [ -n "$_postcmd" ]; then
756                                 eval $_postcmd
757                                 _return=$?
758                         fi
759                         ;;
760
761                 poll)
762                         if [ -n "$rc_pid" ]; then
763                                 wait_for_pids $rc_pid
764                         fi
765                         ;;
766
767                 rcvar)
768                         echo "# $name"
769                         if [ -n "$rcvar" ]; then
770                                 if checkyesno ${rcvar}; then
771                                         echo "\$${rcvar}=YES"
772                                 else
773                                         echo "\$${rcvar}=NO"
774                                 fi
775                         fi
776                         ;;
777
778                 *)
779                         rc_usage "$_keywords"
780                         ;;
781
782                 esac
783                 return $_return
784         done
785
786         echo 1>&2 "$0: unknown directive '$rc_arg'."
787         rc_usage "$_keywords"
788         exit 1
789 }
790
791 #
792 # run_rc_script file arg
793 #       Start the script `file' with `arg', and correctly handle the
794 #       return value from the script.  If `file' ends with `.sh', it's
795 #       sourced into the current environment.  If `file' appears to be
796 #       a backup or scratch file, ignore it.  Otherwise if it's
797 #       executable run as a child process.
798 #
799 run_rc_script()
800 {
801         _file=$1
802         _arg=$2
803         if [ -z "$_file" -o -z "$_arg" ]; then
804                 err 3 'USAGE: run_rc_script file arg'
805         fi
806
807         trap "echo 'Reboot interrupted'; exit 1" 3
808
809         unset   name command command_args command_interpreter \
810                 extra_commands pidfile procname \
811                 rcvar required_dirs required_files required_vars
812         eval unset ${_arg}_cmd ${_arg}_precmd ${_arg}_postcmd
813
814         case "$_file" in
815         *.sh)                           # run in current shell
816                 set $_arg ; . $_file
817                 ;;
818         *[~#]|*.OLD|*.orig)             # scratch file; skip
819                 warn "Ignoring scratch file $_file"
820                 ;;
821         *)                              # run in subshell
822                 if [ -x $_file ]; then
823                         if [ -n "$rc_fast_and_loose" ]; then
824                                 set $_arg ; . $_file
825                         else
826                                 ( trap "echo 'Reboot interrupted'; exit 1" 3
827                                   set $_arg ; . $_file )
828                         fi
829                 fi
830                 ;;
831         esac
832 }
833
834 #
835 # load_rc_config
836 #       Source in the configuration file for a given command.
837 #
838 load_rc_config()
839 {
840         _command=$1
841         if [ -z "$_command" ]; then
842                 err 3 'USAGE: load_rc_config command'
843         fi
844
845         if [ -z "$_rc_conf_loaded" ]; then
846                 if [ -r /etc/defaults/rc.conf ]; then
847                         debug "Sourcing /etc/defaults/rc.conf"
848                         . /etc/defaults/rc.conf
849                         source_rc_confs
850                 elif [ -r /etc/rc.conf ]; then
851                         debug "Sourcing /etc/rc.conf (/etc/defaults/rc.conf doesn't exist)."
852                         . /etc/rc.conf
853                 fi
854                 _rc_conf_loaded=YES
855         fi
856         if [ -f /etc/rc.conf.d/"$_command" ]; then
857                 debug "Sourcing /etc/rc.conf.d/${_command}"
858                 . /etc/rc.conf.d/"$_command"
859         fi
860
861         # XXX - Deprecated variable name support
862         #
863         case ${OSTYPE} in
864         FreeBSD)
865                 [ -n "$portmap_enable" ] && rpcbind_enable="$portmap_enable"
866                 [ -n "$portmap_program" ] && rpcbind_program="$portmap_program"
867                 [ -n "$portmap_flags" ] && rpcbind_flags="$portmap_flags"
868                 [ -n "$single_mountd_enable" ] && mountd_enable="$single_mountd_enable"
869                 [ -n "$xntpd_enable" ] && ntpd_enable="$xntpd_enable"
870                 [ -n "$xntpd_program" ] && ntpd_program="$xntpd_program"
871                 [ -n "$xntpd_flags" ] && ntpd_flags="$xntpd_flags"
872                 [ -n "$dhcp_program" ] && dhclient_program="$dhcp_program"
873                 [ -n "$dhcp_flags" ] && dhclient_flags="$dhcp_flags"
874                 ;;
875         esac
876
877 }
878
879 #
880 # rc_usage commands
881 #       Print a usage string for $0, with `commands' being a list of
882 #       valid commands.
883 #
884 rc_usage()
885 {
886         echo -n 1>&2 "Usage: $0 [fast|force]("
887
888         _sep=
889         for _elem in $*; do
890                 echo -n 1>&2 "$_sep$_elem"
891                 _sep="|"
892         done
893         echo 1>&2 ")"
894         exit 1
895 }
896
897 #
898 # err exitval message
899 #       Display message to stderr and log to the syslog, and exit with exitval.
900 #
901 err()
902 {
903         exitval=$1
904         shift
905
906         if [ -x /usr/bin/logger ]; then
907                 logger "$0: ERROR: $*"
908         fi
909         echo 1>&2 "$0: ERROR: $*"
910         exit $exitval
911 }
912
913 #
914 # warn message
915 #       Display message to stderr and log to the syslog.
916 #
917 warn()
918 {
919         if [ -x /usr/bin/logger ]; then
920                 logger "$0: WARNING: $*"
921         fi
922         echo 1>&2 "$0: WARNING: $*"
923 }
924
925 #
926 # info message
927 #       Display informational message to stdout and log to syslog.
928 #
929 info()
930 {
931         if [ -x /usr/bin/logger ]; then
932                 logger "$0: INFO: $*"
933         fi
934         echo "$0: INFO: $*"
935 }
936
937 #
938 # debug message
939 #       If debugging is enabled in rc.conf output message to stderr.
940 #       BEWARE that you don't call any subroutine that itself calls this
941 #       function.
942 #
943 debug()
944 {
945         case ${rc_debug} in
946         [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
947                 if [ -x /usr/bin/logger ]; then
948                         logger "$0: INFO: $*"
949                 fi
950                 echo 1>&2 "$0: DEBUG: $*"
951                 ;;
952         esac
953 }
954
955 #
956 # backup_file action file cur backup
957 #       Make a backup copy of `file' into `cur', and save the previous
958 #       version of `cur' as `backup' or use rcs for archiving.
959 #
960 #       This routine checks the value of the backup_uses_rcs variable,
961 #       which can be either YES or NO.
962 #
963 #       The `action' keyword can be one of the following:
964 #
965 #       add             `file' is now being backed up (and is possibly
966 #                       being reentered into the backups system).  `cur'
967 #                       is created and RCS files, if necessary, are
968 #                       created as well.
969 #
970 #       update          `file' has changed and needs to be backed up.
971 #                       If `cur' exists, it is copied to to `back' or
972 #                       checked into RCS (if the repository file is old),
973 #                       and then `file' is copied to `cur'.  Another RCS
974 #                       check in done here if RCS is being used.
975 #
976 #       remove          `file' is no longer being tracked by the backups
977 #                       system.  If RCS is not being used, `cur' is moved
978 #                       to `back', otherwise an empty file is checked in,
979 #                       and then `cur' is removed.
980 #
981 #
982 backup_file()
983 {
984         _action=$1
985         _file=$2
986         _cur=$3
987         _back=$4
988
989         if checkyesno backup_uses_rcs; then
990                 _msg0="backup archive"
991                 _msg1="update"
992
993                 # ensure that history file is not locked
994                 if [ -f $_cur,v ]; then
995                         rcs -q -u -U -M $_cur
996                 fi
997
998                 # ensure after switching to rcs that the
999                 # current backup is not lost
1000                 if [ -f $_cur ]; then
1001                         # no archive, or current newer than archive
1002                         if [ ! -f $_cur,v -o $_cur -nt $_cur,v ]; then
1003                                 ci -q -f -u -t-"$_msg0" -m"$_msg1" $_cur
1004                                 rcs -q -kb -U $_cur
1005                                 co -q -f -u $_cur
1006                         fi
1007                 fi
1008
1009                 case $_action in
1010                 add|update)
1011                         cp -p $_file $_cur
1012                         ci -q -f -u -t-"$_msg0" -m"$_msg1" $_cur
1013                         rcs -q -kb -U $_cur
1014                         co -q -f -u $_cur
1015                         chown root:wheel $_cur $_cur,v
1016                         ;;
1017                 remove)
1018                         cp /dev/null $_cur
1019                         ci -q -f -u -t-"$_msg0" -m"$_msg1" $_cur
1020                         rcs -q -kb -U $_cur
1021                         chown root:wheel $_cur $_cur,v
1022                         rm $_cur
1023                         ;;
1024                 esac
1025         else
1026                 case $_action in
1027                 add|update)
1028                         if [ -f $_cur ]; then
1029                                 cp -p $_cur $_back
1030                         fi
1031                         cp -p $_file $_cur
1032                         chown root:wheel $_cur
1033                         ;;
1034                 remove)
1035                         mv -f $_cur $_back
1036                         ;;
1037                 esac
1038         fi
1039 }