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