Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 2 Jun 2013 22:04:40 +0000 (UTC)
From:      Devin Teske <dteske@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r251265 - in head/usr.sbin/bsdconfig: . share
Message-ID:  <201306022204.r52M4eYr067556@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: dteske
Date: Sun Jun  2 22:04:39 2013
New Revision: 251265
URL: http://svnweb.freebsd.org/changeset/base/251265

Log:
  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.

Modified:
  head/usr.sbin/bsdconfig/bsdconfig
  head/usr.sbin/bsdconfig/share/common.subr
  head/usr.sbin/bsdconfig/share/dialog.subr

Modified: head/usr.sbin/bsdconfig/bsdconfig
==============================================================================
--- head/usr.sbin/bsdconfig/bsdconfig	Sun Jun  2 20:02:50 2013	(r251264)
+++ head/usr.sbin/bsdconfig/bsdconfig	Sun Jun  2 22:04:39 2013	(r251265)
@@ -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"

Modified: head/usr.sbin/bsdconfig/share/common.subr
==============================================================================
--- head/usr.sbin/bsdconfig/share/common.subr	Sun Jun  2 20:02:50 2013	(r251264)
+++ head/usr.sbin/bsdconfig/share/common.subr	Sun Jun  2 22:04:39 2013	(r251265)
@@ -77,6 +77,33 @@ export UNAME_R="$(uname -r)" # Release L
 #
 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 ))

Modified: head/usr.sbin/bsdconfig/share/dialog.subr
==============================================================================
--- head/usr.sbin/bsdconfig/share/dialog.subr	Sun Jun  2 20:02:50 2013	(r251264)
+++ head/usr.sbin/bsdconfig/share/dialog.subr	Sun Jun  2 22:04:39 2013	(r251265)
@@ -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
 	)



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201306022204.r52M4eYr067556>