]> git.ipfire.org Git - thirdparty/make.git/commitdiff
Don't write $(shell ...) stdout to stderr on failure
authorPaul Smith <psmith@gnu.org>
Sun, 6 Feb 2022 21:22:40 +0000 (16:22 -0500)
committerPaul Smith <psmith@gnu.org>
Sun, 6 Feb 2022 23:46:32 +0000 (18:46 -0500)
If a $(shell ...) invocation failed due to a command-not-found error,
make wrote the stdout of that shell to our stderr for some reason.
That seems very wrong.

If the command's stderr was not redirected then its output would have
already been written to its stderr, and if it was redirected then we
shouldn't take it upon ourselves to force it to go to stderr!

* src/function.c (func_shell_base): Append shell stdout even if the
shell command failed.
* tests/run_make_tests.pl: Determine the error generated for
command-not-found situations.
* tests/scripts/functions/shell: Verify that redirecting stderr to
stdout will behave properly if the command is not found.

src/function.c
tests/run_make_tests.pl
tests/scripts/functions/shell

index d7c139234deb1ef121c55120652878fa9048f638..9add8f657e630113a86388730466cc846f3ea5d2 100644 (file)
@@ -2012,24 +2012,10 @@ func_shell_base (char *o, char **argv, int trim_newlines)
       }
     shell_function_pid = 0;
 
-    /* shell_completed() will set shell_function_completed to 1 when the
-       child dies normally, or to -1 if it dies with status 127, which is
-       most likely an exec fail.  */
-
-    if (shell_function_completed == -1)
-      {
-        /* This likely means that the execvp failed, so we should just
-           write the error message in the pipe from the child.  */
-        fputs (buffer, stderr);
-        fflush (stderr);
-      }
-    else
-      {
-        /* The child finished normally.  Replace all newlines in its output
-           with spaces, and put that in the variable output buffer.  */
-        fold_newlines (buffer, &i, trim_newlines);
-        o = variable_buffer_output (o, buffer, i);
-      }
+    /* Replace all newlines in the command's output with spaces, and put that
+       in the variable output buffer.  */
+    fold_newlines (buffer, &i, trim_newlines);
+    o = variable_buffer_output (o, buffer, i);
 
     free (buffer);
   }
index 4cc375e535a2741330e5d52469c06f23bf45b541..188a57c4a0b6d4db8f0b6f8bd244ead3b68b09fd 100644 (file)
@@ -108,6 +108,7 @@ $ERR_read_only_file = undef;
 $ERR_unreadable_file = undef;
 $ERR_nonexe_file = undef;
 $ERR_exe_dir = undef;
+$ERR_command_not_found = undef;
 
 {
   use locale;
@@ -164,6 +165,15 @@ $ERR_exe_dir = undef;
 
   unlink('file.out') or die "Failed to delete file.out: $!\n";
 
+  $_ = `/bin/sh -c 'bad-command 2>&1'`;
+  if ($? == 0) {
+      print "Invoked invalid file!  Skipping related tests.\n";
+  } else {
+      chomp($_);
+      s/bad-command/#CMDNAME#/g;
+      $ERR_command_not_found = $_;
+  }
+
   $loc and POSIX::setlocale(&POSIX::LC_ALL, $loc);
 }
 
index 59865293e6f2697d41d57fd16dd0c838ca596a5c..63320a2b5e178921800bfec963f8a2fdcd3d67bb 100644 (file)
@@ -46,10 +46,11 @@ if ($port_type ne 'W32') {
     # This needs to be ported to Windows, or else Windows error messages
     # need to converted to look like more normal make errors.
     run_make_test('
+.RECIPEPREFIX = >
 all:
-       @echo hi
-       $(shell ./basdfdfsed there)
-       @echo $(.SHELLSTATUS)
+>@echo hi
+>$(shell ./basdfdfsed there)
+>@echo $(.SHELLSTATUS)
 ',
                   '', "#MAKE#: ./basdfdfsed: $ERR_no_such_file\nhi\n127\n");
 
@@ -81,10 +82,17 @@ $(shell kill -2 $$$$)
 STAT := $(.SHELLSTATUS)
 all: ; @echo STAT=$(STAT)
               ','',"STAT=$ret\n");
+
+    # Test that not-found errors can be redirected
+    if ($ERR_command_not_found) {
+        $_ = $ERR_command_not_found;
+        s/#CMDNAME#/bad-command/g;
+        run_make_test(q!
+out := $(shell bad-command 2>&1)
+all: ; @echo '$(.SHELLSTATUS): $(out)'
+!,
+                      '', "127: $_\n");
+    }
 }
 
 1;
-
-### Local Variables:
-### eval: (setq whitespace-action (delq 'auto-cleanup whitespace-action))
-### End: