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