PageRenderTime 22ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/update-conf.d.complex.in

http://github.com/Atha/update-conf.d
Autoconf | 368 lines | 219 code | 42 blank | 107 comment | 35 complexity | 2e95cc569278c89fc07a853ff62ad579 MD5 | raw file
Possible License(s): GPL-2.0
  1. #!/bin/sh
  2. #
  3. # update-conf.d COMPLEX VERSION
  4. # Version 2013-09-15
  5. #
  6. # Script for flexible /etc/*.d configuration
  7. # Originally from Atha, with a lot of improvements from truc - thanks!
  8. # Generalized for /etc/*.d by Nicolas Bercher nbercher@yahoo.fr
  9. # Idea for the COMPLEX version and fixes by javeree
  10. # COMPLEX version by Atha
  11. #
  12. #
  13. # In short: read the man page!
  14. #
  15. #
  16. # The included makefile assists easy installation:
  17. # "make clean" will clean previously built versions of this script.
  18. # "make complex install" will build and install it.
  19. # "make build install" builds and installs both versions.
  20. #
  21. # For installing, this script is copied into /usr/local/sbin and is called
  22. # update-conf.d (a symlink) for both the SIMPLE and the COMPLEX version. This
  23. # symlink will point to update-conf.d.complex. If needed, you may also install
  24. # the simple version (update-conf.d.simple) and make sure the symlink points
  25. # to the complex version.
  26. # To install to any other location, e.g. /usr/sbin, edit the Makefile.
  27. #
  28. # You need to configure your <conf> entries in separate files in /etc/<conf>.d;
  29. # For your convenience, the -1 option is included to "run-once" without such an
  30. # entry, but ONLY in the COMPLEX version!
  31. #
  32. # From the .d'ed directory only filenames starting with two digits are included!
  33. # Other files are "inactive" which is the intended way of doing it.
  34. #
  35. # Examples: /etc/fstab.d/01base or /etc/hosts.d/61nfs-dm8000. If one is renamed,
  36. # say to /etc/hosts.d/.61nfs-dm8000 or /etc/hosts.d/nfs-dm8000, it is ignored by
  37. # the script i.e. inactive.
  38. #
  39. # Copyright 2013 javeree
  40. # Copyright 2011 Nicolas Bercher
  41. # Copyright 2010 truc (on improvements)
  42. # Copyright 2008-2013 Atha
  43. # Distributed under the terms of the GNU General Public License v2 or later
  44. #
  45. # The home of this script is https://github.com/Atha/update-conf.d
  46. # It first appeared at http://forums.gentoo.org/viewtopic.php?p=6364143
  47. #
  48. ########
  49. ## SETUP
  50. ########
  51. # scriptname:
  52. scriptname=$(basename "$0")
  53. # root of configuration files:
  54. root="@CONFIGDIR@"
  55. # script configuration path:
  56. scriptconf="${root}/update-conf.d.conf"
  57. # flag_verbose sets the verbosity level (command line option -v). Default is 0 (no verbose output).
  58. flag_verbose=0
  59. # flag_runonce (command line option -1)
  60. flag_runonce=0
  61. # flag_set (command line option -s)
  62. flag_set=0
  63. # flag_unset (command line option -u)
  64. flag_unset=0
  65. # flag_processall (command line option -a)
  66. flag_processall=0
  67. # flag_donothing (command line option -n)
  68. flag_donothing=0
  69. # flag_continueonerror (command line option -c)
  70. flag_continueonerror=0
  71. ##################
  72. ## BASIC FUNCTIONS
  73. ##################
  74. warning () {
  75. echo "$@" >&2
  76. }
  77. message () {
  78. [ ${flag_verbose} -gt 0 ] && echo "$@"
  79. }
  80. fail () {
  81. warning "STOP. Aborted due to failure."
  82. [ ${flag_continueonerror} -gt 0 ] && return 0
  83. exit ${1}
  84. }
  85. #####################
  86. ## SPECIFIC FUNCTIONS
  87. #####################
  88. ## check, if $scripconf is present (available): return 1 if not
  89. scriptconf_checksilent () {
  90. [ -f "${scriptconf}" ] && return 0
  91. return 1
  92. }
  93. ## check, if $scripconf is present (available): exit with warning if not
  94. scriptconf_check () {
  95. if ! scriptconf_checksilent ; then
  96. warning "${scriptname}: script configuration file '${scriptconf}' not found!"
  97. exit 1
  98. fi
  99. return 0
  100. }
  101. print_version () {
  102. warning "update-conf.d COMPLEX version 2013-09-15"
  103. warning
  104. return 0
  105. }
  106. print_usage () {
  107. warning "Usage: ${scriptname} [-12achlnsuv] [<conf>...]"
  108. warning
  109. warning "Options:"
  110. warning " -1 run-once (ignores list of valid <conf> entries)"
  111. warning " -2 (same as -1 -s)"
  112. warning " process and add <conf> to list of valid entries"
  113. warning " -a process all valid <conf> entries from the stored list (implies -c)"
  114. warning " all <conf>-arguments are ignored if present"
  115. warning " when -a is used, options -s and -u will have no effect"
  116. warning " -c continue on error"
  117. warning " (useful when more than one <conf> is specified)"
  118. warning " -h show this short help page"
  119. warning " -l show a list of valid <conf> entries"
  120. warning " -n test, do nothing (implies -v)"
  121. warning " -s set <conf> as valid entry (i.e. add to list)"
  122. warning " cannot be used together with -u"
  123. warning " -u unset <conf> as valid entry (i.e. remove from list)"
  124. warning " cannot be used together with -s"
  125. warning " -v be verbose (default: not verbose)"
  126. warning
  127. warning "Arguments:"
  128. warning " <conf> is a .d'ed config in ${root}"
  129. warning " (directory ${root}/<conf>.d must exist)"
  130. warning
  131. warning "The list of valid <conf> entries is stored in ${scriptconf}."
  132. exit 0
  133. }
  134. scriptconf_findsilent () {
  135. grep "^${1}$" "${scriptconf}" > /dev/null 2>&1 && return 0
  136. return 1
  137. }
  138. ## check, if $1 ($conf from update_confd) is a valid entry
  139. scriptconf_find () {
  140. if [ ${flag_runonce} -eq 1 ] ; then
  141. message "Run-once, not in list: ${1}"
  142. return 0
  143. fi
  144. return $(scriptconf_findsilent ${1})
  145. }
  146. ## option -l (list)
  147. scriptconf_list () {
  148. scriptconf_check
  149. cat "${scriptconf}"
  150. return 0
  151. }
  152. ## option -s (set): add $1 (argument to this function)
  153. scriptconf_add () {
  154. if scriptconf_checksilent && scriptconf_findsilent ${1} ; then
  155. return 1
  156. else
  157. echo ${1} >> "${scriptconf}"
  158. message "${scriptname}: Item added to list of valid entries: ${1}"
  159. fi
  160. return 0
  161. }
  162. ## option -u (unset): remove $1 (argument to this function)
  163. scriptconf_remove () {
  164. if scriptconf_checksilent && scriptconf_findsilent ${1} ; then
  165. mv "${scriptconf}" "${scriptconf}.bak" && grep -v "^${1}$" "${scriptconf}.bak" > "${scriptconf}" && message "${scriptname}: Item removed from list of valid entries: ${1}" && return 0
  166. fi
  167. return 1
  168. }
  169. ################
  170. ## MAIN FUNCTION
  171. ################
  172. update_confd () {
  173. if [ ! $# -eq 1 ] ; then
  174. warning "${scriptname}: internal script error in function update_confd. Please contact the author."
  175. exit 100
  176. # return 1
  177. fi
  178. message "Processing <conf> entry: ${1}"
  179. ################
  180. ## CONFIGURATION
  181. ################
  182. # name of the configuration file to process (argument to this function):
  183. conf="${1}"
  184. # configuration file path:
  185. confpath="${root}/${conf}"
  186. # path to the backup of the current/previous configuration file:
  187. bkpconfpath="${confpath}.d.bak"
  188. # <conf.d> directory path:
  189. dpath="${root}/${conf}.d"
  190. # path to the intermediate location of the new configuration file based on
  191. # <conf>.d/[0-9][0-9]* files:
  192. dconfpath="${dpath}/$(basename ${conf})"
  193. # check if <conf> is available in list (or run-once)
  194. if ! scriptconf_find ${1} ; then
  195. # don't display a warning AND don't exit if option -s (i.e. set) is also used
  196. # INVERSE: do exit if -s is not used
  197. if [ ! ${flag_set} -eq 1 ] ; then
  198. warning "${scriptname}: not allowed to process ${conf}. Add it to the list or use run-once."
  199. fail 2
  200. fi
  201. # in case of -s without -1 (checked by scriptconf_find): simply return... silently...
  202. return 1
  203. fi
  204. # check if <conf>.d directory exists
  205. if [ ! -d "${dpath}" ] ; then
  206. warning "${scriptname}: directory ${dpath} does not exist."
  207. fail 2
  208. return 1
  209. fi
  210. # if <conf>.d/<conf> is already there: prevent data loss
  211. if [ -e "${dconfpath}" ] ; then
  212. warning "${scriptname}: please remove ${dconfpath} before you run this script."
  213. warning "${scriptname}: NOTE: It may have been left by a previous run, but you should check anyway."
  214. fail 2
  215. return 1
  216. fi
  217. if [ $flag_donothing -gt 0 ] ; then
  218. message "Do nothing: ${1} would have been processed."
  219. return 0
  220. fi
  221. cat << 'EOT' > "${dconfpath}" && message "${dconfpath} created, header added"
  222. # Configuration file automatically generated by the update-conf.d
  223. # script.
  224. #
  225. # Please change the according lines in /etc/<conf.d>/* if you want
  226. # them to be permanent, otherwise they will not survive the next
  227. # invocation of update-conf.d!
  228. #
  229. EOT
  230. for dconf_file in "${dpath}"/[0-9][0-9]* ; do
  231. echo "" >> "${dconfpath}"
  232. echo "# ${dconf_file}:" >> "${dconfpath}"
  233. grep '^[^#].*' "${dconf_file}" >> "${dconfpath}"
  234. message "Added: ${dconf_file}"
  235. done
  236. mv -f "${confpath}" "${bkpconfpath}" && message "Existing ${confpath} renamed to ${bkpconfpath}"
  237. mv -f "${dconfpath}" "${confpath}" && message "New configuration file ${dconfpath} moved to ${confpath}"
  238. warning "${scriptname}: ${confpath} updated."
  239. return 0
  240. }
  241. ###############
  242. ## MAIN PROGRAM
  243. ###############
  244. # Parse command line options.
  245. while getopts 12achlnsuv OPT; do
  246. case "$OPT" in
  247. 1)
  248. flag_runonce=1
  249. ;;
  250. 2)
  251. flag_runonce=1
  252. flag_set=1
  253. ;;
  254. a)
  255. flag_continueonerror=1
  256. flag_processall=1
  257. ;;
  258. c)
  259. flag_continueonerror=1
  260. ;;
  261. h)
  262. print_version
  263. print_usage
  264. ;;
  265. l)
  266. echo "Configuration file: ${scriptconf}"
  267. echo "List of valid <conf> entries:"
  268. echo ""
  269. scriptconf_list
  270. exit 0
  271. ;;
  272. n)
  273. flag_donothing=1
  274. flag_verbose=1
  275. ;;
  276. s)
  277. flag_set=1
  278. ;;
  279. u)
  280. flag_unset=1
  281. ;;
  282. v)
  283. flag_verbose=1
  284. ;;
  285. \?)
  286. # getopts issues an error message (automatically, via a POSIX shell)
  287. warning
  288. print_usage
  289. exit 100
  290. ;;
  291. esac
  292. done
  293. # Remove the switches we parsed above.
  294. shift `expr $OPTIND - 1`
  295. ## if -a was used, process all valid <conf> entries here and exit, otherwise continue
  296. if [ ${flag_processall} -eq 1 ] ; then
  297. scriptconf_check
  298. [ ${flag_set} -eq 1 ] && message "${scriptname}: option -s cannot be used together with -a, ignored."
  299. [ ${flag_unset} -eq 1 ] && message "${scriptname}: option -u cannot be used together with -a, ignored."
  300. message "Processing all valid <conf> entries..."
  301. message
  302. for confentry in `cat "${scriptconf}"` ; do
  303. update_confd "$confentry"
  304. message
  305. done
  306. exit 0
  307. fi
  308. # We want at least one non-option argument (the <conf> to be processed)
  309. if [ $# -lt 1 ]; then
  310. print_version
  311. print_usage
  312. exit 1
  313. fi
  314. if [ ${flag_set} -eq 1 ] && [ ${flag_unset} -eq 1 ] ; then
  315. warning "${scriptname}: options -s and -u cannot be used at the same time!"
  316. exit 1
  317. fi
  318. # check for /etc/update-conf.d (or, if PREFIXED, something other than /etc); exit on error
  319. scriptconf_check
  320. for PARAM; do
  321. [ ${flag_unset} -eq 1 ] && scriptconf_remove ${PARAM}
  322. update_confd ${PARAM}
  323. message
  324. [ ${flag_set} -eq 1 ] && scriptconf_add ${PARAM}
  325. done
  326. exit 0