autofs: Sync autofs(5) with FreeBSD
[dragonfly.git] / etc / rc.subr
1 # $NetBSD: rc.subr,v 1.49 2002/05/21 12:31:01 lukem Exp $
2 # $FreeBSD: head/etc/rc.subr 275359 2014-12-01 12:17:42Z des $
3 #
4 # Copyright (c) 1997-2002 The NetBSD Foundation, Inc.
5 # All rights reserved.
6 #
7 # This code is derived from software contributed to The NetBSD Foundation
8 # by Luke Mewburn.
9 #
10 # Redistribution and use in source and binary forms, with or without
11 # modification, are permitted provided that the following conditions
12 # are met:
13 # 1. Redistributions of source code must retain the above copyright
14 #    notice, this list of conditions and the following disclaimer.
15 # 2. Redistributions in binary form must reproduce the above copyright
16 #    notice, this list of conditions and the following disclaimer in the
17 #    documentation and/or other materials provided with the distribution.
18 # 3. All advertising materials mentioning features or use of this software
19 #    must display the following acknowledgement:
20 #        This product includes software developed by the NetBSD
21 #        Foundation, Inc. and its contributors.
22 # 4. Neither the name of The NetBSD Foundation nor the names of its
23 #    contributors may be used to endorse or promote products derived
24 #    from this software without specific prior written permission.
25 #
26 # THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 # PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 # POSSIBILITY OF SUCH DAMAGE.
37 #
38 # rc.subr
39 #       functions used by various rc scripts
40 #
41
42 : ${RC_PID:=$$}; export RC_PID
43
44 #
45 #       Operating System dependent/independent variables
46 #
47
48 if [ -z "$_file" ]; then
49         _file="$0"
50 fi
51 provide_list=`rcorder -p $_file`
52
53 if [ -n "${_rc_subr_loaded}" ]; then
54         return
55 fi
56
57 _rc_subr_loaded="YES"
58
59 SYSCTL="/sbin/sysctl"
60 SYSCTL_N="${SYSCTL} -n"
61 SYSCTL_W="${SYSCTL}"
62 CMD_OSTYPE="${SYSCTL_N} kern.ostype"
63 OSTYPE=`${CMD_OSTYPE}`
64
65 RC_RUNNING=0
66 RC_FAILED=1
67 RC_DISABLED=2
68 RC_IRRELEVANT=3
69 RC_CONFIGURED=4
70 RC_STOPPED=5
71
72 #
73 #       functions
74 #       ---------
75
76 # list_vars pattern
77 #       List vars matching pattern.
78 #
79 list_vars()
80 {
81         set | { while read LINE; do
82                 var="${LINE%%=*}"
83                 case "$var" in
84                 "$LINE"|*[!a-zA-Z0-9_]*) continue ;;
85                 $1) echo $var
86                 esac
87         done; }
88 }
89
90 # set_rcvar base_var
91 #       Set the variable name enabling a specific service.
92 #       FreeBSD uses ${service}_enable, while NetBSD uses
93 #       just the name of the service. For example:
94 #       FreeBSD: sendmail_enable="YES"
95 #       NetBSD : sendmail="YES"
96 #       $1 - if $name is not the base to work of off, specify
97 #            a different one
98 #
99 set_rcvar()
100 {
101         if [ -z "$1" ]; then
102                 base_var=${name}
103         else
104                 base_var="$1"
105         fi
106
107         echo ${base_var}
108 }
109
110 # set_provide_list
111 #
112 #       $1      should be $rc_arg (start, stop, restart, reload, etc)
113 #       $2      return value $RC_* 
114 #
115 #       Set the rcng_* variables associated with elements in provide_list
116 #       based on $1 and $2.
117 #
118 #       Returns non-zero when early termination should occur, in which
119 #       case the caller should return with a value of $? - 1
120 #
121 set_provide_list()
122 {
123     # Remember, plret is set to the early termination return code + 1,
124     # or 0 if we want to continue the operation.
125     #
126     for i in $provide_list; do
127         case $1$2 in
128         start$RC_RUNNING|restart$RC_RUNNING)
129             varsym -s rcng_$i=running
130             ;;
131         start$RC_FAILED|restart$RC_FAILED)
132             varsym -s rcng_$i=failed
133             ;;
134         start$RC_DISABLED|restart$RC_DISABLED|reload$RC_DISABLED)
135             varsym -s rcng_$i=disabled
136             ;;
137         start$RC_IRRELEVANT|restart$RC_IRRELEVANT|reload$RC_IRRELEVANT)
138             varsym -s rcng_$i=irrelevant
139             ;;
140         start$RC_CONFIGURED|restart$RC_CONFIGURED)
141             varsym -s rcng_$i=configured
142             ;;
143         stop$RC_DISABLED)
144             varsym -s rcng_$i=disabled
145             ;;
146         stop$RC_IRRELEVANT)
147             varsym -s rcng_$i=irrelevant
148             ;;
149         stop*)
150             varsym -s rcng_$i=stopped
151             ;;
152         *)
153             ;;
154         esac
155     done
156 }
157
158 # check_early_term
159 #       $1      should be $rc_arg (start, stop, restart, reload, etc)
160 #       $2      return value $RC_* 
161 #       $3      $rc_force       "" not to force, "anything" to force.
162 #
163 # The return code is 0 if early termination is not to occur, non-zero if
164 # it is to occur.  When early termination is to occur the caller should
165 # return check_early_term()'s return code - 1.    That is, early termination
166 # can occur with or without an error.
167 #
168 # The provide list will be adjusted when early termination occurs.
169 #
170 check_early_term()
171 {
172     case $2 in
173     $RC_RUNNING)
174         return 0
175         ;;
176     $RC_FAILED)
177         set_provide_list $1 $2
178         [ -z "$3" ] || return 0
179         return 2
180         ;;
181     $RC_DISABLED)
182         set_provide_list $1 $2
183         [ -z "$3" ] || return 0
184         return 1
185         ;;
186     $RC_IRRELEVANT)
187         set_provide_list $1 $2
188         [ -z "$3" ] || return 0
189         return 1
190         ;;
191     $RC_CONFIGURED)
192         return 0
193         ;;
194     $RC_STOPPED)
195         return 0
196         ;;
197     esac
198     set_provide_list $1 $2
199     [ -z "$3" ] || return 0
200     return 2
201 }
202
203 # adjust_return_code $1
204 #
205 #       Convert the return code to an exit code of 0 (success) or 1 (failure)
206 #
207 adjust_return_code()
208 {
209     if [ $1 = $RC_FAILED ]; then
210         return 1
211     fi
212     return 0
213 }
214
215 #
216 # force_depend script
217 #       Force a service to start. Intended for use by services
218 #       to resolve dependency issues. It is assumed the caller
219 #       has check to make sure this call is necessary
220 #       $1 - filename of script, in /etc/rc.d, to run
221 #
222 force_depend()
223 {
224         _depend="$1"
225
226         info "${name} depends on ${_depend}, which will be forced to start."
227         if ! /etc/rc.d/${_depend} forcestart ; then
228                 warn "Unable to force ${_depend}. It may already be running."
229                 return 1
230         fi
231         return 0
232 }
233
234 #
235 # checkyesno var
236 #       Test $1 variable, and warn if not set to YES or NO.
237 #       Return 0 if it's "yes" (et al), nonzero otherwise.
238 #
239 checkyesno()
240 {
241         # try foo
242         eval _value=\$${1%_enable}
243         # try foo_enable
244         if [ -z $_value ]
245         then
246                 eval _value=\$${1%_enable}_enable;
247         fi
248         debug "checkyesno: $1 is set to $_value."
249         case $_value in
250
251                 #       "yes", "true", "on", or "1"
252         [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
253                 return 0
254                 ;;
255
256                 #       "no", "false", "off", or "0"
257         [Nn][Oo]|[Ff][Aa][Ll][Ss][Ee]|[Oo][Ff][Ff]|0)
258                 return 1
259                 ;;
260         *)
261                 warn "\$${1} is not set properly - see rc.conf(5)."
262                 return 1
263                 ;;
264         esac
265 }
266
267 #
268 # reverse_list list
269 #       print the list in reverse order
270 #
271 reverse_list()
272 {
273         _revlist=
274         for _revfile in $*; do
275                 _revlist="$_revfile $_revlist"
276         done
277         echo $_revlist
278 }
279
280 #
281 # stop_boot always
282 #       If booting directly to multiuser or $always is true,
283 #       send SIGTERM to the parent (/etc/rc) to abort the boot.
284 #       Otherwise just exit.
285 #
286 stop_boot()
287 {
288         local always
289
290         case $1 in
291                 #       "yes", "true", "on", or "1"
292         [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
293                 always=true
294                 ;;
295         *)
296                 always=false
297                 ;;
298         esac
299         if [ "$autoboot" = yes -o "$always" = true ]; then
300                 echo "ERROR: ABORTING BOOT (sending SIGTERM to parent)!"
301                 kill -TERM ${RC_PID}
302         fi
303         exit 1
304 }
305
306 #
307 # mount_critical_filesystems type
308 #       Go through the list of critical filesystems as provided in
309 #       the rc.conf(5) variable $critical_filesystems_${type}, checking
310 #       each one to see if it is mounted, and if it is not, mounting it.
311 #
312 mount_critical_filesystems()
313 {
314         eval _fslist=\$critical_filesystems_${1}
315         for _fs in $_fslist; do
316                 mount | (
317                         _ismounted=no
318                         while read what _on on _type type; do
319                                 if [ $on = $_fs ]; then
320                                         _ismounted=yes
321                                 fi
322                         done
323                         if [ $_ismounted = no ]; then
324                                 mount $_fs >/dev/null 2>&1
325                         fi
326                 )
327         done
328 }
329
330 #
331 # check_pidfile pidfile procname [interpreter]
332 #       Parses the first line of pidfile for a PID, and ensures
333 #       that the process is running and matches procname.
334 #       Prints the matching PID upon success, nothing otherwise.
335 #       interpreter is optional; see _find_processes() for details.
336 #
337 check_pidfile()
338 {
339         _pidfile=$1
340         _procname=$2
341         _interpreter=$3
342         if [ -z "$_pidfile" -o -z "$_procname" ]; then
343                 err 3 'USAGE: check_pidfile pidfile procname [interpreter]'
344         fi
345         if [ ! -f $_pidfile ]; then
346                 debug "pid file {$_pidfile): not readable."
347                 return
348         fi
349         read _pid _junk < $_pidfile
350         if [ -z "$_pid" ]; then
351                 debug "pid file {$_pidfile): no pid in file."
352                 return
353         fi
354         _find_processes $_procname ${_interpreter:-.} '-p '"$_pid"
355 }
356
357 #
358 # check_process procname [interpreter]
359 #       Ensures that a process (or processes) named procname is running.
360 #       Prints a list of matching PIDs.
361 #       interpreter is optional; see _find_processes() for details.
362 #
363 check_process()
364 {
365         _procname=$1
366         _interpreter=$2
367         if [ -z "$_procname" ]; then
368                 err 3 'USAGE: check_process procname [interpreter]'
369         fi
370         _find_processes $_procname ${_interpreter:-.} '-ax'
371 }
372
373 #
374 # _find_processes procname interpreter psargs
375 #       Search for procname in the output of ps generated by psargs.
376 #       Prints the PIDs of any matching processes, space separated.
377 #
378 #       If interpreter == ".", check the following variations of procname
379 #       against the first word of each command:
380 #               procname
381 #               `basename procname`
382 #               `basename procname` + ":"
383 #               "(" + `basename procname` + ")"
384 #
385 #       If interpreter != ".", read the first line of procname, remove the
386 #       leading #!, normalise whitespace, append procname, and attempt to
387 #       match that against each command, either as is, or with extra words
388 #       at the end.
389 #
390 _find_processes()
391 {
392         if [ $# -ne 3 ]; then
393                 err 3 'USAGE: _find_processes procname interpreter psargs'
394         fi
395         _procname=$1
396         _interpreter=$2
397         _psargs=$3
398
399         _pref=
400         if [ $_interpreter != "." ]; then       # an interpreted script
401                 read _interp < $_procname       # read interpreter name
402                 _interp=${_interp#\#!}          # strip #!
403                 set -- $_interp
404                 if [ $_interpreter != $1 ]; then
405                         warn "\$command_interpreter $_interpreter != $1"
406                 fi
407                 _interp="$* $_procname"         # cleanup spaces, add _procname
408                 _interpbn="$1"                  # the interpreter binary
409                 _fp_args='_argv'
410                 _fp_match='case "$_argv" in
411                     "${_interpbn##*/}: "$_procname*|${_interp}|"${_interp} "*)'
412         else                                    # a normal daemon
413                 _procnamebn=${_procname##*/}
414                 _fp_args='_arg0 _argv'
415                 _fp_match='case "$_arg0" in
416                     $_procname|$_procnamebn|${_procnamebn}:|"(${_procnamebn})")'
417         fi
418
419         _proccheck='
420                 ps -o "pid,command" '"$_psargs"' |
421                 while read _npid '"$_fp_args"'; do
422                         case "$_npid" in
423                             PID)
424                                 continue ;;
425                         esac ; '"$_fp_match"'
426                                 echo -n "$_pref$_npid" ;
427                                 _pref=" "
428                                 ;;
429                         esac
430                 done'
431
432 #       debug "in _find_processes: proccheck is ($_proccheck)."
433         eval $_proccheck
434 }
435
436 #
437 # wait_for_pids pid [pid ...]
438 #       spins until none of the pids exist
439 #
440 wait_for_pids()
441 {
442         _list=$*
443         if [ -z "$_list" ]; then
444                 return
445         fi
446         _prefix=
447         while true; do
448                 _nlist="";
449                 for _j in $_list; do
450                         if kill -0 $_j 2>/dev/null; then
451                                 _nlist="${_nlist}${_nlist:+ }$_j"
452                         fi
453                 done
454                 if [ -z "$_nlist" ]; then
455                         break
456                 fi
457                 _list=$_nlist
458                 echo -n ${_prefix:-"Waiting for PIDS: "}$_list
459                 _prefix=", "
460                 sleep 2
461         done
462         if [ -n "$_prefix" ]; then
463                 echo "."
464         fi
465 }
466
467 #
468 # get_pidfile_from_conf string file
469 #
470 #       Takes a string to search for in the specified file.
471 #       Ignores lines with traditional comment characters.
472 #
473 # Example:
474 #
475 # if get_pidfile_from_conf string file; then
476 #       pidfile="$_pidfile_from_conf"
477 # else
478 #       pidfile='appropriate default'
479 # fi
480 #
481 get_pidfile_from_conf()
482 {
483         if [ -z "$1" -o -z "$2" ]; then
484                 err 3 "USAGE: get_pidfile_from_conf string file ($name)"
485         fi
486
487         local string file line
488
489         string="$1" ; file="$2"
490
491         if [ ! -s "$file" ]; then
492                 err 3 "get_pidfile_from_conf: $file does not exist ($name)"
493         fi
494
495         while read line; do
496                 case "$line" in
497                 *[#\;]*${string}*)      continue ;;
498                 *${string}*)            break ;;
499                 esac
500         done < $file
501
502         if [ -n "$line" ]; then
503                 line=${line#*/}
504                 _pidfile_from_conf="/${line%%[\"\;]*}"
505         else
506                 return 1
507         fi
508 }
509
510 #
511 # check_startmsgs
512 #       If rc_quiet is set (usually as a result of using faststart at
513 #       boot time) check if rc_startmsgs is enabled.
514 #
515 check_startmsgs()
516 {
517         if [ -n "$rc_quiet" ]; then
518                 checkyesno rc_startmsgs
519         else
520                 return 0
521         fi
522 }
523
524 #
525 # run_rc_command argument
526 #       Search for argument in the list of supported commands, which is:
527 #               "start stop restart rcvar status poll ${extra_commands}"
528 #       If there's a match, run ${argument}_cmd or the default method
529 #       (see below).
530 #
531 #       If argument has a given prefix, then change the operation as follows:
532 #               Prefix  Operation
533 #               ------  ---------
534 #               fast    Skip the pid check, and set rc_fast=yes, rc_quiet=yes
535 #               force   Set ${rcvar} to YES, and set rc_force=yes
536 #               one     Set ${rcvar} to YES
537 #               quiet   Don't output some diagnostics, and set rc_quiet=yes
538 #
539 #       The following globals are used:
540 #
541 #       Name            Needed  Purpose
542 #       ----            ------  -------
543 #       provide_list    (gen)   list of keywords provided by current rcng file
544 #
545 #       name            y       Name of script.
546 #
547 #       command         n       Full path to command.
548 #                               Not needed if ${rc_arg}_cmd is set for
549 #                               each keyword.
550 #
551 #       command_args    n       Optional args/shell directives for command.
552 #
553 #       command_interpreter n   If not empty, command is interpreted, so
554 #                               call check_{pidfile,process}() appropriately.
555 #
556 #       extra_commands  n       List of extra commands supported.
557 #
558 #       pidfile         n       If set, use check_pidfile $pidfile $command,
559 #                               otherwise use check_process $command.
560 #                               In either case, only check if $command is set.
561 #
562 #       procname        n       Process name to check for instead of $command.
563 #
564 #       rcvar           n       This is checked with checkyesno to determine
565 #                               if the action should be run.
566 #
567 #       ${name}_chroot  n       Directory to chroot to before running ${command}
568 #                               Requires /usr to be mounted.
569 #
570 #       ${name}_chdir   n       Directory to cd to before running ${command}
571 #                               (if not using ${name}_chroot).
572 #
573 #       ${name}_flags   n       Arguments to call ${command} with.
574 #                               NOTE:   $flags from the parent environment
575 #                                       can be used to override this.
576 #
577 #       ${name}_env     n       Environment variables to run ${command} with.
578 #
579 #       ${name}_nice    n       Nice level to run ${command} at.
580 #
581 #       ${name}_user    n       User to run ${command} as, using su(1) if not
582 #                               using ${name}_chroot.
583 #                               Requires /usr to be mounted.
584 #
585 #       ${name}_group   n       Group to run chrooted ${command} as.
586 #                               Requires /usr to be mounted.
587 #
588 #       ${name}_groups  n       Comma separated list of supplementary groups
589 #                               to run the chrooted ${command} with.
590 #                               Requires /usr to be mounted.
591 #
592 #       ${name}_prepend n       Command added before ${command}.
593 #
594 #       ${rc_arg}_cmd   n       If set, use this as the method when invoked;
595 #                               Otherwise, use default command (see below)
596 #
597 #       ${rc_arg}_precmd n      If set, run just before performing the
598 #                               ${rc_arg}_cmd method in the default
599 #                               operation (i.e, after checking for required
600 #                               bits and process (non)existence).
601 #                               If this completes with a non-zero exit code,
602 #                               don't run ${rc_arg}_cmd.
603 #
604 #       ${rc_arg}_postcmd n     If set, run just after performing the
605 #                               ${rc_arg}_cmd method, if that method
606 #                               returned a zero exit code.
607 #
608 #       required_dirs   n       If set, check for the existence of the given
609 #                               directories before running the default
610 #                               (re)start command.
611 #
612 #       required_files  n       If set, check for the readability of the given
613 #                               files before running the default (re)start
614 #                               command.
615 #
616 #       required_modules n      If set, ensure the given kernel modules are
617 #                               loaded before running a (re)start command.
618 #                               The check and possible loads are actually
619 #                               done after start_precmd so that the modules
620 #                               aren't loaded in vain, should the precmd
621 #                               return a non-zero status to indicate a error.
622 #                               If a word in the list looks like "foo:bar",
623 #                               "foo" is the KLD file name and "bar" is the
624 #                               module name.  If a word looks like "foo~bar",
625 #                               "foo" is the KLD file name and "bar" is a
626 #                               egrep(1) pattern matching the module name.
627 #                               Otherwise the module name is assumed to be
628 #                               the same as the KLD file name, which is most
629 #                               common.  See load_kld().
630 #
631 #       required_vars   n       If set, perform checkyesno on each of the
632 #                               listed variables before running the default
633 #                               (re)start command.
634 #
635 #       Default behaviour for a given argument, if no override method is
636 #       provided:
637 #
638 #       Argument        Default behaviour
639 #       --------        -----------------
640 #       start           if !running && checkyesno ${rcvar}
641 #                               ${command}
642 #
643 #       stop            if ${pidfile}
644 #                               rc_pid=$(check_pidfile $pidfile $command)
645 #                       else
646 #                               rc_pid=$(check_process $command)
647 #                       kill $sig_stop $rc_pid
648 #                       wait_for_pids $rc_pid
649 #                       ($sig_stop defaults to TERM.)
650 #
651 #       reload          Similar to stop, except use $sig_reload instead,
652 #                       and doesn't wait_for_pids.
653 #                       $sig_reload defaults to HUP.
654 #
655 #       restart         Run `stop' then `start'.
656 #
657 #       status          Show if ${command} is running, etc.
658 #
659 #       poll            Wait for ${command} to exit.
660 #
661 #       rcvar           Display what rc.conf variable is used (if any).
662 #
663 #       Variables available to methods, and after run_rc_command() has
664 #       completed:
665 #
666 #       Variable        Purpose
667 #       --------        -------
668 #       rc_arg          Argument to command, after fast/force/one processing
669 #                       performed
670 #
671 #       rc_flags        Flags to start the default command with.
672 #                       Defaults to ${name}_flags, unless overridden
673 #                       by $flags from the environment.
674 #                       This variable may be changed by the precmd method.
675 #
676 #       rc_pid          PID of command (if appropriate)
677 #
678 #       rc_fast         Not empty if "fast" was provided (q.v.)
679 #
680 #       rc_force        Not empty if "force" was provided (q.v.)
681 #
682 #       rc_quiet        Not empty if "quiet" was provided
683 #
684 #
685 dummy_rc_command()
686 {
687         rc_arg=$1
688
689         case "$rc_arg" in
690         fast*)                          # "fast" prefix; don't check pid
691                 rc_arg=${rc_arg#fast}
692                 ;;
693         force*)                         # "force" prefix; always start
694                 rc_arg=${rc_arg#force}
695                 ;;
696         one*)                           # "one" prefix; set ${rcvar}=yes
697                 rc_arg=${rc_arg#one}
698                 ;;
699         esac
700         set_provide_list $rc_arg $RC_CONFIGURED
701         return 0
702 }
703
704 run_rc_command()
705 {
706         _return=0
707         rc_arg=$1
708         if [ -z "$name" ]; then
709                 err 3 'run_rc_command: $name is not set.'
710         fi
711
712         # Don't repeat the first argument when passing additional command-
713         # line arguments to the command subroutines.
714         #
715         shift 1
716         rc_extra_args="$*"
717
718         case "$rc_arg" in
719         fast*)                          # "fast" prefix; don't check pid
720                 rc_arg=${rc_arg#fast}
721                 rc_fast=yes
722                 rc_quiet=yes
723                 ;;
724         force*)                         # "force" prefix; always start
725                 rc_arg=${rc_arg#force}
726                 rc_force=yes
727                 if [ -n "${rcvar}" ]; then
728                         eval ${rcvar}=YES
729                 fi
730                 ;;
731         one*)                           # "one" prefix; set ${rcvar}=yes
732                 rc_arg=${rc_arg#one}
733                 if [ -n "${rcvar}" ]; then
734                         eval ${rcvar}=YES
735                 fi
736                 ;;
737         quiet*)                         # "quiet" prefix; omit some messages
738                 _rc_prefix=quiet
739                 rc_arg=${rc_arg#${_rc_prefix}}
740                 rc_quiet=yes
741                 ;;
742         esac
743
744         eval _override_command=\$${name}_program
745         if [ -n "$_override_command" ]; then
746                 command=$_override_command
747         fi
748
749         _keywords="start stop restart rcvar $extra_commands"
750         rc_pid=
751         _pidcmd=
752         _procname=${procname:-${command}}
753
754                                         # setup pid check command if not fast
755         if [ -z "$rc_fast" -a -n "$_procname" ]; then
756                 if [ -n "$pidfile" ]; then
757                         _pidcmd='rc_pid=$(check_pidfile '"$pidfile $_procname $command_interpreter"')'
758                 else
759                         _pidcmd='rc_pid=$(check_process '"$_procname $command_interpreter"')'
760                 fi
761                 if [ -n "$_pidcmd" ]; then
762                         _keywords="${_keywords} status poll"
763                 fi
764         fi
765
766         if [ -z "$rc_arg" ]; then
767                 rc_usage "$_keywords"
768         fi
769
770         if [ -n "$flags" ]; then        # allow override from environment
771                 rc_flags=$flags
772         else
773                 eval rc_flags=\$${name}_flags
774         fi
775         eval _chdir=\$${name}_chdir     _chroot=\$${name}_chroot \
776             _nice=\$${name}_nice        _user=\$${name}_user \
777             _group=\$${name}_group      _groups=\$${name}_groups \
778             _env=\$${name}_env          _prepend=\$${name}_prepend
779
780         if [ -n "$_user" ]; then        # unset $_user if running as that user
781                 if [ "$_user" = "$(id -un)" ]; then
782                         unset _user
783                 fi
784         fi
785
786                                         # if ${rcvar} is set, and $1 is not
787                                         # "rcvar", then run
788                                         #       checkyesno ${rcvar}
789                                         # and return if that failed
790                                         #
791         if [ -n "${rcvar}" -a "$rc_arg" != "rcvar" ]; then
792                 if ! checkyesno ${rcvar}; then
793                         set_provide_list $rc_arg $RC_DISABLED
794                         return 0
795                 fi
796         fi
797
798         eval $_pidcmd                   # determine the pid if necessary
799
800         for _elem in $_keywords; do
801                 if [ "$_elem" != "$rc_arg" ]; then
802                         continue
803                 fi
804
805                                         # if there's a custom ${XXX_cmd},
806                                         # run that instead of the default
807                                         #
808                 eval _cmd=\$${rc_arg}_cmd _precmd=\$${rc_arg}_precmd \
809                     _postcmd=\$${rc_arg}_postcmd
810                 if [ -n "$_cmd" ]; then
811                                         # if the precmd failed and force
812                                         # isn't set, exit
813                                         #
814                         if [ -n "$_precmd" ]; then
815                                 debug "run_rc_command: evaluating ${_precmd}()."
816                                 eval $_precmd $rc_extra_args
817
818                                 _return=$?
819                                 check_early_term $rc_arg $_return "$rc_force" || return $(($?-1))
820                         fi
821
822                         if [ -n "$_cmd" ]; then
823                                 debug "run_rc_command: evaluating ${_cmd}()."
824                                 eval $_cmd $rc_extra_args
825                                 _return=$?
826                                 check_early_term $rc_arg $_return "$rc_force" || return $(($?-1))
827                         fi
828
829                         if [ -n "$_postcmd" ]; then
830                                 debug "run_rc_command: evaluating ${_postcmd}()."
831                                 eval $_postcmd $rc_extra_args
832                                 _return=$?
833                                 check_early_term $rc_arg $_return "" || return $(($?-1))
834                         fi
835                         set_provide_list $rc_arg $_return
836                         adjust_return_code $_return
837                         return $?
838                 fi
839
840                 case "$rc_arg" in       # default operations...
841
842                 status)
843                         if [ -n "$rc_pid" ]; then
844                                 echo "${name} is running as pid $rc_pid."
845                         else
846                                 echo "${name} is not running."
847                                 return 1
848                         fi
849                         ;;
850
851                 start)
852                         if [ -n "$rc_pid" ]; then
853                                 if [ -z "$rc_quiet" ]; then
854                                         echo "${name} already running? (pid=$rc_pid)."
855                                 fi
856                                 exit 1
857                         fi
858
859                         if [ ! -x $command ]; then
860                                 info "run_rc_command: cannot run ($command)."
861                                 set_provide_list $rc_arg $RC_FAILED
862                                 adjust_return_code $RC_FAILED
863                                 return $?
864                         fi
865
866                                         # check for required variables,
867                                         # directories, and files
868                                         #
869                         for _f in $required_vars; do
870                                 if ! checkyesno $_f; then
871                                         warn "\$${_f} is not set."
872                                         if [ -z "$rc_force" ]; then
873                                                 set_provide_list $rc_arg $RC_FAILED
874                                                 adjust_return_code $RC_FAILED
875                                                 return $?
876                                         fi
877                                 fi
878                         done
879                         for _f in $required_dirs; do
880                                 if [ ! -d "${_f}/." ]; then
881                                         warn "${_f} is not a directory."
882                                         if [ -z "$rc_force" ]; then
883                                                 set_provide_list $rc_arg $RC_FAILED
884                                                 adjust_return_code $RC_FAILED
885                                                 return $?
886                                         fi
887                                 fi
888                         done
889                         for _f in $required_files; do
890                                 if [ ! -r "${_f}" ]; then
891                                         warn "${_f} is not readable."
892                                         if [ -z "$rc_force" ]; then
893                                                 set_provide_list $rc_arg $RC_FAILED
894                                                 adjust_return_code $RC_FAILED
895                                                 return $?
896                                         fi
897                                 fi
898                         done
899                         for _f in $required_modules; do
900                                 case "${_f}" in
901                                 *~*)    _args="-e ${_f#*~} ${_f%%~*}" ;;
902                                 *:*)    _args="-m ${_f#*:} ${_f%%:*}" ;;
903                                 *)      _args="${_f}" ;;
904                                 esac
905                                 if ! load_kld ${_args}; then
906                                         if [ -z "$rc_force" ]; then
907                                                 set_provide_list $rc_arg $RC_FAILED
908                                                 adjust_return_code $RC_FAILED
909                                                 return $?
910                                         fi
911                                 fi
912                         done
913
914                                         # if the precmd failed and force
915                                         # isn't set, exit
916                                         #
917                         if [ -n "${_precmd}" ]; then
918                                 debug "run_rc_command: evaluating ${_precmd}()."
919                                 eval $_precmd
920                                 _return=$?
921                                 check_early_term $rc_arg $_return "$rc_force" || return $(($?-1))
922                         fi
923
924                                         # setup the command to run, and run it
925                                         #
926                         echo "Starting ${name}."
927                         if [ -n "$_chroot" ]; then
928                                 _doit="\
929 ${_nice:+nice -n $_nice }\
930 ${_env:+env $_env }\
931 chroot ${_user:+-u $_user }${_group:+-g $_group }${_groups:+-G $_groups }\
932 $_chroot $command $rc_flags $command_args"
933                         else
934                                 _doit="\
935 ${_chdir:+cd $_chdir; }\
936 ${_nice:+nice -n $_nice }\
937 ${_env:+env $_env }\
938 $command $rc_flags $command_args"
939                                 if [ -n "$_user" ]; then
940                                     _doit="su -m $_user -c 'sh -c \"$_doit\"'"
941                                 fi
942                                 if [ -n "$_prepend" ]; then
943                                         _doit="$_prepend $_doit"
944                                 fi
945                         fi
946
947                                         # if the cmd failed and force
948                                         # isn't set, exit
949                                         #
950                         debug "run_rc_command: _doit: $_doit"
951                         eval $_doit
952                         _return=$?
953                         check_early_term $rc_arg $_return "$rc_force" || return $(($?-1))
954                                         # finally, run postcmd
955                                         #
956                         if [ -n "${_postcmd}" ]; then
957                                 debug "run_rc_command: evaluating ${_postcmd}()."
958                                 eval $_postcmd
959                         fi
960                         ;;
961
962                 stop)
963                         if [ -z "$rc_pid" ]; then
964                                 if [ -n "$pidfile" ]; then
965                                         echo \
966                                     "${name} not running? (check $pidfile)."
967                                 else
968                                         echo "${name} not running?"
969                                 fi
970                                 set_provide_list $rc_arg $RC_STOPPED
971                                 exit 1
972                         fi
973
974                                         # if the precmd failed and force
975                                         # isn't set, exit
976                                         #
977                         if [ -n "$_precmd" ]; then
978                                 eval $_precmd
979                                 _return=$?
980                                 check_early_term $rc_arg $_return "$rc_force" || return $(($?-1))
981                         fi
982
983                                         # send the signal to stop
984                                         #
985                         echo "Stopping ${name}."
986                         _doit="kill -${sig_stop:-TERM} $rc_pid"
987                         if [ -n "$_user" ]; then
988                                 _doit="su -m $_user -c 'sh -c \"$_doit\"'"
989                         fi
990
991                                         # if the stop cmd failed and force
992                                         # isn't set, exit
993                                         #
994                         eval $_doit
995                         _return=$?
996                         check_early_term $rc_arg $_return "$rc_force" || return $(($?-1))
997                                         # wait for the command to exit,
998                                         # and run postcmd.
999                         sleep 0.1
1000                         wait_for_pids $rc_pid
1001                         if [ -n "$_postcmd" ]; then
1002                                 eval $_postcmd
1003                                 _return=$?
1004                         fi
1005                         ;;
1006
1007                 reload)
1008                         if [ -z "$rc_pid" ]; then
1009                                 if [ -n "$pidfile" ]; then
1010                                         echo \
1011                                     "${name} not running? (check $pidfile)."
1012                                 else
1013                                         echo "${name} not running?"
1014                                 fi
1015                                 set_provide_list $rc_arg $RC_FAILED
1016                                 exit 1
1017                         fi
1018                         echo "Reloading ${name} config files."
1019                         if [ -n "$_precmd" ]; then
1020                                 eval $_precmd
1021                                 _return=$?
1022                                 check_early_term $rc_arg $_return "$rc_force" || return $(($?-1))
1023                         fi
1024                         _doit="kill -${sig_reload:-HUP} $rc_pid"
1025                         if [ -n "$_user" ]; then
1026                                 _doit="su -m $_user -c 'sh -c \"$_doit\"'"
1027                         fi
1028                         eval $_doit
1029                         _return=$?
1030                         check_early_term $rc_arg $_return "$rc_force" || return $(($?-1))
1031                         if [ -n "$_postcmd" ]; then
1032                                 eval $_postcmd
1033                                 _return=$?
1034                         fi
1035                         ;;
1036
1037                 restart)
1038                         if [ -n "$_precmd" ]; then
1039                                 eval $_precmd $rc_extra_args
1040                                 _return=$?
1041                                 check_early_term $rc_arg $_return "$rc_force" || return $(($?-1))
1042                         fi
1043                                         # prevent restart being called more
1044                                         # than once by any given script
1045                                         #
1046                         if [ -n "$_rc_restart_done" ]; then
1047                                 return 0
1048                         fi
1049                         _rc_restart_done=YES
1050
1051                         ( $0 ${rc_force:+force}stop $rc_extra_args )
1052                         $0 ${rc_force:+force}start $rc_extra_args
1053                         _return=$?
1054
1055                         if [ -n "$_postcmd" ]; then
1056                                 eval $_postcmd $rc_extra_args
1057                                 adjust_return_code $?
1058                                 _return=$?
1059                         fi
1060                         # Do not set_provide_list(), the start command above
1061                         # will have done it for us and we do not know the
1062                         # actual RC code to base a setting on here.
1063                         #
1064                         return $_return
1065                         ;;
1066
1067                 poll)
1068                         if [ -n "$rc_pid" ]; then
1069                                 wait_for_pids $rc_pid
1070                         fi
1071                         ;;
1072
1073                 rcvar)
1074                         echo "# $name"
1075                         if [ -n "$rcvar" ]; then
1076                                 if checkyesno ${rcvar}; then
1077                                         echo "\$${rcvar}=YES"
1078                                 else
1079                                         echo "\$${rcvar}=NO"
1080                                 fi
1081                         fi
1082                         ;;
1083
1084                 *)
1085                         rc_usage "$_keywords"
1086                         ;;
1087
1088                 esac
1089                 set_provide_list $rc_arg $_return
1090                 adjust_return_code $_return
1091                 return $?
1092         done
1093
1094         echo 1>&2 "$0: unknown directive '$rc_arg'."
1095         rc_usage "$_keywords"
1096         exit 1
1097 }
1098
1099 #
1100 # Helper functions for run_rc_command: common code.
1101 # They use such global variables besides the exported rc_* ones:
1102 #
1103 #       name           R/W
1104 #       ------------------
1105 #       _precmd         R
1106 #       _postcmd        R
1107 #       _return         W
1108 #
1109 _run_rc_precmd()
1110 {
1111         check_required_before "$rc_arg" || return 1
1112
1113         if [ -n "$_precmd" ]; then
1114                 debug "run_rc_command: ${rc_arg}_precmd: $_precmd $rc_extra_args"
1115                 eval "$_precmd $rc_extra_args"
1116                 _return=$?
1117
1118                 # If precmd failed and force isn't set, request exit.
1119                 if [ $_return -ne 0 ] && [ -z "$rc_force" ]; then
1120                         return 1
1121                 fi
1122         fi
1123
1124         check_required_after "$rc_arg" || return 1
1125
1126         return 0
1127 }
1128
1129 _run_rc_postcmd()
1130 {
1131         if [ -n "$_postcmd" ]; then
1132                 debug "run_rc_command: ${rc_arg}_postcmd: $_postcmd $rc_extra_args"
1133                 eval "$_postcmd $rc_extra_args"
1134                 _return=$?
1135         fi
1136         return 0
1137 }
1138
1139 _run_rc_doit()
1140 {
1141         debug "run_rc_command: doit: $*"
1142         eval "$@"
1143         _return=$?
1144
1145         # If command failed and force isn't set, request exit.
1146         if [ $_return -ne 0 ] && [ -z "$rc_force" ]; then
1147                 return 1
1148         fi
1149
1150         return 0
1151 }
1152
1153 _run_rc_notrunning()
1154 {
1155         local _pidmsg
1156
1157         if [ -n "$pidfile" ]; then
1158                 _pidmsg=" (check $pidfile)."
1159         else
1160                 _pidmsg=
1161         fi
1162         echo 1>&2 "${name} not running?${_pidmsg}"
1163 }
1164
1165 _run_rc_killcmd()
1166 {
1167         local _cmd
1168
1169         _cmd="kill -$1 $rc_pid"
1170         if [ -n "$_user" ]; then
1171                 _cmd="su -m ${_user} -c 'sh -c \"${_cmd}\"'"
1172         fi
1173         echo "$_cmd"
1174 }
1175
1176 #
1177 # run_rc_script file arg
1178 #       Start the script `file' with `arg', and correctly handle the
1179 #       return value from the script.  If `file' ends with `.sh', it's
1180 #       sourced into the current environment.  If `file' appears to be
1181 #       a backup or scratch file, ignore it.  Otherwise if it's
1182 #       executable run as a child process.
1183 #
1184 run_rc_script()
1185 {
1186         _file=$1
1187         _arg=$2
1188         if [ -z "$_file" -o -z "$_arg" ]; then
1189                 err 3 'USAGE: run_rc_script file arg'
1190         fi
1191
1192         trap "echo 'Reboot interrupted'; exit 1" 3
1193
1194         unset   name command command_args command_interpreter \
1195                 extra_commands pidfile procname \
1196                 rcvar required_dirs required_files required_vars
1197         eval unset ${_arg}_cmd ${_arg}_precmd ${_arg}_postcmd
1198
1199         case "$_file" in
1200         *.sh)                           # run in current shell
1201                 set $_arg ; . $_file
1202                 ;;
1203         *[~#]|*.OLD|*.orig)             # scratch file; skip
1204                 warn "Ignoring scratch file $_file"
1205                 ;;
1206         *)                              # run in subshell
1207                 if [ -x $_file ]; then
1208                         if [ -n "$rc_fast_and_loose" ]; then
1209                                 set $_arg ; . $_file
1210                         else
1211                                 ( trap "echo 'Reboot interrupted'; exit 1" 3
1212                                   set $_arg ; . $_file )
1213                         fi
1214                 fi
1215                 ;;
1216         esac
1217 }
1218
1219 # Code common to scripts that need to load a kernel module
1220 # if it isn't in the kernel yet. Syntax:
1221 #   load_kld [-e regex] [-m module] file
1222 # where -e or -m chooses the way to check if the module
1223 # is already loaded:
1224 #   regex is egrep'd in the output from `kldstat -v',
1225 #   module is passed to `kldstat -m'.
1226 # The default way is as though `-m file' were specified.
1227 load_kld()
1228 {
1229         local _loaded _mod _opt _re
1230
1231         while getopts "e:m:" _opt; do
1232                 case "$_opt" in
1233                 e) _re="$OPTARG" ;;
1234                 m) _mod="$OPTARG" ;;
1235                 *) err 3 'USAGE: load_kld [-e regex] [-m module] file' ;;
1236                 esac
1237         done
1238         shift $(($OPTIND - 1))
1239         if [ $# -ne 1 ]; then
1240                 err 3 'USAGE: load_kld [-e regex] [-m module] file'
1241         fi
1242         _mod=${_mod:-$1}
1243         _loaded=false
1244         if [ -n "$_re" ]; then
1245                 if kldstat -v | egrep -q -e "$_re"; then
1246                         _loaded=true
1247                 fi
1248         else
1249                 if kldstat -q -m "$_mod"; then
1250                         _loaded=true
1251                 fi
1252         fi
1253         if ! $_loaded; then
1254                 if ! kldload "$1"; then
1255                         warn "Unable to load kernel module $1"
1256                         return 1
1257                 else
1258                         info "$1 kernel module loaded."
1259                 fi
1260         else
1261                 debug "load_kld: $1 kernel module already loaded."
1262         fi
1263         return 0
1264 }
1265
1266
1267 # ltr str src dst
1268 #       Change every $src in $str to $dst.
1269 #       Useful when /usr is not yet mounted and we cannot use tr(1), sed(1) nor
1270 #       awk(1).
1271 ltr()
1272 {
1273         local _str _src _dst _out _com
1274         _str=$1
1275         _src=$2
1276         _dst=$3
1277         _out=""
1278
1279         IFS=${_src}
1280         for _com in ${_str}; do
1281                 if [ -z "${_out}" ]; then
1282                         _out="${_com}"
1283                 else
1284                         _out="${_out}${_dst}${_com}"
1285                 fi
1286         done
1287         echo "${_out}"
1288 }
1289
1290 #
1291 # load_rc_config
1292 #       Source in the configuration file for a given command.
1293 #
1294 load_rc_config()
1295 {
1296         _command=$1
1297         if [ -z "$_command" ]; then
1298                 err 3 'USAGE: load_rc_config command'
1299         fi
1300
1301         if [ -z "$_rc_conf_loaded" ]; then
1302                 if [ -r /etc/defaults/rc.conf ]; then
1303                         debug "Sourcing /etc/defaults/rc.conf"
1304                         . /etc/defaults/rc.conf
1305                         source_rc_confs
1306                 elif [ -r /etc/rc.conf ]; then
1307                         debug "Sourcing /etc/rc.conf (/etc/defaults/rc.conf doesn't exist)."
1308                         . /etc/rc.conf
1309                 fi
1310                 _rc_conf_loaded=YES
1311         fi
1312         if [ -f /etc/rc.conf.d/"$_command" ]; then
1313                 debug "Sourcing /etc/rc.conf.d/${_command}"
1314                 . /etc/rc.conf.d/"$_command"
1315         fi
1316
1317         # XXX - Deprecated variable name support
1318         #
1319         [ -n "$portmap_enable" ] && rpcbind_enable="$portmap_enable"
1320         [ -n "$portmap_program" ] && rpcbind_program="$portmap_program"
1321         [ -n "$portmap_flags" ] && rpcbind_flags="$portmap_flags"
1322         [ -n "$single_mountd_enable" ] && mountd_enable="$single_mountd_enable"
1323
1324 }
1325
1326 #
1327 # rc_usage commands
1328 #       Print a usage string for $0, with `commands' being a list of
1329 #       valid commands.
1330 #
1331 rc_usage()
1332 {
1333         echo -n 1>&2 "Usage: $0 [fast|force|one|quiet]("
1334
1335         _sep=
1336         for _elem in $*; do
1337                 echo -n 1>&2 "$_sep$_elem"
1338                 _sep="|"
1339         done
1340         echo 1>&2 ")"
1341         exit 1
1342 }
1343
1344 #
1345 # err exitval message
1346 #       Display message to stderr and log to the syslog, and exit with exitval.
1347 #
1348 err()
1349 {
1350         exitval=$1
1351         shift
1352
1353         if [ -x /usr/bin/logger ]; then
1354                 logger "$0: ERROR: $*"
1355         fi
1356         echo 1>&2 "$0: ERROR: $*"
1357         exit $exitval
1358 }
1359
1360 #
1361 # warn message
1362 #       Display message to stderr and log to the syslog.
1363 #
1364 warn()
1365 {
1366         if [ -x /usr/bin/logger ]; then
1367                 logger "$0: WARNING: $*"
1368         fi
1369         echo 1>&2 "$0: WARNING: $*"
1370 }
1371
1372 #
1373 # info message
1374 #       Display informational message to stdout and log to syslog.
1375 #
1376 info()
1377 {
1378         case ${rc_info} in
1379         [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
1380                 if [ -x /usr/bin/logger ]; then
1381                         logger "$0: INFO: $*"
1382                 fi
1383                 echo "$0: INFO: $*"
1384                 ;;
1385         esac
1386 }
1387
1388 #
1389 # debug message
1390 #       If debugging is enabled in rc.conf output message to stderr.
1391 #       BEWARE that you don't call any subroutine that itself calls this
1392 #       function.
1393 #
1394 debug()
1395 {
1396         case ${rc_debug} in
1397         [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
1398                 if [ -x /usr/bin/logger ]; then
1399                         logger "$0: INFO: $*"
1400                 fi
1401                 echo 1>&2 "$0: DEBUG: $*"
1402                 ;;
1403         esac
1404 }
1405
1406 #
1407 # backup_file action file cur backup
1408 #       Make a backup copy of `file' into `cur', and save the previous
1409 #       version of `cur' as `backup' or use rcs for archiving.
1410 #
1411 #       This routine checks the value of the backup_uses_rcs variable,
1412 #       which can be either YES or NO.
1413 #
1414 #       The `action' keyword can be one of the following:
1415 #
1416 #       add             `file' is now being backed up (and is possibly
1417 #                       being reentered into the backups system).  `cur'
1418 #                       is created and RCS files, if necessary, are
1419 #                       created as well.
1420 #
1421 #       update          `file' has changed and needs to be backed up.
1422 #                       If `cur' exists, it is copied to to `back' or
1423 #                       checked into RCS (if the repository file is old),
1424 #                       and then `file' is copied to `cur'.  Another RCS
1425 #                       check in done here if RCS is being used.
1426 #
1427 #       remove          `file' is no longer being tracked by the backups
1428 #                       system.  If RCS is not being used, `cur' is moved
1429 #                       to `back', otherwise an empty file is checked in,
1430 #                       and then `cur' is removed.
1431 #
1432 #
1433 backup_file()
1434 {
1435         _action=$1
1436         _cpfile=$2
1437         _cur=$3
1438         _back=$4
1439
1440         if checkyesno backup_uses_rcs; then
1441                 _msg0="backup archive"
1442                 _msg1="update"
1443
1444                 # ensure that history file is not locked
1445                 if [ -f $_cur,v ]; then
1446                         rcs -q -u -U -M $_cur
1447                 fi
1448
1449                 # ensure after switching to rcs that the
1450                 # current backup is not lost
1451                 if [ -f $_cur ]; then
1452                         # no archive, or current newer than archive
1453                         if [ ! -f $_cur,v -o $_cur -nt $_cur,v ]; then
1454                                 ci -q -f -u -t-"$_msg0" -m"$_msg1" $_cur
1455                                 rcs -q -kb -U $_cur
1456                                 co -q -f -u $_cur
1457                         fi
1458                 fi
1459
1460                 case $_action in
1461                 add|update)
1462                         cp -p $_cpfile $_cur
1463                         ci -q -f -u -t-"$_msg0" -m"$_msg1" $_cur
1464                         rcs -q -kb -U $_cur
1465                         co -q -f -u $_cur
1466                         chown root:wheel $_cur $_cur,v
1467                         ;;
1468                 remove)
1469                         cp /dev/null $_cur
1470                         ci -q -f -u -t-"$_msg0" -m"$_msg1" $_cur
1471                         rcs -q -kb -U $_cur
1472                         chown root:wheel $_cur $_cur,v
1473                         rm $_cur
1474                         ;;
1475                 esac
1476         else
1477                 case $_action in
1478                 add|update)
1479                         if [ -f $_cur ]; then
1480                                 cp -p $_cur $_back
1481                         fi
1482                         cp -p $_cpfile $_cur
1483                         chown root:wheel $_cur
1484                         ;;
1485                 remove)
1486                         mv -f $_cur $_back
1487                         ;;
1488                 esac
1489         fi
1490 }
1491
1492 # devfs_mount_jail dir
1493 # Mounts a devfs file system appropriate for jails
1494 # on the directory dir.
1495 # This function returns non-zero if an error occurs.
1496 #
1497 devfs_mount_jail()
1498 {
1499         local jdev _me
1500         jdev="$1"
1501         _me="devfs_mount_jail"
1502
1503         if ! devfs_domount "$jdev" $rs; then
1504                 warn "$_me: devfs was not mounted on $jdev"
1505                 return 1
1506         fi
1507         return 0
1508 }
1509
1510 # devfs_domount dir
1511 # Mount devfs on dir.
1512 # Returns 0 on success.
1513 #
1514 devfs_domount()
1515 {
1516         local devdir _me
1517         devdir="$1"
1518         _me="devfs_domount()"
1519
1520         if [ -z "$devdir" ]; then
1521                 warn "$_me: you must specify a mount-point"
1522                 return 1
1523         fi
1524
1525         debug "$_me: mount-point is ($devdir)"
1526         if ! mount -t devfs devfs "$devdir"; then
1527                 warn "$_me: Unable to mount devfs on $devdir"
1528                 return 1
1529         fi
1530
1531 return 0
1532 }
1533
1534 # Find scripts in local_startup directories.
1535 find_local_scripts() {
1536         local_rc=''
1537         for dir in ${local_startup}; do
1538                 if [ -d "${dir}" ]; then
1539                         for file in `grep -l '^# PROVIDE:' ${dir}/* 2>/dev/null`; do
1540                                 case "$file" in
1541                                 *.sample) ;;
1542                                 *)      if [ -x "$file" ]; then
1543                                                 local_rc="${local_rc} ${file}"
1544                                         fi
1545                                         ;;
1546                                 esac
1547                         done
1548                 fi
1549         done
1550 }