summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVisa Hankala <visa@cvs.openbsd.org>2021-12-15 15:30:48 +0000
committerVisa Hankala <visa@cvs.openbsd.org>2021-12-15 15:30:48 +0000
commit2146bba213948527b5b5fda699eac2ea28cc2476 (patch)
treee7d9a62f7458af8eea2c88642fccf7c40e13b3b3
parent709d0314ce6e3b1766eb9b44fe8b1e5f6b0a15be (diff)
Adjust pty and tty event filters
* Implement EVFILT_EXCEPT for ttys for HUP condition detection. This filter is used when pollfd.events has no read/write events. * Add HUP condition detection to filt_ptcwrite() and filt_ttywrite() to reflect ptcpoll() and ttpoll(). Only poll(2) and select(2) can utilize the code; kevent(2) should behave as before with EVFILT_WRITE. * Clear EV_EOF and __EV_HUP if the EOF/HUP condition ends. OK mpi@
-rw-r--r--sys/kern/tty.c62
-rw-r--r--sys/kern/tty_pty.c26
2 files changed, 80 insertions, 8 deletions
diff --git a/sys/kern/tty.c b/sys/kern/tty.c
index 37e9ab5efbd..ae6cffb56ed 100644
--- a/sys/kern/tty.c
+++ b/sys/kern/tty.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tty.c,v 1.172 2021/12/14 15:32:20 visa Exp $ */
+/* $OpenBSD: tty.c,v 1.173 2021/12/15 15:30:47 visa Exp $ */
/* $NetBSD: tty.c,v 1.68.4.2 1996/06/06 16:04:52 thorpej Exp $ */
/*-
@@ -78,6 +78,7 @@ int filt_ttyread(struct knote *kn, long hint);
void filt_ttyrdetach(struct knote *kn);
int filt_ttywrite(struct knote *kn, long hint);
void filt_ttywdetach(struct knote *kn);
+int filt_ttyexcept(struct knote *kn, long hint);
void ttystats_init(struct itty **, int *, size_t *);
int ttywait_nsec(struct tty *, uint64_t);
int ttysleep_nsec(struct tty *, void *, int, char *, uint64_t);
@@ -1110,6 +1111,13 @@ const struct filterops ttywrite_filtops = {
.f_event = filt_ttywrite,
};
+const struct filterops ttyexcept_filtops = {
+ .f_flags = FILTEROP_ISFD,
+ .f_attach = NULL,
+ .f_detach = filt_ttyrdetach,
+ .f_event = filt_ttyexcept,
+};
+
int
ttkqfilter(dev_t dev, struct knote *kn)
{
@@ -1126,6 +1134,18 @@ ttkqfilter(dev_t dev, struct knote *kn)
klist = &tp->t_wsel.si_note;
kn->kn_fop = &ttywrite_filtops;
break;
+ case EVFILT_EXCEPT:
+ if (kn->kn_flags & __EV_SELECT) {
+ /* Prevent triggering exceptfds. */
+ return (EPERM);
+ }
+ if ((kn->kn_flags & __EV_POLL) == 0) {
+ /* Disallow usage through kevent(2). */
+ return (EINVAL);
+ }
+ klist = &tp->t_rsel.si_note;
+ kn->kn_fop = &ttyexcept_filtops;
+ break;
default:
return (EINVAL);
}
@@ -1164,6 +1184,8 @@ filt_ttyread(struct knote *kn, long hint)
if (kn->kn_flags & __EV_POLL)
kn->kn_flags |= __EV_HUP;
active = 1;
+ } else {
+ kn->kn_flags &= ~(EV_EOF | __EV_HUP);
}
splx(s);
return (active);
@@ -1184,13 +1206,45 @@ int
filt_ttywrite(struct knote *kn, long hint)
{
struct tty *tp = kn->kn_hook;
- int canwrite, s;
+ int active, s;
s = spltty();
kn->kn_data = tp->t_outq.c_cn - tp->t_outq.c_cc;
- canwrite = (tp->t_outq.c_cc <= tp->t_lowat);
+ active = (tp->t_outq.c_cc <= tp->t_lowat);
+
+ /* Write-side HUP condition is only for poll(2) and select(2). */
+ if (kn->kn_flags & (__EV_POLL | __EV_SELECT)) {
+ if (!ISSET(tp->t_cflag, CLOCAL) &&
+ !ISSET(tp->t_state, TS_CARR_ON)) {
+ kn->kn_flags |= __EV_HUP;
+ active = 1;
+ } else {
+ kn->kn_flags &= ~__EV_HUP;
+ }
+ }
+ splx(s);
+ return (active);
+}
+
+int
+filt_ttyexcept(struct knote *kn, long hint)
+{
+ struct tty *tp = kn->kn_hook;
+ int active = 0;
+ int s;
+
+ s = spltty();
+ if (kn->kn_flags & __EV_POLL) {
+ if (!ISSET(tp->t_cflag, CLOCAL) &&
+ !ISSET(tp->t_state, TS_CARR_ON)) {
+ kn->kn_flags |= __EV_HUP;
+ active = 1;
+ } else {
+ kn->kn_flags &= ~__EV_HUP;
+ }
+ }
splx(s);
- return (canwrite);
+ return (active);
}
static int
diff --git a/sys/kern/tty_pty.c b/sys/kern/tty_pty.c
index f719155fa85..684b5402a3c 100644
--- a/sys/kern/tty_pty.c
+++ b/sys/kern/tty_pty.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tty_pty.c,v 1.111 2021/12/13 14:56:55 visa Exp $ */
+/* $OpenBSD: tty_pty.c,v 1.112 2021/12/15 15:30:47 visa Exp $ */
/* $NetBSD: tty_pty.c,v 1.33.4.1 1996/06/02 09:08:11 mrg Exp $ */
/*
@@ -667,6 +667,7 @@ filt_ptcread(struct knote *kn, long hint)
{
struct pt_softc *pti = (struct pt_softc *)kn->kn_hook;
struct tty *tp;
+ int active;
tp = pti->pt_tty;
kn->kn_data = 0;
@@ -678,15 +679,18 @@ filt_ptcread(struct knote *kn, long hint)
((pti->pt_flags & PF_UCNTL) && pti->pt_ucntl))
kn->kn_data++;
}
+ active = (kn->kn_data > 0);
if (!ISSET(tp->t_state, TS_CARR_ON)) {
kn->kn_flags |= EV_EOF;
if (kn->kn_flags & __EV_POLL)
kn->kn_flags |= __EV_HUP;
- return (1);
+ active = 1;
+ } else {
+ kn->kn_flags &= ~(EV_EOF | __EV_HUP);
}
- return (kn->kn_data > 0);
+ return (active);
}
void
@@ -705,6 +709,7 @@ filt_ptcwrite(struct knote *kn, long hint)
{
struct pt_softc *pti = (struct pt_softc *)kn->kn_hook;
struct tty *tp;
+ int active;
tp = pti->pt_tty;
kn->kn_data = 0;
@@ -718,8 +723,19 @@ filt_ptcwrite(struct knote *kn, long hint)
kn->kn_data = tp->t_canq.c_cn -
(tp->t_rawq.c_cc + tp->t_canq.c_cc);
}
+ active = (kn->kn_data > 0);
- return (kn->kn_data > 0);
+ /* Write-side HUP condition is only for poll(2) and select(2). */
+ if (kn->kn_flags & (__EV_POLL | __EV_SELECT)) {
+ if (!ISSET(tp->t_state, TS_CARR_ON)) {
+ kn->kn_flags |= __EV_HUP;
+ active = 1;
+ } else {
+ kn->kn_flags &= ~__EV_HUP;
+ }
+ }
+
+ return (active);
}
int
@@ -745,6 +761,8 @@ filt_ptcexcept(struct knote *kn, long hint)
if (!ISSET(tp->t_state, TS_CARR_ON)) {
kn->kn_flags |= __EV_HUP;
active = 1;
+ } else {
+ kn->kn_flags &= ~__EV_HUP;
}
}