From ffa71b4afa3e8865ab4f068f908ff8e05744a6ee Mon Sep 17 00:00:00 2001 From: Harald Hoyer Date: Tue, 3 Jul 2012 14:20:51 +0200 Subject: [PATCH] dracut.sh: use getopt to parse arguments now we can put options and arguments anywhere we like. e.g. $ dracut test.img --force --- dracut.sh | 233 ++++++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 169 insertions(+), 64 deletions(-) diff --git a/dracut.sh b/dracut.sh index 4a6d5c7..c1be619 100755 --- a/dracut.sh +++ b/dracut.sh @@ -24,7 +24,7 @@ # # store for logging -dracut_args="$@" +dracut_args=( "$@" ) set -o pipefail @@ -36,7 +36,32 @@ usage() { # 80x25 linebreak here ^ cat << EOF -Usage: $0 [OPTION]... +Usage: $0 [OPTION]... [ []] + +Version: $DRACUT_VERSION + +Creates initial ramdisk images for preloading modules + + -h, --help Display all options + +If a [LIST] has multiple arguments, then you have to put these in quotes. + +For example: + + # dracut --add-drivers "module1 module2" ... + +EOF +} + +long_usage() { + [[ $dracutbasedir ]] || dracutbasedir=/usr/lib/dracut + if [[ -f $dracutbasedir/dracut-version.sh ]]; then + . $dracutbasedir/dracut-version.sh + fi + +# 80x25 linebreak here ^ + cat << EOF +Usage: $0 [OPTION]... [ []] Version: $DRACUT_VERSION @@ -139,8 +164,11 @@ Creates initial ramdisk images for preloading modules --sshkey [SSHKEY] Add ssh key to initramfs (use with ssh-client module) If [LIST] has multiple arguments, then you have to put these in quotes. + For example: -# dracut --add-drivers "module1 module2" ... + + # dracut --add-drivers "module1 module2" ... + EOF } @@ -151,9 +179,10 @@ EOF # example: # push stack 1 2 "3 4" push() { + local _i local __stack=$1; shift - for i in "$@"; do - eval ${__stack}'[${#'${__stack}'[@]}]="$i"' + for _i in "$@"; do + eval ${__stack}'[${#'${__stack}'[@]}]="$_i"' done } @@ -169,16 +198,16 @@ push() { pop() { local __stack=$1; shift local __resultvar=$1 - local myresult; + local _value; # check for empty stack eval '[[ ${#'${__stack}'[@]} -eq 0 ]] && return 1' - eval myresult='${'${__stack}'[${#'${__stack}'[@]}-1]}' + eval _value='${'${__stack}'[${#'${__stack}'[@]}-1]}' if [[ "$__resultvar" ]]; then - eval $__resultvar="'$myresult'" + eval $__resultvar="'$_value'" else - echo "$myresult" + echo "$_value" fi eval unset ${__stack}'[${#'${__stack}'[@]}-1]' return 0 @@ -202,52 +231,105 @@ read_arg() { fi } -# Little helper function for reading args from the commandline to a stack. -# it automatically handles -a b and -a=b variants, and returns 1 if -# we need to shift $3. -push_arg() { - # $1 = arg name - # $2 = arg value - # $3 = arg parameter - local rematch='^[^=]*=(.*)$' - if [[ $2 =~ $rematch ]]; then - push "$1" "${BASH_REMATCH[1]}" - else - push "$1" "$3" - # There is no way to shift our callers args, so - # return 1 to indicate they should do it instead. - return 1 - fi -} - verbosity_mod_l=0 unset kernel unset outfile -while (($# > 0)); do - case ${1%%=*} in - -a|--add) push_arg add_dracutmodules_l "$@" || shift;; - --force-add) push_arg force_add_dracutmodules_l "$@" || shift;; - --add-drivers) push_arg add_drivers_l "$@" || shift;; - --omit-drivers) push_arg omit_drivers_l "$@" || shift;; - -m|--modules) push_arg dracutmodules_l "$@" || shift;; - -o|--omit) push_arg omit_dracutmodules_l "$@" || shift;; - -d|--drivers) push_arg drivers_l "$@" || shift;; - --filesystems) push_arg filesystems_l "$@" || shift;; - -I|--install) push_arg install_items_l "$@" || shift;; - --fwdir) push_arg fw_dir_l "$@" || shift;; - --libdirs) push_arg libdirs_l "$@" || shift;; - --fscks) push_arg fscks_l "$@" || shift;; - --add-fstab) push_arg add_fstab_l "$@" || shift;; - --mount) push_arg fstab_lines "$@" || shift;; +# Workaround -i, --include taking 2 arguments +set -- "${@/--include/++include}" + +# This prevents any long argument ending with "-i" +# -i, like --opt-i but I think we can just prevent that +set -- "${@/%-i/++include}" + +TEMP=$(unset POSIXLY_CORRECT; getopt \ + -o "a:m:o:d:I:k:c:L:fvqlHhM" \ + --long add: \ + --long force-add: \ + --long add-drivers: \ + --long omit-drivers: \ + --long modules: \ + --long omit: \ + --long drivers: \ + --long filesystems: \ + --long install: \ + --long fwdir: \ + --long libdirs: \ + --long fscks: \ + --long add-fstab: \ + --long mount: \ + --long nofscks: \ + --long kmoddir: \ + --long conf: \ + --long confdir: \ + --long tmpdir: \ + --long stdlog: \ + --long compress: \ + --long prefix: \ + --long force \ + --long kernel-only \ + --long no-kernel \ + --long strip \ + --long nostrip \ + --long hardlink \ + --long nohardlink \ + --long noprefix \ + --long mdadmconf \ + --long nomdadmconf \ + --long lvmconf \ + --long nolvmconf \ + --long debug \ + --long profile \ + --long sshkey: \ + --long verbose \ + --long quiet \ + --long local \ + --long hostonly \ + --long no-hostonly \ + --long fstab \ + --long help \ + --long bzip2 \ + --long lzma \ + --long xz \ + --long no-compress \ + --long gzip \ + --long list-modules \ + --long show-modules \ + --long keep \ + --long printsize \ + -- "$@") + +if (( $? != 0 )); then + usage + exit 1 +fi + +eval set -- "$TEMP" + +while :; do + case $1 in + -a|--add) push add_dracutmodules_l "$2"; shift;; + --force-add) push force_add_dracutmodules_l "$2"; shift;; + --add-drivers) push add_drivers_l "$2"; shift;; + --omit-drivers) push omit_drivers_l "$2"; shift;; + -m|--modules) push dracutmodules_l "$2"; shift;; + -o|--omit) push omit_dracutmodules_l "$2"; shift;; + -d|--drivers) push drivers_l "$2"; shift;; + --filesystems) push filesystems_l "$2"; shift;; + -I|--install) push install_items_l "$2"; shift;; + --fwdir) push fw_dir_l "$2"; shift;; + --libdirs) push libdirs_l "$2"; shift;; + --fscks) push fscks_l "$2"; shift;; + --add-fstab) push add_fstab_l "$2"; shift;; + --mount) push fstab_lines "$2"; shift;; --nofscks) nofscks_l="yes";; - -k|--kmoddir) read_arg drivers_dir_l "$@" || shift;; - -c|--conf) read_arg conffile "$@" || shift;; - --confdir) read_arg confdir "$@" || shift;; - --tmpdir) read_arg tmpdir_l "$@" || shift;; - -L|--stdlog) read_arg stdloglvl_l "$@" || shift;; - --compress) read_arg compress_l "$@" || shift;; - --prefix) read_arg prefix_l "$@" || shift;; + -k|--kmoddir) drivers_dir_l="$2"; shift;; + -c|--conf) conffile="$2"; shift;; + --confdir) confdir="$2"; shift;; + --tmpdir) tmpdir_l="$2"; shift;; + -L|--stdlog) stdloglvl_l="$2"; shift;; + --compress) compress_l="$2"; shift;; + --prefix) prefix_l="$2"; shift;; -f|--force) force=yes;; --kernel-only) kernel_only="yes"; no_kernel="no";; --no-kernel) kernel_only="no"; no_kernel="yes";; @@ -262,7 +344,7 @@ while (($# > 0)); do --nolvmconf) lvmconf_l="no";; --debug) debug="yes";; --profile) profile="yes";; - --sshkey) read_arg sshkey "$@" || shift;; + --sshkey) sshkey="$2"; shift;; -v|--verbose) ((verbosity_mod_l++));; -q|--quiet) ((verbosity_mod_l--));; -l|--local) @@ -273,48 +355,67 @@ while (($# > 0)); do -H|--hostonly) hostonly_l="yes" ;; --no-hostonly) hostonly_l="no" ;; --fstab) use_fstab_l="yes" ;; - -h|--help) usage; exit 1 ;; + -h|--help) long_usage; exit 1 ;; -i|--include) push include_src "$2" - push include_target "$3" - shift 2;; + shift;; --bzip2) compress_l="bzip2";; --lzma) compress_l="lzma";; --xz) compress_l="xz";; --no-compress) _no_compress_l="cat";; --gzip) compress_l="gzip";; - --list-modules) - do_list="yes"; - ;; + --list-modules) do_list="yes";; -M|--show-modules) show_modules_l="yes" ;; --keep) keep="yes";; --printsize) printsize="yes";; - -*) printf "\nUnknown option: %s\n\n" "$1" >&2; usage; exit 1;; + + --) shift; break;; + + *) # should not even reach this point + printf "\n!Unknown option: '%s'\n\n" "$1" >&2; usage; exit 1;; + esac + shift +done + +# getopt cannot handle multiple arguments, so just handle "-I,--include" +# the old fashioned way + +while (($# > 0)); do + case ${1%%=*} in + ++include) push include_src "$2" + push include_target "$3" + shift 2;; *) if ! [[ ${outfile+x} ]]; then outfile=$1 elif ! [[ ${kernel+x} ]]; then kernel=$1 else - echo "Unknown argument: $1" + printf "\nUnknown arguments: %s\n\n" "$*" >&2 usage; exit 1; fi ;; esac shift done + if ! [[ $kernel ]]; then kernel=$(uname -r) fi -[[ $outfile ]] || outfile="/boot/initramfs-$kernel.img" + +if ! [[ $outfile ]]; then + outfile="/boot/initramfs-$kernel.img" +fi for i in /usr/sbin /sbin /usr/bin /bin; do rl=$i if [ -L "$i" ]; then rl=$(readlink -f $i) fi - NPATH+=":$rl" + if [[ "$NPATH" != "*:$rl*" ]] ; then + NPATH+=":$rl" + fi done export PATH="${NPATH#:}" unset NPATH @@ -536,8 +637,12 @@ done omit_drivers="${omit_drivers_corrected%|}" unset omit_drivers_corrected - -ddebug "Executing $0 $dracut_args" +# prepare args for logging +for ((i=0; i < ${#dracut_args[@]}; i++)); do + strstr "${dracut_args[$i]}" " " && \ + dracut_args[$i]="\"${dracut_args[$i]}\"" +done +ddebug "Executing: $0 ${dracut_args[@]}" [[ $do_list = yes ]] && { for mod in $dracutbasedir/modules.d/*; do @@ -573,7 +678,7 @@ if [[ ! -d "$outdir" ]]; then dfatal "Can't write $outfile: Directory $outdir does not exist." exit 1 elif [[ ! -w "$outdir" ]]; then - dfatal "No permission to write $outdir." + dfatal "No permission to write to $outdir." exit 1 elif [[ -f "$outfile" && ! -w "$outfile" ]]; then dfatal "No permission to write $outfile."