Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F143192690
D43378.id132772.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
3 KB
Referenced Files
None
Subscribers
None
D43378.id132772.diff
View Options
diff --git a/sys/kern/tty.c b/sys/kern/tty.c
--- a/sys/kern/tty.c
+++ b/sys/kern/tty.c
@@ -1673,7 +1673,7 @@
/* This device supports non-blocking operation. */
return (0);
case FIONREAD:
- *(int *)data = ttyinq_bytescanonicalized(&tp->t_inq);
+ *(int *)data = ttydisc_bytesavail(tp);
return (0);
case FIONWRITE:
case TIOCOUTQ:
diff --git a/sys/kern/tty_ttydisc.c b/sys/kern/tty_ttydisc.c
--- a/sys/kern/tty_ttydisc.c
+++ b/sys/kern/tty_ttydisc.c
@@ -112,15 +112,20 @@
ttyhook_close(tp);
}
-static int
-ttydisc_read_canonical(struct tty *tp, struct uio *uio, int ioflag)
+/*
+ * Populate our break array; it should likely be at least 4 bytes in size to
+ * allow for \n, VEOF, and VEOL.
+ */
+static void
+ttydisc_read_break(struct tty *tp, char *breakc, size_t breaksz)
{
- char breakc[4] = { CNL }; /* enough to hold \n, VEOF and VEOL. */
- int error;
- size_t clen, flen = 0, n = 1;
- unsigned char lastc = _POSIX_VDISABLE;
+ size_t n = 0;
+ MPASS(breaksz != 0);
+
+ breakc[n++] = CNL;
#define BREAK_ADD(c) do { \
+ MPASS(n < breaksz - 1); /* NUL terminated */ \
if (tp->t_termios.c_cc[c] != _POSIX_VDISABLE) \
breakc[n++] = tp->t_termios.c_cc[c]; \
} while (0)
@@ -128,7 +133,48 @@
BREAK_ADD(VEOF);
BREAK_ADD(VEOL);
#undef BREAK_ADD
+
breakc[n] = '\0';
+}
+
+size_t
+ttydisc_bytesavail(struct tty *tp)
+{
+ size_t clen;
+ char breakc[4];
+ unsigned char lastc = _POSIX_VDISABLE;
+
+ clen = ttyinq_bytescanonicalized(&tp->t_inq);
+ if (!CMP_FLAG(l, ICANON) || clen == 0)
+ return (clen);
+
+ ttydisc_read_break(tp, &breakc[0], sizeof(breakc));
+ clen = ttyinq_findchar(&tp->t_inq, breakc, clen, &lastc);
+
+ /*
+ * We might have a partial line canonicalized in the input queue if we,
+ * for instance, switched to ICANON after taking some input in raw mode.
+ * In this case, read(2) will block because we only have a partial line.
+ */
+ if (lastc == _POSIX_VDISABLE)
+ return (0);
+
+ /* If VEOF was our terminal, it must be discarded (not counted). */
+ if (CMP_CC(VEOF, lastc))
+ clen--;
+
+ return (clen);
+}
+
+static int
+ttydisc_read_canonical(struct tty *tp, struct uio *uio, int ioflag)
+{
+ char breakc[4]; /* enough to hold \n, VEOF and VEOL. */
+ int error;
+ size_t clen, flen = 0;
+ unsigned char lastc = _POSIX_VDISABLE;
+
+ ttydisc_read_break(tp, &breakc[0], sizeof(breakc));
do {
error = tty_wait_background(tp, curthread, SIGTTIN);
@@ -153,7 +199,7 @@
* cause the TTY layer to return data in chunks using
* the blocksize (except the first and last blocks).
*/
- clen = ttyinq_findchar(&tp->t_inq, breakc, uio->uio_resid,
+ clen = ttyinq_findchar(&tp->t_inq, breakc, uio->uio_resid + 1,
&lastc);
/* No more data. */
@@ -169,10 +215,20 @@
continue;
}
- /* Don't send the EOF char back to userspace. */
+ /*
+ * Don't send the EOF char back to userspace. Our above call to
+ * ttyinq_findchar overreads by 1 character in case we would
+ * otherwise be leaving an EOF for the next read(). We'll trim
+ * clen back down to uio_resid whether we find our EOF or not.
+ */
if (CMP_CC(VEOF, lastc))
flen = 1;
+ /*
+ * Trim clen back down to the buffer size, since we had
+ * intentionally over-read.
+ */
+ clen = MIN(uio->uio_resid + flen, clen);
MPASS(flen <= clen);
/* Read and throw away the EOF character. */
diff --git a/sys/sys/ttydisc.h b/sys/sys/ttydisc.h
--- a/sys/sys/ttydisc.h
+++ b/sys/sys/ttydisc.h
@@ -44,6 +44,7 @@
/* Top half routines. */
void ttydisc_open(struct tty *tp);
void ttydisc_close(struct tty *tp);
+size_t ttydisc_bytesavail(struct tty *tp);
int ttydisc_read(struct tty *tp, struct uio *uio, int ioflag);
int ttydisc_write(struct tty *tp, struct uio *uio, int ioflag);
void ttydisc_optimize(struct tty *tp);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Jan 28, 5:48 AM (8 h, 54 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28063661
Default Alt Text
D43378.id132772.diff (3 KB)
Attached To
Mode
D43378: kern: tty: fix EOF handling for canonical reads
Attached
Detach File
Event Timeline
Log In to Comment