1 /*
2 *
3 * Copyright (c) International Business Machines Corp., 2002
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13 * the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20 /* 12/23/2002 Port to LTP robbiew@us.ibm.com */
21 /* 06/30/2001 Port to Linux nsharoff@us.ibm.com */
22
23 #include <errno.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <termio.h>
28 #include <fcntl.h>
29 #include <sys/stat.h>
30 #include <sys/poll.h>
31 #include <sys/types.h>
32
33 #ifndef _GNU_SOURCE
34 #define _GNU_SOURCE 1
35 #endif
36
37 /** LTP Port **/
38 #include "test.h"
39 #include "safe_macros.h"
40
41 char *TCID = "ptem01"; /* Test program identifier. */
42 int TST_TOTAL = 6; /* Total number of test cases. */
43 /**************/
44
45 /*
46 * pty master clone device
47 */
48 #define MASTERCLONE "/dev/ptmx"
49
50 #define BUFSZ 4096
51
52 /*
53 * test termio/termios ioctls
54 */
test1(void)55 int test1(void)
56 {
57 int masterfd, slavefd;
58 char *slavename;
59 struct termio termio;
60 struct termios termios;
61
62 masterfd = SAFE_OPEN(NULL, MASTERCLONE, O_RDWR);
63
64 slavename = ptsname(masterfd);
65 if (slavename == NULL) {
66 tst_brkm(TBROK | TERRNO, NULL, "ptsname() call failed");
67 }
68
69 if (grantpt(masterfd) != 0) {
70 tst_brkm(TBROK | TERRNO, NULL, "grantpt() call failed");
71 }
72
73 if (unlockpt(masterfd) != 0) {
74 tst_brkm(TBROK, NULL, "unlockpt() call failed");
75 }
76
77 if ((slavefd = open(slavename, O_RDWR)) < 0) {
78 tst_brkm(TFAIL, NULL, "Could not open %s", slavename);
79 }
80
81 if (ioctl(slavefd, TCGETS, &termios) != 0) {
82 tst_brkm(TFAIL, NULL, "TCGETS");
83 }
84
85 if (ioctl(slavefd, TCSETS, &termios) != 0) {
86 tst_brkm(TFAIL, NULL, "TCSETS");
87 }
88
89 if (ioctl(slavefd, TCSETSW, &termios) != 0) {
90 tst_brkm(TFAIL, NULL, "TCSETSW");
91 }
92
93 if (ioctl(slavefd, TCSETSF, &termios) != 0) {
94 tst_brkm(TFAIL, NULL, "TCSETSF");
95 }
96
97 if (ioctl(slavefd, TCSETS, &termios) != 0) {
98 tst_brkm(TFAIL, NULL, "TCSETS");
99 }
100
101 if (ioctl(slavefd, TCGETA, &termio) != 0) {
102 tst_brkm(TFAIL, NULL, "TCGETA");
103 }
104
105 if (ioctl(slavefd, TCSETA, &termio) != 0) {
106 tst_brkm(TFAIL, NULL, "TCSETA");
107 }
108
109 if (ioctl(slavefd, TCSETAW, &termio) != 0) {
110 tst_brkm(TFAIL, NULL, "TCSETAW");
111 }
112
113 if (ioctl(slavefd, TCSETAF, &termio) != 0) {
114 tst_brkm(TFAIL, NULL, "TCSETAF");
115 }
116
117 if (close(slavefd) != 0) {
118 tst_brkm(TBROK, NULL, "close slave");
119 }
120
121 if (close(masterfd) != 0) {
122 tst_brkm(TBROK, NULL, "close master");
123 }
124 tst_resm(TPASS, "test1");
125
126 /** NOT REACHED **/
127 return 0;
128 }
129
130 /*
131 * test window size setting and getting
132 */
test2(void)133 int test2(void)
134 {
135 int masterfd, slavefd;
136 char *slavename;
137 struct winsize wsz;
138 struct winsize wsz1 = { 24, 80, 5, 10 };
139 struct winsize wsz2 = { 60, 100, 11, 777 };
140
141 masterfd = SAFE_OPEN(NULL, MASTERCLONE, O_RDWR);
142
143 slavename = ptsname(masterfd);
144 if (slavename == NULL) {
145 tst_brkm(TBROK | TERRNO, NULL, "ptsname() call failed");
146 }
147
148 if (grantpt(masterfd) != 0) {
149 tst_brkm(TBROK | TERRNO, NULL, "grantpt() call failed");
150 }
151
152 if (unlockpt(masterfd) != 0) {
153 tst_brkm(TBROK, NULL, "unlockpt() call failed");
154 }
155
156 if ((slavefd = open(slavename, O_RDWR)) < 0) {
157 tst_brkm(TBROK, NULL, "Could not open %s", slavename);
158 }
159
160 if (ioctl(masterfd, TIOCSWINSZ, &wsz1) != 0) {
161 tst_brkm(TFAIL, NULL, "TIOCSWINSZ");
162 }
163
164 if (ioctl(slavefd, TIOCGWINSZ, &wsz) != 0) {
165 tst_brkm(TFAIL, NULL, "TIOCGWINSZ");
166 }
167
168 if (wsz.ws_row != wsz1.ws_row || wsz.ws_col != wsz1.ws_col ||
169 wsz.ws_xpixel != wsz1.ws_xpixel ||
170 wsz.ws_ypixel != wsz1.ws_ypixel) {
171 tst_brkm(TFAIL, NULL, "unexpected window size returned");
172 }
173
174 if (ioctl(masterfd, TIOCGWINSZ, &wsz) != 0) {
175 tst_brkm(TFAIL, NULL, "TIOCGWINSZ");
176 }
177
178 if (wsz.ws_row != wsz1.ws_row || wsz.ws_col != wsz1.ws_col ||
179 wsz.ws_xpixel != wsz1.ws_xpixel ||
180 wsz.ws_ypixel != wsz1.ws_ypixel) {
181 tst_brkm(TFAIL, NULL, "unexpected window size returned");
182 }
183
184 if (ioctl(slavefd, TIOCSWINSZ, &wsz2) != 0) {
185 tst_brkm(TFAIL, NULL, "TIOCSWINSZ");
186 }
187
188 if (ioctl(slavefd, TIOCGWINSZ, &wsz) != 0) {
189 tst_brkm(TFAIL, NULL, "TIOCGWINSZ");
190 }
191
192 if (wsz.ws_row != wsz2.ws_row || wsz.ws_col != wsz2.ws_col ||
193 wsz.ws_xpixel != wsz2.ws_xpixel ||
194 wsz.ws_ypixel != wsz2.ws_ypixel) {
195 tst_brkm(TFAIL, NULL, "unexpected window size returned");
196 }
197
198 if (close(slavefd) != 0) {
199 tst_brkm(TBROK, NULL, "close");
200 }
201
202 if (close(masterfd) != 0) {
203 tst_brkm(TBROK, NULL, "close");
204 }
205 tst_resm(TPASS, "test2");
206
207 /** NOT REACHED **/
208 return 0;
209 }
210
211 /*
212 * test sending a break
213 */
test3(void)214 int test3(void)
215 {
216 int masterfd, slavefd;
217 char *slavename;
218
219 masterfd = SAFE_OPEN(NULL, MASTERCLONE, O_RDWR);
220
221 slavename = ptsname(masterfd);
222 if (slavename == NULL) {
223 tst_brkm(TBROK | TERRNO, NULL, "ptsname() call failed");
224 }
225
226 if (grantpt(masterfd) != 0) {
227 tst_brkm(TBROK | TERRNO, NULL, "grantpt() call failed");
228 }
229
230 if (unlockpt(masterfd) != 0) {
231 tst_brkm(TBROK, NULL, "unlockpt() call failed");
232 }
233
234 if ((slavefd = open(slavename, O_RDWR)) < 0) {
235 tst_brkm(TBROK, NULL, "Could not open %s", slavename);
236 }
237
238 if (tcsendbreak(masterfd, 10) != 0) {
239 tst_brkm(TFAIL, NULL, "tcsendbreak");
240 }
241
242 if (tcsendbreak(slavefd, 10) != 0) {
243 tst_brkm(TFAIL, NULL, "tcsendbreak");
244 }
245
246 if (close(slavefd) != 0) {
247 tst_brkm(TBROK, NULL, "close slave");
248 }
249
250 if (close(masterfd) != 0) {
251 tst_brkm(TBROK, NULL, "close master");
252 }
253 tst_resm(TPASS, "test3");
254
255 /** NOT REACHED **/
256 return 0;
257 }
258
259 /*
260 * test multiple opens of slave side
261 */
test4(void)262 int test4(void)
263 {
264 int masterfd, slavefd, slavefd2, slavefd3;
265 char *slavename;
266
267 masterfd = SAFE_OPEN(NULL, MASTERCLONE, O_RDWR);
268
269 slavename = ptsname(masterfd);
270 if (slavename == NULL) {
271 tst_brkm(TBROK | TERRNO, NULL, "ptsname() call failed");
272 }
273
274 if (grantpt(masterfd) != 0) {
275 tst_brkm(TBROK | TERRNO, NULL, "grantpt() call failed");
276 }
277
278 if (unlockpt(masterfd) != 0) {
279 tst_brkm(TBROK, NULL, "unlockpt() call failed");
280 }
281
282 if ((slavefd = open(slavename, O_RDWR)) < 0) {
283 tst_brkm(TBROK, NULL, "Could not open %s", slavename);
284 }
285
286 if ((slavefd2 = open(slavename, O_RDWR)) < 0) {
287 tst_brkm(TFAIL, NULL, "Could not open %s (again)", slavename);
288 }
289
290 if ((slavefd3 = open(slavename, O_RDWR)) < 0) {
291 tst_brkm(TFAIL, NULL, "Could not open %s (once more)",
292 slavename);
293 }
294
295 if (close(slavefd) != 0) {
296 tst_brkm(TBROK, NULL, "close slave");
297 }
298 if (close(slavefd2) != 0) {
299 tst_brkm(TBROK, NULL, "close slave again");
300 }
301 if (close(slavefd3) != 0) {
302 tst_brkm(TBROK, NULL, "close slave once more");
303 }
304 if (close(masterfd) != 0) {
305 tst_brkm(TBROK, NULL, "close master");
306 }
307 tst_resm(TPASS, "test4");
308
309 /** NOT REACHED **/
310 return 0;
311 }
312
313 #define NUMOPENS 6
314
315 /*
316 * test several simultaneous opens
317 */
test5(void)318 int test5(void)
319 {
320 static int masterfd[NUMOPENS];
321 static int slavefd[NUMOPENS];
322 char *slavename;
323 int i;
324
325 for (i = 0; i < NUMOPENS; ++i) {
326 masterfd[i] = open(MASTERCLONE, O_RDWR);
327 if (masterfd[i] < 0) {
328 tst_resm(TBROK, "%s", MASTERCLONE);
329 tst_resm(TBROK, "out of ptys");
330 for (i = 0; i < NUMOPENS; ++i) {
331 if (masterfd[i] != 0) {
332 (void)close(masterfd[i]);
333 }
334 if (slavefd[i] != 0) {
335 (void)close(slavefd[i]);
336 }
337 }
338 tst_exit();
339 }
340
341 slavename = ptsname(masterfd[i]);
342 if (slavename == NULL) {
343 tst_brkm(TBROK | TERRNO, NULL,
344 "ptsname() call failed");
345 }
346
347 if (grantpt(masterfd[i]) != 0) {
348 tst_brkm(TBROK | TERRNO, NULL,
349 "grantpt() call failed");
350 }
351
352 if (unlockpt(masterfd[i]) != 0) {
353 tst_brkm(TBROK, NULL, "unlockpt() call failed");
354 }
355
356 if ((slavefd[i] = open(slavename, O_RDWR)) < 0) {
357 tst_brkm(TFAIL, NULL,
358 "Iteration %d: Could not open %s", i,
359 slavename);
360 }
361
362 }
363
364 for (i = 0; i < NUMOPENS; ++i) {
365 if (close(slavefd[i]) != 0) {
366 tst_brkm(TBROK, NULL, "Iteration %d: close slave", i);
367 }
368 if (close(masterfd[i]) != 0) {
369 tst_brkm(TBROK, NULL, "close master");
370 }
371 }
372 tst_resm(TPASS, "test5");
373
374 /** NOT REACHED **/
375 return 0;
376 }
377
378 /*
379 * test hangup semantics
380 */
test6(void)381 int test6(void)
382 {
383 static int masterfd;
384 static int slavefd;
385 char *slavename;
386 struct termios termios;
387
388 masterfd = SAFE_OPEN(NULL, MASTERCLONE, O_RDWR);
389
390 slavename = ptsname(masterfd);
391 if (slavename == NULL) {
392 tst_brkm(TBROK | TERRNO, NULL, "ptsname() call failed");
393 }
394
395 if (grantpt(masterfd) != 0) {
396 tst_brkm(TBROK | TERRNO, NULL, "grantpt() call failed");
397 }
398
399 if (unlockpt(masterfd) != 0) {
400 tst_brkm(TBROK, NULL, "unlockpt() call failed");
401 }
402
403 if ((slavefd = open(slavename, O_RDWR)) < 0) {
404 tst_brkm(TBROK, NULL, "Could not open %s", slavename);
405 }
406
407 if (ioctl(slavefd, TCGETS, &termios) != 0) {
408 tst_brkm(TFAIL, NULL, "TCGETS");
409 }
410
411 termios.c_cflag &= ~CBAUD;
412 termios.c_cflag |= B0 & CBAUD;
413 if (ioctl(slavefd, TCSETS, &termios) != 0) {
414 tst_brkm(TFAIL, NULL, "TCGETS");
415 }
416
417 if (close(slavefd) != 0) {
418 tst_brkm(TBROK, NULL, "close");
419 }
420 if (close(masterfd) != 0) {
421 tst_brkm(TBROK, NULL, "close");
422 }
423 tst_resm(TPASS, "test6");
424
425 /** NOT REACHED **/
426 return 0;
427 }
428
429 /*
430 * main test driver
431 */
main(int argc,char ** argv)432 int main(int argc, char **argv)
433 {
434 test1();
435 test2();
436 test3();
437 test4();
438 test5();
439 test6();
440 /*
441 * all done
442 */
443 tst_exit();
444 }
445