merge from gcc
authorDJ Delorie <dj@redhat.com>
Thu, 7 Aug 2008 20:00:53 +0000 (20:00 +0000)
committerDJ Delorie <dj@redhat.com>
Thu, 7 Aug 2008 20:00:53 +0000 (20:00 +0000)
libiberty/ChangeLog
libiberty/pex-win32.c

index fa8abf51415ea6c32f1aab2a6bc54d1554acd6c0..837035c05f1ddfabad482eb38e0273f53d5b3f85 100644 (file)
@@ -1,3 +1,8 @@
+2008-08-07  Aaron W. LaFramboise  <aaronavay62@aaronwl.com>
+
+       * pex-win32.c (argv_to_argc): New function.
+       (spawn_script): Duplicate argv before calling win32_spawn.
+
 2008-07-31  Jakub Jelinek  <jakub@redhat.com>
 
        * mkstemps.c (mkstemps): Keep looping even for EISDIR.
index 05d44e9d183a6c9e14cd59afe0c26c6cb8920aa9..5897866347d7b1b08ac7d1e62a44349387a2d558 100644 (file)
@@ -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);
            }
        }
     }