PageRenderTime 80ms CodeModel.GetById 60ms app.highlight 15ms RepoModel.GetById 1ms app.codeStats 1ms

/init.d/rc

http://github.com/brinkman83/bashrc
Shell | 346 lines | 212 code | 38 blank | 96 comment | 51 complexity | ce241775a4509ea32df47354be8ec0be MD5 | raw file
  1#! /bin/sh
  2#
  3# rc
  4#
  5# Starts/stops services on runlevel changes.
  6#
  7# Optimization: A start script is not run when the service was already
  8# configured to run in the previous runlevel.  A stop script is not run
  9# when the the service was already configured not to run in the previous
 10# runlevel.
 11#
 12# Authors:
 13# 	Miquel van Smoorenburg <miquels@cistron.nl>
 14# 	Bruce Perens <Bruce@Pixar.com>
 15
 16PATH=/sbin:/usr/sbin:/bin:/usr/bin
 17export PATH
 18
 19# Un-comment the following for interactive debugging. Do not un-comment
 20# this for debugging a real boot process as no scripts will be executed.
 21# debug=echo
 22
 23# Specify method used to enable concurrent init.d scripts.
 24# Valid options are 'none', 'startpar' and 'makefile'. To enable
 25# the concurrent boot option, the init.d script order must allow for
 26# concurrency.  This is not the case with the default boot sequence in
 27# Debian as of 2008-01-20.  Before enabling concurrency, one need to
 28# check the sequence values of all boot scripts, and make sure only
 29# scripts that can be started in parallel have the same sequence
 30# number, and that a scripts dependencies have a earlier sequence
 31# number. See the insserv package for a away to reorder the boot
 32# automatically to allow this.
 33CONCURRENCY=none
 34
 35# Make sure the name survive changing the argument list
 36scriptname="$0"
 37
 38umask 022
 39
 40on_exit() {
 41	echo "error: '$scriptname' exited outside the expected code flow."
 42}
 43trap on_exit EXIT # Enable emergency handler
 44
 45# Ignore CTRL-C only in this shell, so we can interrupt subprocesses.
 46trap ":" INT QUIT TSTP
 47
 48# Set onlcr to avoid staircase effect.
 49stty onlcr 0>&1
 50
 51# Functions for splash progress bars
 52if [ -e /lib/init/splash-functions-base ] ; then
 53	. /lib/init/splash-functions-base
 54else
 55	# Quiet down script if old initscripts version without /lib/init/splash-functions-base is used.
 56	splash_progress() { return 1; }
 57	splash_stop() { return 1; }
 58fi
 59
 60# Now find out what the current and what the previous runlevel are.
 61
 62runlevel=$RUNLEVEL
 63# Get first argument. Set new runlevel to this argument.
 64[ "$1" != "" ] && runlevel=$1
 65if [ "$runlevel" = "" ]
 66then
 67	echo "Usage: $scriptname <runlevel>" >&2
 68	exit 1
 69fi
 70previous=$PREVLEVEL
 71[ "$previous" = "" ] && previous=N
 72
 73export runlevel previous
 74
 75if [ -f /etc/default/rcS ] ; then
 76	. /etc/default/rcS
 77fi
 78export VERBOSE
 79
 80if [ -f /lib/lsb/init-functions ] ; then
 81	. /lib/lsb/init-functions
 82else
 83	log_action_msg() { echo $@; }
 84	log_failure_msg() { echo $@; }
 85	log_warning_msg() { echo $@; }
 86fi
 87
 88#
 89# Stub to do progress bar ticks (for splash programs) on startup
 90#
 91startup_progress() {
 92	# Avoid divide by zero if anyone moved xdm/kdm/gdm first in a runlevel.
 93	if [ 0 -eq "$num_steps" ] ; then return; fi
 94
 95	step=$(($step + $step_change))
 96	progress=$(($step * $progress_size / $num_steps + $first_step))
 97	$debug splash_progress "$progress" || true
 98}
 99
