1: /* 2: * Copyright (c) 1982, 1986 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: * @(#)tty.c 7.1 (Berkeley) 6/5/86 7: */ 8: 9: #include "../machine/reg.h" 10: 11: #include "param.h" 12: #include "systm.h" 13: #include "dir.h" 14: #include "user.h" 15: #include "ioctl.h" 16: #include "tty.h" 17: #include "proc.h" 18: #include "inode.h" 19: #include "file.h" 20: #include "conf.h" 21: #include "buf.h" 22: #include "dk.h" 23: #include "uio.h" 24: #include "kernel.h" 25: 26: /* 27: * Table giving parity for characters and indicating 28: * character classes to tty driver. In particular, 29: * if the low 6 bits are 0, then the character needs 30: * no special processing on output. 31: */ 32: 33: char partab[] = { 34: 0001,0201,0201,0001,0201,0001,0001,0201, 35: 0202,0004,0003,0201,0005,0206,0201,0001, 36: 0201,0001,0001,0201,0001,0201,0201,0001, 37: 0001,0201,0201,0001,0201,0001,0001,0201, 38: 0200,0000,0000,0200,0000,0200,0200,0000, 39: 0000,0200,0200,0000,0200,0000,0000,0200, 40: 0000,0200,0200,0000,0200,0000,0000,0200, 41: 0200,0000,0000,0200,0000,0200,0200,0000, 42: 0200,0000,0000,0200,0000,0200,0200,0000, 43: 0000,0200,0200,0000,0200,0000,0000,0200, 44: 0000,0200,0200,0000,0200,0000,0000,0200, 45: 0200,0000,0000,0200,0000,0200,0200,0000, 46: 0000,0200,0200,0000,0200,0000,0000,0200, 47: 0200,0000,0000,0200,0000,0200,0200,0000, 48: 0200,0000,0000,0200,0000,0200,0200,0000, 49: 0000,0200,0200,0000,0200,0000,0000,0201, 50: 51: /* 52: * 7 bit ascii ends with the last character above, 53: * but we contine through all 256 codes for the sake 54: * of the tty output routines which use special vax 55: * instructions which need a 256 character trt table. 56: */ 57: 58: 0007,0007,0007,0007,0007,0007,0007,0007, 59: 0007,0007,0007,0007,0007,0007,0007,0007, 60: 0007,0007,0007,0007,0007,0007,0007,0007, 61: 0007,0007,0007,0007,0007,0007,0007,0007, 62: 0007,0007,0007,0007,0007,0007,0007,0007, 63: 0007,0007,0007,0007,0007,0007,0007,0007, 64: 0007,0007,0007,0007,0007,0007,0007,0007, 65: 0007,0007,0007,0007,0007,0007,0007,0007, 66: 0007,0007,0007,0007,0007,0007,0007,0007, 67: 0007,0007,0007,0007,0007,0007,0007,0007, 68: 0007,0007,0007,0007,0007,0007,0007,0007, 69: 0007,0007,0007,0007,0007,0007,0007,0007, 70: 0007,0007,0007,0007,0007,0007,0007,0007, 71: 0007,0007,0007,0007,0007,0007,0007,0007, 72: 0007,0007,0007,0007,0007,0007,0007,0007, 73: 0007,0007,0007,0007,0007,0007,0007,0007 74: }; 75: 76: /* 77: * Input mapping table-- if an entry is non-zero, when the 78: * corresponding character is typed preceded by "\" the escape 79: * sequence is replaced by the table value. Mostly used for 80: * upper-case only terminals. 81: */ 82: char maptab[] ={ 83: 000,000,000,000,000,000,000,000, 84: 000,000,000,000,000,000,000,000, 85: 000,000,000,000,000,000,000,000, 86: 000,000,000,000,000,000,000,000, 87: 000,'|',000,000,000,000,000,'`', 88: '{','}',000,000,000,000,000,000, 89: 000,000,000,000,000,000,000,000, 90: 000,000,000,000,000,000,000,000, 91: 000,000,000,000,000,000,000,000, 92: 000,000,000,000,000,000,000,000, 93: 000,000,000,000,000,000,000,000, 94: 000,000,000,000,000,000,'~',000, 95: 000,'A','B','C','D','E','F','G', 96: 'H','I','J','K','L','M','N','O', 97: 'P','Q','R','S','T','U','V','W', 98: 'X','Y','Z',000,000,000,000,000, 99: }; 100: 101: short tthiwat[16] = 102: { 100,100,100,100,100,100,100,200,200,400,400,400,650,650,1300,2000 }; 103: short ttlowat[16] = 104: { 30, 30, 30, 30, 30, 30, 30, 50, 50,120,120,120,125,125,125,125 }; 105: 106: struct ttychars ttydefaults = { 107: CERASE, CKILL, CINTR, CQUIT, CSTART, CSTOP, CEOF, 108: CBRK, CSUSP, CDSUSP, CRPRNT, CFLUSH, CWERASE,CLNEXT 109: }; 110: 111: ttychars(tp) 112: struct tty *tp; 113: { 114: 115: tp->t_chars = ttydefaults; 116: } 117: 118: /* 119: * Wait for output to drain, then flush input waiting. 120: */ 121: ttywflush(tp) 122: register struct tty *tp; 123: { 124: 125: ttywait(tp); 126: ttyflush(tp, FREAD); 127: } 128: 129: ttywait(tp) 130: register struct tty *tp; 131: { 132: register int s = spltty(); 133: 134: while ((tp->t_outq.c_cc || tp->t_state&TS_BUSY) && 135: tp->t_state&TS_CARR_ON) { 136: (*tp->t_oproc)(tp); 137: tp->t_state |= TS_ASLEEP; 138: sleep((caddr_t)&tp->t_outq, TTOPRI); 139: } 140: splx(s); 141: } 142: 143: /* 144: * Flush all TTY queues 145: */ 146: ttyflush(tp, rw) 147: register struct tty *tp; 148: { 149: register s; 150: 151: s = spltty(); 152: if (rw & FREAD) { 153: while (getc(&tp->t_canq) >= 0) 154: ; 155: wakeup((caddr_t)&tp->t_rawq); 156: } 157: if (rw & FWRITE) { 158: wakeup((caddr_t)&tp->t_outq); 159: tp->t_state &= ~TS_TTSTOP; 160: (*cdevsw[major(tp->t_dev)].d_stop)(tp, rw); 161: while (getc(&tp->t_outq) >= 0) 162: ; 163: } 164: if (rw & FREAD) { 165: while (getc(&tp->t_rawq) >= 0) 166: ; 167: tp->t_rocount = 0; 168: tp->t_rocol = 0; 169: tp->t_state &= ~TS_LOCAL; 170: } 171: splx(s); 172: } 173: 174: /* 175: * Send stop character on input overflow. 176: */ 177: ttyblock(tp) 178: register struct tty *tp; 179: { 180: register x; 181: 182: x = tp->t_rawq.c_cc + tp->t_canq.c_cc; 183: if (tp->t_rawq.c_cc > TTYHOG) { 184: ttyflush(tp, FREAD|FWRITE); 185: tp->t_state &= ~TS_TBLOCK; 186: } 187: /* 188: * Block further input iff: 189: * Current input > threshold AND input is available to user program 190: */ 191: if (x >= TTYHOG/2 && 192: ((tp->t_flags & (RAW|CBREAK)) || (tp->t_canq.c_cc > 0))) { 193: if (putc(tp->t_stopc, &tp->t_outq)==0) { 194: tp->t_state |= TS_TBLOCK; 195: ttstart(tp); 196: } 197: } 198: } 199: 200: /* 201: * Restart typewriter output following a delay 202: * timeout. 203: * The name of the routine is passed to the timeout 204: * subroutine and it is called during a clock interrupt. 205: */ 206: ttrstrt(tp) 207: register struct tty *tp; 208: { 209: 210: if (tp == 0) 211: panic("ttrstrt"); 212: tp->t_state &= ~TS_TIMEOUT; 213: ttstart(tp); 214: } 215: 216: /* 217: * Start output on the typewriter. It is used from the top half 218: * after some characters have been put on the output queue, 219: * from the interrupt routine to transmit the next 220: * character, and after a timeout has finished. 221: */ 222: ttstart(tp) 223: register struct tty *tp; 224: { 225: register s; 226: 227: s = spltty(); 228: if ((tp->t_state & (TS_TIMEOUT|TS_TTSTOP|TS_BUSY)) == 0 && 229: tp->t_oproc) /* kludge for pty */ 230: (*tp->t_oproc)(tp); 231: splx(s); 232: } 233: 234: /* 235: * Common code for tty ioctls. 236: */ 237: /*ARGSUSED*/ 238: ttioctl(tp, com, data, flag) 239: register struct tty *tp; 240: caddr_t data; 241: { 242: int dev = tp->t_dev; 243: extern int nldisp; 244: int s; 245: register int newflags; 246: 247: /* 248: * If the ioctl involves modification, 249: * hang if in the background. 250: */ 251: switch (com) { 252: 253: case TIOCSETD: 254: case TIOCSETP: 255: case TIOCSETN: 256: case TIOCFLUSH: 257: case TIOCSETC: 258: case TIOCSLTC: 259: case TIOCSPGRP: 260: case TIOCLBIS: 261: case TIOCLBIC: 262: case TIOCLSET: 263: case TIOCSTI: 264: case TIOCSWINSZ: 265: while (tp->t_line == NTTYDISC && 266: u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp && 267: (u.u_procp->p_flag&SVFORK) == 0 && 268: !(u.u_procp->p_sigignore & sigmask(SIGTTOU)) && 269: !(u.u_procp->p_sigmask & sigmask(SIGTTOU))) { 270: gsignal(u.u_procp->p_pgrp, SIGTTOU); 271: sleep((caddr_t)&lbolt, TTOPRI); 272: } 273: break; 274: } 275: 276: /* 277: * Process the ioctl. 278: */ 279: switch (com) { 280: 281: /* get discipline number */ 282: case TIOCGETD: 283: *(int *)data = tp->t_line; 284: break; 285: 286: /* set line discipline */ 287: case TIOCSETD: { 288: register int t = *(int *)data; 289: int error = 0; 290: 291: if ((unsigned) t >= nldisp) 292: return (ENXIO); 293: if (t != tp->t_line) { 294: s = spltty(); 295: (*linesw[tp->t_line].l_close)(tp); 296: error = (*linesw[t].l_open)(dev, tp); 297: if (error) { 298: (void) (*linesw[tp->t_line].l_open)(dev, tp); 299: splx(s); 300: return (error); 301: } 302: tp->t_line = t; 303: splx(s); 304: } 305: break; 306: } 307: 308: /* prevent more opens on channel */ 309: case TIOCEXCL: 310: tp->t_state |= TS_XCLUDE; 311: break; 312: 313: case TIOCNXCL: 314: tp->t_state &= ~TS_XCLUDE; 315: break; 316: 317: /* hang up line on last close */ 318: case TIOCHPCL: 319: tp->t_state |= TS_HUPCLS; 320: break; 321: 322: case TIOCFLUSH: { 323: register int flags = *(int *)data; 324: 325: if (flags == 0) 326: flags = FREAD|FWRITE; 327: else 328: flags &= FREAD|FWRITE; 329: ttyflush(tp, flags); 330: break; 331: } 332: 333: /* return number of characters immediately available */ 334: case FIONREAD: 335: *(off_t *)data = ttnread(tp); 336: break; 337: 338: case TIOCOUTQ: 339: *(int *)data = tp->t_outq.c_cc; 340: break; 341: 342: case TIOCSTOP: 343: s = spltty(); 344: if ((tp->t_state&TS_TTSTOP) == 0) { 345: tp->t_state |= TS_TTSTOP; 346: (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0); 347: } 348: splx(s); 349: break; 350: 351: case TIOCSTART: 352: s = spltty(); 353: if ((tp->t_state&TS_TTSTOP) || (tp->t_flags&FLUSHO)) { 354: tp->t_state &= ~TS_TTSTOP; 355: tp->t_flags &= ~FLUSHO; 356: ttstart(tp); 357: } 358: splx(s); 359: break; 360: 361: /* 362: * Simulate typing of a character at the terminal. 363: */ 364: case TIOCSTI: 365: if (u.u_uid && (flag & FREAD) == 0) 366: return (EPERM); 367: if (u.u_uid && u.u_ttyp != tp) 368: return (EACCES); 369: (*linesw[tp->t_line].l_rint)(*(char *)data, tp); 370: break; 371: 372: case TIOCSETP: 373: case TIOCSETN: { 374: register struct sgttyb *sg = (struct sgttyb *)data; 375: 376: tp->t_erase = sg->sg_erase; 377: tp->t_kill = sg->sg_kill; 378: tp->t_ispeed = sg->sg_ispeed; 379: tp->t_ospeed = sg->sg_ospeed; 380: newflags = (tp->t_flags&0xffff0000) | (sg->sg_flags&0xffff); 381: s = spltty(); 382: if (tp->t_flags&RAW || newflags&RAW || com == TIOCSETP) { 383: ttywait(tp); 384: ttyflush(tp, FREAD); 385: } else if ((tp->t_flags&CBREAK) != (newflags&CBREAK)) { 386: if (newflags&CBREAK) { 387: struct clist tq; 388: 389: catq(&tp->t_rawq, &tp->t_canq); 390: tq = tp->t_rawq; 391: tp->t_rawq = tp->t_canq; 392: tp->t_canq = tq; 393: } else { 394: tp->t_flags |= PENDIN; 395: newflags |= PENDIN; 396: ttwakeup(tp); 397: } 398: } 399: tp->t_flags = newflags; 400: if (tp->t_flags&RAW) { 401: tp->t_state &= ~TS_TTSTOP; 402: ttstart(tp); 403: } 404: splx(s); 405: break; 406: } 407: 408: /* send current parameters to user */ 409: case TIOCGETP: { 410: register struct sgttyb *sg = (struct sgttyb *)data; 411: 412: sg->sg_ispeed = tp->t_ispeed; 413: sg->sg_ospeed = tp->t_ospeed; 414: sg->sg_erase = tp->t_erase; 415: sg->sg_kill = tp->t_kill; 416: sg->sg_flags = tp->t_flags; 417: break; 418: } 419: 420: case FIONBIO: 421: if (*(int *)data) 422: tp->t_state |= TS_NBIO; 423: else 424: tp->t_state &= ~TS_NBIO; 425: break; 426: 427: case FIOASYNC: 428: if (*(int *)data) 429: tp->t_state |= TS_ASYNC; 430: else 431: tp->t_state &= ~TS_ASYNC; 432: break; 433: 434: case TIOCGETC: 435: bcopy((caddr_t)&tp->t_intrc, data, sizeof (struct tchars)); 436: break; 437: 438: case TIOCSETC: 439: bcopy(data, (caddr_t)&tp->t_intrc, sizeof (struct tchars)); 440: break; 441: 442: /* set/get local special characters */ 443: case TIOCSLTC: 444: bcopy(data, (caddr_t)&tp->t_suspc, sizeof (struct ltchars)); 445: break; 446: 447: case TIOCGLTC: 448: bcopy((caddr_t)&tp->t_suspc, data, sizeof (struct ltchars)); 449: break; 450: 451: /* 452: * Modify local mode word. 453: */ 454: case TIOCLBIS: 455: tp->t_flags |= *(int *)data << 16; 456: break; 457: 458: case TIOCLBIC: 459: tp->t_flags &= ~(*(int *)data << 16); 460: break; 461: 462: case TIOCLSET: 463: tp->t_flags &= 0xffff; 464: tp->t_flags |= *(int *)data << 16; 465: break; 466: 467: case TIOCLGET: 468: *(int *)data = ((unsigned) tp->t_flags) >> 16; 469: break; 470: 471: /* 472: * Allow SPGRP only if tty is open for reading. 473: * Quick check: if we can find a process in the new pgrp, 474: * this user must own that process. 475: * SHOULD VERIFY THAT PGRP IS IN USE AND IS THIS USER'S. 476: */ 477: case TIOCSPGRP: { 478: struct proc *p; 479: int pgrp = *(int *)data; 480: 481: if (u.u_uid && (flag & FREAD) == 0) 482: return (EPERM); 483: p = pfind(pgrp); 484: if (p && p->p_pgrp == pgrp && 485: p->p_uid != u.u_uid && u.u_uid && !inferior(p)) 486: return (EPERM); 487: tp->t_pgrp = pgrp; 488: break; 489: } 490: 491: case TIOCGPGRP: 492: *(int *)data = tp->t_pgrp; 493: break; 494: 495: case TIOCSWINSZ: 496: if (bcmp((caddr_t)&tp->t_winsize, data, 497: sizeof (struct winsize))) { 498: tp->t_winsize = *(struct winsize *)data; 499: gsignal(tp->t_pgrp, SIGWINCH); 500: } 501: break; 502: 503: case TIOCGWINSZ: 504: *(struct winsize *)data = tp->t_winsize; 505: break; 506: 507: default: 508: return (-1); 509: } 510: return (0); 511: } 512: 513: ttnread(tp) 514: struct tty *tp; 515: { 516: int nread = 0; 517: 518: if (tp->t_flags & PENDIN) 519: ttypend(tp); 520: nread = tp->t_canq.c_cc; 521: if (tp->t_flags & (RAW|CBREAK)) 522: nread += tp->t_rawq.c_cc; 523: return (nread); 524: } 525: 526: ttselect(dev, rw) 527: dev_t dev; 528: int rw; 529: { 530: register struct tty *tp = &cdevsw[major(dev)].d_ttys[minor(dev)]; 531: int nread; 532: int s = spltty(); 533: 534: switch (rw) { 535: 536: case FREAD: 537: nread = ttnread(tp); 538: if ((nread > 0) || ((tp->t_state & TS_CARR_ON) == 0)) 539: goto win; 540: if (tp->t_rsel && tp->t_rsel->p_wchan == (caddr_t)&selwait) 541: tp->t_state |= TS_RCOLL; 542: else 543: tp->t_rsel = u.u_procp; 544: break; 545: 546: case FWRITE: 547: if (tp->t_outq.c_cc <= TTLOWAT(tp)) 548: goto win; 549: if (tp->t_wsel && tp->t_wsel->p_wchan == (caddr_t)&selwait) 550: tp->t_state |= TS_WCOLL; 551: else 552: tp->t_wsel = u.u_procp; 553: break; 554: } 555: splx(s); 556: return (0); 557: win: 558: splx(s); 559: return (1); 560: } 561: 562: /* 563: * Initial open of tty, or (re)entry to line discipline. 564: * Establish a process group for distribution of 565: * quits and interrupts from the tty. 566: */ 567: ttyopen(dev, tp) 568: dev_t dev; 569: register struct tty *tp; 570: { 571: register struct proc *pp; 572: 573: pp = u.u_procp; 574: tp->t_dev = dev; 575: if (pp->p_pgrp == 0) { 576: u.u_ttyp = tp; 577: u.u_ttyd = dev; 578: if (tp->t_pgrp == 0) 579: tp->t_pgrp = pp->p_pid; 580: pp->p_pgrp = tp->t_pgrp; 581: } 582: tp->t_state &= ~TS_WOPEN; 583: if ((tp->t_state & TS_ISOPEN) == 0) { 584: tp->t_state |= TS_ISOPEN; 585: bzero((caddr_t)&tp->t_winsize, sizeof(tp->t_winsize)); 586: if (tp->t_line != NTTYDISC) 587: ttywflush(tp); 588: } 589: return (0); 590: } 591: 592: /* 593: * "close" a line discipline 594: */ 595: ttylclose(tp) 596: register struct tty *tp; 597: { 598: 599: ttywflush(tp); 600: tp->t_line = 0; 601: } 602: 603: /* 604: * clean tp on last close 605: */ 606: ttyclose(tp) 607: register struct tty *tp; 608: { 609: 610: ttyflush(tp, FREAD|FWRITE); 611: tp->t_pgrp = 0; 612: tp->t_state = 0; 613: } 614: 615: /* 616: * Handle modem control transition on a tty. 617: * Flag indicates new state of carrier. 618: * Returns 0 if the line should be turned off, otherwise 1. 619: */ 620: ttymodem(tp, flag) 621: register struct tty *tp; 622: { 623: 624: if ((tp->t_state&TS_WOPEN) == 0 && (tp->t_flags & MDMBUF)) { 625: /* 626: * MDMBUF: do flow control according to carrier flag 627: */ 628: if (flag) { 629: tp->t_state &= ~TS_TTSTOP; 630: ttstart(tp); 631: } else if ((tp->t_state&TS_TTSTOP) == 0) { 632: tp->t_state |= TS_TTSTOP; 633: (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0); 634: } 635: } else if (flag == 0) { 636: /* 637: * Lost carrier. 638: */ 639: tp->t_state &= ~TS_CARR_ON; 640: if (tp->t_state & TS_ISOPEN) { 641: if ((tp->t_flags & NOHANG) == 0) { 642: gsignal(tp->t_pgrp, SIGHUP); 643: gsignal(tp->t_pgrp, SIGCONT); 644: ttyflush(tp, FREAD|FWRITE); 645: return (0); 646: } 647: } 648: } else { 649: /* 650: * Carrier now on. 651: */ 652: tp->t_state |= TS_CARR_ON; 653: wakeup((caddr_t)&tp->t_rawq); 654: } 655: return (1); 656: } 657: 658: /* 659: * Default modem control routine (for other line disciplines). 660: * Return argument flag, to turn off device on carrier drop. 661: */ 662: nullmodem(tp, flag) 663: register struct tty *tp; 664: int flag; 665: { 666: 667: if (flag) 668: tp->t_state |= TS_CARR_ON; 669: else 670: tp->t_state &= ~TS_CARR_ON; 671: return (flag); 672: } 673: 674: /* 675: * reinput pending characters after state switch 676: * call at spltty(). 677: */ 678: ttypend(tp) 679: register struct tty *tp; 680: { 681: struct clist tq; 682: register c; 683: 684: tp->t_flags &= ~PENDIN; 685: tp->t_state |= TS_TYPEN; 686: tq = tp->t_rawq; 687: tp->t_rawq.c_cc = 0; 688: tp->t_rawq.c_cf = tp->t_rawq.c_cl = 0; 689: while ((c = getc(&tq)) >= 0) 690: ttyinput(c, tp); 691: tp->t_state &= ~TS_TYPEN; 692: } 693: 694: /* 695: * Place a character on raw TTY input queue, 696: * putting in delimiters and waking up top 697: * half as needed. Also echo if required. 698: * The arguments are the character and the 699: * appropriate tty structure. 700: */ 701: ttyinput(c, tp) 702: register c; 703: register struct tty *tp; 704: { 705: register int t_flags = tp->t_flags; 706: int i; 707: 708: /* 709: * If input is pending take it first. 710: */ 711: if (t_flags&PENDIN) 712: ttypend(tp); 713: tk_nin++; 714: c &= 0377; 715: 716: /* 717: * In tandem mode, check high water mark. 718: */ 719: if (t_flags&TANDEM) 720: ttyblock(tp); 721: 722: if (t_flags&RAW) { 723: /* 724: * Raw mode, just put character 725: * in input q w/o interpretation. 726: */ 727: if (tp->t_rawq.c_cc > TTYHOG) 728: ttyflush(tp, FREAD|FWRITE); 729: else { 730: if (putc(c, &tp->t_rawq) >= 0) 731: ttwakeup(tp); 732: ttyecho(c, tp); 733: } 734: goto endcase; 735: } 736: 737: /* 738: * Ignore any high bit added during 739: * previous ttyinput processing. 740: */ 741: if ((tp->t_state&TS_TYPEN) == 0 && (t_flags&PASS8) == 0) 742: c &= 0177; 743: /* 744: * Check for literal nexting very first 745: */ 746: if (tp->t_state&TS_LNCH) { 747: c |= 0200; 748: tp->t_state &= ~TS_LNCH; 749: } 750: 751: /* 752: * Scan for special characters. This code 753: * is really just a big case statement with 754: * non-constant cases. The bottom of the 755: * case statement is labeled ``endcase'', so goto 756: * it after a case match, or similar. 757: */ 758: if (tp->t_line == NTTYDISC) { 759: if (c == tp->t_lnextc) { 760: if (t_flags&ECHO) 761: ttyout("^\b", tp); 762: tp->t_state |= TS_LNCH; 763: goto endcase; 764: } 765: if (c == tp->t_flushc) { 766: if (t_flags&FLUSHO) 767: tp->t_flags &= ~FLUSHO; 768: else { 769: ttyflush(tp, FWRITE); 770: ttyecho(c, tp); 771: if (tp->t_rawq.c_cc + tp->t_canq.c_cc) 772: ttyretype(tp); 773: tp->t_flags |= FLUSHO; 774: } 775: goto startoutput; 776: } 777: if (c == tp->t_suspc) { 778: if ((t_flags&NOFLSH) == 0) 779: ttyflush(tp, FREAD); 780: ttyecho(c, tp); 781: gsignal(tp->t_pgrp, SIGTSTP); 782: goto endcase; 783: } 784: } 785: 786: /* 787: * Handle start/stop characters. 788: */ 789: if (c == tp->t_stopc) { 790: if ((tp->t_state&TS_TTSTOP) == 0) { 791: tp->t_state |= TS_TTSTOP; 792: (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0); 793: return; 794: } 795: if (c != tp->t_startc) 796: return; 797: goto endcase; 798: } 799: if (c == tp->t_startc) 800: goto restartoutput; 801: 802: /* 803: * Look for interrupt/quit chars. 804: */ 805: if (c == tp->t_intrc || c == tp->t_quitc) { 806: if ((t_flags&NOFLSH) == 0) 807: ttyflush(tp, FREAD|FWRITE); 808: ttyecho(c, tp); 809: gsignal(tp->t_pgrp, c == tp->t_intrc ? SIGINT : SIGQUIT); 810: goto endcase; 811: } 812: 813: if (tp->t_flags & LCASE && c <= 0177) { 814: if (tp->t_state&TS_BKSL) { 815: ttyrub(unputc(&tp->t_rawq), tp); 816: if (maptab[c]) 817: c = maptab[c]; 818: c |= 0200; 819: tp->t_state &= ~(TS_BKSL|TS_QUOT); 820: } else if (c >= 'A' && c <= 'Z') 821: c += 'a' - 'A'; 822: else if (c == '\\') 823: tp->t_state |= TS_BKSL; 824: } 825: 826: /* 827: * Cbreak mode, don't process line editing 828: * characters; check high water mark for wakeup. 829: */ 830: if (t_flags&CBREAK) { 831: if (tp->t_rawq.c_cc > TTYHOG) { 832: if (tp->t_outq.c_cc < TTHIWAT(tp) && 833: tp->t_line == NTTYDISC) 834: (void) ttyoutput(CTRL(g), tp); 835: } else if (putc(c, &tp->t_rawq) >= 0) { 836: ttwakeup(tp); 837: ttyecho(c, tp); 838: } 839: goto endcase; 840: } 841: 842: /* 843: * From here on down cooked mode character 844: * processing takes place. 845: */ 846: if ((tp->t_state&TS_QUOT) && 847: (c == tp->t_erase || c == tp->t_kill)) { 848: ttyrub(unputc(&tp->t_rawq), tp); 849: c |= 0200; 850: } 851: if (c == tp->t_erase) { 852: if (tp->t_rawq.c_cc) 853: ttyrub(unputc(&tp->t_rawq), tp); 854: goto endcase; 855: } 856: if (c == tp->t_kill) { 857: if (t_flags&CRTKIL && 858: tp->t_rawq.c_cc == tp->t_rocount) { 859: while (tp->t_rawq.c_cc) 860: ttyrub(unputc(&tp->t_rawq), tp); 861: } else { 862: ttyecho(c, tp); 863: ttyecho('\n', tp); 864: while (getc(&tp->t_rawq) > 0) 865: ; 866: tp->t_rocount = 0; 867: } 868: tp->t_state &= ~TS_LOCAL; 869: goto endcase; 870: } 871: 872: /* 873: * New line discipline, 874: * check word erase/reprint line. 875: */ 876: if (tp->t_line == NTTYDISC) { 877: if (c == tp->t_werasc) { 878: if (tp->t_rawq.c_cc == 0) 879: goto endcase; 880: do { 881: c = unputc(&tp->t_rawq); 882: if (c != ' ' && c != '\t') 883: goto erasenb; 884: ttyrub(c, tp); 885: } while (tp->t_rawq.c_cc); 886: goto endcase; 887: erasenb: 888: do { 889: ttyrub(c, tp); 890: if (tp->t_rawq.c_cc == 0) 891: goto endcase; 892: c = unputc(&tp->t_rawq); 893: } while (c != ' ' && c != '\t'); 894: (void) putc(c, &tp->t_rawq); 895: goto endcase; 896: } 897: if (c == tp->t_rprntc) { 898: ttyretype(tp); 899: goto endcase; 900: } 901: } 902: 903: /* 904: * Check for input buffer overflow 905: */ 906: if (tp->t_rawq.c_cc+tp->t_canq.c_cc >= TTYHOG) { 907: if (tp->t_line == NTTYDISC) 908: (void) ttyoutput(CTRL(g), tp); 909: goto endcase; 910: } 911: 912: /* 913: * Put data char in q for user and 914: * wakeup on seeing a line delimiter. 915: */ 916: if (putc(c, &tp->t_rawq) >= 0) { 917: if (ttbreakc(c, tp)) { 918: tp->t_rocount = 0; 919: catq(&tp->t_rawq, &tp->t_canq); 920: ttwakeup(tp); 921: } else if (tp->t_rocount++ == 0) 922: tp->t_rocol = tp->t_col; 923: tp->t_state &= ~TS_QUOT; 924: if (c == '\\') 925: tp->t_state |= TS_QUOT; 926: if (tp->t_state&TS_ERASE) { 927: tp->t_state &= ~TS_ERASE; 928: (void) ttyoutput('/', tp); 929: } 930: i = tp->t_col; 931: ttyecho(c, tp); 932: if (c == tp->t_eofc && t_flags&ECHO) { 933: i = MIN(2, tp->t_col - i); 934: while (i > 0) { 935: (void) ttyoutput('\b', tp); 936: i--; 937: } 938: } 939: } 940: endcase: 941: /* 942: * If DEC-style start/stop is enabled don't restart 943: * output until seeing the start character. 944: */ 945: if (t_flags&DECCTQ && tp->t_state&TS_TTSTOP && 946: tp->t_startc != tp->t_stopc) 947: return; 948: restartoutput: 949: tp->t_state &= ~TS_TTSTOP; 950: tp->t_flags &= ~FLUSHO; 951: startoutput: 952: ttstart(tp); 953: } 954: 955: /* 956: * Put character on TTY output queue, adding delays, 957: * expanding tabs, and handling the CR/NL bit. 958: * This is called both from the top half for output, 959: * and from interrupt level for echoing. 960: * The arguments are the character and the tty structure. 961: * Returns < 0 if putc succeeds, otherwise returns char to resend 962: * Must be recursive. 963: */ 964: ttyoutput(c, tp) 965: register c; 966: register struct tty *tp; 967: { 968: register char *colp; 969: register ctype; 970: 971: if (tp->t_flags & (RAW|LITOUT)) { 972: if (tp->t_flags&FLUSHO) 973: return (-1); 974: if (putc(c, &tp->t_outq)) 975: return (c); 976: tk_nout++; 977: return (-1); 978: } 979: 980: /* 981: * Ignore EOT in normal mode to avoid 982: * hanging up certain terminals. 983: */ 984: c &= 0177; 985: if (c == CEOT && (tp->t_flags&CBREAK) == 0) 986: return (-1); 987: /* 988: * Turn tabs to spaces as required 989: */ 990: if (c == '\t' && (tp->t_flags&TBDELAY) == XTABS) { 991: register int s; 992: 993: c = 8 - (tp->t_col&7); 994: if ((tp->t_flags&FLUSHO) == 0) { 995: s = spltty(); /* don't interrupt tabs */ 996: c -= b_to_q(" ", c, &tp->t_outq); 997: tk_nout += c; 998: splx(s); 999: } 1000: tp->t_col += c; 1001: return (c ? -1 : '\t'); 1002: } 1003: tk_nout++; 1004: /* 1005: * for upper-case-only terminals, 1006: * generate escapes. 1007: */ 1008: if (tp->t_flags&LCASE) { 1009: colp = "({)}!|^~'`"; 1010: while (*colp++) 1011: if (c == *colp++) { 1012: if (ttyoutput('\\', tp) >= 0) 1013: return (c); 1014: c = colp[-2]; 1015: break; 1016: } 1017: if ('A' <= c && c <= 'Z') { 1018: if (ttyoutput('\\', tp) >= 0) 1019: return (c); 1020: } else if ('a' <= c && c <= 'z') 1021: c += 'A' - 'a'; 1022: } 1023: 1024: /* 1025: * turn <nl> to <cr><lf> if desired. 1026: */ 1027: if (c == '\n' && tp->t_flags&CRMOD) 1028: if (ttyoutput('\r', tp) >= 0) 1029: return (c); 1030: if (c == '~' && tp->t_flags&TILDE) 1031: c = '`'; 1032: if ((tp->t_flags&FLUSHO) == 0 && putc(c, &tp->t_outq)) 1033: return (c); 1034: /* 1035: * Calculate delays. 1036: * The numbers here represent clock ticks 1037: * and are not necessarily optimal for all terminals. 1038: * The delays are indicated by characters above 0200. 1039: * In raw mode there are no delays and the 1040: * transmission path is 8 bits wide. 1041: * 1042: * SHOULD JUST ALLOW USER TO SPECIFY DELAYS 1043: */ 1044: colp = &tp->t_col; 1045: ctype = partab[c]; 1046: c = 0; 1047: switch (ctype&077) { 1048: 1049: case ORDINARY: 1050: (*colp)++; 1051: 1052: case CONTROL: 1053: break; 1054: 1055: case BACKSPACE: 1056: if (*colp) 1057: (*colp)--; 1058: break; 1059: 1060: /* 1061: * This macro is close enough to the correct thing; 1062: * it should be replaced by real user settable delays 1063: * in any event... 1064: */ 1065: #define mstohz(ms) (((ms) * hz) >> 10) 1066: case NEWLINE: 1067: ctype = (tp->t_flags >> 8) & 03; 1068: if (ctype == 1) { /* tty 37 */ 1069: if (*colp > 0) { 1070: c = (((unsigned)*colp) >> 4) + 3; 1071: if ((unsigned)c > 6) 1072: c = 6; 1073: } 1074: } else if (ctype == 2) /* vt05 */ 1075: c = mstohz(100); 1076: *colp = 0; 1077: break; 1078: 1079: case TAB: 1080: ctype = (tp->t_flags >> 10) & 03; 1081: if (ctype == 1) { /* tty 37 */ 1082: c = 1 - (*colp | ~07); 1083: if (c < 5) 1084: c = 0; 1085: } 1086: *colp |= 07; 1087: (*colp)++; 1088: break; 1089: 1090: case VTAB: 1091: if (tp->t_flags&VTDELAY) /* tty 37 */ 1092: c = 0177; 1093: break; 1094: 1095: case RETURN: 1096: ctype = (tp->t_flags >> 12) & 03; 1097: if (ctype == 1) /* tn 300 */ 1098: c = mstohz(83); 1099: else if (ctype == 2) /* ti 700 */ 1100: c = mstohz(166); 1101: else if (ctype == 3) { /* concept 100 */ 1102: int i; 1103: 1104: if ((i = *colp) >= 0) 1105: for (; i < 9; i++) 1106: (void) putc(0177, &tp->t_outq); 1107: } 1108: *colp = 0; 1109: } 1110: if (c && (tp->t_flags&FLUSHO) == 0) 1111: (void) putc(c|0200, &tp->t_outq); 1112: return (-1); 1113: } 1114: #undef mstohz 1115: 1116: /* 1117: * Called from device's read routine after it has 1118: * calculated the tty-structure given as argument. 1119: */ 1120: ttread(tp, uio) 1121: register struct tty *tp; 1122: struct uio *uio; 1123: { 1124: register struct clist *qp; 1125: register c, t_flags; 1126: int s, first, error = 0; 1127: 1128: loop: 1129: /* 1130: * Take any pending input first. 1131: */ 1132: s = spltty(); 1133: if (tp->t_flags&PENDIN) 1134: ttypend(tp); 1135: splx(s); 1136: 1137: if ((tp->t_state&TS_CARR_ON)==0) 1138: return (EIO); 1139: 1140: /* 1141: * Hang process if it's in the background. 1142: */ 1143: if (tp == u.u_ttyp && u.u_procp->p_pgrp != tp->t_pgrp) { 1144: if ((u.u_procp->p_sigignore & sigmask(SIGTTIN)) || 1145: (u.u_procp->p_sigmask & sigmask(SIGTTIN)) || 1146: u.u_procp->p_flag&SVFORK) 1147: return (EIO); 1148: gsignal(u.u_procp->p_pgrp, SIGTTIN); 1149: sleep((caddr_t)&lbolt, TTIPRI); 1150: goto loop; 1151: } 1152: t_flags = tp->t_flags; 1153: 1154: /* 1155: * In raw mode take characters directly from the 1156: * raw queue w/o processing. Interlock against 1157: * device interrupts when interrogating rawq. 1158: */ 1159: if (t_flags&RAW) { 1160: s = spltty(); 1161: if (tp->t_rawq.c_cc <= 0) { 1162: if ((tp->t_state&TS_CARR_ON) == 0 || 1163: (tp->t_state&TS_NBIO)) { 1164: splx(s); 1165: return (EWOULDBLOCK); 1166: } 1167: sleep((caddr_t)&tp->t_rawq, TTIPRI); 1168: splx(s); 1169: goto loop; 1170: } 1171: splx(s); 1172: while (!error && tp->t_rawq.c_cc && uio->uio_resid) 1173: error = ureadc(getc(&tp->t_rawq), uio); 1174: goto checktandem; 1175: } 1176: 1177: /* 1178: * In cbreak mode use the rawq, otherwise 1179: * take characters from the canonicalized q. 1180: */ 1181: qp = t_flags&CBREAK ? &tp->t_rawq : &tp->t_canq; 1182: 1183: /* 1184: * No input, sleep on rawq awaiting hardware 1185: * receipt and notification. 1186: */ 1187: s = spltty(); 1188: if (qp->c_cc <= 0) { 1189: if ((tp->t_state&TS_CARR_ON) == 0 || 1190: (tp->t_state&TS_NBIO)) { 1191: splx(s); 1192: return (EWOULDBLOCK); 1193: } 1194: sleep((caddr_t)&tp->t_rawq, TTIPRI); 1195: splx(s); 1196: goto loop; 1197: } 1198: splx(s); 1199: 1200: /* 1201: * Input present, perform input mapping 1202: * and processing (we're not in raw mode). 1203: */ 1204: first = 1; 1205: while ((c = getc(qp)) >= 0) { 1206: if (t_flags&CRMOD && c == '\r') 1207: c = '\n'; 1208: /* 1209: * Check for delayed suspend character. 1210: */ 1211: if (tp->t_line == NTTYDISC && c == tp->t_dsuspc) { 1212: gsignal(tp->t_pgrp, SIGTSTP); 1213: if (first) { 1214: sleep((caddr_t)&lbolt, TTIPRI); 1215: goto loop; 1216: } 1217: break; 1218: } 1219: /* 1220: * Interpret EOF only in cooked mode. 1221: */ 1222: if (c == tp->t_eofc && (t_flags&CBREAK) == 0) 1223: break; 1224: /* 1225: * Give user character. 1226: */ 1227: error = ureadc(t_flags&PASS8 ? c : c & 0177, uio); 1228: if (error) 1229: break; 1230: if (uio->uio_resid == 0) 1231: break; 1232: /* 1233: * In cooked mode check for a "break character" 1234: * marking the end of a "line of input". 1235: */ 1236: if ((t_flags&CBREAK) == 0 && ttbreakc(c, tp)) 1237: break; 1238: first = 0; 1239: } 1240: 1241: checktandem: 1242: /* 1243: * Look to unblock output now that (presumably) 1244: * the input queue has gone down. 1245: */ 1246: if (tp->t_state&TS_TBLOCK && tp->t_rawq.c_cc < TTYHOG/5) 1247: if (putc(tp->t_startc, &tp->t_outq) == 0) { 1248: tp->t_state &= ~TS_TBLOCK; 1249: ttstart(tp); 1250: } 1251: return (error); 1252: } 1253: 1254: /* 1255: * Check the output queue on tp for space for a kernel message 1256: * (from uprintf/tprintf). Allow some space over the normal 1257: * hiwater mark so we don't lose messages due to normal flow 1258: * control, but don't let the tty run amok. 1259: */ 1260: ttycheckoutq(tp, wait) 1261: register struct tty *tp; 1262: int wait; 1263: { 1264: int hiwat, s; 1265: 1266: hiwat = TTHIWAT(tp); 1267: s = spltty(); 1268: if (tp->t_outq.c_cc > hiwat + 200) 1269: while (tp->t_outq.c_cc > hiwat) { 1270: ttstart(tp); 1271: if (wait == 0) { 1272: splx(s); 1273: return (0); 1274: } 1275: tp->t_state |= TS_ASLEEP; 1276: sleep((caddr_t)&tp->t_outq, TTOPRI); 1277: } 1278: splx(s); 1279: return (1); 1280: } 1281: 1282: /* 1283: * Called from the device's write routine after it has 1284: * calculated the tty-structure given as argument. 1285: */ 1286: ttwrite(tp, uio) 1287: register struct tty *tp; 1288: register struct uio *uio; 1289: { 1290: register char *cp; 1291: register int cc, ce, c; 1292: int i, hiwat, cnt, error, s; 1293: char obuf[OBUFSIZ]; 1294: 1295: hiwat = TTHIWAT(tp); 1296: cnt = uio->uio_resid; 1297: error = 0; 1298: loop: 1299: if ((tp->t_state&TS_CARR_ON) == 0) 1300: return (EIO); 1301: /* 1302: * Hang the process if it's in the background. 1303: */ 1304: if (u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp && 1305: (tp->t_flags&TOSTOP) && (u.u_procp->p_flag&SVFORK)==0 && 1306: !(u.u_procp->p_sigignore & sigmask(SIGTTOU)) && 1307: !(u.u_procp->p_sigmask & sigmask(SIGTTOU))) { 1308: gsignal(u.u_procp->p_pgrp, SIGTTOU); 1309: sleep((caddr_t)&lbolt, TTIPRI); 1310: goto loop; 1311: } 1312: 1313: /* 1314: * Process the user's data in at most OBUFSIZ 1315: * chunks. Perform lower case simulation and 1316: * similar hacks. Keep track of high water 1317: * mark, sleep on overflow awaiting device aid 1318: * in acquiring new space. 1319: */ 1320: while (uio->uio_resid > 0) { 1321: /* 1322: * Grab a hunk of data from the user. 1323: */ 1324: cc = uio->uio_iov->iov_len; 1325: if (cc == 0) { 1326: uio->uio_iovcnt--; 1327: uio->uio_iov++; 1328: if (uio->uio_iovcnt <= 0) 1329: panic("ttwrite"); 1330: continue; 1331: } 1332: if (cc > OBUFSIZ) 1333: cc = OBUFSIZ; 1334: cp = obuf; 1335: error = uiomove(cp, cc, UIO_WRITE, uio); 1336: if (error) 1337: break; 1338: if (tp->t_outq.c_cc > hiwat) 1339: goto ovhiwat; 1340: if (tp->t_flags&FLUSHO) 1341: continue; 1342: /* 1343: * If we're mapping lower case or kludging tildes, 1344: * then we've got to look at each character, so 1345: * just feed the stuff to ttyoutput... 1346: */ 1347: if (tp->t_flags & (LCASE|TILDE)) { 1348: while (cc > 0) { 1349: c = *cp++; 1350: tp->t_rocount = 0; 1351: while ((c = ttyoutput(c, tp)) >= 0) { 1352: /* out of clists, wait a bit */ 1353: ttstart(tp); 1354: sleep((caddr_t)&lbolt, TTOPRI); 1355: tp->t_rocount = 0; 1356: if (cc != 0) { 1357: uio->uio_iov->iov_base -= cc; 1358: uio->uio_iov->iov_len += cc; 1359: uio->uio_resid += cc; 1360: uio->uio_offset -= cc; 1361: } 1362: goto loop; 1363: } 1364: --cc; 1365: if (tp->t_outq.c_cc > hiwat) 1366: goto ovhiwat; 1367: } 1368: continue; 1369: } 1370: /* 1371: * If nothing fancy need be done, grab those characters we 1372: * can handle without any of ttyoutput's processing and 1373: * just transfer them to the output q. For those chars 1374: * which require special processing (as indicated by the 1375: * bits in partab), call ttyoutput. After processing 1376: * a hunk of data, look for FLUSHO so ^O's will take effect 1377: * immediately. 1378: */ 1379: while (cc > 0) { 1380: if (tp->t_flags & (RAW|LITOUT)) 1381: ce = cc; 1382: else { 1383: ce = cc - scanc((unsigned)cc, (caddr_t)cp, 1384: (caddr_t)partab, 077); 1385: /* 1386: * If ce is zero, then we're processing 1387: * a special character through ttyoutput. 1388: */ 1389: if (ce == 0) { 1390: tp->t_rocount = 0; 1391: if (ttyoutput(*cp, tp) >= 0) { 1392: /* no c-lists, wait a bit */ 1393: ttstart(tp); 1394: sleep((caddr_t)&lbolt, TTOPRI); 1395: if (cc != 0) { 1396: uio->uio_iov->iov_base -= cc; 1397: uio->uio_iov->iov_len += cc; 1398: uio->uio_resid += cc; 1399: uio->uio_offset -= cc; 1400: } 1401: goto loop; 1402: } 1403: cp++, cc--; 1404: if (tp->t_flags&FLUSHO || 1405: tp->t_outq.c_cc > hiwat) 1406: goto ovhiwat; 1407: continue; 1408: } 1409: } 1410: /* 1411: * A bunch of normal characters have been found, 1412: * transfer them en masse to the output queue and 1413: * continue processing at the top of the loop. 1414: * If there are any further characters in this 1415: * <= OBUFSIZ chunk, the first should be a character 1416: * requiring special handling by ttyoutput. 1417: */ 1418: tp->t_rocount = 0; 1419: i = b_to_q(cp, ce, &tp->t_outq); 1420: ce -= i; 1421: tp->t_col += ce; 1422: cp += ce, cc -= ce, tk_nout += ce; 1423: if (i > 0) { 1424: /* out of c-lists, wait a bit */ 1425: ttstart(tp); 1426: sleep((caddr_t)&lbolt, TTOPRI); 1427: uio->uio_iov->iov_base -= cc; 1428: uio->uio_iov->iov_len += cc; 1429: uio->uio_resid += cc; 1430: uio->uio_offset -= cc; 1431: goto loop; 1432: } 1433: if (tp->t_flags&FLUSHO || tp->t_outq.c_cc > hiwat) 1434: goto ovhiwat; 1435: } 1436: } 1437: ttstart(tp); 1438: return (error); 1439: 1440: ovhiwat: 1441: s = spltty(); 1442: if (cc != 0) { 1443: uio->uio_iov->iov_base -= cc; 1444: uio->uio_iov->iov_len += cc; 1445: uio->uio_resid += cc; 1446: uio->uio_offset -= cc; 1447: } 1448: /* 1449: * This can only occur if FLUSHO 1450: * is also set in t_flags. 1451: */ 1452: if (tp->t_outq.c_cc <= hiwat) { 1453: splx(s); 1454: goto loop; 1455: } 1456: ttstart(tp); 1457: if (tp->t_state&TS_NBIO) { 1458: splx(s); 1459: if (uio->uio_resid == cnt) 1460: return (EWOULDBLOCK); 1461: return (0); 1462: } 1463: tp->t_state |= TS_ASLEEP; 1464: sleep((caddr_t)&tp->t_outq, TTOPRI); 1465: splx(s); 1466: goto loop; 1467: } 1468: 1469: /* 1470: * Rubout one character from the rawq of tp 1471: * as cleanly as possible. 1472: */ 1473: ttyrub(c, tp) 1474: register c; 1475: register struct tty *tp; 1476: { 1477: register char *cp; 1478: register int savecol; 1479: int s; 1480: char *nextc(); 1481: 1482: if ((tp->t_flags&ECHO) == 0) 1483: return; 1484: tp->t_flags &= ~FLUSHO; 1485: c &= 0377; 1486: if (tp->t_flags&CRTBS) { 1487: if (tp->t_rocount == 0) { 1488: /* 1489: * Screwed by ttwrite; retype 1490: */ 1491: ttyretype(tp); 1492: return; 1493: } 1494: if (c == ('\t'|0200) || c == ('\n'|0200)) 1495: ttyrubo(tp, 2); 1496: else switch (partab[c&=0177]&0177) { 1497: 1498: case ORDINARY: 1499: if (tp->t_flags&LCASE && c >= 'A' && c <= 'Z') 1500: ttyrubo(tp, 2); 1501: else 1502: ttyrubo(tp, 1); 1503: break; 1504: 1505: case VTAB: 1506: case BACKSPACE: 1507: case CONTROL: 1508: case RETURN: 1509: if (tp->t_flags&CTLECH) 1510: ttyrubo(tp, 2); 1511: break; 1512: 1513: case TAB: 1514: if (tp->t_rocount < tp->t_rawq.c_cc) { 1515: ttyretype(tp); 1516: return; 1517: } 1518: s = spltty(); 1519: savecol = tp->t_col; 1520: tp->t_state |= TS_CNTTB; 1521: tp->t_flags |= FLUSHO; 1522: tp->t_col = tp->t_rocol; 1523: cp = tp->t_rawq.c_cf; 1524: for (; cp; cp = nextc(&tp->t_rawq, cp)) 1525: ttyecho(*cp, tp); 1526: tp->t_flags &= ~FLUSHO; 1527: tp->t_state &= ~TS_CNTTB; 1528: splx(s); 1529: /* 1530: * savecol will now be length of the tab 1531: */ 1532: savecol -= tp->t_col; 1533: tp->t_col += savecol; 1534: if (savecol > 8) 1535: savecol = 8; /* overflow screw */ 1536: while (--savecol >= 0) 1537: (void) ttyoutput('\b', tp); 1538: break; 1539: 1540: default: 1541: panic("ttyrub"); 1542: } 1543: } else if (tp->t_flags&PRTERA) { 1544: if ((tp->t_state&TS_ERASE) == 0) { 1545: (void) ttyoutput('\\', tp); 1546: tp->t_state |= TS_ERASE; 1547: } 1548: ttyecho(c, tp); 1549: } else 1550: ttyecho(tp->t_erase, tp); 1551: tp->t_rocount--; 1552: } 1553: 1554: /* 1555: * Crt back over cnt chars perhaps 1556: * erasing them. 1557: */ 1558: ttyrubo(tp, cnt) 1559: register struct tty *tp; 1560: int cnt; 1561: { 1562: register char *rubostring = tp->t_flags&CRTERA ? "\b \b" : "\b"; 1563: 1564: while (--cnt >= 0) 1565: ttyout(rubostring, tp); 1566: } 1567: 1568: /* 1569: * Reprint the rawq line. 1570: * We assume c_cc has already been checked. 1571: */ 1572: ttyretype(tp) 1573: register struct tty *tp; 1574: { 1575: register char *cp; 1576: char *nextc(); 1577: int s; 1578: 1579: if (tp->t_rprntc != 0377) 1580: ttyecho(tp->t_rprntc, tp); 1581: (void) ttyoutput('\n', tp); 1582: s = spltty(); 1583: for (cp = tp->t_canq.c_cf; cp; cp = nextc(&tp->t_canq, cp)) 1584: ttyecho(*cp, tp); 1585: for (cp = tp->t_rawq.c_cf; cp; cp = nextc(&tp->t_rawq, cp)) 1586: ttyecho(*cp, tp); 1587: tp->t_state &= ~TS_ERASE; 1588: splx(s); 1589: tp->t_rocount = tp->t_rawq.c_cc; 1590: tp->t_rocol = 0; 1591: } 1592: 1593: /* 1594: * Echo a typed character to the terminal 1595: */ 1596: ttyecho(c, tp) 1597: register c; 1598: register struct tty *tp; 1599: { 1600: 1601: if ((tp->t_state&TS_CNTTB) == 0) 1602: tp->t_flags &= ~FLUSHO; 1603: if ((tp->t_flags&ECHO) == 0) 1604: return; 1605: c &= 0377; 1606: if (tp->t_flags&RAW) { 1607: (void) ttyoutput(c, tp); 1608: return; 1609: } 1610: if (c == '\r' && tp->t_flags&CRMOD) 1611: c = '\n'; 1612: if (tp->t_flags&CTLECH) { 1613: if ((c&0177) <= 037 && c!='\t' && c!='\n' || (c&0177)==0177) { 1614: (void) ttyoutput('^', tp); 1615: c &= 0177; 1616: if (c == 0177) 1617: c = '?'; 1618: else if (tp->t_flags&LCASE) 1619: c += 'a' - 1; 1620: else 1621: c += 'A' - 1; 1622: } 1623: } 1624: (void) ttyoutput(c&0177, tp); 1625: } 1626: 1627: /* 1628: * Is c a break char for tp? 1629: */ 1630: ttbreakc(c, tp) 1631: register c; 1632: register struct tty *tp; 1633: { 1634: return (c == '\n' || c == tp->t_eofc || c == tp->t_brkc || 1635: c == '\r' && (tp->t_flags&CRMOD)); 1636: } 1637: 1638: /* 1639: * send string cp to tp 1640: */ 1641: ttyout(cp, tp) 1642: register char *cp; 1643: register struct tty *tp; 1644: { 1645: register char c; 1646: 1647: while (c = *cp++) 1648: (void) ttyoutput(c, tp); 1649: } 1650: 1651: ttwakeup(tp) 1652: struct tty *tp; 1653: { 1654: 1655: if (tp->t_rsel) { 1656: selwakeup(tp->t_rsel, tp->t_state&TS_RCOLL); 1657: tp->t_state &= ~TS_RCOLL; 1658: tp->t_rsel = 0; 1659: } 1660: if (tp->t_state & TS_ASYNC) 1661: gsignal(tp->t_pgrp, SIGIO); 1662: wakeup((caddr_t)&tp->t_rawq); 1663: }