diff options
author | Dave Reisner <dreisner@archlinux.org> | 2016-07-06 13:22:16 +0200 |
---|---|---|
committer | Dave Reisner <dreisner@archlinux.org> | 2016-07-07 14:30:59 +0200 |
commit | b9308a5296fc0dc8da78cd6f02a5af9c38f0a044 (patch) | |
tree | ecfa5b08409b65424cdcf4a063bc0d33fecbd5c2 /init_functions | |
parent | a089c8622708d5249aa7830590464fb29dc799a4 (diff) | |
download | mkinitcpio-b9308a5296fc0dc8da78cd6f02a5af9c38f0a044.tar.gz mkinitcpio-b9308a5296fc0dc8da78cd6f02a5af9c38f0a044.tar.xz |
refactor parse_cmdline into something more readable
This refactors parse_cmdline into a few chunks of code, mainly to
separate the work of parsing from the handling of the actual parsed
parameters. By default, parse_cmdline_item is used as the callback for
handling the parameters, but this could be overriden by other code
sourcing init_functions if desirable.
Our test harness passes more tests, but we leave behind some expected
failures to describe the cases where it still fails. Fortunately I've
not yet been able to find any cases which warrant --expect-parse-fail.
Diffstat (limited to 'init_functions')
-rw-r--r-- | init_functions | 175 |
1 files changed, 117 insertions, 58 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() { |