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