From cc29e54b851212568c3f6eddf4bf0a64c1eabb0d Mon Sep 17 00:00:00 2001 From: Dennis Camera Date: Thu, 23 Jul 2020 23:20:39 +0200 Subject: [PATCH] [type/__localedef] Differentiate between OSes and better handling of normalized locale names --- cdist/conf/type/__localedef/gencode-remote | 117 +++++++++++++++------ 1 file changed, 82 insertions(+), 35 deletions(-) diff --git a/cdist/conf/type/__localedef/gencode-remote b/cdist/conf/type/__localedef/gencode-remote index 9ea3f6f1..b9cc68e8 100755 --- a/cdist/conf/type/__localedef/gencode-remote +++ b/cdist/conf/type/__localedef/gencode-remote @@ -1,6 +1,7 @@ #!/bin/sh -e # # 2013-2019 Nico Schottelius (nico-cdist at schottelius.org) +# 2020 Dennis Camera (dennis.camera at ssrq-sds-fds.ch) # # This file is part of cdist. # @@ -17,35 +18,16 @@ # You should have received a copy of the GNU General Public License # along with cdist. If not, see . # +# Manage system locales using localedef(1). # -# Let localedef do the magic -# - -locale="$__object_id" - -# Hardcoded, create a pull request with -# branching on $os in case it is at another location -alias=/usr/share/locale/locale.alias - -input=$(echo "$locale" | cut -d . -f 1) -charmap=$(echo "$locale" | cut -d . -f 2) - -# Adding locale? The name is de_CH.UTF-8 -# Removing locale? The name is de_CH.utf8. -# W-T-F! -locale_remove=$(echo "$locale" | sed 's/UTF-8/utf8/') state_is=$(cat "${__object:?}/explorer/state") state_should=$(cat "${__object:?}/parameter/state") -os=$(cat "$__global/explorer/os") - -# Nothing to be done on alpine -case "$os" in - alpine) - exit 0 - ;; -esac +test "${state_should}" = 'present' -o "${state_should}" = 'absent' || { + printf 'Invalid state: %s\n' "${state_should}" >&2 + exit 1 +} # NOTE: If state explorer fails (e.g. locale(1) missing), the following check # will always fail and let definition/removal run. @@ -54,16 +36,81 @@ then exit 0 fi -case ${state_should} +locale=${__object_id:?} +os=$(cat "${__global:?}/explorer/os") + +if expr "${locale}" : '.*/' >/dev/null +then + printf 'Paths as locales are not supported.\n' >&2 + printf '__object_id is: %s\n' "${locale}" >&2 + exit 1 +fi + +parse_locale() { + # This function will split locales into their parts. Locale strings are + # usually of the form: [language[_territory][.codeset][@modifier]] + # For simplicity, language and territory are not separated by this function. + # Old Linux systems were also using "english" or "german" as locale strings. + # Usage: parse_locale locale_str lang_var codeset_var modifier_var + eval "${2:?}"="$(expr "$1" : '\([^.@]*\)')" + eval "${3:?}"="$(expr "$1" : '[^.]*\.\([^@]*\)')" + eval "${4:?}"="$(expr "$1" : '.*@\(.*\)$')" +} + +format_locale() { + # Usage: format_locale language codeset modifier + printf '%s' "$1" + test -z "$2" || printf '.%s' "$2" + test -z "$3" || printf '@%s' "$3" + printf '\n' +} + +gnu_normalize_codeset() { + echo "$*" | tr -cd '[:alnum:]' | tr '[:upper:]' '[:lower:]' +} + + +: "${lang=}" "${codeset=}" "${modifier=}" # declare variables for shellcheck +parse_locale "${locale}" lang codeset modifier + + +case ${os} in - present) - echo localedef -A "$alias" -f "$charmap" -i "$input" "$locale" - ;; - absent) - echo localedef --delete-from-archive "$locale_remove" - ;; - *) - echo "Unsupported state: $state" >&2 - exit 1 - ;; + (alpine|openwrt) + printf '%s does not support locales.\n' "${os}" >&2 + exit 1 + ;; + (archlinux|debian|devuan|ubuntu|suse|centos|fedora|redhat|scientific) + # FIXME: The code below only works for glibc-based installations. + + # NOTE: Hardcoded, create a pull request in case it is at another + # location for some opther distro. + # NOTE: locale.alias can be symlinked (e.g. Debian) + aliasfile='/usr/share/locale/locale.alias' + + case ${state_should} + in + (present) + input=$(format_locale "${lang}" '' "${modifier}") + cat <<-EOF + set -- + if test -e '${aliasfile}' + then + set -- -A '${aliasfile}' + fi + + localedef -i '${input}' -f '${codeset}' "\$@" '${locale}' + EOF + ;; + (absent) + localename=$(format_locale "${lang}" "$(gnu_normalize_codeset "${codeset}")" "${modifier}") + printf "localedef --delete-from-archive '%s'\n" "${localename}" + ;; + esac + ;; + (*) + echo "Your operating system (${os}) is currently not supported by this type (${__type##*/})." >&2 + echo "Please contribute an implementation for it if you can." >&2 + exit 1 + ;; esac