autoconf
[Top][All Lists]
Advanced

[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],




reply via email to

[Prev in Thread] Current Thread [Next in Thread]