diff options
Diffstat (limited to 'contrib/netbsd-tests/kernel/tty/t_pr.c')
-rw-r--r-- | contrib/netbsd-tests/kernel/tty/t_pr.c | 186 |
1 files changed, 186 insertions, 0 deletions
diff --git a/contrib/netbsd-tests/kernel/tty/t_pr.c b/contrib/netbsd-tests/kernel/tty/t_pr.c new file mode 100644 index 0000000..c590ea5 --- /dev/null +++ b/contrib/netbsd-tests/kernel/tty/t_pr.c @@ -0,0 +1,186 @@ +/* $NetBSD: t_pr.c,v 1.7 2011/04/26 20:42:01 martin Exp $ */ + +/*- + * Copyright (c) 2010, 2011 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Antti Kantee <pooka@NetBSD.org> and Martin Husemann <martin@NetBSD.org>. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/types.h> +#include <sys/ioctl.h> +#include <sys/tty.h> + +#include <atf-c.h> +#include <fcntl.h> + +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <rump/rump.h> +#include <rump/rump_syscalls.h> + +static int +sendsome(int from, int to) +{ + size_t i; + ssize_t cnt; + static const char msg[] = "hello world\n"; + char buf[sizeof(msg)+10]; + + memset(buf, 0, sizeof(buf)); + rump_sys_write(from, msg, strlen(msg)); + cnt = rump_sys_read(to, buf, sizeof(buf)); + if (cnt < (ssize_t)strlen(msg)) { + printf("short message read: %zd chars: \"%s\"\n", cnt, buf); + return 1; + } + for (i = 0; i < sizeof(buf); i++) { + if (buf[i] == '\r' || buf[i] == '\n') { + buf[i] = '\n'; + buf[i+1] = '\0'; + break; + } + } + + return strcmp(buf, msg) != 0; +} + +static int +exercise_ptytty(int master, int slave) +{ + int error, flags; + + /* + * send a few bytes from master to slave and read them back + */ + error = sendsome(master, slave); + if (error) + return error; + + flags = FREAD|FWRITE; + rump_sys_ioctl(master, TIOCFLUSH, &flags); + + /* + * and the same in the other direction + */ + error = sendsome(slave, master); + if (error) + return error; + + flags = FREAD|FWRITE; + rump_sys_ioctl(master, TIOCFLUSH, &flags); + return 0; +} + +ATF_TC(client_first); +ATF_TC_HEAD(client_first, tc) +{ + + atf_tc_set_md_var(tc, "descr", + "test basic tty/pty operation when opening client side first"); +} + +ATF_TC_BODY(client_first, tc) +{ + int master, slave, error, v; + + rump_init(); + slave = rump_sys_open("/dev/ttyp1", O_RDWR|O_NONBLOCK); + ATF_CHECK(slave != -1); + + master = rump_sys_open("/dev/ptyp1", O_RDWR); + ATF_CHECK(master != -1); + + v = 0; + rump_sys_ioctl(slave, FIOASYNC, &v); + error = exercise_ptytty(master, slave); + ATF_CHECK(error == 0); + + rump_sys_close(master); + rump_sys_close(slave); +} + +ATF_TC(master_first); +ATF_TC_HEAD(master_first, tc) +{ + + atf_tc_set_md_var(tc, "descr", + "test basic tty/pty operation when opening master side first"); +} + +ATF_TC_BODY(master_first, tc) +{ + int master, slave, error; + + rump_init(); + master = rump_sys_open("/dev/ptyp1", O_RDWR); + ATF_CHECK(master != -1); + + slave = rump_sys_open("/dev/ttyp1", O_RDWR); + ATF_CHECK(slave != -1); + + error = exercise_ptytty(master, slave); + ATF_CHECK(error == 0); + + rump_sys_close(master); + rump_sys_close(slave); +} + +ATF_TC(ptyioctl); +ATF_TC_HEAD(ptyioctl, tc) +{ + + atf_tc_set_md_var(tc, "descr", + "ioctl on pty with client side not open"); +} + +ATF_TC_BODY(ptyioctl, tc) +{ + struct termios tio; + int fd; + + rump_init(); + fd = rump_sys_open("/dev/ptyp1", O_RDWR); + ATF_CHECK(fd != -1); + + /* + * This used to die with null deref under ptcwakeup() + * atf_tc_expect_signal(-1, "PR kern/40688"); + */ + rump_sys_ioctl(fd, TIOCGETA, &tio); + + rump_sys_close(fd); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, ptyioctl); + ATF_TP_ADD_TC(tp, client_first); + ATF_TP_ADD_TC(tp, master_first); + + return atf_no_error(); +} |