diff options
author | Dave Reisner <dreisner@archlinux.org> | 2011-11-06 19:13:43 -0500 |
---|---|---|
committer | Dave Reisner <dreisner@archlinux.org> | 2011-11-06 19:15:52 -0500 |
commit | ec9ec4ad367f494165ced611af6b2641e8cb2472 (patch) | |
tree | c282490743d12406421003c352a060a15d7e5605 | |
parent | fe1695420fab1476dec28d70b91282c9b30d161e (diff) |
functions: implement a environment file parser
This adds a 'parse_envfile' function that reads files such as
/etc/locale.conf and /etc/vconsole.conf without sourcing them as bash
logic. Several benefits are realized from this:
- Impossible to execute arbitrary code
- Bad syntax won't prevent the entire file from being read
- Possible to limit what variables are allowed
Signed-off-by: Dave Reisner <dreisner@archlinux.org>
-rw-r--r-- | functions | 50 | ||||
-rwxr-xr-x | rc.sysinit | 4 |
2 files changed, 50 insertions, 4 deletions
@@ -9,6 +9,8 @@ localevars=(LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT LC_IDENTIFICATION LC_ALL) +vconsolevars=(KEYMAP KEYMAP_TOGGLE FONT FONT_MAP FONT_UNIMAP) + if [[ $1 == "start" ]]; then if [[ $STARTING ]]; then echo "A daemon is starting another daemon, this is unlikely to work as intended." @@ -70,12 +72,56 @@ unset TZ # sanitize the locale settins unset "${localevars[@]}" +parse_envfile() { + local file=$1 validkeys=${@:2} ret=0 lineno=0 key= val= + + if [[ -z $file ]]; then + printf "error: no environment file specified\n" + return 1 + fi + + if [[ ! -f $file ]]; then + printf "error: cannot parse \`%s': No such file or directory\n" "$file" + return 1 + fi + + if [[ ! -r $file ]]; then + printf "error: cannot read \`%s': Permission denied\n" "$file" + return 1 + fi + + while IFS='=' read -r key val; do + (( ++lineno )) + + # trim whitespace, avoiding usage of a tempfile + key=$(echo "$1" | { read -r val; echo "$val"; }) + val=$(echo "$1" | { read -r val; echo "$val"; }) + + [[ $key ]] || continue + + if [[ -z $val ]]; then + printf "error: found key \`%s' without value on line %s of %s\n" \ + "$key" "$lineno" "$file" + (( ++ret )) + continue + fi + + # ignore invalid keys if we have a list of valid ones + if (( ${#validkeys[*]} )); then + in_array "$key" "${validkeys[@]}" || continue + fi + + export "$key=$val" || (( ++ret )) + done <"$file" + + return $ret +} + if [[ $DAEMON_LOCALE = [yY][eE][sS] ]]; then LANG=${LOCALE:-C} if [[ -r /etc/locale.conf ]]; then - . /etc/locale.conf + parse_envfile /etc/locale.conf "${localevars[@]}" fi - export "${localevars[@]}" else export LANG=C fi @@ -237,7 +237,7 @@ if [[ $HOSTNAME ]]; then fi if [[ -s /etc/locale.conf ]]; then - . /etc/locale.conf + parse_envfile /etc/locale.conf "LANG" [[ $LANG ]] && LOCALE=$LANG fi if [[ ${LOCALE,,} =~ utf ]]; then @@ -263,7 +263,7 @@ else fi if [[ -s /etc/vconsole.conf ]]; then - . /etc/vconsole.conf + parse_envfile /etc/vconsole.conf "${vconsolevars[@]}" [[ $FONT ]] && CONSOLEFONT=$FONT [[ $FONT_MAP ]] && CONSOLEMAP=$FONT_MAP fi |