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