In tcgetattr(), the conventional workaround for rlwrap v0.40 or later is not work as expected with OpenConsole.exe for some reason. This patch update the workaround so that it works even with OpenConsole.exe by rebuilding tcgetattr responce reffering the corrent console mode instead of just overriding it depends on pseudo console setting up state.
Signed-off-by: Takashi Yano <[email protected]> Reviewed-by: --- winsup/cygwin/fhandler/pty.cc | 86 ++++++++++++++++++++++++++++------- 1 file changed, 70 insertions(+), 16 deletions(-) diff --git a/winsup/cygwin/fhandler/pty.cc b/winsup/cygwin/fhandler/pty.cc index a4bb53573..8963b9424 100644 --- a/winsup/cygwin/fhandler/pty.cc +++ b/winsup/cygwin/fhandler/pty.cc @@ -1738,18 +1738,48 @@ fhandler_pty_slave::tcgetattr (struct termios *t) { *t = get_ttyp ()->ti; - /* Workaround for rlwrap */ - cygheap_fdenum cfd (false); - while (cfd.next () >= 0) - if (cfd->get_major () == DEV_PTYM_MAJOR - && cfd->get_minor () == get_minor ()) - { - if (get_ttyp ()->pcon_start) - t->c_lflag &= ~(ICANON | ECHO); - if (get_ttyp ()->pcon_activated) - t->c_iflag &= ~ICRNL; - break; - } + /* Conventional workaround for rlwrap v0.40 or later is not work + as expected with OpenConsole.exe for some reason. The following + workaround is perhaps better solution even for apps other than + rlwrap under pcon_activated mode. */ + if (get_ttyp ()->pcon_activated) + { + DWORD mode = ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT; + t->c_lflag &= ~(ICANON | ECHO); + t->c_iflag &= ~ICRNL; + cygheap_fdenum cfd (false); + while (cfd.next () >= 0) + if (cfd->get_major () == DEV_PTYM_MAJOR + && cfd->get_minor () == get_minor ()) + { + if (nat_pipe_owner_self (get_ttyp ()->nat_pipe_owner_pid)) + { + DWORD resume_pid = + attach_console_temporarily (get_ttyp()->nat_pipe_owner_pid); + GetConsoleMode (get_ttyp ()->h_pcon_in, &mode); + resume_from_temporarily_attach (resume_pid); + break; + } + HANDLE pcon_owner = OpenProcess (PROCESS_DUP_HANDLE, FALSE, + get_ttyp ()->nat_pipe_owner_pid); + HANDLE h_pcon_in; + DuplicateHandle (pcon_owner, get_ttyp ()->h_pcon_in, + GetCurrentProcess (), &h_pcon_in, + 0, FALSE, DUPLICATE_SAME_ACCESS); + DWORD resume_pid = + attach_console_temporarily (get_ttyp()->nat_pipe_owner_pid); + if (!GetConsoleMode (h_pcon_in, &mode) && get_ttyp ()->pcon_start) + mode = 0; + resume_from_temporarily_attach (resume_pid); + CloseHandle (h_pcon_in); + CloseHandle (pcon_owner); + break; + } + if (mode & ENABLE_LINE_INPUT) + t->c_lflag |= ICANON; + if (mode & ENABLE_ECHO_INPUT) + t->c_lflag |= ECHO; + } return 0; } @@ -2473,11 +2503,35 @@ int fhandler_pty_master::tcgetattr (struct termios *t) { *t = cygwin_shared->tty[get_minor ()]->ti; - /* Workaround for rlwrap v0.40 or later */ - if (get_ttyp ()->pcon_start) - t->c_lflag &= ~(ICANON | ECHO); + + /* Conventional workaround for rlwrap v0.40 or later is not work + as expected with OpenConsole.exe for some reason. The following + workaround is perhaps better solution even for apps other than + rlwrap under pcon_activated mode. */ if (get_ttyp ()->pcon_activated) - t->c_iflag &= ~ICRNL; + { + t->c_lflag &= ~(ICANON | ECHO); + t->c_iflag &= ~ICRNL; + + HANDLE pcon_owner = OpenProcess (PROCESS_DUP_HANDLE, FALSE, + get_ttyp ()->nat_pipe_owner_pid); + HANDLE h_pcon_in; + DuplicateHandle (pcon_owner, get_ttyp ()->h_pcon_in, + GetCurrentProcess (), &h_pcon_in, + 0, FALSE, DUPLICATE_SAME_ACCESS); + DWORD resume_pid = + attach_console_temporarily (get_ttyp()->nat_pipe_owner_pid); + DWORD mode = ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT; + if (!GetConsoleMode (h_pcon_in, &mode) && get_ttyp ()->pcon_start) + mode = 0; + resume_from_temporarily_attach (resume_pid); + CloseHandle (h_pcon_in); + CloseHandle (pcon_owner); + if (mode & ENABLE_LINE_INPUT) + t->c_lflag |= ICANON; + if (mode & ENABLE_ECHO_INPUT) + t->c_lflag |= ECHO; + } return 0; } -- 2.51.0
