• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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