From: Bruno Haible Date: Mon, 29 Sep 2008 13:13:25 +0000 (+0200) Subject: Enable use of shell scripts as executables in mingw. X-Git-Tag: v0.1~6938 X-Git-Url: http://erislabs.net/gitweb/?a=commitdiff_plain;h=a7dd7898b03b95173995e1b69733fd0e91aa04cf;p=gnulib.git Enable use of shell scripts as executables in mingw. --- diff --git a/ChangeLog b/ChangeLog index 3efa157b2..75ed5a830 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2008-09-29 Bruno Haible + + 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 * m4/arpa_inet_h.m4 (gl_REPLACE_ARPA_INET_H): Fix typo. diff --git a/lib/execute.c b/lib/execute.c index 751dcb384..47f408520 100644 --- a/lib/execute.c +++ b/lib/execute.c @@ -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) diff --git a/lib/pipe.c b/lib/pipe.c index a632e9dd2..ebedb0a2d 100644 --- a/lib/pipe.c +++ b/lib/pipe.c @@ -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) diff --git a/lib/w32spawn.h b/lib/w32spawn.h index 7ebbb4c58..9ebf5bc49 100644 --- a/lib/w32spawn.h +++ b/lib/w32spawn.h @@ -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 , 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++)