diff --git a/frontend/lb b/frontend/lb index 137867be2..1d8b89ab6 100755 --- a/frontend/lb +++ b/frontend/lb @@ -19,25 +19,14 @@ DESCRIPTION="Utility to build live systems" HELP="" USAGE="lb {clean|config|build}" -case "${1}" in - -h|--help) - if [ $(which man) ]; then - man lb - else - Usage - fi - exit 0 - ;; +# Handle options up to any command +# We replace the arg set with any remaining args on return +Arguments frontend "${@}" +eval set -- "${REMAINING_ARGS}" - ""|-u|--usage) - Usage - ;; - - -v|--version) - echo "${VERSION}" - exit 0 - ;; -esac +if [ -z "${1}" ]; then + Usage +fi COMMAND="${1}" shift diff --git a/functions/arguments.sh b/functions/arguments.sh index 4f6105649..a8dd33251 100755 --- a/functions/arguments.sh +++ b/functions/arguments.sh @@ -11,23 +11,84 @@ Arguments () { + # This function is used for handling arguments both at the frontend (`lb`) + # level and at the command level, since both accept almost the same basic + # argument set, with little difference in response to them. + # + # We enlist the help of getopt here which takes care of some of the + # intricacies of parsing for us. Note that getopt does not itself + # understand the concept of "command" arguments, and the behaviour of it + # shuffling non-options (those arguments that are not options or option + # values) to the end of the argument list would present a difficulty, if it + # were not for the fact that you can control this behaviour with use of the + # `POSIXLY_CORRECT` environment variable; setting this variable causes + # getopt to stop parsing arguments once it encounters the first non-option, + # treating all remaining arguments as being non-options. Note also that + # getopt always outputs a `--` separator argument between option (including + # option value) arguments and non-option arguments. + # + # At the frontend we need getopt to only parse options up to the point of + # a command. A command as far as getopt is concerned is simply a + # "non-option" argument. Using the above mentioned `POSIXLY_CORRECT` + # environment variable when parsing for the frontend, we can thus have + # getopt process options up to the first non-option, if given, which should + # be our command. We can then pass back any remaining arguments including + # the command argument, for a second command-stage handling. If no command + # is given, this is trivial to handle. If an invalid option is used before + # a command, this is caught by getopt. + # + # When a command is run, it is passed all remaining arguments, with most + # scripts then passing them to this function, with argument parsing then + # occurring in command-context, which just so happens to use almost the same + # set of arguments for most scripts (the config command is a notable + # exception). + # + # It is true that many of the common options have no effect in the frontend + # currently, but some do, such as colour control, and others could do in + # future or during development. + # + # Note, do not worry about options unavailable in frontend mode being + # handled in the case statement, they will never reach there if used for the + # frontend (i.e. before a command), they will result in an invalid option + # error! + + local LONGOPTS="breakpoints,color,debug,help,no-color,quiet,usage,verbose,version" + local SHORTOPTS="huv" + + local IS_FRONTEND="false" + if [ "${1}" = "frontend" ]; then + shift + IS_FRONTEND="true" + else + LONGOPTS="${LONGOPTS},force" + fi + + local GETOPT_ARGS="--name=${PROGRAM} --shell sh --longoptions $LONGOPTS --options $SHORTOPTS" + local ARGUMENTS local ERR=0 - ARGUMENTS="$(getopt --longoptions breakpoints,color,debug,force,help,no-color,quiet,usage,verbose,version --name=${PROGRAM} --options huv --shell sh -- "${@}")" || ERR=$? + if [ "${IS_FRONTEND}" = "true" ]; then + ARGUMENTS="$(export POSIXLY_CORRECT=1; getopt $GETOPT_ARGS -- "${@}")" || ERR=$? + else + ARGUMENTS="$(getopt $GETOPT_ARGS -- "${@}")" || ERR=$? + fi if [ $ERR -eq 1 ]; then - Echo_error "invalid arguments" + Echo_error "Invalid argument(s)" exit 1 elif [ $ERR -ne 0 ]; then Echo_error "getopt failure" exit 1 fi + # Replace arguments with result of getopt processing (e.g. with non-options shuffled to end) + # Note that this only affects this function's parameter set, not the calling function's or + # calling script's argument set. eval set -- "${ARGUMENTS}" - while true - do - case "${1}" in + local ARG + for ARG in "$@"; do + case "${ARG}" in --breakpoints) _BREAKPOINTS="true" shift @@ -58,8 +119,16 @@ Arguments () ;; -h|--help) - Man - shift + if [ $(which man) ]; then + if [ "${IS_FRONTEND}" = "true" ]; then + man ${PROGRAM} + else + man ${PROGRAM} $(basename ${0}) + fi + exit 0 + elif [ "${IS_FRONTEND}" = "true" ]; then + Usage + fi ;; --quiet) @@ -88,9 +157,17 @@ Arguments () ;; *) - Echo_error "internal error %s" "${0}" + if [ "${IS_FRONTEND}" = "true" ]; then + # We have handled all frontend options up to what we assume to be a command + break + fi + Echo_error "Internal error, unhandled option: %s" "${ARG}" exit 1 ;; esac done + + # Return remaining args + # Much more simple than trying to deal with command substitution. + REMAINING_ARGS="$@" } diff --git a/functions/init.sh b/functions/init.sh index 1fbbd9308..c9927492e 100755 --- a/functions/init.sh +++ b/functions/init.sh @@ -25,7 +25,14 @@ Auto_build_config () Init_config_data () { + # Here we ignore the consumption of option arguments, we would have to return REMAINING_ARGS + # for use in a `set -- $REMAINING_ARGS` (or `eval set -- "$REMAINING_ARGS"`) if we wanted to + # remove them from the set of args for calling scripts to make use of, in which case we might + # as well just move use of the function out of here. Note that currently scripts taking args + # like `$_PASS` do so as the first arg to the script, thus then just ignore any following + # option args (and capture them before arg processing takes place). Arguments "${@}" + unset REMAINING_ARGS Read_conffiles $(Common_config_files) Prepare_config diff --git a/functions/man.sh b/functions/man.sh deleted file mode 100755 index 06b51a7d4..000000000 --- a/functions/man.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/sh - -## live-build(7) - System Build Scripts -## Copyright (C) 2016-2020 The Debian Live team -## Copyright (C) 2006-2015 Daniel Baumann -## -## This program comes with ABSOLUTELY NO WARRANTY; for details see COPYING. -## This is free software, and you are welcome to redistribute it -## under certain conditions; see COPYING for details. - - -Man () -{ - if [ $(which man) ] - then - man ${PROGRAM} $(basename ${0}) - exit 0 - fi -} diff --git a/scripts/build/config b/scripts/build/config index 05239eae6..9805e2af0 100755 --- a/scripts/build/config +++ b/scripts/build/config @@ -179,7 +179,7 @@ Local_arguments () ARGUMENTS="$(getopt --longoptions ${LONG_OPTIONS} --name="${PROGRAM}" --options a:d:m:k:b:s:c:huv --shell sh -- "${@}")" || ERR=$? if [ $ERR -eq 1 ]; then - Echo_error "invalid arguments" + Echo_error "Invalid argument(s)" exit 1 elif [ $ERR -ne 0 ]; then Echo_error "getopt failure"