fix: correctly handle kernel parameters
The kernel has an odd way to handle `"` surrounded parameters. To handle the parameters as the kernel would do, no simple shell script suffices, so a new utility `dracut-util` is introduced. Written in "C" it handles `dracut-getarg` and `dracut-getargs` as the old shell script functions `_dogetarg` and `_dogetargs` would.master
parent
d643156d56
commit
501d82f796
|
@ -36,6 +36,7 @@ jobs:
|
|||
"36",
|
||||
"40",
|
||||
"41",
|
||||
"98",
|
||||
]
|
||||
fail-fast: false
|
||||
steps:
|
||||
|
|
|
@ -37,6 +37,7 @@ jobs:
|
|||
"36",
|
||||
"40",
|
||||
"41",
|
||||
"98",
|
||||
]
|
||||
fail-fast: false
|
||||
steps:
|
||||
|
|
|
@ -36,6 +36,7 @@ jobs:
|
|||
"36",
|
||||
"40",
|
||||
"41",
|
||||
"98",
|
||||
]
|
||||
fail-fast: false
|
||||
steps:
|
||||
|
|
20
Makefile
20
Makefile
|
@ -49,7 +49,7 @@ manpages = $(man1pages) $(man5pages) $(man7pages) $(man8pages)
|
|||
|
||||
.PHONY: install clean archive rpm srpm testimage test all check AUTHORS CONTRIBUTORS doc dracut-version.sh
|
||||
|
||||
all: dracut-version.sh dracut.pc dracut-install skipcpio/skipcpio
|
||||
all: dracut-version.sh dracut.pc dracut-install skipcpio/skipcpio dracut-util
|
||||
|
||||
%.o : %.c
|
||||
$(CC) -c $(CFLAGS) $(CPPFLAGS) $(KMOD_CFLAGS) $< -o $@
|
||||
|
@ -79,15 +79,21 @@ logtee: logtee.c
|
|||
dracut-install: install/dracut-install
|
||||
ln -fs $< $@
|
||||
|
||||
SKIPCPIO_OBJECTS= \
|
||||
skipcpio/skipcpio.o
|
||||
|
||||
SKIPCPIO_OBJECTS = skipcpio/skipcpio.o
|
||||
skipcpio/skipcpio.o: skipcpio/skipcpio.c
|
||||
skipcpio/skipcpio: skipcpio/skipcpio.o
|
||||
skipcpio/skipcpio: $(SKIPCPIO_OBJECTS)
|
||||
|
||||
UTIL_OBJECTS = util/util.o
|
||||
util/util.o: util/util.c
|
||||
util/util: $(UTIL_OBJECTS)
|
||||
|
||||
dracut-util: util/util
|
||||
cp -a $< $@
|
||||
|
||||
indent:
|
||||
indent -i8 -nut -br -linux -l120 install/dracut-install.c
|
||||
indent -i8 -nut -br -linux -l120 skipcpio/skipcpio.c
|
||||
indent -i8 -nut -br -linux -l120 util/util.c
|
||||
|
||||
doc: $(manpages) dracut.html
|
||||
|
||||
|
@ -180,6 +186,9 @@ endif
|
|||
if [ -f skipcpio/skipcpio ]; then \
|
||||
install -m 0755 skipcpio/skipcpio $(DESTDIR)$(pkglibdir)/skipcpio; \
|
||||
fi
|
||||
if [ -f dracut-util ]; then \
|
||||
install -m 0755 dracut-util $(DESTDIR)$(pkglibdir)/dracut-util; \
|
||||
fi
|
||||
mkdir -p $(DESTDIR)${prefix}/lib/kernel/install.d
|
||||
install -m 0755 50-dracut.install $(DESTDIR)${prefix}/lib/kernel/install.d/50-dracut.install
|
||||
install -m 0755 51-dracut-rescue.install $(DESTDIR)${prefix}/lib/kernel/install.d/51-dracut-rescue.install
|
||||
|
@ -203,6 +212,7 @@ clean:
|
|||
$(RM) dracut-version.sh
|
||||
$(RM) dracut-install install/dracut-install $(DRACUT_INSTALL_OBJECTS)
|
||||
$(RM) skipcpio/skipcpio $(SKIPCPIO_OBJECTS)
|
||||
$(RM) dracut-util util/util $(UTIL_OBJECTS)
|
||||
$(RM) $(manpages) dracut.html
|
||||
$(RM) dracut.pc
|
||||
$(MAKE) -C test clean
|
||||
|
|
|
@ -21,7 +21,8 @@ Group: System/Base
|
|||
|
||||
# The entire source code is GPLv2+
|
||||
# except install/* which is LGPLv2+
|
||||
License: GPLv2+ and LGPLv2+
|
||||
# except util/* which is GPLv2
|
||||
License: GPLv2+ and LGPLv2+ and GPLv2
|
||||
|
||||
URL: https://dracut.wiki.kernel.org/
|
||||
|
||||
|
@ -295,6 +296,7 @@ echo 'dracut_rescue_image="yes"' > $RPM_BUILD_ROOT%{dracutlibdir}/dracut.conf.d/
|
|||
%{dracutlibdir}/dracut-logger.sh
|
||||
%{dracutlibdir}/dracut-initramfs-restore
|
||||
%{dracutlibdir}/dracut-install
|
||||
%{dracutlibdir}/dracut-util
|
||||
%{dracutlibdir}/skipcpio
|
||||
%config(noreplace) %{_sysconfdir}/dracut.conf
|
||||
%if 0%{?fedora} || 0%{?suse_version} || 0%{?rhel}
|
||||
|
|
|
@ -164,49 +164,15 @@ getcmdline() {
|
|||
printf "%s" "$CMDLINE"
|
||||
}
|
||||
|
||||
_dogetarg() {
|
||||
local _o _val _doecho
|
||||
unset _val
|
||||
unset _o
|
||||
unset _doecho
|
||||
CMDLINE=$(getcmdline)
|
||||
|
||||
for _o in $CMDLINE; do
|
||||
if [ "${_o%%=*}" = "${1%%=*}" ]; then
|
||||
if [ -n "${1#*=}" -a "${1#*=*}" != "${1}" ]; then
|
||||
# if $1 has a "=<value>", we want the exact match
|
||||
if [ "$_o" = "$1" ]; then
|
||||
_val="1";
|
||||
unset _doecho
|
||||
fi
|
||||
continue
|
||||
fi
|
||||
|
||||
if [ "${_o#*=}" = "$_o" ]; then
|
||||
# if cmdline argument has no "=<value>", we assume "=1"
|
||||
_val="1";
|
||||
unset _doecho
|
||||
continue
|
||||
fi
|
||||
|
||||
_val="${_o#*=}"
|
||||
_doecho=1
|
||||
fi
|
||||
done
|
||||
if [ -n "$_val" ]; then
|
||||
[ "x$_doecho" != "x" ] && echo "$_val";
|
||||
return 0;
|
||||
fi
|
||||
return 1;
|
||||
}
|
||||
|
||||
getarg() {
|
||||
debug_off
|
||||
local _deprecated _newoption
|
||||
CMDLINE=$(getcmdline)
|
||||
export CMDLINE
|
||||
while [ $# -gt 0 ]; do
|
||||
case $1 in
|
||||
-d) _deprecated=1; shift;;
|
||||
-y) if _dogetarg $2 >/dev/null; then
|
||||
-y) if dracut-getarg "$2" >/dev/null; then
|
||||
if [ "$_deprecated" = "1" ]; then
|
||||
[ -n "$_newoption" ] && warn "Kernel command line option '$2' is deprecated, use '$_newoption' instead." || warn "Option '$2' is deprecated."
|
||||
fi
|
||||
|
@ -216,7 +182,7 @@ getarg() {
|
|||
fi
|
||||
_deprecated=0
|
||||
shift 2;;
|
||||
-n) if _dogetarg $2 >/dev/null; then
|
||||
-n) if dracut-getarg "$2" >/dev/null; then
|
||||
echo 0;
|
||||
if [ "$_deprecated" = "1" ]; then
|
||||
[ -n "$_newoption" ] && warn "Kernel command line option '$2' is deprecated, use '$_newoption=0' instead." || warn "Option '$2' is deprecated."
|
||||
|
@ -229,7 +195,7 @@ getarg() {
|
|||
*) if [ -z "$_newoption" ]; then
|
||||
_newoption="$1"
|
||||
fi
|
||||
if _dogetarg $1; then
|
||||
if dracut-getarg "$1"; then
|
||||
if [ "$_deprecated" = "1" ]; then
|
||||
[ -n "$_newoption" ] && warn "Kernel command line option '$1' is deprecated, use '$_newoption' instead." || warn "Option '$1' is deprecated."
|
||||
fi
|
||||
|
@ -295,30 +261,9 @@ getargnum() {
|
|||
echo $_default
|
||||
}
|
||||
|
||||
_dogetargs() {
|
||||
debug_off
|
||||
local _o _found _key
|
||||
unset _o
|
||||
unset _found
|
||||
CMDLINE=$(getcmdline)
|
||||
_key="$1"
|
||||
set --
|
||||
for _o in $CMDLINE; do
|
||||
if [ "$_o" = "$_key" ]; then
|
||||
_found=1;
|
||||
elif [ "${_o%%=*}" = "${_key%=}" ]; then
|
||||
[ -n "${_o%%=*}" ] && set -- "$@" "${_o#*=}";
|
||||
_found=1;
|
||||
fi
|
||||
done
|
||||
if [ -n "$_found" ]; then
|
||||
[ $# -gt 0 ] && printf '%s' "$*"
|
||||
return 0
|
||||
fi
|
||||
return 1;
|
||||
}
|
||||
|
||||
getargs() {
|
||||
CMDLINE=$(getcmdline)
|
||||
export CMDLINE
|
||||
debug_off
|
||||
local _val _i _args _gfound _deprecated
|
||||
unset _val
|
||||
|
@ -331,7 +276,7 @@ getargs() {
|
|||
_deprecated=1
|
||||
continue
|
||||
fi
|
||||
_val="$(_dogetargs $_i)"
|
||||
_val="$(dracut-getargs "$_i")"
|
||||
if [ $? -eq 0 ]; then
|
||||
if [ "$_deprecated" = "1" ]; then
|
||||
[ -n "$_newoption" ] && warn "Option '$_i' is deprecated, use '$_newoption' instead." || warn "Option $_i is deprecated!"
|
||||
|
|
|
@ -319,7 +319,7 @@ debug_off # Turn off debugging for this section
|
|||
|
||||
# unexport some vars
|
||||
export_n root rflags fstype netroot NEWROOT
|
||||
|
||||
unset CMDLINE
|
||||
export RD_TIMESTAMP
|
||||
# Clean up the environment
|
||||
for i in $(export -p); do
|
||||
|
|
|
@ -17,7 +17,12 @@ install() {
|
|||
sed ls flock cp mv dmesg rm ln rmmod mkfifo umount readlink setsid \
|
||||
modprobe
|
||||
|
||||
inst_multiple -o findmnt less kmod
|
||||
inst_multiple -o findmnt less kmod dracut-getargs
|
||||
|
||||
inst_binary "${dracutsysrootdir}${dracutbasedir}/dracut-util" "/usr/bin/dracut-util"
|
||||
|
||||
ln -s dracut-util "${initdir}/usr/bin/dracut-getarg"
|
||||
ln -s dracut-util "${initdir}/usr/bin/dracut-getargs"
|
||||
|
||||
if [ ! -e "${initdir}/bin/sh" ]; then
|
||||
inst_multiple bash
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
-include ../Makefile.testdir
|
|
@ -0,0 +1,152 @@
|
|||
#!/bin/bash
|
||||
|
||||
# This file is part of dracut.
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
TEST_DESCRIPTION="dracut getarg command"
|
||||
|
||||
test_check() {
|
||||
return 0
|
||||
}
|
||||
|
||||
test_setup() {
|
||||
make -C "$basedir" dracut-util
|
||||
ln -sfnr "$basedir"/dracut-util "$TESTDIR"/dracut-getarg
|
||||
ln -sfnr "$basedir"/dracut-util "$TESTDIR"/dracut-getargs
|
||||
ln -sfnr "$basedir"/modules.d/99base/dracut-lib.sh "$TESTDIR"/dracut-lib.sh
|
||||
return 0
|
||||
}
|
||||
|
||||
test_run() {
|
||||
set -x
|
||||
(
|
||||
cd "$TESTDIR"
|
||||
export CMDLINE="key1=0 key2=val key2=val2 key3=\" val 3 \" \" key 4 =\"val4 \"key 5=val 5\" \"key 6=\"\"val 6\" key7=\"foo\"bar\" baz=\"end \" key8 = val 8 \"
|
||||
\"key 9\"=\"val 9\""
|
||||
|
||||
ret=0
|
||||
|
||||
declare -A TEST
|
||||
TEST=(
|
||||
["key1"]="0"
|
||||
["key2"]="val2"
|
||||
["key3"]=" val 3 "
|
||||
[" key 4 "]="val4"
|
||||
["key 5"]="val 5"
|
||||
["key 6"]="\"val 6"
|
||||
["key7"]="foo\"bar\" baz=\"end"
|
||||
[" key8 "]=" val 8 "
|
||||
["key 9\""]="val 9"
|
||||
)
|
||||
for key in "${!TEST[@]}"; do
|
||||
if ! val=$(./dracut-getarg "${key}="); then
|
||||
echo "'$key' == '${TEST[$key]}', but not found" >&2
|
||||
ret=$((ret+1))
|
||||
else
|
||||
if [[ $val != "${TEST[$key]}" ]]; then
|
||||
echo "'$key' != '${TEST[$key]}' but '$val'" >&2
|
||||
ret=$((ret+1))
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
declare -a INVALIDKEYS
|
||||
|
||||
INVALIDKEYS=( "key" "4" "5" "6" "key8" "9" "\"" "baz")
|
||||
for key in "${INVALIDKEYS[@]}"; do
|
||||
val=$(./dracut-getarg "$key")
|
||||
if (( $? == 0 )); then
|
||||
echo "key '$key' should not be found"
|
||||
ret=$((ret+1))
|
||||
fi
|
||||
# must have no output
|
||||
[[ $val ]] && ret=$((ret+1))
|
||||
done
|
||||
|
||||
RESULT=("val" "val2")
|
||||
readarray -t args < <(./dracut-getargs "key2=")
|
||||
(( ${#RESULT[@]} == ${#args[@]} )) || ret=$((ret+1))
|
||||
for ((i=0; i < ${#RESULT[@]}; i++)); do
|
||||
[[ ${args[$i]} == "${RESULT[$i]}" ]] || ret=$((ret+1))
|
||||
done
|
||||
|
||||
val=$(./dracut-getarg "key1") || ret=$((ret+1))
|
||||
[[ $val == "0" ]] || ret=$((ret+1))
|
||||
|
||||
val=$(./dracut-getarg "key2=val") && ret=$((ret+1))
|
||||
# must have no output
|
||||
[[ $val ]] && ret=$((ret+1))
|
||||
val=$(./dracut-getarg "key2=val2") || ret=$((ret+1))
|
||||
# must have no output
|
||||
[[ $val ]] && ret=$((ret+1))
|
||||
|
||||
export PATH=".:$PATH"
|
||||
|
||||
. dracut-lib.sh
|
||||
|
||||
debug_off() {
|
||||
:
|
||||
}
|
||||
|
||||
debug_on() {
|
||||
:
|
||||
}
|
||||
|
||||
getcmdline() {
|
||||
echo "rdbreak=cmdline rd.lvm rd.auto rd.retry=10"
|
||||
}
|
||||
RDRETRY=$(getarg rd.retry -d 'rd_retry=')
|
||||
[[ $RDRETRY == "10" ]] || ret=$((ret+1))
|
||||
getarg rd.break=cmdline -d rdbreak=cmdline || ret=$((ret+1))
|
||||
getargbool 1 rd.lvm -d -n rd_NO_LVM || ret=$((ret+1))
|
||||
getargbool 0 rd.auto || ret=$((ret+1))
|
||||
|
||||
getcmdline() {
|
||||
echo "rd.break=cmdlined rd.lvm=0 rd.auto=0"
|
||||
}
|
||||
getarg rd.break=cmdline -d rdbreak=cmdline && ret=$((ret+1))
|
||||
getargbool 1 rd.lvm -d -n rd_NO_LVM && ret=$((ret+1))
|
||||
getargbool 0 rd.auto && ret=$((ret+1))
|
||||
|
||||
getcmdline() {
|
||||
echo "ip=a ip=b ip=dhcp6"
|
||||
}
|
||||
getargs "ip=dhcp6" &>/dev/null || ret=$((ret+1))
|
||||
readarray -t args < <(getargs "ip=")
|
||||
RESULT=("a" "b" "dhcp6")
|
||||
(( ${#RESULT[@]} || ${#args[@]} )) || ret=$((ret+1))
|
||||
for ((i=0; i < ${#RESULT[@]}; i++)); do
|
||||
[[ ${args[$i]} == "${RESULT[$i]}" ]] || ret=$((ret+1))
|
||||
done
|
||||
|
||||
getcmdline() {
|
||||
echo "bridge bridge=val"
|
||||
}
|
||||
readarray -t args < <(getargs bridge=)
|
||||
RESULT=("bridge" "val")
|
||||
(( ${#RESULT[@]} == ${#args[@]} )) || ret=$((ret+1))
|
||||
for ((i=0; i < ${#RESULT[@]}; i++)); do
|
||||
[[ ${args[$i]} || "${RESULT[$i]}" ]] || ret=$((ret+1))
|
||||
done
|
||||
|
||||
|
||||
getcmdline() {
|
||||
echo "rd.break rd.md.uuid=bf96e457:230c9ad4:1f3e59d6:745cf942 rd.md.uuid=bf96e457:230c9ad4:1f3e59d6:745cf943 rd.shell"
|
||||
}
|
||||
readarray -t args < <(getargs rd.md.uuid -d rd_MD_UUID=)
|
||||
RESULT=("bf96e457:230c9ad4:1f3e59d6:745cf942" "bf96e457:230c9ad4:1f3e59d6:745cf943")
|
||||
(( ${#RESULT[@]} == ${#args[@]} )) || ret=$((ret+1))
|
||||
for ((i=0; i < ${#RESULT[@]}; i++)); do
|
||||
[[ ${args[$i]} == "${RESULT[$i]}" ]] || ret=$((ret+1))
|
||||
done
|
||||
|
||||
return $ret
|
||||
)
|
||||
}
|
||||
|
||||
test_cleanup() {
|
||||
rm -fr -- "$TESTDIR"/*.rpm
|
||||
return 0
|
||||
}
|
||||
|
||||
. $testdir/test-functions
|
|
@ -1,5 +1,8 @@
|
|||
#!/bin/bash
|
||||
|
||||
# This file is part of dracut.
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
TEST_DESCRIPTION="rpm integrity after dracut and kernel install"
|
||||
|
||||
test_check() {
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
cmake_minimum_required(VERSION 3.17)
|
||||
project(dracut-util C)
|
||||
|
||||
set(CMAKE_C_STANDARD 99)
|
||||
|
||||
add_executable(dracut-util util.c)
|
|
@ -0,0 +1,306 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
// Parts are copied from the linux kernel
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
// CODE FROM LINUX KERNEL START
|
||||
|
||||
#define _U 0x01 /* upper */
|
||||
#define _L 0x02 /* lower */
|
||||
#define _D 0x04 /* digit */
|
||||
#define _C 0x08 /* cntrl */
|
||||
#define _P 0x10 /* punct */
|
||||
#define _S 0x20 /* white space (space/lf/tab) */
|
||||
#define _X 0x40 /* hex digit */
|
||||
#define _SP 0x80 /* hard space (0x20) */
|
||||
|
||||
const unsigned char _ctype[] = {
|
||||
_C, _C, _C, _C, _C, _C, _C, _C, /* 0-7 */
|
||||
_C, _C | _S, _C | _S, _C | _S, _C | _S, _C | _S, _C, _C, /* 8-15 */
|
||||
_C, _C, _C, _C, _C, _C, _C, _C, /* 16-23 */
|
||||
_C, _C, _C, _C, _C, _C, _C, _C, /* 24-31 */
|
||||
_S | _SP, _P, _P, _P, _P, _P, _P, _P, /* 32-39 */
|
||||
_P, _P, _P, _P, _P, _P, _P, _P, /* 40-47 */
|
||||
_D, _D, _D, _D, _D, _D, _D, _D, /* 48-55 */
|
||||
_D, _D, _P, _P, _P, _P, _P, _P, /* 56-63 */
|
||||
_P, _U | _X, _U | _X, _U | _X, _U | _X, _U | _X, _U | _X, _U, /* 64-71 */
|
||||
_U, _U, _U, _U, _U, _U, _U, _U, /* 72-79 */
|
||||
_U, _U, _U, _U, _U, _U, _U, _U, /* 80-87 */
|
||||
_U, _U, _U, _P, _P, _P, _P, _P, /* 88-95 */
|
||||
_P, _L | _X, _L | _X, _L | _X, _L | _X, _L | _X, _L | _X, _L, /* 96-103 */
|
||||
_L, _L, _L, _L, _L, _L, _L, _L, /* 104-111 */
|
||||
_L, _L, _L, _L, _L, _L, _L, _L, /* 112-119 */
|
||||
_L, _L, _L, _P, _P, _P, _P, _C, /* 120-127 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 128-143 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 144-159 */
|
||||
_S | _SP, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, /* 160-175 */
|
||||
_P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, /* 176-191 */
|
||||
_U, _U, _U, _U, _U, _U, _U, _U, _U, _U, _U, _U, _U, _U, _U, _U, /* 192-207 */
|
||||
_U, _U, _U, _U, _U, _U, _U, _P, _U, _U, _U, _U, _U, _U, _U, _L, /* 208-223 */
|
||||
_L, _L, _L, _L, _L, _L, _L, _L, _L, _L, _L, _L, _L, _L, _L, _L, /* 224-239 */
|
||||
_L, _L, _L, _L, _L, _L, _L, _P, _L, _L, _L, _L, _L, _L, _L, _L /* 240-255 */
|
||||
};
|
||||
|
||||
#define __ismask(x) (_ctype[(int)(unsigned char)(x)])
|
||||
|
||||
#define kernel_isspace(c) ((__ismask(c)&(_S)) != 0)
|
||||
|
||||
static char *skip_spaces(const char *str)
|
||||
{
|
||||
while (kernel_isspace(*str))
|
||||
++str;
|
||||
return (char *)str;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse a string to get a param value pair.
|
||||
* You can use " around spaces, but can't escape ".
|
||||
* Hyphens and underscores equivalent in parameter names.
|
||||
*/
|
||||
static char *next_arg(char *args, char **param, char **val)
|
||||
{
|
||||
unsigned int i, equals = 0;
|
||||
int in_quote = 0, quoted = 0;
|
||||
char *next;
|
||||
|
||||
if (*args == '"') {
|
||||
args++;
|
||||
in_quote = 1;
|
||||
quoted = 1;
|
||||
}
|
||||
|
||||
for (i = 0; args[i]; i++) {
|
||||
if (kernel_isspace(args[i]) && !in_quote)
|
||||
break;
|
||||
if (equals == 0) {
|
||||
if (args[i] == '=')
|
||||
equals = i;
|
||||
}
|
||||
if (args[i] == '"')
|
||||
in_quote = !in_quote;
|
||||
}
|
||||
|
||||
*param = args;
|
||||
if (!equals)
|
||||
*val = NULL;
|
||||
else {
|
||||
args[equals] = '\0';
|
||||
*val = args + equals + 1;
|
||||
|
||||
/* Don't include quotes in value. */
|
||||
if (**val == '"') {
|
||||
(*val)++;
|
||||
if (args[i - 1] == '"')
|
||||
args[i - 1] = '\0';
|
||||
}
|
||||
}
|
||||
if (quoted && args[i - 1] == '"')
|
||||
args[i - 1] = '\0';
|
||||
|
||||
if (args[i]) {
|
||||
args[i] = '\0';
|
||||
next = args + i + 1;
|
||||
} else
|
||||
next = args + i;
|
||||
|
||||
/* Chew up trailing spaces. */
|
||||
return skip_spaces(next);
|
||||
}
|
||||
|
||||
// CODE FROM LINUX KERNEL STOP
|
||||
|
||||
enum EXEC_MODE {
|
||||
UNDEFINED,
|
||||
GETARG,
|
||||
GETARGS,
|
||||
};
|
||||
|
||||
static void usage(enum EXEC_MODE enumExecMode, int ret, char *msg)
|
||||
{
|
||||
switch (enumExecMode) {
|
||||
case UNDEFINED:
|
||||
fprintf(stderr, "ERROR: 'dracut-util' has to be called via a symlink to the tool name.");
|
||||
break;
|
||||
case GETARG:
|
||||
fprintf(stderr, "ERROR: %s\nUsage: dracut-getarg <KEY>[=[<VALUE>]]\n", msg);
|
||||
break;
|
||||
case GETARGS:
|
||||
fprintf(stderr, "ERROR: %s\nUsage: dracut-getargs <KEY>[=]\n", msg);
|
||||
break;
|
||||
}
|
||||
exit(ret);
|
||||
}
|
||||
|
||||
#define ARGV0_GETARG "dracut-getarg"
|
||||
#define ARGV0_GETARGS "dracut-getargs"
|
||||
|
||||
static enum EXEC_MODE get_mode(const char *argv_0)
|
||||
{
|
||||
struct _mode_table {
|
||||
enum EXEC_MODE mode;
|
||||
const char *arg;
|
||||
size_t arg_len;
|
||||
const char *s_arg;
|
||||
} modeTable[] = {
|
||||
{GETARG, ARGV0_GETARG, sizeof(ARGV0_GETARG), "/" ARGV0_GETARG},
|
||||
{GETARGS, ARGV0_GETARGS, sizeof(ARGV0_GETARGS), "/" ARGV0_GETARGS},
|
||||
{UNDEFINED, NULL, 0, NULL}
|
||||
};
|
||||
int i;
|
||||
|
||||
size_t argv_0_len = strlen(argv_0);
|
||||
|
||||
if (!argv_0_len)
|
||||
return UNDEFINED;
|
||||
|
||||
for (i = 0; modeTable[i].mode != UNDEFINED; i++) {
|
||||
if (argv_0_len == (modeTable[i].arg_len - 1)) {
|
||||
if (strncmp(argv_0, modeTable[i].arg, argv_0_len) == 0) {
|
||||
return modeTable[i].mode;
|
||||
}
|
||||
}
|
||||
|
||||
if (modeTable[i].arg_len > argv_0_len)
|
||||
continue;
|
||||
|
||||
if (strncmp(argv_0 + argv_0_len - modeTable[i].arg_len, modeTable[i].s_arg, modeTable[i].arg_len) == 0)
|
||||
return modeTable[i].mode;
|
||||
}
|
||||
return UNDEFINED;
|
||||
}
|
||||
|
||||
static int getarg(int argc, char **argv)
|
||||
{
|
||||
char *search_key;
|
||||
char *search_value;
|
||||
char *end_value = NULL;
|
||||
bool bool_value = false;
|
||||
char *cmdline = NULL;
|
||||
|
||||
char *p = getenv("CMDLINE");
|
||||
if (p == NULL) {
|
||||
usage(GETARG, EXIT_FAILURE, "CMDLINE env not set");
|
||||
}
|
||||
cmdline = strdup(p);
|
||||
|
||||
if (argc != 2) {
|
||||
usage(GETARG, EXIT_FAILURE, "Number of arguments invalid");
|
||||
}
|
||||
|
||||
search_key = argv[1];
|
||||
|
||||
search_value = strchr(argv[1], '=');
|
||||
if (search_value != NULL) {
|
||||
*search_value = 0;
|
||||
search_value++;
|
||||
if (*search_value == 0)
|
||||
search_value = NULL;
|
||||
}
|
||||
|
||||
if (strlen(search_key) == 0)
|
||||
usage(GETARG, EXIT_FAILURE, "search key undefined");
|
||||
|
||||
do {
|
||||
char *key = NULL, *value = NULL;
|
||||
cmdline = next_arg(cmdline, &key, &value);
|
||||
if (strcmp(key, search_key) == 0) {
|
||||
if (value) {
|
||||
end_value = value;
|
||||
bool_value = -1;
|
||||
} else {
|
||||
end_value = NULL;
|
||||
bool_value = true;
|
||||
}
|
||||
}
|
||||
} while (cmdline[0]);
|
||||
|
||||
if (search_value) {
|
||||
if (end_value && strcmp(end_value, search_value) == 0) {
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (end_value) {
|
||||
// includes "=0"
|
||||
puts(end_value);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
if (bool_value) {
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
static int getargs(int argc, char **argv)
|
||||
{
|
||||
char *search_key;
|
||||
char *search_value;
|
||||
bool found_value = false;
|
||||
char *cmdline = NULL;
|
||||
|
||||
char *p = getenv("CMDLINE");
|
||||
if (p == NULL) {
|
||||
usage(GETARGS, EXIT_FAILURE, "CMDLINE env not set");
|
||||
}
|
||||
cmdline = strdup(p);
|
||||
|
||||
if (argc != 2) {
|
||||
usage(GETARGS, EXIT_FAILURE, "Number of arguments invalid");
|
||||
}
|
||||
|
||||
search_key = argv[1];
|
||||
|
||||
search_value = strchr(argv[1], '=');
|
||||
if (search_value != NULL) {
|
||||
*search_value = 0;
|
||||
search_value++;
|
||||
if (*search_value == 0)
|
||||
search_value = NULL;
|
||||
}
|
||||
|
||||
if (strlen(search_key) == 0)
|
||||
usage(GETARGS, EXIT_FAILURE, "search key undefined");
|
||||
|
||||
do {
|
||||
char *key = NULL, *value = NULL;
|
||||
cmdline = next_arg(cmdline, &key, &value);
|
||||
if (strcmp(key, search_key) == 0) {
|
||||
if (search_value) {
|
||||
if (strcmp(value, search_value) == 0) {
|
||||
printf("%s\n", value);
|
||||
found_value = true;
|
||||
}
|
||||
} else {
|
||||
if (value) {
|
||||
printf("%s\n", value);
|
||||
} else {
|
||||
puts(key);
|
||||
}
|
||||
found_value = true;
|
||||
}
|
||||
}
|
||||
} while (cmdline[0]);
|
||||
return found_value ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
switch (get_mode(argv[0])) {
|
||||
case UNDEFINED:
|
||||
usage(UNDEFINED, EXIT_FAILURE, NULL);
|
||||
break;
|
||||
case GETARG:
|
||||
return getarg(argc, argv);
|
||||
case GETARGS:
|
||||
return getargs(argc, argv);
|
||||
}
|
||||
|
||||
return EXIT_FAILURE;
|
||||
}
|
Loading…
Reference in New Issue