78b99d6807
also recognize "interpreter: daemon" in ps(1) output. That case statement should be rewritten with expr(1) if more flexibility is needed. Fixes PR 35366 by Dominik Joe Pantucek, debugged with much assistance by him on IRC.
911 lines
21 KiB
Plaintext
911 lines
21 KiB
Plaintext
# $NetBSD: rc.subr,v 1.68 2007/01/27 14:30:26 hubertf Exp $
|
|
#
|
|
# Copyright (c) 1997-2004 The NetBSD Foundation, Inc.
|
|
# All rights reserved.
|
|
#
|
|
# This code is derived from software contributed to The NetBSD Foundation
|
|
# by Luke Mewburn.
|
|
#
|
|
# Redistribution and use in source and binary forms, with or without
|
|
# modification, are permitted provided that the following conditions
|
|
# are met:
|
|
# 1. Redistributions of source code must retain the above copyright
|
|
# notice, this list of conditions and the following disclaimer.
|
|
# 2. Redistributions in binary form must reproduce the above copyright
|
|
# notice, this list of conditions and the following disclaimer in the
|
|
# documentation and/or other materials provided with the distribution.
|
|
# 3. All advertising materials mentioning features or use of this software
|
|
# must display the following acknowledgement:
|
|
# This product includes software developed by the NetBSD
|
|
# Foundation, Inc. and its contributors.
|
|
# 4. Neither the name of The NetBSD Foundation nor the names of its
|
|
# contributors may be used to endorse or promote products derived
|
|
# from this software without specific prior written permission.
|
|
#
|
|
# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
|
# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
|
# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
# POSSIBILITY OF SUCH DAMAGE.
|
|
#
|
|
# rc.subr
|
|
# functions used by various rc scripts
|
|
#
|
|
|
|
: ${rcvar_manpage:='rc.conf(5)'}
|
|
|
|
#
|
|
# functions
|
|
# ---------
|
|
|
|
#
|
|
# checkyesno var
|
|
# Test $1 variable, and warn if not set to YES or NO.
|
|
# Return 0 if it's "yes" (et al), nonzero otherwise.
|
|
#
|
|
checkyesno()
|
|
{
|
|
eval _value=\$${1}
|
|
case $_value in
|
|
|
|
# "yes", "true", "on", or "1"
|
|
[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
|
|
return 0
|
|
;;
|
|
|
|
# "no", "false", "off", or "0"
|
|
[Nn][Oo]|[Ff][Aa][Ll][Ss][Ee]|[Oo][Ff][Ff]|0)
|
|
return 1
|
|
;;
|
|
*)
|
|
warn "\$${1} is not set properly - see ${rcvar_manpage}."
|
|
return 1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
#
|
|
# reverse_list list
|
|
# print the list in reverse order
|
|
#
|
|
reverse_list()
|
|
{
|
|
_revlist=
|
|
for _revfile; do
|
|
_revlist="$_revfile $_revlist"
|
|
done
|
|
echo $_revlist
|
|
}
|
|
|
|
#
|
|
# mount_critical_filesystems type
|
|
# Go through the list of critical filesystems as provided in
|
|
# the rc.conf(5) variable $critical_filesystems_${type}, checking
|
|
# each one to see if it is mounted, and if it is not, mounting it.
|
|
#
|
|
mount_critical_filesystems()
|
|
{
|
|
eval _fslist=\$critical_filesystems_${1}
|
|
for _fs in $_fslist; do
|
|
mount | (
|
|
_ismounted=false
|
|
while read what _on on _type type; do
|
|
if [ $on = $_fs ]; then
|
|
_ismounted=true
|
|
fi
|
|
done
|
|
if $_ismounted; then
|
|
:
|
|
else
|
|
mount $_fs >/dev/null 2>&1
|
|
fi
|
|
)
|
|
done
|
|
}
|
|
|
|
#
|
|
# check_pidfile pidfile procname [interpreter]
|
|
# Parses the first line of pidfile for a PID, and ensures
|
|
# that the process is running and matches procname.
|
|
# Prints the matching PID upon success, nothing otherwise.
|
|
# interpreter is optional; see _find_processes() for details.
|
|
#
|
|
check_pidfile()
|
|
{
|
|
_pidfile=$1
|
|
_procname=$2
|
|
_interpreter=$3
|
|
if [ -z "$_pidfile" -o -z "$_procname" ]; then
|
|
err 3 'USAGE: check_pidfile pidfile procname [interpreter]'
|
|
fi
|
|
if [ ! -f $_pidfile ]; then
|
|
return
|
|
fi
|
|
read _pid _junk < $_pidfile
|
|
if [ -z "$_pid" ]; then
|
|
return
|
|
fi
|
|
_find_processes $_procname ${_interpreter:-.} '-p '"$_pid"
|
|
}
|
|
|
|
#
|
|
# check_process procname [interpreter]
|
|
# Ensures that a process (or processes) named procname is running.
|
|
# Prints a list of matching PIDs.
|
|
# interpreter is optional; see _find_processes() for details.
|
|
#
|
|
check_process()
|
|
{
|
|
_procname=$1
|
|
_interpreter=$2
|
|
if [ -z "$_procname" ]; then
|
|
err 3 'USAGE: check_process procname [interpreter]'
|
|
fi
|
|
_find_processes $_procname ${_interpreter:-.} '-ax'
|
|
}
|
|
|
|
#
|
|
# _find_processes procname interpreter psargs
|
|
# Search for procname in the output of ps generated by psargs.
|
|
# Prints the PIDs of any matching processes, space separated.
|
|
#
|
|
# If interpreter == ".", check the following variations of procname
|
|
# against the first word of each command:
|
|
# procname
|
|
# `basename procname`
|
|
# `basename procname` + ":"
|
|
# "(" + `basename procname` + ")"
|
|
#
|
|
# If interpreter != ".", read the first line of procname, remove the
|
|
# leading #!, normalise whitespace, append procname, and attempt to
|
|
# match that against each command, either as is, or with extra words
|
|
# at the end. As an alternative, to deal with interpreted deaemons
|
|
# using perl, the basename of the interpreter plus a colon is also
|
|
# tried as the prefix to procname.
|
|
#
|
|
_find_processes()
|
|
{
|
|
if [ $# -ne 3 ]; then
|
|
err 3 'USAGE: _find_processes procname interpreter psargs'
|
|
fi
|
|
_procname=$1
|
|
_interpreter=$2
|
|
_psargs=$3
|
|
|
|
_pref=
|
|
_procnamebn=${_procname##*/}
|
|
if [ $_interpreter != "." ]; then # an interpreted script
|
|
read _interp < ${_chroot:-}/$_procname # read interpreter name
|
|
_interp=${_interp#\#!} # strip #!
|
|
set -- $_interp
|
|
if [ $_interpreter != $1 ]; then
|
|
warn "\$command_interpreter $_interpreter != $1"
|
|
fi
|
|
_interp="$* $_procname" # cleanup spaces, add _procname
|
|
_interpbn=${1##*/}
|
|
_fp_args='_argv'
|
|
_fp_match='case "$_argv" in
|
|
${_interp}|"${_interp} "*|"${_interpbn}: "*${_procnamebn}*)'
|
|
else # a normal daemon
|
|
_fp_args='_arg0 _argv'
|
|
_fp_match='case "$_arg0" in
|
|
$_procname|$_procnamebn|${_procnamebn}:|"(${_procnamebn})")'
|
|
fi
|
|
|
|
_proccheck='
|
|
ps -o "pid,command" '"$_psargs"' |
|
|
while read _npid '"$_fp_args"'; do
|
|
case "$_npid" in
|
|
PID)
|
|
continue ;;
|
|
esac ; '"$_fp_match"'
|
|
echo -n "$_pref$_npid" ;
|
|
_pref=" "
|
|
;;
|
|
esac
|
|
done'
|
|
|
|
#echo 1>&2 "proccheck is :$_proccheck:"
|
|
eval $_proccheck
|
|
}
|
|
|
|
#
|
|
# wait_for_pids pid [pid ...]
|
|
# spins until none of the pids exist
|
|
#
|
|
wait_for_pids()
|
|
{
|
|
_list="$@"
|
|
if [ -z "$_list" ]; then
|
|
return
|
|
fi
|
|
_prefix=
|
|
while true; do
|
|
_nlist="";
|
|
for _j in $_list; do
|
|
if kill -0 $_j 2>/dev/null; then
|
|
_nlist="${_nlist}${_nlist:+ }$_j"
|
|
fi
|
|
done
|
|
if [ -z "$_nlist" ]; then
|
|
break
|
|
fi
|
|
_list=$_nlist
|
|
echo -n ${_prefix:-"Waiting for PIDS: "}$_list
|
|
_prefix=", "
|
|
sleep 2
|
|
done
|
|
if [ -n "$_prefix" ]; then
|
|
echo "."
|
|
fi
|
|
}
|
|
|
|
#
|
|
# run_rc_command argument
|
|
# Search for argument in the list of supported commands, which is:
|
|
# "start stop restart rcvar status poll ${extra_commands}"
|
|
# If there's a match, run ${argument}_cmd or the default method
|
|
# (see below).
|
|
#
|
|
# If argument has a given prefix, then change the operation as follows:
|
|
# Prefix Operation
|
|
# ------ ---------
|
|
# fast Skip the pid check, and set rc_fast=yes
|
|
# force Set ${rcvar} to YES, and set rc_force=yes
|
|
# one Set ${rcvar} to YES
|
|
#
|
|
# The following globals are used:
|
|
#
|
|
# Name Needed Purpose
|
|
# ---- ------ -------
|
|
# name y Name of script.
|
|
#
|
|
# command n Full path to command.
|
|
# Not needed if ${rc_arg}_cmd is set for
|
|
# each keyword.
|
|
#
|
|
# command_args n Optional args/shell directives for command.
|
|
#
|
|
# command_interpreter n If not empty, command is interpreted, so
|
|
# call check_{pidfile,process}() appropriately.
|
|
#
|
|
# extra_commands n List of extra commands supported.
|
|
#
|
|
# pidfile n If set, use check_pidfile $pidfile $command,
|
|
# otherwise use check_process $command.
|
|
# In either case, only check if $command is set.
|
|
#
|
|
# procname n Process name to check for instead of $command.
|
|
#
|
|
# rcvar n This is checked with checkyesno to determine
|
|
# if the action should be run.
|
|
#
|
|
# ${name}_chroot n Directory to chroot to before running ${command}
|
|
# Requires /usr to be mounted.
|
|
#
|
|
# ${name}_chdir n Directory to cd to before running ${command}
|
|
# (if not using ${name}_chroot).
|
|
#
|
|
# ${name}_flags n Arguments to call ${command} with.
|
|
# NOTE: $flags from the parent environment
|
|
# can be used to override this.
|
|
#
|
|
# ${name}_nice n Nice level to run ${command} at.
|
|
#
|
|
# ${name}_user n User to run ${command} as, using su(1) if not
|
|
# using ${name}_chroot.
|
|
# Requires /usr to be mounted.
|
|
#
|
|
# ${name}_group n Group to run chrooted ${command} as.
|
|
# Requires /usr to be mounted.
|
|
#
|
|
# ${name}_groups n Comma separated list of supplementary groups
|
|
# to run the chrooted ${command} with.
|
|
# Requires /usr to be mounted.
|
|
#
|
|
# ${name}_systrace n Flags passed to systrace(1) if it is used.
|
|
# Setting this variable enables systracing
|
|
# of the given program. The use of "-a" is
|
|
# recommended so that the boot process is not
|
|
# stalled. In order to pass no flags to
|
|
# systrace, set this variable to "--".
|
|
#
|
|
# ${rc_arg}_cmd n If set, use this as the method when invoked;
|
|
# Otherwise, use default command (see below)
|
|
#
|
|
# ${rc_arg}_precmd n If set, run just before performing the
|
|
# ${rc_arg}_cmd method in the default
|
|
# operation (i.e, after checking for required
|
|
# bits and process (non)existence).
|
|
# If this completes with a non-zero exit code,
|
|
# don't run ${rc_arg}_cmd.
|
|
#
|
|
# ${rc_arg}_postcmd n If set, run just after performing the
|
|
# ${rc_arg}_cmd method, if that method
|
|
# returned a zero exit code.
|
|
#
|
|
# required_dirs n If set, check for the existence of the given
|
|
# directories before running the default
|
|
# (re)start command.
|
|
#
|
|
# required_files n If set, check for the readability of the given
|
|
# files before running the default (re)start
|
|
# command.
|
|
#
|
|
# required_vars n If set, perform checkyesno on each of the
|
|
# listed variables before running the default
|
|
# (re)start command.
|
|
#
|
|
# Default behaviour for a given argument, if no override method is
|
|
# provided:
|
|
#
|
|
# Argument Default behaviour
|
|
# -------- -----------------
|
|
# start if !running && checkyesno ${rcvar}
|
|
# ${command}
|
|
#
|
|
# stop if ${pidfile}
|
|
# rc_pid=$(check_pidfile $pidfile $command)
|
|
# else
|
|
# rc_pid=$(check_process $command)
|
|
# kill $sig_stop $rc_pid
|
|
# wait_for_pids $rc_pid
|
|
# ($sig_stop defaults to TERM.)
|
|
#
|
|
# reload Similar to stop, except use $sig_reload instead,
|
|
# and doesn't wait_for_pids.
|
|
# $sig_reload defaults to HUP.
|
|
#
|
|
# restart Run `stop' then `start'.
|
|
#
|
|
# status Show if ${command} is running, etc.
|
|
#
|
|
# poll Wait for ${command} to exit.
|
|
#
|
|
# rcvar Display what rc.conf variable is used (if any).
|
|
#
|
|
# Variables available to methods, and after run_rc_command() has
|
|
# completed:
|
|
#
|
|
# Variable Purpose
|
|
# -------- -------
|
|
# rc_arg Argument to command, after fast/force/one processing
|
|
# performed
|
|
#
|
|
# rc_flags Flags to start the default command with.
|
|
# Defaults to ${name}_flags, unless overridden
|
|
# by $flags from the environment.
|
|
# This variable may be changed by the precmd method.
|
|
#
|
|
# rc_pid PID of command (if appropriate)
|
|
#
|
|
# rc_fast Not empty if "fast" was provided (q.v.)
|
|
#
|
|
# rc_force Not empty if "force" was provided (q.v.)
|
|
#
|
|
#
|
|
run_rc_command()
|
|
{
|
|
rc_arg=$1
|
|
if [ -z "$name" ]; then
|
|
err 3 'run_rc_command: $name is not set.'
|
|
fi
|
|
|
|
_rc_prefix=
|
|
case "$rc_arg" in
|
|
fast*) # "fast" prefix; don't check pid
|
|
rc_arg=${rc_arg#fast}
|
|
rc_fast=yes
|
|
;;
|
|
force*) # "force" prefix; always run
|
|
rc_force=yes
|
|
_rc_prefix=force
|
|
rc_arg=${rc_arg#${_rc_prefix}}
|
|
if [ -n "${rcvar}" ]; then
|
|
eval ${rcvar}=YES
|
|
fi
|
|
;;
|
|
one*) # "one" prefix; set ${rcvar}=yes
|
|
_rc_prefix=one
|
|
rc_arg=${rc_arg#${_rc_prefix}}
|
|
if [ -n "${rcvar}" ]; then
|
|
eval ${rcvar}=YES
|
|
fi
|
|
;;
|
|
esac
|
|
|
|
_keywords="start stop restart rcvar $extra_commands"
|
|
rc_pid=
|
|
_pidcmd=
|
|
_procname=${procname:-${command}}
|
|
|
|
# setup pid check command if not fast
|
|
if [ -z "$rc_fast" -a -n "$_procname" ]; then
|
|
if [ -n "$pidfile" ]; then
|
|
_pidcmd='rc_pid=$(check_pidfile '"$pidfile $_procname $command_interpreter"')'
|
|
else
|
|
_pidcmd='rc_pid=$(check_process '"$_procname $command_interpreter"')'
|
|
fi
|
|
if [ -n "$_pidcmd" ]; then
|
|
_keywords="${_keywords} status poll"
|
|
fi
|
|
fi
|
|
|
|
if [ -z "$rc_arg" ]; then
|
|
rc_usage "$_keywords"
|
|
fi
|
|
|
|
if [ -n "$flags" ]; then # allow override from environment
|
|
rc_flags=$flags
|
|
else
|
|
eval rc_flags=\$${name}_flags
|
|
fi
|
|
eval _chdir=\$${name}_chdir _chroot=\$${name}_chroot \
|
|
_nice=\$${name}_nice _user=\$${name}_user \
|
|
_group=\$${name}_group _groups=\$${name}_groups \
|
|
_systrace=\$${name}_systrace
|
|
|
|
if [ -n "$_user" ]; then # unset $_user if running as that user
|
|
if [ "$_user" = "$(id -un)" ]; then
|
|
unset _user
|
|
fi
|
|
fi
|
|
|
|
# if ${rcvar} is set, and $1 is not
|
|
# "rcvar", then run
|
|
# checkyesno ${rcvar}
|
|
# and return if that failed
|
|
#
|
|
if [ -n "${rcvar}" -a "$rc_arg" != "rcvar" ]; then
|
|
if ! checkyesno ${rcvar}; then
|
|
return 0
|
|
fi
|
|
fi
|
|
|
|
eval $_pidcmd # determine the pid if necessary
|
|
|
|
for _elem in $_keywords; do
|
|
if [ "$_elem" != "$rc_arg" ]; then
|
|
continue
|
|
fi
|
|
|
|
# if there's a custom ${XXX_cmd},
|
|
# run that instead of the default
|
|
#
|
|
eval _cmd=\$${rc_arg}_cmd _precmd=\$${rc_arg}_precmd \
|
|
_postcmd=\$${rc_arg}_postcmd
|
|
if [ -n "$_cmd" ]; then
|
|
# if the precmd failed and force
|
|
# isn't set, exit
|
|
#
|
|
if ! eval $_precmd && [ -z "$rc_force" ]; then
|
|
return 1
|
|
fi
|
|
|
|
if ! eval $_cmd && [ -z "$rc_force" ]; then
|
|
return 1
|
|
fi
|
|
eval $_postcmd
|
|
return 0
|
|
fi
|
|
|
|
case "$rc_arg" in # default operations...
|
|
|
|
status)
|
|
if [ -n "$rc_pid" ]; then
|
|
echo "${name} is running as pid $rc_pid."
|
|
else
|
|
echo "${name} is not running."
|
|
return 1
|
|
fi
|
|
;;
|
|
|
|
start)
|
|
if [ -n "$rc_pid" ]; then
|
|
echo 1>&2 "${name} already running? (pid=$rc_pid)."
|
|
exit 1
|
|
fi
|
|
|
|
if [ ! -x ${_chroot}${command} ]; then
|
|
return 0
|
|
fi
|
|
|
|
# check for required variables,
|
|
# directories, and files
|
|
#
|
|
for _f in $required_vars; do
|
|
if ! checkyesno $_f; then
|
|
warn "\$${_f} is not enabled."
|
|
if [ -z "$rc_force" ]; then
|
|
return 1
|
|
fi
|
|
fi
|
|
done
|
|
for _f in $required_dirs; do
|
|
if [ ! -d "${_f}/." ]; then
|
|
warn "${_f} is not a directory."
|
|
if [ -z "$rc_force" ]; then
|
|
return 1
|
|
fi
|
|
fi
|
|
done
|
|
for _f in $required_files; do
|
|
if [ ! -r "${_f}" ]; then
|
|
warn "${_f} is not readable."
|
|
if [ -z "$rc_force" ]; then
|
|
return 1
|
|
fi
|
|
fi
|
|
done
|
|
|
|
# if the precmd failed and force
|
|
# isn't set, exit
|
|
#
|
|
if ! eval $_precmd && [ -z "$rc_force" ]; then
|
|
return 1
|
|
fi
|
|
|
|
# setup the command to run, and run it
|
|
#
|
|
echo "Starting ${name}."
|
|
if [ -n "$_chroot" ]; then
|
|
_doit="\
|
|
${_nice:+nice -n $_nice }\
|
|
${_systrace:+systrace $_systrace }\
|
|
chroot ${_user:+-u $_user }${_group:+-g $_group }${_groups:+-G $_groups }\
|
|
$_chroot $command $rc_flags $command_args"
|
|
else
|
|
_doit="\
|
|
${_chdir:+cd $_chdir; }\
|
|
${_nice:+nice -n $_nice }\
|
|
${_systrace:+systrace $_systrace }\
|
|
$command $rc_flags $command_args"
|
|
if [ -n "$_user" ]; then
|
|
_doit="su -m $_user -c 'sh -c \"$_doit\"'"
|
|
fi
|
|
fi
|
|
|
|
# if the cmd failed and force
|
|
# isn't set, exit
|
|
#
|
|
if ! eval $_doit && [ -z "$rc_force" ]; then
|
|
return 1
|
|
fi
|
|
|
|
# finally, run postcmd
|
|
#
|
|
eval $_postcmd
|
|
;;
|
|
|
|
stop)
|
|
if [ -z "$rc_pid" ]; then
|
|
if [ -n "$pidfile" ]; then
|
|
echo 1>&2 \
|
|
"${name} not running? (check $pidfile)."
|
|
else
|
|
echo 1>&2 "${name} not running?"
|
|
fi
|
|
exit 1
|
|
fi
|
|
|
|
# if the precmd failed and force
|
|
# isn't set, exit
|
|
#
|
|
if ! eval $_precmd && [ -z "$rc_force" ]; then
|
|
return 1
|
|
fi
|
|
|
|
# send the signal to stop
|
|
#
|
|
echo "Stopping ${name}."
|
|
_doit="kill -${sig_stop:-TERM} $rc_pid"
|
|
if [ -n "$_user" ]; then
|
|
_doit="su -m $_user -c 'sh -c \"$_doit\"'"
|
|
fi
|
|
|
|
# if the stop cmd failed and force
|
|
# isn't set, exit
|
|
#
|
|
if ! eval $_doit && [ -z "$rc_force" ]; then
|
|
return 1
|
|
fi
|
|
|
|
# wait for the command to exit,
|
|
# and run postcmd.
|
|
wait_for_pids $rc_pid
|
|
eval $_postcmd
|
|
;;
|
|
|
|
reload)
|
|
if [ -z "$rc_pid" ]; then
|
|
if [ -n "$pidfile" ]; then
|
|
echo 1>&2 \
|
|
"${name} not running? (check $pidfile)."
|
|
else
|
|
echo 1>&2 "${name} not running?"
|
|
fi
|
|
exit 1
|
|
fi
|
|
echo "Reloading ${name} config files."
|
|
if ! eval $_precmd && [ -z "$rc_force" ]; then
|
|
return 1
|
|
fi
|
|
_doit="kill -${sig_reload:-HUP} $rc_pid"
|
|
if [ -n "$_user" ]; then
|
|
_doit="su -m $_user -c 'sh -c \"$_doit\"'"
|
|
fi
|
|
if ! eval $_doit && [ -z "$rc_force" ]; then
|
|
return 1
|
|
fi
|
|
eval $_postcmd
|
|
;;
|
|
|
|
restart)
|
|
if ! eval $_precmd && [ -z "$rc_force" ]; then
|
|
return 1
|
|
fi
|
|
# prevent restart being called more
|
|
# than once by any given script
|
|
#
|
|
if ${_rc_restart_done:-false}; then
|
|
return 0
|
|
fi
|
|
_rc_restart_done=true
|
|
|
|
( $0 ${_rc_prefix}stop )
|
|
$0 ${_rc_prefix}start
|
|
|
|
eval $_postcmd
|
|
;;
|
|
|
|
poll)
|
|
if [ -n "$rc_pid" ]; then
|
|
wait_for_pids $rc_pid
|
|
fi
|
|
;;
|
|
|
|
rcvar)
|
|
echo "# $name"
|
|
if [ -n "$rcvar" ]; then
|
|
if checkyesno ${rcvar}; then
|
|
echo "\$${rcvar}=YES"
|
|
else
|
|
echo "\$${rcvar}=NO"
|
|
fi
|
|
fi
|
|
;;
|
|
|
|
*)
|
|
rc_usage "$_keywords"
|
|
;;
|
|
|
|
esac
|
|
return 0
|
|
done
|
|
|
|
echo 1>&2 "$0: unknown directive '$rc_arg'."
|
|
rc_usage "$_keywords"
|
|
exit 1
|
|
}
|
|
|
|
#
|
|
# run_rc_script file arg
|
|
# Start the script `file' with `arg', and correctly handle the
|
|
# return value from the script. If `file' ends with `.sh', it's
|
|
# sourced into the current environment. If `file' appears to be
|
|
# a backup or scratch file, ignore it. Otherwise if it's
|
|
# executable run as a child process.
|
|
#
|
|
run_rc_script()
|
|
{
|
|
_file=$1
|
|
_arg=$2
|
|
if [ -z "$_file" -o -z "$_arg" ]; then
|
|
err 3 'USAGE: run_rc_script file arg'
|
|
fi
|
|
|
|
unset name command command_args command_interpreter \
|
|
extra_commands pidfile procname \
|
|
rcvar required_dirs required_files required_vars
|
|
eval unset ${_arg}_cmd ${_arg}_precmd ${_arg}_postcmd
|
|
|
|
case "$_file" in
|
|
*.sh) # run in current shell
|
|
set $_arg ; . $_file
|
|
;;
|
|
*[~#]|*.OLD|*.orig|*,v) # scratch file; skip
|
|
warn "Ignoring scratch file $_file"
|
|
;;
|
|
*) # run in subshell
|
|
if [ -x $_file ]; then
|
|
if [ -n "$rc_fast_and_loose" ]; then
|
|
set $_arg ; . $_file
|
|
else
|
|
( set $_arg ; . $_file )
|
|
fi
|
|
fi
|
|
;;
|
|
esac
|
|
}
|
|
|
|
#
|
|
# load_rc_config command
|
|
# Source in the configuration file for a given command.
|
|
#
|
|
load_rc_config()
|
|
{
|
|
_command=$1
|
|
if [ -z "$_command" ]; then
|
|
err 3 'USAGE: load_rc_config command'
|
|
fi
|
|
|
|
if ${_rc_conf_loaded:-false}; then
|
|
:
|
|
else
|
|
. /etc/rc.conf
|
|
_rc_conf_loaded=true
|
|
fi
|
|
if [ -f /etc/rc.conf.d/"$_command" ]; then
|
|
. /etc/rc.conf.d/"$_command"
|
|
fi
|
|
}
|
|
|
|
#
|
|
# load_rc_config_var cmd var
|
|
# Read the rc.conf(5) var for cmd and set in the
|
|
# current shell, using load_rc_config in a subshell to prevent
|
|
# unwanted side effects from other variable assignments.
|
|
#
|
|
load_rc_config_var()
|
|
{
|
|
if [ $# -ne 2 ]; then
|
|
err 3 'USAGE: load_rc_config_var cmd var'
|
|
fi
|
|
eval $(eval '(
|
|
load_rc_config '$1' >/dev/null;
|
|
if [ -n "${'$2'}" -o "${'$2'-UNSET}" != "UNSET" ]; then
|
|
echo '$2'=\'\''${'$2'}\'\'';
|
|
fi
|
|
)' )
|
|
}
|
|
|
|
#
|
|
# rc_usage commands
|
|
# Print a usage string for $0, with `commands' being a list of
|
|
# valid commands.
|
|
#
|
|
rc_usage()
|
|
{
|
|
echo -n 1>&2 "Usage: $0 [fast|force|one]("
|
|
|
|
_sep=
|
|
for _elem; do
|
|
echo -n 1>&2 "$_sep$_elem"
|
|
_sep="|"
|
|
done
|
|
echo 1>&2 ")"
|
|
exit 1
|
|
}
|
|
|
|
#
|
|
# err exitval message
|
|
# Display message to stderr and log to the syslog, and exit with exitval.
|
|
#
|
|
err()
|
|
{
|
|
exitval=$1
|
|
shift
|
|
|
|
if [ -x /usr/bin/logger ]; then
|
|
logger "$0: ERROR: $*"
|
|
fi
|
|
echo 1>&2 "$0: ERROR: $*"
|
|
exit $exitval
|
|
}
|
|
|
|
#
|
|
# warn message
|
|
# Display message to stderr and log to the syslog.
|
|
#
|
|
warn()
|
|
{
|
|
if [ -x /usr/bin/logger ]; then
|
|
logger "$0: WARNING: $*"
|
|
fi
|
|
echo 1>&2 "$0: WARNING: $*"
|
|
}
|
|
|
|
#
|
|
# backup_file action file cur backup
|
|
# Make a backup copy of `file' into `cur', and save the previous
|
|
# version of `cur' as `backup' or use rcs for archiving.
|
|
#
|
|
# This routine checks the value of the backup_uses_rcs variable,
|
|
# which can be either YES or NO.
|
|
#
|
|
# The `action' keyword can be one of the following:
|
|
#
|
|
# add `file' is now being backed up (and is possibly
|
|
# being reentered into the backups system). `cur'
|
|
# is created and RCS files, if necessary, are
|
|
# created as well.
|
|
#
|
|
# update `file' has changed and needs to be backed up.
|
|
# If `cur' exists, it is copied to to `back' or
|
|
# checked into RCS (if the repository file is old),
|
|
# and then `file' is copied to `cur'. Another RCS
|
|
# check in done here if RCS is being used.
|
|
#
|
|
# remove `file' is no longer being tracked by the backups
|
|
# system. If RCS is not being used, `cur' is moved
|
|
# to `back', otherwise an empty file is checked in,
|
|
# and then `cur' is removed.
|
|
#
|
|
#
|
|
backup_file()
|
|
{
|
|
_action=$1
|
|
_file=$2
|
|
_cur=$3
|
|
_back=$4
|
|
|
|
if checkyesno backup_uses_rcs; then
|
|
_msg0="backup archive"
|
|
_msg1="update"
|
|
|
|
# ensure that history file is not locked
|
|
if [ -f $_cur,v ]; then
|
|
rcs -q -u -U -M $_cur
|
|
fi
|
|
|
|
# ensure after switching to rcs that the
|
|
# current backup is not lost
|
|
if [ -f $_cur ]; then
|
|
# no archive, or current newer than archive
|
|
if [ ! -f $_cur,v -o $_cur -nt $_cur,v ]; then
|
|
ci -q -f -u -t-"$_msg0" -m"$_msg1" $_cur
|
|
rcs -q -kb -U $_cur
|
|
co -q -f -u $_cur
|
|
fi
|
|
fi
|
|
|
|
case $_action in
|
|
add|update)
|
|
cp -p $_file $_cur
|
|
ci -q -f -u -t-"$_msg0" -m"$_msg1" $_cur
|
|
rcs -q -kb -U $_cur
|
|
co -q -f -u $_cur
|
|
chown root:wheel $_cur $_cur,v
|
|
;;
|
|
remove)
|
|
cp /dev/null $_cur
|
|
ci -q -f -u -t-"$_msg0" -m"$_msg1" $_cur
|
|
rcs -q -kb -U $_cur
|
|
chown root:wheel $_cur $_cur,v
|
|
rm $_cur
|
|
;;
|
|
esac
|
|
else
|
|
case $_action in
|
|
add|update)
|
|
if [ -f $_cur ]; then
|
|
cp -p $_cur $_back
|
|
fi
|
|
cp -p $_file $_cur
|
|
chown root:wheel $_cur
|
|
;;
|
|
remove)
|
|
mv -f $_cur $_back
|
|
;;
|
|
esac
|
|
fi
|
|
}
|
|
|
|
_rc_subr_loaded=:
|