1 /* 2 * Copyright (c) 1980 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 */ 6 7 #ifndef lint 8 char copyright[] = 9 "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 10 All rights reserved.\n"; 11 #endif not lint 12 13 #ifndef lint 14 static char sccsid[] = "@(#)stty.c 5.4 (Berkeley) 04/04/86"; 15 #endif not lint 16 17 /* 18 * set teletype modes 19 */ 20 21 #include <stdio.h> 22 #include <sys/ioctl.h> 23 24 struct 25 { 26 char *string; 27 int speed; 28 } speeds[] = { 29 "0", B0, 30 "50", B50, 31 "75", B75, 32 "110", B110, 33 "134", B134, 34 "134.5",B134, 35 "150", B150, 36 "200", B200, 37 "300", B300, 38 "600", B600, 39 "1200", B1200, 40 "1800", B1800, 41 "2400", B2400, 42 "4800", B4800, 43 "9600", B9600, 44 "exta", EXTA, 45 "19200", EXTA, 46 "extb", EXTB, 47 "38400", EXTB, 48 0, 49 }; 50 struct 51 { 52 char *string; 53 int set; 54 int reset; 55 int lset; 56 int lreset; 57 } modes[] = { 58 "even", EVENP, 0, 0, 0, 59 "-even", 0, EVENP, 0, 0, 60 "odd", ODDP, 0, 0, 0, 61 "-odd", 0, ODDP, 0, 0, 62 "raw", RAW, 0, 0, 0, 63 "-raw", 0, RAW, 0, 0, 64 "cooked", 0, RAW, 0, 0, 65 "-nl", CRMOD, 0, 0, 0, 66 "nl", 0, CRMOD, 0, 0, 67 "echo", ECHO, 0, 0, 0, 68 "-echo", 0, ECHO, 0, 0, 69 "LCASE", LCASE, 0, 0, 0, 70 "lcase", LCASE, 0, 0, 0, 71 "-LCASE", 0, LCASE, 0, 0, 72 "-lcase", 0, LCASE, 0, 0, 73 "-tabs", XTABS, 0, 0, 0, 74 "tabs", 0, XTABS, 0, 0, 75 "tandem", TANDEM, 0, 0, 0, 76 "-tandem", 0, TANDEM, 0, 0, 77 "cbreak", CBREAK, 0, 0, 0, 78 "-cbreak", 0, CBREAK, 0, 0, 79 "cr0", CR0, CR3, 0, 0, 80 "cr1", CR1, CR3, 0, 0, 81 "cr2", CR2, CR3, 0, 0, 82 "cr3", CR3, CR3, 0, 0, 83 "tab0", TAB0, XTABS, 0, 0, 84 "tab1", TAB1, XTABS, 0, 0, 85 "tab2", TAB2, XTABS, 0, 0, 86 "nl0", NL0, NL3, 0, 0, 87 "nl1", NL1, NL3, 0, 0, 88 "nl2", NL2, NL3, 0, 0, 89 "nl3", NL3, NL3, 0, 0, 90 "ff0", FF0, FF1, 0, 0, 91 "ff1", FF1, FF1, 0, 0, 92 "bs0", BS0, BS1, 0, 0, 93 "bs1", BS1, BS1, 0, 0, 94 "33", CR1, ALLDELAY, 0, 0, 95 "tty33", CR1, ALLDELAY, 0, 0, 96 "37", FF1+CR2+TAB1+NL1, ALLDELAY, 0, 0, 97 "tty37", FF1+CR2+TAB1+NL1, ALLDELAY, 0, 0, 98 "05", NL2, ALLDELAY, 0, 0, 99 "vt05", NL2, ALLDELAY, 0, 0, 100 "tn", CR1, ALLDELAY, 0, 0, 101 "tn300", CR1, ALLDELAY, 0, 0, 102 "ti", CR2, ALLDELAY, 0, 0, 103 "ti700", CR2, ALLDELAY, 0, 0, 104 "tek", FF1, ALLDELAY, 0, 0, 105 "crtbs", 0, 0, LCRTBS, LPRTERA, 106 "-crtbs", 0, 0, 0, LCRTBS, 107 "prterase", 0, 0, LPRTERA, LCRTBS+LCRTKIL+LCRTERA, 108 "-prterase", 0, 0, 0, LPRTERA, 109 "crterase", 0, 0, LCRTERA, LPRTERA, 110 "-crterase", 0, 0, 0, LCRTERA, 111 "crtkill", 0, 0, LCRTKIL, LPRTERA, 112 "-crtkill", 0, 0, 0, LCRTKIL, 113 "tilde", 0, 0, LTILDE, 0, 114 "-tilde", 0, 0, 0, LTILDE, 115 "mdmbuf", 0, 0, LMDMBUF, 0, 116 "-mdmbuf", 0, 0, 0, LMDMBUF, 117 "litout", 0, 0, LLITOUT, 0, 118 "-litout", 0, 0, 0, LLITOUT, 119 "pass8", 0, 0, LPASS8, 0, 120 "-pass8", 0, 0, 0, LPASS8, 121 "tostop", 0, 0, LTOSTOP, 0, 122 "-tostop", 0, 0, 0, LTOSTOP, 123 "flusho", 0, 0, LFLUSHO, 0, 124 "-flusho", 0, 0, 0, LFLUSHO, 125 "nohang", 0, 0, LNOHANG, 0, 126 "-nohang", 0, 0, 0, LNOHANG, 127 #ifdef notdef 128 "etxack", 0, 0, LETXACK, 0, 129 "-etxack", 0, 0, 0, LETXACK, 130 #endif 131 "ctlecho", 0, 0, LCTLECH, 0, 132 "-ctlecho", 0, 0, 0, LCTLECH, 133 "pendin", 0, 0, LPENDIN, 0, 134 "-pendin", 0, 0, 0, LPENDIN, 135 "decctlq", 0, 0, LDECCTQ, 0, 136 "-decctlq", 0, 0, 0, LDECCTQ, 137 "noflsh", 0, 0, LNOFLSH, 0, 138 "-noflsh", 0, 0, 0, LNOFLSH, 139 0, 140 }; 141 142 struct tchars tc; 143 struct ltchars ltc; 144 struct sgttyb mode; 145 struct winsize win; 146 int lmode; 147 int oldisc, ldisc; 148 149 struct special { 150 char *name; 151 char *cp; 152 char def; 153 } special[] = { 154 "erase", &mode.sg_erase, CERASE, 155 "kill", &mode.sg_kill, CKILL, 156 "intr", &tc.t_intrc, CINTR, 157 "quit", &tc.t_quitc, CQUIT, 158 "start", &tc.t_startc, CSTART, 159 "stop", &tc.t_stopc, CSTOP, 160 "eof", &tc.t_eofc, CEOF, 161 "brk", &tc.t_brkc, CBRK, 162 "susp", <c.t_suspc, CSUSP, 163 "dsusp", <c.t_dsuspc, CDSUSP, 164 "rprnt", <c.t_rprntc, CRPRNT, 165 "flush", <c.t_flushc, CFLUSH, 166 "werase", <c.t_werasc, CWERASE, 167 "lnext", <c.t_lnextc, CLNEXT, 168 0 169 }; 170 char *arg; 171 172 int argc; 173 char **argv; 174 main(iargc, iargv) 175 char **iargv; 176 { 177 int i; 178 register struct special *sp; 179 char obuf[BUFSIZ]; 180 181 setbuf(stderr, obuf); 182 argc = iargc; 183 argv = iargv; 184 ioctl(1, TIOCGETP, &mode); 185 ioctl(1, TIOCGETD, &ldisc); 186 oldisc = ldisc; 187 ioctl(1, TIOCGETC, &tc); 188 ioctl(1, TIOCLGET, &lmode); 189 ioctl(1, TIOCGLTC, <c); 190 ioctl(1, TIOCGWINSZ, &win); 191 if(argc == 1) { 192 prmodes(0); 193 exit(0); 194 } 195 if (argc == 2 && !strcmp(argv[1], "all")) { 196 prmodes(1); 197 exit(0); 198 } 199 if (argc == 2 && !strcmp(argv[1], "everything")) { 200 prmodes(2); 201 exit(0); 202 } 203 /* 204 if (argc == 2 && !strcmp(argv[1], "all")) { 205 prmodes(2); 206 exit(0); 207 } 208 */ 209 while(--argc > 0) { 210 arg = *++argv; 211 if (eq("ek")){ 212 mode.sg_erase = '#'; 213 mode.sg_kill = '@'; 214 continue; 215 } 216 if (eq("new")){ 217 ldisc = NTTYDISC; 218 if (ioctl(1, TIOCSETD, &ldisc)<0) 219 perror("ioctl"); 220 continue; 221 } 222 if (eq("newcrt")){ 223 ldisc = NTTYDISC; 224 lmode &= ~LPRTERA; 225 lmode |= LCRTBS|LCTLECH; 226 if (mode.sg_ospeed >= B1200) 227 lmode |= LCRTERA|LCRTKIL; 228 if (ioctl(1, TIOCSETD, &ldisc)<0) 229 perror("ioctl"); 230 continue; 231 } 232 if (eq("crt")){ 233 lmode &= ~LPRTERA; 234 lmode |= LCRTBS|LCTLECH; 235 if (mode.sg_ospeed >= B1200) 236 lmode |= LCRTERA|LCRTKIL; 237 continue; 238 } 239 if (eq("old")){ 240 ldisc = 0; 241 if (ioctl(1, TIOCSETD, &ldisc)<0) 242 perror("ioctl"); 243 continue; 244 } 245 if (eq("dec")){ 246 mode.sg_erase = 0177; 247 mode.sg_kill = CTRL(u); 248 tc.t_intrc = CTRL(c); 249 ldisc = NTTYDISC; 250 lmode &= ~LPRTERA; 251 lmode |= LCRTBS|LCTLECH|LDECCTQ; 252 if (mode.sg_ospeed >= B1200) 253 lmode |= LCRTERA|LCRTKIL; 254 if (ioctl(1, TIOCSETD, &ldisc)<0) 255 perror("ioctl"); 256 continue; 257 } 258 for (sp = special; sp->name; sp++) 259 if (eq(sp->name)) { 260 if (--argc == 0) 261 goto done; 262 if (**++argv == 'u') 263 *sp->cp = 0377; 264 else if (**argv == '^') 265 *sp->cp = ((*argv)[1] == '?') ? 266 0177 : (*argv)[1] & 037; 267 else 268 *sp->cp = **argv; 269 goto cont; 270 } 271 if (eq("gspeed")) { 272 mode.sg_ispeed = B300; 273 mode.sg_ospeed = B9600; 274 continue; 275 } 276 if (eq("hup")) { 277 ioctl(1, TIOCHPCL, NULL); 278 continue; 279 } 280 if (eq("rows")) { 281 if (--argc == 0) 282 goto done; 283 win.ws_row = atoi(*++argv); 284 } 285 if (eq("cols") || eq("columns")) { 286 if (--argc == 0) 287 goto done; 288 win.ws_col = atoi(*++argv); 289 } 290 if (eq("size")) { 291 ioctl(open("/dev/tty", 0), TIOCGWINSZ, &win); 292 printf("%d %d\n", win.ws_row, win.ws_col); 293 exit(0); 294 } 295 for(i=0; speeds[i].string; i++) 296 if(eq(speeds[i].string)) { 297 mode.sg_ispeed = mode.sg_ospeed = speeds[i].speed; 298 goto cont; 299 } 300 if (eq("speed")) { 301 ioctl(open("/dev/tty", 0), TIOCGETP, &mode); 302 for(i=0; speeds[i].string; i++) 303 if (mode.sg_ospeed == speeds[i].speed) { 304 printf("%s\n", speeds[i].string); 305 exit(0); 306 } 307 printf("unknown\n"); 308 exit(1); 309 } 310 for(i=0; modes[i].string; i++) 311 if(eq(modes[i].string)) { 312 mode.sg_flags &= ~modes[i].reset; 313 mode.sg_flags |= modes[i].set; 314 lmode &= ~modes[i].lreset; 315 lmode |= modes[i].lset; 316 } 317 if(arg) 318 fprintf(stderr,"unknown mode: %s\n", arg); 319 cont: 320 ; 321 } 322 done: 323 ioctl(1, TIOCSETN, &mode); 324 ioctl(1, TIOCSETC, &tc); 325 ioctl(1, TIOCSLTC, <c); 326 ioctl(1, TIOCLSET, &lmode); 327 ioctl(1, TIOCSWINSZ, &win); 328 } 329 330 eq(string) 331 char *string; 332 { 333 int i; 334 335 if(!arg) 336 return(0); 337 i = 0; 338 loop: 339 if(arg[i] != string[i]) 340 return(0); 341 if(arg[i++] != '\0') 342 goto loop; 343 arg = 0; 344 return(1); 345 } 346 347 prmodes(all) 348 { 349 register m; 350 int any; 351 352 if(ldisc==NETLDISC) 353 fprintf(stderr, "net discipline, "); 354 else if(ldisc==NTTYDISC) 355 fprintf(stderr, "new tty, "); 356 else if(all==2) 357 fprintf(stderr, "old tty, "); 358 if(mode.sg_ispeed != mode.sg_ospeed) { 359 prspeed("input speed ", mode.sg_ispeed); 360 prspeed("output speed ", mode.sg_ospeed); 361 } else 362 prspeed("speed ", mode.sg_ispeed); 363 if (all) 364 fprintf(stderr, ", %d rows, %d columns", win.ws_row, win.ws_col); 365 fprintf(stderr, all==2 ? "\n" : "; "); 366 m = mode.sg_flags; 367 if(all==2 || (m&(EVENP|ODDP))!=(EVENP|ODDP)) { 368 if(m & EVENP) fprintf(stderr,"even "); 369 if(m & ODDP) fprintf(stderr,"odd "); 370 } 371 if(all==2 || m&RAW) 372 fprintf(stderr,"-raw "+((m&RAW)!=0)); 373 if(all==2 || (m&CRMOD)==0) 374 fprintf(stderr,"-nl "+((m&CRMOD)==0)); 375 if(all==2 || (m&ECHO)==0) 376 fprintf(stderr,"-echo "+((m&ECHO)!=0)); 377 if(all==2 || (m&LCASE)) 378 fprintf(stderr,"-lcase "+((m&LCASE)!=0)); 379 if(all==2 || (m&TANDEM)) 380 fprintf(stderr,"-tandem "+((m&TANDEM)!=0)); 381 fprintf(stderr,"-tabs "+((m&XTABS)!=XTABS)); 382 if(all==2 || (m&CBREAK)) 383 fprintf(stderr,"-cbreak "+((m&CBREAK)!=0)); 384 if(all==2 || (m&NLDELAY)) 385 delay((m&NLDELAY)/NL1, "nl"); 386 if ((m&TBDELAY)!=XTABS) 387 delay((m&TBDELAY)/TAB1, "tab"); 388 if(all==2 || (m&CRDELAY)) 389 delay((m&CRDELAY)/CR1, "cr"); 390 if(all==2 || (m&VTDELAY)) 391 delay((m&VTDELAY)/FF1, "ff"); 392 if(all==2 || (m&BSDELAY)) 393 delay((m&BSDELAY)/BS1, "bs"); 394 if (all) 395 fprintf(stderr,"\n"); 396 #define lpit(what,str) \ 397 if (all==2||(lmode&what)) { \ 398 fprintf(stderr,str+((lmode&what)!=0)); any++; \ 399 } 400 if (ldisc == NTTYDISC) { 401 int newcrt = (lmode&(LCTLECH|LCRTBS)) == (LCTLECH|LCRTBS) && 402 (lmode&(LCRTERA|LCRTKIL)) == 403 ((mode.sg_ospeed > B300) ? LCRTERA|LCRTKIL : 0); 404 int nothing = 1; 405 if (newcrt) { 406 if (all==2) 407 fprintf(stderr, "crt: (crtbs crterase crtkill ctlecho) "); 408 else 409 fprintf(stderr, "crt "); 410 any++; 411 } else { 412 lpit(LCRTBS, "-crtbs "); 413 lpit(LCRTERA, "-crterase "); 414 lpit(LCRTKIL, "-crtkill "); 415 lpit(LCTLECH, "-ctlecho "); 416 lpit(LPRTERA, "-prterase "); 417 } 418 lpit(LTOSTOP, "-tostop "); 419 if (all==2) { 420 fprintf(stderr, "\n"); 421 any = 0; 422 nothing = 0; 423 } 424 lpit(LTILDE, "-tilde "); 425 lpit(LFLUSHO, "-flusho "); 426 lpit(LMDMBUF, "-mdmbuf "); 427 lpit(LLITOUT, "-litout "); 428 lpit(LPASS8, "-pass8 "); 429 lpit(LNOHANG, "-nohang "); 430 if (any) { 431 fprintf(stderr,"\n"); 432 any = 0; 433 nothing = 0; 434 } 435 #ifdef notdef 436 lpit(LETXACK, "-etxack "); 437 #endif 438 lpit(LPENDIN, "-pendin "); 439 lpit(LDECCTQ, "-decctlq "); 440 lpit(LNOFLSH, "-noflsh "); 441 if (any || nothing) 442 fprintf(stderr,"\n"); 443 } else if (!all) 444 fprintf(stderr,"\n"); 445 if (all) { 446 switch (ldisc) { 447 448 case 0: 449 fprintf(stderr,"\ 450 erase kill intr quit stop eof\ 451 \n"); 452 pcol(mode.sg_erase, -1); 453 pcol(mode.sg_kill, -1); 454 pcol(tc.t_intrc, -1); 455 pcol(tc.t_quitc, -1); 456 pcol(tc.t_stopc, tc.t_startc); 457 pcol(tc.t_eofc, tc.t_brkc); 458 fprintf(stderr,"\n"); 459 break; 460 461 case NTTYDISC: 462 fprintf(stderr,"\ 463 erase kill werase rprnt flush lnext susp intr quit stop eof\ 464 \n"); 465 pcol(mode.sg_erase, -1); 466 pcol(mode.sg_kill, -1); 467 pcol(ltc.t_werasc, -1); 468 pcol(ltc.t_rprntc, -1); 469 pcol(ltc.t_flushc, -1); 470 pcol(ltc.t_lnextc, -1); 471 pcol(ltc.t_suspc, ltc.t_dsuspc); 472 pcol(tc.t_intrc, -1); 473 pcol(tc.t_quitc, -1); 474 pcol(tc.t_stopc, tc.t_startc); 475 pcol(tc.t_eofc, tc.t_brkc); 476 fprintf(stderr,"\n"); 477 break; 478 } 479 } else if (ldisc != NETLDISC) { 480 register struct special *sp; 481 int first = 1; 482 483 for (sp = special; sp->name; sp++) { 484 if ((*sp->cp&0377) != (sp->def&0377)) { 485 pit(*sp->cp, sp->name, first ? "" : ", "); 486 first = 0; 487 }; 488 if (sp->cp == &tc.t_brkc && ldisc == 0) 489 break; 490 } 491 if (!first) 492 fprintf(stderr, "\n"); 493 } 494 } 495 496 pcol(ch1, ch2) 497 int ch1, ch2; 498 { 499 int nout = 0; 500 501 ch1 &= 0377; 502 ch2 &= 0377; 503 if (ch1 == ch2) 504 ch2 = 0377; 505 for (; ch1 != 0377 || ch2 != 0377; ch1 = ch2, ch2 = 0377) { 506 if (ch1 == 0377) 507 continue; 508 if (ch1 & 0200) { 509 fprintf(stderr, "M-"); 510 nout += 2; 511 ch1 &= ~ 0200; 512 } 513 if (ch1 == 0177) { 514 fprintf(stderr, "^"); 515 nout++; 516 ch1 = '?'; 517 } else if (ch1 < ' ') { 518 fprintf(stderr, "^"); 519 nout++; 520 ch1 += '@'; 521 } 522 fprintf(stderr, "%c", ch1); 523 nout++; 524 if (ch2 != 0377) { 525 fprintf(stderr, "/"); 526 nout++; 527 } 528 } 529 while (nout < 7) { 530 fprintf(stderr, " "); 531 nout++; 532 } 533 } 534 535 pit(what, itsname, sep) 536 unsigned what; 537 char *itsname, *sep; 538 { 539 540 what &= 0377; 541 fprintf(stderr, "%s%s", sep, itsname); 542 if (what == 0377) { 543 fprintf(stderr, " <undef>"); 544 return; 545 } 546 fprintf(stderr, " = "); 547 if (what & 0200) { 548 fprintf(stderr, "M-"); 549 what &= ~ 0200; 550 } 551 if (what == 0177) { 552 fprintf(stderr, "^"); 553 what = '?'; 554 } else if (what < ' ') { 555 fprintf(stderr, "^"); 556 what += '@'; 557 } 558 fprintf(stderr, "%c", what); 559 } 560 561 delay(m, s) 562 char *s; 563 { 564 565 if(m) 566 fprintf(stderr,"%s%d ", s, m); 567 } 568 569 int speed[] = { 570 0,50,75,110,134,150,200,300,600,1200,1800,2400,4800,9600,19200,38400 571 }; 572 573 prspeed(c, s) 574 char *c; 575 { 576 577 fprintf(stderr,"%s%d baud", c, speed[s]); 578 } 579