Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin/spawn.cc')
-rw-r--r--winsup/cygwin/spawn.cc105
1 files changed, 52 insertions, 53 deletions
diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc
index af177c0f1..8308bccf3 100644
--- a/winsup/cygwin/spawn.cc
+++ b/winsup/cygwin/spawn.cc
@@ -177,7 +177,7 @@ find_exec (const char *name, path_conv& buf, const char *search,
/* Utility for child_info_spawn::worker. */
static HANDLE
-handle (int fd, bool writing, bool iscygwin)
+handle (int fd, bool writing)
{
HANDLE h;
cygheap_fdget cfd (fd);
@@ -188,17 +188,30 @@ handle (int fd, bool writing, bool iscygwin)
h = INVALID_HANDLE_VALUE;
else if (!writing)
h = cfd->get_handle ();
- else if (cfd->get_major () == DEV_PTYS_MAJOR && iscygwin)
- {
- fhandler_pty_slave *ptys = (fhandler_pty_slave *)(fhandler_base *) cfd;
- h = ptys->get_output_handle_cyg ();
- }
else
h = cfd->get_output_handle ();
return h;
}
+static bool
+is_console_app (WCHAR *filename)
+{
+ HANDLE h;
+ const int id_offset = 92;
+ h = CreateFileW (filename, GENERIC_READ, FILE_SHARE_READ,
+ NULL, OPEN_EXISTING, 0, NULL);
+ char buf[1024];
+ DWORD n;
+ ReadFile (h, buf, sizeof (buf), &n, 0);
+ CloseHandle (h);
+ char *p = (char *) memmem (buf, n, "PE\0\0", 4);
+ if (p && p + id_offset <= buf + n)
+ return p[id_offset] == '\003'; /* 02: GUI, 03: console */
+ else
+ return false;
+}
+
int
iscmd (const char *argv0, const char *what)
{
@@ -266,8 +279,6 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
{
bool rc;
int res = -1;
- DWORD pid_restore = 0;
- bool attach_to_console = false;
pid_t ctty_pgid = 0;
/* Search for CTTY and retrieve its PGID */
@@ -587,9 +598,7 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
PROCESS_QUERY_LIMITED_INFORMATION))
sa = &sec_none_nih;
- /* Attach to pseudo console if pty salve is used */
- pid_restore = fhandler_console::get_console_process_id
- (GetCurrentProcessId (), false);
+ fhandler_pty_slave *ptys_primary = NULL;
for (int i = 0; i < 3; i ++)
{
const int chk_order[] = {1, 0, 2};
@@ -598,29 +607,11 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
if (fh && fh->get_major () == DEV_PTYS_MAJOR)
{
fhandler_pty_slave *ptys = (fhandler_pty_slave *) fh;
- if (ptys->get_pseudo_console ())
- {
- DWORD helper_process_id = ptys->get_helper_process_id ();
- debug_printf ("found a PTY slave %d: helper_PID=%d",
- fh->get_minor (), helper_process_id);
- if (fhandler_console::get_console_process_id
- (helper_process_id, true))
- /* Already attached */
- attach_to_console = true;
- else if (!attach_to_console)
- {
- FreeConsole ();
- if (AttachConsole (helper_process_id))
- attach_to_console = true;
- }
- ptys->fixup_after_attach (!iscygwin (), fd);
- if (mode == _P_OVERLAY)
- ptys->set_freeconsole_on_close (iscygwin ());
- }
+ if (ptys_primary == NULL)
+ ptys_primary = ptys;
}
else if (fh && fh->get_major () == DEV_CONS_MAJOR)
{
- attach_to_console = true;
fhandler_console *cons = (fhandler_console *) fh;
if (wincap.has_con_24bit_colors () && !iscygwin ())
if (fd == 1 || fd == 2)
@@ -642,17 +633,28 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
/* Set up needed handles for stdio */
si.dwFlags = STARTF_USESTDHANDLES;
- si.hStdInput = handle ((in__stdin < 0 ? 0 : in__stdin), false,
- iscygwin ());
- si.hStdOutput = handle ((in__stdout < 0 ? 1 : in__stdout), true,
- iscygwin ());
- si.hStdError = handle (2, true, iscygwin ());
+ si.hStdInput = handle ((in__stdin < 0 ? 0 : in__stdin), false);
+ si.hStdOutput = handle ((in__stdout < 0 ? 1 : in__stdout), true);
+ si.hStdError = handle (2, true);
si.cb = sizeof (si);
if (!iscygwin ())
init_console_handler (myself->ctty > 0);
+ bool enable_pcon = false;
+ STARTUPINFOEXW si_pcon;
+ ZeroMemory (&si_pcon, sizeof (si_pcon));
+ STARTUPINFOW *si_tmp = &si;
+ if (!iscygwin () && ptys_primary && is_console_app (runpath))
+ if (ptys_primary->setup_pseudoconsole (&si_pcon,
+ mode != _P_OVERLAY && mode != _P_WAIT))
+ {
+ c_flags |= EXTENDED_STARTUPINFO_PRESENT;
+ si_tmp = &si_pcon.StartupInfo;
+ enable_pcon = true;
+ }
+
loop:
/* When ruid != euid we create the new process under the current original
account and impersonate in child, this way maintaining the different
@@ -681,7 +683,7 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
c_flags,
envblock, /* environment */
NULL,
- &si,
+ si_tmp,
&pi);
}
else
@@ -735,7 +737,7 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
c_flags,
envblock, /* environment */
NULL,
- &si,
+ si_tmp,
&pi);
if (hwst)
{
@@ -748,6 +750,11 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
CloseDesktop (hdsk);
}
}
+ if (enable_pcon)
+ {
+ DeleteProcThreadAttributeList (si_pcon.lpAttributeList);
+ HeapFree (GetProcessHeap (), 0, si_pcon.lpAttributeList);
+ }
if (mode != _P_OVERLAY)
SetHandleInformation (my_wr_proc_pipe, HANDLE_FLAG_INHERIT,
@@ -920,6 +927,11 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
}
if (sem)
__posix_spawn_sem_release (sem, 0);
+ if (enable_pcon)
+ {
+ WaitForSingleObject (pi.hProcess, INFINITE);
+ ptys_primary->close_pseudoconsole ();
+ }
myself.exit (EXITCODE_NOSET);
break;
case _P_WAIT:
@@ -927,6 +939,8 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
system_call.arm ();
if (waitpid (cygpid, &res, 0) != cygpid)
res = -1;
+ if (enable_pcon)
+ ptys_primary->close_pseudoconsole ();
break;
case _P_DETACH:
res = 0; /* Lost all memory of this child. */
@@ -953,21 +967,6 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
if (envblock)
free (envblock);
- if (attach_to_console && pid_restore)
- {
- FreeConsole ();
- AttachConsole (pid_restore);
- cygheap_fdenum cfd (false);
- int fd;
- while ((fd = cfd.next ()) >= 0)
- if (cfd->get_major () == DEV_PTYS_MAJOR)
- {
- fhandler_pty_slave *ptys =
- (fhandler_pty_slave *) (fhandler_base *) cfd;
- ptys->fixup_after_attach (false, fd);
- }
- }
-
return (int) res;
}