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