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: #if !defined(lint) && defined(DOSCCS) 8: char copyright[] = 9: "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 10: All rights reserved.\n"; 11: 12: static char sccsid[] = "@(#)stty.c 5.4.3 (2.11BSD GTE) 1997/5/7"; 13: #endif 14: 15: /* 16: * set teletype modes 17: */ 18: 19: #include <stdio.h> 20: #include <sys/ioctl.h> 21: #include <errno.h> 22: #include <fcntl.h> 23: #include <stdlib.h> 24: 25: struct 26: { 27: char *string; 28: int speed; 29: } speeds[] = { 30: "0", B0, 31: "50", B50, 32: "75", B75, 33: "110", B110, 34: "134", B134, 35: "134.5",B134, 36: "150", B150, 37: "200", B200, 38: "300", B300, 39: "600", B600, 40: "1200", B1200, 41: "1800", B1800, 42: "2400", B2400, 43: "4800", B4800, 44: "9600", B9600, 45: "exta", EXTA, 46: "19200", EXTA, 47: "extb", EXTB, 48: "38400", EXTB, 49: 0, 50: }; 51: 52: unsigned speed[] = { 53: 0,50,75,110,134,150,200,300,600,1200,1800,2400,4800,9600,19200,38400 54: }; 55: 56: struct MODES 57: { 58: char *string; 59: int set; 60: int reset; 61: }; 62: 63: struct MODES modes[] = { 64: "even", EVENP, 0, 65: "-even", 0, EVENP, 66: "odd", ODDP, 0, 67: "-odd", 0, ODDP, 68: "raw", RAW, 0, 69: "-raw", 0, RAW, 70: "cooked", 0, RAW, 71: "-nl", CRMOD, 0, 72: "nl", 0, CRMOD, 73: "echo", ECHO, 0, 74: "-echo", 0, ECHO, 75: "-tabs", XTABS, 0, 76: "tabs", 0, XTABS, 77: "tandem", TANDEM, 0, 78: "-tandem", 0, TANDEM, 79: "cbreak", CBREAK, 0, 80: "-cbreak", 0, CBREAK, 81: 0 82: }; 83: 84: struct MODES lmodes[] = { 85: "rtscts", LRTSCTS, 0, 86: "-rtscts", 0, LRTSCTS, 87: "crtbs", LCRTBS, LPRTERA, 88: "-crtbs", 0, LCRTBS, 89: "prterase", LPRTERA, LCRTBS+LCRTKIL+LCRTERA, 90: "-prterase", 0, LPRTERA, 91: "crterase", LCRTERA, LPRTERA, 92: "-crterase", 0, LCRTERA, 93: "crtkill", LCRTKIL, LPRTERA, 94: "-crtkill", 0, LCRTKIL, 95: "mdmbuf", LMDMBUF, 0, 96: "-mdmbuf", 0, LMDMBUF, 97: "litout", LLITOUT, 0, 98: "-litout", 0, LLITOUT, 99: "pass8", LPASS8, 0, 100: "-pass8", 0, LPASS8, 101: "tostop", LTOSTOP, 0, 102: "-tostop", 0, LTOSTOP, 103: "flusho", LFLUSHO, 0, 104: "-flusho", 0, LFLUSHO, 105: "nohang", LNOHANG, 0, 106: "-nohang", 0, LNOHANG, 107: "ctlecho", LCTLECH, 0, 108: "-ctlecho", 0, LCTLECH, 109: "pendin", LPENDIN, 0, 110: "-pendin", 0, LPENDIN, 111: "decctlq", LDECCTQ, 0, 112: "-decctlq", 0, LDECCTQ, 113: "noflsh", LNOFLSH, 0, 114: "-noflsh", 0, LNOFLSH, 115: 0 116: }; 117: 118: struct MODES mmodes[] = { 119: "dcd", TIOCM_CD, 0, 120: "-dcd", 0, TIOCM_CD, 121: "dsr", TIOCM_DSR, 0, 122: "-dsr", 0, TIOCM_DSR, 123: "dtr", TIOCM_DTR, 0, 124: "-dtr", 0, TIOCM_DTR, 125: "cts", TIOCM_CTS, 0, 126: "-cts", 0, TIOCM_CTS, 127: "rts", TIOCM_RTS, 0, 128: "-rts", 0, TIOCM_RTS, 129: 0, 130: }; 131: 132: struct tchars tc; 133: struct ltchars ltc; 134: struct sgttyb mode; 135: struct winsize win; 136: int lmode; 137: int ldisc; 138: int mstate, nmstate; 139: 140: struct special { 141: char *name; 142: char *cp; 143: char def; 144: } special[] = { 145: "erase", &mode.sg_erase, CERASE, 146: "kill", &mode.sg_kill, CKILL, 147: "intr", &tc.t_intrc, CINTR, 148: "quit", &tc.t_quitc, CQUIT, 149: "start", &tc.t_startc, CSTART, 150: "stop", &tc.t_stopc, CSTOP, 151: "eof", &tc.t_eofc, CEOF, 152: "brk", &tc.t_brkc, CBRK, 153: "susp", <c.t_suspc, CSUSP, 154: "dsusp", <c.t_dsuspc, CDSUSP, 155: "rprnt", <c.t_rprntc, CRPRNT, 156: "flush", <c.t_flushc, CFLUSH, 157: "werase", <c.t_werasc, CWERASE, 158: "lnext", <c.t_lnextc, CLNEXT, 159: 0 160: }; 161: 162: char *arg; 163: char *Nfmt = "%-8s"; 164: 165: main(argc, argv) 166: int argc; 167: register char **argv; 168: { 169: int i, fmt = 0, ch, zero = 0; 170: register struct special *sp; 171: char obuf[BUFSIZ]; 172: char *arg2; 173: 174: setbuf(stderr, obuf); 175: 176: opterr = 0; 177: while (optind < argc && strspn(argv[optind], "-aef") == strlen(argv[optind]) && 178: (ch = getopt(argc, argv, "aef:")) != EOF) 179: { 180: switch (ch) 181: { 182: case 'e': 183: case 'a': 184: fmt = 2; 185: break; 186: case 'f': 187: i = open(optarg, O_RDONLY|O_NONBLOCK); 188: if (i < 0) 189: err(1, "%s", optarg); 190: if (dup2(i, 1) < 0) 191: err(1, "dup2(%d,1)", i); 192: break; 193: case '?': 194: default: 195: goto args; 196: } 197: } 198: args: 199: argc -= optind; 200: argv += optind; 201: 202: ioctl(1, TIOCGETP, &mode); 203: ioctl(1, TIOCGETD, &ldisc); 204: ioctl(1, TIOCGETC, &tc); 205: ioctl(1, TIOCLGET, &lmode); 206: ioctl(1, TIOCGLTC, <c); 207: ioctl(1, TIOCGWINSZ, &win); 208: if (ioctl(1, TIOCMGET, &mstate) < 0) 209: { 210: if (errno == ENOTTY) 211: mstate = -1; 212: else 213: warn("TIOCMGET"); 214: } 215: nmstate = mstate; 216: 217: if (argc == 0) { 218: prmodes(fmt); 219: exit(0); 220: } 221: arg = argv[1]; 222: if (argc == 1 && (!strcmp(arg, "everything") || !strcmp(arg, "all"))) { 223: prmodes(2); 224: exit(0); 225: } 226: 227: while (argc-- > 0) { 228: arg = *argv++; 229: if (eq("new")){ 230: ldisc = NTTYDISC; 231: if (ioctl(1, TIOCSETD, &ldisc)<0) 232: perror("ioctl"); 233: continue; 234: } 235: if (eq("newcrt")){ 236: ldisc = NTTYDISC; 237: lmode &= ~LPRTERA; 238: lmode |= LCRTBS|LCTLECH; 239: if (mode.sg_ospeed >= B1200) 240: lmode |= LCRTERA|LCRTKIL; 241: if (ioctl(1, TIOCSETD, &ldisc)<0) 242: perror("ioctl"); 243: continue; 244: } 245: if (eq("crt")){ 246: lmode &= ~LPRTERA; 247: lmode |= LCRTBS|LCTLECH; 248: if (mode.sg_ospeed >= B1200) 249: lmode |= LCRTERA|LCRTKIL; 250: continue; 251: } 252: if (eq("old")){ 253: ldisc = 0; 254: if (ioctl(1, TIOCSETD, &ldisc)<0) 255: perror("ioctl"); 256: continue; 257: } 258: if (eq("dec")){ 259: mode.sg_erase = 0177; 260: mode.sg_kill = CTRL(u); 261: tc.t_intrc = CTRL(c); 262: ldisc = NTTYDISC; 263: lmode &= ~LPRTERA; 264: lmode |= LCRTBS|LCTLECH|LDECCTQ; 265: if (mode.sg_ospeed >= B1200) 266: lmode |= LCRTERA|LCRTKIL; 267: if (ioctl(1, TIOCSETD, &ldisc)<0) 268: perror("ioctl"); 269: continue; 270: } 271: for (sp = special; sp->name; sp++) 272: if (eq(sp->name)) { 273: if (argc-- == 0) 274: goto done; 275: arg2 = *argv++; 276: if (strcmp(arg2, "undef") == 0) 277: *sp->cp = 0377; 278: else if (*arg2 == '^') 279: { 280: arg2++; 281: *sp->cp = (*arg2 == '?') ? 282: 0177 : *arg2 & 037; 283: } 284: else 285: *sp->cp = *arg2; 286: goto cont; 287: } 288: if (eq("flushout")) 289: { 290: ioctl(1, TIOCFLUSH, &zero); 291: continue; 292: } 293: if (eq("hup")) { 294: ioctl(1, TIOCHPCL, NULL); 295: continue; 296: } 297: if (eq("rows")) { 298: if (argc-- == 0) 299: goto done; 300: win.ws_row = atoi(*argv++); 301: } 302: if (eq("cols") || eq("columns")) { 303: if (argc-- == 0) 304: goto done; 305: win.ws_col = atoi(*argv++); 306: } 307: if (eq("size")) { 308: printf("%d %d\n", win.ws_row, win.ws_col); 309: exit(0); 310: } 311: for(i=0; speeds[i].string; i++) 312: if(eq(speeds[i].string)) { 313: mode.sg_ispeed = mode.sg_ospeed = speeds[i].speed; 314: goto cont; 315: } 316: if (eq("speed")) { 317: for(i=0; speeds[i].string; i++) 318: if (mode.sg_ospeed == speeds[i].speed) { 319: printf("%s\n", speeds[i].string); 320: exit(0); 321: } 322: printf("unknown\n"); 323: exit(1); 324: } 325: for (i = 0; modes[i].string; i++) 326: { 327: if (eq(modes[i].string)) 328: { 329: mode.sg_flags &= ~modes[i].reset; 330: mode.sg_flags |= modes[i].set; 331: goto cont; 332: } 333: } 334: for (i = 0; lmodes[i].string; i++) 335: { 336: if (eq(lmodes[i].string)) 337: { 338: lmode &= ~lmodes[i].reset; 339: lmode |= lmodes[i].set; 340: goto cont; 341: } 342: } 343: for (i = 0; mmodes[i].string; i++) 344: { 345: if (eq(mmodes[i].string)) 346: { 347: nmstate &= ~mmodes[i].reset; 348: nmstate |= mmodes[i].set; 349: goto cont; 350: } 351: } 352: if(arg) 353: fprintf(stderr,"unknown mode: %s\n", arg); 354: cont: 355: ; 356: } 357: done: 358: ioctl(1, TIOCSETN, &mode); 359: ioctl(1, TIOCSETC, &tc); 360: ioctl(1, TIOCSLTC, <c); 361: ioctl(1, TIOCLSET, &lmode); 362: ioctl(1, TIOCSWINSZ, &win); 363: if (mstate != -1 && nmstate != mstate) 364: { 365: if (ioctl(1, TIOCMSET, &nmstate) < 0) 366: warn("TIOCMSET"); 367: } 368: } 369: 370: eq(string) 371: char *string; 372: { 373: 374: if (!arg) 375: return(0); 376: if (strcmp(arg, string)) 377: return(0); 378: arg = 0; 379: return(1); 380: } 381: 382: #define lpit(what,str) \ 383: if (all || (lmode&what)) { \ 384: fprintf(stderr,str+((lmode&what)!=0)); any++; \ 385: } 386: 387: prmodes(all) 388: int all; /* 0 for short display, !0 for long display */ 389: { 390: register m; 391: int any, i; 392: register struct special *sp; 393: 394: if(ldisc==NETLDISC) 395: fprintf(stderr, "net discipline, "); 396: else if (ldisc==NTTYDISC) 397: fprintf(stderr, "new tty, "); 398: else if (ldisc == 0) 399: fprintf(stderr, "old tty, "); 400: else 401: fprintf(stderr, "discipline %d, "); 402: if(mode.sg_ispeed != mode.sg_ospeed) { 403: fprintf(stderr,"input speed %u baud", speed[mode.sg_ispeed]); 404: fprintf(stderr,"output speed %u baud", speed[mode.sg_ospeed]); 405: } else 406: fprintf(stderr,"speed %u baud", speed[mode.sg_ispeed]); 407: if (all) 408: fprintf(stderr, ", %d rows, %d columns", win.ws_row, win.ws_col); 409: fprintf(stderr, all ? "\n" : "; "); 410: m = mode.sg_flags; 411: if (all) { 412: if(m & EVENP) fprintf(stderr,"even "); 413: if(m & ODDP) fprintf(stderr,"odd "); 414: } 415: if (all || m&RAW) 416: fprintf(stderr,"-raw "+((m&RAW)!=0)); 417: if (all || (m&CRMOD)==0) 418: fprintf(stderr,"-nl "+((m&CRMOD)==0)); 419: if (all || (m&ECHO)==0) 420: fprintf(stderr,"-echo "+((m&ECHO)!=0)); 421: if (all || (m&TANDEM)) 422: fprintf(stderr,"-tandem "+((m&TANDEM)!=0)); 423: fprintf(stderr,"-tabs "+((m&XTABS)!=XTABS)); 424: if (all || (m&CBREAK)) 425: fprintf(stderr,"-cbreak "+((m&CBREAK)!=0)); 426: lpit(LRTSCTS, "-rtscts "); 427: if (all) 428: { 429: fputc('\n', stderr); 430: if (mstate != -1) 431: { 432: fprintf(stderr, "modem control: "); 433: fprintf(stderr,"-dcd "+((mstate & TIOCM_CD)!=0)); 434: fprintf(stderr,"-dsr "+((mstate & TIOCM_DSR)!=0)); 435: fprintf(stderr,"-dtr "+((mstate & TIOCM_DTR)!=0)); 436: fprintf(stderr,"-cts "+((mstate & TIOCM_CTS)!=0)); 437: fprintf(stderr,"-rts "+((mstate & TIOCM_RTS)!=0)); 438: fputc('\n', stderr); 439: } 440: } 441: if (ldisc == NTTYDISC) { 442: int newcrt = (lmode&(LCTLECH|LCRTBS)) == (LCTLECH|LCRTBS) && 443: (lmode&(LCRTERA|LCRTKIL)) == 444: ((mode.sg_ospeed > B300) ? LCRTERA|LCRTKIL : 0); 445: int nothing = 1; 446: if (newcrt) { 447: if (all) 448: fprintf(stderr, "crt: (crtbs crterase crtkill ctlecho) "); 449: else 450: fprintf(stderr, "crt "); 451: any++; 452: } else { 453: lpit(LCRTBS, "-crtbs "); 454: lpit(LCRTERA, "-crterase "); 455: lpit(LCRTKIL, "-crtkill "); 456: lpit(LCTLECH, "-ctlecho "); 457: lpit(LPRTERA, "-prterase "); 458: } 459: lpit(LTOSTOP, "-tostop "); 460: if (all) { 461: fputc('\n', stderr); 462: any = 0; 463: nothing = 0; 464: } 465: lpit(LFLUSHO, "-flusho "); 466: lpit(LMDMBUF, "-mdmbuf "); 467: lpit(LLITOUT, "-litout "); 468: lpit(LPASS8, "-pass8 "); 469: lpit(LNOHANG, "-nohang "); 470: if (any) { 471: fputc('\n', stderr); 472: any = 0; 473: nothing = 0; 474: } 475: lpit(LPENDIN, "-pendin "); 476: lpit(LDECCTQ, "-decctlq "); 477: lpit(LNOFLSH, "-noflsh "); 478: if (any || nothing) 479: fputc('\n', stderr); 480: } else if (!all) 481: fputc('\n', stderr); 482: 483: if (all) { 484: for (i = 0, sp = special; i < 9; i++, sp++) 485: fprintf(stderr, Nfmt, sp->name); 486: fputc('\n', stderr); 487: for (i = 0, sp = special; i < 9; i++, sp++) 488: pit(sp); 489: fputc('\n', stderr); 490: for (i = 9, sp = &special[9]; sp->name; i++, sp++) 491: fprintf(stderr, Nfmt, sp->name); 492: fputc('\n', stderr); 493: for (i = 9, sp = &special[9]; sp->name; i++, sp++) 494: pit(sp); 495: fputc('\n', stderr); 496: } 497: } 498: 499: pit(sp) 500: struct special *sp; 501: { 502: register int c = *sp->cp & 0xff; 503: char junk[6]; 504: register char *p = junk; 505: 506: if (c == 0xff) 507: { 508: fprintf(stderr, Nfmt, "<undef>"); 509: return; 510: } 511: if (c & 0200) 512: { 513: *p++ = 'M'; 514: *p++ = '-'; 515: c &= ~ 0200; 516: } 517: if (c == 0177) 518: { 519: *p++ = '^'; 520: *p++ = '?'; 521: } 522: else if (c < ' ') 523: { 524: *p++ = '^'; 525: *p++ = c += '@'; 526: } 527: *p++ = '\0'; 528: fprintf(stderr, Nfmt, junk); 529: }