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