]> git.ipfire.org Git - thirdparty/autoconf.git/commitdiff
Proper file name escaping in Autoconf programs and Perl modules.
authorRalf Wildenhues <Ralf.Wildenhues@gmx.de>
Sat, 8 Dec 2007 10:46:43 +0000 (11:46 +0100)
committerRalf Wildenhues <Ralf.Wildenhues@gmx.de>
Sat, 8 Dec 2007 10:46:43 +0000 (11:46 +0100)
This includes escaping of characters special to the shell
as well as special to Perl, e.g., leading `<' or `>'.
For example, when $file starts with `>', `open ">$file"'
wrongly tries to append to a different file.

* bin/autoconf.as: Fix quoting for autom4te options.
* lib/Autom4te/General.pm (shell_quote): New function, taken
from coreutils, written by Jim Meyering.
(mktmpdir): Use it.
* bin/autom4te.in (files_to_options, handle_m4): Use shell_quote
and open_quote.
* bin/autoreconf.in (parse_args): Likewise.
* bin/autoscan.in (main): Likewise.
* bin/autoupdate.in (main): Likewise.
* bin/autoheader.in: Likewise, fixing old insufficient escaping.
* bin/ifnames.in: Likewise, XFile usage fixes.
* tests/tools.at (autom4te and whitespace in file names): Extend
test.  Test twice, with special characters allowed on w32, and the
rest.  Test leading and trailing whitespace, for `open_quote'.
(autotools and whitespace in file names): New, analogous test.
Reported by Paul Eggert and Benoit Sigoure, additional suggestions
by Russ Allbery and Eric Blake.

ChangeLog
bin/autoconf.as
bin/autoheader.in
bin/autom4te.in
bin/autoreconf.in
bin/autoscan.in
bin/autoupdate.in
bin/ifnames.in
lib/Autom4te/General.pm
tests/tools.at

index 5d49b2cd619c4db2584d1074b6009fe148bf2df7..9b86bc4ad4027af64b03429cba8693808131d08d 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,28 @@
 2007-12-08  Ralf Wildenhues  <Ralf.Wildenhues@gmx.de>
 
+       Proper file name escaping in Autoconf programs and Perl modules.
+       This includes escaping of characters special to the shell
+       as well as special to Perl, e.g., leading `<' or `>'.
+       For example, when $file starts with `>', `open ">$file"'
+       wrongly tries to append to a different file.
+       * bin/autoconf.as: Fix quoting for autom4te options.
+       * lib/Autom4te/General.pm (shell_quote): New function, taken
+       from coreutils, written by Jim Meyering.
+       (mktmpdir): Use it.
+       * bin/autom4te.in (files_to_options, handle_m4): Use shell_quote
+       and open_quote.
+       * bin/autoreconf.in (parse_args): Likewise.
+       * bin/autoscan.in (main): Likewise.
+       * bin/autoupdate.in (main): Likewise.
+       * bin/autoheader.in: Likewise, fixing old insufficient escaping.
+       * bin/ifnames.in: Likewise, XFile usage fixes.
+       * tests/tools.at (autom4te and whitespace in file names): Extend
+       test.  Test twice, with special characters allowed on w32, and the
+       rest.  Test leading and trailing whitespace, for `open_quote'.
+       (autotools and whitespace in file names): New, analogous test.
+       Reported by Paul Eggert and Benoit Sigoure, additional suggestions
+       by Russ Allbery and Eric Blake.
+
        Sync from Automake.
        * lib/Autom4te/Channels.pm, lib/Autom4te/Configure_ac.pm,
        lib/Autom4te/Struct.pm, lib/Autom4te/XFile.pm: Likewise.
index b68d4ef607d00c8d0bbe8a2b5281fae0cbac6ecc..dbabc308b139369444b53d0492966eceae2c3385 100644 (file)
@@ -107,14 +107,21 @@ while test $# -gt 0 ; do
     --include=*  | -I?* | \
     --prepend-include=* | -B?* | \
     --warnings=* | -W?* )
-       autom4te_options="$autom4te_options '$1'"; shift ;;
-
+       case $1 in
+         *\'*) arg=`AS_ECHO(["$1"]) | sed "s/'/'\\\\\\\\''/g"` ;;
+        *) arg=$1 ;;
+       esac
+       autom4te_options="$autom4te_options '$arg'"; shift ;;
     # Options with separated arg passed as is to autom4te.
     --include  | -I | \
     --prepend-include  | -B | \
     --warnings | -W )
        test $# = 1 && eval "$exit_missing_arg"
-       autom4te_options="$autom4te_options $option '$2'"
+       case $2 in
+         *\'*) arg=`AS_ECHO(["$2"]) | sed "s/'/'\\\\\\\\''/g"` ;;
+        *) arg=$2 ;;
+       esac
+       autom4te_options="$autom4te_options $option '$arg'"
        shift; shift ;;
 
     --trace=* | -t?* )
@@ -178,8 +185,8 @@ esac
 test -z "$outfile" && outfile=-
 
 # Run autom4te with expansion.
-eval set x $autom4te_options \
-  --language=autoconf --output=\$outfile "$traces" \$infile
+eval set x "$autom4te_options" \
+  --language=autoconf --output=\"\$outfile\" "$traces" \"\$infile\"
 shift
 $verbose && AS_ECHO(["$as_me: running $AUTOM4TE $*"]) >&2
 exec "$AUTOM4TE" "$@"
index 9c19ea3a263d43fe50d1c764c6b29ff8691b3c12..2565db21099cd0aa08b95e63bfa98e05a3ce5baf 100644 (file)
@@ -157,8 +157,8 @@ END
 
 # Set up autoconf.
 my $autoconf = "'$autom4te' --language=autoconf ";
-$autoconf .= join (' ', map { "--include='$_'" } @include);
-$autoconf .= join (' ', map { "--prepend-include='$_'" } @prepend_include);
+$autoconf .= join (' --include=', '', map { shell_quote ($_) } @include);
+$autoconf .= join (' --prepend-include=', '', map { shell_quote ($_) } @prepend_include);
 $autoconf .= ' --debug' if $debug;
 $autoconf .= ' --force' if $force;
 $autoconf .= ' --verbose' if $verbose;
@@ -169,16 +169,17 @@ $autoconf .= ' --verbose' if $verbose;
 
 # Source what the traces are trying to tell us.
 verb "$me: running $autoconf to trace from $ARGV[0]";
+my $quoted_tmp = shell_quote ($tmp);
 xsystem ("$autoconf"
         # If you change this list, update the
         # `Autoheader-preselections' section of autom4te.in.
         . ' --trace AC_CONFIG_HEADERS:\'$$config_h ||= \'"\'"\'$1\'"\'"\';\''
         . ' --trace AH_OUTPUT:\'$$verbatim{\'"\'"\'$1\'"\'"\'} = \'"\'"\'$2\'"\'"\';\''
         . ' --trace AC_DEFINE_TRACE_LITERAL:\'$$symbol{\'"\'"\'$1\'"\'"\'} = 1;\''
