Home | History | Annotate | Download | only in pty
      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 (at) us.ibm.com */
     21 /* 06/30/2001   Port to Linux   nsharoff (at) 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 <sys/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  */
     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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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