summaryrefslogtreecommitdiff
path: root/libiberty/pex-win32.c
diff options
context:
space:
mode:
authorDJ Delorie <dj@redhat.com>2008-08-07 20:00:53 +0000
committerDJ Delorie <dj@redhat.com>2008-08-07 20:00:53 +0000
commitbd8aab1c2944a603af1182db1d81cfbd832d162a (patch)
tree27111fb3e4337aeaf3529696e1a37cc599838b2d /libiberty/pex-win32.c
parentd4596a51ebc208135442993152367a37a751b0a2 (diff)
downloadbinutils-gdb-bd8aab1c2944a603af1182db1d81cfbd832d162a.tar.gz
merge from gcc
Diffstat (limited to 'libiberty/pex-win32.c')
-rw-r--r--libiberty/pex-win32.c37
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);
}
}
}