-/* $OpenBSD: tty_pty.c,v 1.108 2021/02/08 09:18:30 claudio Exp $ */
+/* $OpenBSD: tty_pty.c,v 1.109 2021/10/22 15:11:32 mpi Exp $ */
/* $NetBSD: tty_pty.c,v 1.33.4.1 1996/06/02 09:08:11 mrg Exp $ */
/*
int filt_ptcread(struct knote *, long);
void filt_ptcwdetach(struct knote *);
int filt_ptcwrite(struct knote *, long);
+int filt_ptcexcept(struct knote *, long);
static struct pt_softc **ptyarralloc(int);
static int check_pty(int);
tp = pti->pt_tty;
kn->kn_data = 0;
- if (kn->kn_sfflags & NOTE_OOB) {
- /* If in packet or user control mode, check for data. */
- if (((pti->pt_flags & PF_PKT) && pti->pt_send) ||
- ((pti->pt_flags & PF_UCNTL) && pti->pt_ucntl)) {
- kn->kn_fflags |= NOTE_OOB;
- kn->kn_data = 1;
- return (1);
- }
- return (0);
- }
if (ISSET(tp->t_state, TS_ISOPEN)) {
if (!ISSET(tp->t_state, TS_TTSTOP))
kn->kn_data = tp->t_outq.c_cc;
return (kn->kn_data > 0);
}
+int
+filt_ptcexcept(struct knote *kn, long hint)
+{
+ struct pt_softc *pti = (struct pt_softc *)kn->kn_hook;
+ struct tty *tp;
+
+ tp = pti->pt_tty;
+
+ if (kn->kn_sfflags & NOTE_OOB) {
+ /* If in packet or user control mode, check for data. */
+ if (((pti->pt_flags & PF_PKT) && pti->pt_send) ||
+ ((pti->pt_flags & PF_UCNTL) && pti->pt_ucntl)) {
+ kn->kn_fflags |= NOTE_OOB;
+ kn->kn_data = 1;
+ return (1);
+ }
+ return (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);
+ }
+
+ return (0);
+}
+
const struct filterops ptcread_filtops = {
.f_flags = FILTEROP_ISFD,
.f_attach = NULL,
.f_flags = FILTEROP_ISFD,
.f_attach = NULL,
.f_detach = filt_ptcrdetach,
- .f_event = filt_ptcread,
+ .f_event = filt_ptcexcept,
};
int
-/* $OpenBSD: uipc_socket.c,v 1.265 2021/10/14 23:05:10 mvs Exp $ */
+/* $OpenBSD: uipc_socket.c,v 1.266 2021/10/22 15:11:32 mpi Exp $ */
/* $NetBSD: uipc_socket.c,v 1.21 1996/02/04 02:17:52 christos Exp $ */
/*
int filt_sowritemodify(struct kevent *kev, struct knote *kn);
int filt_sowriteprocess(struct knote *kn, struct kevent *kev);
int filt_sowrite_common(struct knote *kn, struct socket *so);
+int filt_soexcept(struct knote *kn, long hint);
+int filt_soexceptmodify(struct kevent *kev, struct knote *kn);
+int filt_soexceptprocess(struct knote *kn, struct kevent *kev);
+int filt_soexcept_common(struct knote *kn, struct socket *so);
int filt_solisten(struct knote *kn, long hint);
int filt_solistenmodify(struct kevent *kev, struct knote *kn);
int filt_solistenprocess(struct knote *kn, struct kevent *kev);
.f_flags = FILTEROP_ISFD,
.f_attach = NULL,
.f_detach = filt_sordetach,
- .f_event = filt_soread,
- .f_modify = filt_soreadmodify,
- .f_process = filt_soreadprocess,
+ .f_event = filt_soexcept,
+ .f_modify = filt_soexceptmodify,
+ .f_process = filt_soexceptprocess,
};
#ifndef SOMINCONN
rv = 0;
} else
#endif /* SOCKET_SPLICE */
- if (kn->kn_sfflags & NOTE_OOB) {
- if (so->so_oobmark || (so->so_state & SS_RCVATMARK)) {
- kn->kn_fflags |= NOTE_OOB;
- kn->kn_data -= so->so_oobmark;
- rv = 1;
- }
- } else if (so->so_state & SS_CANTRCVMORE) {
+ if (so->so_state & SS_CANTRCVMORE) {
kn->kn_flags |= EV_EOF;
if (kn->kn_flags & __EV_POLL) {
if (so->so_state & SS_ISDISCONNECTED)
return (rv);
}
+int
+filt_soexcept_common(struct knote *kn, struct socket *so)
+{
+ int rv = 0;
+
+ soassertlocked(so);
+
+#ifdef SOCKET_SPLICE
+ if (isspliced(so)) {
+ rv = 0;
+ } else
+#endif /* SOCKET_SPLICE */
+ if (kn->kn_sfflags & NOTE_OOB) {
+ if (so->so_oobmark || (so->so_state & SS_RCVATMARK)) {
+ kn->kn_fflags |= NOTE_OOB;
+ kn->kn_data -= so->so_oobmark;
+ rv = 1;
+ }
+ } else if (so->so_state & SS_CANTRCVMORE) {
+ kn->kn_flags |= EV_EOF;
+ if (kn->kn_flags & __EV_POLL) {
+ if (so->so_state & SS_ISDISCONNECTED)
+ kn->kn_flags |= __EV_HUP;
+ }
+ kn->kn_fflags = so->so_error;
+ rv = 1;
+ }
+
+ return rv;
+}
+
+int
+filt_soexcept(struct knote *kn, long hint)
+{
+ struct socket *so = kn->kn_fp->f_data;
+
+ return (filt_soexcept_common(kn, so));
+}
+
+int
+filt_soexceptmodify(struct kevent *kev, struct knote *kn)
+{
+ struct socket *so = kn->kn_fp->f_data;
+ int rv, s;
+
+ s = solock(so);
+ knote_modify(kev, kn);
+ rv = filt_soexcept_common(kn, so);
+ sounlock(so, s);
+
+ return (rv);
+}
+
+int
+filt_soexceptprocess(struct knote *kn, struct kevent *kev)
+{
+ struct socket *so = kn->kn_fp->f_data;
+ int rv, s;
+
+ s = solock(so);
+ if (kev != NULL && (kn->kn_flags & EV_ONESHOT))
+ rv = 1;
+ else
+ rv = filt_soexcept_common(kn, so);
+ if (rv != 0)
+ knote_submit(kn, kev);
+ sounlock(so, s);
+
+ return (rv);
+}
+
int
filt_solisten_common(struct knote *kn, struct socket *so)
{
-/* $OpenBSD: fifo_vnops.c,v 1.82 2021/10/15 06:30:06 semarie Exp $ */
+/* $OpenBSD: fifo_vnops.c,v 1.83 2021/10/22 15:11:32 mpi Exp $ */
/* $NetBSD: fifo_vnops.c,v 1.18 1996/03/16 23:52:42 christos Exp $ */
/*
int filt_fifowritemodify(struct kevent *kev, struct knote *kn);
int filt_fifowriteprocess(struct knote *kn, struct kevent *kev);
int filt_fifowrite_common(struct knote *kn, struct socket *so);
+int filt_fifoexcept(struct knote *kn, long hint);
+int filt_fifoexceptmodify(struct kevent *kev, struct knote *kn);
+int filt_fifoexceptprocess(struct knote *kn, struct kevent *kev);
+int filt_fifoexcept_common(struct knote *kn, struct socket *so);
const struct filterops fiforead_filtops = {
.f_flags = FILTEROP_ISFD,
.f_process = filt_fifowriteprocess,
};
+const struct filterops fifoexcept_filtops = {
+ .f_flags = FILTEROP_ISFD,
+ .f_attach = NULL,
+ .f_detach = filt_fifordetach,
+ .f_event = filt_fifoexcept,
+ .f_modify = filt_fifoexceptmodify,
+ .f_process = filt_fifoexceptprocess,
+};
+
/*
* Open called to set up a new instance of a fifo or
* to find an active instance of a fifo.
so = fip->fi_writesock;
sb = &so->so_snd;
break;
+ case EVFILT_EXCEPT:
+ ap->a_kn->kn_fop = &fifoexcept_filtops;
+ so = fip->fi_readsock;
+ sb = &so->so_rcv;
+ break;
default:
return (EINVAL);
}
return (rv);
}
+
+int
+filt_fifoexcept_common(struct knote *kn, struct socket *so)
+{
+ int rv = 0;
+
+ soassertlocked(so);
+
+ if (so->so_state & SS_CANTRCVMORE) {
+ kn->kn_flags |= EV_EOF;
+ if (kn->kn_flags & __EV_POLL) {
+ if (so->so_state & SS_ISDISCONNECTED)
+ kn->kn_flags |= __EV_HUP;
+ }
+ rv = 1;
+ }
+
+ return (rv);
+}
+
+int
+filt_fifoexcept(struct knote *kn, long hint)
+{
+ struct socket *so = kn->kn_hook;
+
+ return (filt_fifoexcept_common(kn, so));
+}
+
+int
+filt_fifoexceptmodify(struct kevent *kev, struct knote *kn)
+{
+ struct socket *so = kn->kn_hook;
+ int rv, s;
+
+ s = solock(so);
+ knote_modify(kev, kn);
+ rv = filt_fifoexcept_common(kn, so);
+ sounlock(so, s);
+
+ return (rv);
+}
+
+int
+filt_fifoexceptprocess(struct knote *kn, struct kevent *kev)
+{
+ struct socket *so = kn->kn_hook;
+ int rv, s;
+
+ s = solock(so);
+ if (kev != NULL && (kn->kn_flags & EV_ONESHOT))
+ rv = 1;
+ else
+ rv = filt_fifoexcept_common(kn, so);
+ if (rv != 0)
+ knote_submit(kn, kev);
+ sounlock(so, s);
+
+ return (rv);
+}