I managed to get SHELL=.../zsh in some weird configuration of some unrelated package (m4 on AIX in this case, but I've seen this issue elsewhere and in other packages before), and it caused mdate-sh to loop endlessly, trying to shift nonexistent positional parameters in the hope of finding a date to parse.
This patch fixes both the underlying issue (zsh emulation mode) as well as making the script a bit more robust and reliable wrt. errors. Pushing to maint. Thanks, Ralf Improve robustness of mdate-sh script. * lib/mdate-sh: Sanitize zsh behavior on startup, to ensure $ls_command is word-split properly upon invocation. (error): New function. (main): Use it. Improve error checking to avoid endless loop in case $ls_command gave bogus output. Fix eval quotation. * tests/mdate6.test: New test, to expose eval quotation error. * tests/Makefile.am: Update. diff --git a/lib/mdate-sh b/lib/mdate-sh index c477512..60dc485 100755 --- a/lib/mdate-sh +++ b/lib/mdate-sh @@ -1,7 +1,7 @@ #!/bin/sh # Get modification time of a file or directory and pretty-print it. -scriptversion=2010-02-22.21; # UTC +scriptversion=2010-08-21.06; # UTC # Copyright (C) 1995, 1996, 1997, 2003, 2004, 2005, 2007, 2009, 2010 # Free Software Foundation, Inc. @@ -29,6 +29,15 @@ scriptversion=2010-02-22.21; # UTC # bugs to <bug-autom...@gnu.org> or send patches to # <automake-patches@gnu.org>. +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +fi + case $1 in '') echo "$0: No file. Try \`$0 --help' for more information." 1>&2 @@ -51,6 +60,13 @@ EOF ;; esac +error () +{ + echo "$0: $1" >&2 + exit 1 +} + + # Prevent date giving response in another language. LANG=C export LANG @@ -100,6 +116,7 @@ month= command= until test $month do + test $# -gt 0 || error "failed parsing \`$ls_command /' output" shift # Add another shift to the command. command="$command shift;" @@ -119,8 +136,10 @@ do esac done +test -n "$month" || error "failed parsing \`$ls_command /' output" + # Get the extended ls output of the file or directory. -set dummy x`eval "$ls_command \"\$save_arg1\""` +set dummy x`eval "$ls_command \"\\\$save_arg1\""` # Remove all preceding arguments eval $command diff --git a/tests/Makefile.am b/tests/Makefile.am index 0558149..3ecc341 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -474,6 +474,7 @@ mdate2.test \ mdate3.test \ mdate4.test \ mdate5.test \ +mdate6.test \ missing.test \ missing2.test \ missing3.test \ diff --git a/tests/Makefile.in b/tests/Makefile.in index a06026e..4671ad0 100644 --- a/tests/Makefile.in +++ b/tests/Makefile.in @@ -712,6 +712,7 @@ mdate2.test \ mdate3.test \ mdate4.test \ mdate5.test \ +mdate6.test \ missing.test \ missing2.test \ missing3.test \ diff --git a/tests/mdate6.test b/tests/mdate6.test new file mode 100755 index 0000000..e7f7d69 --- /dev/null +++ b/tests/mdate6.test @@ -0,0 +1,35 @@ +#! /bin/sh +# Copyright (C) 2010 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# mdate-sh can work with weird file names, doesn't eval too much. + +. ./defs || Exit 1 + +set -e + +a= +file='file name $a' +( : > "$file" ) || Exit 77 + +cp "$testsrcdir"/../lib/mdate-sh . +$SHELL ./mdate-sh "$file" >stdout 2>stderr || + { cat stdout; cat stderr >&2; Exit 1; } +cat stdout +cat stderr >&2 +grep '[12][0-9]\{3\}' stdout +test ! -s stderr + +: