#! /bin/sh
#
# rc
#
# Starts/stops services on runlevel changes.
#
# Optimization: A start script is not run when the service was already
# configured to run in the previous runlevel.  A stop script is not run
# when the the service was already configured not to run in the previous
# runlevel.
#
# Authors:
# 	Miquel van Smoorenburg <miquels@cistron.nl>
# 	Bruce Perens <Bruce@Pixar.com>

setvar PATH = "/sbin:/usr/sbin:/bin:/usr/bin"
export PATH

# Un-comment the following for interactive debugging. Do not un-comment
# this for debugging a real boot process as no scripts will be executed.
# debug=echo

# Make sure the name survive changing the argument list
setvar scriptname = "$0"

umask 022

proc on_exit {
	echo "error: '$scriptname' exited outside the expected code flow."
}
trap on_exit EXIT # Enable emergency handler

# 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

# Now find out what the current and what the previous runlevel are.

setvar runlevel = "$RUNLEVEL"
# Get first argument. Set new runlevel to this argument.
test $1 != "" && setvar runlevel = "$1"
if test $runlevel = ""
{
	echo "Usage: $scriptname <runlevel>" >&2
	exit 1
}
setvar previous = "$PREVLEVEL"
test $previous = "" && setvar previous = 'N'

export runlevel previous

if test -f /etc/default/rcS  {
	source /etc/default/rcS
}
export VERBOSE

if test -f /lib/lsb/init-functions  {
	source /lib/lsb/init-functions
} else {
	proc log_action_msg { echo $[join(ARGV)]; }
	proc log_failure_msg { echo $[join(ARGV)]; }
	proc log_warning_msg { echo $[join(ARGV)]; }
}

#
# Check if we are able to use make like booting.  It require the
# insserv package to be enabled. Boot concurrency also requires
# startpar to be installed.
#
#CONCURRENCY=makefile
# disable startpar, incompatible with "task" upstart jobs
setvar CONCURRENCY = 'none'
test -s /etc/init.d/.depend.boot  || setvar CONCURRENCY = ""none""
test -s /etc/init.d/.depend.start || setvar CONCURRENCY = ""none""
test -s /etc/init.d/.depend.stop  || setvar CONCURRENCY = ""none""
if test -e /etc/init.d/.legacy-bootordering  {
	setvar CONCURRENCY = ""none""
}
if ! test -e /proc/stat {
	# startpar requires /proc/stat
	if test $(uname) = "GNU/kFreeBSD"  {
		mount -t linprocfs linprocfs /proc
	} elif test $(uname) = "GNU"  {
		mount -t proc none /proc
	}
}
if test -x /lib/startpar/startpar  {
    setvar STARTPAR = "/lib/startpar/startpar"
} else {
    setvar STARTPAR = 'startpar'
}
$STARTPAR -v > /dev/null 2>&1 || setvar CONCURRENCY = ""none""

#
# Start script or program.
#
case (CONCURRENCY) {
	makefile|startpar|shell { # startpar and shell are obsolete
		setvar CONCURRENCY = 'makefile'
		log_action_msg "Using makefile-style concurrent boot in runlevel $runlevel"
		proc startup {
			eval $($STARTPAR -p 4 -t 20 -T 3 -M $1 -P $previous -R $runlevel)

			if test -n $failed_service
			{
				log_failure_msg "startpar: service(s) returned failure: $failed_service"
			}

			if test -n $skipped_service_not_installed
			{
				log_warning_msg "startpar: service(s) skipped, program is not installed: $skipped_service_not_installed"
			}

			if test -n $skipped_service_not_configured
			{
				log_warning_msg "startpar: service(s) skipped, program is not configured: $skipped_service_not_configured"
			}

			unset failed_service skipped_service_not_installed skipped_service_not_configured
		}
		}
	none|* {
		proc startup {
			setvar action = "$1"
			shift
			setvar scripts = "@ARGV"
			for script in $scripts  {
				$debug $script $action
			}
		}
		}
}

# Is there an rc directory for this new runlevel?
if test -d /etc/rc$runlevel.d
{
	case (runlevel) {
		0|6 {
			setvar ACTION = 'stop'
			}
		S {
			setvar ACTION = 'start'
			}
		* {
			setvar ACTION = 'start'
			}
	}

	# First, run the KILL scripts.
	if test makefile = $CONCURRENCY
	{
		if test $ACTION = "start" && test $previous != N
		{
			startup stop
		}
	} elif test $previous != N
	{
		# Run all scripts with the same level in parallel
		setvar CURLEVEL = """"
		for s in /etc/rc$runlevel.d/K*
		{
			# Extract order value from symlink
			setvar level = ${s#/etc/rc$runlevel.d/K}
			setvar level = ${level%%[a-zA-Z]*}
			if test $level = $CURLEVEL
			{
				continue
			}
			setvar CURLEVEL = "$level"
			setvar SCRIPTS = """"
			for i in /etc/rc$runlevel.d/K$level*
			{
				# Check if the script is there.
				test ! -f $i && continue

				#
				# Find stop script in previous runlevel but
				# no start script there.
				#
				setvar suffix = ${i#/etc/rc$runlevel.d/K[0-9][0-9]}
				setvar previous_stop = "/etc/rc$previous.d/K[0-9][0-9]$suffix"
				setvar previous_start = "/etc/rc$previous.d/S[0-9][0-9]$suffix"
				#
				# If there is a stop script in the previous level
				# and _no_ start script there, we don't
				# have to re-stop the service.
				#
				test -f $previous_stop && test ! -f $previous_start && continue

				# Stop the service.
				setvar SCRIPTS = ""$SCRIPTS $i""
			}
			startup stop $SCRIPTS
		}
	}

	if test makefile = $CONCURRENCY
	{
		if test S = $runlevel
		{
			startup boot
		} else {
			startup $ACTION
		}
	} else {
		# Now run the START scripts for this runlevel.
		# Run all scripts with the same level in parallel
		setvar CURLEVEL = """"
		for s in /etc/rc$runlevel.d/S*
		{
			# Extract order value from symlink
			setvar level = ${s#/etc/rc$runlevel.d/S}
			setvar level = ${level%%[a-zA-Z]*}
			if test $level = $CURLEVEL
			{
				continue
			}
			setvar CURLEVEL = "$level"
			setvar SCRIPTS = """"
			for i in /etc/rc$runlevel.d/S$level*
			{
				test ! -f $i && continue

				setvar suffix = ${i#/etc/rc$runlevel.d/S[0-9][0-9]}
				if test $previous != N
				{
					#
					# Find start script in previous runlevel and
					# stop script in this runlevel.
					#
					setvar stop = "/etc/rc$runlevel.d/K[0-9][0-9]$suffix"
					setvar previous_start = "/etc/rc$previous.d/S[0-9][0-9]$suffix"
					#
					# If there is a start script in the previous level
					# and _no_ stop script in this level, we don't
					# have to re-start the service.
					#
					if test start = $ACTION  {
						test -f $previous_start && test ! -f $stop && continue
					} else {
						# Workaround for the special
						# handling of runlevels 0 and 6.
						setvar previous_stop = "/etc/rc$previous.d/K[0-9][0-9]$suffix"
						#
						# If there is a stop script in the previous level
						# and _no_ start script there, we don't
						# have to re-stop the service.
						#
						test -f $previous_stop && test ! -f $previous_start && continue
					}

				}
				setvar SCRIPTS = ""$SCRIPTS $i""
			}
			startup $ACTION $SCRIPTS
		}
	}
}

trap - EXIT # Disable emergency handler

exit 0