100#
101# Check if we are able to use make like booting.  It require the
102# insserv package to be enabled. Boot concurrency also requires
103# startpar to be installed.
104#
105if [ "none" != "$CONCURRENCY" ] ; then
106	test -s /etc/init.d/.depend.boot  || CONCURRENCY="none"
107	test -s /etc/init.d/.depend.start || CONCURRENCY="none"
108	test -s /etc/init.d/.depend.stop  || CONCURRENCY="none"
109	startpar -v      > /dev/null 2>&1 || CONCURRENCY="none"
110fi
111
112#
113# Start script or program.
114#
115case "$CONCURRENCY" in
116	startpar|shell) # shell is obsolete
117		log_action_msg "Using startpar-style concurrent boot in runlevel $runlevel"
118		startup() {
119			action=$1
120			shift
121			scripts="$@"
122
123			# Update progress bar counter and jump to the new position
124			for script in $scripts ; do
125				step=$(($step + $step_change))
126			done
127
128			[ -n "$scripts" ] && $debug startpar -a $action $scripts
129
130			# Jump back one step to compencate for stepping one
131			# time too many in the for loop.
132			step=$(($step - $step_change))
133			startup_progress
134		}
135		;;
136	makefile)
137		log_action_msg "Using makefile-style concurrent boot in runlevel $runlevel"
138		# The splash API is not handled with this CONCURRENCY mode
139		startup() {
140			eval "$(startpar -p 4 -t 20 -T 3 -M $1 -P $previous -R $runlevel)"
141
142			if [ -n "$failed_service" ]
143			then
144				log_failure_msg "startpar: service(s) returned failure: $failed_service"
145			fi
146
147			if [ -n "$skipped_service" ]
148			then
149				log_warning_msg "startpar: service(s) skipped: $skipped_service"
150			fi
151
152			unset failed_service skipped_service
153		}
154		;;
155	none|*)
156		startup() {
157			action=$1
158			shift
159			scripts="$@"
160			for script in $scripts ; do
161				$debug "$script" $action
162				startup_progress
163			done
164		}
165		;;
166esac
167
168# Check if the splash screen should be stopped before the given
169# script.
170is_splash_stop_scripts() {
171	scriptname=$1
172	case "$scriptname" in
173		# killprocs is used in runlevel 1
174		gdm|xdm|kdm|ltsp-client|ltsp-client-core|reboot|halt|killprocs)
175			return 0
176			;;
177	esac
178	return 1
179}
180
181# Is there an rc directory for this new runlevel?
182if [ -d /etc/rc$runlevel.d ]
183then
184	# Find out where in the progress bar the initramfs got to.
185	PROGRESS_STATE=0
186	if [ -f /dev/.initramfs/progress_state ]; then
187		. /dev/.initramfs/progress_state
188	fi
189
190	# Split the remaining portion of the progress bar into thirds
191	progress_size=$(((100 - $PROGRESS_STATE) / 3))
192
193	case "$runlevel" in
194		0|6)
195			ACTION=stop
196			# Count down from 0 to -100 and use the entire bar
197			first_step=0
198			progress_size=100
199			step_change=-1
200			;;
201		S)
202			ACTION=start
203			# Begin where the initramfs left off and use 2/3
204			# of the remaining space
205			first_step=$PROGRESS_STATE
206			progress_size=$(($progress_size * 2))
207			step_change=1
208			;;
209		*)
210			ACTION=start
211			# Begin where rcS left off and use the final 1/3 of
212			# the space (by leaving progress_size unchanged)
213			first_step=$(($progress_size * 2 + $PROGRESS_STATE))
214			step_change=1
215			;;
216	esac
217
218	# Count the number of scripts we need to run
219	# (for progress bars)
220	num_steps=0
221	for s in /etc/rc$runlevel.d/[SK]*; do
222		if is_splash_stop_scripts "${s##/etc/rc$runlevel.d/S??}" ; then
223			break
224		fi
225		num_steps=$(($num_steps + 1))
226	done
227	step=0
228
229	if [ makefile = "$CONCURRENCY" ]
230	then
231		[ "$previous" != N ] && startup stop
232	# First, run the KILL scripts.
233	elif [ "$previous" != N ]
234	then
235		# Run all scripts with the same level in parallel
236		CURLEVEL=""
237		for s in /etc/rc$runlevel.d/K*
238		do
239			# Extract order value from symlink
240			level=${s#/etc/rc$runlevel.d/K}
241			level=${level%%[a-zA-Z]*}
242			if [ "$level" = "$CURLEVEL" ]
243			then
244				continue
245			fi
246			CURLEVEL=$level
247			SCRIPTS=""
248			for i in /etc/rc$runlevel.d/K$level*
249			do
250				# Check if the script is there.
251				[ ! -f $i ] && continue
252
253				#
254				# Find stop script in previous runlevel but
255				# no start script there.
256				#
257				suffix=${i#/etc/rc$runlevel.d/K[0-9][0-9]}
258				previous_stop=/etc/rc$previous.d/K[0-9][0-9]$suffix
259				previous_start=/etc/rc$previous.d/S[0-9][0-9]$suffix
260				#
261				# If there is a stop script in the previous level
262				# and _no_ start script there, we don't
263				# have to re-stop the service.
264				#
265				[ -f $previous_stop ] && [ ! -f $previous_start ] && continue
266
267				# Stop the service.
268				SCRIPTS="$SCRIPTS $i"
269				if is_splash_stop_scripts "$suffix" ; then
270					$debug splash_stop || true
271				fi
272			done
273			startup stop $SCRIPTS
274		done
275	fi
276
277	if [ makefile = "$CONCURRENCY" ]
278	then
279		if [ S = "$runlevel" ]
280		then
281			startup boot
282		else
283			startup $ACTION
284		fi
285	else
286		# Now run the START scripts for this runlevel.
287		# Run all scripts with the same level in parallel
288		CURLEVEL=""
289		for s in /etc/rc$runlevel.d/S*
290		do
291			# Extract order value from symlink
292			level=${s#/etc/rc$runlevel.d/S}
293			level=${level%%[a-zA-Z]*}
294			if [ "$level" = "$CURLEVEL" ]
295			then
296				continue
297			fi
298			CURLEVEL=$level
299			SCRIPTS=""
300			for i in /etc/rc$runlevel.d/S$level*
301			do
302				[ ! -f $i ] && continue
303
304				suffix=${i#/etc/rc$runlevel.d/S[0-9][0-9]}
305				if [ "$previous" != N ]
306				then
307					#
308					# Find start script in previous runlevel and
309					# stop script in this runlevel.
310					#
311					stop=/etc/rc$runlevel.d/K[0-9][0-9]$suffix
312					previous_start=/etc/rc$previous.d/S[0-9][0-9]$suffix
313					#
314					# If there is a start script in the previous level
315					# and _no_ stop script in this level, we don't
316					# have to re-start the service.
317					#
318					if [ start = "$ACTION" ] ; then
319						[ -f $previous_start ] && [ ! -f $stop ] && continue
320					else
321						# Workaround for the special
322						# handling of runlevels 0 and 6.
323						previous_stop=/etc/rc$previous.d/K[0-9][0-9]$suffix
324						#
325						# If there is a stop script in the previous level
326						# and _no_ start script there, we don't
327						# have to re-stop the service.
328						#
329						[ -f $previous_stop ] && [ ! -f $previous_start ] && continue
330					fi
331
332				fi
333				SCRIPTS="$SCRIPTS $i"
334				if is_splash_stop_scripts "$suffix" ; then
335					$debug splash_stop || true
336				fi
337			done
338			startup $ACTION $SCRIPTS
339		done
340	fi
341fi
342
343trap - EXIT # Disable emergency handler
344
345exit 0
346