t_pr.c revision 1.5 1 1.5 martin /* $NetBSD: t_pr.c,v 1.5 2011/04/09 11:55:59 martin Exp $ */
2 1.1 pooka
3 1.1 pooka #include <sys/types.h>
4 1.1 pooka #include <sys/ioctl.h>
5 1.1 pooka #include <sys/tty.h>
6 1.1 pooka
7 1.1 pooka #include <atf-c.h>
8 1.1 pooka #include <fcntl.h>
9 1.1 pooka
10 1.5 martin #include <stdio.h>
11 1.5 martin #include <string.h>
12 1.5 martin #include <errno.h>
13 1.1 pooka #include <rump/rump.h>
14 1.1 pooka #include <rump/rump_syscalls.h>
15 1.1 pooka
16 1.5 martin static bool init_done = false;
17 1.5 martin
18 1.5 martin static void
19 1.5 martin init(void)
20 1.5 martin {
21 1.5 martin if (init_done)
22 1.5 martin return;
23 1.5 martin rump_init();
24 1.5 martin init_done = true;
25 1.5 martin }
26 1.5 martin
27 1.5 martin static int
28 1.5 martin sendsome(int from, int to)
29 1.5 martin {
30 1.5 martin size_t i;
31 1.5 martin ssize_t cnt;
32 1.5 martin static const char msg[] = "hello world\n";
33 1.5 martin char buf[sizeof(msg)+10];
34 1.5 martin
35 1.5 martin memset(buf, 0, sizeof(buf));
36 1.5 martin rump_sys_write(from, msg, strlen(msg));
37 1.5 martin cnt = rump_sys_read(to, buf, sizeof(buf));
38 1.5 martin if (cnt < (ssize_t)strlen(msg)) {
39 1.5 martin printf("short message read: %zd chars: \"%s\"\n", cnt, buf);
40 1.5 martin return 1;
41 1.5 martin }
42 1.5 martin for (i = 0; i < sizeof(buf); i++) {
43 1.5 martin if (buf[i] == '\r' || buf[i] == '\n') {
44 1.5 martin buf[i] = '\n';
45 1.5 martin buf[i+1] = '\0';
46 1.5 martin break;
47 1.5 martin }
48 1.5 martin }
49 1.5 martin
50 1.5 martin return strcmp(buf, msg) != 0;
51 1.5 martin }
52 1.5 martin
53 1.5 martin static int
54 1.5 martin exercise_ptytty(int master, int slave)
55 1.5 martin {
56 1.5 martin int error, flags;
57 1.5 martin
58 1.5 martin /*
59 1.5 martin * send a few bytes from master to slave and read them back
60 1.5 martin */
61 1.5 martin error = sendsome(master, slave);
62 1.5 martin if (error)
63 1.5 martin return error;
64 1.5 martin
65 1.5 martin flags = FREAD|FWRITE;
66 1.5 martin rump_sys_ioctl(master, TIOCFLUSH, &flags);
67 1.5 martin
68 1.5 martin /*
69 1.5 martin * and the same in the other direction
70 1.5 martin */
71 1.5 martin error = sendsome(slave, master);
72 1.5 martin if (error)
73 1.5 martin return error;
74 1.5 martin
75 1.5 martin flags = FREAD|FWRITE;
76 1.5 martin rump_sys_ioctl(master, TIOCFLUSH, &flags);
77 1.5 martin return 0;
78 1.5 martin }
79 1.5 martin
80 1.5 martin ATF_TC(client_first);
81 1.5 martin ATF_TC_HEAD(client_first, tc)
82 1.5 martin {
83 1.5 martin
84 1.5 martin atf_tc_set_md_var(tc, "descr",
85 1.5 martin "test basic tty/pty operation when opening client side first");
86 1.5 martin }
87 1.5 martin
88 1.5 martin ATF_TC_BODY(client_first, tc)
89 1.5 martin {
90 1.5 martin int master, slave, error, v;
91 1.5 martin
92 1.5 martin init();
93 1.5 martin slave = rump_sys_open("/dev/ttyp1", O_RDWR|O_NONBLOCK);
94 1.5 martin ATF_CHECK(slave != -1);
95 1.5 martin
96 1.5 martin master = rump_sys_open("/dev/ptyp1", O_RDWR);
97 1.5 martin ATF_CHECK(master != -1);
98 1.5 martin
99 1.5 martin v = 0;
100 1.5 martin rump_sys_ioctl(slave, FIOASYNC, &v);
101 1.5 martin error = exercise_ptytty(master, slave);
102 1.5 martin ATF_CHECK(error == 0);
103 1.5 martin
104 1.5 martin rump_sys_close(master);
105 1.5 martin rump_sys_close(slave);
106 1.5 martin }
107 1.5 martin
108 1.5 martin ATF_TC(master_first);
109 1.5 martin ATF_TC_HEAD(master_first, tc)
110 1.5 martin {
111 1.5 martin
112 1.5 martin atf_tc_set_md_var(tc, "descr",
113 1.5 martin "test basic tty/pty operation when opening master side first");
114 1.5 martin }
115 1.5 martin
116 1.5 martin ATF_TC_BODY(master_first, tc)
117 1.5 martin {
118 1.5 martin int master, slave, error;
119 1.5 martin
120 1.5 martin init();
121 1.5 martin master = rump_sys_open("/dev/ptyp1", O_RDWR);
122 1.5 martin ATF_CHECK(master != -1);
123 1.5 martin
124 1.5 martin slave = rump_sys_open("/dev/ttyp1", O_RDWR);
125 1.5 martin ATF_CHECK(slave != -1);
126 1.5 martin
127 1.5 martin error = exercise_ptytty(master, slave);
128 1.5 martin ATF_CHECK(error == 0);
129 1.5 martin
130 1.5 martin rump_sys_close(master);
131 1.5 martin rump_sys_close(slave);
132 1.5 martin }
133 1.5 martin
134 1.1 pooka ATF_TC(ptyioctl);
135 1.1 pooka ATF_TC_HEAD(ptyioctl, tc)
136 1.1 pooka {
137 1.1 pooka
138 1.5 martin atf_tc_set_md_var(tc, "descr",
139 1.5 martin "ioctl on pty with client side not open");
140 1.1 pooka }
141 1.1 pooka
142 1.1 pooka ATF_TC_BODY(ptyioctl, tc)
143 1.1 pooka {
144 1.1 pooka struct termios tio;
145 1.1 pooka int fd;
146 1.1 pooka
147 1.5 martin init();
148 1.1 pooka fd = rump_sys_open("/dev/ptyp1", O_RDWR);
149 1.3 christos ATF_CHECK(fd != -1);
150 1.1 pooka
151 1.4 martin /*
152 1.4 martin * This used to die with null deref under ptcwakeup()
153 1.4 martin * atf_tc_expect_signal(-1, "PR kern/40688");
154 1.4 martin */
155 1.1 pooka rump_sys_ioctl(fd, TIOCGETA, &tio);
156 1.5 martin
157 1.5 martin rump_sys_close(fd);
158 1.1 pooka }
159 1.1 pooka
160 1.1 pooka ATF_TP_ADD_TCS(tp)
161 1.1 pooka {
162 1.1 pooka
163 1.1 pooka ATF_TP_ADD_TC(tp, ptyioctl);
164 1.5 martin ATF_TP_ADD_TC(tp, client_first);
165 1.5 martin ATF_TP_ADD_TC(tp, master_first);
166 1.1 pooka
167 1.1 pooka return atf_no_error();
168 1.1 pooka }
169