diff options
author | Todd C. Miller <millert@cvs.openbsd.org> | 2013-01-02 17:54:47 +0000 |
---|---|---|
committer | Todd C. Miller <millert@cvs.openbsd.org> | 2013-01-02 17:54:47 +0000 |
commit | 31047eee00be65ad496c1084d6bd94f1435d2806 (patch) | |
tree | 789059849b789cb3afc7881618e6fb8fa0cae15e /regress/sys/kern | |
parent | 085e5a0dfff321d9929777ec0938fff8c8a7ff17 (diff) |
regress test for pty TTYHOG bug; OK miod@
Diffstat (limited to 'regress/sys/kern')
-rw-r--r-- | regress/sys/kern/Makefile | 4 | ||||
-rw-r--r-- | regress/sys/kern/pty/Makefile | 7 | ||||
-rw-r--r-- | regress/sys/kern/pty/ptyhog.c | 106 |
3 files changed, 115 insertions, 2 deletions
diff --git a/regress/sys/kern/Makefile b/regress/sys/kern/Makefile index 23e794decb6..90e375a67d9 100644 --- a/regress/sys/kern/Makefile +++ b/regress/sys/kern/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.58 2012/04/12 14:00:22 guenther Exp $ +# $OpenBSD: Makefile,v 1.59 2013/01/02 17:54:46 millert Exp $ SUBDIR+= __syscall accept dup2 dup2_self exec_self execve exit extent SUBDIR+= fchdir @@ -9,7 +9,7 @@ SUBDIR+= kqueue mbuf minherit SUBDIR+= main-thread-exited SUBDIR+= mmap mmap2 mmap3 mmap-fail #SUBDIR+= mquery -SUBDIR+= nanosleep noexec pread preadv ptmget pwrite pwritev rcvtimeo +SUBDIR+= nanosleep noexec pread preadv ptmget pty pwrite pwritev rcvtimeo SUBDIR+= rlimit-file signal signal-stress sigsuspend SUBDIR+= syscall sysvmsg sysvsem SUBDIR+= sysvshm unalign unfdpass wait diff --git a/regress/sys/kern/pty/Makefile b/regress/sys/kern/pty/Makefile new file mode 100644 index 00000000000..29e881987df --- /dev/null +++ b/regress/sys/kern/pty/Makefile @@ -0,0 +1,7 @@ +# $OpenBSD: Makefile,v 1.1 2013/01/02 17:54:46 millert Exp $ + +PROG= ptyhog +LDADD+= -lutil +DPADD+= ${LIBUTIL} + +.include <bsd.regress.mk> diff --git a/regress/sys/kern/pty/ptyhog.c b/regress/sys/kern/pty/ptyhog.c new file mode 100644 index 00000000000..3da987a1dc4 --- /dev/null +++ b/regress/sys/kern/pty/ptyhog.c @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2013 Todd C. Miller <Todd.Miller@courtesan.com> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/types.h> +#include <sys/wait.h> + +#include <err.h> +#include <errno.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <termios.h> +#include <unistd.h> +#include <util.h> + +#define BUF_SIZE 1024 + +/* + * Exercise a bug in ptcwrite() when we git the TTYHOG limit if + * the tty is in raw mode. + */ +static void sigalrm(int signo) +{ + /* just return */ + return; +} + +int +main(int argc, char *argv[]) +{ + struct sigaction sa; + unsigned char buf[BUF_SIZE]; + int mfd, sfd, status; + struct termios term; + size_t i, nwritten = 0, nread= 0; + ssize_t n; + + /* + * Open pty and set slave to raw mode. + */ + if (openpty(&mfd, &sfd, NULL, NULL, NULL) == -1) + err(1, "openpty"); + if (tcgetattr(sfd, &term) == -1) + err(1, "tcgetattr"); + cfmakeraw(&term); + if (tcsetattr(sfd, TCSAFLUSH, &term) == -1) + err(1, "tcsetattr"); + + switch (fork()) { + case -1: + err(1, "fork"); + case 0: + /* prevent a hang if the bug is present */ + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = sigalrm; + sigemptyset(&sa.sa_mask); + sigaction(SIGALRM, &sa, NULL); + alarm(5); + + /* child, read data from slave */ + do { + n = read(sfd, buf + nread, sizeof(buf) - nread); + if (n == -1) { + if (errno == EINTR) + errx(1, "timed out @ %zd", nread); + err(1, "read @ %zd", nread); + } + nread += n; + } while (nread != sizeof(buf)); + for (i = 0; i < sizeof(buf); i++) { + if (buf[i] != (i & 0xff)) { + errx(1, "buffer corrupted at %zd " + "(got %u, expected %zd)", i, + buf[i], (i & 0xff)); + } + } + printf("all data received\n"); + exit(0); + default: + /* parent, write data to master */ + for (i = 0; i < sizeof(buf); i++) + buf[i] = (i & 0xff); + do { + n = write(mfd, buf + nwritten, sizeof(buf) - nwritten); + if (n == -1) + err(1, "write @ %zd", nwritten); + nwritten += n; + } while (nwritten != sizeof(buf)); + wait(&status); + exit(WIFEXITED(status) ? WEXITSTATUS(status) : WTERMSIG(status) + 128); + } +} |