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 <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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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