-        . " $ARGV[0] >$tmp/traces.pl");
+        . " " . shell_quote ($ARGV[0]) . " >$quoted_tmp/traces.pl");
 
 local (%verbatim, %symbol);
-debug "$me: \`do'ing $tmp/traces.pl:\n" . `sed 's/^/| /' $tmp/traces.pl`;
+debug "$me: \`do'ing $tmp/traces.pl:\n" . `sed 's/^/| /' $quoted_tmp/traces.pl`;
 do "$tmp/traces.pl";
 warn "couldn't parse $tmp/traces.pl: $@" if $@;
 unless ($config_h)
@@ -197,7 +198,7 @@ $config_h_in ||= "$config_h.in";
 # only the name of the macro.
 %symbol = map { s/\(.*//; $_ => 1 } keys %symbol;
 
-my $out = new Autom4te::XFile (">$tmp/config.hin");
+my $out = new Autom4te::XFile ("> " . open_quote ("$tmp/config.hin"));
 
 # Don't write "do not edit" -- it will get copied into the
 # config.h, which it's ok to edit.
@@ -206,7 +207,7 @@ print $out "/* $config_h_in.  Generated from $ARGV[0] by autoheader.  */\n";
 # Dump the top.
 if ($config_h_top)
   {
-    my $in = new Autom4te::XFile ($config_h_top);
+    my $in = new Autom4te::XFile ("< " . open_quote ($config_h_top));
     while ($_ = $in->getline)
       {
        print $out $_;
@@ -216,7 +217,7 @@ if ($config_h_top)
 # Dump `acconfig.h', except for its bottom portion.
 if ($acconfig_h)
   {
-    my $in = new Autom4te::XFile ($acconfig_h);
+    my $in = new Autom4te::XFile ("< " . open_quote ($acconfig_h));
     while ($_ = $in->getline)
       {
        last if /\@BOTTOM\@/;
@@ -234,7 +235,7 @@ foreach (sort keys %verbatim)
 # Dump bottom portion of `acconfig.h'.
 if ($acconfig_h)
   {
-    my $in = new Autom4te::XFile ($acconfig_h);
+    my $in = new Autom4te::XFile ("< " . open_quote ($acconfig_h));
     my $dump = 0;
     while ($_ = $in->getline)
       {
@@ -246,7 +247,7 @@ if ($acconfig_h)
 # Dump the bottom.
 if ($config_h_bot)
   {
-    my $in = new Autom4te::XFile ($config_h_bot);
+    my $in = new Autom4te::XFile ("< " . open_quote ($config_h_bot));
     while ($_ = $in->getline)
       {
        print $out $_;
@@ -257,7 +258,7 @@ $out->close;
 
 # Check that all the symbols have a template.
 {
-  my $in = new Autom4te::XFile ("$tmp/config.hin");
+  my $in = new Autom4te::XFile ("< " . open_quote ("$tmp/config.hin"));
   my $suggest_ac_define = 1;
   while ($_ = $in->getline)
     {
index b273b9a08f6c4166ae079937e44a2f0a1d9a53d1..8efe537a46620028be59a4c4ed821785bfce81d6 100644 (file)
@@ -235,14 +235,10 @@ sub files_to_options (@)
   my @res;
   foreach my $file (@file)
     {
-      (my $arg = $file) =~ s/'/'\\''/g;
+      my $arg = shell_quote ($file);
       if ($file =~ /\.m4f$/)
        {
-         $arg = "--reload-state=$file";
-       }
-      if ($file =~ /[\t "'\\\$()]/)
-       {
-         $arg = "'$arg'";
+         $arg = "--reload-state=$arg";
        }
       push @res, $arg;
     }
@@ -258,7 +254,7 @@ sub load_configuration ($)
   my ($file) = @_;
   use Text::ParseWords;
 
-  my $cfg = new Autom4te::XFile ($file);
+  my $cfg = new Autom4te::XFile ("< " . open_quote ($file));
   my $lang;
   while ($_ = $cfg->getline)
     {
@@ -462,13 +458,13 @@ sub handle_m4 ($@)
   # We don't output directly to the cache files, to avoid problems
   # when we are interrupted (that leaves corrupted files).
   xsystem ("$m4"
-          . join (' --include=', '', @include)
+          . join (' --include=', '', map { shell_quote ($_) } @include)
           . ' --debug=aflq'
           . (!exists $ENV{'AUTOM4TE_NO_FATAL'} ? ' --fatal-warning' : '')
-          . " @M4_DEBUGFILE@=$tcache" . $req->id . "t"
+          . " @M4_DEBUGFILE@=" . shell_quote ("$tcache" . $req->id . "t")
           . join (' --trace=',   '', sort @macro)
           . " " . files_to_options (@ARGV)
-          . " >$ocache" . $req->id . "t");
+          . " > " . shell_quote ("$ocache" . $req->id . "t"));
 
   # Everything went ok: preserve the outputs.
   foreach my $file (map { $_ . $req->id } ($tcache, $ocache))
@@ -526,7 +522,7 @@ sub handle_output ($$)
   handle_traces ($req, "$tmp/patterns",
                 ('m4_pattern_forbid' => 'forbid:$1:$2',
                  'm4_pattern_allow'  => 'allow:$1'));
-  my @patterns = new Autom4te::XFile ("$tmp/patterns")->getlines;
+  my @patterns = new Autom4te::XFile ("< " . open_quote ("$tmp/patterns"))->getlines;
   chomp @patterns;
   my %forbidden =
     map { /^forbid:([^:]+):.+$/ => /^forbid:[^:]+:(.+)$/ } @patterns;
@@ -553,7 +549,7 @@ sub handle_output ($$)
     }
   fatal "cannot create $output: $!"
     unless $out;
-  my $in = new Autom4te::XFile ($ocache . $req->id);
+  my $in = new Autom4te::XFile ("< " . open_quote ($ocache . $req->id));
 
   my %prohibited;
   my $res;
@@ -594,7 +590,7 @@ sub handle_output ($$)
   if ($ARGV[$#ARGV] ne '-')
     {
       my $prohibited = '\b(' . join ('|', keys %prohibited) . ')\b';
-      my $file = new Autom4te::XFile ($ARGV[$#ARGV]);
+      my $file = new Autom4te::XFile ("< " . open_quote ($ARGV[$#ARGV]));
 
       while ($_ = $file->getline)
        {
@@ -712,7 +708,7 @@ sub handle_traces ($$%)
   verb "formatting traces for `$output': " . join (', ', sort keys %trace);
 
   # Processing the traces.
-  my $trace_m4 = new Autom4te::XFile (">$tmp/traces.m4");
+  my $trace_m4 = new Autom4te::XFile ("> " . open_quote ("$tmp/traces.m4"));
 
   $_ = <<'EOF';
   divert(-1)
@@ -816,7 +812,7 @@ EOF
   #
   # Pay attention that the file name might include colons, if under DOS
   # for instance, so we don't use `[^:]+'.
-  my $traces = new Autom4te::XFile ($tcache . $req->id);
+  my $traces = new Autom4te::XFile ("< " . open_quote ($tcache . $req->id));
   while ($_ = $traces->getline)
     {
       # Trace with arguments, as the example above.  We don't try
@@ -831,8 +827,8 @@ EOF
     }
   $trace_m4->close;
 
-  my $in = new Autom4te::XFile ("$m4 $tmp/traces.m4 |");
-  my $out = new Autom4te::XFile (">$output");
+  my $in = new Autom4te::XFile ("$m4 " . shell_quote ("$tmp/traces.m4") . " |");
+  my $out = new Autom4te::XFile ("> " . open_quote ($output));
 
   # This is dubious: should we really transform the quadrigraphs in
   # traces?  It might break balanced [ ] etc. in the output.  The
@@ -892,7 +888,7 @@ sub up_to_date ($)
   handle_traces ($req, "$tmp/dependencies",
                 ('include'    => '$1',
                  'm4_include' => '$1'));
-  my $deps = new Autom4te::XFile ("$tmp/dependencies");
+  my $deps = new Autom4te::XFile ("< " . open_quote ("$tmp/dependencies"));
   while ($_ = $deps->getline)
     {
       chomp;
@@ -925,7 +921,7 @@ sub freeze ($)
   # output but comments and empty lines.
   my $result = xqx ("$m4"
                    . ' --fatal-warning'
-                   . join (' --include=', '', @include)
+                   . join (' --include=', '', map { shell_quote ($_) } @include)
                    . ' --define=divert'
                    . " " . files_to_options (@ARGV)
                    . ' </dev/null');
@@ -939,8 +935,8 @@ sub freeze ($)
   # or an improper paren etc.
   xsystem ("$m4"
           . ' --fatal-warning'
-          . join (' --include=', '', @include)
-          . " --freeze-state=$output"
+          . join (' --include=', '', map { shell_quote ($_) } @include)
+          . " --freeze-state=" . shell_quote ($output)
           . " " . files_to_options (@ARGV)
           . ' </dev/null');
 }
index c964b031753d306567fd8aa6aa18891d373110ff..e7074466dff1cf3dcc4ab8ca49c0c46d1728ed98 100644 (file)
@@ -182,10 +182,10 @@ sub parse_args ()
 
   # Dispatch autoreconf's option to the tools.
   # --include;
-  $autoconf   .= join (' --include=', '', @include);
-  $autoconf   .= join (' --prepend-include=', '', @prepend_include);
-  $autoheader .= join (' --include=', '', @include);
-  $autoheader .= join (' --prepend-include=', '', @prepend_include);
+  $autoconf   .= join (' --include=', '', map { shell_quote ($_) } @include);
+  $autoconf   .= join (' --prepend-include=', '', map { shell_quote ($_) } @prepend_include);
+  $autoheader .= join (' --include=', '', map { shell_quote ($_) } @include);
+  $autoheader .= join (' --prepend-include=', '', map { shell_quote ($_) } @prepend_include);
 
   # --install and --symlink;
   if ($install)
@@ -316,7 +316,7 @@ sub autoreconf_current_directory ()
   my $uses_gettext;
   if (-f $configure_ac)
     {
-      my $configure_ac_file = new Autom4te::XFile $configure_ac;
+      my $configure_ac_file = new Autom4te::XFile "< $configure_ac";
       while ($_ = $configure_ac_file->getline)
        {
          s/#.*//;
index 372a8788e5be3e498926f1e41371b01219b0395e..59227e2644e9cc5b18d569a973d243751b70e186 100644 (file)
@@ -166,7 +166,7 @@ sub init_tables ()
   # instead of duplicating the code in lots of configure.ac files.
   my $file = find_file ("autoscan/autoscan.list",
                        reverse (@prepend_include), @include);
-  my $table = new Autom4te::XFile $file;
+  my $table = new Autom4te::XFile "< " . open_quote ($file);
   my $tables_are_consistent = 1;
 
   while ($_ = $table->getline)
@@ -241,7 +241,7 @@ sub scan_c_file ($)
   # Nonzero if in a multiline comment.
   my $in_comment = 0;
 
-  my $file = new Autom4te::XFile "<$file_name";
+  my $file = new Autom4te::XFile "< " . open_quote ($file_name);
 
   while ($_ = $file->getline)
     {
@@ -307,7 +307,7 @@ sub scan_makefile ($)
   my ($file_name) = @_;
   push @makefiles, $File::Find::name;
 
-  my $file = new Autom4te::XFile "<$file_name";
+  my $file = new Autom4te::XFile "< " . open_quote ($file_name);
 
   while ($_ = $file->getline)
     {
@@ -349,7 +349,7 @@ sub scan_sh_file ($)
   my ($file_name) = @_;
   push @shfiles, $File::Find::name;
 
-  my $file = new Autom4te::XFile "<$file_name";
+  my $file = new Autom4te::XFile "< " . open_quote ($file_name);
 
   while ($_ = $file->getline)
     {
@@ -518,7 +518,7 @@ sub output ($)
   my $configure_scan = shift;
   my %unique_makefiles;
 
-  my $file = new Autom4te::XFile ">$configure_scan";
+  my $file = new Autom4te::XFile "> " . open_quote ($configure_scan);
 
   print $file
     ("#                                               -*- Autoconf -*-\n" .
@@ -587,7 +587,7 @@ sub check_configure_ac ($)
 
   verb "running: $autoconf $trace_option $configure_ac";
   my $traces =
-    new Autom4te::XFile "$autoconf $trace_option $configure_ac|";
+    new Autom4te::XFile "$autoconf $trace_option $configure_ac |";
 
   while ($_ = $traces->getline)
     {
@@ -636,12 +636,12 @@ sub check_configure_ac ($)
 ## -------------- ##
 
 parse_args;
-$log = new Autom4te::XFile ">$me.log";
+$log = new Autom4te::XFile "> " . open_quote ("$me.log");
 
 $autoconf .= " --debug" if $debug;
 $autoconf .= " --verbose" if $verbose;
-$autoconf .= join (' --include=', '', @include);
-$autoconf .= join (' --prepend-include=', '', @prepend_include);
+$autoconf .= join (' --include=', '', map { shell_quote ($_) } @include);
+$autoconf .= join (' --prepend-include=', '', map { shell_quote ($_) } @prepend_include);
 
 my $configure_ac = find_configure_ac;
 init_tables;
index d69211d6c192b3b0263c1ddcdbadd2aa21f77be7..23060f2958cc1b8133e8098c471d2e79502ebb23 100644 (file)
@@ -127,8 +127,8 @@ my (%ac_macros, %au_macros, %m4_builtins);
 sub handle_autoconf_macros ()
 {
   # Get the builtins.
-  xsystem ("echo dumpdef | $m4 2>$tmp/m4.defs >/dev/null");
-  my $m4_defs = new Autom4te::XFile "$tmp/m4.defs";
+  xsystem ("echo dumpdef | $m4 2>" . shell_quote ("$tmp/m4.defs") . " >/dev/null");
+  my $m4_defs = new Autom4te::XFile "< " . open_quote ("$tmp/m4.defs");
   while ($_ = $m4_defs->getline)
     {
       $m4_builtins{$1} = 1
@@ -184,9 +184,9 @@ sub handle_autoconf_macros ()
 
   # ac.m4 -- autoquoting definitions of the AC macros (M4sugar excluded).
   # unac.m4 -- undefine the AC macros.
-  my $ac_m4 = new Autom4te::XFile ">$tmp/ac.m4";
+  my $ac_m4 = new Autom4te::XFile "> " . open_quote ("$tmp/ac.m4");
   print $ac_m4 "# ac.m4 -- autoquoting definitions of the AC macros.\n";
-  my $unac_m4 = new Autom4te::XFile ">$tmp/unac.m4";
+  my $unac_m4 = new Autom4te::XFile "> " . open_quote ("$tmp/unac.m4");
   print $unac_m4 "# unac.m4 -- undefine the AC macros.\n";
   foreach (sort keys %ac_macros)
     {
@@ -197,11 +197,11 @@ sub handle_autoconf_macros ()
   # m4save.m4 -- save the m4 builtins.
   # unm4.m4 -- disable the m4 builtins.
   # m4.m4 -- enable the m4 builtins.
-  my $m4save_m4 = new Autom4te::XFile ">$tmp/m4save.m4";
+  my $m4save_m4 = new Autom4te::XFile "> " . open_quote ("$tmp/m4save.m4");
   print $m4save_m4 "# m4save.m4 -- save the m4 builtins.\n";
-  my $unm4_m4 = new Autom4te::XFile ">$tmp/unm4.m4";
+  my $unm4_m4 = new Autom4te::XFile "> " . open_quote ("$tmp/unm4.m4");
   print $unm4_m4 "# unm4.m4 -- disable the m4 builtins.\n";
-  my $m4_m4 = new Autom4te::XFile ">$tmp/m4.m4";
+  my $m4_m4 = new Autom4te::XFile "> " . open_quote ("$tmp/m4.m4");
   print $m4_m4 "# m4.m4 -- enable the m4 builtins.\n";
   foreach (sort keys %m4_builtins)
     {
@@ -220,8 +220,8 @@ parse_args;
 $autoconf .= " --debug" if $debug;
 $autoconf .= " --force" if $force;
 $autoconf .= " --verbose" if $verbose;
-$autoconf .= join (' --include=', '', @include);
-$autoconf .= join (' --prepend-include=', '', @prepend_include);
+$autoconf .= join (' --include=', '', map { shell_quote ($_) } @include);
+$autoconf .= join (' --prepend-include=', '', map { shell_quote ($_) } @prepend_include);
 
 mktmpdir ('au');
 handle_autoconf_macros;
@@ -233,7 +233,7 @@ my $au_changequote =
 # au.m4 -- definitions the AU macros.
 xsystem ("$autoconf --trace AU_DEFINE:'_au_defun(\@<:\@\$1\@:>\@,
 \@<:\@\$2\@:>\@)' --melt /dev/null "
-       . ">$tmp/au.m4");
+       . ">" . shell_quote ("$tmp/au.m4"));
 
 
 
@@ -247,7 +247,7 @@ foreach my $file (@ARGV)
     if ($file eq '-')
       {
        $file = "$tmp/stdin";
-       system "cat >$file";
+       system "cat >" . shell_quote ($file);
       }
     elsif (! -r "$file")
       {
@@ -376,9 +376,9 @@ EOF
     $input_m4 =~ s/\$file/$file/g;
 
     # prepared input -- input, but reenables the quote before each AU macro.
-    open INPUT_M4, ">$tmp/input.m4"
+    open INPUT_M4, "> " . open_quote ("$tmp/input.m4")
        or error "cannot open: $!";
-    open FILE, "<$file"
+    open FILE, "< " . open_quote ($file)
        or error "cannot open: $!";
     print INPUT_M4 "$input_m4";
     while (<FILE>)
@@ -392,10 +392,10 @@ EOF
        or error "cannot close $tmp/input.m4: $!";
 
     # Now ask m4 to perform the update.
-    xsystem ("$m4 --include=$tmp"
-            . join (' --include=', '', reverse (@prepend_include))
-            . join (' --include=', '', @include)
-            . " $tmp/input.m4 >$tmp/updated");
+    xsystem ("$m4 --include=" . shell_quote ($tmp)
+            . join (' --include=', '', map { shell_quote ($_) } reverse (@prepend_include))
+            . join (' --include=', '', map { shell_quote ($_) } @include)
+            . " " . shell_quote ("$tmp/input.m4") . " > " . shell_quote ("$tmp/updated"));
     update_file ("$tmp/updated",
                 "$file" eq "$tmp/stdin" ? '-' : "$file");
   }
index d7c36bab722f81b08a491247bdbebe18edfc6a5a..bd65bbf75e7b25f97a66d188e167d2d9beb13abb 100644 (file)
@@ -43,6 +43,7 @@ BEGIN
 
 use Autom4te::General;
 use Autom4te::XFile;
+use Autom4te::FileUtils;
 
 # $HELP
 # -----
@@ -92,7 +93,7 @@ my %occurrence;
 sub scan_file ($)
 {
   my ($file_name) = @_;
-  my $file = new Autom4te::XFile ($file_name);
+  my $file = new Autom4te::XFile ("< " . open_quote ($file_name));
   while ($_ = $file->getline)
     {
       # Continuation lines.
index b79467fe1ce15f743e3b32744b3c6c5da44cb494..5639e4cb85446fdefc29c725b7310b7ecc487ac2 100644 (file)
@@ -1,5 +1,6 @@
 # autoconf -- create `configure' using m4 macros
-# Copyright (C) 2001, 2002, 2003, 2004, 2006 Free Software Foundation, Inc.
+# Copyright (C) 2001, 2002, 2003, 2004, 2006, 2007 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
@@ -53,7 +54,7 @@ my @export_vars =
 # Functions we define and export.
 my @export_subs =
   qw (&debug
-      &getopt &mktmpdir
+      &getopt &shell_quote &mktmpdir
       &uniq);
 
 # Functions we forward (coming from modules we use).
@@ -281,6 +282,31 @@ sub getopt (%)
 }
 
 
+=item C<shell_quote ($file_name)>
+
+Quote C<$file_name> for the shell.
+
+=cut
+
+# $FILE_NAME
+# shell_quote ($FILE_NAME)
+# ------------------------
+# If the string $S is a well-behaved file name, simply return it.
+# If it contains white space, quotes, etc., quote it, and return
+# the new string.
+sub shell_quote($)
+{
+  my ($s) = @_;
+  if ($s =~ m![^\w+/.,-]!)
+    {
+      # Convert each single quote to '\''
+      $s =~ s/\'/\'\\\'\'/g;
+      # Then single quote the string.
+      $s = "'$s'";
+    }
+  return $s;
+}
+
 =item C<mktmpdir ($signature)>
 
 Create a temporary directory which name is based on C<$signature>.
@@ -295,10 +321,11 @@ sub mktmpdir ($)
 {
   my ($signature) = @_;
   my $TMPDIR = $ENV{'TMPDIR'} || '/tmp';
+  my $quoted_tmpdir = shell_quote ($TMPDIR);
 
   # If mktemp supports dirs, use it.
   $tmp = `(umask 077 &&
-          mktemp -d "$TMPDIR/${signature}XXXXXX") 2>/dev/null`;
+          mktemp -d $quoted_tmpdir/"${signature}XXXXXX") 2>/dev/null`;
   chomp $tmp;
 
   if (!$tmp || ! -d $tmp)
index 4096d9e5c97b45fce940ee4f4bf5ed35d217f270..199c15e4aceb4c92f8ef1433572a561a8fdfefa7 100644 (file)
@@ -138,22 +138,73 @@ AT_CHECK([cat file], 0,
 AT_CLEANUP
 
 
-# autom4te and file names containing white space
-# ----------------------------------------------
+# autom4te and file names containing whitespace
+# ---------------------------------------------
+
+AT_SETUP([autom4te and whitespace in file names])
+
+x=
+export x
+rm -f a b
+# the first one omits special characters that are not w32 safe.
+for funny in \
+  'with  funny '\'' $x & #! name ' \
+  'with  funny \ '\'' \'\'' " <a >b * ? name '
+do
+  file=" file $funny"
+  outfile="$file out "
+  dir=" dir $funny"
+  cachedir=" cache$dir"
+  TMPDIR=" tmp$dir"
+  export TMPDIR
+
+  cat >"$file" <<'END'
+[m4@&t@_include(foo.m4)
+m4@&t@_divert(0)d@&t@nl
+FOO]
+END
+  # skip if we cannot create such a file or directory
+  AT_CHECK([mkdir "$dir" "$cachedir" "$TMPDIR" && test -f "$file" || exit 77])
+  cat >"$dir"/foo.m4 <<'END'
+[m4@&t@_define([FOO], [bar])]
+END
 
-AT_SETUP([autom4te and white space in file names])
+  AT_CHECK_AUTOM4TE([-C "$cachedir" -B "$dir" --language=m4sugar -o "$outfile" "$file"])
+  AT_CHECK([cat "$outfile"], [],
+  [[bar
+]])
+  rm -rf "$outfile" "$cachedir"
+  AT_CHECK_AUTOM4TE([-C "$cachedir" -I "$dir" --language=m4sugar -o "$outfile" "$file"])
+  AT_CHECK([cat "$outfile"], [],
+  [[bar
+]])
 
-file='file with  funny \ '\'' \'\'' $ & #!*? name'
-cat >"$file.m4" <<'END'
-right
+  # This exercises a slightly different code path and will catch an open with
+  # trailing whitespace:
+  cat >"$file" <<'END'
+[m4@&t@_include(foo.m4)
+m4@&t@_pattern_forbid([^bar$])
+m4@&t@_divert(0)d@&t@nl
+FOO]
+END
+  rm -rf "$outfile" "$cachedir"
+  AT_CHECK_AUTOM4TE([-C "$cachedir" -I "$dir" --language=m4sugar -o "$outfile" "$file"],
+                   [1], [], [stderr])
+  AT_CHECK([grep 'possibly undefined macro' stderr], [], [ignore])
+
+  cat >"$file" <<'END'
+[m4@&t@_include(foo.m4)
+m4@&t@_divert(0)d@&t@nl]
 END
-# skip if we cannot create such a file
-AT_CHECK([test -f "$file.m4" || exit 77])
-AT_CHECK_AUTOM4TE([-o "$file" "$file.m4"])
+  rm -rf "$file.m4f"
+  AT_CHECK_AUTOM4TE([-C "$cachedir" -I "$dir" --language=m4sugar --freeze -o "$file.m4f" "$file"])
+  AT_CHECK([test -s "$file.m4f"])
 
-AT_CHECK([cat "$file"], [],
-[[right
-]])
+  # Check --reload-state
+  AT_CHECK_AUTOM4TE([-C "$cachedir" --language=m4sugar -o "$outfile" "$file.m4f" /dev/null])
+
+  test ! -f b
+done
 
 AT_CLEANUP
 
@@ -925,3 +976,64 @@ AT_CHECK([test "`find configure -newer newer`" = "" ||
          { diff old-requests autom4te.cache/requests; exit 1; }])
 
 AT_CLEANUP
+
+
+# autotools and file names containing whitespace
+# ---------------------------------------------
+
+AT_SETUP([autotools and whitespace in file names])
+
+x=
+export x
+rm -f a b
+# the first one omits special characters that are not w32 safe.
+for funny in \
+  'with  funny '\'' $x & #! name ' \
+  'with  funny \ '\'' \'\'' " <a >b * ? name '
+do
+  file=" file $funny"
+  dir=" dir $funny"
+  TMPDIR=" tmp$dir"
+  export TMPDIR
+
+  cat >"$file.in" <<'END'
+[AC_INIT(x,0)
+m4@&t@_include([foo.m4])
+AC_CONFIG_HEADERS([config.h:config.hin])
+AC_MACRO
+AC_OUTPUT]
+END
+  # skip if we cannot create such a file or directory
+  AT_CHECK([mkdir "$dir" "$TMPDIR" && test -f "$file.in" || exit 77])
+  cat >"$dir"/foo.m4 <<'END'
+[AC_DEFUN([AC_MACRO], [echo hi])]
+END
+
+  AT_CHECK_AUTOHEADER([-B "$dir" "$file.in"])
+  AT_CHECK_AUTOHEADER([-I "$dir" "$file.in"])
+  AT_CHECK_AUTOUPDATE([-B "$dir" "$file.in"])
+  AT_CHECK_AUTOUPDATE([-I "$dir" "$file.in"])
+  AT_CHECK_AUTOUPDATE([-B "$dir" - < "$file.in"], [], [ignore])
+  AT_CHECK_AUTOCONF([-B "$dir" -o "$file" "$file.in"])
+  AT_CHECK_AUTOCONF([-I "$dir" -o "$file" "$file.in"])
+  # In autoconf, these exercise a slightly different code path:
+  AT_CHECK_AUTOCONF([--prepend-include="$dir" -o "$file" "$file.in"])
+  AT_CHECK_AUTOCONF([--include="$dir" -o "$file" "$file.in"])
+  AT_CHECK([autoscan -B "$dir"], [], [], [ignore])
+  AT_CHECK([autoscan -I "$dir"], [], [], [ignore])
+  # autoreconf requires a sane input file name.  Also, disable aclocal.
+  mv -f "$file.in" configure.in
+  AT_DATA([aclocal.m4])
+  AT_CHECK([autoreconf -B "$dir"])
+  AT_CHECK([autoreconf -I "$dir"])
+
+  cat >"$file.c" <<'END'
+#if FOO
+#endif
+END
+  AT_CHECK([ifnames "$file.c"], [], [ignore])
+
+  test ! -f b
+done
+
+AT_CLEANUP