Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
branch: master
Fetching contributors…

Cannot retrieve contributors at this time

executable file 328 lines (287 sloc) 7.956 kB
#! /bin/sh
# This is the file "rc" which starts and stops services for the different
# runlevels of the SysV init.
#
# Author: Winfried Trümper <winni@xpilot.org>
# Misc fixes by Tom Lees <tom@lpsg.demon.co.uk>.
# Misc improvements and code rewrite by Martin Schulze <joey@debian.org>
# Misc improvements by Roland Rosenfeld <roland@spinnaker.de>
# Partial rewrite by Alexander Wirt <formorer@debian.org>
#
# Copyright (c) 1998 Martin Schulze <joey@debian.org>
# 1998 Winfried Trümper <winni@xpilot.org>
# 1998 Miquel van Smoorenburg <miquels@cistron.nl>
# 1999-2000 Roland Rosenfeld <roland@spinnaker.de>
# 2010 Alexander Wirt <formorer@formorer.de>
#
# Unlike traditional implementations it avoids the messy scheme with
# expressing the setup through links but reads a central config file
# instead. From a technical point of view both methods are almost
# equivalent.
#
# To be compatible with the common configuration scheme in the Linux-world,
# every script has two states: "on" or "off". The effect of this is that
# once it is switched on, it is never started again when the runlevel changes
# (it is only executed to switch it off if necessary).
#
#
# This scripts accept to different parameters, -v and -d. Please don't mix them
# -v means some verbose output during operations
# -d means the same output, but also rc is doing a dry-run and does not try to
# start or stop anything.
#
# The following section is taken from the original rc with slight
# modifications.
# Ignore CTRL-C only in this shell, so we can interrupt subprocesses.
trap ":" INT QUIT TSTP
# Set onlcr to avoid staircase effect.
stty onlcr 0>&1
debug=0
if [ "$1" = "-d" ]
then
debug=1
shift
fi
verbose=0
if [ "$1" = "-v" ]
then
verbose=1
debug=1
shift
fi
# Is this done because RUNLEVEL and PREVLEVEL could be read-only?
#
# Now find out what the current and what the previous runlevel are.
runlevel=$RUNLEVEL
# Get first argument. Set new runlevel to this argument.
[ "$1" != "" ] && runlevel="$1"
# Is this necessary?
prevlevel=${PREVLEVEL:="N"}
# Is this necessary?
export runlevel previous
CFGFILE="/etc/runlevel.conf"
BAKCFG="/etc/runlevel.fallback"
LOCKFILE="/var/lock/runlevel.lock"
true=0
false=1
valid_min_seq=0
valid_max_seq=99
[ $debug -eq 1 ] && echo "rc: $prevlevel -> $runlevel"
# wait for any lock to vanish (but only when not booting)
i=0
while [ -f "$LOCKFILE" ] && [ "$previous" != "N" ]
do
read pid < "$LOCKFILE"
if ! kill -s 0 $pid > /dev/null 2>&1
then
echo "$0: found stale lockfile '$LOCKFILE'. Ignoring it." >&2
rm -f "$LOCKFILE" # external command (does not work on R/O fs)
break
fi
if [ "$i" -gt "60" ]
then
echo "Process no. '$pid' is locking the configuration database." >&2
if [ "$runlevel" = "1" -o "$runlevel" = "6" ]
then
# Try killing locking process, if booting, rebooting or halting.
echo "Sending TERM signal to $pid." >&2
kill -s 15 $pid
sleep 5
echo "Sending KILL signal to $pid." >&2
kill -s 9 $pid > /dev/null 2>&1
rm -f "$LOCKFILE" # external command (does not work on R/O FS)
sleep 5
break
else
# Normal runlevel change (not boot, reboot or halt)
echo "Terminating." >&2
exit 1
fi
fi
sleep 2
echo -n "."
i=$(($i + 1))
done
# This script is vital so we better keep an old copy of the configuration
# file as fallsave-configuration. This does not handle a broken config
# file, though.
if [ ! -f "$CFGFILE" ]
then
echo "Missing configuration file '$CFGFILE' using fallback config."
if [ ! -f "$BAKCFG" ]
then
echo "No configuration file at all. You're in serious trouble now."
echo "Please try to fix this problem with a root shell and reboot."
if [ -f /etc/default/rcS ]
then
# Read value of $CONSOLE:
. /etc/default/rcS
fi
/sbin/sulogin $CONSOLE
exit 1
fi
CFGFILE="$BAKCFG"
fi
is_valid_sequence() {
if [ $# -ne 1 ]
then
return $false
fi
case $1 in
[0-9]|[0-9][0-9]) ;;
*) return $false ;;
esac
if [ $1 -ge $valid_min_seq ] && [ $1 -le $valid_max_seq ]
then
return $true
fi
return $false
}
element() {
element="$1"
case "$element" in
reboot | R) element=0 ;;
halt | H) element=6 ;;
esac
[ "$2" = "in" ] && shift
list="$2"
[ "$list" = "-" ] && return 1
[ "$list" = "*" ] && return 0
ORGIFS="$IFS"
IFS=","
set -- $list
IFS="$ORGIFS"
case $element in
"$1" | "$2" | "$3" | "$4" | "$5" | "$6" | "$7" | "$8" | "$9")
return 0
esac
return 1
}
is_elem() {
elem=$1; shift
for x in $*
do
[ "$x" = "$elem" ] && return 0
done
return 1
}
# Adds new levels to list of levels of the given command. The entire
# list of commands and levels is tested.
#
pushlevel() {
newcmd=$1;shift
newlevels=$1; shift
add="$newcmd:$newlevels"
outline=""
for i in $*
do
cmd=${i%:*}
if [ "$cmd" = "$newcmd" ]
then
outline="$outline$i,$newlevels "
add=""
else
outline="$outline$i "
fi
done
echo "$outline$add"
}
# CMDLIST ensures scripts are killed in reversed order
CMDLIST="set centerline=here"
STARTCMD=""
STOPCMD=""
# Experimental: To tell the scripts they are not called manually.
# (should be unset in init.d-scripts)
CALL_FROM_RC="yes"
[ $debug -eq 1 ] && echo "Reading configuration file $CFGFILE."
case $runlevel in
0|6) start=stop; stop=stop;;
*) start=start; stop=stop;;
esac
# lock the configuration file
if [ "$prevlevel" != "N" ] && [ "$runlevel" != "1" ] && [ "$runlevel" != "6" ]
then
(echo "$$" > "$LOCKFILE") || true
fi
while read SORT_NO OFF_LEVELS ON_LEVELS CMD OPTIONS
do
case "$SORT_NO" in
\#*|""|\#) continue ;;
esac
[ ! -f "$CMD" ] && continue
is_valid_sequence "$SORT_NO" || continue
# currently OPTIONS is completely ignored ... we _could_ pass them to the
# init-script after "start" or "stop".
[ "$ON_LEVELS" != "-" ] && element "$runlevel" in "$ON_LEVELS" \
&& STARTLIST=`pushlevel $SORT_NO:$CMD $ON_LEVELS $STARTLIST`
if ! element "$prevlevel" in "$OFF_LEVELS"; then
element "$runlevel" in "$OFF_LEVELS" && STOPLIST="$STOPLIST$SORT_NO:$CMD "
fi
done < $CFGFILE
# remove lock of configuration file
if [ "$prevlevel" != "N" ] && [ "$runlevel" != "1" ] && [ "$runlevel" != "6" ]
then
rm -f "$LOCKFILE"
fi
# First, run the KILL scripts.
for x in 0 1 2 3 4 5 6 7 8 9
do
for y in 0 1 2 3 4 5 6 7 8 9
do
for script in $STOPLIST
do
STOP_NUM=${script%%:*}
if [ $STOP_NUM -eq $x$y ]
then
CMD=${script#*:}
if [ "$prevlevel" != "N" ]
then
case "$CMD" in
*.sh) CMDLIST="$CMDLIST; (set -- $stop; . $CMD)" ;;
*) [ -x "$CMD" ] && CMDLIST="$CMDLIST; $CMD $stop"
test $debug = 1 && echo "Stop $CMD"
;;
esac
fi
fi
done
done
done
# Then look at the start scripts
for x in 0 1 2 3 4 5 6 7 8 9
do
for y in 0 1 2 3 4 5 6 7 8 9
do
for script in $STARTLIST
do
START_NUM=${script%%:*}
if [ $START_NUM -eq $x$y ]
then
comb=${script#*:}
CMD=${comb%:*}
if [ "$prevlevel" != "N" ]
then
level=${comb#*:}
if element "$prevlevel" in "$level" && ! is_elem $CMD $STOPLIST
then
continue
fi
fi
case "$CMD" in
*.sh) CMDLIST="$CMDLIST; (set -- $start; . $CMD)" ;;
*) [ -x "$CMD" ] && CMDLIST="$CMDLIST; $CMD $start"
test $debug = 1 && echo "Start $CMD"
;;
esac
fi
done
done
done
# Execute the commands collected above
if test $debug -eq 1 && test $verbose -eq 0
then
echo "$CMDLIST"
else
test $verbose -eq 1 && echo "$CMDLIST"
(trap - INT QUIT TSTP; sh -c "$CMDLIST")
fi
Jump to Line
Something went wrong with that request. Please try again.