diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index e457e2785..faa910692 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -2135,11 +2135,9 @@ private: const unsigned char *write_normal (unsigned const char*, unsigned const char *); void char_command (char); bool set_raw_win32_keyboard_mode (bool); - int output_tcsetattr (int a, const struct termios *t); /* Input calls */ int igncr_enabled (); - int input_tcsetattr (int a, const struct termios *t); void set_cursor_maybe (); static bool create_invisible_console (HWINSTA); static bool create_invisible_console_workaround (bool force); @@ -2196,7 +2194,6 @@ private: void fixup_after_exec () {fixup_after_fork_exec (true);} void fixup_after_fork (HANDLE) {fixup_after_fork_exec (false);} void set_close_on_exec (bool val); - void set_input_state (); bool send_winch_maybe (); void setup (); bool set_unit (); @@ -2245,8 +2242,10 @@ private: void get_duplicated_handle_set (handle_set_t *p); static void close_handle_set (handle_set_t *p); - static void request_xterm_mode_input (bool, const handle_set_t *p); - static void request_xterm_mode_output (bool, const handle_set_t *p); + static void set_input_mode (tty::cons_mode m, const termios *t, + const handle_set_t *p); + static void set_output_mode (tty::cons_mode m, const termios *t, + const handle_set_t *p); static void cons_master_thread (handle_set_t *p, tty *ttyp); diff --git a/winsup/cygwin/fhandler_console.cc b/winsup/cygwin/fhandler_console.cc index 4dee506dd..ca8eb6400 100644 --- a/winsup/cygwin/fhandler_console.cc +++ b/winsup/cygwin/fhandler_console.cc @@ -299,8 +299,8 @@ fhandler_console::cons_master_thread (handle_set_t *p, tty *ttyp) { /* Fix tab position */ /* Re-setting ENABLE_VIRTUAL_TERMINAL_PROCESSING fixes the tab position. */ - request_xterm_mode_output (false, p); - request_xterm_mode_output (true, p); + set_output_mode (tty::restore, &ti, p); + set_input_mode (tty::cygwin, &ti, p); } ttyp->kill_pgrp (SIGWINCH); } @@ -446,64 +446,72 @@ fhandler_console::rabuflen () return con_ra.rabuflen; } -/* The function request_xterm_mode_{in,out}put() should be static so that - they can be called even after the fhandler_console instance is deleted. */ +/* The function set_{in,out}put_mode() should be static so that they + can be called even after the fhandler_console instance is deleted. */ void -fhandler_console::request_xterm_mode_input (bool req, const handle_set_t *p) +fhandler_console::set_input_mode (tty::cons_mode m, const termios *t, + const handle_set_t *p) { - if (con_is_legacy) - return; + DWORD flags = 0, oflags; WaitForSingleObject (p->input_mutex, INFINITE); - DWORD dwMode; - GetConsoleMode (p->input_handle, &dwMode); - if (req) + GetConsoleMode (p->input_handle, &oflags); + switch (m) { - if (!(dwMode & ENABLE_VIRTUAL_TERMINAL_INPUT)) - { - dwMode |= ENABLE_VIRTUAL_TERMINAL_INPUT; - SetConsoleMode (p->input_handle, dwMode); - if (con.cursor_key_app_mode) /* Restore DECCKM */ - { - request_xterm_mode_output (true, p); - WriteConsoleW (p->output_handle, L"\033[?1h", 5, NULL, 0); - } - } + case tty::restore: + flags = ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT; + break; + case tty::cygwin: + flags = ENABLE_WINDOW_INPUT; + if (wincap.has_con_24bit_colors () && !con_is_legacy) + flags |= ENABLE_VIRTUAL_TERMINAL_INPUT; + else + flags |= ENABLE_MOUSE_INPUT; + break; + case tty::native: + if (t->c_lflag & ECHO) + flags |= ENABLE_ECHO_INPUT; + if (t->c_lflag & ICANON) + flags |= ENABLE_LINE_INPUT; + if (flags & ENABLE_ECHO_INPUT && !(flags & ENABLE_LINE_INPUT)) + /* This is illegal, so turn off the echo here, and fake it + when we read the characters */ + flags &= ~ENABLE_ECHO_INPUT; + if ((t->c_lflag & ISIG) && !(t->c_iflag & IGNBRK)) + flags |= ENABLE_PROCESSED_INPUT; + break; } - else - { - if (dwMode & ENABLE_VIRTUAL_TERMINAL_INPUT) - { - dwMode &= ~ENABLE_VIRTUAL_TERMINAL_INPUT; - SetConsoleMode (p->input_handle, dwMode); - } + SetConsoleMode (p->input_handle, flags); + if (!(oflags & ENABLE_VIRTUAL_TERMINAL_INPUT) + && (flags & ENABLE_VIRTUAL_TERMINAL_INPUT) + && con.cursor_key_app_mode) + { /* Restore DECCKM */ + set_output_mode (tty::cygwin, t, p); + WriteConsoleW (p->output_handle, L"\033[?1h", 5, NULL, 0); } ReleaseMutex (p->input_mutex); } void -fhandler_console::request_xterm_mode_output (bool req, const handle_set_t *p) +fhandler_console::set_output_mode (tty::cons_mode m, const termios *t, + const handle_set_t *p) { - if (con_is_legacy) - return; + DWORD flags = ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT; WaitForSingleObject (p->output_mutex, INFINITE); - DWORD dwMode; - GetConsoleMode (p->output_handle, &dwMode); - if (req) + switch (m) { - if (!(dwMode & ENABLE_VIRTUAL_TERMINAL_PROCESSING)) - { - dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING; - SetConsoleMode (p->output_handle, dwMode); - } - } - else - { - if (dwMode & ENABLE_VIRTUAL_TERMINAL_PROCESSING) - { - dwMode &= ~ENABLE_VIRTUAL_TERMINAL_PROCESSING; - SetConsoleMode (p->output_handle, dwMode); - } + case tty::restore: + break; + case tty::cygwin: + if (wincap.has_con_24bit_colors () && !con_is_legacy) + flags |= ENABLE_VIRTUAL_TERMINAL_PROCESSING; + fallthrough; + case tty::native: + if (wincap.has_con_24bit_colors () && !con_is_legacy + && (!(t->c_oflag & OPOST) || !(t->c_oflag & ONLCR))) + flags |= DISABLE_NEWLINE_AUTO_RETURN; + break; } + SetConsoleMode (p->output_handle, flags); ReleaseMutex (p->output_mutex); } @@ -616,8 +624,8 @@ fhandler_console::fix_tab_position (void) { /* Re-setting ENABLE_VIRTUAL_TERMINAL_PROCESSING fixes the tab position. */ - request_xterm_mode_output (false, &handle_set); - request_xterm_mode_output (true, &handle_set); + set_output_mode (tty::restore, &get_ttyp ()->ti, &handle_set); + set_output_mode (tty::cygwin, &get_ttyp ()->ti, &handle_set); } bool @@ -678,11 +686,7 @@ fhandler_console::read (void *pv, size_t& buflen) DWORD timeout = is_nonblocking () ? 0 : INFINITE; - set_input_state (); - - /* if system has 24 bit color capability, use xterm compatible mode. */ - if (wincap.has_con_24bit_colors ()) - request_xterm_mode_input (true, &handle_set); + set_input_mode (tty::cygwin, &get_ttyp ()->ti, &handle_set); while (!input_ready && !get_cons_readahead_valid ()) { @@ -1165,13 +1169,6 @@ out: return stat; } -void -fhandler_console::set_input_state () -{ - if (get_ttyp ()->rstcons ()) - input_tcsetattr (0, &get_ttyp ()->ti); -} - bool dev_console::fillin (HANDLE h) { @@ -1313,7 +1310,6 @@ fhandler_console::open (int flags, mode_t) con.set_default_attr (); } - get_ttyp ()->rstcons (false); set_open_status (); if (myself->pid == con.owner && wincap.has_con_24bit_colors ()) @@ -1338,12 +1334,8 @@ fhandler_console::open (int flags, mode_t) setenv ("TERM", "cygwin", 1); } - DWORD cflags; - if (GetConsoleMode (get_handle (), &cflags)) - SetConsoleMode (get_handle (), ENABLE_WINDOW_INPUT - | ((wincap.has_con_24bit_colors () && !con_is_legacy) ? - 0 : ENABLE_MOUSE_INPUT) - | cflags); + set_input_mode (tty::cygwin, &get_ttyp ()->ti, &handle_set); + set_output_mode (tty::cygwin, &get_ttyp ()->ti, &handle_set); debug_printf ("opened conin$ %p, conout$ %p", get_handle (), get_output_handle ()); @@ -1376,7 +1368,7 @@ fhandler_console::close () acquire_output_mutex (INFINITE); - if (shared_console_info && wincap.has_con_24bit_colors ()) + if (shared_console_info) { /* Restore console mode if this is the last closure. */ OBJECT_BASIC_INFORMATION obi; @@ -1386,8 +1378,8 @@ fhandler_console::close () if ((NT_SUCCESS (status) && obi.HandleCount == 1) || myself->pid == con.owner) { - request_xterm_mode_output (false, &handle_set); - request_xterm_mode_input (false, &handle_set); + set_output_mode (tty::restore, &get_ttyp ()->ti, &handle_set); + set_input_mode (tty::restore, &get_ttyp ()->ti, &handle_set); } } @@ -1561,154 +1553,19 @@ fhandler_console::tcflush (int queue) return res; } -int -fhandler_console::output_tcsetattr (int, struct termios const *t) -{ - /* All the output bits we can ignore */ - - acquire_output_mutex (INFINITE); - DWORD flags = ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT; - - DWORD oflags; - acquire_attach_mutex (INFINITE); - GetConsoleMode (get_output_handle (), &oflags); - if (wincap.has_con_24bit_colors () && !con_is_legacy - && (oflags & ENABLE_VIRTUAL_TERMINAL_PROCESSING)) - flags |= ENABLE_VIRTUAL_TERMINAL_PROCESSING; - - int res = SetConsoleMode (get_output_handle (), flags) ? 0 : -1; - release_attach_mutex (); - if (res) - __seterrno_from_win_error (GetLastError ()); - release_output_mutex (); - syscall_printf ("%d = tcsetattr(,%p) (ENABLE FLAGS %y) (lflag %y oflag %y)", - res, t, flags, t->c_lflag, t->c_oflag); - return res; -} - -int -fhandler_console::input_tcsetattr (int, struct termios const *t) -{ - /* Ignore the optional_actions stuff, since all output is emitted - instantly */ - acquire_input_mutex (INFINITE); - - DWORD oflags; - - acquire_attach_mutex (INFINITE); - if (!GetConsoleMode (get_handle (), &oflags)) - oflags = 0; - DWORD flags = 0; - -#if 0 - /* Enable/disable LF -> CRLF conversions */ - rbinary ((t->c_iflag & INLCR) ? false : true); -#endif - - /* There's some disparity between what we need and what's - available. We've got ECHO and ICANON, they've - got ENABLE_ECHO_INPUT and ENABLE_LINE_INPUT. */ - - termios_printf ("this %p, get_ttyp () %p, t %p", this, get_ttyp (), t); - get_ttyp ()->ti = *t; - - if (t->c_lflag & ECHO) - { - flags |= ENABLE_ECHO_INPUT; - } - if (t->c_lflag & ICANON) - { - flags |= ENABLE_LINE_INPUT; - } - - if (flags & ENABLE_ECHO_INPUT - && !(flags & ENABLE_LINE_INPUT)) - { - /* This is illegal, so turn off the echo here, and fake it - when we read the characters */ - - flags &= ~ENABLE_ECHO_INPUT; - } - - if ((t->c_lflag & ISIG) && !(t->c_iflag & IGNBRK)) - { - flags |= ENABLE_PROCESSED_INPUT; - } - - flags |= ENABLE_WINDOW_INPUT | - ((wincap.has_con_24bit_colors () && !con_is_legacy) ? - 0 : ENABLE_MOUSE_INPUT); - - if (wincap.has_con_24bit_colors () && !con_is_legacy - && (oflags & ENABLE_VIRTUAL_TERMINAL_INPUT)) - flags |= ENABLE_VIRTUAL_TERMINAL_INPUT; - - int res; - if (flags == oflags) - res = 0; - else - { - res = SetConsoleMode (get_handle (), flags) ? 0 : -1; - if (res < 0) - __seterrno (); - syscall_printf ("%d = tcsetattr(,%p) enable flags %y, c_lflag %y iflag %y", - res, t, flags, t->c_lflag, t->c_iflag); - } - release_attach_mutex (); - - get_ttyp ()->rstcons (false); - release_input_mutex (); - return res; -} - int fhandler_console::tcsetattr (int a, struct termios const *t) { - int res = output_tcsetattr (a, t); - if (res != 0) - return res; - return input_tcsetattr (a, t); + get_ttyp ()->ti = *t; + return 0; } int fhandler_console::tcgetattr (struct termios *t) { - int res; *t = get_ttyp ()->ti; - t->c_cflag |= CS8; - - DWORD flags; - - acquire_attach_mutex (INFINITE); - if (!GetConsoleMode (get_handle (), &flags)) - { - __seterrno (); - res = -1; - } - else - { - if (flags & ENABLE_ECHO_INPUT) - t->c_lflag |= ECHO; - - if (flags & ENABLE_LINE_INPUT) - t->c_lflag |= ICANON; - - if (flags & ENABLE_PROCESSED_INPUT) - t->c_lflag |= ISIG; - else - t->c_iflag |= IGNBRK; - - /* What about ENABLE_WINDOW_INPUT - and ENABLE_MOUSE_INPUT ? */ - - /* All the output bits we can ignore */ - res = 0; - } - release_attach_mutex (); - syscall_printf ("%d = tcgetattr(%p) enable flags %y, t->lflag %y, t->iflag %y", - res, t, flags, t->c_lflag, t->c_iflag); - return res; + return 0; } fhandler_console::fhandler_console (fh_devices unit) : @@ -3205,22 +3062,10 @@ fhandler_console::write (const void *vsrc, size_t len) acquire_attach_mutex (INFINITE); push_process_state process_state (PID_TTYOU); - acquire_output_mutex (INFINITE); - /* If system has 24 bit color capability, use xterm compatible mode. */ - if (wincap.has_con_24bit_colors ()) - request_xterm_mode_output (true, &handle_set); - if (wincap.has_con_24bit_colors () && !con_is_legacy) - { - DWORD dwMode; - GetConsoleMode (get_output_handle (), &dwMode); - if (!(get_ttyp ()->ti.c_oflag & OPOST) || - !(get_ttyp ()->ti.c_oflag & ONLCR)) - dwMode |= DISABLE_NEWLINE_AUTO_RETURN; - else - dwMode &= ~DISABLE_NEWLINE_AUTO_RETURN; - SetConsoleMode (get_output_handle (), dwMode); - } + set_output_mode (tty::cygwin, &get_ttyp ()->ti, &handle_set); + + acquire_output_mutex (INFINITE); /* Run and check for ansi sequences */ unsigned const char *src = (unsigned char *) vsrc; diff --git a/winsup/cygwin/select.cc b/winsup/cygwin/select.cc index dc75a2dbf..085de6deb 100644 --- a/winsup/cygwin/select.cc +++ b/winsup/cygwin/select.cc @@ -1147,8 +1147,8 @@ static int console_startup (select_record *me, select_stuff *stuff) { fhandler_console *fh = (fhandler_console *) me->fh; - if (wincap.has_con_24bit_colors ()) - fhandler_console::request_xterm_mode_input (true, fh->get_handle_set ()); + fhandler_console::set_input_mode (tty::cygwin, &((tty *)fh->tc ())->ti, + fh->get_handle_set ()); select_console_info *ci = stuff->device_specific_console; if (ci->start) diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc index 4d4d599ca..323630fcb 100644 --- a/winsup/cygwin/spawn.cc +++ b/winsup/cygwin/spawn.cc @@ -607,6 +607,7 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv, fhandler_pty_slave *ptys_primary = NULL; fhandler_console *cons_native = NULL; + termios *cons_ti = NULL; for (int i = 0; i < 3; i ++) { const int chk_order[] = {1, 0, 2}; @@ -621,16 +622,19 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv, else if (fh && fh->get_major () == DEV_CONS_MAJOR) { fhandler_console *cons = (fhandler_console *) fh; - if (wincap.has_con_24bit_colors () && !iscygwin ()) + if (!iscygwin ()) { if (cons_native == NULL) - cons_native = cons; + { + cons_native = cons; + cons_ti = &((tty *)cons->tc ())->ti; + } if (fd == 0) - fhandler_console::request_xterm_mode_input (false, - cons->get_handle_set ()); + fhandler_console::set_input_mode (tty::native, + cons_ti, cons->get_handle_set ()); else if (fd == 1 || fd == 2) - fhandler_console::request_xterm_mode_output (false, - cons->get_handle_set ()); + fhandler_console::set_output_mode (tty::native, + cons_ti, cons->get_handle_set ()); } } } @@ -996,10 +1000,10 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv, } if (cons_native) { - fhandler_console::request_xterm_mode_output (true, - &cons_handle_set); - fhandler_console::request_xterm_mode_input (true, - &cons_handle_set); + fhandler_console::set_output_mode (tty::cygwin, cons_ti, + &cons_handle_set); + fhandler_console::set_input_mode (tty::cygwin, cons_ti, + &cons_handle_set); fhandler_console::close_handle_set (&cons_handle_set); } myself.exit (EXITCODE_NOSET); @@ -1031,10 +1035,10 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv, } if (cons_native) { - fhandler_console::request_xterm_mode_output (true, - &cons_handle_set); - fhandler_console::request_xterm_mode_input (true, - &cons_handle_set); + fhandler_console::set_output_mode (tty::cygwin, cons_ti, + &cons_handle_set); + fhandler_console::set_input_mode (tty::cygwin, cons_ti, + &cons_handle_set); fhandler_console::close_handle_set (&cons_handle_set); } break; diff --git a/winsup/cygwin/tty.h b/winsup/cygwin/tty.h index a8ddd68d6..4ef1e04c9 100644 --- a/winsup/cygwin/tty.h +++ b/winsup/cygwin/tty.h @@ -39,7 +39,6 @@ class tty_min struct status_flags { unsigned initialized : 1; /* Set if tty is initialized */ - unsigned rstcons : 1; /* Set if console needs to be set to "non-cooked" */ } status; public: @@ -51,7 +50,6 @@ public: int last_sig; IMPLEMENT_STATUS_FLAG (bool, initialized) - IMPLEMENT_STATUS_FLAG (bool, rstcons) struct termios ti; struct winsize winsize; @@ -97,6 +95,12 @@ public: to_cyg, to_nat }; + enum cons_mode + { + restore, /* For restoring when exit from cygwin. */ + cygwin, /* For cygwin apps */ + native /* For native apps executed from cygwin. */ + }; private: HANDLE _from_master;