Add kdump_parse_args and kdump_parse_get_arg, these two helper can parse
shell args properly, handle quotes and escaped characters.
kdump_parse_args accepts a plain string, and a callback function. It
will parse the string as shell command line arguments correctly (except
it doesn't allow newline in the command line, which should be accetable
since newline is not supported in kdump.conf file either), and then it
call the callback using these arguments.
kdump_parse_get_arg will parse the string the same way, then get the
specified args value. It can handle all kind of argument format: arg=val,
--arg val, --arg=val).
For example:
`kdump_parse_args '-e "\nword\n"' echo
Is equivalent to:
echo -e "\nword\n"
`kdump_parse_get_arg '--opt=1 --opt 2 -o "3 4"' -o --opt`
Will print:
1
2
3 4
Because some params can be used multiple times, caller should decide
if the later value should override previous value or not.
All dracut_args related parsing codes are updated to use these two
new helper.
Signed-off-by: Kairui Song <kasong(a)redhat.com>
---
dracut-module-setup.sh | 1 +
kdump-lib-initramfs.sh | 45 ++++++++++++++++++++++++++++++++++++++++--
kdump-lib.sh | 24 ++++++++--------------
kdumpctl | 4 ++--
mkdumprd | 4 +---
5 files changed, 55 insertions(+), 23 deletions(-)
diff --git a/dracut-module-setup.sh b/dracut-module-setup.sh
index a5e4b678..a6257bf6 100755
--- a/dracut-module-setup.sh
+++ b/dracut-module-setup.sh
@@ -1029,6 +1029,7 @@ install() {
inst "/bin/awk" "/bin/awk"
inst "/bin/sed" "/bin/sed"
inst "/bin/stat" "/bin/stat"
+ inst "/bin/xargs" "/bin/xargs"
inst "/sbin/makedumpfile" "/sbin/makedumpfile"
inst "/sbin/vmcore-dmesg" "/sbin/vmcore-dmesg"
inst "/usr/bin/printf" "/sbin/printf"
diff --git a/kdump-lib-initramfs.sh b/kdump-lib-initramfs.sh
index c1fd75f5..ab4c7010 100755
--- a/kdump-lib-initramfs.sh
+++ b/kdump-lib-initramfs.sh
@@ -24,6 +24,47 @@ kdump_get_conf_val()
sed -n -e "/^\s*\($1\)\s\+/{s/^\s*\($1\)\s\+//;s/#.*//;s/\s*$//;h};\${x;p}" $KDUMP_CONFIG_FILE
}
+# parse shell arguments properly, call a function use parses args
+# $1: args plain string
+# ${@:2}: callback
+kdump_parse_args()
+{
+ _arg=$1
+ shift
+ _func=$*
+ set --
+ while read -r _arg; do
+ set -- "$@" "$_arg"
+ done << EOF
+$(xargs -n 1 echo '' << ARG
+$_arg
+ARG
+)
+EOF
+ $_func "$@"
+}
+
+# $1: args plain string
+# ${@:2}: list of the arg to get
+kdump_parse_get_arg()
+{
+ _arg=$1
+ shift
+ _func="_func() {
+ while [ \$# -gt 1 ]; do
+ case \$1 in"
+ while [ $# -ge 1 ]; do
+ _func="$_func
+ $1) echo \"\$2\" ;;
+ $1=*) echo \"\${1#$1=}\" ;;"
+ shift
+ done
+ _func="$_func esac; shift; done
+ }"
+ eval "$_func"
+ kdump_parse_args "$_arg" _func
+}
+
is_mounted()
{
findmnt -k -n "$1" > /dev/null 2>&1
@@ -55,13 +96,13 @@ is_fs_type_nfs()
# If $1 contains dracut_args "--mount", return <filesystem type>
get_dracut_args_fstype()
{
- echo $1 | grep "\-\-mount" | sed "s/.*--mount .\(.*\)/\1/" | cut -d' ' -f3
+ kdump_parse_get_arg "$1" "--mount" | awk '{print $3}'
}
# If $1 contains dracut_args "--mount", return <device>
get_dracut_args_target()
{
- echo $1 | grep "\-\-mount" | sed "s/.*--mount .\(.*\)/\1/" | cut -d' ' -f1
+ kdump_parse_get_arg "$1" "--mount" | awk '{print $1}'
}
get_save_path()
diff --git a/kdump-lib.sh b/kdump-lib.sh
index 2e2775c9..3da9ac3b 100755
--- a/kdump-lib.sh
+++ b/kdump-lib.sh
@@ -411,21 +411,13 @@ get_ifcfg_filename()
echo -n "${ifcfg_file}"
}
-# returns 0 when omission of a module is desired in dracut_args
-# returns 1 otherwise
-is_dracut_mod_omitted()
-{
- local dracut_args dracut_mod=$1
-
- set -- $(kdump_get_conf_val dracut_args)
- while [ $# -gt 0 ]; do
- case $1 in
- -o | --omit)
- [[ " ${2//[^[:alnum:]]/ } " == *" $dracut_mod "* ]] && return 0
- ;;
- esac
- shift
- done
+is_dracut_mod_omitted() {
+ local dracut_mod=$1 dracut_args omit_mod
+
+ dracut_args="$(kdump_get_conf_val dracut_args)"
+ omit_mod=$(kdump_parse_get_arg "$dracut_args" -o --omit)
+
+ [[ " ${omit_mod//[^[:alnum:]]/ } " == *" $dracut_mod "* ]] && return 0
return 1
}
@@ -448,7 +440,7 @@ is_wdt_active()
# its correctness).
is_mount_in_dracut_args()
{
- [[ " $(kdump_get_conf_val dracut_args)" =~ .*[[:space:]]--mount[=[:space:]].* ]]
+ [[ $(kdump_parse_get_arg "$(kdump_get_conf_val dracut_args)" --mount) ]]
}
check_crash_mem_reserved()
diff --git a/kdumpctl b/kdumpctl
index 59ec0688..16f6e81a 100755
--- a/kdumpctl
+++ b/kdumpctl
@@ -219,7 +219,7 @@ check_config()
case "$config_opt" in
dracut_args)
if [[ $config_val == *--mount* ]]; then
- if [[ $(echo "$config_val" | grep -o "\-\-mount" | wc -l) -ne 1 ]]; then
+ if [[ $(kdump_parse_get_arg "$config_val" "--mount") ]]; then
derror 'Multiple mount targets specified in one "dracut_args".'
return 1
fi
@@ -498,7 +498,7 @@ check_fs_modified()
# point and file system. If any of them mismatches then rebuild
if echo "$_dracut_args" | grep -q "\-\-mount"; then
# shellcheck disable=SC2046
- set -- $(echo "$_dracut_args" | awk -F "--mount '" '{print $2}' | cut -d' ' -f1,2,3)
+ set -- $(kdump_parse_get_arg "$_dracut_args" "--mount")
_old_dev=$1
_old_mntpoint=$2
_old_fstype=$3
diff --git a/mkdumprd b/mkdumprd
index c6cb0018..d02ef8c0 100644
--- a/mkdumprd
+++ b/mkdumprd
@@ -420,9 +420,7 @@ while read -r config_opt config_val; do
verify_core_collector "$config_val"
;;
dracut_args)
- while read -r dracut_arg; do
- add_dracut_arg "$dracut_arg"
- done <<< "$(echo "$config_val" | xargs -n 1 echo)"
+ kdump_parse_args "$config_val" add_dracut_arg
;;
*) ;;
--
2.31.1