diff --git a/winsup/cygwin/fhandler_tty.cc b/winsup/cygwin/fhandler_tty.cc index da6119dfb..26f99669f 100644 --- a/winsup/cygwin/fhandler_tty.cc +++ b/winsup/cygwin/fhandler_tty.cc @@ -1296,6 +1296,30 @@ detach: restore_reattach_pcon (); } +/* If master process is running as service, attaching to + pseudo console should be done in fork. If attaching + is done in spawn for inetd or sshd, it fails because + the helper process is running as privileged user while + slave process is not. This function is used to determine + if the process is running as a srvice or not. */ +static bool +is_running_as_service (void) +{ + DWORD dwSize = 0; + PTOKEN_GROUPS pGroupInfo; + tmp_pathbuf tp; + pGroupInfo = (PTOKEN_GROUPS) tp.w_get (); + NtQueryInformationToken (hProcToken, TokenGroups, pGroupInfo, + 2 * NT_MAX_PATH, &dwSize); + for (DWORD i=0; iGroupCount; i++) + if (RtlEqualSid (well_known_service_sid, pGroupInfo->Groups[i].Sid)) + return true; + for (DWORD i=0; iGroupCount; i++) + if (RtlEqualSid (mandatory_system_integrity_sid, pGroupInfo->Groups[i].Sid)) + return true; + return false; +} + ssize_t __stdcall fhandler_pty_slave::write (const void *ptr, size_t len) { @@ -1305,6 +1329,30 @@ fhandler_pty_slave::write (const void *ptr, size_t len) if (bg <= bg_eof) return (ssize_t) bg; + if (get_ttyp ()->need_clear_screen_on_write) + { + if (is_running_as_service ()) + { + struct termios ti, ti_new; + tcgetattr (&ti); + ti_new = ti; + ti_new.c_lflag &= (~ICANON | ECHO); + tcsetattr (TCSANOW, &ti_new); + char buf[32]; + DWORD n; + WriteFile (get_output_handle_cyg (), "\033[6n", 4, &n, NULL); + ReadFile (get_handle_cyg (), buf, sizeof(buf)-1, &n, NULL); + ResetEvent (input_available_event); + tcsetattr (TCSANOW, &ti); + buf[n] = '\0'; + int rows, cols; + sscanf (buf, "\033[%d;%dR", &rows, &cols); + COORD dwCursorPosition = {(SHORT)(cols-1), (SHORT)(rows-1)}; + SetConsoleCursorPosition (get_output_handle (), dwCursorPosition); + } + get_ttyp ()->need_clear_screen_on_write = false; + } + termios_printf ("pty%d, write(%p, %lu)", get_minor (), ptr, len); push_process_state process_state (PID_TTYOU); @@ -2668,7 +2716,12 @@ fhandler_pty_slave::fixup_after_attach (bool native_maybe, int fd_set) if (get_ttyp ()->num_pcon_attached_slaves == 0 && !ALWAYS_USE_PCON) /* Assume this is the first process using this pty slave. */ - get_ttyp ()->need_clear_screen = true; + { + if (is_running_as_service ()) + get_ttyp ()->need_clear_screen_on_write = true; + else + get_ttyp ()->need_clear_screen = true; + } get_ttyp ()->num_pcon_attached_slaves ++; } @@ -2722,10 +2775,22 @@ fhandler_pty_slave::fixup_after_fork (HANDLE parent) const char *term = getenv ("TERM"); if (term && strcmp (term, "dumb") && !strstr (term, "emacs")) { - /* FIXME: Clearing sequence may not be "^[[H^[[J" - depending on the terminal type. */ + struct termios ti, ti_new; + tcgetattr (&ti); + ti_new = ti; + ti_new.c_lflag &= (~ICANON | ECHO); + tcsetattr (TCSANOW, &ti_new); + char buf[32]; DWORD n; - WriteFile (get_output_handle_cyg (), "\033[H\033[J", 6, &n, NULL); + WriteFile (get_output_handle_cyg (), "\033[6n", 4, &n, NULL); + ReadFile (get_handle_cyg (), buf, sizeof(buf)-1, &n, NULL); + ResetEvent (input_available_event); + tcsetattr (TCSANOW, &ti); + buf[n] = '\0'; + int rows, cols; + sscanf (buf, "\033[%d;%dR", &rows, &cols); + COORD dwCursorPosition = {(SHORT)(cols-1), (SHORT)(rows-1)}; + SetConsoleCursorPosition (get_output_handle (), dwCursorPosition); } get_ttyp ()->need_clear_screen = false; } @@ -3088,30 +3153,6 @@ pty_master_fwd_thread (VOID *arg) return ((fhandler_pty_master *) arg)->pty_master_fwd_thread (); } -/* If master process is running as service, attaching to - pseudo console should be done in fork. If attaching - is done in spawn for inetd or sshd, it fails because - the helper process is running as privileged user while - slave process is not. This function is used to determine - if the process is running as a srvice or not. */ -static bool -is_running_as_service (void) -{ - DWORD dwSize = 0; - PTOKEN_GROUPS pGroupInfo; - tmp_pathbuf tp; - pGroupInfo = (PTOKEN_GROUPS) tp.w_get (); - NtQueryInformationToken (hProcToken, TokenGroups, pGroupInfo, - 2 * NT_MAX_PATH, &dwSize); - for (DWORD i=0; iGroupCount; i++) - if (RtlEqualSid (well_known_service_sid, pGroupInfo->Groups[i].Sid)) - return true; - for (DWORD i=0; iGroupCount; i++) - if (RtlEqualSid (well_known_interactive_sid, pGroupInfo->Groups[i].Sid)) - return false; - return true; -} - bool fhandler_pty_master::setup_pseudoconsole () { diff --git a/winsup/cygwin/tty.cc b/winsup/cygwin/tty.cc index 460153cdb..1595d0278 100644 --- a/winsup/cygwin/tty.cc +++ b/winsup/cygwin/tty.cc @@ -245,6 +245,7 @@ tty::init () num_pcon_attached_slaves = 0; term_code_page = 0; need_clear_screen = false; + need_clear_screen_on_write = false; } HANDLE diff --git a/winsup/cygwin/tty.h b/winsup/cygwin/tty.h index 927d7afd9..c7aeef85b 100644 --- a/winsup/cygwin/tty.h +++ b/winsup/cygwin/tty.h @@ -106,6 +106,7 @@ private: int num_pcon_attached_slaves; UINT term_code_page; bool need_clear_screen; + bool need_clear_screen_on_write; public: HANDLE from_master () const { return _from_master; }