* Makefile.in: Add cygheap.o.
* child_info.h: Add specific exec class. * cygheap.h: New file. Contains declarations for cygwin heap. * cygheap.cc: New file. Implements cygwin heap functions. * dcrt0.cc (quoted): Simplify due to new method for passing arguments between cygwin programs. (alloc_stack_hard_way): Attempt to handle overlapped stack. (dll_crt0_1): Move child_info processing here. Accomodate new method for passing arguments between cygwin programs. Initialize cygwin heap. Establish __argc and __argv variables. (_dll_crt0): Move most of child_info processing to dll_crt0_1. (cygwin_dll_init): Remove duplication. * dtable.cc (dtable::extend): Allocate dtable using cygwin heap. (dtable::build_fhandler): Ditto for fhandler type being constructed. (dtable::dup_worker): Free new fhandler from cygwin heap on error. (dtable::select_*): Don't assume that this == fdtab. (dtable::linearize_fd_array): Delete. (dtable::delinearize_fd_array): Delete. (dtable::fixup_after_exec): New file. (dtable::vfork_child_dup): Use cygwin heap. (dtable::vfork_parent_restore): Ditto. * dtable.h: Remove obsolete methods. Add new method. * environ.cc (posify): Eliminate already_posix parameter and logic. (envsize): New function. (_addenv): Use envsize. (environ_init): Accept an argument pointing to an existing environment list. If supplied, allocate space for this in the the program's heap. * fhandler.cc (fhandler_base::operator =): Move here from fhandler.h. Use cygwin heap to allocate filenames. (fhandler_base::set_name): Allocate/free names from cygwin heap. (fhandler_base::linearize): Delete. (fhandler_base::de_linearize): Delete. (fhandler_base::operator delete): Free from cygwin heap. (fhandler_base::~fhandler_base): Ditto. * fhandler.h: Accomodate elimination of *linearize and other changes above. * fhandler_console.cc (fhandler_console::fixup_after_exec): Rename from de_linearize. * heap.h: New file. * fhandler_tty.cc (fhandler_tty_slave::fhandler_tty_slave): Use cygwin heap for name. fhandler_tty::fixup_after_exec): Rename from de_linearize. * fork.cc (fork): Call cygheap_fixup_in_child. * heap.cc: Use declarations in heap.h. * malloc.cc: Sprinkle assertions throughout to catch attempts to free/realloc something from the cygwin heap. * path.cc: Throughout, eliminate use of per-thread cache for cwd. Use cwd_* functions rather than cwd_* variables to access cwd_win32 and cwd_posix. (cwd_win32): New function. (cwd_posix): New function. (cwd_hash): New function. (cwd_fixup_after_exec): New function. * path.h: Accomodate path.cc changes. * pinfo.cc (pinfo_init): Accept a pointer to an environment table. Pass this to environ_init. Eliminate old 'title' tests. * pinfo.h: Accomodate above change in argument. * spawn.cc (struct av): New method for building argv list. (av::unshift): New method. (spawn_guts): Allocate everything that the child process needs in the cygwin heap and pass a pointer to this to the child. Build argv list using new method. Eliminate delinearize stuff. * thread.h: Eliminate _cwd_win32 and _cwd_posix buffers. * winsup.h: Eliminate obsolete functions. Add envsize() declaration.
This commit is contained in:
@ -19,7 +19,6 @@ details. */
|
||||
#include <wingdi.h>
|
||||
#include <winuser.h>
|
||||
#include <ctype.h>
|
||||
#include <paths.h>
|
||||
#include "cygerrno.h"
|
||||
#include "fhandler.h"
|
||||
#include "path.h"
|
||||
@ -28,10 +27,9 @@ details. */
|
||||
#include "sigproc.h"
|
||||
#include "child_info.h"
|
||||
#include "pinfo.h"
|
||||
#include "cygheap.h"
|
||||
#include "perthread.h"
|
||||
|
||||
extern BOOL allow_ntsec;
|
||||
|
||||
#define LINE_BUF_CHUNK (MAX_PATH * 2)
|
||||
|
||||
suffix_info std_suffixes[] =
|
||||
@ -171,7 +169,6 @@ handle (int n, int direction)
|
||||
*/
|
||||
|
||||
HANDLE NO_COPY hExeced = NULL;
|
||||
DWORD NO_COPY exec_exit = 0;
|
||||
|
||||
int
|
||||
iscmd (const char *argv0, const char *what)
|
||||
@ -242,19 +239,66 @@ exec_fixup_after_fork ()
|
||||
hexec_proc = NULL;
|
||||
}
|
||||
|
||||
struct av
|
||||
{
|
||||
int argc;
|
||||
int calloced;
|
||||
private:
|
||||
char **argv;
|
||||
public:
|
||||
av (int ac, const char * const *av) : argc (ac), calloced (0)
|
||||
{
|
||||
argv = (char **) cmalloc (HEAP_ARGV, (argc + 1) * sizeof (char *));
|
||||
memcpy (argv, av, (argc + 1) * sizeof (char *));
|
||||
}
|
||||
~av ()
|
||||
{
|
||||
for (int i = 0; i < calloced; i++)
|
||||
cfree (argv[i]);
|
||||
cfree (argv);
|
||||
}
|
||||
int unshift (const char *what, int conv = 0);
|
||||
operator char **() {return argv;}
|
||||
};
|
||||
|
||||
int
|
||||
av::unshift (const char *what, int conv)
|
||||
{
|
||||
char **av;
|
||||
av = (char **) crealloc (argv, (argc + 2) * sizeof (char *));
|
||||
if (!av)
|
||||
return 0;
|
||||
|
||||
argv = av;
|
||||
memmove (argv + 1, argv, (argc + 1) * sizeof (char *));
|
||||
char buf[MAX_PATH + 1];
|
||||
if (conv)
|
||||
{
|
||||
cygwin_conv_to_posix_path (what, buf);
|
||||
char *p = strchr (buf, '\0') - 4;
|
||||
if (p > buf && strcasematch (p, ".exe"))
|
||||
*p = '\0';
|
||||
what = buf;
|
||||
}
|
||||
*argv = cstrdup (what);
|
||||
argc++;
|
||||
calloced++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int __stdcall
|
||||
spawn_guts (HANDLE hToken, const char * prog_arg, const char *const *argv,
|
||||
const char *const envp[], int mode)
|
||||
{
|
||||
int i;
|
||||
BOOL rc;
|
||||
int argc;
|
||||
pid_t cygpid;
|
||||
|
||||
hExeced = NULL;
|
||||
|
||||
MALLOC_CHECK;
|
||||
|
||||
// if (strstr (prog_arg, "dopath")) try_to_debug ();
|
||||
if (prog_arg == NULL)
|
||||
{
|
||||
syscall_printf ("prog_arg is NULL");
|
||||
@ -271,46 +315,69 @@ spawn_guts (HANDLE hToken, const char * prog_arg, const char *const *argv,
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* CreateProcess takes one long string that is the command line (sigh).
|
||||
We need to quote any argument that has whitespace or embedded "'s. */
|
||||
|
||||
for (argc = 0; argv[argc]; argc++)
|
||||
/* nothing */;
|
||||
|
||||
char *real_path;
|
||||
path_conv real_path_buf;
|
||||
path_conv real_path;
|
||||
|
||||
linebuf one_line;
|
||||
|
||||
if (argc == 3 && argv[1][0] == '/' && argv[1][1] == 'c' &&
|
||||
STARTUPINFO si = {0, NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL};
|
||||
|
||||
child_info_spawn ciresrv;
|
||||
si.lpReserved2 = (LPBYTE) &ciresrv;
|
||||
si.cbReserved2 = sizeof (ciresrv);
|
||||
|
||||
HANDLE spr = NULL;
|
||||
DWORD chtype;
|
||||
if (mode != _P_OVERLAY && mode != _P_VFORK)
|
||||
chtype = PROC_SPAWN;
|
||||
else
|
||||
{
|
||||
spr = CreateEvent(&sec_all, TRUE, FALSE, NULL);
|
||||
ProtectHandle (spr);
|
||||
chtype = PROC_EXEC;
|
||||
}
|
||||
|
||||
init_child_info (chtype, &ciresrv, (mode == _P_OVERLAY) ? myself->pid : 1, spr);
|
||||
if (!DuplicateHandle (hMainProc, hMainProc, hMainProc, &ciresrv.parent, 0, 1,
|
||||
DUPLICATE_SAME_ACCESS))
|
||||
{
|
||||
system_printf ("couldn't create handle to myself for child, %E");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ciresrv.moreinfo = (cygheap_exec_info *) ccalloc (HEAP_EXEC, 1, sizeof (cygheap_exec_info));
|
||||
ciresrv.moreinfo->old_title = old_title ? cstrdup (old_title) : NULL;
|
||||
ciresrv.moreinfo->fds = fdtab;
|
||||
ciresrv.moreinfo->nfds = fdtab.size;
|
||||
|
||||
/* CreateProcess takes one long string that is the command line (sigh).
|
||||
We need to quote any argument that has whitespace or embedded "'s. */
|
||||
|
||||
int ac;
|
||||
for (ac = 0; argv[ac]; ac++)
|
||||
/* nothing */;
|
||||
|
||||
av newargv (ac, argv);
|
||||
|
||||
if (ac == 3 && argv[1][0] == '/' && argv[1][1] == 'c' &&
|
||||
(iscmd (argv[0], "command.com") || iscmd (argv[0], "cmd.exe")))
|
||||
{
|
||||
one_line.add (argv[0]);
|
||||
one_line.add (" ");
|
||||
one_line.add (argv[1]);
|
||||
one_line.add (" ");
|
||||
real_path = NULL;
|
||||
one_line.add (argv[2]);
|
||||
strcpy (real_path_buf, argv[0]);
|
||||
strcpy (real_path, argv[0]);
|
||||
goto skip_arg_parsing;
|
||||
}
|
||||
|
||||
real_path = real_path_buf;
|
||||
|
||||
const char *saved_prog_arg;
|
||||
const char *newargv0, **firstarg;
|
||||
const char *ext;
|
||||
|
||||
if ((ext = perhaps_suffix (prog_arg, real_path_buf)) == NULL)
|
||||
if ((ext = perhaps_suffix (prog_arg, real_path)) == NULL)
|
||||
{
|
||||
set_errno (ENOENT);
|
||||
return -1;
|
||||
}
|
||||
|
||||
MALLOC_CHECK;
|
||||
saved_prog_arg = prog_arg;
|
||||
newargv0 = argv[0];
|
||||
firstarg = &newargv0;
|
||||
|
||||
/* If the file name ends in either .exe, .com, .bat, or .cmd we assume
|
||||
that it is NOT a script file */
|
||||
@ -351,8 +418,7 @@ spawn_guts (HANDLE hToken, const char * prog_arg, const char *const *argv,
|
||||
|
||||
if (buf[0] != '#' || buf[1] != '!')
|
||||
{
|
||||
strcpy (buf, "sh"); /* shell script without magic */
|
||||
pgm = buf;
|
||||
pgm = (char *) "/bin/sh";
|
||||
ptr = buf + 2;
|
||||
arg1 = NULL;
|
||||
}
|
||||
@ -379,87 +445,84 @@ spawn_guts (HANDLE hToken, const char * prog_arg, const char *const *argv,
|
||||
ptr = newptr - 1;
|
||||
}
|
||||
|
||||
|
||||
*ptr = '\0';
|
||||
}
|
||||
|
||||
char buf2[MAX_PATH + 1];
|
||||
|
||||
/* pointers:
|
||||
* pgm interpreter name
|
||||
* arg1 optional string
|
||||
* ptr end of string
|
||||
*/
|
||||
if (arg1)
|
||||
newargv.unshift (arg1);
|
||||
|
||||
if (!arg1)
|
||||
one_line.prepend (" ", 1);
|
||||
else
|
||||
{
|
||||
one_line.prepend ("\" ", 2);
|
||||
one_line.prepend (arg1, strlen (arg1));
|
||||
one_line.prepend (" \"", 2);
|
||||
}
|
||||
|
||||
find_exec (pgm, real_path_buf, "PATH=", 0, &ext);
|
||||
cygwin_conv_to_posix_path (real_path, buf2);
|
||||
one_line.prepend (buf2, strlen (buf2));
|
||||
|
||||
/* If script had absolute path, add it to script name now!
|
||||
* This is necessary if script has been found via PATH.
|
||||
* For example, /usr/local/bin/tkman started as "tkman":
|
||||
* #!/usr/local/bin/wish -f
|
||||
* ...
|
||||
* We should run /usr/local/bin/wish -f /usr/local/bin/tkman,
|
||||
* but not /usr/local/bin/wish -f tkman!
|
||||
* We don't modify anything, if script has qulified path.
|
||||
*/
|
||||
if (firstarg)
|
||||
*firstarg = saved_prog_arg;
|
||||
|
||||
debug_printf ("prog_arg '%s', copy '%s'", prog_arg, one_line.buf);
|
||||
firstarg = NULL;
|
||||
find_exec (pgm, real_path, "PATH=", 0, &ext);
|
||||
newargv.unshift (real_path, 1);
|
||||
}
|
||||
|
||||
for (; *argv; argv++)
|
||||
{
|
||||
char *p = NULL;
|
||||
const char *a = newargv0 ?: *argv;
|
||||
|
||||
MALLOC_CHECK;
|
||||
|
||||
newargv0 = NULL;
|
||||
int len = strlen (a);
|
||||
if (len != 0 && !strpbrk (a, " \t\n\r\""))
|
||||
one_line.add (a, len);
|
||||
else
|
||||
{
|
||||
one_line.add ("\"", 1);
|
||||
for (; (p = strpbrk (a, "\"\\")); a = ++p)
|
||||
{
|
||||
one_line.add (a, p - a);
|
||||
if (*p == '\\' || *p == '"')
|
||||
one_line.add ("\\", 1);
|
||||
one_line.add (p, 1);
|
||||
}
|
||||
if (*a)
|
||||
one_line.add (a);
|
||||
one_line.add ("\"", 1);
|
||||
}
|
||||
MALLOC_CHECK;
|
||||
one_line.add (" ", 1);
|
||||
MALLOC_CHECK;
|
||||
}
|
||||
|
||||
MALLOC_CHECK;
|
||||
if (one_line.ix)
|
||||
one_line.buf[one_line.ix - 1] = '\0';
|
||||
if (real_path.iscygexec ())
|
||||
for (int i = newargv.calloced; i < newargv.argc; i++)
|
||||
newargv[i] = cstrdup (newargv[i]);
|
||||
else
|
||||
one_line.add ("", 1);
|
||||
MALLOC_CHECK;
|
||||
{
|
||||
for (int i = 0; i < newargv.argc; i++)
|
||||
{
|
||||
char *p = NULL;
|
||||
const char *a;
|
||||
|
||||
if (i >= newargv.calloced)
|
||||
newargv[i] = cstrdup (newargv[i]);
|
||||
a = newargv[i];
|
||||
int len = strlen (a);
|
||||
if (len != 0 && !strpbrk (a, " \t\n\r\""))
|
||||
one_line.add (a, len);
|
||||
else
|
||||
{
|
||||
one_line.add ("\"", 1);
|
||||
for (; (p = strpbrk (a, "\"\\")); a = ++p)
|
||||
{
|
||||
one_line.add (a, p - a);
|
||||
if (*p == '\\' || *p == '"')
|
||||
one_line.add ("\\", 1);
|
||||
one_line.add (p, 1);
|
||||
}
|
||||
if (*a)
|
||||
one_line.add (a);
|
||||
one_line.add ("\"", 1);
|
||||
}
|
||||
MALLOC_CHECK;
|
||||
one_line.add (" ", 1);
|
||||
MALLOC_CHECK;
|
||||
}
|
||||
|
||||
MALLOC_CHECK;
|
||||
if (one_line.ix)
|
||||
one_line.buf[one_line.ix - 1] = '\0';
|
||||
else
|
||||
one_line.add ("", 1);
|
||||
MALLOC_CHECK;
|
||||
}
|
||||
ciresrv.moreinfo->argc = newargv.argc;
|
||||
ciresrv.moreinfo->argv = newargv;
|
||||
|
||||
/* FIXME: Should lock cwd access here. */
|
||||
ciresrv.moreinfo->cwd_posix = cwd_posix (NULL);
|
||||
ciresrv.moreinfo->cwd_win32 = cwd_win32 (NULL);
|
||||
ciresrv.moreinfo->cwd_hash = cwd_hash ();
|
||||
|
||||
ciresrv.moreinfo->environ = (char **) cmalloc (HEAP_ARGV, envsize (envp, 1));
|
||||
char **c;
|
||||
const char * const *e;
|
||||
for (c = ciresrv.moreinfo->environ, e = envp; *e; )
|
||||
*c++ = cstrdup (*e++);
|
||||
*c = NULL;
|
||||
if (mode != _P_OVERLAY ||
|
||||
!DuplicateHandle (hMainProc, myself.shared_handle (), hMainProc, &ciresrv.moreinfo->myself_pinfo, 0,
|
||||
TRUE, DUPLICATE_SAME_ACCESS))
|
||||
ciresrv.moreinfo->myself_pinfo = NULL;
|
||||
|
||||
skip_arg_parsing:
|
||||
PROCESS_INFORMATION pi = {NULL, 0, 0, 0};
|
||||
STARTUPINFO si = {0, NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL};
|
||||
si.lpReserved = NULL;
|
||||
si.lpDesktop = NULL;
|
||||
si.dwFlags = STARTF_USESTDHANDLES;
|
||||
@ -470,53 +533,7 @@ skip_arg_parsing:
|
||||
|
||||
/* Pass fd table to a child */
|
||||
|
||||
MALLOC_CHECK;
|
||||
int len = fdtab.linearize_fd_array (0, 0);
|
||||
MALLOC_CHECK;
|
||||
if (len == -1)
|
||||
{
|
||||
system_printf ("FATAL error in linearize_fd_array");
|
||||
return -1;
|
||||
}
|
||||
int titlelen = 1 + (old_title && mode == _P_OVERLAY ? strlen (old_title) : 0);
|
||||
si.cbReserved2 = len + titlelen + sizeof(child_info);
|
||||
si.lpReserved2 = (LPBYTE) alloca (si.cbReserved2);
|
||||
|
||||
# define ciresrv ((child_info *)si.lpReserved2)
|
||||
HANDLE spr = NULL;
|
||||
DWORD chtype;
|
||||
if (mode != _P_OVERLAY)
|
||||
chtype = PROC_SPAWN;
|
||||
else
|
||||
{
|
||||
spr = CreateEvent(&sec_all, TRUE, FALSE, NULL);
|
||||
ProtectHandle (spr);
|
||||
chtype = PROC_EXEC;
|
||||
}
|
||||
|
||||
init_child_info (chtype, ciresrv, (mode == _P_OVERLAY) ? myself->pid : 1, spr);
|
||||
if (mode != _P_OVERLAY ||
|
||||
!DuplicateHandle (hMainProc, myself.shared_handle (), hMainProc,
|
||||
&ciresrv->myself_pinfo, 0,
|
||||
TRUE, DUPLICATE_SAME_ACCESS))
|
||||
ciresrv->myself_pinfo = NULL;
|
||||
|
||||
LPBYTE resrv = si.lpReserved2 + sizeof *ciresrv;
|
||||
|
||||
if (fdtab.linearize_fd_array (resrv, len) < 0)
|
||||
{
|
||||
system_printf ("FATAL error in second linearize_fd_array");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (titlelen > 1)
|
||||
strcpy ((char *) resrv + len, old_title);
|
||||
else
|
||||
resrv[len] = '\0';
|
||||
|
||||
/* We print the translated program and arguments here so the user can see
|
||||
what was done to it. */
|
||||
syscall_printf ("spawn_guts (%s, %.132s)", real_path, one_line.buf);
|
||||
syscall_printf ("spawn_guts (%s, %.132s)", (char *) real_path, one_line.buf);
|
||||
|
||||
int flags = CREATE_DEFAULT_ERROR_MODE | CREATE_SUSPENDED |
|
||||
GetPriorityClass (hMainProc);
|
||||
@ -525,7 +542,14 @@ skip_arg_parsing:
|
||||
flags |= DETACHED_PROCESS;
|
||||
|
||||
/* Build windows style environment list */
|
||||
char *envblock = winenv (envp, 0);
|
||||
char *envblock;
|
||||
if (real_path.iscygexec ())
|
||||
envblock = NULL;
|
||||
else
|
||||
envblock = winenv (envp, 0);
|
||||
|
||||
ciresrv.cygheap = cygheap;
|
||||
ciresrv.cygheap_max = cygheap_max;
|
||||
|
||||
/* Preallocated buffer for `sec_user' call */
|
||||
char sa_buf[1024];
|
||||
@ -533,9 +557,12 @@ skip_arg_parsing:
|
||||
if (!hToken && myself->token != INVALID_HANDLE_VALUE)
|
||||
hToken = myself->token;
|
||||
|
||||
/* FIXME: This leaves a handle to the process open so that the pid is not
|
||||
duplicated. However, if a process execs another process two handles are
|
||||
left open, which is unnecessary. */
|
||||
if (mode == _P_OVERLAY && !hexec_proc &&
|
||||
!DuplicateHandle (hMainProc, hMainProc, hMainProc, &hexec_proc, 0,
|
||||
TRUE, DUPLICATE_SAME_ACCESS))
|
||||
TRUE, DUPLICATE_SAME_ACCESS))
|
||||
system_printf ("couldn't save current process handle %p, %E", hMainProc);
|
||||
|
||||
if (hToken)
|
||||
@ -561,22 +588,22 @@ skip_arg_parsing:
|
||||
PSID sid = NULL;
|
||||
DWORD ret_len;
|
||||
if (GetTokenInformation (hToken, TokenUser,
|
||||
(LPVOID) &tu, sizeof tu,
|
||||
&ret_len))
|
||||
sid = ((TOKEN_USER *) &tu)->User.Sid;
|
||||
(LPVOID) &tu, sizeof tu,
|
||||
&ret_len))
|
||||
sid = ((TOKEN_USER *) &tu)->User.Sid;
|
||||
else
|
||||
system_printf ("GetTokenInformation: %E");
|
||||
system_printf ("GetTokenInformation: %E");
|
||||
|
||||
/* Retrieve security attributes before setting psid to NULL
|
||||
since it's value is needed by `sec_user'. */
|
||||
since it's value is needed by `sec_user'. */
|
||||
PSECURITY_ATTRIBUTES sec_attribs = allow_ntsec && sid
|
||||
? sec_user (sa_buf, sid)
|
||||
: &sec_all_nih;
|
||||
? sec_user (sa_buf, sid)
|
||||
: &sec_all_nih;
|
||||
|
||||
/* Remove impersonation */
|
||||
uid_t uid = geteuid();
|
||||
if (myself->impersonated && myself->token != INVALID_HANDLE_VALUE)
|
||||
seteuid (myself->orig_uid);
|
||||
seteuid (myself->orig_uid);
|
||||
|
||||
/* Load users registry hive. */
|
||||
load_registry_hive (sid);
|
||||
@ -584,8 +611,8 @@ skip_arg_parsing:
|
||||
rc = CreateProcessAsUser (hToken,
|
||||
real_path, /* image name - with full path */
|
||||
one_line.buf, /* what was passed to exec */
|
||||
sec_attribs, /* process security attrs */
|
||||
sec_attribs, /* thread security attrs */
|
||||
sec_attribs, /* process security attrs */
|
||||
sec_attribs, /* thread security attrs */
|
||||
TRUE, /* inherit handles from parent */
|
||||
flags,
|
||||
envblock,/* environment */
|
||||
@ -593,18 +620,18 @@ skip_arg_parsing:
|
||||
&si,
|
||||
&pi);
|
||||
/* Restore impersonation. In case of _P_OVERLAY this isn't
|
||||
allowed since it would overwrite child data. */
|
||||
if (mode != _P_OVERLAY
|
||||
&& myself->impersonated && myself->token != INVALID_HANDLE_VALUE)
|
||||
seteuid (uid);
|
||||
allowed since it would overwrite child data. */
|
||||
if (mode != _P_OVERLAY && mode != _P_VFORK
|
||||
&& myself->impersonated && myself->token != INVALID_HANDLE_VALUE)
|
||||
seteuid (uid);
|
||||
}
|
||||
else
|
||||
rc = CreateProcessA (real_path, /* image name - with full path */
|
||||
one_line.buf, /* what was passed to exec */
|
||||
/* process security attrs */
|
||||
allow_ntsec ? sec_user (sa_buf) : &sec_all_nih,
|
||||
/* thread security attrs */
|
||||
allow_ntsec ? sec_user (sa_buf) : &sec_all_nih,
|
||||
/* process security attrs */
|
||||
allow_ntsec ? sec_user (sa_buf) : &sec_all_nih,
|
||||
/* thread security attrs */
|
||||
allow_ntsec ? sec_user (sa_buf) : &sec_all_nih,
|
||||
TRUE, /* inherit handles from parent */
|
||||
flags,
|
||||
envblock,/* environment */
|
||||
@ -613,17 +640,13 @@ skip_arg_parsing:
|
||||
&pi);
|
||||
|
||||
MALLOC_CHECK;
|
||||
free (envblock);
|
||||
if (envblock)
|
||||
free (envblock);
|
||||
MALLOC_CHECK;
|
||||
|
||||
if (ciresrv->myself_pinfo)
|
||||
CloseHandle (ciresrv->myself_pinfo);
|
||||
|
||||
/* Set errno now so that debugging messages from it appear before our
|
||||
final debugging message [this is a general rule for debugging
|
||||
messages]. */
|
||||
if (!rc)
|
||||
|
||||
if (!rc)
|
||||
{
|
||||
if (spr)
|
||||
@ -651,8 +674,8 @@ skip_arg_parsing:
|
||||
|
||||
if (mode == _P_OVERLAY)
|
||||
{
|
||||
close_all_files ();
|
||||
strcpy (myself->progname, real_path_buf);
|
||||
strcpy (myself->progname, real_path);
|
||||
// close_all_files ();
|
||||
proc_terminate ();
|
||||
hExeced = pi.hProcess;
|
||||
|
||||
@ -676,8 +699,6 @@ skip_arg_parsing:
|
||||
}
|
||||
child->username[0] = '\0';
|
||||
child->progname[0] = '\0';
|
||||
// CGF FIXME -- need to do this? strcpy (child->progname, path);
|
||||
// CGF FIXME -- need to do this? memcpy (child->username, myself->username, MAX_USER_NAME);
|
||||
child->ppid = myself->pid;
|
||||
child->uid = myself->uid;
|
||||
child->gid = myself->gid;
|
||||
@ -723,7 +744,7 @@ skip_arg_parsing:
|
||||
|
||||
DWORD res;
|
||||
|
||||
if (mode == _P_OVERLAY)
|
||||
if (mode == _P_OVERLAY || mode == _P_VFORK)
|
||||
{
|
||||
BOOL exited;
|
||||
|
||||
@ -732,54 +753,45 @@ skip_arg_parsing:
|
||||
|
||||
SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_HIGHEST);
|
||||
res = 0;
|
||||
DWORD timeout = INFINITE;
|
||||
exec_exit = 1;
|
||||
exited = FALSE;
|
||||
MALLOC_CHECK;
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
switch (WaitForMultipleObjects (nwait, waitbuf, FALSE, timeout))
|
||||
switch (WaitForMultipleObjects (nwait, waitbuf, FALSE, INFINITE))
|
||||
{
|
||||
case WAIT_TIMEOUT:
|
||||
syscall_printf ("WFMO timed out after signal");
|
||||
if (WaitForSingleObject (pi.hProcess, 0) != WAIT_OBJECT_0)
|
||||
{
|
||||
sigproc_printf ("subprocess still alive after signal");
|
||||
res = exec_exit;
|
||||
}
|
||||
else
|
||||
{
|
||||
sigproc_printf ("subprocess exited after signal");
|
||||
case WAIT_OBJECT_0:
|
||||
sigproc_printf ("subprocess exited");
|
||||
if (!GetExitCodeProcess (pi.hProcess, &res))
|
||||
res = exec_exit;
|
||||
exited = TRUE;
|
||||
}
|
||||
if (nwait > 2)
|
||||
if (WaitForSingleObject (spr, 1) == WAIT_OBJECT_0)
|
||||
res |= EXIT_REPARENTING;
|
||||
else if (!(res & EXIT_REPARENTING))
|
||||
{
|
||||
MALLOC_CHECK;
|
||||
close_all_files ();
|
||||
MALLOC_CHECK;
|
||||
}
|
||||
sigproc_printf ("subprocess exited");
|
||||
if (!GetExitCodeProcess (pi.hProcess, &res))
|
||||
res = 1;
|
||||
exited = TRUE;
|
||||
|
||||
if (nwait <= 2 || mode != _P_OVERLAY)
|
||||
/* nothing to do */;
|
||||
else if (WaitForSingleObject (spr, 1) == WAIT_OBJECT_0)
|
||||
goto reparent;
|
||||
else if (!(res & EXIT_REPARENTING))
|
||||
{
|
||||
MALLOC_CHECK;
|
||||
close_all_files ();
|
||||
MALLOC_CHECK;
|
||||
}
|
||||
break;
|
||||
case WAIT_OBJECT_0 + 1:
|
||||
sigproc_printf ("signal arrived");
|
||||
ResetEvent (signal_arrived);
|
||||
continue;
|
||||
case WAIT_OBJECT_0 + 2:
|
||||
res = EXIT_REPARENTING;
|
||||
MALLOC_CHECK;
|
||||
ForceCloseHandle (spr);
|
||||
MALLOC_CHECK;
|
||||
if (!parent_alive)
|
||||
if (mode == _P_OVERLAY)
|
||||
{
|
||||
nwait = 1;
|
||||
sigproc_terminate ();
|
||||
continue;
|
||||
reparent:
|
||||
res |= EXIT_REPARENTING;
|
||||
close_all_files ();
|
||||
if (!parent_alive)
|
||||
{
|
||||
nwait = 1;
|
||||
sigproc_terminate ();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WAIT_FAILED:
|
||||
@ -796,8 +808,7 @@ skip_arg_parsing:
|
||||
break;
|
||||
}
|
||||
|
||||
if (nwait > 2)
|
||||
ForceCloseHandle (spr);
|
||||
ForceCloseHandle (spr);
|
||||
|
||||
sigproc_printf ("res = %x", res);
|
||||
|
||||
@ -813,18 +824,19 @@ skip_arg_parsing:
|
||||
/* nothing */;
|
||||
else
|
||||
{
|
||||
int rc;
|
||||
HANDLE hP = OpenProcess (PROCESS_ALL_ACCESS, FALSE,
|
||||
parent->dwProcessId);
|
||||
sigproc_printf ("parent handle %p, pid %d", hP, parent->dwProcessId);
|
||||
if (hP == NULL && GetLastError () == ERROR_INVALID_PARAMETER)
|
||||
res = 1;
|
||||
rc = 1;
|
||||
else if (hP)
|
||||
{
|
||||
ProtectHandle (hP);
|
||||
res = DuplicateHandle (hMainProc, pi.hProcess, hP,
|
||||
&myself->hProcess, 0, FALSE,
|
||||
DUPLICATE_SAME_ACCESS);
|
||||
sigproc_printf ("Dup hP %d", res);
|
||||
rc = DuplicateHandle (hMainProc, pi.hProcess, hP,
|
||||
&myself->hProcess, 0, FALSE,
|
||||
DUPLICATE_SAME_ACCESS);
|
||||
sigproc_printf ("Dup hP %d", rc);
|
||||
ForceCloseHandle (hP);
|
||||
}
|
||||
if (!res)
|
||||
@ -837,7 +849,6 @@ skip_arg_parsing:
|
||||
system_printf ("myself->hProcess %x", myself->hProcess);
|
||||
}
|
||||
}
|
||||
res = EXIT_REPARENTING;
|
||||
ForceCloseHandle1 (hExeced, childhProc);
|
||||
hExeced = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
@ -848,15 +859,26 @@ skip_arg_parsing:
|
||||
}
|
||||
|
||||
MALLOC_CHECK;
|
||||
do_exit (res | EXIT_NOCLOSEALL);
|
||||
if (mode == _P_OVERLAY)
|
||||
do_exit (res | EXIT_NOCLOSEALL);
|
||||
}
|
||||
|
||||
if (mode == _P_WAIT)
|
||||
waitpid (cygpid, (int *) &res, 0);
|
||||
else if (mode == _P_DETACH)
|
||||
res = 0; /* Lose all memory of this child. */
|
||||
else if ((mode == _P_NOWAIT) || (mode == _P_NOWAITO))
|
||||
res = cygpid;
|
||||
switch (mode)
|
||||
{
|
||||
case _P_WAIT:
|
||||
waitpid (cygpid, (int *) &res, 0);
|
||||
break;
|
||||
case _P_DETACH:
|
||||
res = 0; /* Lose all memory of this child. */
|
||||
break;
|
||||
case _P_NOWAIT:
|
||||
case _P_NOWAITO:
|
||||
case _P_VFORK:
|
||||
res = cygpid;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return (int) res;
|
||||
}
|
||||
@ -889,29 +911,30 @@ _spawnve (HANDLE hToken, int mode, const char *path, const char *const *argv,
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case _P_OVERLAY:
|
||||
/* We do not pass _P_SEARCH_PATH here. execve doesn't search PATH.*/
|
||||
/* Just act as an exec if _P_OVERLAY set. */
|
||||
spawn_guts (hToken, path, argv, envp, mode);
|
||||
/* Errno should be set by spawn_guts. */
|
||||
ret = -1;
|
||||
break;
|
||||
case _P_NOWAIT:
|
||||
case _P_NOWAITO:
|
||||
case _P_WAIT:
|
||||
case _P_DETACH:
|
||||
subproc_init ();
|
||||
ret = spawn_guts (hToken, path, argv, envp, mode);
|
||||
if (vf && ret > 0)
|
||||
{
|
||||
vf->pid = ret;
|
||||
longjmp (vf->j, 1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
set_errno (EINVAL);
|
||||
ret = -1;
|
||||
break;
|
||||
case _P_OVERLAY:
|
||||
/* We do not pass _P_SEARCH_PATH here. execve doesn't search PATH.*/
|
||||
/* Just act as an exec if _P_OVERLAY set. */
|
||||
spawn_guts (hToken, path, argv, envp, mode);
|
||||
/* Errno should be set by spawn_guts. */
|
||||
ret = -1;
|
||||
break;
|
||||
case _P_VFORK:
|
||||
case _P_NOWAIT:
|
||||
case _P_NOWAITO:
|
||||
case _P_WAIT:
|
||||
case _P_DETACH:
|
||||
subproc_init ();
|
||||
ret = spawn_guts (hToken, path, argv, envp, 0);
|
||||
if (vf && ret > 0)
|
||||
{
|
||||
vf->pid = ret;
|
||||
longjmp (vf->j, 1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
set_errno (EINVAL);
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
Reference in New Issue
Block a user