xref: /openbsd-src/regress/sys/kern/pty/ptyhog.c (revision bf198cc6eba0ca1f6d79f71e8e2243d386241fa8)
187ea74dfSmillert /*
2*bf198cc6Smillert  * Copyright (c) 2013 Todd C. Miller <millert@openbsd.org>
387ea74dfSmillert  *
487ea74dfSmillert  * Permission to use, copy, modify, and distribute this software for any
587ea74dfSmillert  * purpose with or without fee is hereby granted, provided that the above
687ea74dfSmillert  * copyright notice and this permission notice appear in all copies.
787ea74dfSmillert  *
887ea74dfSmillert  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
987ea74dfSmillert  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1087ea74dfSmillert  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1187ea74dfSmillert  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1287ea74dfSmillert  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1387ea74dfSmillert  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1487ea74dfSmillert  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1587ea74dfSmillert  */
1687ea74dfSmillert 
1787ea74dfSmillert #include <sys/types.h>
1887ea74dfSmillert #include <sys/wait.h>
1987ea74dfSmillert 
2087ea74dfSmillert #include <err.h>
2187ea74dfSmillert #include <errno.h>
2287ea74dfSmillert #include <signal.h>
2387ea74dfSmillert #include <stdio.h>
2487ea74dfSmillert #include <stdlib.h>
2587ea74dfSmillert #include <string.h>
2687ea74dfSmillert #include <termios.h>
2787ea74dfSmillert #include <unistd.h>
2887ea74dfSmillert #include <util.h>
2987ea74dfSmillert 
3087ea74dfSmillert #define BUF_SIZE 1024
3187ea74dfSmillert 
3287ea74dfSmillert /*
33c5b7b152Sjasper  * Exercise a bug in ptcwrite() when we hit the TTYHOG limit if
3487ea74dfSmillert  * the tty is in raw mode.
3587ea74dfSmillert  */
sigalrm(int signo)3687ea74dfSmillert static void sigalrm(int signo)
3787ea74dfSmillert {
3887ea74dfSmillert 	/* just return */
3987ea74dfSmillert 	return;
4087ea74dfSmillert }
4187ea74dfSmillert 
4287ea74dfSmillert int
main(int argc,char * argv[])4387ea74dfSmillert main(int argc, char *argv[])
4487ea74dfSmillert {
4587ea74dfSmillert 	struct sigaction sa;
4687ea74dfSmillert         unsigned char buf[BUF_SIZE];
4787ea74dfSmillert         int mfd, sfd, status;
4887ea74dfSmillert         struct termios term;
4987ea74dfSmillert         size_t i, nwritten = 0, nread= 0;
5087ea74dfSmillert         ssize_t n;
5187ea74dfSmillert 
5287ea74dfSmillert 	/*
5387ea74dfSmillert 	 * Open pty and set slave to raw mode.
5487ea74dfSmillert 	 */
5587ea74dfSmillert         if (openpty(&mfd, &sfd, NULL, NULL, NULL) == -1)
5687ea74dfSmillert 		err(1, "openpty");
5787ea74dfSmillert         if (tcgetattr(sfd, &term) == -1)
5887ea74dfSmillert                 err(1, "tcgetattr");
5987ea74dfSmillert         cfmakeraw(&term);
6087ea74dfSmillert         if (tcsetattr(sfd, TCSAFLUSH, &term) == -1)
6187ea74dfSmillert                 err(1, "tcsetattr");
6287ea74dfSmillert 
6387ea74dfSmillert 	switch (fork()) {
6487ea74dfSmillert 	case -1:
6587ea74dfSmillert 		err(1, "fork");
6687ea74dfSmillert 	case 0:
6787ea74dfSmillert 		/* prevent a hang if the bug is present */
6887ea74dfSmillert 		memset(&sa, 0, sizeof(sa));
6987ea74dfSmillert 		sa.sa_handler = sigalrm;
7087ea74dfSmillert 		sigemptyset(&sa.sa_mask);
7187ea74dfSmillert 		sigaction(SIGALRM, &sa, NULL);
7287ea74dfSmillert 		alarm(5);
7387ea74dfSmillert 
7487ea74dfSmillert 		/* child, read data from slave */
7587ea74dfSmillert 		do {
7687ea74dfSmillert 			n = read(sfd, buf + nread, sizeof(buf) - nread);
7787ea74dfSmillert 			if (n == -1) {
7887ea74dfSmillert 				if (errno == EINTR)
7987ea74dfSmillert 					errx(1, "timed out @ %zd", nread);
8087ea74dfSmillert 				err(1, "read @ %zd", nread);
8187ea74dfSmillert 			}
8287ea74dfSmillert 			nread += n;
8387ea74dfSmillert 		} while (nread != sizeof(buf));
8487ea74dfSmillert 		for (i = 0; i < sizeof(buf); i++) {
8587ea74dfSmillert 			if (buf[i] != (i & 0xff)) {
8687ea74dfSmillert 				errx(1, "buffer corrupted at %zd "
8787ea74dfSmillert 				    "(got %u, expected %zd)", i,
8887ea74dfSmillert 				    buf[i], (i & 0xff));
8987ea74dfSmillert 			}
9087ea74dfSmillert 		}
9187ea74dfSmillert 		printf("all data received\n");
9287ea74dfSmillert 		exit(0);
9387ea74dfSmillert 	default:
9487ea74dfSmillert 		/* parent, write data to master */
9587ea74dfSmillert 		for (i = 0; i < sizeof(buf); i++)
9687ea74dfSmillert 			buf[i] = (i & 0xff);
9787ea74dfSmillert 		do {
9887ea74dfSmillert 			n = write(mfd, buf + nwritten, sizeof(buf) - nwritten);
9987ea74dfSmillert 			if (n == -1)
10087ea74dfSmillert 				err(1, "write @ %zd", nwritten);
10187ea74dfSmillert 			nwritten += n;
10287ea74dfSmillert 		} while (nwritten != sizeof(buf));
10387ea74dfSmillert 		wait(&status);
10487ea74dfSmillert 		exit(WIFEXITED(status) ? WEXITSTATUS(status) : WTERMSIG(status) + 128);
10587ea74dfSmillert 	}
10687ea74dfSmillert }
107