[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH] Shell selection bug fixes
From: |
Eric Sunshine |
Subject: |
[PATCH] Shell selection bug fixes |
Date: |
Wed, 7 Jan 2004 17:08:55 -0500 |
Hello,
Here is a patch which corrects several problems with the way the Autoconf
CVS version of AS_SHELL_SANITIZE attempts to locate a usable shell. The
patch address the following issues.
* New heuristic for choosing a suitable shell. Now selects a more
functional shell over less functional shells. Prefers a shell supporting both
functions and LINENO. If no such shell is found, then prefers a shell
supporting functions (>2.59 behavior); else, if that fails, prefers one
supporting LINENO (<=2.59 behavior). It first consults the already running
shell; then consults SHELL if necessary; and, finally, performs a more
exhaustive search if needed. This heuristic fixes the broken behavior of
>2.59 where it could prefer highly crippled ancient shells over more modern
shells.
* Fixed bug where the invalid assumption was made that SHELL was the same as
the shell running the script. This is frequently not the case. It would
test if SHELL supported functions, and then erroneously apply the result of
that test to the currently running shell. This could lead to it believing
that the running shell supported functions even if it did not; and, worse, it
would prefer this non-function-supporting shell over other more functional
shells.
* Fixed bug where logic was reversed for reporting that function-supporting
shell could not be found. It reported failure when it did find a useful
shell; and neglected to report failure when it did not find a shell.
The patch looks somewhat lengthy, but this is largely due to the fact that I
had to refactor some existing code, and because I reformatted some code
which did not adhere to the formatting of the rest of the file. The actual
new code is relatively minimal, and is contained mostly in the new macro
_AS_SHELL_BEST() which implements the new search heuristic, plus a few small
supporting macros.
Eric
2004-01-07 Eric Sunshine <address@hidden>
* lib/m4sugar/m4sh.m4 (AS_SHELL_SANITIZE): New heuristic for choosing
best shell with which to run script. Now chooses most functional
shell. Specifically, prefers a shell which implements functions and
LINENO, rather than preferring a shell which provides only LINENO
(Autoconf <=2.59 behavior) or a shell which provides only functions
(>2.59). If it fails to find a shell supplying all desired features,
then it falls back to the >2.59 behavior (if a suitable shell is
found), else it falls back to the <=2.59 behavior. This fixes the
problem in Autoconf >2.59 in which it could choose less functional
shells over more functional shells. For example, on NextStep, the
factory-supplied /bin/sh is highly crippled and slow, yet it supports
functions, though it does not support LINENO. Even with a modern
version of Bash installed, the >2.59 behavior would choose the ancient
/bin/sh simply because it was the first shell encountered supporting
functions. The new heuristic correctly chooses the modern Bash since
it provides all of the facilities desired in a shell, rather than
choosing the ancient /bin/sh which provides only a subset.
(AS_SHELL_SANITIZE): Fixed bug where logic for choosing
function-supporting shell incorrectly assumed that SHELL was the shell
actually running the script. This frequently is not the case. For
instance, SHELL imported from the environment might be
/usr/local/bin/bash, whereas the script is being run by /bin/sh (on
account of the #!/bin/sh). The bogus logic tested SHELL for function
support and then incorrectly applied the result of that test to the
currently running shell.
(AS_SHELL_SANITIZE): Fixed bug where logic was reversed for reporting
that function-supporting shell could not be found. It reported failure
when it did find a useful shell; and neglected to report failure when
it did not find a shell.
(_AS_SHELL_BEST): New macro. Attempt to locate suitable shell via the
following heuristic: Prefer a shell which provides functions and
LINENO; else prefer a shell which provides functions; else prefer a
shell which provides LINENO. It first checks the currently running
shell; if that fails, it checks SHELL; finally, if that fails, it
performs an exhaustive search.
(_AS_SHELL_FN_SUPPORTED): New macro. Check if currently running shell
supports functions.
(_AS_SHELL_FN_SUPPORTED_FOR_SHELL): New macro. Check if the specified
shell supports functions.
(_AS_SHELL_FN_WORKS): New macro. Workhorse for _AS_SHELL_FN_SUPPORTED
and _AS_SHELL_FN_SUPPORTED_FOR_SHELL. This is a refactored version of
the old _AS_SHELL_FN_WORK.
(_AS_LINENO_WORKS_FOR_SHELL): New macro. Checks if the specified shell
supports LINENO. This complements the existing _AS_LINENO_WORKS which
checks if the currently running shell supports LINENO.
(AS_VAR_SET_DEFAULT): New macro. Sets a variable to a given value iff
the variable is not already set.
--- lib/m4sugar/m4sh.m4 Wed Jan 7 13:58:34 2004
+++ lib/m4sugar/m4sh.m4-fix Wed Jan 7 14:10:04 2004
@@ -167,56 +167,146 @@
])
-# _AS_SHELL_FN_WORK(TESTED-SHELL)
-# --------------------------------------------------
-# This is a spy to detect "in the wild" shells that do not support shell
-# functions correctly. It is based on the m4sh.at Autotest testcases.
-m4_define([_AS_SHELL_FN_WORK],
-[{ $1 2>/dev/null <<\_ASEOF
-_AS_BOURNE_COMPATIBLE
-func_return () {
+# _AS_SHELL_FN_WORKS([SUPPORTED], [NOT-SUPPORTED])
+# ------------------------------------------------
+# Helper macro for testing if functions are supported. Invokes SUPPORTED if
+# functions are supported; else invokes NOT-SUPPORTED.
+m4_define([_AS_SHELL_FN_WORKS],
+[func_return () {
(exit [$]1)
}
-
func_success () {
func_return 0
}
-
func_failure () {
func_return 1
}
-
func_ret_success () {
return 0
}
-
func_ret_failure () {
return 1
}
-exitcode=0
-AS_IF([func_success], [], [
- exitcode=1
- echo func_failure succeeded.
-])
-AS_IF([func_failure], [
- exitcode=1
- echo func_success failed.
-])
-AS_IF([func_ret_success], [], [
- exitcode=1
- echo func_ret_success failed.
-])
-AS_IF([func_ret_failure], [
- exitcode=1
- echo func_ret_failure succeeded.
-])
-AS_EXIT($exitcode)
+as_fn_exitcode=0
+AS_IF([func_success], [],
+ [as_fn_exitcode=1
+ echo 'func_failure() succeeded.'])
+AS_IF([func_failure],
+ [as_fn_exitcode=1
+ echo 'func_success() failed.'])
+AS_IF([func_ret_success], [],
+ [as_fn_exitcode=1
+ echo 'func_ret_success() failed.'])
+AS_IF([func_ret_failure],
+ [as_fn_exitcode=1
+ echo 'func_ret_failure() succeeded.'])
+
+AS_IF([test $as_fn_exitcode -eq 0],
+ m4_ifval([$1], [$1], [:]),
+ m4_ifval([$2], [$2], [:]))
+])# _AS_SHELL_FN_WORKS
+
+
+# _AS_SHELL_FN_SUPPORTED
+# ----------------------
+# Succeed if the currently executing shell supports functions. The macro can
+# be used with && and ||.
+# Example: _AS_SHELL_FN_SUPPORTED([/bin/sh]) && as_functions=yes
+m4_define([_AS_SHELL_FN_SUPPORTED],
+[(_AS_BOURNE_COMPATIBLE
+_AS_SHELL_FN_WORKS([as_fn_exitcode=0], [as_fn_exitcode=1])
+AS_EXIT([$as_fn_exitcode])
+)])# _AS_SHELL_FN_SUPPORTED
+
+
+# _AS_SHELL_FN_SUPPORTED_FOR_SHELL(SHELL)
+# ---------------------------------------
+# Succeed if shell SHELL supports functions. The macro can be used with &&
+# and ||.
+# Example: _AS_SHELL_FN_SUPPORTED_FOR_SHELL([/bin/sh]) && as_functions=yes
+m4_define([_AS_SHELL_FN_SUPPORTED_FOR_SHELL],
+[{ $1 2>/dev/null <<\_ASEOF
+_AS_BOURNE_COMPATIBLE
+_AS_SHELL_FN_WORKS([as_fn_exitcode=0], [as_fn_exitcode=1])
+AS_EXIT([$as_fn_exitcode])
_ASEOF
-}])
+}])# _AS_SHELL_FN_WORK
-# AS_SHELL_SANITIZE(WHAT-IF-SHELL-FUNCTIONS-DO-NOT-WORK)
-# ------------------------------------------------------
+
+# _AS_SHELL_BEST([ACTION-RUNNING], [ACTION-NOT-RUNNING], [ACTION-NO-SHELL-FN])
+# ----------------------------------------------------------------------------
+# Attempt to locate a usable shell. Prefer more featureful shells over less
+# featureful shells. The very best shell supports all desired features. If
+# the best shell is already running this script, then ACTION-RUNNING is
+# invoked. If the best shell is not already running, then the variable
+# `as_shell_best' is set to the path of the best shell and ACTION-NOT-RUNNING
+# is invoked.
+#
+# If no function-supporting shell is found, then ACTION-NO-SHELL-FN is also
+# invoked (prior to the invocation of either of the other two actions). This
+# action might be used, for instance, to emit a diagnostic message.
+#
+# Current heuristic: Prefer a shell which supports both functions and LINENO.
+# If no such shell is found, prefer a shell which supports functions; else
+# prefer a shell which supports LINENO.
+m4_define([_AS_SHELL_BEST],
+[# Check currently executing shell.
+_AS_SHELL_FN_SUPPORTED && as_shell_func=x
+_AS_LINENO_WORKS && as_shell_lineno=x
+
+AS_IF([test -z "$as_shell_func" || test -z "$as_shell_lineno"],
+ [# Currently executing is not the "best" shell, so check $SHELL and others.
+ as_shell_candidates="$SHELL"
+ _AS_PATH_WALK([/bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH],
+ [for as_base in sh bash ksh sh5; do
+ case $as_dir in
+ /*) as_shell_candidates="$as_shell_candidates $as_dir/$as_base" ;;
+ esac
+ done])
+
+ for as_shell in $as_shell_candidates; do
+ as_found_func=''
+ as_found_lineno=''
+ _AS_SHELL_FN_SUPPORTED_FOR_SHELL([$as_shell]) && as_found_func="$as_shell"
+ _AS_LINENO_WORKS_FOR_SHELL([$as_shell]) && as_found_lineno="$as_shell"
+
+ AS_IF([test -n "$as_found_func" && test -n "$as_found_lineno"],
+ [# Found a shell which supports all desired features.
+ as_shell_func="$as_found_func"
+ as_shell_lineno="$as_found_lineno"
+ break])
+
+ # Else, remember if this shell supports a feature (if no other shell does).
+ AS_IF([test -n "$as_found_func"],
+ [AS_VAR_SET_DEFAULT([as_shell_func], ["$as_found_func"])])
+ AS_IF([test -n "$as_found_lineno"],
+ [AS_VAR_SET_DEFAULT([as_shell_lineno], ["$as_found_lineno"])])
+ done])
+
+m4_ifval([$3],
+[# Failed to find a function-supporting shell?
+AS_IF([test -z "$as_shell_func"], [$3])])
+
+# Best shell supports all features; else prefer functions over LINENO.
+AS_IF([test "$as_shell_func" = "$as_shell_lineno"],
+ [as_shell_best="$as_shell_func"],
+ [AS_IF([test -n "$as_shell_func"],
+ [as_shell_best="$as_shell_func"],
+ [as_shell_best="$as_shell_lineno"])])
+
+# If best shell is "x", then that is the shell already running; if best shell
+# is empty then we failed to find a decent shell, so make do with already
+# running shell; else, best shell is some other shell.
+case $as_shell_best in
+ x|'') m4_default([$1]) ;;
+ *) m4_default([$2]) ;;
+esac
+])# _AS_SHELL_BEST
+
+
+# AS_SHELL_SANITIZE(ACTION-NO-SHELL-FN)
+# -------------------------------------
# The parameter is temporary; it will go away and you
# should not rely on it.
m4_defun([AS_SHELL_SANITIZE],
@@ -248,27 +338,15 @@
AS_ERROR([cannot find myself; rerun with an absolute path])
fi
-dnl In the future, the `else' branch will be that in AS_INIT_WITH_SHELL_FN.
-AS_IF([_AS_SHELL_FN_WORK([$SHELL])], [], [
- case $CONFIG_SHELL in
- '')
- _AS_PATH_WALK([/bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH],
- [for as_base in sh bash ksh sh5; do
- case $as_dir in
- /*)
- AS_IF([_AS_SHELL_FN_WORK([$as_dir/$as_base])], [
- AS_UNSET(BASH_ENV)
- AS_UNSET(ENV)
- CONFIG_SHELL=$as_dir/$as_base
- export CONFIG_SHELL
- exec "$CONFIG_SHELL" "$as_myself" ${1+"address@hidden"}
- ]);;
- esac
- done]);;
- *)
- $1;;
- esac
-])
+# Find the most desirable shell for running this script.
+AS_IF([test -z "$CONFIG_SHELL"],
+ [_AS_SHELL_BEST([],
+ [AS_UNSET([BASH_ENV])
+ AS_UNSET([ENV])
+ CONFIG_SHELL=$as_shell_best
+ export CONFIG_SHELL
+ exec "$CONFIG_SHELL" "$as_myself" ${1+"address@hidden"}],
+ [$1])])
# Work around bugs in pre-3.0 UWIN ksh.
$as_unset ENV MAIL MAILPATH
@@ -625,19 +703,32 @@
])# _AS_EXPR_PREPARE
# _AS_LINENO_WORKS
-# ---------------
+# ----------------
# Succeed if the currently executing shell supports LINENO.
# This macro does not expand to a single shell command, so be careful
# when using it. Surrounding the body of this macro with {} would
# cause "bash -c '_ASLINENO_WORKS'" to fail (with Bash 2.05, anyway),
-# but that bug is irrelevant to our use of LINENO.
+# but that bug is irrelevant to our use of LINENO. The macro can be
+# used with && and ||. Example: _AS_LINENO_WORKS || as_emulate_lineno=yes
m4_define([_AS_LINENO_WORKS],
-[
- as_lineno_1=$LINENO
- as_lineno_2=$LINENO
- as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
- test "x$as_lineno_1" != "x$as_lineno_2" &&
- test "x$as_lineno_3" = "x$as_lineno_2"])
+[as_lineno_1=$LINENO
+as_lineno_2=$LINENO
+as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+test "x$as_lineno_1" != "x$as_lineno_2" &&
+test "x$as_lineno_3" = "x$as_lineno_2"])
+# _AS_LINENO_WORKS
+
+# _AS_LINENO_WORKS_FOR_SHELL(SHELL)
+# ---------------------------------
+# Succeed if shell SHELL supports LINENO. The macro can be used with &&
+# and ||. Example: _AS_LINENO_WORKS_FOR_SHELL([/bin/sh]) && as_has_lineno=yes
+m4_define([_AS_LINENO_WORKS_FOR_SHELL],
+[{ $1 2>/dev/null <<\_ASEOF
+_AS_LINENO_WORKS
+exitcode=$?
+AS_EXIT([$exitcode])
+_ASEOF
+}])# _AS_LINENO_WORKS_FOR_SHELL
# _AS_LINENO_PREPARE
# ------------------
@@ -1114,6 +1205,14 @@
[eval "$1=AS_ESCAPE([$2])"])])
+# AS_VAR_SET_DEFAULT(VARIABLE, VALUE)
+# -----------------------------------
+# Set the VALUE of the shell VARIABLE iff VARIABLE is not already set.
+# Polymorphic.
+m4_define([AS_VAR_SET_DEFAULT],
+ [AS_VAR_SET_IF([$1], [], [AS_VAR_SET([$1], [$2])])])
+
+
# AS_VAR_GET(VARIABLE)
# --------------------
# Get the value of the shell VARIABLE.
@@ -1194,8 +1293,8 @@
## ----------------- ##
-# AS_INIT(WHAT-IF-SHELL-FUNCTIONS-DO-NOT-WORK)
-# --------------------------------------------
+# AS_INIT(ACTION-NO-SHELL-FN)
+# ---------------------------
# The parameter is temporary; it will go away and you
# should not rely on it.
m4_define([AS_INIT],
- [PATCH] Shell selection bug fixes,
Eric Sunshine <=