Cygwin: console: Make the console accessible from other terminals.

Previously, the console device could not be accessed from other terminals.
Due to this limitation, GNU screen and tmux cannot be opened in console.
With this patch, console device can be accessed from other TTYs, such as
other consoles or ptys. Thanks to this patch, screen and tmux get working
in console.

Reviewed-by: Corinna Vinschen <corinna@vinschen.de>
Signed-off-by: Takashi Yano <takashi.yano@nifty.ne.jp>
This commit is contained in:
Takashi Yano 2022-12-22 21:05:31 +09:00
parent 043b6089e2
commit 3721a756b0
7 changed files with 418 additions and 138 deletions

View File

@ -69,6 +69,21 @@ exists_ntdev_silent (const device& dev)
return exists_ntdev (dev) ? -1 : false; 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 static int
exists_console (const device& dev) exists_console (const device& dev)
{ {
@ -81,8 +96,13 @@ exists_console (const device& dev)
return cygheap && cygheap->ctty && cygheap->ctty->is_console () return cygheap && cygheap->ctty && cygheap->ctty->is_console ()
&& fhandler_console::exists (); && fhandler_console::exists ();
default: default:
/* Only show my own console device (for now?) */ if (dev.get_minor () < MAX_CONS_DEV)
return iscons_dev (myself->ctty) && myself->ctty == devn; {
unsigned long bitmask = 0;
EnumWindows (enum_cons_dev, (LPARAM) &bitmask);
return bitmask & (1UL << dev.get_minor ());
}
return false;
} }
} }

View File

