xref: /openbsd-src/regress/sys/kern/pledge/generic/pty.c (revision 7a7077c028cf38d6f086fdf15b487a0ad276c621)
1*7a7077c0Santon /*	$OpenBSD: pty.c,v 1.1 2024/06/03 08:02:22 anton Exp $	*/
2*7a7077c0Santon 
3*7a7077c0Santon #include <sys/ioctl.h>
4*7a7077c0Santon 
5*7a7077c0Santon #include <err.h>
6*7a7077c0Santon #include <fcntl.h>
7*7a7077c0Santon #include <stdlib.h>
8*7a7077c0Santon #include <unistd.h>
9*7a7077c0Santon 
10*7a7077c0Santon #include "pty.h"
11*7a7077c0Santon 
12*7a7077c0Santon int
pty_open(struct pty * pty)13*7a7077c0Santon pty_open(struct pty *pty)
14*7a7077c0Santon {
15*7a7077c0Santon 	int master, slave;
16*7a7077c0Santon 
17*7a7077c0Santon 	master = posix_openpt(O_RDWR);
18*7a7077c0Santon 	if (master == -1) {
19*7a7077c0Santon 		warn("posix_openpt");
20*7a7077c0Santon 		return 1;
21*7a7077c0Santon 	}
22*7a7077c0Santon 	if (grantpt(master) == -1) {
23*7a7077c0Santon 		warn("grantpt");
24*7a7077c0Santon 		return 1;
25*7a7077c0Santon 	}
26*7a7077c0Santon 	if (unlockpt(master) == -1) {
27*7a7077c0Santon 		warn("unlockpt");
28*7a7077c0Santon 		return 1;
29*7a7077c0Santon 	}
30*7a7077c0Santon 
31*7a7077c0Santon 	slave = open(ptsname(master), O_RDWR);
32*7a7077c0Santon 	if (slave == -1) {
33*7a7077c0Santon 		warn("%s", ptsname(master));
34*7a7077c0Santon 		return 1;
35*7a7077c0Santon 	}
36*7a7077c0Santon 
37*7a7077c0Santon 	pty->master = master;
38*7a7077c0Santon 	pty->slave = slave;
39*7a7077c0Santon 	return 0;
40*7a7077c0Santon }
41*7a7077c0Santon 
42*7a7077c0Santon void
pty_close(struct pty * pty)43*7a7077c0Santon pty_close(struct pty *pty)
44*7a7077c0Santon {
45*7a7077c0Santon 	close(pty->slave);
46*7a7077c0Santon 	close(pty->master);
47*7a7077c0Santon }
48*7a7077c0Santon 
49*7a7077c0Santon /*
50*7a7077c0Santon  * Disconnect the controlling tty, if present.
51*7a7077c0Santon  */
52*7a7077c0Santon int
pty_detach(struct pty * pty)53*7a7077c0Santon pty_detach(struct pty *pty)
54*7a7077c0Santon {
55*7a7077c0Santon 	int fd;
56*7a7077c0Santon 
57*7a7077c0Santon 	fd = open("/dev/tty", O_RDWR | O_NOCTTY);
58*7a7077c0Santon 	if (fd >= 0) {
59*7a7077c0Santon 		(void)ioctl(fd, TIOCNOTTY, NULL);
60*7a7077c0Santon 		close(fd);
61*7a7077c0Santon 	}
62*7a7077c0Santon 	return 0;
63*7a7077c0Santon }
64*7a7077c0Santon 
65*7a7077c0Santon /*
66*7a7077c0Santon  * Connect the slave as the controlling tty.
67*7a7077c0Santon  */
68*7a7077c0Santon int
pty_attach(struct pty * pty)69*7a7077c0Santon pty_attach(struct pty *pty)
70*7a7077c0Santon {
71*7a7077c0Santon 	if (ioctl(pty->slave, TIOCSCTTY, NULL) == -1) {
72*7a7077c0Santon 		warn("TIOCSCTTY");
73*7a7077c0Santon 		return 1;
74*7a7077c0Santon 	}
75*7a7077c0Santon 	return 0;
76*7a7077c0Santon }
77*7a7077c0Santon 
78*7a7077c0Santon int
pty_drain(struct pty * pty)79*7a7077c0Santon pty_drain(struct pty *pty)
80*7a7077c0Santon {
81*7a7077c0Santon 	for (;;) {
82*7a7077c0Santon 		char *buf = &pty->buf.storage[pty->buf.len];
83*7a7077c0Santon 		size_t bufsize = sizeof(pty->buf.storage) - pty->buf.len;
84*7a7077c0Santon 		ssize_t n;
85*7a7077c0Santon 
86*7a7077c0Santon 		n = read(pty->master, buf, bufsize);
87*7a7077c0Santon 		if (n == -1) {
88*7a7077c0Santon 			warn("read");
89*7a7077c0Santon 			return 1;
90*7a7077c0Santon 		}
91*7a7077c0Santon 		if (n == 0)
92*7a7077c0Santon 			break;
93*7a7077c0Santon 
94*7a7077c0Santon 		/* Ensure space for NUL-terminator. */
95*7a7077c0Santon 		if ((size_t)n >= bufsize) {
96*7a7077c0Santon 			warnx("pty buffer too small");
97*7a7077c0Santon 			return 1;
98*7a7077c0Santon 		}
99*7a7077c0Santon 		pty->buf.len += n;
100*7a7077c0Santon 	}
101*7a7077c0Santon 
102*7a7077c0Santon 	return 0;
103*7a7077c0Santon }
104