xref: /freebsd-src/tests/sys/kern/tty_pts.c (revision 30189156d325fbcc9d1997d791daedc9fa3bed20)
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