diff options
author | DJ Delorie <dj@redhat.com> | 2008-08-07 20:00:53 +0000 |
---|---|---|
committer | DJ Delorie <dj@redhat.com> | 2008-08-07 20:00:53 +0000 |
commit | bd8aab1c2944a603af1182db1d81cfbd832d162a (patch) | |
tree | 27111fb3e4337aeaf3529696e1a37cc599838b2d /libiberty/pex-win32.c | |
parent | d4596a51ebc208135442993152367a37a751b0a2 (diff) | |
download | binutils-gdb-bd8aab1c2944a603af1182db1d81cfbd832d162a.tar.gz |
merge from gcc
Diffstat (limited to 'libiberty/pex-win32.c')
-rw-r--r-- | libiberty/pex-win32.c | 37 |
1 files changed, 35 insertions, 2 deletions
diff --git a/libiberty/pex-win32.c b/libiberty/pex-win32.c index 05d44e9d183..5897866347d 100644 --- a/libiberty/pex-win32.c +++ b/libiberty/pex-win32.c @@ -321,6 +321,18 @@ msys_rootify (const char *executable) } #endif +/* Return the number of arguments in an argv array, not including the null + terminating argument. */ + +static int +argv_to_argc (char *const *argv) +{ + char *const *i = argv; + while (*i) + i++; + return i - argv; +} + /* Return a Windows command-line from ARGV. It is the caller's responsibility to free the string returned. */ @@ -522,6 +534,9 @@ env_compare (const void *a_ptr, const void *b_ptr) return c1 - c2; } +/* Execute a Windows executable as a child process. This will fail if the + * target is not actually an executable, such as if it is a shell script. */ + static pid_t win32_spawn (const char *executable, BOOL search, @@ -619,6 +634,9 @@ win32_spawn (const char *executable, return (pid_t) -1; } +/* Spawn a script. This simulates the Unix script execution mechanism. + This function is called as a fallback if win32_spawn fails. */ + static pid_t spawn_script (const char *executable, char *const *argv, char* const *env, @@ -630,6 +648,8 @@ spawn_script (const char *executable, char *const *argv, int save_errno = errno; int fd = _open (executable, _O_RDONLY); + /* Try to open script, check header format, extract interpreter path, + and spawn script using that interpretter. */ if (fd >= 0) { char buf[MAX_PATH + 5]; @@ -642,16 +662,28 @@ spawn_script (const char *executable, char *const *argv, eol = strchr (buf, '\n'); if (eol && strncmp (buf, "#!", 2) == 0) { + + /* Header format is OK. */ char *executable1; - const char ** avhere = (const char **) --argv; + int new_argc; + const char **avhere; + + /* Extract interpreter path. */ do *eol = '\0'; while (*--eol == '\r' || *eol == ' ' || *eol == '\t'); for (executable1 = buf + 2; *executable1 == ' ' || *executable1 == '\t'; executable1++) continue; - backslashify (executable1); + + /* Duplicate argv, prepending the interpreter path. */ + new_argc = argv_to_argc (argv) + 1; + avhere = XNEWVEC (const char *, new_argc + 1); *avhere = executable1; + memcpy (avhere + 1, argv, new_argc * sizeof(*argv)); + argv = (char *const *)avhere; + + /* Spawn the child. */ #ifndef USE_MINGW_MSYS executable = strrchr (executable1, '\\') + 1; if (!executable) @@ -686,6 +718,7 @@ spawn_script (const char *executable, char *const *argv, } } #endif + free (avhere); } } } |