* lib/m4sugar/m4sh.m4 (_AS_DETECT_BETTER_SHELL): Always re-execute the current script with $CONFIG_SHELL, if that's set. * tests/m4sh.at: Add tests for the new semantics, in ... (Re-exec with CONFIG_SHELL): ... this new section. * doc/autoconf.texi (config.status Invocation): Update. * doc/install.texi (Defining Variables): Likewise. * NEWS: Likewise. --- ChangeLog | 11 ++++++ doc/autoconf.texi | 11 ++---- doc/install.texi | 6 ++-- lib/m4sugar/m4sh.m4 | 90 +++++++++++++++++++++++++++++++++----------------- tests/m4sh.at | 68 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 145 insertions(+), 41 deletions(-)
diff --git a/ChangeLog b/ChangeLog index e51f7d7..188c394 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2011-11-01 Stefano Lattarini <[email protected]> + + m4sh: always re-exec with $CONFIG_SHELL, if it's set + * lib/m4sugar/m4sh.m4 (_AS_DETECT_BETTER_SHELL): Always re-execute + the current script with $CONFIG_SHELL, if that's set. + * tests/m4sh.at: Add tests for the new semantics, in ... + (Re-exec with CONFIG_SHELL): ... this new section. + * doc/autoconf.texi (config.status Invocation): Update. + * doc/install.texi (Defining Variables): Likewise. + * NEWS: Likewise. + 2011-10-21 Stefano Lattarini <[email protected]> fortran: define $GFC to "yes" if $FC is a GNU compiler diff --git a/doc/autoconf.texi b/doc/autoconf.texi index b6dc67b..5735200 100644 --- a/doc/autoconf.texi +++ b/doc/autoconf.texi @@ -22616,13 +22616,10 @@ can alter its behavior: @anchor{CONFIG_SHELL} @defvar CONFIG_SHELL @evindex CONFIG_SHELL -The shell with which to run @command{configure} for the @option{--recheck} -option. It must be Bourne-compatible. The default is a shell that -supports @code{LINENO} if available, and @file{/bin/sh} otherwise. -Invoking @command{configure} by hand bypasses this setting, so you may -need to use a command like @samp{CONFIG_SHELL=/bin/bash /bin/bash ./configure} -to insure that the same shell is used everywhere. The absolute name of the -shell should be passed. +The shell with which to run @command{configure}. It must be +Bourne-compatible, and the absolute name of the shell should be passed. +The default is a shell that supports @code{LINENO} if available, and +@file{/bin/sh} otherwise. @end defvar @defvar CONFIG_STATUS diff --git a/doc/install.texi b/doc/install.texi index d397b8a..c6a8bdf 100644 --- a/doc/install.texi +++ b/doc/install.texi @@ -364,11 +364,11 @@ overridden in the site shell script). @noindent Unfortunately, this technique does not work for @env{CONFIG_SHELL} due -to an Autoconf bug. Until the bug is fixed you can use this -workaround: +to an Autoconf limitation. Until the limitation is lifted, you can use +this workaround: @example -CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash +CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash @end example @node configure Invocation diff --git a/lib/m4sugar/m4sh.m4 b/lib/m4sugar/m4sh.m4 index 1ff1705..043a2c6 100644 --- a/lib/m4sugar/m4sh.m4 +++ b/lib/m4sugar/m4sh.m4 @@ -178,8 +178,9 @@ m4_define([_AS_DETECT_SUGGESTED_PRUNE], # _AS_DETECT_BETTER_SHELL # ----------------------- -# The real workhorse for detecting a shell with the correct -# features. +# The real workhorse for detecting a shell with the correct features. +# FIXME: this should be split into two macros, one to detect a better +# shell, and one to re-execute with it. # # In previous versions, we prepended /usr/posix/bin to the path, but that # caused a regression on OpenServer 6.0.0 @@ -220,42 +221,69 @@ dnl Remove any tests from suggested that are also required esac], [AS_IF([{ test -f "$SHELL" || test -f "$SHELL.exe"; } && _AS_RUN(["$as_required"], ["$SHELL"])], - [CONFIG_SHELL=$SHELL as_have_required=yes])]) - - AS_IF([test "x$CONFIG_SHELL" != x], - [# We cannot yet assume a decent shell, so we have to provide a - # neutralization value for shells without unset; and this also - # works around shells that cannot unset nonexistent variables. - # Preserve -v and -x to the replacement shell. - BASH_ENV=/dev/null - ENV=/dev/null - (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV - export CONFIG_SHELL - case $- in @%:@ (((( - *v*x* | *x*v* ) as_opts=-vx ;; - *v* ) as_opts=-v ;; - *x* ) as_opts=-x ;; - * ) as_opts= ;; - esac - exec "$CONFIG_SHELL" $as_opts "$as_myself" ${1+"$[@]"}]) - -dnl Unfortunately, $as_me isn't available here. - AS_IF([test x$as_have_required = xno], - [AS_ECHO(["$[]0: This script requires a shell more modern than all"]) - AS_ECHO(["$[]0: the shells that I found on your system."]) - if test x${ZSH_VERSION+set} = xset ; then - AS_ECHO(["$[]0: In particular, zsh $ZSH_VERSION has bugs and should"]) - AS_ECHO(["$[]0: be upgraded to zsh 4.3.4 or later."]) + [CONFIG_SHELL=$SHELL as_have_required=yes])])]) + + if test "x$CONFIG_SHELL" != x; then + : We have found a good-enough or better shell, we will re-execute + : ourselves with it soon. + elif test x$as_have_required = xyes; then + : The current shell is good enough. else - AS_ECHO("m4_text_wrap([Please tell ]_m4_defn([m4_PACKAGE_BUGREPORT]) + : Just give up. + # Unfortunately, $as_me isn't available here, so we just use $0. + AS_ECHO(["$[]0: This script requires a shell more modern than all"]) + AS_ECHO(["$[]0: the shells that I found on your system."]) + if test x${ZSH_VERSION+set} = xset ; then + AS_ECHO(["$[]0: In particular, zsh $ZSH_VERSION has bugs and should"]) + AS_ECHO(["$[]0: be upgraded to zsh 4.3.4 or later."]) + else + AS_ECHO("m4_text_wrap([Please tell ]_m4_defn([m4_PACKAGE_BUGREPORT]) m4_ifset([AC_PACKAGE_BUGREPORT], [m4_if(_m4_defn([m4_PACKAGE_BUGREPORT]), _m4_defn([AC_PACKAGE_BUGREPORT]), [], [and _m4_defn([AC_PACKAGE_BUGREPORT])])]) [about your system, including any error possibly output before this message. Then install a modern shell, or manually run the script under such a shell if you do have one.], [$[]0: ], [], [62])") - fi - AS_EXIT])]) + fi + AS_EXIT + fi # No good-enough shell found. + +fi # $CONFIG_SHELL not pre-set by the user. + +# We might have to re-execute the current script, either because the +# current shell is not good enough, or a better shell has been found, +# or the user has pre-set $CONFIG_SHELL in the environment. +# Use a proper internal environment variable to ensure we don't fall +# into an infinite loop, continuously re-executing ourselves. +if test x"${_ac_no_reexec}" = x && test "x$CONFIG_SHELL" != x; then + # We cannot yet assume a decent shell, so we have to provide a + # neutralization value for shells without unset; and this also + # works around shells that cannot unset nonexistent variables. + # Preserve -v and -x to the replacement shell. + BASH_ENV=/dev/null + ENV=/dev/null + (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV + export CONFIG_SHELL + case $- in @%:@ (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; + esac + _ac_no_reexec=yes; export _ac_no_reexec; + exec "$CONFIG_SHELL" $as_opts "$as_myself" ${1+"$[@]"} + # In case the user has done a typo in the setting of $CONFIG_SHELL. + # Admittedly, this is quite paranoid, since all the known shells bail + # out after a failed `exec'. + AS_ECHO(["$[]0: could not re-execute with $CONFIG_SHELL"]) >&2 + AS_EXIT([255]) fi +# We don't want this to propagate to other subprocesses. +dnl This might be especially important in case an m4sh-generated script +dnl is used to later execute other m4sh-generated scripts. This happens +dnl for example in autoconf's own testsuite (and happens *a lot* there, +dnl in fact). +AS_UNSET([_ac_no_reexec]) + SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. diff --git a/tests/m4sh.at b/tests/m4sh.at index a5ef905..4fa26d1 100644 --- a/tests/m4sh.at +++ b/tests/m4sh.at @@ -17,6 +17,74 @@ AT_BANNER([M4sh.]) # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. +## --------------------------- ## +## Re-exec with CONFIG_SHELL. ## +## --------------------------- ## + +AT_SETUP([Re-exec with CONFIG_SHELL]) +AT_KEYWORDS([CONFIG_SHELL]) + +AT_DATA_M4SH([script.as], +[[AS_INIT +echo foo > sentinel +]]) +AT_CHECK_M4SH + +AT_DATA([fake-shell], +[[#!/bin/sh +echo 'Fake shell executed.' +shift # fake shell +echo "nargs = @S|@#" +for i +do + printf ' :%s:\n' "$i" +done +]]) +chmod a+x fake-shell + +AT_CHECK([CONFIG_SHELL=./fake-shell ./script 1 2 4 8], [0], +[Fake shell executed. +nargs = 4 + :1: + :2: + :4: + :8: +], []) +AT_CHECK([test ! -f sentinel], [0]) +test ! -f sentinel || rm -f sentinel # Cleanup for next test. + +AT_CHECK( +[CONFIG_SHELL=`pwd`/fake-shell sh script a 'b c' ' d e '], +[0], +[Fake shell executed. +nargs = 3 + :a: + :b c: + : d e : +], []) +AT_CHECK([test ! -f sentinel], [0]) +test ! -f sentinel || rm -f sentinel # Cleanup for next test. + +AT_CHECK([(PATH=`pwd`:$PATH; export PATH; +CONFIG_SHELL=fake-shell script '' '&' '!;*' '<($[]@%:@)>,' 'x +y z +1 2 3')], [0], +[Fake shell executed. +nargs = 5 + :: + :&: + :!;*: + :<($[]@%:@)>,: + :x +y z +1 2 3: +], []) +AT_CHECK([test ! -f sentinel], [0]) +test ! -f sentinel || rm -f sentinel # Cleanup for next test. + +AT_CLEANUP + + ## ------------------- ## ## AS_WARN, AS_ERROR. ## ## ------------------- ## -- 1.7.2.3
