From f7a9af7f49d267d084e47fab6853c81ad65f09e9 Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Wed, 8 Sep 2010 22:24:22 +0200 Subject: [PATCH] init.sh: penalize a set-x-impaired shell; don't disqualify it * tests/init.sh: Too many shells corrupt application stderr when you set -x, so we can't afford to disqualify them, since at least on Irix-6.5, that would disqualify all bourne shells. Instead, use a more discerning approach. When iterating through candidate shells, give each a score of 10 for perfect, 9 if corrupts stderr upon set -x but passes all other tests, and some other value if it is unacceptable. Use the first shell that gets a score of 10. If no shell scores 10, use the first that scored 9. Finally, when VERBOSE=yes is requested and set -x might cause trouble, simply issue a warning and refrain from enabling debug output. --- ChangeLog | 14 ++++++++ tests/init.sh | 105 ++++++++++++++++++++++++++++++++++++++++++---------------- 2 files changed, 90 insertions(+), 29 deletions(-) diff --git a/ChangeLog b/ChangeLog index 82937ac73..2ac4e0001 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2010-09-08 Jim Meyering + + init.sh: penalize a set-x-impaired shell; don't disqualify it + * tests/init.sh: Too many shells corrupt application stderr when + you set -x, so we can't afford to disqualify them, since at least + on Irix-6.5, that would disqualify all bourne shells. + Instead, use a two-pass approach. + On the first pass, try to find a shell that meets the stricter + condition that set -x does not corrupt stderr. + If no shell meets the stricter condition, retest each candidate + shell, but without that extra condition. Finally, when + VERBOSE=yes is requested and set -x might cause trouble, simply + issue a warning and refrain from enabling debug output. + 2010-09-08 Eric Blake unsetenv: fix OpenBSD bug diff --git a/tests/init.sh b/tests/init.sh index 9886a8da6..c5d19610d 100644 --- a/tests/init.sh +++ b/tests/init.sh @@ -109,48 +109,84 @@ fi # Use "9" to indicate success (rather than 0), in case some shell acts # like Solaris 10's /bin/sh but exits successfully instead of with status 2. +# Eval this code in a subshell to determine a shell's suitability. +# 10 - passes all tests; ok to use +# 9 - ok, but enabling "set -x" corrupts application stderr; prefer higher score +# ? - not ok gl_shell_test_script_=' test $(echo y) = y || exit 1 -test -z "$( (exec 3>&1; set -x; P=1 true 2>&3) 2> /dev/null)" || exit 1 -test -z "$EXEEXT" && exit 9 +score_=10 +if test "$VERBOSE" = yes; then + test -n "$( (exec 3>&1; set -x; P=1 true 2>&3) 2> /dev/null)" && score_=9 +fi +test -z "$EXEEXT" && exit $score_ shopt -s expand_aliases alias a-b="echo zoo" v=abx test ${v%x} = ab \ && test ${v#a} = bx \ && test $(a-b) = zoo \ - && exit 9 + && exit $score_ ' if test "x$1" = "x--no-reexec"; then shift else - # 'eval'ing the above code makes Solaris 10's /bin/sh exit with $? set to 2. - # It does not evaluate any of the code after the "unexpected" `('. Thus, - # we must run it in a subshell. - ( eval "$gl_shell_test_script_" ) > /dev/null 2>&1 - if test $? = 9; then - : # The current shell is adequate. No re-exec required. - else - # Search for a shell that meets our requirements. - for re_shell_ in "${CONFIG_SHELL:-no_shell}" /bin/sh bash dash zsh pdksh fail - do - test "$re_shell_" = no_shell && continue - test "$re_shell_" = fail && skip_ failed to find an adequate shell + # Assume a working shell. Export to subshells (setup_ needs this). + gl_set_x_corrupts_stderr_=false + export gl_set_x_corrupts_stderr_ + + # Record the first marginally acceptable shell. + marginal_= + + # Search for a shell that meets our requirements. + for re_shell_ in __current__ "${CONFIG_SHELL:-no_shell}" \ + /bin/sh bash dash zsh pdksh fail + do + test "$re_shell_" = no_shell && continue + + # If we've made it all the way to the sentinel, "fail" without + # finding even a marginal shell, skip this test. + if test "$re_shell_" = fail; then + test -z "$marginal_" && skip_ failed to find an adequate shell + re_shell_=$marginal_ + break + fi + + # When testing the current shell, simply "eval" the test code. + # Otherwise, run it via $re_shell_ -c ... + if test "$re_shell_" = __current__; then + # 'eval'ing this code makes Solaris 10's /bin/sh exit with + # $? set to 2. It does not evaluate any of the code after the + # "unexpected" first `('. Thus, we must run it in a subshell. + ( eval "$gl_shell_test_script_" ) > /dev/null 2>&1 + else "$re_shell_" -c "$gl_shell_test_script_" 2>/dev/null - if test $? = 9; then - # Found an acceptable shell. Preserve -v and -x. - case $- in - *v*x* | *x*v*) opts_=-vx ;; - *v*) opts_=-v ;; - *x*) opts_=-x ;; - *) opts_= ;; - esac - exec "$re_shell_" $opts_ "$0" --no-reexec "$@" - echo "$ME_: exec failed" 1>&2 - exit 127 - fi - done + fi + + st_=$? + + # $re_shell_ works just fine. Use it. + test $st_ = 10 && break + + # If this is our first marginally acceptable shell, remember it. + if test "$st_:$marginal_" = 9: ; then + marginal_="$re_shell_" + gl_set_x_corrupts_stderr_=true + fi + done + + if test "$re_shell_" != __current__; then + # Found a usable shell. Preserve -v and -x. + case $- in + *v*x* | *x*v*) opts_=-vx ;; + *v*) opts_=-v ;; + *x*) opts_=-x ;; + *) opts_= ;; + esac + exec "$re_shell_" $opts_ "$0" --no-reexec "$@" + echo "$ME_: exec failed" 1>&2 + exit 127 fi fi @@ -269,7 +305,18 @@ path_prepend_() setup_() { - test "$VERBOSE" = yes && set -x + if test "$VERBOSE" = yes; then + # Test whether set -x may cause the selected shell to corrupt an + # application's stderr. Many do, including zsh-4.3.10 and the /bin/sh + # from SunOS 5.11, OpenBSD 4.7 and Irix 5.x and 6.5. + # If enabling verbose output this way would cause trouble, simply + # issue a warning and refrain. + if $gl_set_x_corrupts_stderr_; then + warn_ "using SHELL=$SHELL with 'set -x' corrupts stderr" + else + set -x + fi + fi initial_cwd_=$PWD -- 2.11.0