Line 82... |
Line 82... |
static pid_t pex_win32_exec_child (struct pex_obj *, int, const char *,
|
static pid_t pex_win32_exec_child (struct pex_obj *, int, const char *,
|
char * const *, char * const *,
|
char * const *, char * const *,
|
int, int, int, int,
|
int, int, int, int,
|
const char **, int *);
|
const char **, int *);
|
static int pex_win32_close (struct pex_obj *, int);
|
static int pex_win32_close (struct pex_obj *, int);
|
static int pex_win32_wait (struct pex_obj *, pid_t, int *,
|
static pid_t pex_win32_wait (struct pex_obj *, pid_t, int *,
|
struct pex_time *, int, const char **, int *);
|
struct pex_time *, int, const char **, int *);
|
static int pex_win32_pipe (struct pex_obj *, int *, int);
|
static int pex_win32_pipe (struct pex_obj *, int *, int);
|
static FILE *pex_win32_fdopenr (struct pex_obj *, int, int);
|
static FILE *pex_win32_fdopenr (struct pex_obj *, int, int);
|
static FILE *pex_win32_fdopenw (struct pex_obj *, int, int);
|
static FILE *pex_win32_fdopenw (struct pex_obj *, int, int);
|
|
|
Line 319... |
Line 319... |
free (buf);
|
free (buf);
|
return executable;
|
return executable;
|
}
|
}
|
#endif
|
#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
|
/* Return a Windows command-line from ARGV. It is the caller's
|
responsibility to free the string returned. */
|
responsibility to free the string returned. */
|
|
|
static char *
|
static char *
|
argv_to_cmdline (char *const *argv)
|
argv_to_cmdline (char *const *argv)
|
Line 520... |
Line 532... |
while (c1 == c2 && c1 != '\0');
|
while (c1 == c2 && c1 != '\0');
|
|
|
return c1 - c2;
|
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
|
static pid_t
|
win32_spawn (const char *executable,
|
win32_spawn (const char *executable,
|
BOOL search,
|
BOOL search,
|
char *const *argv,
|
char *const *argv,
|
char *const *env, /* array of strings of the form: VAR=VALUE */
|
char *const *env, /* array of strings of the form: VAR=VALUE */
|
Line 617... |
Line 632... |
free (full_executable);
|
free (full_executable);
|
|
|
return (pid_t) -1;
|
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
|
static pid_t
|
spawn_script (const char *executable, char *const *argv,
|
spawn_script (const char *executable, char *const *argv,
|
char* const *env,
|
char* const *env,
|
DWORD dwCreationFlags,
|
DWORD dwCreationFlags,
|
LPSTARTUPINFO si,
|
LPSTARTUPINFO si,
|
Line 628... |
Line 646... |
{
|
{
|
pid_t pid = (pid_t) -1;
|
pid_t pid = (pid_t) -1;
|
int save_errno = errno;
|
int save_errno = errno;
|
int fd = _open (executable, _O_RDONLY);
|
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)
|
if (fd >= 0)
|
{
|
{
|
char buf[MAX_PATH + 5];
|
char buf[MAX_PATH + 5];
|
int len = _read (fd, buf, sizeof (buf) - 1);
|
int len = _read (fd, buf, sizeof (buf) - 1);
|
_close (fd);
|
_close (fd);
|
Line 640... |
Line 660... |
char *eol;
|
char *eol;
|
buf[len] = '\0';
|
buf[len] = '\0';
|
eol = strchr (buf, '\n');
|
eol = strchr (buf, '\n');
|
if (eol && strncmp (buf, "#!", 2) == 0)
|
if (eol && strncmp (buf, "#!", 2) == 0)
|
{
|
{
|
|
|
|
/* Header format is OK. */
|
char *executable1;
|
char *executable1;
|
const char ** avhere = (const char **) --argv;
|
int new_argc;
|
|
const char **avhere;
|
|
|
|
/* Extract interpreter path. */
|
do
|
do
|
*eol = '\0';
|
*eol = '\0';
|
while (*--eol == '\r' || *eol == ' ' || *eol == '\t');
|
while (*--eol == '\r' || *eol == ' ' || *eol == '\t');
|
for (executable1 = buf + 2; *executable1 == ' ' || *executable1 == '\t'; executable1++)
|
for (executable1 = buf + 2; *executable1 == ' ' || *executable1 == '\t'; executable1++)
|
continue;
|
continue;
|
|
|
backslashify (executable1);
|
backslashify (executable1);
|
|
|
|
/* Duplicate argv, prepending the interpreter path. */
|
|
new_argc = argv_to_argc (argv) + 1;
|
|
avhere = XNEWVEC (const char *, new_argc + 1);
|
*avhere = executable1;
|
*avhere = executable1;
|
|
memcpy (avhere + 1, argv, new_argc * sizeof(*argv));
|
|
argv = (char *const *)avhere;
|
|
|
|
/* Spawn the child. */
|
#ifndef USE_MINGW_MSYS
|
#ifndef USE_MINGW_MSYS
|
executable = strrchr (executable1, '\\') + 1;
|
executable = strrchr (executable1, '\\') + 1;
|
if (!executable)
|
if (!executable)
|
executable = executable1;
|
executable = executable1;
|
pid = win32_spawn (executable, TRUE, argv, env,
|
pid = win32_spawn (executable, TRUE, argv, env,
|
Line 671... |
Line 703... |
*avhere = newex;
|
*avhere = newex;
|
pid = win32_spawn (newex, FALSE, argv, env,
|
pid = win32_spawn (newex, FALSE, argv, env,
|
dwCreationFlags, si, pi);
|
dwCreationFlags, si, pi);
|
if (executable1 != newex)
|
if (executable1 != newex)
|
free ((char *) newex);
|
free ((char *) newex);
|
if ((long) pid < 0)
|
if (pid == (pid_t) -1)
|
{
|
{
|
newex = msys_rootify (executable1);
|
newex = msys_rootify (executable1);
|
if (newex != executable1)
|
if (newex != executable1)
|
{
|
{
|
*avhere = newex;
|
*avhere = newex;
|
Line 684... |
Line 716... |
free ((char *) newex);
|
free ((char *) newex);
|
}
|
}
|
}
|
}
|
}
|
}
|
#endif
|
#endif
|
|
free (avhere);
|
}
|
}
|
}
|
}
|
}
|
}
|
if ((long) pid < 0)
|
if (pid == (pid_t) -1)
|
errno = save_errno;
|
errno = save_errno;
|
return pid;
|
return pid;
|
}
|
}
|
|
|
/* Execute a child. */
|
/* Execute a child. */
|
Line 711... |
Line 744... |
HANDLE stderr_handle;
|
HANDLE stderr_handle;
|
DWORD dwCreationFlags;
|
DWORD dwCreationFlags;
|
OSVERSIONINFO version_info;
|
OSVERSIONINFO version_info;
|
STARTUPINFO si;
|
STARTUPINFO si;
|
PROCESS_INFORMATION pi;
|
PROCESS_INFORMATION pi;
|
|
int orig_out, orig_in, orig_err;
|
|
BOOL separate_stderr = !(flags & PEX_STDERR_TO_STDOUT);
|
|
|
|
/* Ensure we have inheritable descriptors to pass to the child, and close the
|
|
original descriptors. */
|
|
orig_in = in;
|
|
in = _dup (orig_in);
|
|
if (orig_in != STDIN_FILENO)
|
|
_close (orig_in);
|
|
|
|
orig_out = out;
|
|
out = _dup (orig_out);
|
|
if (orig_out != STDOUT_FILENO)
|
|
_close (orig_out);
|
|
|
|
if (separate_stderr)
|
|
{
|
|
orig_err = errdes;
|
|
errdes = _dup (orig_err);
|
|
if (orig_err != STDERR_FILENO)
|
|
_close (orig_err);
|
|
}
|
|
|
stdin_handle = INVALID_HANDLE_VALUE;
|
stdin_handle = INVALID_HANDLE_VALUE;
|
stdout_handle = INVALID_HANDLE_VALUE;
|
stdout_handle = INVALID_HANDLE_VALUE;
|
stderr_handle = INVALID_HANDLE_VALUE;
|
stderr_handle = INVALID_HANDLE_VALUE;
|
|
|
stdin_handle = (HANDLE) _get_osfhandle (in);
|
stdin_handle = (HANDLE) _get_osfhandle (in);
|
stdout_handle = (HANDLE) _get_osfhandle (out);
|
stdout_handle = (HANDLE) _get_osfhandle (out);
|
if (!(flags & PEX_STDERR_TO_STDOUT))
|
if (separate_stderr)
|
stderr_handle = (HANDLE) _get_osfhandle (errdes);
|
stderr_handle = (HANDLE) _get_osfhandle (errdes);
|
else
|
else
|
stderr_handle = stdout_handle;
|
stderr_handle = stdout_handle;
|
|
|
/* Determine the version of Windows we are running on. */
|
/* Determine the version of Windows we are running on. */
|
Line 787... |
Line 842... |
{
|
{
|
*err = ENOENT;
|
*err = ENOENT;
|
*errmsg = "CreateProcess";
|
*errmsg = "CreateProcess";
|
}
|
}
|
|
|
/* Close the standard output and standard error handles in the
|
/* Close the standard input, standard output and standard error handles
|
parent. */
|
in the parent. */
|
if (out != STDOUT_FILENO)
|
|
obj->funcs->close (obj, out);
|
_close (in);
|
if (errdes != STDERR_FILENO)
|
_close (out);
|
obj->funcs->close (obj, errdes);
|
if (separate_stderr)
|
|
_close (errdes);
|
|
|
return pid;
|
return pid;
|
}
|
}
|
|
|
/* Wait for a child process to complete. MS CRTDLL doesn't return
|
/* Wait for a child process to complete. MS CRTDLL doesn't return
|
Line 805... |
Line 861... |
code of the child; eg., if the child exited with an abort() call
|
code of the child; eg., if the child exited with an abort() call
|
and didn't have a handler for SIGABRT, it simply returns with
|
and didn't have a handler for SIGABRT, it simply returns with
|
status == 3. We fix the status code to conform to the usual WIF*
|
status == 3. We fix the status code to conform to the usual WIF*
|
macros. Note that WIFSIGNALED will never be true under CRTDLL. */
|
macros. Note that WIFSIGNALED will never be true under CRTDLL. */
|
|
|
static int
|
static pid_t
|
pex_win32_wait (struct pex_obj *obj ATTRIBUTE_UNUSED, pid_t pid,
|
pex_win32_wait (struct pex_obj *obj ATTRIBUTE_UNUSED, pid_t pid,
|
int *status, struct pex_time *time, int done ATTRIBUTE_UNUSED,
|
int *status, struct pex_time *time, int done ATTRIBUTE_UNUSED,
|
const char **errmsg, int *err)
|
const char **errmsg, int *err)
|
{
|
{
|
DWORD termstat;
|
DWORD termstat;
|
Line 848... |
Line 904... |
|
|
static int
|
static int
|
pex_win32_pipe (struct pex_obj *obj ATTRIBUTE_UNUSED, int *p,
|
pex_win32_pipe (struct pex_obj *obj ATTRIBUTE_UNUSED, int *p,
|
int binary)
|
int binary)
|
{
|
{
|
return _pipe (p, 256, binary ? _O_BINARY : _O_TEXT);
|
return _pipe (p, 256, (binary ? _O_BINARY : _O_TEXT) | _O_NOINHERIT);
|
}
|
}
|
|
|
/* Get a FILE pointer to read from a file descriptor. */
|
/* Get a FILE pointer to read from a file descriptor. */
|
|
|
static FILE *
|
static FILE *
|
pex_win32_fdopenr (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd,
|
pex_win32_fdopenr (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd,
|
int binary)
|
int binary)
|
{
|
{
|
|
HANDLE h = (HANDLE) _get_osfhandle (fd);
|
|
if (h == INVALID_HANDLE_VALUE)
|
|
return NULL;
|
|
if (! SetHandleInformation (h, HANDLE_FLAG_INHERIT, 0))
|
|
return NULL;
|
return fdopen (fd, binary ? "rb" : "r");
|
return fdopen (fd, binary ? "rb" : "r");
|
}
|
}
|
|
|
static FILE *
|
static FILE *
|
pex_win32_fdopenw (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd,
|
pex_win32_fdopenw (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd,
|