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