Enable use of shell scripts as executables in mingw.
authorBruno Haible <bruno@clisp.org>
Mon, 29 Sep 2008 13:13:25 +0000 (15:13 +0200)
committerBruno Haible <bruno@clisp.org>
Mon, 29 Sep 2008 13:13:25 +0000 (15:13 +0200)
ChangeLog
lib/execute.c
lib/pipe.c
lib/w32spawn.h

index 3efa157..75ed5a8 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2008-09-29  Bruno Haible  <bruno@clisp.org>
+
+       Enable use of shell scripts as executables in mingw.
+       * lib/execute.c (execute): When spawnv fails with error ENOEXEC,
+       run the program as a shell script.
+       * lib/pipe.c (create_pipe): Likewise.
+       * lib/w32spawn.h (prepare_spawn): Add a hidden element in front of the
+       resulting array.
+
 2008-09-29  Eric Blake  <ebb9@byu.net>
 
        * m4/arpa_inet_h.m4 (gl_REPLACE_ARPA_INET_H): Fix typo.
index 751dcb3..47f4085 100644 (file)
@@ -130,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.  */
@@ -160,7 +161,17 @@ 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);
+    {
+      exitcode = spawnvp (P_WAIT, prog_path, prog_argv);
+      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 = spawnvp (P_WAIT, prog_argv[0], prog_argv);
+       }
+    }
   if (nulloutfd >= 0)
     close (nulloutfd);
   if (nullinfd >= 0)
index a632e9d..ebedb0a 100644 (file)
@@ -145,6 +145,7 @@ create_pipe (const char *progname,
   int stdinfd;
   int stdoutfd;
 
+  /* FIXME: Need to free memory allocated by prepare_spawn.  */
   prog_argv = prepare_spawn (prog_argv);
 
   if (pipe_stdout)
@@ -201,7 +202,17 @@ create_pipe (const char *progname,
        we want in the case of STD*_FILENO) and also orig_stdin,
        orig_stdout, orig_stderr (which is not explicitly wanted but
        harmless).  */
-    child = spawnvp (P_NOWAIT, prog_path, prog_argv);
+    {
+      child = spawnvp (P_NOWAIT, prog_path, prog_argv);
+      if (child < 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;
+         child = spawnvp (P_NOWAIT, prog_argv[0], prog_argv);
+       }
+    }
   if (stdinfd >= 0)
     close (stdinfd);
   if (stdoutfd >= 0)
index 7ebbb4c..9ebf5bc 100644 (file)
@@ -1,5 +1,5 @@
 /* Auxiliary functions for the creation of subprocesses.  Native Woe32 API.
-   Copyright (C) 2003, 2006, 2007 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2006-2008 Free Software Foundation, Inc.
    Written by Bruno Haible <bruno@clisp.org>, 2003.
 
    This program is free software: you can redistribute it and/or modify
@@ -91,7 +91,15 @@ prepare_spawn (char **argv)
     ;
 
   /* Allocate new argument vector.  */
-  new_argv = XNMALLOC (argc + 1, char *);
+  new_argv = XNMALLOC (1 + argc + 1, char *);
+
+  /* Add an element upfront that can be used when argv[0] turns out to be a
+     script, not a program.
+     On Unix, this would be "/bin/sh". On native Windows, "sh" is actually
+     "sh.exe".  We have to omit the directory part and rely on the search in
+     PATH, because the mingw "mount points" are not visible inside Win32
+     CreateProcess().  */
+  *new_argv++ = "sh.exe";
 
   /* Put quoted arguments into the new argument vector.  */
   for (i = 0; i < argc; i++)