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

Reply via email to