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) 4/4/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: }