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
40 char *TCID = "ptem01"; /* Test program identifier. */
41 int TST_TOTAL = 6; /* Total number of test cases. */
42 /**************/
43
44 /*
45 * pty master clone device
46 */
47 #define MASTERCLONE "/dev/ptmx"
48
49 #define BUFSZ 4096
50
51 /*
52 * test termio/termios ioctls
53 */
test1(void)54 int test1(void)
55 {
56 int masterfd, slavefd;
57 char *slavename;
58 struct termio termio;
59 struct termios termios;
60
61 masterfd = open(MASTERCLONE, O_RDWR);
62 if (masterfd < 0) {
63 tst_brkm(TBROK, NULL, "%s", MASTERCLONE);
64 }
65
66 slavename = ptsname(masterfd);
67 if (slavename == NULL) {
68 tst_brkm(TBROK | TERRNO, NULL, "ptsname() call failed");
69 }
70
71 if (grantpt(masterfd) != 0) {
72 tst_brkm(TBROK | TERRNO, NULL, "grantpt() call failed");
73 }
74
75 if (unlockpt(masterfd) != 0) {
76 tst_brkm(TBROK, NULL, "unlockpt() call failed");
77 }
78
79 if ((slavefd = open(slavename, O_RDWR)) < 0) {
80 tst_brkm(TFAIL, NULL, "Could not open %s", slavename);
81 }
82
83 if (ioctl(slavefd, TCGETS, &termios) != 0) {
84 tst_brkm(TFAIL, NULL, "TCGETS");
85 }
86
87 if (ioctl(slavefd, TCSETS, &termios) != 0) {
88 tst_brkm(TFAIL, NULL, "TCSETS");
89 }
90
91 if (ioctl(slavefd, TCSETSW, &termios) != 0) {
92 tst_brkm(TFAIL, NULL, "TCSETSW");
93 }
94
95 if (ioctl(slavefd, TCSETSF, &termios) != 0) {
96 tst_brkm(TFAIL, NULL, "TCSETSF");
97 }
98
99 if (ioctl(slavefd, TCSETS, &termios) != 0) {
100 tst_brkm(TFAIL, NULL, "TCSETS");
101 }
102
103 if (ioctl(slavefd, TCGETA, &termio) != 0) {
104 tst_brkm(TFAIL, NULL, "TCGETA");
105 }
106
107 if (ioctl(slavefd, TCSETA, &termio) != 0) {
108 tst_brkm(TFAIL, NULL, "TCSETA");
109 }
110
111 if (ioctl(slavefd, TCSETAW, &termio) != 0) {
112 tst_brkm(TFAIL, NULL, "TCSETAW");
113 }
114
115 if (ioctl(slavefd, TCSETAF, &termio) != 0) {
116 tst_brkm(TFAIL, NULL, "TCSETAF");
117 }
118
119 if (close(slavefd) != 0) {
120 tst_brkm(TBROK, NULL, "close slave");
121 }
122
123 if (close(masterfd) != 0) {
124 tst_brkm(TBROK, NULL, "close master");
125 }
126 tst_resm(TPASS, "test1");
127
128 /** NOT REACHED **/
129 return 0;
130 }
131
132 /*
133 * test window size setting and getting
134 */
test2(void)135 int test2(void)
136 {
137 int masterfd, slavefd;
138 char *slavename;
139 struct winsize wsz;
140 struct winsize wsz1 = { 24, 80, 5, 10 };
141 struct winsize wsz2 = { 60, 100, 11, 777 };
142
143 masterfd = open(MASTERCLONE, O_RDWR);
144 if (masterfd < 0) {
145 tst_brkm(TBROK, NULL, "%s", MASTERCLONE);
146 }
147
148 slavename = ptsname(masterfd);
149 if (slavename == NULL) {
150 tst_brkm(TBROK | TERRNO, NULL, "ptsname() call failed");
151 }
152
153 if (grantpt(masterfd) != 0) {
154 tst_brkm(TBROK | TERRNO, NULL, "grantpt() call failed");
155 }
156
157 if (unlockpt(masterfd) != 0) {
158 tst_brkm(TBROK, NULL, "unlockpt() call failed");
159 }
160
161 if ((slavefd = open(slavename, O_RDWR)) < 0) {
162 tst_brkm(TBROK, NULL, "Could not open %s", slavename);
163 }
164
165 if (ioctl(masterfd, TIOCSWINSZ, &wsz1) != 0) {
166 tst_brkm(TFAIL, NULL, "TIOCSWINSZ");
167 }
168
169 if (ioctl(slavefd, TIOCGWINSZ, &wsz) != 0) {
170 tst_brkm(TFAIL, NULL, "TIOCGWINSZ");
171 }
172
173 if (wsz.ws_row != wsz1.ws_row || wsz.ws_col != wsz1.ws_col ||
174 wsz.ws_xpixel != wsz1.ws_xpixel ||
175 wsz.ws_ypixel != wsz1.ws_ypixel) {
176 tst_brkm(TFAIL, NULL, "unexpected window size returned");
177 }
178
179 if (ioctl(masterfd, TIOCGWINSZ, &wsz) != 0) {
180 tst_brkm(TFAIL, NULL, "TIOCGWINSZ");
181 }
182
183 if (wsz.ws_row != wsz1.ws_row || wsz.ws_col != wsz1.ws_col ||
184 wsz.ws_xpixel != wsz1.ws_xpixel ||
185 wsz.ws_ypixel != wsz1.ws_ypixel) {
186 tst_brkm(TFAIL, NULL, "unexpected window size returned");
187 }
188
189 if (ioctl(slavefd, TIOCSWINSZ, &wsz2) != 0) {
190 tst_brkm(TFAIL, NULL, "TIOCSWINSZ");
191 }
192
193 if (ioctl(slavefd, TIOCGWINSZ, &wsz) != 0) {
194 tst_brkm(TFAIL, NULL, "TIOCGWINSZ");
195 }
196
197 if (wsz.ws_row != wsz2.ws_row || wsz.ws_col != wsz2.ws_col ||
198 wsz.ws_xpixel != wsz2.ws_xpixel ||
199 wsz.ws_ypixel != wsz2.ws_ypixel) {
200 tst_brkm(TFAIL, NULL, "unexpected window size returned");
201 }
202
203 if (close(slavefd) != 0) {
204 tst_brkm(TBROK, NULL, "close");
205 }
206
207 if (close(masterfd) != 0) {
208 tst_brkm(TBROK, NULL, "close");
209 }
210 tst_resm(TPASS, "test2");
211
212 /** NOT REACHED **/
213 return 0;
214 }
215
216 /*
217 * test sending a break
218 */
test3(void)219 int test3(void)
220 {
221 int masterfd, slavefd;
222 char *slavename;
223
224 masterfd = open(MASTERCLONE, O_RDWR);
225 if (masterfd < 0) {
226 tst_brkm(TBROK, NULL, "%s", MASTERCLONE);
227 }
228
229 slavename = ptsname(masterfd);
230 if (slavename == NULL) {
231 tst_brkm(TBROK | TERRNO, NULL, "ptsname() call failed");
232 }
233
234 if (grantpt(masterfd) != 0) {
235 tst_brkm(TBROK | TERRNO, NULL, "grantpt() call failed");
236 }
237
238 if (unlockpt(masterfd) != 0) {
239 tst_brkm(TBROK, NULL, "unlockpt() call failed");
240 }
241
242 if ((slavefd = open(slavename, O_RDWR)) < 0) {
243 tst_brkm(TBROK, NULL, "Could not open %s", slavename);
244 }
245
246 if (tcsendbreak(masterfd, 10) != 0) {
247 tst_brkm(TFAIL, NULL, "tcsendbreak");
248 }
249
250 if (tcsendbreak(slavefd, 10) != 0) {
251 tst_brkm(TFAIL, NULL, "tcsendbreak");
252 }
253
254 if (close(slavefd) != 0) {
255 tst_brkm(TBROK, NULL, "close slave");
256 }
257
258 if (close(masterfd) != 0) {
259 tst_brkm(TBROK, NULL, "close master");
260 }
261 tst_resm(TPASS, "test3");
262
263 /** NOT REACHED **/
264 return 0;
265 }
266
267 /*
268 * test multiple opens of slave side
269 */
test4(void)270 int test4(void)
271 {
272 int masterfd, slavefd, slavefd2, slavefd3;
273 char *slavename;
274
275 masterfd = open(MASTERCLONE, O_RDWR);
276 if (masterfd < 0) {
277 tst_brkm(TBROK, NULL, "%s", MASTERCLONE);
278 }
279
280 slavename = ptsname(masterfd);
281 if (slavename == NULL) {
282 tst_brkm(TBROK | TERRNO, NULL, "ptsname() call failed");
283 }
284
285 if (grantpt(masterfd) != 0) {
286 tst_brkm(TBROK | TERRNO, NULL, "grantpt() call failed");
287 }
288
289 if (unlockpt(masterfd) != 0) {
290 tst_brkm(TBROK, NULL, "unlockpt() call failed");
291 }
292
293 if ((slavefd = open(slavename, O_RDWR)) < 0) {
294 tst_brkm(TBROK, NULL, "Could not open %s", slavename);
295 }
296
297 if ((slavefd2 = open(slavename, O_RDWR)) < 0) {
298 tst_brkm(TFAIL, NULL, "Could not open %s (again)", slavename);
299 }
300
301 if ((slavefd3 = open(slavename, O_RDWR)) < 0) {
302 tst_brkm(TFAIL, NULL, "Could not open %s (once more)",
303 slavename);
304 }
305
306 if (close(slavefd) != 0) {
307 tst_brkm(TBROK, NULL, "close slave");
308 }
309 if (close(slavefd2) != 0) {
310 tst_brkm(TBROK, NULL, "close slave again");
311 }
312 if (close(slavefd3) != 0) {
313 tst_brkm(TBROK, NULL, "close slave once more");
314 }
315 if (close(masterfd) != 0) {
316 tst_brkm(TBROK, NULL, "close master");
317 }
318 tst_resm(TPASS, "test4");
319
320 /** NOT REACHED **/
321 return 0;
322 }
323
324 #define NUMOPENS 6
325
326 /*
327 * test several simultaneous opens
328 */
test5(void)329 int test5(void)
330 {
331 static int masterfd[NUMOPENS];
332 static int slavefd[NUMOPENS];
333 char *slavename;
334 int i;
335
336 for (i = 0; i < NUMOPENS; ++i) {
337 masterfd[i] = open(MASTERCLONE, O_RDWR);
338 if (masterfd[i] < 0) {
339 tst_resm(TBROK, "%s", MASTERCLONE);
340 tst_resm(TBROK, "out of ptys");
341 for (i = 0; i < NUMOPENS; ++i) {
342 if (masterfd[i] != 0) {
343 (void)close(masterfd[i]);
344 }
345 if (slavefd[i] != 0) {
346 (void)close(slavefd[i]);
347 }
348 }
349 tst_exit();
350 }
351
352 slavename = ptsname(masterfd[i]);
353 if (slavename == NULL) {
354 tst_brkm(TBROK | TERRNO, NULL,
355 "ptsname() call failed");
356 }
357
358 if (grantpt(masterfd[i]) != 0) {
359 tst_brkm(TBROK | TERRNO, NULL,
360 "grantpt() call failed");
361 }
362
363 if (unlockpt(masterfd[i]) != 0) {
364 tst_brkm(TBROK, NULL, "unlockpt() call failed");
365 }
366
367 if ((slavefd[i] = open(slavename, O_RDWR)) < 0) {
368 tst_brkm(TFAIL, NULL,
369 "Iteration %d: Could not open %s", i,
370 slavename);
371 }
372
373 }
374
375 for (i = 0; i < NUMOPENS; ++i) {
376 if (close(slavefd[i]) != 0) {
377 tst_brkm(TBROK, NULL, "Iteration %d: close slave", i);
378 }
379 if (close(masterfd[i]) != 0) {
380 tst_brkm(TBROK, NULL, "close master");
381 }
382 }
383 tst_resm(TPASS, "test5");
384
385 /** NOT REACHED **/
386 return 0;
387 }
388
389 /*
390 * test hangup semantics
391 */
test6(void)392 int test6(void)
393 {
394 static int masterfd;
395 static int slavefd;
396 char *slavename;
397 struct termios termios;
398
399 masterfd = open(MASTERCLONE, O_RDWR);
400 if (masterfd < 0) {
401 tst_brkm(TBROK, NULL, "%s", MASTERCLONE);
402 }
403
404 slavename = ptsname(masterfd);
405 if (slavename == NULL) {
406 tst_brkm(TBROK | TERRNO, NULL, "ptsname() call failed");
407 }
408
409 if (grantpt(masterfd) != 0) {
410 tst_brkm(TBROK | TERRNO, NULL, "grantpt() call failed");
411 }
412
413 if (unlockpt(masterfd) != 0) {
414 tst_brkm(TBROK, NULL, "unlockpt() call failed");
415 }
416
417 if ((slavefd = open(slavename, O_RDWR)) < 0) {
418 tst_brkm(TBROK, NULL, "Could not open %s", slavename);
419 }
420
421 if (ioctl(slavefd, TCGETS, &termios) != 0) {
422 tst_brkm(TFAIL, NULL, "TCGETS");
423 }
424
425 termios.c_cflag &= ~CBAUD;
426 termios.c_cflag |= B0 & CBAUD;
427 if (ioctl(slavefd, TCSETS, &termios) != 0) {
428 tst_brkm(TFAIL, NULL, "TCGETS");
429 }
430
431 if (close(slavefd) != 0) {
432 tst_brkm(TBROK, NULL, "close");
433 }
434 if (close(masterfd) != 0) {
435 tst_brkm(TBROK, NULL, "close");
436 }
437 tst_resm(TPASS, "test6");
438
439 /** NOT REACHED **/
440 return 0;
441 }
442
443 /*
444 * main test driver
445 */
main(int argc,char ** argv)446 int main(int argc, char **argv)
447 {
448 test1();
449 test2();
450 test3();
451 test4();
452 test5();
453 test6();
454 /*
455 * all done
456 */
457 tst_exit();
458 }
459