1 /*-
2 * Copyright (c) 2024 Kyle Evans <kevans@FreeBSD.org>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7 #include <sys/types.h>
8 #include <sys/ioctl.h>
9
10 #include <termios.h>
11
12 #include <atf-c.h>
13 #include <libutil.h>
14
15 /* Just a little more concise. */
16 #define newpty(masterp, slavep) openpty((masterp), (slavep), NULL, NULL, NULL)
17
18 ATF_TC_WITHOUT_HEAD(fionread);
ATF_TC_BODY(fionread,tc)19 ATF_TC_BODY(fionread, tc)
20 {
21 char rbuf[32];
22 char buf[] = "Hello";
23 int master, slave;
24 int bytes;
25
26 ATF_REQUIRE_EQ(0, newpty(&master, &slave));
27
28 /* Should be empty to begin with. */
29 ATF_REQUIRE_EQ(0, ioctl(master, FIONREAD, &bytes));
30 ATF_REQUIRE_EQ(0, bytes);
31
32 ATF_REQUIRE_EQ(sizeof(buf) - 1, write(slave, buf, sizeof(buf) - 1));
33 ATF_REQUIRE_EQ(0, ioctl(master, FIONREAD, &bytes));
34 ATF_REQUIRE_EQ(sizeof(buf) - 1, bytes);
35
36 /* Drain what we have available, should result in 0 bytes again. */
37 ATF_REQUIRE_EQ(sizeof(buf) - 1, read(master, rbuf, sizeof(rbuf)));
38 ATF_REQUIRE_EQ(0, ioctl(master, FIONREAD, &bytes));
39 ATF_REQUIRE_EQ(0, bytes);
40
41 /*
42 * Write once more, then close the slave side with data still in the
43 * buffer.
44 */
45 ATF_REQUIRE_EQ(sizeof(buf) - 1, write(slave, buf, sizeof(buf) - 1));
46 ATF_REQUIRE_EQ(0, ioctl(master, FIONREAD, &bytes));
47 ATF_REQUIRE_EQ(sizeof(buf) - 1, bytes);
48
49 ATF_REQUIRE_EQ(0, close(slave));
50
51 /*
52 * The tty's output queue is discarded upon close, so we shouldn't have
53 * anything else to read().
54 */
55 ATF_REQUIRE_EQ(0, ioctl(master, FIONREAD, &bytes));
56 ATF_REQUIRE_EQ(0, bytes);
57 ATF_REQUIRE_EQ(0, read(master, rbuf, sizeof(rbuf)));
58 }
59
ATF_TP_ADD_TCS(tp)60 ATF_TP_ADD_TCS(tp)
61 {
62 ATF_TP_ADD_TC(tp, fionread);
63 return (atf_no_error());
64 }
65