summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--init_functions175
-rwxr-xr-xtest/test_parse_cmdline16
2 files changed, 125 insertions, 66 deletions
diff --git a/init_functions b/init_functions
index 05f4ab0..d5a584e 100644
--- a/init_functions
+++ b/init_functions
@@ -114,74 +114,133 @@ set_log_option() {
done
}
-parse_cmdline() {
- local _w _quoted _lhs _rhs _cmdline
- read -r _cmdline
- for _w in $_cmdline; do
- if [ -z "$_quoted" ]; then
- case $_w in
- # ignore everything after a # in the commandline
- \#*) break ;;
- # special cases
- rw|ro) rwopt=$_w ;;
- fstype) rootfstype=$_w ;;
- fsck.mode=*)
- case ${_w#*=} in
- force)
- forcefsck=y
- ;;
- skip)
- fastboot=y
- ;;
- *)
- err "unknown fsck.mode parameter: '${_w#*=}'"
- ;;
- esac
+startswith() {
+ local word=$1 prefix=$2
+
+ case $word in
+ $prefix*)
+ return 0
+ ;;
+ esac
+
+ return 1
+}
+
+endswith() {
+ local word=$1 suffix=$2
+
+ case $word in
+ *$suffix)
+ return 0
+ ;;
+ esac
+
+ return 1
+}
+
+parse_cmdline_item() {
+ local key=$1 value=$2
+
+ case $key in
+ rw|ro)
+ rwopt=$key
+ ;;
+ fstype)
+ # The kernel understands 'rootfstype', but mkinitcpio has (without
+ # documentation) supported 'fstype' instead. Ensure we support both
+ # for backwards compat, but make fstype legacy.
+ rootfstype=$value
+ ;;
+ fsck.mode)
+ case $value in
+ force)
+ forcefsck=y
;;
- rd.*)
- case ${_w#rd.} in
- debug)
- rd_debug=y
- ;;
- log)
- rd_logmask=$(( _rdlog_kmsg | _rdlog_cons ))
- ;;
- log=*)
- set_log_option "${_w#rd.log=}"
- ;;
- esac
+ skip)
+ fastboot=y
;;
- # abide by shell variable naming rules
- [[:alpha:]_]*=*)
- _rhs=${_w#*=}
- _lhs=${_w%%=*}
- _lhs=${_lhs//[-.]/_}
- if [ '"' = "${_rhs:0:1}" ]; then
- if [ '"' = "${_rhs:$((${#_rhs}-1))}" ]; then
- _rhs="${_rhs:1:$((${#_rhs}-2))}"
- else
- _rhs=${_rhs:1}
- _quoted=1
- continue
- fi
+ *)
+ err "unknown fsck.mode parameter: '$value'"
+ ;;
+ esac
+ ;;
+ rd.debug)
+ rd_debug=y
+ ;;
+ rd.log)
+ if [ -n "$value" ]; then
+ set_log_option "$value"
+ else
+ rd_logmask=$(( _rdlog_kmsg | _rdlog_cons ))
+ fi
+ ;;
+ [![:alpha:]_]*|[[:alpha:]_]*[![:alnum:]_]*)
+ # invalid shell variable, ignore it
+ ;;
+ *)
+ # valid shell variable
+ eval "$key"='${value:-y}'
+ ;;
+ esac
+}
+
+process_cmdline_param() {
+ local item_callback=$1 key=$2 value=$3
+
+ # maybe unquote the value
+ if startswith "$value" "[\"']" && endswith "$value" "${value:0:1}"; then
+ value=${value#?} value=${value%?}
+ fi
+
+ "$item_callback" "$key" "$value"
+}
+
+parse_cmdline() {
+ local item_callback=${1:-parse_cmdline_item}
+ local cmdline word quoted key value
+
+ set -f
+ read -r cmdline
+ set -- $cmdline
+ set +f
+
+ for word; do
+ if [ -n "$quoted" ]; then
+ value="$value $word"
+ else
+ case $word in
+ *=*)
+ key=${word%%=*}
+ value=${word#*=}
+
+ if startswith "$value" "[\"']"; then
+ quoted=${value:0:1}
fi
- eval $_lhs=\$_rhs
;;
- [[:alpha:]_]*)
- _lhs=${_w//[-.]/_}
- eval $_lhs=y
+ '#'*)
+ break
+ ;;
+ *)
+ key=$word
;;
esac
- else
- if [ '"' = "${_w:$((${#_w}-1))}" ]; then
- _rhs="$_rhs ${_w%\"}"
- unset _quoted
- eval $_lhs=\$_rhs
+ fi
+
+ if [ -n "$quoted" ]; then
+ if endswith "$value" "$quoted"; then
+ unset quoted
else
- _rhs="$_rhs $_w"
+ continue
fi
fi
+
+ process_cmdline_param "$item_callback" "$key" "$value"
+ unset key value
done
+
+ if [ -n "$key" ]; then
+ process_cmdline_param "$item_callback" "$key" "$value"
+ fi
}
fsck_device() {
diff --git a/test/test_parse_cmdline b/test/test_parse_cmdline
index 9afd9cb..ff855e4 100755
--- a/test/test_parse_cmdline
+++ b/test/test_parse_cmdline
@@ -130,19 +130,19 @@ test_parse 'foo="bar baz"' \
'foo' 'bar baz'
# single quoting
-test_parse --expect-fail "foo='bar'" \
+test_parse "foo='bar'" \
'foo' 'bar'
-test_parse --expect-parse-fail "foo='bar baz'" \
+test_parse "foo='bar baz'" \
'foo' 'bar baz'
# dangling quotes
-test_parse --expect-fail 'foo="bar' \
+test_parse 'foo="bar' \
'foo' '"bar'
test_parse 'foo=bar"' \
'foo' 'bar"'
# nested quotes
-test_parse --expect-parse-fail "foo='\"bar baz\"' herp='\"de\"rp'" \
+test_parse "foo='\"bar baz\"' herp='\"de\"rp'" \
'foo' '"bar baz"' \
'herp' '"de"rp'
@@ -174,9 +174,9 @@ test_parse 'foo="bar #baz" parse=this' \
# shell metachars
test_parse 'foo=*' \
'foo' '\*'
-test_parse --expect-fail 'Make*' \
+test_parse 'Make*' \
'Makefile' ''
-test_parse --expect-fail '[Makefile]*' \
+test_parse '[Makefile]*' \
'Makefile' '' \
'init' '' \
'functions' ''
@@ -184,7 +184,7 @@ test_parse --expect-fail '[Makefile]*' \
# invalid names
test_parse 'in-valid=name'
test_parse '6foo=bar'
-test_parse --expect-parse-fail '"gar bage"' \
+test_parse '"gar bage"' \
'gar' '' \
'bage' ''
@@ -197,7 +197,7 @@ test_parse 'ro' \
'ro' '' \
'rw' '' \
'rwopt' 'ro'
-test_parse --expect-fail 'fstype=btrfs' \
+test_parse 'fstype=btrfs' \
'rootfstype' 'btrfs'
test_parse 'fsck.mode=force' \
'forcefsck' 'y' \