Fix option processing from the library layer to address unexpected

behavior(s); e.g., `-Xd' versus `-dX' did not produce the same results.

The libraries common.subr and dialog.subr automatically process the
arguments passed to the program and enable/disable functionality without the
need to process the arguments within your program. For example, if "$@"
contains `-d', common.subr will see this and enable debugging regardless of
whether you process "$@" yourself or not (this automatic processing can
easily be disabled for custom scripts that don't want it; see the afore-
mentioned scripts for additional details).

NOTE: common.subr stores a copy of "$@" in $ARGV for convenient (and
repeated) processing by libraries such as dialog.subr which provide such
transparent functionality for the consuming script(s).

However, the libraries don't know if a program wants to accept `extra'
options. Flags are not really a problem, because the library can be
programmed to silently ignore unknown flags. The trouble comes into play
when the program wants to define an option that takes an argument.

For example:

	bsdconfig -D logfile -X

In the above example, the library uses getopts to process $ARGV and if it
doesn't know that `-D' takes an argument, the option processing will
prematurely terminate on `logfile' (this is standard/correct behavior for
getopts but is undesired in our situation where we have partially off-loaded
main argument processing).

The problem is solved by allowing the program to define an extra set of
options to be included in each library's handling of $ARGV. Only options
that require arguments are truly necessary to be pre-specified in this new
manner.
This commit is contained in:
dteske 2013-06-02 22:04:39 +00:00
parent e9cea34539
commit 9d0ce61896
3 changed files with 50 additions and 6 deletions

View File

@ -29,6 +29,21 @@
#
############################################################ INCLUDES
# When common.subr is included, it automatically scans "$@" for `-d' and/or
# `-D file' arguments to conditionally enable debugging. Similarly, when
# dialog.subr is included, it automatically scans "$@" for `-X' and/or `-S'.
# To prevent this scanning from becoming confused by extra options, define
# any/all extra arguments to use in the optstring to getopts when scanning
# for dedicated options such as those described.
#
# NOTE: This needs to be declared before including `common.subr'.
# NOTE: You really only need to list flags that require an argument as unknown
# flags are silently accepted unless they take an argument (in which case
# the following argument will terminate option processing unless it looks
# like a flag).
#
GETOPTS_EXTRA="f:"
BSDCFG_SHARE="/usr/share/bsdconfig"
. $BSDCFG_SHARE/common.subr || exit 1
f_dprintf "%s: loading includes..." "$0"

View File

@ -77,6 +77,33 @@ export UNAME_R="$(uname -r)" # Release Level (i.e. X.Y-RELEASE)
#
GETOPTS_STDARGS="dD:"
#
# The getopts builtin will return 1 either when the end of "$@" or the first
# invalid flag is reached. This makes it impossible to determine if you've
# processed all the arguments or simply have hit an invalid flag. In the cases
# where we want to tolerate invalid flags (f_debug_init() for example), the
# following variable can be appended to your optstring argument to getopts,
# preventing it from prematurely returning 1 before the end of the arguments.
#
# NOTE: This assumes that all unknown flags are argument-less.
#
GETOPTS_ALLFLAGS="abcdefghijklmnopqrstuvwxyz"
GETOPTS_ALLFLAGS="${GETOPTS_ALLFLAGS}ABCDEFGHIJKLMNOPQRSTUVWXYZ"
GETOPTS_ALLFLAGS="${GETOPTS_ALLFLAGS}0123456789"
#
# When we get included, f_debug_init() will fire (unless $DEBUG_SELF_INITIALIZE
# is set to disable automatic initialization) and process "$@" for a few global
# options such as `-d' and/or `-D file'. However, if your program takes custom
# flags that take arguments, this automatic processing may fail unexpectedly.
#
# The solution to this problem is to pre-define (before including this file)
# the following variable (which defaults to NULL) to indicate that there are
# extra flags that should be considered when performing automatic processing of
# globally persistent flags.
#
: ${GETOPTS_EXTRA:=}
############################################################ FUNCTIONS
# f_dprintf $fmt [ $opts ... ]
@ -114,11 +141,11 @@ f_debug_init()
local OPTIND
f_dprintf "f_debug_init: ARGV=[%s] GETOPTS_STDARGS=[%s]" \
"$ARGV" "$GETOPTS_STDARGS"
while getopts "$GETOPTS_STDARGS" flag > /dev/null; do
while getopts "$GETOPTS_STDARGS$GETOPTS_EXTRA$GETOPTS_ALLFLAGS" flag \
> /dev/null; do
case "$flag" in
d) debug=1;;
D) debugFile="$OPTARG";;
\?) continue;;
esac
done
shift $(( $OPTIND - 1 ))

View File

@ -1970,18 +1970,20 @@ f_dialog_init()
f_dprintf "f_dialog_init: ARGV=[%s] GETOPTS_STDARGS=[%s]" \
"$ARGV" "$GETOPTS_STDARGS"
SECURE=$( set -- $ARGV
while getopts "$GETOPTS_STDARGS" flag > /dev/null; do
while getopts \
"$GETOPTS_STDARGS$GETOPTS_EXTRA$GETOPTS_ALLFLAGS" \
flag > /dev/null; do
case "$flag" in
S) echo 1;;
\?) continue;;
esac
done
)
USE_XDIALOG=$( set -- $ARGV
while getopts $GETOPTS_STDARGS flag > /dev/null; do
while getopts \
"$GETOPTS_STDARGS$GETOPTS_EXTRA$GETOPTS_ALLFLAGS" \
flag > /dev/null; do
case "$flag" in
S|X) echo 1;;
\?) continue;;
esac
done
)