diff --git a/winsup/cygwin/devices.cc b/winsup/cygwin/devices.cc index 9f6e80acb..747dcc8c6 100644 --- a/winsup/cygwin/devices.cc +++ b/winsup/cygwin/devices.cc @@ -69,6 +69,21 @@ exists_ntdev_silent (const device& dev) return exists_ntdev (dev) ? -1 : false; } +static BOOL CALLBACK +enum_cons_dev (HWND hw, LPARAM lp) +{ + unsigned long *bitmask = (unsigned long *) lp; + HANDLE h = NULL; + fhandler_console::console_state *cs; + if ((cs = fhandler_console::open_shared_console (hw, h))) + { + *bitmask |= (1UL << cs->tty_min_state.getntty ()); + UnmapViewOfFile ((void *) cs); + CloseHandle (h); + } + return TRUE; +} + static int exists_console (const device& dev) { @@ -81,8 +96,13 @@ exists_console (const device& dev) return cygheap && cygheap->ctty && cygheap->ctty->is_console () && fhandler_console::exists (); default: - /* Only show my own console device (for now?) */ - return iscons_dev (myself->ctty) && myself->ctty == devn; + if (dev.get_minor () < MAX_CONS_DEV) + { + unsigned long bitmask = 0; + EnumWindows (enum_cons_dev, (LPARAM) &bitmask); + return bitmask & (1UL << dev.get_minor ()); + } + return false; } } diff --git a/winsup/cygwin/devices.in b/winsup/cygwin/devices.in index 48199f46c..a467cb593 100644 --- a/winsup/cygwin/devices.in +++ b/winsup/cygwin/devices.in @@ -65,6 +65,21 @@ exists_ntdev_silent (const device& dev) return exists_ntdev (dev) ? -1 : false; } +static BOOL CALLBACK +enum_cons_dev (HWND hw, LPARAM lp) +{ + unsigned long *bitmask = (unsigned long *) lp; + HANDLE h = NULL; + fhandler_console::console_state *cs; + if ((cs = fhandler_console::open_shared_console (hw, h))) + { + *bitmask |= (1UL << cs->tty_min_state.getntty ()); + UnmapViewOfFile ((void *) cs); + CloseHandle (h); + } + return TRUE; +} + static int exists_console (const device& dev) { @@ -77,8 +92,13 @@ exists_console (const device& dev) return cygheap && cygheap->ctty && cygheap->ctty->is_console () && fhandler_console::exists (); default: - /* Only show my own console device (for now?) */ - return iscons_dev (myself->ctty) && myself->ctty == devn; + if (dev.get_minor () < MAX_CONS_DEV) + { + unsigned long bitmask = 0; + EnumWindows (enum_cons_dev, (LPARAM) &bitmask); + return bitmask & (1UL << dev.get_minor ()); + } + return false; } } diff --git a/winsup/cygwin/fhandler/console.cc b/winsup/cygwin/fhandler/console.cc index ee07c84f8..ee392fda2 100644 --- a/winsup/cygwin/fhandler/console.cc +++ b/winsup/cygwin/fhandler/console.cc @@ -41,19 +41,20 @@ details. */ #define ALT_PRESSED (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED) #define CTRL_PRESSED (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED) -#define con (shared_console_info->con) +#define con (shared_console_info[unit]->con) #define srTop (con.b.srWindow.Top + con.scroll_region.Top) #define srBottom ((con.scroll_region.Bottom < 0) ? \ con.b.srWindow.Bottom : \ con.b.srWindow.Top + con.scroll_region.Bottom) -#define con_is_legacy (shared_console_info && con.is_legacy) +#define con_is_legacy (shared_console_info[unit] && con.is_legacy) #define CONS_THREAD_SYNC "cygcons.thread_sync" static bool NO_COPY master_thread_started = false; const unsigned fhandler_console::MAX_WRITE_CHARS = 16384; -fhandler_console::console_state NO_COPY *fhandler_console::shared_console_info; +fhandler_console::console_state NO_COPY + *fhandler_console::shared_console_info[MAX_CONS_DEV + 1]; bool NO_COPY fhandler_console::invisible_console; @@ -65,6 +66,56 @@ static struct fhandler_base::rabuf_t con_ra; in xterm compatible mode */ static wchar_t last_char; +DWORD +fhandler_console::attach_console (pid_t owner, bool *err) +{ + DWORD resume_pid = (DWORD) -1; + pinfo p (owner); + if (p) + { + DWORD attached = + fhandler_pty_common::get_console_process_id (p->dwProcessId, + true, false, false); + if (!attached) + { + resume_pid = + fhandler_pty_common::get_console_process_id (myself->dwProcessId, + false, false, false); + FreeConsole (); + BOOL r = AttachConsole (p->dwProcessId); + if (!r) + { + if (resume_pid) + AttachConsole (resume_pid); + if (err) + *err = true; + return (DWORD) -1; + } + } + } + return resume_pid; +} + +void +fhandler_console::detach_console (DWORD resume_pid, pid_t owner) +{ + if (resume_pid == (DWORD) -1) + return; + if (resume_pid) + { + FreeConsole (); + AttachConsole (resume_pid); + } + else if (myself->pid != owner) + FreeConsole (); +} + +pid_t +fhandler_console::get_owner () +{ + return con.owner; +} + /* simple helper class to accumulate output in a buffer and send that to the console on request: */ static class write_pending_buffer @@ -73,21 +124,19 @@ private: static const size_t WPBUF_LEN = 256u; char buf[WPBUF_LEN]; size_t ixput; - HANDLE output_handle; public: - void init (HANDLE &handle) + void init () { - output_handle = handle; empty (); } - inline void put (char x) + inline void put (HANDLE output_handle, pid_t owner, char x) { if (ixput == WPBUF_LEN) - send (); + send (output_handle, owner); buf[ixput++] = x; } inline void empty () { ixput = 0u; } - inline void send () + inline void send (HANDLE output_handle, pid_t owner) { if (!output_handle) { @@ -125,11 +174,25 @@ public: } } acquire_attach_mutex (mutex_timeout); + DWORD resume_pid = fhandler_console::attach_console (owner); WriteConsoleW (output_handle, bufw, len, NULL, 0); + fhandler_console::detach_console (resume_pid, owner); release_attach_mutex (); } } wpbuf; +void +fhandler_console::wpbuf_put (char c) +{ + wpbuf.put (get_output_handle (), con.owner, c); +} + +void +fhandler_console::wpbuf_send () +{ + wpbuf.send (get_output_handle (), con.owner); +} + static void beep () { @@ -155,7 +218,7 @@ fhandler_console::open_shared_console (HWND hw, HANDLE& h, bool& create) shared_locations m = create ? SH_SHARED_CONSOLE : SH_JUSTOPEN; console_state *res = (console_state *) - open_shared (namebuf, 0, h, sizeof (*shared_console_info), &m); + open_shared (namebuf, 0, h, sizeof (console_state), &m); create = m != SH_JUSTOPEN; return res; } @@ -182,7 +245,7 @@ enum_windows (HWND hw, LPARAM lp) fhandler_console::console_state *cs; if ((cs = fhandler_console::open_shared_console (hw, h))) { - this1->bitmask ^= 1 << cs->tty_min_state.getntty (); + this1->bitmask ^= 1UL << cs->tty_min_state.getntty (); UnmapViewOfFile ((void *) cs); CloseHandle (h); } @@ -190,12 +253,12 @@ enum_windows (HWND hw, LPARAM lp) } console_unit::console_unit (HWND me0): - bitmask (0xffffffff), me (me0) + bitmask (~0UL), me (me0) { EnumWindows (enum_windows, (LPARAM) this); n = (_minor_t) ffs (bitmask) - 1; if (n < 0) - api_fatal ("console device allocation failure - too many consoles in use, max consoles is 32"); + api_fatal ("console device allocation failure - too many consoles in use, max consoles is 64"); } static DWORD @@ -286,6 +349,7 @@ inrec_eq (const INPUT_RECORD *a, const INPUT_RECORD *b, DWORD n) void fhandler_console::cons_master_thread (handle_set_t *p, tty *ttyp) { + const _minor_t unit = p->unit; const int additional_space = 128; /* Possible max number of incoming events during the process. Additional space should be left for writeback fix. */ @@ -436,7 +500,7 @@ fhandler_console::cons_master_thread (handle_set_t *p, tty *ttyp) con.scroll_region.Bottom = -1; if (wincap.has_con_24bit_colors () && !con_is_legacy && wincap.has_con_broken_tabs ()) - fix_tab_position (p->output_handle); + fix_tab_position (p->output_handle, con.owner); ttyp->kill_pgrp (SIGWINCH); } processed = true; @@ -562,49 +626,95 @@ skip_writeback: free (input_tmp); } +struct scan_console_args_t +{ + _minor_t unit; + fhandler_console::console_state **shared_console_info; +}; + +BOOL CALLBACK +scan_console (HWND hw, LPARAM lp) +{ + scan_console_args_t *p = (scan_console_args_t *) lp; + HANDLE h = NULL; + fhandler_console::console_state *cs; + if ((cs = fhandler_console::open_shared_console (hw, h))) + { + if (p->unit == minor (cs->tty_min_state.getntty ())) + { + *p->shared_console_info = cs; + CloseHandle (h); + return TRUE; + } + UnmapViewOfFile ((void *) cs); + CloseHandle (h); + } + return TRUE; +} + bool fhandler_console::set_unit () { - bool created; + bool created = false; fh_devices devset; lock_ttys here; HWND me; fh_devices this_unit = dev (); - bool generic_console = this_unit == FH_CONIN || this_unit == FH_CONOUT; - if (shared_console_info) - { - fh_devices shared_unit = - (fh_devices) shared_console_info->tty_min_state.getntty (); - devset = (shared_unit == this_unit || this_unit == FH_CONSOLE - || generic_console - || this_unit == FH_TTY) ? - shared_unit : FH_ERROR; - created = false; - } - else if ((!generic_console && - (myself->ctty != -1 && !iscons_dev (myself->ctty))) - || !(me = GetConsoleWindow ())) + bool generic_console = + this_unit == FH_CONSOLE || this_unit == FH_CONIN || this_unit == FH_CONOUT; + if (!generic_console && this_unit != FH_TTY) + unit = get_minor (); + else if (myself->ctty != -1) + unit = device::minor (myself->ctty); + + if (shared_console_info[unit]) + ; /* Do nothing */ + else if (generic_console && myself->ctty != -1 && !iscons_dev (myself->ctty)) devset = FH_ERROR; else { - created = true; - shared_console_info = - open_shared_console (me, cygheap->console_h, created); - ProtectHandleINH (cygheap->console_h); - if (created) - shared_console_info-> - tty_min_state.setntty (DEV_CONS_MAJOR, console_unit (me)); - devset = (fh_devices) shared_console_info->tty_min_state.getntty (); - if (created) - con.owner = myself->pid; + if (!generic_console && (dev_t) myself->ctty != get_device ()) + { + /* Scan for existing shared console info */ + scan_console_args_t arg = { unit, &shared_console_info[unit] }; + EnumWindows (scan_console, (LPARAM) &arg); + } + if (generic_console || !shared_console_info[unit]) + { + me = GetConsoleWindow (); + if (!me) + devset = FH_ERROR; + else + { + created = true; + fhandler_console::console_state *cs = + open_shared_console (me, cygheap->console_h, created); + ProtectHandleINH (cygheap->console_h); + if (created) + { + unit = console_unit (me); + cs->tty_min_state.setntty (DEV_CONS_MAJOR, unit); + } + else + unit = device::minor (cs->tty_min_state.ntty); + shared_console_info[unit] = cs; + if (created) + con.owner = myself->pid; + } + } } - if (!created && shared_console_info) + if (shared_console_info[unit]) { - while (con.owner > MAX_PID) - Sleep (1); - pinfo p (con.owner); - if (!p) - con.owner = myself->pid; + devset = (fh_devices) shared_console_info[unit]->tty_min_state.getntty (); + _tc = &(shared_console_info[unit]->tty_min_state); + if (!created) + { + while (con.owner > MAX_PID) + Sleep (1); + pinfo p (con.owner); + if (!p) + con.owner = myself->pid; + } } dev ().parse (devset); @@ -651,7 +761,7 @@ fhandler_console::setup () con.set_default_attr (); con.backspace_keycode = CERASE; con.cons_rapoi = NULL; - shared_console_info->tty_min_state.is_console = true; + shared_console_info[unit]->tty_min_state.is_console = true; con.cursor_key_app_mode = false; con.disable_master_thread = true; con.master_thread_suspended = false; @@ -695,9 +805,11 @@ void fhandler_console::set_input_mode (tty::cons_mode m, const termios *t, const handle_set_t *p) { + const _minor_t unit = p->unit; DWORD oflags; WaitForSingleObject (p->input_mutex, mutex_timeout); acquire_attach_mutex (mutex_timeout); + DWORD resume_pid = attach_console (con.owner); GetConsoleMode (p->input_handle, &oflags); DWORD flags = oflags & (ENABLE_EXTENDED_FLAGS | ENABLE_INSERT_MODE | ENABLE_QUICK_EDIT_MODE); @@ -736,6 +848,7 @@ fhandler_console::set_input_mode (tty::cons_mode m, const termios *t, set_output_mode (tty::cygwin, t, p); WriteConsoleW (p->output_handle, L"\033[?1h", 5, NULL, 0); } + detach_console (resume_pid, con.owner); release_attach_mutex (); ReleaseMutex (p->input_mutex); } @@ -744,6 +857,7 @@ void fhandler_console::set_output_mode (tty::cons_mode m, const termios *t, const handle_set_t *p) { + const _minor_t unit = p->unit; DWORD flags = ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT; if (con.orig_virtual_terminal_processing_mode) flags |= ENABLE_VIRTUAL_TERMINAL_PROCESSING; @@ -763,7 +877,9 @@ fhandler_console::set_output_mode (tty::cons_mode m, const termios *t, break; } acquire_attach_mutex (mutex_timeout); + DWORD resume_pid = attach_console (con.owner); SetConsoleMode (p->output_handle, flags); + detach_console (resume_pid, con.owner); release_attach_mutex (); ReleaseMutex (p->output_mutex); } @@ -786,9 +902,10 @@ fhandler_console::setup_for_non_cygwin_app () void fhandler_console::cleanup_for_non_cygwin_app (handle_set_t *p) { + const _minor_t unit = p->unit; termios dummy = {0, }; - termios *ti = - shared_console_info ? &(shared_console_info->tty_min_state.ti) : &dummy; + termios *ti = shared_console_info[unit] ? + &(shared_console_info[unit]->tty_min_state.ti) : &dummy; /* Cleaning-up console mode for non-cygwin app. */ /* conmode can be tty::restore when non-cygwin app is exec'ed from login shell. */ @@ -805,11 +922,12 @@ tty_min * tty_list::get_cttyp () { dev_t n = myself->ctty; + const _minor_t unit = device::minor (n); if (iscons_dev (n)) - return fhandler_console::shared_console_info ? - &fhandler_console::shared_console_info->tty_min_state : NULL; + return fhandler_console::shared_console_info[unit] ? + &fhandler_console::shared_console_info[unit]->tty_min_state : NULL; else if (istty_slave_dev (n)) - return &ttys[device::minor (n)]; + return &ttys[unit]; else return NULL; } @@ -851,6 +969,10 @@ fhandler_console::setup_io_mutex (void) } if (res == WAIT_OBJECT_0) release_output_mutex (); + + extern HANDLE attach_mutex; + if (!attach_mutex) + attach_mutex = CreateMutex (&sec_none_nih, FALSE, NULL); } inline DWORD @@ -893,7 +1015,9 @@ fhandler_console::set_cursor_maybe () con.dwLastCursorPosition.Y != con.b.dwCursorPosition.Y) { acquire_attach_mutex (mutex_timeout); + DWORD resume_pid = attach_console (con.owner); SetConsoleCursorPosition (get_output_handle (), con.b.dwCursorPosition); + detach_console (resume_pid, con.owner); release_attach_mutex (); con.dwLastCursorPosition = con.b.dwCursorPosition; } @@ -902,15 +1026,17 @@ fhandler_console::set_cursor_maybe () /* Workaround for a bug of windows xterm compatible mode. */ /* The horizontal tab positions are broken after resize. */ void -fhandler_console::fix_tab_position (HANDLE h) +fhandler_console::fix_tab_position (HANDLE h, pid_t owner) { /* Re-setting ENABLE_VIRTUAL_TERMINAL_PROCESSING fixes the tab position. */ DWORD mode; acquire_attach_mutex (mutex_timeout); + DWORD resume_pid = attach_console (owner); GetConsoleMode (h, &mode); SetConsoleMode (h, mode & ~ENABLE_VIRTUAL_TERMINAL_PROCESSING); SetConsoleMode (h, mode); + detach_console (resume_pid, owner); release_attach_mutex (); } @@ -927,7 +1053,7 @@ fhandler_console::send_winch_maybe () con.scroll_region.Bottom = -1; if (wincap.has_con_24bit_colors () && !con_is_legacy && wincap.has_con_broken_tabs ()) - fix_tab_position (get_output_handle ()); + fix_tab_position (get_output_handle (), con.owner); /* longjmp() may be called in the signal handler like less, so release input_mutex temporarily before kill_pgrp(). */ release_input_mutex (); @@ -949,7 +1075,9 @@ fhandler_console::mouse_aware (MOUSE_EVENT_RECORD& mouse_event) and remember adjusted position in state for use by read() */ CONSOLE_SCREEN_BUFFER_INFO now; acquire_attach_mutex (mutex_timeout); + DWORD resume_pid = attach_console (con.owner); BOOL r = GetConsoleScreenBufferInfo (get_output_handle (), &now); + detach_console (resume_pid, con.owner); release_attach_mutex (); if (!r) /* Cannot adjust position by window scroll buffer offset */ @@ -1028,7 +1156,9 @@ wait_retry: { /* Confirm the handle is still valid */ DWORD mode; acquire_attach_mutex (mutex_timeout); + DWORD resume_pid = attach_console (con.owner); BOOL res = GetConsoleMode (get_handle (), &mode); + detach_console (resume_pid, con.owner); release_attach_mutex (); if (res) goto wait_retry; @@ -1098,7 +1228,7 @@ fhandler_console::process_input_message (void) { char tmp[60]; - if (!shared_console_info) + if (!shared_console_info[unit]) return input_error; termios *ti = &(get_ttyp ()->ti); @@ -1108,8 +1238,10 @@ fhandler_console::process_input_message (void) INPUT_RECORD input_rec[INREC_SIZE]; acquire_attach_mutex (mutex_timeout); + DWORD resume_pid = attach_console (con.owner); BOOL r = PeekConsoleInputW (get_handle (), input_rec, INREC_SIZE, &total_read); + detach_console (resume_pid, con.owner); release_attach_mutex (); if (!r) { @@ -1498,7 +1630,9 @@ out: { DWORD discarded; acquire_attach_mutex (mutex_timeout); + DWORD resume_pid = attach_console (con.owner); ReadConsoleInputW (get_handle (), input_rec, discard_len, &discarded); + detach_console (resume_pid, con.owner); release_attach_mutex (); con.num_processed -= min (con.num_processed, discarded); } @@ -1509,7 +1643,9 @@ bool dev_console::fillin (HANDLE h) { acquire_attach_mutex (mutex_timeout); + DWORD resume_pid = fhandler_console::attach_console (owner); bool ret = GetConsoleScreenBufferInfo (h, &b); + fhandler_console::detach_console (resume_pid, owner); release_attach_mutex (); if (ret) @@ -1564,7 +1700,9 @@ dev_console::scroll_buffer (HANDLE h, int x1, int y1, int x2, int y2, dest.X = xn >= 0 ? xn : dwWinSize.X - 1; dest.Y = yn >= 0 ? yn : b.srWindow.Bottom; acquire_attach_mutex (mutex_timeout); + DWORD resume_pid = fhandler_console::attach_console (owner); ScrollConsoleScreenBufferW (h, &sr1, &sr2, dest, &fill); + fhandler_console::detach_console (resume_pid, owner); release_attach_mutex (); } @@ -1616,9 +1754,17 @@ fhandler_console::open (int flags, mode_t) set_output_handle (NULL); /* Open the input handle as handle_ */ + bool err = false; + DWORD resume_pid = attach_console (con.owner, &err); + if (err) + { + set_errno (EACCES); + return 0; + } h = CreateFileW (L"CONIN$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, &sec_none, OPEN_EXISTING, 0, 0); + detach_console (resume_pid, con.owner); if (h == INVALID_HANDLE_VALUE) { @@ -1628,9 +1774,16 @@ fhandler_console::open (int flags, mode_t) set_handle (h); handle_set.input_handle = h; + resume_pid = attach_console (con.owner, &err); + if (err) + { + set_errno (EACCES); + return 0; + } h = CreateFileW (L"CONOUT$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, &sec_none, OPEN_EXISTING, 0, 0); + detach_console (resume_pid, con.owner); if (h == INVALID_HANDLE_VALUE) { @@ -1639,12 +1792,14 @@ fhandler_console::open (int flags, mode_t) } set_output_handle (h); handle_set.output_handle = h; - wpbuf.init (get_output_handle ()); + wpbuf.init (); setup_io_mutex (); handle_set.input_mutex = input_mutex; handle_set.output_mutex = output_mutex; + handle_set.unit = unit; + if (con.fillin (get_output_handle ())) { con.current_win32_attr = con.b.wAttributes; @@ -1661,6 +1816,7 @@ fhandler_console::open (int flags, mode_t) DWORD dwMode; /* Check xterm compatible mode in output */ acquire_attach_mutex (mutex_timeout); + DWORD resume_pid = attach_console (con.owner); GetConsoleMode (get_output_handle (), &dwMode); con.orig_virtual_terminal_processing_mode = !!(dwMode & ENABLE_VIRTUAL_TERMINAL_PROCESSING); @@ -1674,6 +1830,7 @@ fhandler_console::open (int flags, mode_t) dwMode | ENABLE_VIRTUAL_TERMINAL_INPUT)) is_legacy = true; SetConsoleMode (get_handle (), dwMode); + detach_console (resume_pid, con.owner); release_attach_mutex (); con.is_legacy = is_legacy; extern int sawTERM; @@ -1729,14 +1886,15 @@ fhandler_console::close () acquire_output_mutex (mutex_timeout); - if (shared_console_info) + if (shared_console_info[unit]) { /* Restore console mode if this is the last closure. */ OBJECT_BASIC_INFORMATION obi; NTSTATUS status; status = NtQueryObject (get_handle (), ObjectBasicInformation, &obi, sizeof obi, NULL); - if ((NT_SUCCESS (status) && obi.HandleCount == 1) + if ((NT_SUCCESS (status) && obi.HandleCount == 1 + && (dev_t) myself->ctty == get_device ()) || myself->pid == con.owner) { /* Cleaning-up console mode for cygwin apps. */ @@ -1748,7 +1906,7 @@ fhandler_console::close () release_output_mutex (); - if (shared_console_info && con.owner == myself->pid + if (shared_console_info[unit] && con.owner == myself->pid && master_thread_started) { char name[MAX_PATH]; @@ -1770,9 +1928,16 @@ fhandler_console::close () if (con_ra.rabuf) free (con_ra.rabuf); + memset (&con_ra, 0, sizeof (con_ra)); - if (!have_execed && !invisible_console) + if (!have_execed && !invisible_console + && (myself->ctty <= 0 || get_device () == (dev_t) myself->ctty)) free_console (); + + if (shared_console_info[unit]) + UnmapViewOfFile ((void *) shared_console_info[unit]); + shared_console_info[unit] = NULL; + return 0; } @@ -1847,7 +2012,9 @@ fhandler_console::ioctl (unsigned int cmd, void *arg) int ret = 0; INPUT_RECORD inp[INREC_SIZE]; acquire_attach_mutex (mutex_timeout); + DWORD resume_pid = attach_console (con.owner); BOOL r = PeekConsoleInputW (get_handle (), inp, INREC_SIZE, &n); + detach_console (resume_pid, con.owner); release_attach_mutex (); if (!r) { @@ -1906,7 +2073,9 @@ fhandler_console::tcflush (int queue) || queue == TCIOFLUSH) { acquire_attach_mutex (mutex_timeout); + DWORD resume_pid = attach_console (con.owner); BOOL r = FlushConsoleInputBuffer (get_handle ()); + detach_console (resume_pid, con.owner); release_attach_mutex (); if (!r) { @@ -1933,15 +2102,14 @@ fhandler_console::tcgetattr (struct termios *t) return 0; } -fhandler_console::fhandler_console (fh_devices unit) : +fhandler_console::fhandler_console (fh_devices devunit) : fhandler_termios (), input_ready (false), thread_sync_event (NULL), - input_mutex (NULL), output_mutex (NULL) + input_mutex (NULL), output_mutex (NULL), unit (MAX_CONS_DEV) { - if (unit > 0) - dev ().parse (unit); + if (devunit > 0) + dev ().parse (devunit); setup (); trunc_buf.len = 0; - _tc = &(shared_console_info->tty_min_state); } void @@ -1982,7 +2150,9 @@ dev_console::set_color (HANDLE h) if (h) { acquire_attach_mutex (mutex_timeout); + DWORD resume_pid = fhandler_console::attach_console (owner); SetConsoleTextAttribute (h, current_win32_attr); + fhandler_console::detach_console (resume_pid, owner); release_attach_mutex (); } } @@ -2039,6 +2209,7 @@ dev_console::scroll_window (HANDLE h, int x1, int y1, int x2, int y2) sr.Left = sr.Right = dwEnd.X = 0; acquire_attach_mutex (mutex_timeout); + DWORD resume_pid = fhandler_console::attach_console (owner); if (b.srWindow.Bottom + toscroll >= b.dwSize.Y) { /* So we're at the end of the buffer and scrolling the console window @@ -2093,6 +2264,7 @@ dev_console::scroll_window (HANDLE h, int x1, int y1, int x2, int y2) /* Eventually set cursor to new end position at the top of the window. */ dwEnd.Y++; SetConsoleCursorPosition (h, dwEnd); + fhandler_console::detach_console (resume_pid, owner); release_attach_mutex (); /* Fix up console buffer info. */ fillin (h); @@ -2151,8 +2323,10 @@ dev_console::clear_screen (HANDLE h, int x1, int y1, int x2, int y2) tlc.Y = y2; } acquire_attach_mutex (mutex_timeout); + DWORD resume_pid = fhandler_console::attach_console (owner); FillConsoleOutputCharacterW (h, L' ', num, tlc, &done); FillConsoleOutputAttribute (h, current_win32_attr, num, tlc, &done); + fhandler_console::detach_console (resume_pid, owner); release_attach_mutex (); } @@ -2187,7 +2361,9 @@ fhandler_console::cursor_set (bool rel_to_top, int x, int y) pos.X = x; pos.Y = y; acquire_attach_mutex (mutex_timeout); + DWORD resume_pid = attach_console (con.owner); SetConsoleCursorPosition (get_output_handle (), pos); + detach_console (resume_pid, con.owner); release_attach_mutex (); } @@ -2261,7 +2437,9 @@ fhandler_console::write_console (PWCHAR buf, DWORD len, DWORD& done) { DWORD nbytes = len > MAX_WRITE_CHARS ? MAX_WRITE_CHARS : len; acquire_attach_mutex (mutex_timeout); + DWORD resume_pid = attach_console (con.owner); BOOL r = WriteConsoleW (get_output_handle (), buf, nbytes, &done, 0); + detach_console (resume_pid, con.owner); release_attach_mutex (); if (!r) { @@ -2313,9 +2491,7 @@ ReadConsoleOutputWrapper (HANDLE h, PCHAR_INFO buf, COORD bufsiz, if ((width == 0) || (height == 0)) return TRUE; - acquire_attach_mutex (mutex_timeout); BOOL success = ReadConsoleOutputW (h, buf, bufsiz, coord, ®ion); - release_attach_mutex (); if (success) /* it worked */; else if (GetLastError () == ERROR_NOT_ENOUGH_MEMORY && (width * height) > 1) @@ -2351,14 +2527,20 @@ dev_console::save_restore (HANDLE h, char c) SMALL_RECT now = {}; /* Read the whole buffer */ now.Bottom = save_bufsize.Y - 1; now.Right = save_bufsize.X - 1; + acquire_attach_mutex (mutex_timeout); + DWORD resume_pid = fhandler_console::attach_console (owner); if (!ReadConsoleOutputWrapper (h, save_buf, save_bufsize, now)) debug_printf ("ReadConsoleOutputWrapper(h, ...) failed during save, %E"); + fhandler_console::detach_console (resume_pid, owner); + release_attach_mutex (); /* Position at top of buffer */ COORD cob = {}; acquire_attach_mutex (mutex_timeout); + resume_pid = fhandler_console::attach_console (owner); if (!SetConsoleCursorPosition (h, cob)) debug_printf ("SetConsoleCursorInfo(%p, ...) failed during save, %E", h); + fhandler_console::detach_console (resume_pid, owner); release_attach_mutex (); /* Clear entire buffer */ @@ -2374,7 +2556,9 @@ dev_console::save_restore (HANDLE h, char c) /* Restore whole buffer */ clear_screen (h, 0, 0, b.dwSize.X - 1, b.dwSize.Y - 1); acquire_attach_mutex (mutex_timeout); + DWORD resume_pid = fhandler_console::attach_console (owner); BOOL res = WriteConsoleOutputW (h, save_buf, save_bufsize, cob, &now); + fhandler_console::detach_console (resume_pid, owner); release_attach_mutex (); if (!res) debug_printf ("WriteConsoleOutputW failed, %E"); @@ -2387,11 +2571,13 @@ dev_console::save_restore (HANDLE h, char c) /* CGF: NOOP? Doesn't seem to position screen as expected */ /* Temporarily position at top of screen */ acquire_attach_mutex (mutex_timeout); + resume_pid = fhandler_console::attach_console (owner); if (!SetConsoleCursorPosition (h, cob)) debug_printf ("SetConsoleCursorInfo(%p, cob) failed during restore, %E", h); /* Position where we were previously */ if (!SetConsoleCursorPosition (h, save_cursor)) debug_printf ("SetConsoleCursorInfo(%p, save_cursor) failed during restore, %E", h); + fhandler_console::detach_console (resume_pid, owner); release_attach_mutex (); /* Get back correct version of buffer information */ dwEnd.X = dwEnd.Y = 0; @@ -2507,24 +2693,26 @@ fhandler_console::char_command (char c) break; #endif case 'b': /* REP */ - wpbuf.put (c); + wpbuf_put (c); if (wincap.has_con_esc_rep ()) /* Just send the sequence */ - wpbuf.send (); + wpbuf_send (); else if (last_char && last_char != L'\n') { acquire_attach_mutex (mutex_timeout); + DWORD resume_pid = attach_console (con.owner); for (int i = 0; i < con.args[0]; i++) WriteConsoleW (get_output_handle (), &last_char, 1, 0, 0); + detach_console (resume_pid, con.owner); release_attach_mutex (); } break; case 'r': /* DECSTBM */ con.scroll_region.Top = con.args[0] ? con.args[0] - 1 : 0; con.scroll_region.Bottom = con.args[1] ? con.args[1] - 1 : -1; - wpbuf.put (c); + wpbuf_put (c); /* Just send the sequence */ - wpbuf.send (); + wpbuf_send (); break; case 'L': /* IL */ if (wincap.has_con_broken_il_dl ()) @@ -2536,11 +2724,14 @@ fhandler_console::char_command (char c) if (y == con.b.srWindow.Bottom) { acquire_attach_mutex (mutex_timeout); + DWORD resume_pid = attach_console (con.owner); WriteConsoleW (get_output_handle (), L"\033[2K", 4, 0, 0); + detach_console (resume_pid, con.owner); release_attach_mutex (); break; } acquire_attach_mutex (mutex_timeout); + DWORD resume_pid = attach_console (con.owner); if (y == con.b.srWindow.Top && srBottom == con.b.srWindow.Bottom) { @@ -2556,8 +2747,8 @@ fhandler_console::char_command (char c) y + 1 - con.b.srWindow.Top, srBottom + 1 - con.b.srWindow.Top); WriteConsoleW (get_output_handle (), bufw, wcslen (bufw), 0, 0); - wpbuf.put ('T'); - wpbuf.send (); + wpbuf_put ('T'); + wpbuf_send (); __small_swprintf (bufw, L"\033[%d;%dr", srTop + 1 - con.b.srWindow.Top, srBottom + 1 - con.b.srWindow.Top); @@ -2565,13 +2756,14 @@ fhandler_console::char_command (char c) __small_swprintf (bufw, L"\033[%d;%dH", y + 1 - con.b.srWindow.Top, x + 1); WriteConsoleW (get_output_handle (), bufw, wcslen (bufw), 0, 0); + detach_console (resume_pid, con.owner); release_attach_mutex (); } else { - wpbuf.put (c); + wpbuf_put (c); /* Just send the sequence */ - wpbuf.send (); + wpbuf_send (); } break; case 'M': /* DL */ @@ -2584,7 +2776,9 @@ fhandler_console::char_command (char c) if (y == con.b.srWindow.Bottom) { acquire_attach_mutex (mutex_timeout); + DWORD resume_pid = attach_console (con.owner); WriteConsoleW (get_output_handle (), L"\033[2K", 4, 0, 0); + detach_console (resume_pid, con.owner); release_attach_mutex (); break; } @@ -2592,9 +2786,10 @@ fhandler_console::char_command (char c) y + 1 - con.b.srWindow.Top, srBottom + 1 - con.b.srWindow.Top); acquire_attach_mutex (mutex_timeout); + DWORD resume_pid = attach_console (con.owner); WriteConsoleW (get_output_handle (), bufw, wcslen (bufw), 0, 0); - wpbuf.put ('S'); - wpbuf.send (); + wpbuf_put ('S'); + wpbuf_send (); __small_swprintf (bufw, L"\033[%d;%dr", srTop + 1 - con.b.srWindow.Top, srBottom + 1 - con.b.srWindow.Top); @@ -2602,17 +2797,18 @@ fhandler_console::char_command (char c) __small_swprintf (bufw, L"\033[%d;%dH", y + 1 - con.b.srWindow.Top, x + 1); WriteConsoleW (get_output_handle (), bufw, wcslen (bufw), 0, 0); + detach_console (resume_pid, con.owner); release_attach_mutex (); } else { - wpbuf.put (c); + wpbuf_put (c); /* Just send the sequence */ - wpbuf.send (); + wpbuf_send (); } break; case 'J': /* ED */ - wpbuf.put (c); + wpbuf_put (c); if (con.args[0] == 3 && con.savey >= 0) { con.fillin (get_output_handle ()); @@ -2622,6 +2818,7 @@ fhandler_console::char_command (char c) { /* Workaround for broken CSI3J in Win10 1809 */ CONSOLE_SCREEN_BUFFER_INFO sbi; acquire_attach_mutex (mutex_timeout); + DWORD resume_pid = attach_console (con.owner); GetConsoleScreenBufferInfo (get_output_handle (), &sbi); SMALL_RECT r = {0, sbi.srWindow.Top, (SHORT) (sbi.dwSize.X - 1), (SHORT) (sbi.dwSize.Y - 1)}; @@ -2633,17 +2830,18 @@ fhandler_console::char_command (char c) d = sbi.dwCursorPosition; d.Y -= sbi.srWindow.Top; SetConsoleCursorPosition (get_output_handle (), d); + detach_console (resume_pid, con.owner); release_attach_mutex (); } else /* Just send the sequence */ - wpbuf.send (); + wpbuf_send (); break; case 'h': /* DECSET */ case 'l': /* DECRST */ - wpbuf.put (c); + wpbuf_put (c); /* Just send the sequence */ - wpbuf.send (); + wpbuf_send (); if (con.saw_question_mark) { bool need_fix_tab_position = false; @@ -2659,7 +2857,7 @@ fhandler_console::char_command (char c) } /* Call fix_tab_position() if screen has been alternated. */ if (need_fix_tab_position) - fix_tab_position (get_output_handle ()); + fix_tab_position (get_output_handle (), con.owner); } break; case 'p': @@ -2670,23 +2868,23 @@ fhandler_console::char_command (char c) con.savex = con.savey = -1; con.cursor_key_app_mode = false; } - wpbuf.put (c); + wpbuf_put (c); /* Just send the sequence */ - wpbuf.send (); + wpbuf_send (); break; case 'm': if (con.saw_greater_than_sign) break; /* Ignore unsupported CSI > Pm m */ /* Text attribute settings */ - wpbuf.put (c); + wpbuf_put (c); /* Just send the sequence */ - wpbuf.send (); + wpbuf_send (); break; default: /* Other escape sequences */ - wpbuf.put (c); + wpbuf_put (c); /* Just send the sequence */ - wpbuf.send (); + wpbuf_send (); break; } return; @@ -2871,6 +3069,7 @@ fhandler_console::char_command (char c) { CONSOLE_CURSOR_INFO console_cursor_info; acquire_attach_mutex (mutex_timeout); + DWORD resume_pid = attach_console (con.owner); GetConsoleCursorInfo (get_output_handle (), &console_cursor_info); switch (con.args[0]) { @@ -2893,6 +3092,7 @@ fhandler_console::char_command (char c) &console_cursor_info); break; } + detach_console (resume_pid, con.owner); release_attach_mutex (); } break; @@ -2916,12 +3116,14 @@ fhandler_console::char_command (char c) { CONSOLE_CURSOR_INFO console_cursor_info; acquire_attach_mutex (mutex_timeout); + DWORD resume_pid = attach_console (con.owner); GetConsoleCursorInfo (get_output_handle (), & console_cursor_info); if (c == 'h') console_cursor_info.bVisible = TRUE; else console_cursor_info.bVisible = FALSE; SetConsoleCursorInfo (get_output_handle (), & console_cursor_info); + detach_console (resume_pid, con.owner); release_attach_mutex (); break; } @@ -3168,14 +3370,16 @@ enum_proc (const LOGFONTW *lf, const TEXTMETRICW *tm, } static void -check_font (HANDLE hdl) +check_font (HANDLE hdl, pid_t owner) { CONSOLE_FONT_INFOEX cfi; LOGFONTW lf; cfi.cbSize = sizeof cfi; acquire_attach_mutex (mutex_timeout); + DWORD resume_pid = fhandler_console::attach_console (owner); BOOL r = GetCurrentConsoleFontEx (hdl, 0, &cfi); + fhandler_console::detach_console (resume_pid, owner); release_attach_mutex (); if (!r) return; @@ -3246,11 +3450,13 @@ check_font (HANDLE hdl) inline void fhandler_console::write_replacement_char () { - check_font (get_output_handle ()); + check_font (get_output_handle (), unit); DWORD done; acquire_attach_mutex (mutex_timeout); + DWORD resume_pid = attach_console (con.owner); WriteConsoleW (get_output_handle (), &rp_char, 1, &done, 0); + detach_console (resume_pid, con.owner); release_attach_mutex (); } @@ -3401,7 +3607,7 @@ do_print: break; case ESC: con.state = gotesc; - wpbuf.put (*found); + wpbuf_put (*found); break; case DWN: cursor_get (&x, &y); @@ -3410,7 +3616,9 @@ do_print: if (y >= con.b.srWindow.Bottom && !con.scroll_region.Top) { acquire_attach_mutex (mutex_timeout); + DWORD resume_pid = attach_console (con.owner); WriteConsoleW (get_output_handle (), L"\n", 1, &done, 0); + detach_console (resume_pid, con.owner); release_attach_mutex (); } else @@ -3448,12 +3656,14 @@ do_print: if (ret != -1) { acquire_attach_mutex (mutex_timeout); + DWORD resume_pid = attach_console (con.owner); while (ret-- > 0) { WCHAR w = *(found + 1); WriteConsoleW (get_output_handle (), &w, 1, &done, 0); found++; } + detach_console (resume_pid, con.owner); release_attach_mutex (); } } @@ -3521,7 +3731,7 @@ fhandler_console::write (const void *vsrc, size_t len) case gotesc: if (*src == '[') /* CSI Control Sequence Introducer */ { - wpbuf.put (*src); + wpbuf_put (*src); con.state = gotsquare; memset (con.args, 0, sizeof con.args); con.nargs = 0; @@ -3536,8 +3746,8 @@ fhandler_console::write (const void *vsrc, size_t len) { /* For xterm mode only */ /* Just send the sequence */ - wpbuf.put (*src); - wpbuf.send (); + wpbuf_put (*src); + wpbuf_send (); } else if (con.savex >= 0 && con.savey >= 0) cursor_set (false, con.savex, con.savey); @@ -3550,8 +3760,8 @@ fhandler_console::write (const void *vsrc, size_t len) { /* For xterm mode only */ /* Just send the sequence */ - wpbuf.put (*src); - wpbuf.send (); + wpbuf_put (*src); + wpbuf_send (); } else cursor_get (&con.savex, &con.savey); @@ -3574,23 +3784,25 @@ fhandler_console::write (const void *vsrc, size_t len) srBottom - con.b.srWindow.Top + 1, y + 1 - con.b.srWindow.Top, x + 1); acquire_attach_mutex (mutex_timeout); + DWORD resume_pid = attach_console (con.owner); WriteConsoleW (get_output_handle (), buf, wcslen (buf), 0, 0); + detach_console (resume_pid, con.owner); release_attach_mutex (); } /* Substitute "CSI Ps T" */ - wpbuf.put ('['); - wpbuf.put ('T'); + wpbuf_put ('['); + wpbuf_put ('T'); } else - wpbuf.put (*src); - wpbuf.send (); + wpbuf_put (*src); + wpbuf_send (); con.state = normal; wpbuf.empty(); } else if (*src == ']') /* OSC Operating System Command */ { - wpbuf.put (*src); + wpbuf_put (*src); con.rarg = 0; con.my_title_buf[0] = '\0'; con.state = gotrsquare; @@ -3607,20 +3819,20 @@ fhandler_console::write (const void *vsrc, size_t len) /* ESC sequences below (e.g. OSC, etc) are left to xterm emulation in xterm compatible mode, therefore, are not handled and just sent them. */ - wpbuf.put (*src); + wpbuf_put (*src); /* Just send the sequence */ - wpbuf.send (); + wpbuf_send (); con.state = normal; wpbuf.empty(); } else if (*src == '(') /* Designate G0 character set */ { - wpbuf.put (*src); + wpbuf_put (*src); con.state = gotparen; } else if (*src == ')') /* Designate G1 character set */ { - wpbuf.put (*src); + wpbuf_put (*src); con.state = gotrparen; } else if (*src == 'M') /* Reverse Index (scroll down) */ @@ -3658,19 +3870,19 @@ fhandler_console::write (const void *vsrc, size_t len) { if (con.nargs < MAXARGS) con.args[con.nargs] = con.args[con.nargs] * 10 + *src - '0'; - wpbuf.put (*src); + wpbuf_put (*src); src++; } else if (*src == ';') { - wpbuf.put (*src); + wpbuf_put (*src); src++; if (con.nargs < MAXARGS) con.nargs++; } else if (*src == ' ') { - wpbuf.put (*src); + wpbuf_put (*src); src++; con.saw_space = true; con.state = gotcommand; @@ -3704,26 +3916,26 @@ fhandler_console::write (const void *vsrc, size_t len) con.state = endpalette; else if (*src == '\007') { - wpbuf.put (*src); + wpbuf_put (*src); if (wincap.has_con_24bit_colors () && !con_is_legacy) - wpbuf.send (); + wpbuf_send (); wpbuf.empty (); con.state = normal; src++; break; } - wpbuf.put (*src); + wpbuf_put (*src); src++; break; case eattitle: case gettitle: { - wpbuf.put (*src); + wpbuf_put (*src); int n = strlen (con.my_title_buf); if (*src < ' ') { if (wincap.has_con_24bit_colors () && !con_is_legacy) - wpbuf.send (); + wpbuf_send (); else if (*src == '\007' && con.state == gettitle) set_console_title (con.my_title_buf); con.state = normal; @@ -3738,7 +3950,7 @@ fhandler_console::write (const void *vsrc, size_t len) break; } case eatpalette: - wpbuf.put (*src); + wpbuf_put (*src); if (*src == '?') con.saw_question_mark = true; else if (*src == '\033') @@ -3748,20 +3960,20 @@ fhandler_console::write (const void *vsrc, size_t len) /* Send OSC Ps; Pt BEL other than OSC Ps; ? BEL */ if (wincap.has_con_24bit_colors () && !con_is_legacy && !con.saw_question_mark) - wpbuf.send (); + wpbuf_send (); con.state = normal; wpbuf.empty(); } src++; break; case endpalette: - wpbuf.put (*src); + wpbuf_put (*src); if (*src == '\\') { /* Send OSC Ps; Pt ST other than OSC Ps; ? ST */ if (wincap.has_con_24bit_colors () && !con_is_legacy && !con.saw_question_mark) - wpbuf.send (); + wpbuf_send (); con.state = normal; } else @@ -3774,7 +3986,7 @@ fhandler_console::write (const void *vsrc, size_t len) if (*src == ';') { con.state = gotarg1; - wpbuf.put (*src); + wpbuf_put (*src); if (con.nargs < MAXARGS) con.nargs++; src++; @@ -3789,7 +4001,7 @@ fhandler_console::write (const void *vsrc, size_t len) con.saw_greater_than_sign = true; else if (*src == '!') con.saw_exclamation_mark = true; - wpbuf.put (*src); + wpbuf_put (*src); /* ignore any extra chars between [ and first arg or command */ src++; } @@ -3940,13 +4152,15 @@ fhandler_console::set_close_on_exec (bool val) } void -set_console_title (char *title) +fhandler_console::set_console_title (char *title) { wchar_t buf[TITLESIZE + 1]; sys_mbstowcs (buf, TITLESIZE + 1, title); lock_ttys here (15000); acquire_attach_mutex (mutex_timeout); + DWORD resume_pid = attach_console (con.owner); SetConsoleTitleW (buf); + detach_console (resume_pid, con.owner); release_attach_mutex (); debug_printf ("title '%W'", buf); } @@ -4035,7 +4249,7 @@ fhandler_console::fixup_after_fork_exec (bool execing) { set_unit (); setup_io_mutex (); - wpbuf.init (get_output_handle ()); + wpbuf.init (); if (!execing) return; @@ -4285,6 +4499,7 @@ fhandler_console::get_duplicated_handle_set (handle_set_t *p) DuplicateHandle (GetCurrentProcess (), output_mutex, GetCurrentProcess (), &p->output_mutex, 0, FALSE, DUPLICATE_SAME_ACCESS); + p->unit = unit; } /* The function close_handle_set() should be static so that they can @@ -4311,6 +4526,7 @@ fhandler_console::need_console_handler () void fhandler_console::set_disable_master_thread (bool x, fhandler_console *cons) { + const _minor_t unit = cons->get_minor (); if (con.disable_master_thread == x) return; if (cons == NULL) @@ -4324,3 +4540,17 @@ fhandler_console::set_disable_master_thread (bool x, fhandler_console *cons) con.disable_master_thread = x; cons->release_input_mutex (); } + +int +fhandler_console::fstat (struct stat *st) +{ + fhandler_base::fstat (st); + st->st_mode = S_IFCHR | S_IRUSR | S_IWUSR; + pinfo p (get_ttyp ()->getsid ()); + if (p) + { + st->st_uid = p->uid; + st->st_gid = p->gid; + } + return 0; +} diff --git a/winsup/cygwin/fhandler/pty.cc b/winsup/cygwin/fhandler/pty.cc index c9b05e3d7..718709580 100644 --- a/winsup/cygwin/fhandler/pty.cc +++ b/winsup/cygwin/fhandler/pty.cc @@ -58,7 +58,7 @@ struct pipe_reply { DWORD error; }; -HANDLE attach_mutex; +HANDLE NO_COPY attach_mutex; DWORD acquire_attach_mutex (DWORD t) { @@ -2993,7 +2993,7 @@ fhandler_pty_master::setup () goto err; if (!attach_mutex) - attach_mutex = CreateMutex (&sa, FALSE, NULL); + attach_mutex = CreateMutex (&sec_none_nih, FALSE, NULL); /* Create master control pipe which allows the master to duplicate the pty pipe handles to processes which deserve it. */ diff --git a/winsup/cygwin/local_includes/fhandler.h b/winsup/cygwin/local_includes/fhandler.h index 8c320421b..8406dff64 100644 --- a/winsup/cygwin/local_includes/fhandler.h +++ b/winsup/cygwin/local_includes/fhandler.h @@ -2001,6 +2001,7 @@ class fhandler_termios: public fhandler_base HANDLE output_handle; HANDLE input_mutex; HANDLE output_mutex; + _minor_t unit; }; class spawn_worker { @@ -2147,6 +2148,8 @@ class dev_console friend class fhandler_console; }; +#define MAX_CONS_DEV (sizeof (unsigned long) * 8) + /* This is a input and output console handle */ class fhandler_console: public fhandler_termios { @@ -2169,10 +2172,11 @@ public: HANDLE thread_sync_event; private: static const unsigned MAX_WRITE_CHARS; - static console_state *shared_console_info; + static console_state *shared_console_info[MAX_CONS_DEV + 1]; static bool invisible_console; HANDLE input_mutex, output_mutex; handle_set_t handle_set; + _minor_t unit; /* Used when we encounter a truncated multi-byte sequence. The lead bytes are stored here and revisited in the next write call. */ @@ -2196,13 +2200,14 @@ private: const unsigned char *write_normal (unsigned const char*, unsigned const char *); void char_command (char); bool set_raw_win32_keyboard_mode (bool); + void set_console_title (char *); /* Input calls */ int igncr_enabled (); void set_cursor_maybe (); static bool create_invisible_console_workaround (bool force); static console_state *open_shared_console (HWND, HANDLE&, bool&); - static void fix_tab_position (HANDLE h); + static void fix_tab_position (HANDLE h, pid_t owner); /* console mode calls */ const handle_set_t *get_handle_set (void) {return &handle_set;} @@ -2214,8 +2219,8 @@ private: public: pid_t tc_getpgid () { - return shared_console_info ? - shared_console_info->tty_min_state.getpgid () : 0; + return shared_console_info[unit] ? + shared_console_info[unit]->tty_min_state.getpgid () : 0; } fhandler_console (fh_devices); static console_state *open_shared_console (HWND hw, HANDLE& h) @@ -2252,12 +2257,12 @@ private: int ioctl (unsigned int cmd, void *); int init (HANDLE, DWORD, mode_t); bool mouse_aware (MOUSE_EVENT_RECORD& mouse_event); - bool focus_aware () {return shared_console_info->con.use_focus;} + bool focus_aware () {return shared_console_info[unit]->con.use_focus;} bool get_cons_readahead_valid () { acquire_input_mutex (INFINITE); - bool ret = shared_console_info->con.cons_rapoi != NULL && - *shared_console_info->con.cons_rapoi; + bool ret = shared_console_info[unit]->con.cons_rapoi != NULL && + *shared_console_info[unit]->con.cons_rapoi; release_input_mutex (); return ret; } @@ -2302,11 +2307,9 @@ private: void acquire_input_mutex_if_necessary (DWORD ms) { acquire_input_mutex (ms); - acquire_attach_mutex (ms); } void release_input_mutex_if_necessary (void) { - release_attach_mutex (); release_input_mutex (); } @@ -2325,6 +2328,12 @@ private: static void set_console_mode_to_native (); bool need_console_handler (); static void set_disable_master_thread (bool x, fhandler_console *cons = NULL); + static DWORD attach_console (pid_t, bool *err = NULL); + static void detach_console (DWORD, pid_t); + pid_t get_owner (); + void wpbuf_put (char c); + void wpbuf_send (); + int fstat (struct stat *buf); friend tty_min * tty_list::get_cttyp (); }; diff --git a/winsup/cygwin/local_includes/winsup.h b/winsup/cygwin/local_includes/winsup.h index 44c7f08f8..c54440fa8 100644 --- a/winsup/cygwin/local_includes/winsup.h +++ b/winsup/cygwin/local_includes/winsup.h @@ -202,7 +202,6 @@ void timespec_to_filetime (const struct timespec *, PLARGE_INTEGER); bool timeval_to_ms (const struct timeval *, DWORD &); /* Console related */ -void set_console_title (char *); void init_console_handler (bool); extern bool wsock_started; diff --git a/winsup/cygwin/select.cc b/winsup/cygwin/select.cc index 2fd7b72b6..bad4c37f3 100644 --- a/winsup/cygwin/select.cc +++ b/winsup/cygwin/select.cc @@ -1141,7 +1141,9 @@ peek_console (select_record *me, bool) else { acquire_attach_mutex (mutex_timeout); + DWORD resume_pid = fh->attach_console (fh->get_owner ()); BOOL r = PeekConsoleInputW (h, &irec, 1, &events_read); + fh->detach_console (resume_pid, fh->get_owner ()); release_attach_mutex (); if (!r || !events_read) break;