Cygwin: pty, console: Refactor the code processing special keys.
- This patch commonize the code which processes special keys in pty and console to improve maintanancibility. As a result, some small bugs have been fixed.
This commit is contained in:
parent
416792d59a
commit
2cab4d0bb4
|
@ -422,6 +422,7 @@ dtable::init_std_file_from_handle (int fd, HANDLE handle)
|
||||||
cygheap->fdtab[fd]->inc_refcnt ();
|
cygheap->fdtab[fd]->inc_refcnt ();
|
||||||
set_std_handle (fd);
|
set_std_handle (fd);
|
||||||
paranoid_printf ("fd %d, handle %p", fd, handle);
|
paranoid_printf ("fd %d, handle %p", fd, handle);
|
||||||
|
fh->post_open_setup (fd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1147,6 +1147,19 @@ ctrl_c_handler (DWORD type)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
tty_min *t = cygwin_shared->tty.get_cttyp ();
|
tty_min *t = cygwin_shared->tty.get_cttyp ();
|
||||||
|
|
||||||
|
/* If process group leader is non-cygwin process or not exist,
|
||||||
|
send signal to myself. */
|
||||||
|
pinfo pi (t->getpgid ());
|
||||||
|
if ((!pi || (pi->process_state & PID_NOTCYGWIN))
|
||||||
|
&& (!have_execed || have_execed_cygwin)
|
||||||
|
&& t->getpgid () == myself->pgid
|
||||||
|
&& type == CTRL_C_EVENT)
|
||||||
|
{
|
||||||
|
t->output_stopped = false;
|
||||||
|
sig_send(myself, SIGINT);
|
||||||
|
}
|
||||||
|
|
||||||
/* Ignore this if we're not the process group leader since it should be
|
/* Ignore this if we're not the process group leader since it should be
|
||||||
handled *by* the process group leader. */
|
handled *by* the process group leader. */
|
||||||
if (t && (!have_execed || have_execed_cygwin)
|
if (t && (!have_execed || have_execed_cygwin)
|
||||||
|
@ -1556,6 +1569,8 @@ dosig:
|
||||||
if (have_execed)
|
if (have_execed)
|
||||||
{
|
{
|
||||||
sigproc_printf ("terminating captive process");
|
sigproc_printf ("terminating captive process");
|
||||||
|
if (::cygheap->ctty)
|
||||||
|
::cygheap->ctty->cleanup_before_exit ();
|
||||||
TerminateProcess (ch_spawn, sigExeced = si.si_signo);
|
TerminateProcess (ch_spawn, sigExeced = si.si_signo);
|
||||||
}
|
}
|
||||||
/* Dispatch to the appropriate function. */
|
/* Dispatch to the appropriate function. */
|
||||||
|
|
|
@ -356,6 +356,7 @@ class fhandler_base
|
||||||
virtual int open (int, mode_t);
|
virtual int open (int, mode_t);
|
||||||
virtual fhandler_base *fd_reopen (int, mode_t);
|
virtual fhandler_base *fd_reopen (int, mode_t);
|
||||||
virtual bool open_setup (int flags);
|
virtual bool open_setup (int flags);
|
||||||
|
virtual void post_open_setup (int fd) {}
|
||||||
void set_unique_id (int64_t u) { unique_id = u; }
|
void set_unique_id (int64_t u) { unique_id = u; }
|
||||||
void set_unique_id () { NtAllocateLocallyUniqueId ((PLUID) &unique_id); }
|
void set_unique_id () { NtAllocateLocallyUniqueId ((PLUID) &unique_id); }
|
||||||
|
|
||||||
|
@ -1901,6 +1902,13 @@ class fhandler_termios: public fhandler_base
|
||||||
virtual void release_input_mutex_if_necessary (void) {};
|
virtual void release_input_mutex_if_necessary (void) {};
|
||||||
virtual void discard_input () {};
|
virtual void discard_input () {};
|
||||||
|
|
||||||
|
enum process_sig_state {
|
||||||
|
signalled,
|
||||||
|
not_signalled,
|
||||||
|
not_signalled_but_done,
|
||||||
|
not_signalled_with_cyg_reader
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
tty_min*& tc () {return _tc;}
|
tty_min*& tc () {return _tc;}
|
||||||
fhandler_termios () :
|
fhandler_termios () :
|
||||||
|
@ -1910,6 +1918,9 @@ class fhandler_termios: public fhandler_base
|
||||||
}
|
}
|
||||||
HANDLE& get_output_handle () { return output_handle; }
|
HANDLE& get_output_handle () { return output_handle; }
|
||||||
HANDLE& get_output_handle_nat () { return output_handle; }
|
HANDLE& get_output_handle_nat () { return output_handle; }
|
||||||
|
static process_sig_state process_sigs (char c, tty *ttyp,
|
||||||
|
fhandler_termios *fh);
|
||||||
|
static bool process_stop_start (char c, tty *ttyp, bool on_ixany);
|
||||||
line_edit_status line_edit (const char *rptr, size_t nread, termios&,
|
line_edit_status line_edit (const char *rptr, size_t nread, termios&,
|
||||||
ssize_t *bytes_read = NULL);
|
ssize_t *bytes_read = NULL);
|
||||||
void set_output_handle (HANDLE h) { output_handle = h; }
|
void set_output_handle (HANDLE h) { output_handle = h; }
|
||||||
|
@ -1943,6 +1954,8 @@ class fhandler_termios: public fhandler_base
|
||||||
}
|
}
|
||||||
static bool path_iscygexec_a (LPCSTR n, LPSTR c);
|
static bool path_iscygexec_a (LPCSTR n, LPSTR c);
|
||||||
static bool path_iscygexec_w (LPCWSTR n, LPWSTR c);
|
static bool path_iscygexec_w (LPCWSTR n, LPWSTR c);
|
||||||
|
virtual bool is_pty_master_with_pcon () { return false; }
|
||||||
|
virtual void cleanup_before_exit () {}
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ansi_intensity
|
enum ansi_intensity
|
||||||
|
@ -2047,7 +2060,6 @@ class dev_console
|
||||||
char cons_rabuf[40]; // cannot get longer than char buf[40] in char_command
|
char cons_rabuf[40]; // cannot get longer than char buf[40] in char_command
|
||||||
char *cons_rapoi;
|
char *cons_rapoi;
|
||||||
bool cursor_key_app_mode;
|
bool cursor_key_app_mode;
|
||||||
bool disable_master_thread;
|
|
||||||
|
|
||||||
inline UINT get_console_cp ();
|
inline UINT get_console_cp ();
|
||||||
DWORD con_to_str (char *d, int dlen, WCHAR w);
|
DWORD con_to_str (char *d, int dlen, WCHAR w);
|
||||||
|
@ -2146,6 +2158,7 @@ private:
|
||||||
|
|
||||||
int open (int flags, mode_t mode);
|
int open (int flags, mode_t mode);
|
||||||
bool open_setup (int flags);
|
bool open_setup (int flags);
|
||||||
|
void post_open_setup (int fd);
|
||||||
int dup (fhandler_base *, int);
|
int dup (fhandler_base *, int);
|
||||||
|
|
||||||
void __reg3 read (void *ptr, size_t& len);
|
void __reg3 read (void *ptr, size_t& len);
|
||||||
|
@ -2369,6 +2382,7 @@ class fhandler_pty_slave: public fhandler_pty_common
|
||||||
HANDLE input_available_event);
|
HANDLE input_available_event);
|
||||||
HANDLE get_input_available_event (void) { return input_available_event; }
|
HANDLE get_input_available_event (void) { return input_available_event; }
|
||||||
bool pcon_activated (void) { return get_ttyp ()->pcon_activated; }
|
bool pcon_activated (void) { return get_ttyp ()->pcon_activated; }
|
||||||
|
void cleanup_before_exit ();
|
||||||
};
|
};
|
||||||
|
|
||||||
#define __ptsname(buf, unit) __small_sprintf ((buf), "/dev/pty%d", (unit))
|
#define __ptsname(buf, unit) __small_sprintf ((buf), "/dev/pty%d", (unit))
|
||||||
|
@ -2456,6 +2470,7 @@ public:
|
||||||
void get_master_thread_param (master_thread_param_t *p);
|
void get_master_thread_param (master_thread_param_t *p);
|
||||||
void get_master_fwd_thread_param (master_fwd_thread_param_t *p);
|
void get_master_fwd_thread_param (master_fwd_thread_param_t *p);
|
||||||
void set_mask_flusho (bool m) { get_ttyp ()->mask_flusho = m; }
|
void set_mask_flusho (bool m) { get_ttyp ()->mask_flusho = m; }
|
||||||
|
bool is_pty_master_with_pcon () { return get_ttyp ()->pcon_activated; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class fhandler_dev_null: public fhandler_base
|
class fhandler_dev_null: public fhandler_base
|
||||||
|
|
|
@ -188,13 +188,28 @@ cons_master_thread (VOID *arg)
|
||||||
void
|
void
|
||||||
fhandler_console::cons_master_thread (handle_set_t *p, tty *ttyp)
|
fhandler_console::cons_master_thread (handle_set_t *p, tty *ttyp)
|
||||||
{
|
{
|
||||||
|
termios &ti = ttyp->ti;
|
||||||
DWORD output_stopped_at = 0;
|
DWORD output_stopped_at = 0;
|
||||||
while (con.owner == myself->pid)
|
while (con.owner == myself->pid)
|
||||||
{
|
{
|
||||||
DWORD total_read, n, i;
|
DWORD total_read, n, i;
|
||||||
INPUT_RECORD input_rec[INREC_SIZE];
|
INPUT_RECORD input_rec[INREC_SIZE];
|
||||||
|
|
||||||
if (con.disable_master_thread)
|
bool nat_fg = false;
|
||||||
|
bool nat_child_fg = false;
|
||||||
|
winpids pids ((DWORD) 0);
|
||||||
|
for (unsigned i = 0; i < pids.npids; i++)
|
||||||
|
{
|
||||||
|
_pinfo *pi = pids[i];
|
||||||
|
if (pi && pi->ctty == ttyp->ntty && pi->pgid == ttyp->getpgid ()
|
||||||
|
&& (pi->process_state & PID_NOTCYGWIN)
|
||||||
|
&& !(pi->process_state & PID_NEW_PG))
|
||||||
|
nat_fg = true;
|
||||||
|
if (pi && pi->ctty == ttyp->ntty && pi->pgid == ttyp->getpgid ()
|
||||||
|
&& !(pi->process_state & PID_CYGPARENT))
|
||||||
|
nat_child_fg = true;
|
||||||
|
}
|
||||||
|
if (nat_fg && !nat_child_fg)
|
||||||
{
|
{
|
||||||
cygwait (40);
|
cygwait (40);
|
||||||
continue;
|
continue;
|
||||||
|
@ -233,90 +248,35 @@ fhandler_console::cons_master_thread (handle_set_t *p, tty *ttyp)
|
||||||
}
|
}
|
||||||
for (i = 0; i < total_read; i++)
|
for (i = 0; i < total_read; i++)
|
||||||
{
|
{
|
||||||
const wchar_t wc = input_rec[i].Event.KeyEvent.uChar.UnicodeChar;
|
wchar_t wc;
|
||||||
if ((wint_t) wc >= 0x80)
|
char c;
|
||||||
continue;
|
bool was_output_stopped;
|
||||||
char c = (char) wc;
|
|
||||||
bool processed = false;
|
bool processed = false;
|
||||||
termios &ti = ttyp->ti;
|
|
||||||
pinfo pi (ttyp->getpgid ());
|
|
||||||
if (pi && pi->ctty == ttyp->ntty
|
|
||||||
&& (pi->process_state & PID_NOTCYGWIN)
|
|
||||||
&& input_rec[i].EventType == KEY_EVENT && c == '\003')
|
|
||||||
{
|
|
||||||
bool not_a_sig = false;
|
|
||||||
if (!CCEQ (ti.c_cc[VINTR], c)
|
|
||||||
&& !CCEQ (ti.c_cc[VQUIT], c)
|
|
||||||
&& !CCEQ (ti.c_cc[VSUSP], c))
|
|
||||||
not_a_sig = true;
|
|
||||||
if (input_rec[i].Event.KeyEvent.bKeyDown)
|
|
||||||
{
|
|
||||||
/* CTRL_C_EVENT does not work for the process started with
|
|
||||||
CREATE_NEW_PROCESS_GROUP flag, so send CTRL_BREAK_EVENT
|
|
||||||
instead. */
|
|
||||||
if (pi->process_state & PID_NEW_PG)
|
|
||||||
GenerateConsoleCtrlEvent (CTRL_BREAK_EVENT,
|
|
||||||
pi->dwProcessId);
|
|
||||||
else
|
|
||||||
GenerateConsoleCtrlEvent (CTRL_C_EVENT, 0);
|
|
||||||
if (not_a_sig)
|
|
||||||
goto skip_writeback;
|
|
||||||
}
|
|
||||||
processed = true;
|
|
||||||
if (not_a_sig)
|
|
||||||
goto remove_record;
|
|
||||||
}
|
|
||||||
switch (input_rec[i].EventType)
|
switch (input_rec[i].EventType)
|
||||||
{
|
{
|
||||||
case KEY_EVENT:
|
case KEY_EVENT:
|
||||||
if (ti.c_lflag & ISIG)
|
if (!input_rec[i].Event.KeyEvent.bKeyDown)
|
||||||
|
continue;
|
||||||
|
wc = input_rec[i].Event.KeyEvent.uChar.UnicodeChar;
|
||||||
|
if (!wc || (wint_t) wc >= 0x80)
|
||||||
|
continue;
|
||||||
|
c = (char) wc;
|
||||||
|
switch (process_sigs (c, ttyp, NULL))
|
||||||
{
|
{
|
||||||
int sig = 0;
|
case signalled:
|
||||||
if (CCEQ (ti.c_cc[VINTR], c))
|
case not_signalled_but_done:
|
||||||
sig = SIGINT;
|
|
||||||
else if (CCEQ (ti.c_cc[VQUIT], c))
|
|
||||||
sig = SIGQUIT;
|
|
||||||
else if (CCEQ (ti.c_cc[VSUSP], c))
|
|
||||||
sig = SIGTSTP;
|
|
||||||
if (sig && input_rec[i].Event.KeyEvent.bKeyDown)
|
|
||||||
{
|
|
||||||
ttyp->kill_pgrp (sig);
|
|
||||||
ttyp->output_stopped = false;
|
|
||||||
ti.c_lflag &= ~FLUSHO;
|
|
||||||
/* Discard type ahead input */
|
|
||||||
goto skip_writeback;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (ti.c_iflag & IXON)
|
|
||||||
{
|
|
||||||
if (CCEQ (ti.c_cc[VSTOP], c))
|
|
||||||
{
|
|
||||||
if (!ttyp->output_stopped
|
|
||||||
&& input_rec[i].Event.KeyEvent.bKeyDown)
|
|
||||||
{
|
|
||||||
ttyp->output_stopped = true;
|
|
||||||
output_stopped_at = i;
|
|
||||||
}
|
|
||||||
processed = true;
|
|
||||||
}
|
|
||||||
else if (CCEQ (ti.c_cc[VSTART], c))
|
|
||||||
{
|
|
||||||
restart_output:
|
|
||||||
if (input_rec[i].Event.KeyEvent.bKeyDown)
|
|
||||||
ttyp->output_stopped = false;
|
|
||||||
processed = true;
|
|
||||||
}
|
|
||||||
else if ((ti.c_iflag & IXANY) && ttyp->output_stopped
|
|
||||||
&& c && i >= output_stopped_at)
|
|
||||||
goto restart_output;
|
|
||||||
}
|
|
||||||
if ((ti.c_lflag & ICANON) && (ti.c_lflag & IEXTEN)
|
|
||||||
&& CCEQ (ti.c_cc[VDISCARD], c))
|
|
||||||
{
|
|
||||||
if (input_rec[i].Event.KeyEvent.bKeyDown)
|
|
||||||
ti.c_lflag ^= FLUSHO;
|
|
||||||
processed = true;
|
processed = true;
|
||||||
|
ttyp->output_stopped = false;
|
||||||
|
if (ti.c_lflag & NOFLSH)
|
||||||
|
goto remove_record;
|
||||||
|
goto skip_writeback;
|
||||||
|
default: /* not signalled */
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
was_output_stopped = ttyp->output_stopped;
|
||||||
|
processed = process_stop_start (c, ttyp, i > output_stopped_at);
|
||||||
|
if (!was_output_stopped && ttyp->output_stopped)
|
||||||
|
output_stopped_at = i;
|
||||||
break;
|
break;
|
||||||
case WINDOW_BUFFER_SIZE_EVENT:
|
case WINDOW_BUFFER_SIZE_EVENT:
|
||||||
SHORT y = con.dwWinSize.Y;
|
SHORT y = con.dwWinSize.Y;
|
||||||
|
@ -447,7 +407,6 @@ fhandler_console::setup ()
|
||||||
con.cons_rapoi = NULL;
|
con.cons_rapoi = NULL;
|
||||||
shared_console_info->tty_min_state.is_console = true;
|
shared_console_info->tty_min_state.is_console = true;
|
||||||
con.cursor_key_app_mode = false;
|
con.cursor_key_app_mode = false;
|
||||||
con.disable_master_thread = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -503,8 +462,6 @@ fhandler_console::set_input_mode (tty::cons_mode m, const termios *t,
|
||||||
flags |= ENABLE_VIRTUAL_TERMINAL_INPUT;
|
flags |= ENABLE_VIRTUAL_TERMINAL_INPUT;
|
||||||
else
|
else
|
||||||
flags |= ENABLE_MOUSE_INPUT;
|
flags |= ENABLE_MOUSE_INPUT;
|
||||||
if (shared_console_info)
|
|
||||||
con.disable_master_thread = false;
|
|
||||||
break;
|
break;
|
||||||
case tty::native:
|
case tty::native:
|
||||||
if (t->c_lflag & ECHO)
|
if (t->c_lflag & ECHO)
|
||||||
|
@ -517,8 +474,6 @@ fhandler_console::set_input_mode (tty::cons_mode m, const termios *t,
|
||||||
flags &= ~ENABLE_ECHO_INPUT;
|
flags &= ~ENABLE_ECHO_INPUT;
|
||||||
if (t->c_lflag & ISIG)
|
if (t->c_lflag & ISIG)
|
||||||
flags |= ENABLE_PROCESSED_INPUT;
|
flags |= ENABLE_PROCESSED_INPUT;
|
||||||
if (shared_console_info)
|
|
||||||
con.disable_master_thread = true;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
SetConsoleMode (p->input_handle, flags);
|
SetConsoleMode (p->input_handle, flags);
|
||||||
|
@ -1394,9 +1349,6 @@ fhandler_console::open (int flags, mode_t)
|
||||||
setenv ("TERM", "cygwin", 1);
|
setenv ("TERM", "cygwin", 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
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 (),
|
debug_printf ("opened conin$ %p, conout$ %p", get_handle (),
|
||||||
get_output_handle ());
|
get_output_handle ());
|
||||||
|
|
||||||
|
@ -1421,6 +1373,17 @@ fhandler_console::open_setup (int flags)
|
||||||
return fhandler_base::open_setup (flags);
|
return fhandler_base::open_setup (flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
fhandler_console::post_open_setup (int fd)
|
||||||
|
{
|
||||||
|
if (fd == 0)
|
||||||
|
set_input_mode (tty::cygwin, &get_ttyp ()->ti, &handle_set);
|
||||||
|
else if (fd == 1 || fd == 2)
|
||||||
|
set_output_mode (tty::cygwin, &get_ttyp ()->ti, &handle_set);
|
||||||
|
|
||||||
|
fhandler_base::post_open_setup (fd);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
fhandler_console::close ()
|
fhandler_console::close ()
|
||||||
{
|
{
|
||||||
|
|
|
@ -130,8 +130,9 @@ is_flush_sig (int sig)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
tty_min::kill_pgrp (int sig)
|
tty_min::kill_pgrp (int sig, pid_t target_pgid)
|
||||||
{
|
{
|
||||||
|
target_pgid = target_pgid ?: pgid;
|
||||||
bool killself = false;
|
bool killself = false;
|
||||||
if (is_flush_sig (sig) && cygheap->ctty)
|
if (is_flush_sig (sig) && cygheap->ctty)
|
||||||
cygheap->ctty->sigflush ();
|
cygheap->ctty->sigflush ();
|
||||||
|
@ -145,7 +146,7 @@ tty_min::kill_pgrp (int sig)
|
||||||
for (unsigned i = 0; i < pids.npids; i++)
|
for (unsigned i = 0; i < pids.npids; i++)
|
||||||
{
|
{
|
||||||
_pinfo *p = pids[i];
|
_pinfo *p = pids[i];
|
||||||
if (!p || !p->exists () || p->ctty != ntty || p->pgid != pgid)
|
if (!p || !p->exists () || p->ctty != ntty || p->pgid != target_pgid)
|
||||||
continue;
|
continue;
|
||||||
if (p->process_state & PID_NOTCYGWIN)
|
if (p->process_state & PID_NOTCYGWIN)
|
||||||
continue;
|
continue;
|
||||||
|
@ -308,6 +309,156 @@ fhandler_termios::echo_erase (int force)
|
||||||
doecho ("\b \b", 3);
|
doecho ("\b \b", 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fhandler_termios::process_sig_state
|
||||||
|
fhandler_termios::process_sigs (char c, tty* ttyp, fhandler_termios *fh)
|
||||||
|
{
|
||||||
|
termios &ti = ttyp->ti;
|
||||||
|
pid_t pgid = ttyp->pgid;
|
||||||
|
|
||||||
|
pinfo leader (pgid);
|
||||||
|
bool cyg_leader = leader && !(leader->process_state & PID_NOTCYGWIN);
|
||||||
|
bool ctrl_c_event_sent = false;
|
||||||
|
bool need_discard_input = false;
|
||||||
|
bool pg_with_nat = false;
|
||||||
|
bool need_send_sig = false;
|
||||||
|
bool nat_shell = false;
|
||||||
|
bool cyg_reader = false;
|
||||||
|
|
||||||
|
winpids pids ((DWORD) 0);
|
||||||
|
for (unsigned i = 0; i < pids.npids; i++)
|
||||||
|
{
|
||||||
|
_pinfo *p = pids[i];
|
||||||
|
if (c == '\003' && p && p->ctty == ttyp->ntty && p->pgid == pgid
|
||||||
|
&& ((p->process_state & PID_NOTCYGWIN)
|
||||||
|
|| !(p->process_state & PID_CYGPARENT)))
|
||||||
|
{
|
||||||
|
pinfo pinfo_resume = pinfo (myself->ppid);
|
||||||
|
DWORD resume_pid = 0;
|
||||||
|
if (pinfo_resume)
|
||||||
|
resume_pid = pinfo_resume->dwProcessId;
|
||||||
|
else
|
||||||
|
resume_pid = fhandler_pty_common::get_console_process_id
|
||||||
|
(myself->dwProcessId, false);
|
||||||
|
if (resume_pid && fh && !fh->is_console ())
|
||||||
|
{
|
||||||
|
FreeConsole ();
|
||||||
|
AttachConsole (p->dwProcessId);
|
||||||
|
}
|
||||||
|
/* CTRL_C_EVENT does not work for the process started with
|
||||||
|
CREATE_NEW_PROCESS_GROUP flag, so send CTRL_BREAK_EVENT
|
||||||
|
instead. */
|
||||||
|
if (p->process_state & PID_NEW_PG)
|
||||||
|
GenerateConsoleCtrlEvent (CTRL_BREAK_EVENT,
|
||||||
|
p->dwProcessId);
|
||||||
|
else if ((!fh || !fh->is_pty_master_with_pcon () || cyg_leader)
|
||||||
|
&& !ctrl_c_event_sent)
|
||||||
|
{
|
||||||
|
GenerateConsoleCtrlEvent (CTRL_C_EVENT, 0);
|
||||||
|
ctrl_c_event_sent = true;
|
||||||
|
}
|
||||||
|
if (resume_pid && fh && !fh->is_console ())
|
||||||
|
{
|
||||||
|
FreeConsole ();
|
||||||
|
AttachConsole (resume_pid);
|
||||||
|
}
|
||||||
|
need_discard_input = true;
|
||||||
|
}
|
||||||
|
if (p && p->ctty == ttyp->ntty && p->pgid == pgid)
|
||||||
|
{
|
||||||
|
if (p->process_state & PID_NOTCYGWIN)
|
||||||
|
pg_with_nat = true;
|
||||||
|
if (!(p->process_state & PID_NOTCYGWIN))
|
||||||
|
need_send_sig = true;
|
||||||
|
if (!p->cygstarted)
|
||||||
|
nat_shell = true;
|
||||||
|
if (p->process_state & PID_TTYIN)
|
||||||
|
cyg_reader = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Send SIGQUIT to non-cygwin process. */
|
||||||
|
if ((ti.c_lflag & ISIG) && CCEQ (ti.c_cc[VQUIT], c)
|
||||||
|
&& pg_with_nat && need_send_sig && !nat_shell)
|
||||||
|
{
|
||||||
|
for (unsigned i = 0; i < pids.npids; i++)
|
||||||
|
{
|
||||||
|
_pinfo *p = pids[i];
|
||||||
|
if (p && p->ctty == ttyp->ntty && p->pgid == pgid
|
||||||
|
&& (p->process_state & PID_NOTCYGWIN))
|
||||||
|
sig_send (p, SIGQUIT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((ti.c_lflag & ISIG) && need_send_sig)
|
||||||
|
{
|
||||||
|
int sig;
|
||||||
|
if (CCEQ (ti.c_cc[VINTR], c))
|
||||||
|
sig = SIGINT;
|
||||||
|
else if (CCEQ (ti.c_cc[VQUIT], c))
|
||||||
|
sig = SIGQUIT;
|
||||||
|
else if (pg_with_nat)
|
||||||
|
goto not_a_sig;
|
||||||
|
else if (CCEQ (ti.c_cc[VSUSP], c))
|
||||||
|
sig = SIGTSTP;
|
||||||
|
else
|
||||||
|
goto not_a_sig;
|
||||||
|
|
||||||
|
termios_printf ("got interrupt %d, sending signal %d", c, sig);
|
||||||
|
if (!(ti.c_lflag & NOFLSH) && fh)
|
||||||
|
{
|
||||||
|
fh->eat_readahead (-1);
|
||||||
|
fh->discard_input ();
|
||||||
|
}
|
||||||
|
if (fh)
|
||||||
|
fh->release_input_mutex_if_necessary ();
|
||||||
|
ttyp->kill_pgrp (sig, pgid);
|
||||||
|
if (fh)
|
||||||
|
fh->acquire_input_mutex_if_necessary (mutex_timeout);
|
||||||
|
ti.c_lflag &= ~FLUSHO;
|
||||||
|
return signalled;
|
||||||
|
}
|
||||||
|
not_a_sig:
|
||||||
|
if (need_discard_input)
|
||||||
|
{
|
||||||
|
if (!(ti.c_lflag & NOFLSH) && fh)
|
||||||
|
{
|
||||||
|
fh->eat_readahead (-1);
|
||||||
|
fh->discard_input ();
|
||||||
|
}
|
||||||
|
ti.c_lflag &= ~FLUSHO;
|
||||||
|
return not_signalled_but_done;
|
||||||
|
}
|
||||||
|
bool to_cyg = cyg_reader || !pg_with_nat;
|
||||||
|
return to_cyg ? not_signalled_with_cyg_reader : not_signalled;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
fhandler_termios::process_stop_start (char c, tty *ttyp, bool on_ixany)
|
||||||
|
{
|
||||||
|
termios &ti = ttyp->ti;
|
||||||
|
if (ti.c_iflag & IXON)
|
||||||
|
{
|
||||||
|
if (CCEQ (ti.c_cc[VSTOP], c))
|
||||||
|
{
|
||||||
|
ttyp->output_stopped = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (CCEQ (ti.c_cc[VSTART], c))
|
||||||
|
{
|
||||||
|
restart_output:
|
||||||
|
ttyp->output_stopped = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if ((ti.c_iflag & IXANY) && ttyp->output_stopped && on_ixany)
|
||||||
|
goto restart_output;
|
||||||
|
}
|
||||||
|
if ((ti.c_lflag & ICANON) && (ti.c_lflag & IEXTEN)
|
||||||
|
&& CCEQ (ti.c_cc[VDISCARD], c))
|
||||||
|
{
|
||||||
|
ti.c_lflag ^= FLUSHO;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
line_edit_status
|
line_edit_status
|
||||||
fhandler_termios::line_edit (const char *rptr, size_t nread, termios& ti,
|
fhandler_termios::line_edit (const char *rptr, size_t nread, termios& ti,
|
||||||
ssize_t *bytes_read)
|
ssize_t *bytes_read)
|
||||||
|
@ -328,92 +479,24 @@ fhandler_termios::line_edit (const char *rptr, size_t nread, termios& ti,
|
||||||
|
|
||||||
if (ti.c_iflag & ISTRIP)
|
if (ti.c_iflag & ISTRIP)
|
||||||
c &= 0x7f;
|
c &= 0x7f;
|
||||||
winpids pids ((DWORD) 0);
|
bool disable_eof_key = true;
|
||||||
bool need_check_sigs = get_ttyp ()->pcon_input_state_eq (tty::to_cyg);
|
switch (process_sigs (c, get_ttyp (), this))
|
||||||
if (get_ttyp ()->pcon_input_state_eq (tty::to_nat))
|
|
||||||
{
|
{
|
||||||
bool need_discard_input = false;
|
case signalled:
|
||||||
for (unsigned i = 0; i < pids.npids; i++)
|
|
||||||
{
|
|
||||||
_pinfo *p = pids[i];
|
|
||||||
if (c == '\003' && p && p->ctty == tc ()->ntty
|
|
||||||
&& p->pgid == tc ()->getpgid ()
|
|
||||||
&& (p->process_state & PID_NOTCYGWIN))
|
|
||||||
{
|
|
||||||
/* CTRL_C_EVENT does not work for the process started with
|
|
||||||
CREATE_NEW_PROCESS_GROUP flag, so send CTRL_BREAK_EVENT
|
|
||||||
instead. */
|
|
||||||
if (p->process_state & PID_NEW_PG)
|
|
||||||
GenerateConsoleCtrlEvent (CTRL_BREAK_EVENT,
|
|
||||||
p->dwProcessId);
|
|
||||||
else
|
|
||||||
GenerateConsoleCtrlEvent (CTRL_C_EVENT, 0);
|
|
||||||
need_discard_input = true;
|
|
||||||
}
|
|
||||||
if (p->ctty == get_ttyp ()->ntty
|
|
||||||
&& p->pgid == get_ttyp ()->getpgid () && !p->cygstarted)
|
|
||||||
need_check_sigs = true;
|
|
||||||
}
|
|
||||||
if (!CCEQ (ti.c_cc[VINTR], c)
|
|
||||||
&& !CCEQ (ti.c_cc[VQUIT], c)
|
|
||||||
&& !CCEQ (ti.c_cc[VSUSP], c))
|
|
||||||
need_check_sigs = false;
|
|
||||||
if (need_discard_input && !need_check_sigs)
|
|
||||||
{
|
|
||||||
if (!(ti.c_lflag & NOFLSH))
|
|
||||||
{
|
|
||||||
eat_readahead (-1);
|
|
||||||
discard_input ();
|
|
||||||
}
|
|
||||||
ti.c_lflag &= ~FLUSHO;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((ti.c_lflag & ISIG) && need_check_sigs)
|
|
||||||
{
|
|
||||||
int sig;
|
|
||||||
if (CCEQ (ti.c_cc[VINTR], c))
|
|
||||||
sig = SIGINT;
|
|
||||||
else if (CCEQ (ti.c_cc[VQUIT], c))
|
|
||||||
sig = SIGQUIT;
|
|
||||||
else if (CCEQ (ti.c_cc[VSUSP], c))
|
|
||||||
sig = SIGTSTP;
|
|
||||||
else
|
|
||||||
goto not_a_sig;
|
|
||||||
|
|
||||||
termios_printf ("got interrupt %d, sending signal %d", c, sig);
|
|
||||||
if (!(ti.c_lflag & NOFLSH))
|
|
||||||
{
|
|
||||||
eat_readahead (-1);
|
|
||||||
discard_input ();
|
|
||||||
}
|
|
||||||
release_input_mutex_if_necessary ();
|
|
||||||
tc ()->kill_pgrp (sig);
|
|
||||||
acquire_input_mutex_if_necessary (mutex_timeout);
|
|
||||||
ti.c_lflag &= ~FLUSHO;
|
|
||||||
sawsig = true;
|
sawsig = true;
|
||||||
goto restart_output;
|
fallthrough;
|
||||||
}
|
case not_signalled_but_done:
|
||||||
not_a_sig:
|
get_ttyp ()->output_stopped = false;
|
||||||
if (ti.c_iflag & IXON)
|
continue;
|
||||||
{
|
case not_signalled_with_cyg_reader:
|
||||||
if (CCEQ (ti.c_cc[VSTOP], c))
|
disable_eof_key = false;
|
||||||
{
|
break;
|
||||||
if (!tc ()->output_stopped)
|
default: /* Not signalled */
|
||||||
tc ()->output_stopped = true;
|
break;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else if (CCEQ (ti.c_cc[VSTART], c))
|
|
||||||
{
|
|
||||||
restart_output:
|
|
||||||
tc ()->output_stopped = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else if ((ti.c_iflag & IXANY) && tc ()->output_stopped)
|
|
||||||
goto restart_output;
|
|
||||||
}
|
}
|
||||||
|
if (process_stop_start (c, get_ttyp (), true))
|
||||||
|
continue;
|
||||||
/* Check for special chars */
|
/* Check for special chars */
|
||||||
|
|
||||||
if (c == '\r')
|
if (c == '\r')
|
||||||
{
|
{
|
||||||
if (ti.c_iflag & IGNCR)
|
if (ti.c_iflag & IGNCR)
|
||||||
|
@ -432,12 +515,6 @@ fhandler_termios::line_edit (const char *rptr, size_t nread, termios& ti,
|
||||||
set_input_done (iscanon);
|
set_input_done (iscanon);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iscanon && ti.c_lflag & IEXTEN && CCEQ (ti.c_cc[VDISCARD], c))
|
|
||||||
{
|
|
||||||
ti.c_lflag ^= FLUSHO;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!iscanon)
|
if (!iscanon)
|
||||||
/* nothing */;
|
/* nothing */;
|
||||||
else if (CCEQ (ti.c_cc[VERASE], c))
|
else if (CCEQ (ti.c_cc[VERASE], c))
|
||||||
|
@ -474,7 +551,7 @@ fhandler_termios::line_edit (const char *rptr, size_t nread, termios& ti,
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (CCEQ (ti.c_cc[VEOF], c) && need_check_sigs)
|
else if (CCEQ (ti.c_cc[VEOF], c) && !disable_eof_key)
|
||||||
{
|
{
|
||||||
termios_printf ("EOF");
|
termios_printf ("EOF");
|
||||||
accept_input ();
|
accept_input ();
|
||||||
|
|
|
@ -2291,47 +2291,12 @@ fhandler_pty_master::write (const void *ptr, size_t len)
|
||||||
&mbp);
|
&mbp);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ti.c_lflag & ISIG) && memchr (buf, '\003', nlen))
|
for (size_t i = 0; i < nlen; i++)
|
||||||
{
|
{
|
||||||
/* If the process is started with CREATE_NEW_PROCESS_GROUP
|
fhandler_termios::process_sigs (buf[i], get_ttyp (), this);
|
||||||
flag, Ctrl-C will not be sent to that process. Therefore,
|
process_stop_start (buf[i], get_ttyp (), true);
|
||||||
send Ctrl-break event to that process here. */
|
|
||||||
DWORD wpid = 0;
|
|
||||||
winpids pids ((DWORD) 0);
|
|
||||||
for (unsigned i = 0; i < pids.npids; i++)
|
|
||||||
{
|
|
||||||
_pinfo *p = pids[i];
|
|
||||||
if (p->ctty == get_ttyp ()->ntty
|
|
||||||
&& p->pgid == get_ttyp ()->getpgid ()
|
|
||||||
&& (p->process_state & PID_NOTCYGWIN)
|
|
||||||
&& (p->process_state & PID_NEW_PG))
|
|
||||||
{
|
|
||||||
wpid = p->dwProcessId;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pinfo pinfo_resume = pinfo (myself->ppid);
|
|
||||||
DWORD resume_pid;
|
|
||||||
if (pinfo_resume)
|
|
||||||
resume_pid = pinfo_resume->dwProcessId;
|
|
||||||
else
|
|
||||||
resume_pid = get_console_process_id (myself->dwProcessId, false);
|
|
||||||
if (wpid && resume_pid)
|
|
||||||
{
|
|
||||||
WaitForSingleObject (pcon_mutex, INFINITE);
|
|
||||||
FreeConsole ();
|
|
||||||
AttachConsole (wpid);
|
|
||||||
/* CTRL_C_EVENT does not work for the process started with
|
|
||||||
CREATE_NEW_PROCESS_GROUP flag, so send CTRL_BREAK_EVENT
|
|
||||||
instead. */
|
|
||||||
GenerateConsoleCtrlEvent (CTRL_BREAK_EVENT, wpid);
|
|
||||||
FreeConsole ();
|
|
||||||
AttachConsole (resume_pid);
|
|
||||||
ReleaseMutex (pcon_mutex);
|
|
||||||
}
|
|
||||||
if (!(ti.c_lflag & NOFLSH))
|
|
||||||
get_ttyp ()->discard_input = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD n;
|
DWORD n;
|
||||||
WriteFile (to_slave_nat, buf, nlen, &n, NULL);
|
WriteFile (to_slave_nat, buf, nlen, &n, NULL);
|
||||||
ReleaseMutex (input_mutex);
|
ReleaseMutex (input_mutex);
|
||||||
|
@ -2885,7 +2850,8 @@ fhandler_pty_master::pty_master_fwd_thread (const master_fwd_thread_param_t *p)
|
||||||
WaitForSingleObject (p->output_mutex, mutex_timeout);
|
WaitForSingleObject (p->output_mutex, mutex_timeout);
|
||||||
while (rlen>0)
|
while (rlen>0)
|
||||||
{
|
{
|
||||||
if (!process_opost_output (p->to_master, ptr, wlen, false,
|
if (!process_opost_output (p->to_master, ptr, wlen,
|
||||||
|
true /* disable output_stopped */,
|
||||||
p->ttyp, false))
|
p->ttyp, false))
|
||||||
{
|
{
|
||||||
termios_printf ("WriteFile for forwarding failed, %E");
|
termios_printf ("WriteFile for forwarding failed, %E");
|
||||||
|
@ -4006,3 +3972,10 @@ fhandler_pty_slave::transfer_input (tty::xfer_dir dir, HANDLE from, tty *ttyp,
|
||||||
ttyp->pcon_input_state = dir;
|
ttyp->pcon_input_state = dir;
|
||||||
ttyp->discard_input = false;
|
ttyp->discard_input = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
fhandler_pty_slave::cleanup_before_exit ()
|
||||||
|
{
|
||||||
|
if (myself->process_state & PID_NOTCYGWIN)
|
||||||
|
get_ttyp ()->wait_pcon_fwd ();
|
||||||
|
}
|
||||||
|
|
|
@ -75,7 +75,7 @@ public:
|
||||||
void setpgid (int pid);
|
void setpgid (int pid);
|
||||||
int getsid () const {return sid;}
|
int getsid () const {return sid;}
|
||||||
void setsid (pid_t tsid) {sid = tsid;}
|
void setsid (pid_t tsid) {sid = tsid;}
|
||||||
void kill_pgrp (int);
|
void kill_pgrp (int, pid_t target_pgid = 0);
|
||||||
int is_orphaned_process_group (int);
|
int is_orphaned_process_group (int);
|
||||||
const __reg1 char *ttyname () __attribute (());
|
const __reg1 char *ttyname () __attribute (());
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue