allow renaming bootstrap, and change the name of bootstrap.conf accordingly
[gnulib.git] / lib / execute.c
index cfac196..231f467 100644 (file)
@@ -117,7 +117,8 @@ execute (const char *progname,
         const char *prog_path, char **prog_argv,
         bool ignore_sigpipe,
         bool null_stdin, bool null_stdout, bool null_stderr,
-        bool slave_process, bool exit_on_error)
+        bool slave_process, bool exit_on_error,
+        int *termsigp)
 {
 #if defined _MSC_VER || defined __MINGW32__
 
@@ -129,6 +130,7 @@ execute (const char *progname,
   int nullinfd;
   int nulloutfd;
 
+  /* FIXME: Need to free memory allocated by prepare_spawn.  */
   prog_argv = prepare_spawn (prog_argv);
 
   /* Save standard file handles of parent process.  */
@@ -159,7 +161,25 @@ execute (const char *progname,
              && ((null_stdout && nulloutfd == STDOUT_FILENO)
                  || (null_stderr && nulloutfd == STDERR_FILENO)
                  || close (nulloutfd) >= 0))))
-    exitcode = spawnvp (P_WAIT, prog_path, prog_argv);
+    /* Use spawnvpe and pass the environment explicitly.  This is needed if
+       the program has modified the environment using putenv() or [un]setenv().
+       On Windows, programs have two environments, one in the "environment
+       block" of the process and managed through SetEnvironmentVariable(), and
+       one inside the process, in the location retrieved by the 'environ'
+       macro.  When using spawnvp() without 'e', the child process inherits a
+       copy of the environment block - ignoring the effects of putenv() and
+       [un]setenv().  */
+    {
+      exitcode = spawnvpe (P_WAIT, prog_path, prog_argv, environ);
+      if (exitcode < 0 && errno == ENOEXEC)
+       {
+         /* prog is not an native executable.  Try to execute it as a
+            shell script.  Note that prepare_spawn() has already prepended
+            a hidden element "sh.exe" to prog_argv.  */
+         --prog_argv;
+         exitcode = spawnvpe (P_WAIT, prog_argv[0], prog_argv, environ);
+       }
+    }
   if (nulloutfd >= 0)
     close (nulloutfd);
   if (nullinfd >= 0)
@@ -173,6 +193,9 @@ execute (const char *progname,
   if (null_stdin)
     dup2 (orig_stdin, STDIN_FILENO), close (orig_stdin);
 
+  if (termsigp != NULL)
+    *termsigp = 0;
+
   if (exitcode == -1)
     {
       if (exit_on_error || !null_stderr)
@@ -251,6 +274,8 @@ execute (const char *progname,
        posix_spawnattr_destroy (&attrs);
       if (slave_process)
        unblock_fatal_signals ();
+      if (termsigp != NULL)
+       *termsigp = 0;
       if (exit_on_error || !null_stderr)
        error (exit_on_error ? EXIT_FAILURE : 0, err,
               _("%s subprocess failed"), progname);
@@ -293,6 +318,8 @@ execute (const char *progname,
     {
       if (slave_process)
        unblock_fatal_signals ();
+      if (termsigp != NULL)
+       *termsigp = 0;
       if (exit_on_error || !null_stderr)
        error (exit_on_error ? EXIT_FAILURE : 0, errno,
               _("%s subprocess failed"), progname);
@@ -306,7 +333,7 @@ execute (const char *progname,
     }
 
   return wait_subprocess (child, progname, ignore_sigpipe, null_stderr,
-                         slave_process, exit_on_error);
+                         slave_process, exit_on_error, termsigp);
 
 #endif
 }