summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Reisner <dreisner@archlinux.org>2011-11-06 19:13:43 -0500
committerDave Reisner <dreisner@archlinux.org>2011-11-06 19:15:52 -0500
commitec9ec4ad367f494165ced611af6b2641e8cb2472 (patch)
treec282490743d12406421003c352a060a15d7e5605
parentfe1695420fab1476dec28d70b91282c9b30d161e (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--functions50
-rwxr-xr-xrc.sysinit4
2 files changed, 50 insertions, 4 deletions
diff --git a/functions b/functions
index ce664ed..387f2af 100644
--- a/functions
+++ b/functions
@@ -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
diff --git a/rc.sysinit b/rc.sysinit
index eb66935..654a409 100755
--- a/rc.sysinit
+++ b/rc.sysinit
@@ -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