update-rc.d 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. #! /bin/sh
  2. ## Copyright (c) 2015 Minoca Corp.
  3. ##
  4. ## This file is licensed under the terms of the GNU General Public License
  5. ## version 3. Alternative licensing terms are available. Contact
  6. ## info@minocacorp.com for details. See the LICENSE file at the root of this
  7. ## project for complete licensing information..
  8. ##
  9. ## Script Name:
  10. ##
  11. ## update-rc.d
  12. ##
  13. ## Abstract:
  14. ##
  15. ## This script provides a poor man's version of the real update-rc.d. This
  16. ## script does not read or understand dependencies.
  17. ##
  18. ## Author:
  19. ##
  20. ## Evan Green 24-Mar-2015
  21. ##
  22. ## Environment:
  23. ##
  24. ## POSIX
  25. ##
  26. me=$0
  27. do_it=
  28. force=
  29. name=
  30. usage () {
  31. echo "Usage: $me [-n] [-f] name command"
  32. echo "Commands:"
  33. echo " defaults [NN | SS KK]"
  34. echo " remove"
  35. echo " start|stop NN runlevel... . start|stop NN runlevel... . ..."
  36. echo " enable|disable [S|2|3|4|5]"
  37. exit 1
  38. }
  39. validate_sequence () {
  40. case "$1" in
  41. [0123456789][0123456789]) return 0 ;;
  42. *) return 1 ;;
  43. esac
  44. }
  45. validate_runlevels () {
  46. local levels
  47. levels=`echo $1 | sed 's/\(.\)/\1 /g'`
  48. for level in $levels; do
  49. case $level in
  50. [0123456S])
  51. ;;
  52. *)
  53. echo "$me: Error: Invalid runlevel $level."
  54. exit 1
  55. ;;
  56. esac
  57. done
  58. }
  59. check_name () {
  60. local name
  61. name="$1"
  62. if [ ! -f /etc/init.d/$name ]; then
  63. echo "$me: Error: /etc/init.d/$name does not exist."
  64. exit 1
  65. fi
  66. }
  67. create_links () {
  68. local action name sequence runlevels levels link_dest
  69. action="$1"
  70. name="$2"
  71. sequence="$3"
  72. runlevels="$4"
  73. levels=`echo $runlevels | sed 's/\(.\)/\1 /g'`
  74. if ! validate_sequence "$sequence"; then
  75. exit 1
  76. fi
  77. if ! validate_runlevels "$runlevels"; then
  78. exit 1
  79. fi
  80. ##
  81. ## Create the links.
  82. ##
  83. for level in $levels; do
  84. mkdir -p /etc/rc$level.d/
  85. link_dest=/etc/rc$level.d/$action$sequence$name
  86. ##
  87. ## Only create the link if nothing already exists there.
  88. ##
  89. if [ -f "$link_dest" -o -L "$link_dest" ]; then
  90. echo "$me: Skipping pre-existing $link_dest."
  91. else
  92. $do_it ln -s "../init.d/$name" "$link_dest"
  93. fi
  94. done
  95. }
  96. rename_links() {
  97. local src_prefix dst_prefix name levels runlevels suffix link_dest seq
  98. src_prefix="$1"
  99. dst_prefix="$2"
  100. name="$3"
  101. runlevels="$4"
  102. if ! validate_runlevels "$runlevels"; then
  103. exit 1
  104. fi
  105. levels=`echo $runlevels | sed 's/\(.\)/\1 /g'`
  106. for level in $levels; do
  107. if [ ! -d /etc/rc$level.d/ ]; then
  108. continue
  109. fi
  110. for f in /etc/rc$level.d/$src_prefix[0123456789][0123456789]$name; do
  111. suffix=${f#/etc/rc$level.d/$src_prefix}
  112. seq=${suffix%$name}
  113. seq=$((100 - $seq))
  114. link_dest=/etc/rc$level.d/$dst_prefix$seq$name
  115. ##
  116. ## Only move the link if nothing already exists there.
  117. ##
  118. if [ -f "$link_dest" -o -L "$link_dest" ]; then
  119. echo "$me: Skipping pre-existing $link_dest."
  120. else
  121. $do_it mv "$f" "$link_dest"
  122. fi
  123. done
  124. done
  125. }
  126. ##
  127. ## Process arguments.
  128. ##
  129. while [ -n $1 ]; do
  130. case "$1" in
  131. -n)
  132. do_it=echo
  133. ;;
  134. -f)
  135. force=yes
  136. ;;
  137. *)
  138. break
  139. ;;
  140. esac
  141. shift
  142. done
  143. name=$1
  144. if [ -z $name ]; then
  145. usage
  146. fi
  147. shift
  148. ##
  149. ## Loop processing action arguments. Technically only start and stop are
  150. ## supposed to be able to keep going, but that's okay.
  151. ##
  152. while [ -n "$1" ] ; do
  153. action=$1
  154. shift
  155. case "$action" in
  156. ##
  157. ## Remove all symbolic links which point to /etc/init.d/<name>.
  158. ##
  159. remove)
  160. script=/etc/init.d/$name
  161. if [ "$force" != "yes" ]; then
  162. if [ -f $script ]; then
  163. echo "$me: Error: $script still exists!"
  164. exit 1
  165. fi
  166. fi
  167. ##
  168. ## Touch the file to make it exist so the symbolic link destination
  169. ## can be checked.
  170. ##
  171. touch $script
  172. for level in 0 1 2 3 4 5 6 S; do
  173. if [ ! -d /etc/rc$level.d/ ]; then
  174. continue
  175. fi
  176. for f in /etc/rc$level.d/*; do
  177. if [ $f -fe $script ]; then
  178. $do_it rm $f
  179. fi
  180. done
  181. done
  182. ##
  183. ## If the script is just an empty file (created by the touch), then
  184. ## remove it.
  185. ##
  186. if [ -s $script ]; then
  187. rm $script
  188. fi
  189. ;;
  190. ##
  191. ## Create start scripts at sequence 20, runlevels 2345, and kill scripts
  192. ## at sequence 80, runlevels 016.
  193. ##
  194. defaults)
  195. check_name "$name"
  196. start_seq=20
  197. kill_seq=80
  198. if [ -n "$1" ]; then
  199. if [ -n "$2" ]; then
  200. start_seq="$1"
  201. kill_seq="$2"
  202. shift
  203. else
  204. start_seq="$1"
  205. kill_seq="$1"
  206. fi
  207. shift
  208. fi
  209. start_runlevels="2345"
  210. kill_runlevels="016"
  211. create_links "S" "$name" "$start_seq" "$start_runlevels"
  212. create_links "K" "$name" "$kill_seq" "$kill_runlevels"
  213. ;;
  214. ##
  215. ## Create the specified start/stop scripts.
  216. ##
  217. start|stop)
  218. check_name "$name"
  219. if [ -z "$1" ]; then
  220. echo "$me: Error: sequence number missing after start/stop."
  221. usage
  222. exit 1
  223. fi
  224. sequence="$1"
  225. shift
  226. runlevels=""
  227. while [ "$1" != "." ]; do
  228. if [ -z "$1" ]; then
  229. echo "$me: Error: Expected runlevel or period for start/stop."
  230. usage
  231. exit 1
  232. fi
  233. runlevels="$runlevels$1"
  234. shift
  235. done
  236. ##
  237. ## Shift away the period.
  238. ##
  239. shift
  240. ##
  241. ## Create the desired scripts.
  242. ##
  243. action_code="K"
  244. if [ "$action" = "start" ]; then
  245. action_code="S"
  246. fi
  247. create_links "$action_code" "$name" "$sequence" "$runlevels"
  248. ;;
  249. enable|disable)
  250. runlevels="2345"
  251. if [ -n "$1" ]; then
  252. runlevels="$1"
  253. shift
  254. fi
  255. if [ "$action" = "enable" ]; then
  256. rename_links "K" "S" "$name" "$runlevels"
  257. else
  258. rename_links "S" "K" "$name" "$runlevels"
  259. fi
  260. ;;
  261. *)
  262. echo "$me: Error: Unexpected argument $action."
  263. exit 1
  264. ;;
  265. esac
  266. done
  267. exit 0