mirror of
git://sourceware.org/git/newlib-cygwin.git
synced 2025-02-02 12:30:24 +08:00
Cygwin: pty: Inherit typeahead data between two input pipes.
- PTY has a problem that the key input, which is typed during windows native app is running, disappears when it returns to shell. This is beacuse pty has two input pipes, one is for cygwin apps and the other one is for native windows apps. The key input during windows native program is running is sent to the second input pipe while cygwin shell reads input from the first input pipe. This issue had been fixed once by commit 29431fcb, however, the new implementation of pseudo console support by commit bb428520 could not inherit this feature. This patch realize transfering input data between these two pipes bidirectionally by utilizing cygwin-console-helper process. The helper process is launched prior to starting the non-cygwin app, however, exits immediately unlike previous implementation.
This commit is contained in:
parent
0ef6b1ec59
commit
0ed1104b9a
@ -2482,6 +2482,13 @@ class fhandler_pty_slave: public fhandler_pty_common
|
|||||||
void fch_close_handles ();
|
void fch_close_handles ();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
/* Transfer direction for transfer_input() */
|
||||||
|
enum xfer_dir
|
||||||
|
{
|
||||||
|
to_nat,
|
||||||
|
to_cyg
|
||||||
|
};
|
||||||
|
|
||||||
/* Constructor */
|
/* Constructor */
|
||||||
fhandler_pty_slave (int);
|
fhandler_pty_slave (int);
|
||||||
|
|
||||||
@ -2533,7 +2540,7 @@ class fhandler_pty_slave: public fhandler_pty_common
|
|||||||
copyto (fh);
|
copyto (fh);
|
||||||
return fh;
|
return fh;
|
||||||
}
|
}
|
||||||
bool setup_pseudoconsole (STARTUPINFOEXW *si, bool nopcon);
|
bool setup_pseudoconsole (bool nopcon);
|
||||||
static void close_pseudoconsole (tty *ttyp);
|
static void close_pseudoconsole (tty *ttyp);
|
||||||
bool term_has_pcon_cap (const WCHAR *env);
|
bool term_has_pcon_cap (const WCHAR *env);
|
||||||
void set_switch_to_pcon (void);
|
void set_switch_to_pcon (void);
|
||||||
@ -2542,6 +2549,9 @@ class fhandler_pty_slave: public fhandler_pty_common
|
|||||||
void setup_locale (void);
|
void setup_locale (void);
|
||||||
tty *get_ttyp () { return (tty *) tc (); } /* Override as public */
|
tty *get_ttyp () { return (tty *) tc (); } /* Override as public */
|
||||||
void create_invisible_console (void);
|
void create_invisible_console (void);
|
||||||
|
static void transfer_input (xfer_dir dir, HANDLE from, tty *ttyp,
|
||||||
|
_minor_t unit, HANDLE input_available_event);
|
||||||
|
HANDLE get_input_available_event (void) { return input_available_event; }
|
||||||
};
|
};
|
||||||
|
|
||||||
#define __ptsname(buf, unit) __small_sprintf ((buf), "/dev/pty%d", (unit))
|
#define __ptsname(buf, unit) __small_sprintf ((buf), "/dev/pty%d", (unit))
|
||||||
@ -2554,6 +2564,8 @@ public:
|
|||||||
HANDLE from_master_cyg;
|
HANDLE from_master_cyg;
|
||||||
HANDLE to_master;
|
HANDLE to_master;
|
||||||
HANDLE to_master_cyg;
|
HANDLE to_master_cyg;
|
||||||
|
HANDLE to_slave;
|
||||||
|
HANDLE to_slave_cyg;
|
||||||
HANDLE master_ctl;
|
HANDLE master_ctl;
|
||||||
HANDLE input_available_event;
|
HANDLE input_available_event;
|
||||||
};
|
};
|
||||||
|
@ -56,6 +56,8 @@ struct pipe_reply {
|
|||||||
HANDLE from_master_cyg;
|
HANDLE from_master_cyg;
|
||||||
HANDLE to_master;
|
HANDLE to_master;
|
||||||
HANDLE to_master_cyg;
|
HANDLE to_master_cyg;
|
||||||
|
HANDLE to_slave;
|
||||||
|
HANDLE to_slave_cyg;
|
||||||
DWORD error;
|
DWORD error;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -848,8 +850,14 @@ fhandler_pty_slave::reset_switch_to_pcon (void)
|
|||||||
return;
|
return;
|
||||||
if (isHybrid)
|
if (isHybrid)
|
||||||
return;
|
return;
|
||||||
|
if (get_ttyp ()->switch_to_pcon_in && !get_ttyp ()->h_pseudo_console)
|
||||||
|
fhandler_pty_slave::transfer_input (fhandler_pty_slave::to_cyg,
|
||||||
|
get_handle (),
|
||||||
|
get_ttyp (), get_minor (),
|
||||||
|
input_available_event);
|
||||||
get_ttyp ()->pcon_pid = 0;
|
get_ttyp ()->pcon_pid = 0;
|
||||||
get_ttyp ()->switch_to_pcon_in = false;
|
get_ttyp ()->switch_to_pcon_in = false;
|
||||||
|
get_ttyp ()->h_pseudo_console = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t __stdcall
|
ssize_t __stdcall
|
||||||
@ -891,6 +899,22 @@ fhandler_pty_slave::write (const void *ptr, size_t len)
|
|||||||
void
|
void
|
||||||
fhandler_pty_slave::mask_switch_to_pcon_in (bool mask)
|
fhandler_pty_slave::mask_switch_to_pcon_in (bool mask)
|
||||||
{
|
{
|
||||||
|
if (get_ttyp ()->switch_to_pcon_in
|
||||||
|
&& (get_ttyp ()->pcon_pid == myself->pid
|
||||||
|
|| !get_ttyp ()->h_pseudo_console)
|
||||||
|
&& get_ttyp ()->mask_switch_to_pcon_in != mask)
|
||||||
|
{
|
||||||
|
if (mask)
|
||||||
|
fhandler_pty_slave::transfer_input (fhandler_pty_slave::to_cyg,
|
||||||
|
get_handle (),
|
||||||
|
get_ttyp (), get_minor (),
|
||||||
|
input_available_event);
|
||||||
|
else
|
||||||
|
fhandler_pty_slave::transfer_input (fhandler_pty_slave::to_nat,
|
||||||
|
get_handle_cyg (),
|
||||||
|
get_ttyp (), get_minor (),
|
||||||
|
input_available_event);
|
||||||
|
}
|
||||||
get_ttyp ()->mask_switch_to_pcon_in = mask;
|
get_ttyp ()->mask_switch_to_pcon_in = mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1840,7 +1864,7 @@ fhandler_pty_common::resize_pseudo_console (struct winsize *ws)
|
|||||||
size.X = ws->ws_col;
|
size.X = ws->ws_col;
|
||||||
size.Y = ws->ws_row;
|
size.Y = ws->ws_row;
|
||||||
pinfo p (get_ttyp ()->pcon_pid);
|
pinfo p (get_ttyp ()->pcon_pid);
|
||||||
if (p && !get_ttyp ()->do_not_resize_pcon)
|
if (p)
|
||||||
{
|
{
|
||||||
HPCON_INTERNAL hpcon_local;
|
HPCON_INTERNAL hpcon_local;
|
||||||
HANDLE pcon_owner =
|
HANDLE pcon_owner =
|
||||||
@ -2012,6 +2036,17 @@ fhandler_pty_master::write (const void *ptr, size_t len)
|
|||||||
get_ttyp ()->pcon_start = false;
|
get_ttyp ()->pcon_start = false;
|
||||||
}
|
}
|
||||||
ReleaseMutex (input_mutex);
|
ReleaseMutex (input_mutex);
|
||||||
|
if (get_ttyp ()->switch_to_pcon_in)
|
||||||
|
{
|
||||||
|
fhandler_pty_slave::transfer_input (fhandler_pty_slave::to_nat,
|
||||||
|
from_master_cyg,
|
||||||
|
get_ttyp (), get_minor (),
|
||||||
|
input_available_event);
|
||||||
|
/* This accept_input() call is needed in order to transfer input
|
||||||
|
which is not accepted yet to non-cygwin pipe. */
|
||||||
|
if (get_readahead_valid ())
|
||||||
|
accept_input ();
|
||||||
|
}
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2232,7 +2267,7 @@ fhandler_pty_master::pty_master_thread (const master_thread_param_t *p)
|
|||||||
while (!exit && (ConnectNamedPipe (p->master_ctl, NULL)
|
while (!exit && (ConnectNamedPipe (p->master_ctl, NULL)
|
||||||
|| GetLastError () == ERROR_PIPE_CONNECTED))
|
|| GetLastError () == ERROR_PIPE_CONNECTED))
|
||||||
{
|
{
|
||||||
pipe_reply repl = { NULL, NULL, NULL, NULL, 0 };
|
pipe_reply repl = { NULL, NULL, NULL, NULL, NULL, NULL, 0 };
|
||||||
bool deimp = false;
|
bool deimp = false;
|
||||||
NTSTATUS allow = STATUS_ACCESS_DENIED;
|
NTSTATUS allow = STATUS_ACCESS_DENIED;
|
||||||
ACCESS_MASK access = EVENT_MODIFY_STATE;
|
ACCESS_MASK access = EVENT_MODIFY_STATE;
|
||||||
@ -2323,6 +2358,20 @@ fhandler_pty_master::pty_master_thread (const master_thread_param_t *p)
|
|||||||
termios_printf ("DuplicateHandle (to_master_cyg), %E");
|
termios_printf ("DuplicateHandle (to_master_cyg), %E");
|
||||||
goto reply;
|
goto reply;
|
||||||
}
|
}
|
||||||
|
if (!DuplicateHandle (GetCurrentProcess (), p->to_slave,
|
||||||
|
client, &repl.to_slave,
|
||||||
|
0, TRUE, DUPLICATE_SAME_ACCESS))
|
||||||
|
{
|
||||||
|
termios_printf ("DuplicateHandle (to_slave), %E");
|
||||||
|
goto reply;
|
||||||
|
}
|
||||||
|
if (!DuplicateHandle (GetCurrentProcess (), p->to_slave_cyg,
|
||||||
|
client, &repl.to_slave_cyg,
|
||||||
|
0, TRUE, DUPLICATE_SAME_ACCESS))
|
||||||
|
{
|
||||||
|
termios_printf ("DuplicateHandle (to_slave_cyg), %E");
|
||||||
|
goto reply;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
reply:
|
reply:
|
||||||
repl.error = GetLastError ();
|
repl.error = GetLastError ();
|
||||||
@ -2379,22 +2428,44 @@ fhandler_pty_master::pty_master_fwd_thread (const master_fwd_thread_param_t *p)
|
|||||||
char *ptr = outbuf;
|
char *ptr = outbuf;
|
||||||
if (p->ttyp->h_pseudo_console)
|
if (p->ttyp->h_pseudo_console)
|
||||||
{
|
{
|
||||||
if (!p->ttyp->has_set_title)
|
/* Avoid setting window title to "cygwin-console-helper.exe" */
|
||||||
{
|
|
||||||
/* Remove Set title sequence */
|
|
||||||
char *p0, *p1;
|
|
||||||
p0 = outbuf;
|
|
||||||
while ((p0 = (char *) memmem (p0, rlen, "\033]0;", 4))
|
|
||||||
&& (p1 = (char *) memchr (p0, '\007', rlen-(p0-outbuf))))
|
|
||||||
{
|
|
||||||
memmove (p0, p1 + 1, rlen - (p1 + 1 - outbuf));
|
|
||||||
rlen -= p1 + 1 - p0;
|
|
||||||
wlen = rlen;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Remove CSI > Pm m */
|
|
||||||
int state = 0;
|
int state = 0;
|
||||||
int start_at = 0;
|
int start_at = 0;
|
||||||
|
for (DWORD i=0; i<rlen; i++)
|
||||||
|
if (outbuf[i] == '\033')
|
||||||
|
{
|
||||||
|
start_at = i;
|
||||||
|
state = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if ((state == 1 && outbuf[i] == ']') ||
|
||||||
|
(state == 2 && outbuf[i] == '0') ||
|
||||||
|
(state == 3 && outbuf[i] == ';'))
|
||||||
|
{
|
||||||
|
state ++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (state == 4 && outbuf[i] == '\a')
|
||||||
|
{
|
||||||
|
const char *helper_str = "\\bin\\cygwin-console-helper.exe";
|
||||||
|
if (memmem (&outbuf[start_at], i + 1 - start_at,
|
||||||
|
helper_str, strlen (helper_str)))
|
||||||
|
{
|
||||||
|
memmove (&outbuf[start_at], &outbuf[i+1], rlen-i-1);
|
||||||
|
rlen = wlen = start_at + rlen - i - 1;
|
||||||
|
}
|
||||||
|
state = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (outbuf[i] == '\a')
|
||||||
|
{
|
||||||
|
state = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove CSI > Pm m */
|
||||||
|
state = 0;
|
||||||
|
start_at = 0;
|
||||||
for (DWORD i = 0; i < rlen; i++)
|
for (DWORD i = 0; i < rlen; i++)
|
||||||
if (outbuf[i] == '\033')
|
if (outbuf[i] == '\033')
|
||||||
{
|
{
|
||||||
@ -2668,6 +2739,8 @@ fhandler_pty_master::setup ()
|
|||||||
t.set_from_master_cyg (from_master_cyg);
|
t.set_from_master_cyg (from_master_cyg);
|
||||||
t.set_to_master (to_master);
|
t.set_to_master (to_master);
|
||||||
t.set_to_master_cyg (to_master_cyg);
|
t.set_to_master_cyg (to_master_cyg);
|
||||||
|
t.set_to_slave (to_slave);
|
||||||
|
t.set_to_slave_cyg (get_output_handle ());
|
||||||
t.winsize.ws_col = 80;
|
t.winsize.ws_col = 80;
|
||||||
t.winsize.ws_row = 25;
|
t.winsize.ws_row = 25;
|
||||||
t.master_pid = myself->pid;
|
t.master_pid = myself->pid;
|
||||||
@ -2828,10 +2901,15 @@ fhandler_pty_common::process_opost_output (HANDLE h, const void *ptr,
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Pseudo console supprot is realized using a tricky technic.
|
||||||
|
PTY need the pseudo console handles, however, they cannot
|
||||||
|
be retrieved by normal procedure. Therefore, run a helper
|
||||||
|
process in a pseudo console and get them from the helper.
|
||||||
|
Slave process will attach to the pseudo console in the
|
||||||
|
helper process using AttachConsole(). */
|
||||||
bool
|
bool
|
||||||
fhandler_pty_slave::setup_pseudoconsole (STARTUPINFOEXW *si, bool nopcon)
|
fhandler_pty_slave::setup_pseudoconsole (bool nopcon)
|
||||||
{
|
{
|
||||||
|
|
||||||
/* Setting switch_to_pcon_in is necessary even if
|
/* Setting switch_to_pcon_in is necessary even if
|
||||||
pseudo console will not be activated. */
|
pseudo console will not be activated. */
|
||||||
fhandler_base *fh = ::cygheap->fdtab[0];
|
fhandler_base *fh = ::cygheap->fdtab[0];
|
||||||
@ -2862,60 +2940,151 @@ fhandler_pty_slave::setup_pseudoconsole (STARTUPINFOEXW *si, bool nopcon)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
COORD size = {
|
STARTUPINFOEXW si;
|
||||||
(SHORT) get_ttyp ()->winsize.ws_col,
|
PROCESS_INFORMATION pi;
|
||||||
(SHORT) get_ttyp ()->winsize.ws_row
|
HANDLE hello, goodbye;
|
||||||
};
|
HANDLE hr, hw;
|
||||||
const DWORD inherit_cursor = 1;
|
HANDLE hpConIn, hpConOut;
|
||||||
SetLastError (ERROR_SUCCESS);
|
|
||||||
HRESULT res = CreatePseudoConsole (size, get_handle (), get_output_handle (),
|
do
|
||||||
inherit_cursor,
|
|
||||||
&get_ttyp ()->h_pseudo_console);
|
|
||||||
if (res != S_OK || GetLastError () == ERROR_PROC_NOT_FOUND)
|
|
||||||
{
|
{
|
||||||
if (res != S_OK)
|
COORD size = {
|
||||||
system_printf ("CreatePseudoConsole() failed. %08x %08x\n",
|
(SHORT) get_ttyp ()->winsize.ws_col,
|
||||||
GetLastError (), res);
|
(SHORT) get_ttyp ()->winsize.ws_row
|
||||||
goto fallback;
|
};
|
||||||
|
const DWORD inherit_cursor = 1;
|
||||||
|
SetLastError (ERROR_SUCCESS);
|
||||||
|
HRESULT res = CreatePseudoConsole (size, get_handle (),
|
||||||
|
get_output_handle (),
|
||||||
|
inherit_cursor,
|
||||||
|
&get_ttyp ()->h_pseudo_console);
|
||||||
|
if (res != S_OK || GetLastError () == ERROR_PROC_NOT_FOUND)
|
||||||
|
{
|
||||||
|
if (res != S_OK)
|
||||||
|
system_printf ("CreatePseudoConsole() failed. %08x %08x\n",
|
||||||
|
GetLastError (), res);
|
||||||
|
goto fallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
SIZE_T bytesRequired;
|
||||||
|
InitializeProcThreadAttributeList (NULL, 2, 0, &bytesRequired);
|
||||||
|
ZeroMemory (&si, sizeof (si));
|
||||||
|
si.StartupInfo.cb = sizeof (STARTUPINFOEXW);
|
||||||
|
si.lpAttributeList = (PPROC_THREAD_ATTRIBUTE_LIST)
|
||||||
|
HeapAlloc (GetProcessHeap (), 0, bytesRequired);
|
||||||
|
if (si.lpAttributeList == NULL)
|
||||||
|
goto cleanup_pseudo_console;
|
||||||
|
if (!InitializeProcThreadAttributeList (si.lpAttributeList,
|
||||||
|
2, 0, &bytesRequired))
|
||||||
|
goto cleanup_heap;
|
||||||
|
if (!UpdateProcThreadAttribute (si.lpAttributeList,
|
||||||
|
0,
|
||||||
|
PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE,
|
||||||
|
get_ttyp ()->h_pseudo_console,
|
||||||
|
sizeof (get_ttyp ()->h_pseudo_console),
|
||||||
|
NULL, NULL))
|
||||||
|
|
||||||
|
goto cleanup_heap;
|
||||||
|
|
||||||
|
hello = CreateEvent (&sec_none, true, false, NULL);
|
||||||
|
goodbye = CreateEvent (&sec_none, true, false, NULL);
|
||||||
|
CreatePipe (&hr, &hw, &sec_none, 0);
|
||||||
|
|
||||||
|
HANDLE handles_to_inherit[] = {hello, goodbye, hw};
|
||||||
|
if (!UpdateProcThreadAttribute (si.lpAttributeList,
|
||||||
|
0,
|
||||||
|
PROC_THREAD_ATTRIBUTE_HANDLE_LIST,
|
||||||
|
handles_to_inherit,
|
||||||
|
sizeof (handles_to_inherit),
|
||||||
|
NULL, NULL))
|
||||||
|
goto cleanup_event_and_pipes;
|
||||||
|
|
||||||
|
/* Execute helper process */
|
||||||
|
WCHAR cmd[MAX_PATH];
|
||||||
|
path_conv helper ("/bin/cygwin-console-helper.exe");
|
||||||
|
size_t len = helper.get_wide_win32_path_len ();
|
||||||
|
helper.get_wide_win32_path (cmd);
|
||||||
|
__small_swprintf (cmd + len, L" %p %p %p", hello, goodbye, hw);
|
||||||
|
si.StartupInfo.dwFlags = STARTF_USESTDHANDLES;
|
||||||
|
si.StartupInfo.hStdInput = NULL;
|
||||||
|
si.StartupInfo.hStdOutput = NULL;
|
||||||
|
si.StartupInfo.hStdError = NULL;
|
||||||
|
|
||||||
|
get_ttyp ()->pcon_start = true;
|
||||||
|
if (!CreateProcessW (NULL, cmd, &sec_none, &sec_none,
|
||||||
|
TRUE, EXTENDED_STARTUPINFO_PRESENT,
|
||||||
|
NULL, NULL, &si.StartupInfo, &pi))
|
||||||
|
goto cleanup_event_and_pipes;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
DWORD wait_result = WaitForSingleObject (hello, 500);
|
||||||
|
if (wait_result == WAIT_OBJECT_0)
|
||||||
|
break;
|
||||||
|
if (wait_result != WAIT_TIMEOUT)
|
||||||
|
goto cleanup_helper_process;
|
||||||
|
DWORD exit_code;
|
||||||
|
if (!GetExitCodeProcess (pi.hProcess, &exit_code))
|
||||||
|
goto cleanup_helper_process;
|
||||||
|
if (exit_code == STILL_ACTIVE)
|
||||||
|
continue;
|
||||||
|
if (exit_code != 0 ||
|
||||||
|
WaitForSingleObject (hello, 500) != WAIT_OBJECT_0)
|
||||||
|
goto cleanup_helper_process;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
CloseHandle (hello);
|
||||||
|
CloseHandle (pi.hThread);
|
||||||
|
|
||||||
|
/* Duplicate pseudo console handles */
|
||||||
|
DWORD rlen;
|
||||||
|
char buf[64];
|
||||||
|
if (!ReadFile (hr, buf, sizeof (buf), &rlen, NULL))
|
||||||
|
goto cleanup_helper_process;
|
||||||
|
buf[rlen] = '\0';
|
||||||
|
sscanf (buf, "StdHandles=%p,%p", &hpConIn, &hpConOut);
|
||||||
|
if (!DuplicateHandle (pi.hProcess, hpConIn,
|
||||||
|
GetCurrentProcess (), &hpConIn, 0,
|
||||||
|
TRUE, DUPLICATE_SAME_ACCESS))
|
||||||
|
goto cleanup_helper_process;
|
||||||
|
if (!DuplicateHandle (pi.hProcess, hpConOut,
|
||||||
|
GetCurrentProcess (), &hpConOut, 0,
|
||||||
|
TRUE, DUPLICATE_SAME_ACCESS))
|
||||||
|
goto cleanup_pcon_in;
|
||||||
|
|
||||||
|
CloseHandle (hr);
|
||||||
|
CloseHandle (hw);
|
||||||
|
DeleteProcThreadAttributeList (si.lpAttributeList);
|
||||||
|
HeapFree (GetProcessHeap (), 0, si.lpAttributeList);
|
||||||
|
|
||||||
|
/* Attach to pseudo console */
|
||||||
|
FreeConsole ();
|
||||||
|
AttachConsole (pi.dwProcessId);
|
||||||
|
|
||||||
|
/* Terminate helper process */
|
||||||
|
SetEvent (goodbye);
|
||||||
|
WaitForSingleObject (pi.hProcess, INFINITE);
|
||||||
|
CloseHandle (goodbye);
|
||||||
|
CloseHandle (pi.hProcess);
|
||||||
|
|
||||||
|
/* Set handle */
|
||||||
|
HANDLE orig_input_handle = get_handle ();
|
||||||
|
HANDLE orig_output_handle = get_output_handle ();
|
||||||
|
cygheap_fdenum cfd (false);
|
||||||
|
while (cfd.next () >= 0)
|
||||||
|
if (cfd->get_device () == get_device ())
|
||||||
|
{
|
||||||
|
fhandler_base *fh = cfd;
|
||||||
|
fhandler_pty_slave *ptys = (fhandler_pty_slave *) fh;
|
||||||
|
if (ptys->get_handle () == orig_input_handle)
|
||||||
|
ptys->set_handle (hpConIn);
|
||||||
|
if (ptys->get_output_handle () == orig_output_handle)
|
||||||
|
ptys->set_output_handle (hpConOut);
|
||||||
|
}
|
||||||
|
CloseHandle (orig_input_handle);
|
||||||
|
CloseHandle (orig_output_handle);
|
||||||
}
|
}
|
||||||
|
while (false);
|
||||||
SIZE_T bytesRequired;
|
|
||||||
InitializeProcThreadAttributeList (NULL, 1, 0, &bytesRequired);
|
|
||||||
ZeroMemory (si, sizeof (*si));
|
|
||||||
si->StartupInfo.cb = sizeof (STARTUPINFOEXW);
|
|
||||||
si->lpAttributeList = (PPROC_THREAD_ATTRIBUTE_LIST)
|
|
||||||
HeapAlloc (GetProcessHeap (), 0, bytesRequired);
|
|
||||||
if (si->lpAttributeList == NULL)
|
|
||||||
goto cleanup_pseudo_console;
|
|
||||||
if (!InitializeProcThreadAttributeList (si->lpAttributeList,
|
|
||||||
1, 0, &bytesRequired))
|
|
||||||
goto cleanup_heap;
|
|
||||||
if (!UpdateProcThreadAttribute (si->lpAttributeList,
|
|
||||||
0,
|
|
||||||
PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE,
|
|
||||||
get_ttyp ()->h_pseudo_console,
|
|
||||||
sizeof (get_ttyp ()->h_pseudo_console),
|
|
||||||
NULL, NULL))
|
|
||||||
goto cleanup_heap;
|
|
||||||
si->StartupInfo.dwFlags = STARTF_USESTDHANDLES;
|
|
||||||
si->StartupInfo.hStdInput = NULL;
|
|
||||||
si->StartupInfo.hStdOutput = NULL;
|
|
||||||
si->StartupInfo.hStdError = NULL;
|
|
||||||
|
|
||||||
{
|
|
||||||
fhandler_base *fh0 = ::cygheap->fdtab[0];
|
|
||||||
if (fh0 && fh0->get_device () != get_device ())
|
|
||||||
si->StartupInfo.hStdInput = fh0->get_handle ();
|
|
||||||
fhandler_base *fh1 = ::cygheap->fdtab[1];
|
|
||||||
if (fh1 && fh1->get_device () != get_device ())
|
|
||||||
{
|
|
||||||
get_ttyp ()->do_not_resize_pcon = true;
|
|
||||||
si->StartupInfo.hStdOutput = fh1->get_output_handle ();
|
|
||||||
}
|
|
||||||
fhandler_base *fh2 = ::cygheap->fdtab[2];
|
|
||||||
if (fh2 && fh2->get_device () != get_device ())
|
|
||||||
si->StartupInfo.hStdError = fh2->get_output_handle ();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (get_ttyp ()->pcon_pid == 0 || !pinfo (get_ttyp ()->pcon_pid))
|
if (get_ttyp ()->pcon_pid == 0 || !pinfo (get_ttyp ()->pcon_pid))
|
||||||
get_ttyp ()->pcon_pid = myself->pid;
|
get_ttyp ()->pcon_pid = myself->pid;
|
||||||
@ -2925,11 +3094,23 @@ fhandler_pty_slave::setup_pseudoconsole (STARTUPINFOEXW *si, bool nopcon)
|
|||||||
HPCON_INTERNAL *hp = (HPCON_INTERNAL *) get_ttyp ()->h_pseudo_console;
|
HPCON_INTERNAL *hp = (HPCON_INTERNAL *) get_ttyp ()->h_pseudo_console;
|
||||||
get_ttyp ()->h_pcon_write_pipe = hp->hWritePipe;
|
get_ttyp ()->h_pcon_write_pipe = hp->hWritePipe;
|
||||||
}
|
}
|
||||||
get_ttyp ()->pcon_start = true;
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
cleanup_pcon_in:
|
||||||
|
CloseHandle (hpConIn);
|
||||||
|
cleanup_helper_process:
|
||||||
|
SetEvent (goodbye);
|
||||||
|
WaitForSingleObject (pi.hProcess, INFINITE);
|
||||||
|
CloseHandle (pi.hProcess);
|
||||||
|
goto skip_close_hello;
|
||||||
|
cleanup_event_and_pipes:
|
||||||
|
CloseHandle (hello);
|
||||||
|
skip_close_hello:
|
||||||
|
CloseHandle (goodbye);
|
||||||
|
CloseHandle (hr);
|
||||||
|
CloseHandle (hw);
|
||||||
cleanup_heap:
|
cleanup_heap:
|
||||||
HeapFree (GetProcessHeap (), 0, si->lpAttributeList);
|
HeapFree (GetProcessHeap (), 0, si.lpAttributeList);
|
||||||
cleanup_pseudo_console:
|
cleanup_pseudo_console:
|
||||||
if (get_ttyp ()->h_pseudo_console)
|
if (get_ttyp ()->h_pseudo_console)
|
||||||
{
|
{
|
||||||
@ -2939,6 +3120,7 @@ cleanup_pseudo_console:
|
|||||||
CloseHandle (tmp);
|
CloseHandle (tmp);
|
||||||
}
|
}
|
||||||
fallback:
|
fallback:
|
||||||
|
get_ttyp ()->pcon_start = false;
|
||||||
get_ttyp ()->h_pseudo_console = NULL;
|
get_ttyp ()->h_pseudo_console = NULL;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -2951,6 +3133,8 @@ fhandler_pty_slave::close_pseudoconsole (tty *ttyp)
|
|||||||
if (ttyp->h_pseudo_console)
|
if (ttyp->h_pseudo_console)
|
||||||
{
|
{
|
||||||
ttyp->wait_pcon_fwd ();
|
ttyp->wait_pcon_fwd ();
|
||||||
|
FreeConsole ();
|
||||||
|
AttachConsole (ATTACH_PARENT_PROCESS);
|
||||||
HPCON_INTERNAL *hp = (HPCON_INTERNAL *) ttyp->h_pseudo_console;
|
HPCON_INTERNAL *hp = (HPCON_INTERNAL *) ttyp->h_pseudo_console;
|
||||||
HANDLE tmp = hp->hConHostProcess;
|
HANDLE tmp = hp->hConHostProcess;
|
||||||
ClosePseudoConsole (ttyp->h_pseudo_console);
|
ClosePseudoConsole (ttyp->h_pseudo_console);
|
||||||
@ -2959,7 +3143,6 @@ fhandler_pty_slave::close_pseudoconsole (tty *ttyp)
|
|||||||
ttyp->switch_to_pcon_in = false;
|
ttyp->switch_to_pcon_in = false;
|
||||||
ttyp->pcon_pid = 0;
|
ttyp->pcon_pid = 0;
|
||||||
ttyp->pcon_start = false;
|
ttyp->pcon_start = false;
|
||||||
ttyp->do_not_resize_pcon = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3042,7 +3225,6 @@ fhandler_pty_slave::term_has_pcon_cap (const WCHAR *env)
|
|||||||
char buf[1024];
|
char buf[1024];
|
||||||
char *p;
|
char *p;
|
||||||
int len;
|
int len;
|
||||||
int x1, y1, x2, y2;
|
|
||||||
int wait_cnt = 0;
|
int wait_cnt = 0;
|
||||||
|
|
||||||
/* Check if terminal has ANSI escape sequence. */
|
/* Check if terminal has ANSI escape sequence. */
|
||||||
@ -3054,6 +3236,7 @@ fhandler_pty_slave::term_has_pcon_cap (const WCHAR *env)
|
|||||||
/* Set h_pseudo_console and pcon_start so that the response
|
/* Set h_pseudo_console and pcon_start so that the response
|
||||||
will sent to io_handle rather than io_handle_cyg. */
|
will sent to io_handle rather than io_handle_cyg. */
|
||||||
get_ttyp ()->h_pseudo_console = (HPCON *) -1; /* dummy */
|
get_ttyp ()->h_pseudo_console = (HPCON *) -1; /* dummy */
|
||||||
|
get_ttyp ()->pcon_pid = myself->pid;
|
||||||
/* pcon_start will be cleared in master write() when CSI6n is responded. */
|
/* pcon_start will be cleared in master write() when CSI6n is responded. */
|
||||||
get_ttyp ()->pcon_start = true;
|
get_ttyp ()->pcon_start = true;
|
||||||
WriteFile (get_output_handle_cyg (), "\033[6n", 4, &n, NULL);
|
WriteFile (get_output_handle_cyg (), "\033[6n", 4, &n, NULL);
|
||||||
@ -3069,8 +3252,9 @@ fhandler_pty_slave::term_has_pcon_cap (const WCHAR *env)
|
|||||||
len -= n;
|
len -= n;
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
char *p1 = strrchr (buf, '\033');
|
char *p1 = strrchr (buf, '\033');
|
||||||
|
int x, y;
|
||||||
char c;
|
char c;
|
||||||
if (p1 == NULL || sscanf (p1, "\033[%d;%d%c", &y1, &x1, &c) != 3
|
if (p1 == NULL || sscanf (p1, "\033[%d;%d%c", &y, &x, &c) != 3
|
||||||
|| c != 'R')
|
|| c != 'R')
|
||||||
continue;
|
continue;
|
||||||
wait_cnt = 0;
|
wait_cnt = 0;
|
||||||
@ -3082,48 +3266,14 @@ fhandler_pty_slave::term_has_pcon_cap (const WCHAR *env)
|
|||||||
Sleep (1);
|
Sleep (1);
|
||||||
}
|
}
|
||||||
while (len);
|
while (len);
|
||||||
|
get_ttyp ()->h_pseudo_console = NULL;
|
||||||
|
get_ttyp ()->pcon_pid = 0;
|
||||||
if (len == 0)
|
if (len == 0)
|
||||||
goto not_has_csi6n;
|
goto not_has_csi6n;
|
||||||
|
|
||||||
get_ttyp ()->has_csi6n = true;
|
get_ttyp ()->has_csi6n = true;
|
||||||
get_ttyp ()->pcon_cap_checked = true;
|
get_ttyp ()->pcon_cap_checked = true;
|
||||||
|
|
||||||
/* Check if terminal has set-title capability */
|
|
||||||
WaitForSingleObject (input_mutex, INFINITE);
|
|
||||||
/* Set pcon_start again because it should be cleared
|
|
||||||
in master write(). */
|
|
||||||
get_ttyp ()->pcon_start = true;
|
|
||||||
WriteFile (get_output_handle_cyg (), "\033]0;\033\\\033[6n", 10, &n, NULL);
|
|
||||||
ReleaseMutex (input_mutex);
|
|
||||||
p = buf;
|
|
||||||
len = sizeof (buf) - 1;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
ReadFile (get_handle (), p, len, &n, NULL);
|
|
||||||
p += n;
|
|
||||||
len -= n;
|
|
||||||
*p = '\0';
|
|
||||||
char *p2 = strrchr (buf, '\033');
|
|
||||||
char c;
|
|
||||||
if (p2 == NULL || sscanf (p2, "\033[%d;%d%c", &y2, &x2, &c) != 3
|
|
||||||
|| c != 'R')
|
|
||||||
continue;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
while (len);
|
|
||||||
get_ttyp ()->h_pseudo_console = NULL;
|
|
||||||
|
|
||||||
if (len == 0)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (x2 == x1 && y2 == y1)
|
|
||||||
/* If "\033]0;\033\\" does not move cursor position,
|
|
||||||
set-title is supposed to be supported. */
|
|
||||||
get_ttyp ()->has_set_title = true;
|
|
||||||
else
|
|
||||||
/* Try to erase garbage string caused by "\033]0;\033\\" */
|
|
||||||
for (int i=0; i<x2-x1; i++)
|
|
||||||
WriteFile (get_output_handle_cyg (), "\b \b", 3, &n, NULL);
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
not_has_csi6n:
|
not_has_csi6n:
|
||||||
@ -3163,6 +3313,8 @@ fhandler_pty_master::get_master_thread_param (master_thread_param_t *p)
|
|||||||
p->from_master_cyg = from_master_cyg;
|
p->from_master_cyg = from_master_cyg;
|
||||||
p->to_master = to_master;
|
p->to_master = to_master;
|
||||||
p->to_master_cyg = to_master_cyg;
|
p->to_master_cyg = to_master_cyg;
|
||||||
|
p->to_slave = to_slave;
|
||||||
|
p->to_slave_cyg = get_output_handle ();
|
||||||
p->master_ctl = master_ctl;
|
p->master_ctl = master_ctl;
|
||||||
p->input_available_event = input_available_event;
|
p->input_available_event = input_available_event;
|
||||||
SetEvent (thread_param_copied_event);
|
SetEvent (thread_param_copied_event);
|
||||||
@ -3177,3 +3329,172 @@ fhandler_pty_master::get_master_fwd_thread_param (master_fwd_thread_param_t *p)
|
|||||||
p->ttyp = get_ttyp ();
|
p->ttyp = get_ttyp ();
|
||||||
SetEvent (thread_param_copied_event);
|
SetEvent (thread_param_copied_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define ALT_PRESSED (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)
|
||||||
|
#define CTRL_PRESSED (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)
|
||||||
|
void
|
||||||
|
fhandler_pty_slave::transfer_input (xfer_dir dir, HANDLE from, tty *ttyp,
|
||||||
|
_minor_t unit, HANDLE input_available_event)
|
||||||
|
{
|
||||||
|
HANDLE to;
|
||||||
|
if (dir == to_nat)
|
||||||
|
to = ttyp->to_slave ();
|
||||||
|
else
|
||||||
|
to = ttyp->to_slave_cyg ();
|
||||||
|
|
||||||
|
pinfo p (ttyp->master_pid);
|
||||||
|
HANDLE pty_owner = OpenProcess (PROCESS_DUP_HANDLE, FALSE, p->dwProcessId);
|
||||||
|
if (pty_owner)
|
||||||
|
{
|
||||||
|
DuplicateHandle (pty_owner, to, GetCurrentProcess (), &to,
|
||||||
|
0, TRUE, DUPLICATE_SAME_ACCESS);
|
||||||
|
CloseHandle (pty_owner);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char pipe[MAX_PATH];
|
||||||
|
__small_sprintf (pipe,
|
||||||
|
"\\\\.\\pipe\\cygwin-%S-pty%d-master-ctl",
|
||||||
|
&cygheap->installation_key, unit);
|
||||||
|
pipe_request req = { GetCurrentProcessId () };
|
||||||
|
pipe_reply repl;
|
||||||
|
DWORD len;
|
||||||
|
if (!CallNamedPipe (pipe, &req, sizeof req,
|
||||||
|
&repl, sizeof repl, &len, 500))
|
||||||
|
return; /* What can we do? */
|
||||||
|
if (dir == to_nat)
|
||||||
|
to = repl.to_slave;
|
||||||
|
else
|
||||||
|
to = repl.to_slave_cyg;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT cp_from = 0, cp_to = 0;
|
||||||
|
|
||||||
|
if (dir == to_nat)
|
||||||
|
{
|
||||||
|
cp_from = ttyp->term_code_page;
|
||||||
|
if (ttyp->h_pseudo_console)
|
||||||
|
cp_to = CP_UTF8;
|
||||||
|
else
|
||||||
|
cp_to = GetConsoleCP ();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cp_from = GetConsoleCP ();
|
||||||
|
cp_to = ttyp->term_code_page;
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp_pathbuf tp;
|
||||||
|
char *buf = tp.c_get ();
|
||||||
|
|
||||||
|
bool transfered = false;
|
||||||
|
|
||||||
|
if (dir == to_cyg && ttyp->h_pseudo_console)
|
||||||
|
{ /* from handle is console handle */
|
||||||
|
INPUT_RECORD r[INREC_SIZE];
|
||||||
|
DWORD n;
|
||||||
|
while (PeekConsoleInputA (from, r, INREC_SIZE, &n) && n)
|
||||||
|
{
|
||||||
|
ReadConsoleInputA (from, r, n, &n);
|
||||||
|
int len = 0;
|
||||||
|
char *ptr = buf;
|
||||||
|
for (DWORD i = 0; i < n; i++)
|
||||||
|
if (r[i].EventType == KEY_EVENT && r[i].Event.KeyEvent.bKeyDown)
|
||||||
|
{
|
||||||
|
DWORD ctrl_key_state = r[i].Event.KeyEvent.dwControlKeyState;
|
||||||
|
if (r[i].Event.KeyEvent.uChar.AsciiChar)
|
||||||
|
{
|
||||||
|
if ((ctrl_key_state & ALT_PRESSED)
|
||||||
|
&& r[i].Event.KeyEvent.uChar.AsciiChar <= 0x7f)
|
||||||
|
buf[len++] = '\033'; /* Meta */
|
||||||
|
buf[len++] = r[i].Event.KeyEvent.uChar.AsciiChar;
|
||||||
|
}
|
||||||
|
/* Allow Ctrl-Space to emit ^@ */
|
||||||
|
else if (r[i].Event.KeyEvent.wVirtualKeyCode == '2'
|
||||||
|
&& (ctrl_key_state & CTRL_PRESSED)
|
||||||
|
&& !(ctrl_key_state & ALT_PRESSED))
|
||||||
|
buf[len++] = '\0';
|
||||||
|
else if (r[i].Event.KeyEvent.wVirtualKeyCode == VK_F3)
|
||||||
|
{
|
||||||
|
/* If the cursor position report for CSI6n matches
|
||||||
|
with e.g. "ESC[1;2R", pseudo console translates
|
||||||
|
it to Shift-F3. This is a workaround for that. */
|
||||||
|
int ctrl = 1;
|
||||||
|
if (ctrl_key_state & SHIFT_PRESSED) ctrl += 1;
|
||||||
|
if (ctrl_key_state & ALT_PRESSED) ctrl += 2;
|
||||||
|
if (ctrl_key_state & CTRL_PRESSED) ctrl += 4;
|
||||||
|
__small_sprintf (buf + len, "\033[1;%1dR", ctrl);
|
||||||
|
len += 6;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ /* arrow/function keys */
|
||||||
|
/* FIXME: The current code generates cygwin terminal
|
||||||
|
sequence rather than xterm sequence. */
|
||||||
|
char tmp[16];
|
||||||
|
const char *add =
|
||||||
|
fhandler_console::get_nonascii_key (r[i], tmp);
|
||||||
|
if (add)
|
||||||
|
{
|
||||||
|
strcpy (buf + len, add);
|
||||||
|
len += strlen (add);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (cp_to != cp_from)
|
||||||
|
{
|
||||||
|
static mbstate_t mbp;
|
||||||
|
char *mbbuf = tp.c_get ();
|
||||||
|
size_t nlen = NT_MAX_PATH;
|
||||||
|
convert_mb_str (cp_to, mbbuf, &nlen, cp_from, buf, len, &mbp);
|
||||||
|
ptr = mbbuf;
|
||||||
|
len = nlen;
|
||||||
|
}
|
||||||
|
/* Call WriteFile() line by line */
|
||||||
|
char *p0 = ptr;
|
||||||
|
char *p1 = ptr;
|
||||||
|
while ((p1 = (char *) memchr (p0, '\r', len - (p0 - ptr))))
|
||||||
|
{
|
||||||
|
*p1 = '\n';
|
||||||
|
n = p1 - p0 + 1;
|
||||||
|
if (n && WriteFile (to, p0, n, &n, NULL) && n)
|
||||||
|
transfered = true;
|
||||||
|
p0 = p1 + 1;
|
||||||
|
}
|
||||||
|
n = len - (p0 - ptr);
|
||||||
|
if (n && WriteFile (to, p0, n, &n, NULL) && n)
|
||||||
|
transfered = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DWORD bytes_in_pipe;
|
||||||
|
while (::bytes_available (bytes_in_pipe, from) && bytes_in_pipe)
|
||||||
|
{
|
||||||
|
DWORD n = MIN (bytes_in_pipe, NT_MAX_PATH);
|
||||||
|
ReadFile (from, buf, n, &n, NULL);
|
||||||
|
char *ptr = buf;
|
||||||
|
if (dir == to_nat && ttyp->h_pseudo_console)
|
||||||
|
{
|
||||||
|
char *p = buf;
|
||||||
|
while ((p = (char *) memchr (p, '\n', n - (p - buf))))
|
||||||
|
*p = '\r';
|
||||||
|
}
|
||||||
|
if (cp_to != cp_from)
|
||||||
|
{
|
||||||
|
static mbstate_t mbp;
|
||||||
|
char *mbbuf = tp.c_get ();
|
||||||
|
size_t nlen = NT_MAX_PATH;
|
||||||
|
convert_mb_str (cp_to, mbbuf, &nlen, cp_from, buf, n, &mbp);
|
||||||
|
ptr = mbbuf;
|
||||||
|
n = nlen;
|
||||||
|
}
|
||||||
|
if (n && WriteFile (to, ptr, n, &n, NULL) && n)
|
||||||
|
transfered = true;;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dir == to_nat)
|
||||||
|
ResetEvent (input_available_event);
|
||||||
|
else if (transfered)
|
||||||
|
SetEvent (input_available_event);
|
||||||
|
}
|
||||||
|
@ -653,6 +653,36 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool enable_pcon = false;
|
||||||
|
HANDLE ptys_from_master = NULL;
|
||||||
|
HANDLE ptys_input_available_event = NULL;
|
||||||
|
tty *ptys_ttyp = NULL;
|
||||||
|
_minor_t ptys_unit = 0;
|
||||||
|
if (!iscygwin () && ptys_primary && is_console_app (runpath))
|
||||||
|
{
|
||||||
|
bool nopcon = mode != _P_OVERLAY && mode != _P_WAIT;
|
||||||
|
if (disable_pcon || !ptys_primary->term_has_pcon_cap (envblock))
|
||||||
|
nopcon = true;
|
||||||
|
if (ptys_primary->setup_pseudoconsole (nopcon))
|
||||||
|
enable_pcon = true;
|
||||||
|
ptys_ttyp = ptys_primary->get_ttyp ();
|
||||||
|
ptys_unit = ptys_primary->get_minor ();
|
||||||
|
ptys_from_master = ptys_primary->get_handle ();
|
||||||
|
DuplicateHandle (GetCurrentProcess (), ptys_from_master,
|
||||||
|
GetCurrentProcess (), &ptys_from_master,
|
||||||
|
0, 0, DUPLICATE_SAME_ACCESS);
|
||||||
|
ptys_input_available_event =
|
||||||
|
ptys_primary->get_input_available_event ();
|
||||||
|
DuplicateHandle (GetCurrentProcess (), ptys_input_available_event,
|
||||||
|
GetCurrentProcess (), &ptys_input_available_event,
|
||||||
|
0, 0, DUPLICATE_SAME_ACCESS);
|
||||||
|
if (!enable_pcon)
|
||||||
|
fhandler_pty_slave::transfer_input (fhandler_pty_slave::to_nat,
|
||||||
|
ptys_primary->get_handle_cyg (),
|
||||||
|
ptys_ttyp, ptys_unit,
|
||||||
|
ptys_input_available_event);
|
||||||
|
}
|
||||||
|
|
||||||
/* Set up needed handles for stdio */
|
/* Set up needed handles for stdio */
|
||||||
si.dwFlags = STARTF_USESTDHANDLES;
|
si.dwFlags = STARTF_USESTDHANDLES;
|
||||||
si.hStdInput = handle ((in__stdin < 0 ? 0 : in__stdin), false);
|
si.hStdInput = handle ((in__stdin < 0 ? 0 : in__stdin), false);
|
||||||
@ -664,25 +694,6 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
|
|||||||
if (!iscygwin ())
|
if (!iscygwin ())
|
||||||
init_console_handler (myself->ctty > 0);
|
init_console_handler (myself->ctty > 0);
|
||||||
|
|
||||||
bool enable_pcon = false;
|
|
||||||
tty *ptys_ttyp = NULL;
|
|
||||||
STARTUPINFOEXW si_pcon;
|
|
||||||
ZeroMemory (&si_pcon, sizeof (si_pcon));
|
|
||||||
STARTUPINFOW *si_tmp = &si;
|
|
||||||
if (!iscygwin () && ptys_primary && is_console_app (runpath))
|
|
||||||
{
|
|
||||||
bool nopcon = mode != _P_OVERLAY && mode != _P_WAIT;
|
|
||||||
if (disable_pcon || !ptys_primary->term_has_pcon_cap (envblock))
|
|
||||||
nopcon = true;
|
|
||||||
if (ptys_primary->setup_pseudoconsole (&si_pcon, nopcon))
|
|
||||||
{
|
|
||||||
c_flags |= EXTENDED_STARTUPINFO_PRESENT;
|
|
||||||
si_tmp = &si_pcon.StartupInfo;
|
|
||||||
enable_pcon = true;
|
|
||||||
ptys_ttyp = ptys_primary->get_ttyp ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
loop:
|
loop:
|
||||||
/* When ruid != euid we create the new process under the current original
|
/* When ruid != euid we create the new process under the current original
|
||||||
account and impersonate in child, this way maintaining the different
|
account and impersonate in child, this way maintaining the different
|
||||||
@ -711,7 +722,7 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
|
|||||||
c_flags,
|
c_flags,
|
||||||
envblock, /* environment */
|
envblock, /* environment */
|
||||||
NULL,
|
NULL,
|
||||||
si_tmp,
|
&si,
|
||||||
&pi);
|
&pi);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -765,7 +776,7 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
|
|||||||
c_flags,
|
c_flags,
|
||||||
envblock, /* environment */
|
envblock, /* environment */
|
||||||
NULL,
|
NULL,
|
||||||
si_tmp,
|
&si,
|
||||||
&pi);
|
&pi);
|
||||||
if (hwst)
|
if (hwst)
|
||||||
{
|
{
|
||||||
@ -778,11 +789,6 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
|
|||||||
CloseDesktop (hdsk);
|
CloseDesktop (hdsk);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (enable_pcon)
|
|
||||||
{
|
|
||||||
DeleteProcThreadAttributeList (si_pcon.lpAttributeList);
|
|
||||||
HeapFree (GetProcessHeap (), 0, si_pcon.lpAttributeList);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mode != _P_OVERLAY)
|
if (mode != _P_OVERLAY)
|
||||||
SetHandleInformation (my_wr_proc_pipe, HANDLE_FLAG_INHERIT,
|
SetHandleInformation (my_wr_proc_pipe, HANDLE_FLAG_INHERIT,
|
||||||
@ -954,14 +960,21 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
|
|||||||
}
|
}
|
||||||
if (sem)
|
if (sem)
|
||||||
__posix_spawn_sem_release (sem, 0);
|
__posix_spawn_sem_release (sem, 0);
|
||||||
if (enable_pcon)
|
if (enable_pcon || ptys_ttyp || cons_native)
|
||||||
|
WaitForSingleObject (pi.hProcess, INFINITE);
|
||||||
|
if (ptys_ttyp)
|
||||||
{
|
{
|
||||||
WaitForSingleObject (pi.hProcess, INFINITE);
|
fhandler_pty_slave::transfer_input (fhandler_pty_slave::to_cyg,
|
||||||
fhandler_pty_slave::close_pseudoconsole (ptys_ttyp);
|
ptys_from_master,
|
||||||
|
ptys_ttyp, ptys_unit,
|
||||||
|
ptys_input_available_event);
|
||||||
|
CloseHandle (ptys_from_master);
|
||||||
|
CloseHandle (ptys_input_available_event);
|
||||||
}
|
}
|
||||||
|
if (enable_pcon)
|
||||||
|
fhandler_pty_slave::close_pseudoconsole (ptys_ttyp);
|
||||||
else if (cons_native)
|
else if (cons_native)
|
||||||
{
|
{
|
||||||
WaitForSingleObject (pi.hProcess, INFINITE);
|
|
||||||
fhandler_console::request_xterm_mode_output (true,
|
fhandler_console::request_xterm_mode_output (true,
|
||||||
&cons_handle_set);
|
&cons_handle_set);
|
||||||
fhandler_console::request_xterm_mode_input (true,
|
fhandler_console::request_xterm_mode_input (true,
|
||||||
@ -975,6 +988,15 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
|
|||||||
system_call.arm ();
|
system_call.arm ();
|
||||||
if (waitpid (cygpid, &res, 0) != cygpid)
|
if (waitpid (cygpid, &res, 0) != cygpid)
|
||||||
res = -1;
|
res = -1;
|
||||||
|
if (ptys_ttyp)
|
||||||
|
{
|
||||||
|
fhandler_pty_slave::transfer_input (fhandler_pty_slave::to_cyg,
|
||||||
|
ptys_from_master,
|
||||||
|
ptys_ttyp, ptys_unit,
|
||||||
|
ptys_input_available_event);
|
||||||
|
CloseHandle (ptys_from_master);
|
||||||
|
CloseHandle (ptys_input_available_event);
|
||||||
|
}
|
||||||
if (enable_pcon)
|
if (enable_pcon)
|
||||||
fhandler_pty_slave::close_pseudoconsole (ptys_ttyp);
|
fhandler_pty_slave::close_pseudoconsole (ptys_ttyp);
|
||||||
else if (cons_native)
|
else if (cons_native)
|
||||||
|
@ -244,8 +244,6 @@ tty::init ()
|
|||||||
pcon_start = false;
|
pcon_start = false;
|
||||||
pcon_cap_checked = false;
|
pcon_cap_checked = false;
|
||||||
has_csi6n = false;
|
has_csi6n = false;
|
||||||
has_set_title = false;
|
|
||||||
do_not_resize_pcon = false;
|
|
||||||
need_invisible_console = false;
|
need_invisible_console = false;
|
||||||
invisible_console_pid = 0;
|
invisible_console_pid = 0;
|
||||||
}
|
}
|
||||||
|
@ -93,6 +93,8 @@ private:
|
|||||||
HANDLE _from_master_cyg;
|
HANDLE _from_master_cyg;
|
||||||
HANDLE _to_master;
|
HANDLE _to_master;
|
||||||
HANDLE _to_master_cyg;
|
HANDLE _to_master_cyg;
|
||||||
|
HANDLE _to_slave;
|
||||||
|
HANDLE _to_slave_cyg;
|
||||||
HPCON h_pseudo_console;
|
HPCON h_pseudo_console;
|
||||||
bool pcon_start;
|
bool pcon_start;
|
||||||
bool switch_to_pcon_in;
|
bool switch_to_pcon_in;
|
||||||
@ -103,8 +105,6 @@ private:
|
|||||||
HANDLE h_pcon_write_pipe;
|
HANDLE h_pcon_write_pipe;
|
||||||
bool pcon_cap_checked;
|
bool pcon_cap_checked;
|
||||||
bool has_csi6n;
|
bool has_csi6n;
|
||||||
bool has_set_title;
|
|
||||||
bool do_not_resize_pcon;
|
|
||||||
bool need_invisible_console;
|
bool need_invisible_console;
|
||||||
pid_t invisible_console_pid;
|
pid_t invisible_console_pid;
|
||||||
|
|
||||||
@ -113,10 +113,14 @@ public:
|
|||||||
HANDLE from_master_cyg () const { return _from_master_cyg; }
|
HANDLE from_master_cyg () const { return _from_master_cyg; }
|
||||||
HANDLE to_master () const { return _to_master; }
|
HANDLE to_master () const { return _to_master; }
|
||||||
HANDLE to_master_cyg () const { return _to_master_cyg; }
|
HANDLE to_master_cyg () const { return _to_master_cyg; }
|
||||||
|
HANDLE to_slave () const { return _to_slave; }
|
||||||
|
HANDLE to_slave_cyg () const { return _to_slave_cyg; }
|
||||||
void set_from_master (HANDLE h) { _from_master = h; }
|
void set_from_master (HANDLE h) { _from_master = h; }
|
||||||
void set_from_master_cyg (HANDLE h) { _from_master_cyg = h; }
|
void set_from_master_cyg (HANDLE h) { _from_master_cyg = h; }
|
||||||
void set_to_master (HANDLE h) { _to_master = h; }
|
void set_to_master (HANDLE h) { _to_master = h; }
|
||||||
void set_to_master_cyg (HANDLE h) { _to_master_cyg = h; }
|
void set_to_master_cyg (HANDLE h) { _to_master_cyg = h; }
|
||||||
|
void set_to_slave (HANDLE h) { _to_slave = h; }
|
||||||
|
void set_to_slave_cyg (HANDLE h) { _to_slave_cyg = h; }
|
||||||
|
|
||||||
int read_retval;
|
int read_retval;
|
||||||
bool was_opened; /* True if opened at least once. */
|
bool was_opened; /* True if opened at least once. */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user