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