[newlib-cygwin] Cygwin: pty: Handle CSIc in pcon_start phase

Takashi Yano tyan0@sourceware.org
Tue Apr 7 10:15:47 GMT 2026


https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=9c2ea0805fbf4c183c9b7ee4d4e4d7c57044e7bf

commit 9c2ea0805fbf4c183c9b7ee4d4e4d7c57044e7bf
Author: Takashi Yano <takashi.yano@nifty.ne.jp>
Date:   Tue Apr 7 08:59:52 2026 +0900

    Cygwin: pty: Handle CSIc in pcon_start phase
    
    OpenConsole.exe sends CSIc in addition to CSI6n in pcon_start phase
    (in initialization of pseudo console). This patch adds code to handle
    CSIc and its response.
    
    Signed-off-by: Takashi Yano <takashi.yano@nifty.ne.jp>
    Reviewed-by:  Johannes Schindelin <Johannes.Schindelin@gmx.de>

Diff:
---
 winsup/cygwin/fhandler/pty.cc           | 60 +++++++++++++++++++++++++--------
 winsup/cygwin/local_includes/fhandler.h |  1 +
 winsup/cygwin/local_includes/tty.h      |  1 +
 winsup/cygwin/tty.cc                    |  1 +
 4 files changed, 49 insertions(+), 14 deletions(-)

diff --git a/winsup/cygwin/fhandler/pty.cc b/winsup/cygwin/fhandler/pty.cc
index d6b783ae0..e9191aaad 100644
--- a/winsup/cygwin/fhandler/pty.cc
+++ b/winsup/cygwin/fhandler/pty.cc
@@ -1349,7 +1349,8 @@ fhandler_pty_slave::reset_switch_to_nat_pipe (void)
     }
   if (isHybrid)
     return;
-  if (get_ttyp ()->pcon_start) /* Pseudo console initialization is on going */
+  if (get_ttyp ()->pcon_start || get_ttyp ()->pcon_start_csi_c)
+    /* Pseudo console initialization is on going */
     return;
   DWORD wait_ret = WaitForSingleObject (pipe_sw_mutex, mutex_timeout);
   if (wait_ret == WAIT_TIMEOUT)
@@ -1456,7 +1457,8 @@ fhandler_pty_common::to_be_read_from_nat_pipe (void)
      to CSI6n should be go to cyg-pipe. So, wait for pcon_start and
      return false. */
   while (WaitForSingleObject (pipe_sw_mutex, 0) == WAIT_TIMEOUT)
-    if (get_ttyp ()->pcon_start || get_ttyp ()->pcon_start_pid)
+    if (get_ttyp ()->pcon_start || get_ttyp ()->pcon_start_csi_c
+	|| get_ttyp ()->pcon_start_pid)
       return false;
     else
       yield ();
