Implement FLUSHO

Turn FLUSHO on/off with ^O (or whatever VDISCARD is). Honor that to
throw away output quickly. This tries to remain true to 4.4BSD
behavior (since that was the origin of this feature), with any
corrections NetBSD has done. Since the implemenations are a little
different, though, some edge conditions may be handled differently.

Reviewed by: kib, kevans
Differential Review: https://reviews.freebsd.org/D26148
This commit is contained in:
Warner Losh 2020-08-27 05:11:15 +00:00
parent 23f93ed79b
commit cbda6f66f4
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=364855
2 changed files with 34 additions and 1 deletions

View File

@ -1467,6 +1467,7 @@ tty_signal_sessleader(struct tty *tp, int sig)
/* Make signals start output again. */
tp->t_flags &= ~TF_STOPPED;
tp->t_termios.c_lflag &= ~FLUSHO;
if (tp->t_session != NULL && tp->t_session->s_leader != NULL) {
p = tp->t_session->s_leader;
@ -1486,6 +1487,7 @@ tty_signal_pgrp(struct tty *tp, int sig)
/* Make signals start output again. */
tp->t_flags &= ~TF_STOPPED;
tp->t_termios.c_lflag &= ~FLUSHO;
if (sig == SIGINFO && !(tp->t_termios.c_lflag & NOKERNINFO))
tty_info(tp);
@ -1930,6 +1932,7 @@ tty_generic_ioctl(struct tty *tp, u_long cmd, void *data, int fflag,
return (0);
case TIOCSTART:
tp->t_flags &= ~TF_STOPPED;
tp->t_termios.c_lflag &= ~FLUSHO;
ttydevsw_outwakeup(tp);
ttydevsw_pktnotify(tp, TIOCPKT_START);
return (0);

View File

@ -95,6 +95,7 @@ ttydisc_close(struct tty *tp)
/* Clean up our flags when leaving the discipline. */
tp->t_flags &= ~(TF_STOPPED|TF_HIWAT|TF_ZOMBIE);
tp->t_termios.c_lflag &= ~FLUSHO;
/*
* POSIX states that we must drain output and flush input on
@ -474,6 +475,12 @@ ttydisc_write(struct tty *tp, struct uio *uio, int ioflag)
MPASS(oblen == 0);
if (CMP_FLAG(l, FLUSHO)) {
uio->uio_offset += uio->uio_resid;
uio->uio_resid = 0;
return (0);
}
/* Step 1: read data. */
obstart = ob;
nlen = MIN(uio->uio_resid, sizeof ob);
@ -495,6 +502,12 @@ ttydisc_write(struct tty *tp, struct uio *uio, int ioflag)
do {
unsigned int plen, wlen;
if (CMP_FLAG(l, FLUSHO)) {
uio->uio_offset += uio->uio_resid;
uio->uio_resid = 0;
return (0);
}
/* Search for special characters for post processing. */
if (CMP_FLAG(o, OPOST)) {
plen = ttydisc_findchar(obstart, oblen);
@ -629,6 +642,9 @@ static int
ttydisc_echo_force(struct tty *tp, char c, int quote)
{
if (CMP_FLAG(l, FLUSHO))
return 0;
if (CMP_FLAG(o, OPOST) && CTL_ECHO(c, quote)) {
/*
* Only perform postprocessing when OPOST is turned on
@ -879,8 +895,10 @@ ttydisc_rint(struct tty *tp, char c, int flags)
}
/* Allow any character to perform a wakeup. */
if (CMP_FLAG(i, IXANY))
if (CMP_FLAG(i, IXANY)) {
tp->t_flags &= ~TF_STOPPED;
tp->t_termios.c_lflag &= ~FLUSHO;
}
/* Remove the top bit. */
if (CMP_FLAG(i, ISTRIP))
@ -906,6 +924,18 @@ ttydisc_rint(struct tty *tp, char c, int flags)
tp->t_flags |= TF_LITERAL;
return (0);
}
/* Discard processing */
if (CMP_CC(VDISCARD, c)) {
if (CMP_FLAG(l, FLUSHO)) {
tp->t_termios.c_lflag &= ~FLUSHO;
} else {
tty_flush(tp, FWRITE);
ttydisc_echo(tp, c, 0);
if (tp->t_inq.ti_end > 0)
ttydisc_reprint(tp);
tp->t_termios.c_lflag |= FLUSHO;
}
}
}
/*