@ -65,6 +65,21 @@ exists_ntdev_silent (const device& dev)
return exists_ntdev (dev) ? -1 : false; 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 static int
exists_console (const device& dev) exists_console (const device& dev)
{ {
@ -77,8 +92,13 @@ exists_console (const device& dev)
return cygheap && cygheap->ctty && cygheap->ctty->is_console () return cygheap && cygheap->ctty && cygheap->ctty->is_console ()
&& fhandler_console::exists (); && fhandler_console::exists ();
default: default:
/* Only show my own console device (for now?) */ if (dev.get_minor () < MAX_CONS_DEV)
return iscons_dev (myself->ctty) && myself->ctty == devn; {
unsigned long bitmask = 0;
EnumWindows (enum_cons_dev, (LPARAM) &bitmask);
return bitmask & (1UL << dev.get_minor ());
}
return false;
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -58,7 +58,7 @@ struct pipe_reply {
DWORD error; DWORD error;
}; };
HANDLE attach_mutex; HANDLE NO_COPY attach_mutex;
DWORD acquire_attach_mutex (DWORD t) DWORD acquire_attach_mutex (DWORD t)
{ {
@ -2993,7 +2993,7 @@ fhandler_pty_master::setup ()
goto err; goto err;
if (!attach_mutex) 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 /* Create master control pipe which allows the master to duplicate
the pty pipe handles to processes which deserve it. */ the pty pipe handles to processes which deserve it. */

View File

@ -2001,6 +2001,7 @@ class fhandler_termios: public fhandler_base
HANDLE output_handle; HANDLE output_handle;
HANDLE input_mutex; HANDLE input_mutex;
HANDLE output_mutex; HANDLE output_mutex;
_minor_t unit;
}; };
class spawn_worker class spawn_worker
{ {
@ -2147,6 +2148,8 @@ class dev_console
friend class fhandler_console; friend class fhandler_console;
}; };
#define MAX_CONS_DEV (sizeof (unsigned long) * 8)
/* This is a input and output console handle */ /* This is a input and output console handle */
class fhandler_console: public fhandler_termios class fhandler_console: public fhandler_termios
{ {
@ -2169,10 +2172,11 @@ public:
HANDLE thread_sync_event; HANDLE thread_sync_event;
private: private:
static const unsigned MAX_WRITE_CHARS; 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; static bool invisible_console;
HANDLE input_mutex, output_mutex; HANDLE input_mutex, output_mutex;
handle_set_t handle_set; handle_set_t handle_set;
_minor_t unit;
/* Used when we encounter a truncated multi-byte sequence. The /* Used when we encounter a truncated multi-byte sequence. The
lead bytes are stored here and revisited in the next write call. */ 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 *); const unsigned char *write_normal (unsigned const char*, unsigned const char *);
void char_command (char); void char_command (char);
bool set_raw_win32_keyboard_mode (bool); bool set_raw_win32_keyboard_mode (bool);
void set_console_title (char *);
/* Input calls */ /* Input calls */
int igncr_enabled (); int igncr_enabled ();
void set_cursor_maybe (); void set_cursor_maybe ();
static bool create_invisible_console_workaround (bool force); static bool create_invisible_console_workaround (bool force);
static console_state *open_shared_console (HWND, HANDLE&, bool&); 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 */ /* console mode calls */
const handle_set_t *get_handle_set (void) {return &handle_set;} const handle_set_t *get_handle_set (void) {return &handle_set;}
@ -2214,8 +2219,8 @@ private:
public: public:
pid_t tc_getpgid () pid_t tc_getpgid ()
{ {
return shared_console_info ? return shared_console_info[unit] ?
shared_console_info->tty_min_state.getpgid () : 0; shared_console_info[unit]->tty_min_state.getpgid () : 0;
} }
fhandler_console (fh_devices); fhandler_console (fh_devices);
static console_state *open_shared_console (HWND hw, HANDLE& h) static console_state *open_shared_console (HWND hw, HANDLE& h)
@ -2252,12 +2257,12 @@ private:
int ioctl (unsigned int cmd, void *); int ioctl (unsigned int cmd, void *);
int init (HANDLE, DWORD, mode_t); int init (HANDLE, DWORD, mode_t);
bool mouse_aware (MOUSE_EVENT_RECORD& mouse_event); 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 () bool get_cons_readahead_valid ()
{ {
acquire_input_mutex (INFINITE); acquire_input_mutex (INFINITE);
bool ret = shared_console_info->con.cons_rapoi != NULL && bool ret = shared_console_info[unit]->con.cons_rapoi != NULL &&
*shared_console_info->con.cons_rapoi; *shared_console_info[unit]->con.cons_rapoi;
release_input_mutex (); release_input_mutex ();
return ret; return ret;
} }
@ -2302,11 +2307,9 @@ private:
void acquire_input_mutex_if_necessary (DWORD ms) void acquire_input_mutex_if_necessary (DWORD ms)
{ {
acquire_input_mutex (ms); acquire_input_mutex (ms);
acquire_attach_mutex (ms);
} }
void release_input_mutex_if_necessary (void) void release_input_mutex_if_necessary (void)
{ {
release_attach_mutex ();
release_input_mutex (); release_input_mutex ();
} }
@ -2325,6 +2328,12 @@ private:
static void set_console_mode_to_native (); static void set_console_mode_to_native ();
bool need_console_handler (); bool need_console_handler ();
static void set_disable_master_thread (bool x, fhandler_console *cons = NULL); 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 (); friend tty_min * tty_list::get_cttyp ();
}; };

View File

@ -202,7 +202,6 @@ void timespec_to_filetime (const struct timespec *, PLARGE_INTEGER);
bool timeval_to_ms (const struct timeval *, DWORD &); bool timeval_to_ms (const struct timeval *, DWORD &);
/* Console related */ /* Console related */
void set_console_title (char *);
void init_console_handler (bool); void init_console_handler (bool);
extern bool wsock_started; extern bool wsock_started;

View File

@ -1141,7 +1141,9 @@ peek_console (select_record *me, bool)
else else
{ {
acquire_attach_mutex (mutex_timeout); acquire_attach_mutex (mutex_timeout);
DWORD resume_pid = fh->attach_console (fh->get_owner ());
BOOL r = PeekConsoleInputW (h, &irec, 1, &events_read); BOOL r = PeekConsoleInputW (h, &irec, 1, &events_read);
fh->detach_console (resume_pid, fh->get_owner ());
release_attach_mutex (); release_attach_mutex ();
if (!r || !events_read) if (!r || !events_read)
break; break;