/update-conf.d.complex.in
Autoconf | 368 lines | 219 code | 42 blank | 107 comment | 35 complexity | 2e95cc569278c89fc07a853ff62ad579 MD5 | raw file
Possible License(s): GPL-2.0
- #!/bin/sh
- #
- # update-conf.d COMPLEX VERSION
- # Version 2013-09-15
- #
- # Script for flexible /etc/*.d configuration
- # Originally from Atha, with a lot of improvements from truc - thanks!
- # Generalized for /etc/*.d by Nicolas Bercher nbercher@yahoo.fr
- # Idea for the COMPLEX version and fixes by javeree
- # COMPLEX version by Atha
- #
- #
- # In short: read the man page!
- #
- #
- # The included makefile assists easy installation:
- # "make clean" will clean previously built versions of this script.
- # "make complex install" will build and install it.
- # "make build install" builds and installs both versions.
- #
- # For installing, this script is copied into /usr/local/sbin and is called
- # update-conf.d (a symlink) for both the SIMPLE and the COMPLEX version. This
- # symlink will point to update-conf.d.complex. If needed, you may also install
- # the simple version (update-conf.d.simple) and make sure the symlink points
- # to the complex version.
- # To install to any other location, e.g. /usr/sbin, edit the Makefile.
- #
- # You need to configure your <conf> entries in separate files in /etc/<conf>.d;
- # For your convenience, the -1 option is included to "run-once" without such an
- # entry, but ONLY in the COMPLEX version!
- #
- # From the .d'ed directory only filenames starting with two digits are included!
- # Other files are "inactive" which is the intended way of doing it.
- #
- # Examples: /etc/fstab.d/01base or /etc/hosts.d/61nfs-dm8000. If one is renamed,
- # say to /etc/hosts.d/.61nfs-dm8000 or /etc/hosts.d/nfs-dm8000, it is ignored by
- # the script i.e. inactive.
- #
- # Copyright 2013 javeree
- # Copyright 2011 Nicolas Bercher
- # Copyright 2010 truc (on improvements)
- # Copyright 2008-2013 Atha
- # Distributed under the terms of the GNU General Public License v2 or later
- #
- # The home of this script is https://github.com/Atha/update-conf.d
- # It first appeared at http://forums.gentoo.org/viewtopic.php?p=6364143
- #
- ########
- ## SETUP
- ########
- # scriptname:
- scriptname=$(basename "$0")
- # root of configuration files:
- root="@CONFIGDIR@"
- # script configuration path:
- scriptconf="${root}/update-conf.d.conf"
- # flag_verbose sets the verbosity level (command line option -v). Default is 0 (no verbose output).
- flag_verbose=0
- # flag_runonce (command line option -1)
- flag_runonce=0
- # flag_set (command line option -s)
- flag_set=0
- # flag_unset (command line option -u)
- flag_unset=0
- # flag_processall (command line option -a)
- flag_processall=0
- # flag_donothing (command line option -n)
- flag_donothing=0
- # flag_continueonerror (command line option -c)
- flag_continueonerror=0
- ##################
- ## BASIC FUNCTIONS
- ##################
- warning () {
- echo "$@" >&2
- }
- message () {
- [ ${flag_verbose} -gt 0 ] && echo "$@"
- }
- fail () {
- warning "STOP. Aborted due to failure."
- [ ${flag_continueonerror} -gt 0 ] && return 0
- exit ${1}
- }
- #####################
- ## SPECIFIC FUNCTIONS
- #####################
- ## check, if $scripconf is present (available): return 1 if not
- scriptconf_checksilent () {
- [ -f "${scriptconf}" ] && return 0
- return 1
- }
- ## check, if $scripconf is present (available): exit with warning if not
- scriptconf_check () {
- if ! scriptconf_checksilent ; then
- warning "${scriptname}: script configuration file '${scriptconf}' not found!"
- exit 1
- fi
- return 0
- }
- print_version () {
- warning "update-conf.d COMPLEX version 2013-09-15"
- warning
- return 0
- }
- print_usage () {
- warning "Usage: ${scriptname} [-12achlnsuv] [<conf>...]"
- warning
- warning "Options:"
- warning " -1 run-once (ignores list of valid <conf> entries)"
- warning " -2 (same as -1 -s)"
- warning " process and add <conf> to list of valid entries"
- warning " -a process all valid <conf> entries from the stored list (implies -c)"
- warning " all <conf>-arguments are ignored if present"
- warning " when -a is used, options -s and -u will have no effect"
- warning " -c continue on error"
- warning " (useful when more than one <conf> is specified)"
- warning " -h show this short help page"
- warning " -l show a list of valid <conf> entries"
- warning " -n test, do nothing (implies -v)"
- warning " -s set <conf> as valid entry (i.e. add to list)"
- warning " cannot be used together with -u"
- warning " -u unset <conf> as valid entry (i.e. remove from list)"
- warning " cannot be used together with -s"
- warning " -v be verbose (default: not verbose)"
- warning
- warning "Arguments:"
- warning " <conf> is a .d'ed config in ${root}"
- warning " (directory ${root}/<conf>.d must exist)"
- warning
- warning "The list of valid <conf> entries is stored in ${scriptconf}."
- exit 0
- }
- scriptconf_findsilent () {
- grep "^${1}$" "${scriptconf}" > /dev/null 2>&1 && return 0
- return 1
- }
- ## check, if $1 ($conf from update_confd) is a valid entry
- scriptconf_find () {
- if [ ${flag_runonce} -eq 1 ] ; then
- message "Run-once, not in list: ${1}"
- return 0
- fi
- return $(scriptconf_findsilent ${1})
- }
- ## option -l (list)
- scriptconf_list () {
- scriptconf_check
- cat "${scriptconf}"
- return 0
- }
- ## option -s (set): add $1 (argument to this function)
- scriptconf_add () {
- if scriptconf_checksilent && scriptconf_findsilent ${1} ; then
- return 1
- else
- echo ${1} >> "${scriptconf}"
- message "${scriptname}: Item added to list of valid entries: ${1}"
- fi
- return 0
- }
- ## option -u (unset): remove $1 (argument to this function)
- scriptconf_remove () {
- if scriptconf_checksilent && scriptconf_findsilent ${1} ; then
- mv "${scriptconf}" "${scriptconf}.bak" && grep -v "^${1}$" "${scriptconf}.bak" > "${scriptconf}" && message "${scriptname}: Item removed from list of valid entries: ${1}" && return 0
- fi
- return 1
- }
- ################
- ## MAIN FUNCTION
- ################
- update_confd () {
- if [ ! $# -eq 1 ] ; then
- warning "${scriptname}: internal script error in function update_confd. Please contact the author."
- exit 100
- # return 1
- fi
- message "Processing <conf> entry: ${1}"
- ################
- ## CONFIGURATION
- ################
- # name of the configuration file to process (argument to this function):
- conf="${1}"
- # configuration file path:
- confpath="${root}/${conf}"
- # path to the backup of the current/previous configuration file:
- bkpconfpath="${confpath}.d.bak"
- # <conf.d> directory path:
- dpath="${root}/${conf}.d"
- # path to the intermediate location of the new configuration file based on
- # <conf>.d/[0-9][0-9]* files:
- dconfpath="${dpath}/$(basename ${conf})"
- # check if <conf> is available in list (or run-once)
- if ! scriptconf_find ${1} ; then
- # don't display a warning AND don't exit if option -s (i.e. set) is also used
- # INVERSE: do exit if -s is not used
- if [ ! ${flag_set} -eq 1 ] ; then
- warning "${scriptname}: not allowed to process ${conf}. Add it to the list or use run-once."
- fail 2
- fi
- # in case of -s without -1 (checked by scriptconf_find): simply return... silently...
- return 1
- fi
- # check if <conf>.d directory exists
- if [ ! -d "${dpath}" ] ; then
- warning "${scriptname}: directory ${dpath} does not exist."
- fail 2
- return 1
- fi
- # if <conf>.d/<conf> is already there: prevent data loss
- if [ -e "${dconfpath}" ] ; then
- warning "${scriptname}: please remove ${dconfpath} before you run this script."
- warning "${scriptname}: NOTE: It may have been left by a previous run, but you should check anyway."
- fail 2
- return 1
- fi
- if [ $flag_donothing -gt 0 ] ; then
- message "Do nothing: ${1} would have been processed."
- return 0
- fi
- cat << 'EOT' > "${dconfpath}" && message "${dconfpath} created, header added"
- # Configuration file automatically generated by the update-conf.d
- # script.
- #
- # Please change the according lines in /etc/<conf.d>/* if you want
- # them to be permanent, otherwise they will not survive the next
- # invocation of update-conf.d!
- #
- EOT
- for dconf_file in "${dpath}"/[0-9][0-9]* ; do
- echo "" >> "${dconfpath}"
- echo "# ${dconf_file}:" >> "${dconfpath}"
- grep '^[^#].*' "${dconf_file}" >> "${dconfpath}"
- message "Added: ${dconf_file}"
- done
- mv -f "${confpath}" "${bkpconfpath}" && message "Existing ${confpath} renamed to ${bkpconfpath}"
- mv -f "${dconfpath}" "${confpath}" && message "New configuration file ${dconfpath} moved to ${confpath}"
- warning "${scriptname}: ${confpath} updated."
- return 0
- }
- ###############
- ## MAIN PROGRAM
- ###############
- # Parse command line options.
- while getopts 12achlnsuv OPT; do
- case "$OPT" in
- 1)
- flag_runonce=1
- ;;
- 2)
- flag_runonce=1
- flag_set=1
- ;;
- a)
- flag_continueonerror=1
- flag_processall=1
- ;;
- c)
- flag_continueonerror=1
- ;;
- h)
- print_version
- print_usage
- ;;
- l)
- echo "Configuration file: ${scriptconf}"
- echo "List of valid <conf> entries:"
- echo ""
- scriptconf_list
- exit 0
- ;;
- n)
- flag_donothing=1
- flag_verbose=1
- ;;
- s)
- flag_set=1
- ;;
- u)
- flag_unset=1
- ;;
- v)
- flag_verbose=1
- ;;
- \?)
- # getopts issues an error message (automatically, via a POSIX shell)
- warning
- print_usage
- exit 100
- ;;
- esac
- done
- # Remove the switches we parsed above.
- shift `expr $OPTIND - 1`
- ## if -a was used, process all valid <conf> entries here and exit, otherwise continue
- if [ ${flag_processall} -eq 1 ] ; then
- scriptconf_check
- [ ${flag_set} -eq 1 ] && message "${scriptname}: option -s cannot be used together with -a, ignored."
- [ ${flag_unset} -eq 1 ] && message "${scriptname}: option -u cannot be used together with -a, ignored."
- message "Processing all valid <conf> entries..."
- message
- for confentry in `cat "${scriptconf}"` ; do
- update_confd "$confentry"
- message
- done
- exit 0
- fi
- # We want at least one non-option argument (the <conf> to be processed)
- if [ $# -lt 1 ]; then
- print_version
- print_usage
- exit 1
- fi
- if [ ${flag_set} -eq 1 ] && [ ${flag_unset} -eq 1 ] ; then
- warning "${scriptname}: options -s and -u cannot be used at the same time!"
- exit 1
- fi
- # check for /etc/update-conf.d (or, if PREFIXED, something other than /etc); exit on error
- scriptconf_check
- for PARAM; do
- [ ${flag_unset} -eq 1 ] && scriptconf_remove ${PARAM}
- update_confd ${PARAM}
- message
- [ ${flag_set} -eq 1 ] && scriptconf_add ${PARAM}
- done
- exit 0