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