@@ -1780,7 +1782,7 @@ fhandler_pty_slave::tcgetattr (struct termios *t)
     if (cfd->get_major () == DEV_PTYM_MAJOR
 	&& cfd->get_minor () == get_minor ())
       {
-	if (get_ttyp ()->pcon_start)
+	if (get_ttyp ()->pcon_start || get_ttyp ()->pcon_start_csi_c)
 	  t->c_lflag &= ~(ICANON | ECHO);
 	if (get_ttyp ()->pcon_activated)
 	  t->c_iflag &= ~ICRNL;
@@ -2362,13 +2364,16 @@ fhandler_pty_master::write (const void *ptr, size_t len)
 
   get_ttyp ()->discard_input = false;
 
-  if (get_ttyp ()->pcon_start)
+  int pcon_start_mode =
+    get_ttyp ()->pcon_start ? 1 : (get_ttyp ()->pcon_start_csi_c ? 2 : 0);
+  if (pcon_start_mode)
     { /* Reaches here when pseudo console initialization is on going. */
       /* Pseudo condole support uses "CSI6n" to get cursor position.
 	 If the reply for "CSI6n" is divided into multiple writes,
 	 pseudo console sometimes does not recognize it.  Therefore,
 	 put them together into wpbuf and write all at once. */
-      static const int wpbuf_len = strlen ("\033[32768;32868R");
+      /* Do the same for CSIc. */
+      static const int wpbuf_len = 64; /* Enough space for CSIc response */
       static char wpbuf[wpbuf_len];
       static int ixput = 0;
       static int state = 0;
@@ -2404,7 +2409,15 @@ fhandler_pty_master::write (const void *ptr, size_t len)
 	  len = orig_len - i - 1;
 	  ptr = p + i + 1;
 	  if (state == 1 && wp_tid == _my_tls.thread_id && p[i] == 'R')
-	    state = 2;
+	    {
+	      get_ttyp ()->pcon_start = false;
+	      state = 2;
+	    }
+	  if (state == 1 && wp_tid == _my_tls.thread_id && p[i] == 'c')
+	    {
+	      get_ttyp ()->pcon_start_csi_c = false;
+	      state = 2;
+	    }
 	  if (state == 2)
 	    {
 	      /* req_xfer_input is true if "ESC[6n" was sent just for
@@ -2416,13 +2429,14 @@ fhandler_pty_master::write (const void *ptr, size_t len)
 	      state = 0;
 	      wp_tid = 0;
 	      get_ttyp ()->req_xfer_input = false;
-	      get_ttyp ()->pcon_start = false;
-	      break;
+	      if (!get_ttyp ()->pcon_start && !get_ttyp ()->pcon_start_csi_c)
+		break;
 	    }
 	}
       ReleaseMutex (input_mutex);
 
-      if (!get_ttyp ()->pcon_start)
+      if (pcon_start_mode
+	  && !get_ttyp ()->pcon_start && !get_ttyp ()->pcon_start_csi_c)
 	{ /* Pseudo console initialization has been done in above code. */
 	  pinfo pp (get_ttyp ()->pcon_start_pid);
 	  if (get_ttyp ()->switch_to_nat_pipe
@@ -2580,7 +2594,7 @@ 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)
+  if (get_ttyp ()->pcon_start || get_ttyp ()->pcon_start_csi_c)
     t->c_lflag &= ~(ICANON | ECHO);
   if (get_ttyp ()->pcon_activated)
     t->c_iflag &= ~ICRNL;
@@ -2947,8 +2961,10 @@ pty_master_thread (VOID *arg)
 #define CONSOLE_HELPER "\\bin\\cygwin-console-helper.exe"
 #define CONSOLE_HELPER_LEN (sizeof (CONSOLE_HELPER) - 1)
 
-inline static DWORD
-workarounds_for_pseudo_console_output (char *outbuf, DWORD rlen)
+DWORD
+fhandler_pty_master::workarounds_for_pseudo_console_output (char *outbuf,
+							    DWORD rlen,
+							    tty *ttyp)
 {
   int state = 0;
   int start_at = 0;
@@ -2957,6 +2973,7 @@ workarounds_for_pseudo_console_output (char *outbuf, DWORD rlen)
   int arg = 0;
   bool saw_greater_than_sign = false;
   bool saw_question_mark = false;
+  static bool in_pcon_start = false;
   for (DWORD i=0; i<rlen; i++)
     if (state == 0 && outbuf[i] == '\033')
       {
@@ -3038,8 +3055,21 @@ workarounds_for_pseudo_console_output (char *outbuf, DWORD rlen)
 	    start_at = i;
 	    state = 1;
 	  }
+	else if (arg == 6 && outbuf[i] == 'n' && ttyp->pcon_start)
+	  {
+	    in_pcon_start = true;
+	    state = 0;
+	  }
+	else if (arg == 0 && outbuf[i] == 'c' && in_pcon_start)
+	  {
+	    ttyp->pcon_start_csi_c = true;
+	    state = 0;
+	  }
 	else
-	  state = 0;
+	  {
+	    in_pcon_start = false;
+	    state = 0;
+	  }
 
 	if (state < 2)
 	  {
@@ -3097,6 +3127,7 @@ workarounds_for_pseudo_console_output (char *outbuf, DWORD rlen)
 	is_osc = false;
 	saw_greater_than_sign = false;
 	saw_question_mark = false;
+	in_pcon_start = false;
 	arg = 0;
 	state = 0;
       }
@@ -3155,7 +3186,8 @@ wait_event:
       char *ptr = outbuf;
       if (p->ttyp->pcon_activated)
 	{
-	  wlen = rlen = workarounds_for_pseudo_console_output (outbuf, rlen);
+	  wlen = rlen =
+	    workarounds_for_pseudo_console_output (outbuf, rlen, p->ttyp);
 
 	  if (p->ttyp->term_code_page != CP_UTF8)
 	    {
diff --git a/winsup/cygwin/local_includes/fhandler.h b/winsup/cygwin/local_includes/fhandler.h
index 974e39698..4f5605524 100644
--- a/winsup/cygwin/local_includes/fhandler.h
+++ b/winsup/cygwin/local_includes/fhandler.h
@@ -2580,6 +2580,7 @@ public:
 
   static DWORD pty_master_thread (const master_thread_param_t *p);
   static DWORD pty_master_fwd_thread (const master_fwd_thread_param_t *p);
+  static DWORD workarounds_for_pseudo_console_output (char *, DWORD, tty *);
   int process_slave_output (char *buf, size_t len, int pktmode_on);
   void doecho (const void *str, DWORD len);
   int accept_input ();
diff --git a/winsup/cygwin/local_includes/tty.h b/winsup/cygwin/local_includes/tty.h
index 962697782..4fbebd820 100644
--- a/winsup/cygwin/local_includes/tty.h
+++ b/winsup/cygwin/local_includes/tty.h
@@ -122,6 +122,7 @@ private:
   bool pcon_activated;
   bool pcon_start;
   pid_t pcon_start_pid;
+  bool pcon_start_csi_c;
   bool switch_to_nat_pipe;
   DWORD nat_pipe_owner_pid;
   UINT term_code_page;
diff --git a/winsup/cygwin/tty.cc b/winsup/cygwin/tty.cc
index 0c49dc2bd..40b270309 100644
--- a/winsup/cygwin/tty.cc
+++ b/winsup/cygwin/tty.cc
@@ -243,6 +243,7 @@ tty::init ()
   fwd_not_empty = false;
   pcon_start = false;
   pcon_start_pid = 0;
+  pcon_start_csi_c = false;
   pcon_cap_checked = false;
   has_csi6n = false;
   need_invisible_console = false;


More information about the Cygwin-cvs mailing list