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