1: /* 2: * SCCS id @(#)ttynew.c 2.1 (Berkeley) 8/5/83 3: */ 4: 5: /* 6: * New version of tty driver, supported 7: * as NTTYDISC. Adapted from a tty.c written 8: * by J.E.Kulp of IIASA, Austria (jekulp@mc) 9: */ 10: #include "param.h" 11: #ifdef UCB_NTTY 12: #include <sys/systm.h> 13: #include <sys/dir.h> 14: #include <sys/user.h> 15: #include <sys/tty.h> 16: #include <sys/proc.h> 17: #ifdef MPX_FILS 18: #include <sys/mx.h> 19: #endif 20: #include <sys/inode.h> 21: #include <sys/file.h> 22: #include <sys/reg.h> 23: #include <sys/conf.h> 24: #include <sys/buf.h> 25: 26: #ifndef UCB_NET 27: #define ttsignal(tp, c) gsignal((tp)->t_pgrp, c) 28: #define ttwakeup(tp) wakeup((caddr_t) &(tp)->t_rawq) 29: #endif 30: 31: extern char partab[]; 32: 33: /* 34: * Input mapping table-- if an entry is non-zero, when the 35: * corresponding character is typed preceded by "\" the escape 36: * sequence is replaced by the table value. Mostly used for 37: * upper-case only terminals. 38: */ 39: 40: char maptab[]; /* see tty.c */ 41: 42: /* 43: * shorthand 44: */ 45: #define q1 tp->t_rawq 46: #define q2 tp->t_canq 47: #define q3 tp->t_outq 48: #define q4 tp->t_un.t_ctlq 49: 50: #define OBUFSIZ 100 51: 52: /* 53: * routine called on switching to NTTYDISC 54: */ 55: ntyopen(tp) 56: register struct tty *tp; 57: { 58: if (tp->t_line != NTTYDISC) 59: wflushtty(tp); 60: } 61: 62: /* 63: * clean tp on exiting NTTYDISC 64: */ 65: ntyclose(tp) 66: struct tty *tp; 67: { 68: wflushtty(tp); 69: } 70: 71: /* 72: * reinput pending characters after state switch 73: * call at spl5(). 74: */ 75: ttypend(tp) 76: register struct tty *tp; 77: { 78: struct clist tq; 79: register c; 80: 81: tp->t_local &= ~LPENDIN; 82: tp->t_lstate |= LSTYPEN; 83: tq = tp->t_rawq; 84: tp->t_rawq.c_cc = 0; 85: tp->t_rawq.c_cf = tp->t_rawq.c_cl = NULL; 86: while ((c = getc(&tq)) >= 0) 87: ntyinput(c, tp); 88: tp->t_lstate &= ~LSTYPEN; 89: } 90: 91: /* 92: * Place a character on raw TTY input queue, putting in delimiters 93: * and waking up top half as needed. 94: * Also echo if required. 95: * The arguments are the character and the appropriate 96: * tty structure. 97: */ 98: ntyinput(c, tp) 99: register c; 100: register struct tty *tp; 101: { 102: register int t_flags; 103: int i; 104: 105: if (tp->t_local&LPENDIN) 106: ttypend(tp); 107: tk_nin++; 108: c &= 0377; 109: t_flags = tp->t_flags; 110: if (t_flags&TANDEM) 111: ttyblock(tp); 112: if ((t_flags&RAW)==0) { 113: if ((tp->t_lstate&LSTYPEN) == 0) 114: c &= 0177; 115: /* check for literal nexting before any other processing */ 116: if (tp->t_lstate&LSLNCH) { 117: c |= 0200; 118: tp->t_lstate &= ~LSLNCH; 119: } 120: if (c==tlun.t_lnextc) { 121: if (tp->t_flags&ECHO) 122: ntyout("^\b", tp); 123: tp->t_lstate |= LSLNCH; 124: /* check for output control functions */ 125: } else if (c==tun.t_stopc) { 126: if ((tp->t_state&TTSTOP)==0) { 127: tp->t_state |= TTSTOP; 128: (*cdevsw[major(tp->t_dev)].d_stop)(tp,0); 129: return; 130: } 131: if (c!=tun.t_startc) 132: return; 133: } else if (c==tun.t_startc) { 134: tp->t_state &= ~TTSTOP; 135: tp->t_local &= ~LFLUSHO; 136: ttstart(tp); 137: return; 138: /* check for input interrupts (and flushed output) */ 139: } else if (c==tlun.t_flushc) { 140: if (tp->t_local & LFLUSHO) 141: tp->t_local &= ~LFLUSHO; 142: else { 143: flushtty(tp, FWRITE); 144: ntyecho(c, tp); 145: if (tp->t_rawq.c_cc+tp->t_canq.c_cc) 146: ntyretype(tp); 147: tp->t_local |= LFLUSHO; 148: } 149: ttstart(tp); 150: return; 151: #ifdef MENLO_JCL 152: } else if (c==tlun.t_suspc || c==tun.t_intrc || 153: c==tun.t_quitc) { 154: if ((tp->t_local & LNOFLSH) == 0) 155: flushtty(tp, c==tlun.t_suspc ? FREAD : FREAD|FWRITE); 156: ntyecho(c, tp); 157: c = c==tun.t_intrc ? SIGINT : 158: ((c==tun.t_quitc) ? SIGQUIT : SIGTSTP); 159: #else 160: } else if (c==tun.t_intrc || c==tun.t_quitc) { 161: if ((tp->t_local & LNOFLSH) == 0) 162: flushtty(tp, FREAD|FWRITE); 163: ntyecho(c, tp); 164: c = c==tun.t_intrc ? SIGINT : SIGQUIT; 165: #endif 166: #ifdef MPX_FILS 167: if (tp->t_chan) 168: scontrol(tp->t_chan, M_SIG, c); 169: else 170: #endif 171: ttsignal(tp, c); 172: /* check for buffer editing functions - cooked mode */ 173: } else if ((t_flags&CBREAK) == 0) { 174: if ((tp->t_lstate&LSQUOT) && 175: (c==tp->t_erase||c==tp->t_kill)) { 176: ntyrub(unputc(&tp->t_rawq), tp); 177: c |= 0200; 178: } 179: if (c==tp->t_erase) { 180: if (tp->t_rawq.c_cc) 181: ntyrub(unputc(&tp->t_rawq), tp); 182: } else if (c==tp->t_kill) { 183: if (tp->t_local&LCRTKIL && 184: tp->t_rawq.c_cc == tp->t_rocount) { 185: while (tp->t_rawq.c_cc) 186: ntyrub(unputc(&tp->t_rawq), tp); 187: } else { 188: ntyecho(c, tp); 189: ntyecho('\n', tp); 190: while (getc(&tp->t_rawq) > 0) 191: ; 192: tp->t_rocount = 0; 193: } 194: tp->t_lstate = 0; 195: } else if (c==tlun.t_werasc) { 196: if (tp->t_rawq.c_cc == 0) 197: goto out; 198: do { 199: c = unputc(&tp->t_rawq); 200: if (c != ' ' && c != '\t') 201: goto erasenb; 202: ntyrub(c, tp); 203: } while (tp->t_rawq.c_cc); 204: goto out; 205: erasenb: 206: do { 207: ntyrub(c, tp); 208: if (tp->t_rawq.c_cc == 0) 209: goto out; 210: c = unputc(&tp->t_rawq); 211: } while (c != ' ' && c != '\t'); 212: (void) putc(c, &tp->t_rawq); 213: } else if (c==tlun.t_rprntc) { 214: ntyretype(tp); 215: /* check for cooked mode input buffer overflow */ 216: } else if (tp->t_rawq.c_cc + tp->t_canq.c_cc > TTYHOG) { 217: /* we should start a timeout that flushes the 218: buffer if it stays full - same in CBREAK */ 219: if (tp->t_outq.c_cc < TTHIWAT(tp)) 220: (void) ntyoutput(CTRL(g), tp); 221: /* put data char in q for user and wakeup if a break char */ 222: } else if (putc(c, &tp->t_rawq) >= 0) { 223: if (!ntbreakc(c, tp)) { 224: if (tp->t_rocount++ == 0) 225: tp->t_rocol = tp->t_col; 226: } else { 227: tp->t_rocount = 0; 228: catq(&tp->t_rawq, &tp->t_canq); 229: #ifdef MPX_FILS 230: if (tp->t_chan) 231: (void) sdata(tp->t_chan); 232: else 233: #endif 234: ttwakeup(tp); 235: #ifdef MENLO_JCL 236: if (tp->t_local&LINTRUP) 237: ttsignal(tp, SIGTINT); 238: #endif 239: } 240: tp->t_lstate &= ~LSQUOT; 241: if (c == '\\') 242: tp->t_lstate |= LSQUOT; 243: if (tp->t_lstate&LSERASE) { 244: tp->t_lstate &= ~LSERASE; 245: (void) ntyoutput('/', tp); 246: } 247: i = tp->t_col; 248: ntyecho(c, tp); 249: if (c==tun.t_eofc && tp->t_flags&ECHO) { 250: i = MIN(2, tp->t_col - i); 251: while (i > 0) { 252: (void) ntyoutput('\b', tp); 253: i--; 254: } 255: } 256: } 257: /* CBREAK mode */ 258: } else if (tp->t_rawq.c_cc > TTYHOG) { 259: if (tp->t_outq.c_cc < TTHIWAT(tp)) 260: (void) ntyoutput(CTRL(g), tp); 261: } else if (putc(c, &tp->t_rawq) >= 0) { 262: #ifdef MENLO_JCL 263: if (tp->t_local&LINTRUP) 264: ttsignal(tp, SIGTINT); 265: #endif 266: #ifdef MPX_FILS 267: if (tp->t_chan) 268: (void) sdata(tp->t_chan); 269: else 270: #endif 271: ttwakeup(tp); 272: ntyecho(c, tp); 273: } 274: /* RAW mode */ 275: } else if (tp->t_rawq.c_cc > TTYHOG) 276: flushtty(tp, FREAD|FWRITE); 277: else { 278: if (putc(c, &tp->t_rawq) >= 0) { 279: #ifdef MENLO_JCL 280: if (tp->t_local&LINTRUP) 281: ttsignal(tp, SIGTINT); 282: #endif 283: #ifdef MPX_FILS 284: if (tp->t_chan) 285: (void) sdata(tp->t_chan); 286: else 287: #endif 288: ttwakeup(tp); 289: } 290: ntyecho(c, tp); 291: } 292: out: 293: if (tp->t_local & LDECCTQ && tp->t_state & TTSTOP) 294: return; 295: tp->t_state &= ~TTSTOP; 296: tp->t_local &= ~LFLUSHO; 297: ttstart(tp); 298: } 299: 300: /* 301: * put character on TTY output queue, adding delays, 302: * expanding tabs, and handling the CR/NL bit. 303: * It is called both from the top half for output, and from 304: * interrupt level for echoing. 305: * The arguments are the character and the tty structure. 306: * Returns < 0 if putc succeeds, otherwise returns char to resend 307: * Must be recursive. 308: */ 309: ntyoutput(c, tp) 310: register c; 311: register struct tty *tp; 312: { 313: register char *colp; 314: register ctype; 315: 316: if (tp->t_flags&RAW || tp->t_local&LLITOUT) { 317: if (tp->t_local&LFLUSHO) 318: return (-1); 319: if (putc(c, &tp->t_outq)) 320: return(c); 321: tk_nout++; 322: return (-1); 323: } 324: /* 325: * Ignore EOT in normal mode to avoid hanging up 326: * certain terminals. 327: */ 328: c &= 0177; 329: if (c==CEOT && (tp->t_flags&CBREAK)==0) 330: return (-1); 331: /* 332: * Turn tabs to spaces as required 333: */ 334: if (c=='\t' && (tp->t_flags&TBDELAY)==XTABS) { 335: register int s; 336: 337: c = 8 - (tp->t_col&7); 338: if ((tp->t_local&LFLUSHO) == 0) { 339: s = spl5(); /* don't interrupt tabs */ 340: c -= b_to_q(" ", c, &tp->t_outq); 341: tk_nout += c; 342: splx(s); 343: } 344: tp->t_col += c; 345: return (c ? -1 : '\t'); 346: } 347: tk_nout++; 348: /* 349: * for upper-case-only terminals, 350: * generate escapes. 351: */ 352: if (tp->t_flags&LCASE) { 353: colp = "({)}!|^~'`"; 354: while(*colp++) 355: if(c == *colp++) { 356: if (ntyoutput('\\', tp) >= 0) 357: return (c); 358: c = colp[-2]; 359: break; 360: } 361: if ('a'<=c && c<='z') 362: c += 'A' - 'a'; 363: } 364: /* 365: * turn <nl> to <cr><lf> if desired. 366: */ 367: if (c=='\n' && tp->t_flags&CRMOD) 368: if (ntyoutput('\r', tp) >= 0) 369: return (c); 370: if (c=='~' && tp->t_local<ILDE) 371: c = '`'; 372: if ((tp->t_local&LFLUSHO) == 0 && putc(c, &tp->t_outq)) 373: return (c); 374: /* 375: * Calculate delays. 376: * The numbers here represent clock ticks 377: * and are not necessarily optimal for all terminals. 378: * The delays are indicated by characters above 0200. 379: * In raw mode there are no delays and the 380: * transmission path is 8 bits wide. 381: */ 382: colp = &tp->t_col; 383: ctype = partab[c]; 384: c = 0; 385: switch (ctype&077) { 386: 387: case ORDINARY: 388: (*colp)++; 389: 390: case CONTROL: 391: break; 392: 393: case BACKSPACE: 394: if (*colp) 395: (*colp)--; 396: break; 397: 398: case NEWLINE: 399: ctype = (tp->t_flags >> 8) & 03; 400: if(ctype == 1) { /* tty 37 */ 401: if (*colp) 402: c = MAX(((unsigned)*colp>>4) + 3, (unsigned)6); 403: } else 404: if(ctype == 2) { /* vt05 */ 405: c = 6; 406: } 407: *colp = 0; 408: break; 409: 410: case TAB: 411: ctype = (tp->t_flags >> 10) & 03; 412: if(ctype == 1) { /* tty 37 */ 413: c = 1 - (*colp | ~07); 414: if(c < 5) 415: c = 0; 416: } 417: *colp |= 07; 418: (*colp)++; 419: break; 420: 421: case VTAB: 422: if(tp->t_flags & VTDELAY) /* tty 37 */ 423: c = 0177; 424: break; 425: 426: case RETURN: 427: ctype = (tp->t_flags >> 12) & 03; 428: if(ctype == 1) { /* tn 300 */ 429: c = 5; 430: } else if(ctype == 2) { /* ti 700 */ 431: c = 10; 432: } else if(ctype == 3) { /* concept 100 */ 433: int i; 434: if ((i = *colp) >= 0) 435: for (; i<9; i++) 436: (void) putc(0177, &tp->t_outq); 437: } 438: *colp = 0; 439: } 440: if(c && (tp->t_local&LFLUSHO) == 0) 441: (void) putc(c|0200, &tp->t_outq); 442: return (-1); 443: } 444: 445: /* 446: * Called from device's read routine after it has 447: * calculated the tty-structure given as argument. 448: */ 449: ntread(tp) 450: register struct tty *tp; 451: { 452: register struct clist *qp; 453: register c, first; 454: 455: if ((tp->t_state&CARR_ON)==0) 456: return(0); 457: loop: 458: (void) _spl5(); 459: if (tp->t_local&LPENDIN) 460: ttypend(tp); 461: (void) _spl0(); 462: #ifdef MENLO_JCL 463: while (tp == u.u_ttyp && u.u_procp->p_pgrp != tp->t_pgrp) { 464: if (u.u_signal[SIGTTIN] == SIG_IGN || 465: u.u_signal[SIGTTIN] == SIG_HOLD || 466: (u.u_procp->p_flag&SDETACH)) 467: return (0); 468: gsignal(u.u_procp->p_pgrp, SIGTTIN); 469: sleep((caddr_t)&lbolt, TTIPRI); 470: } 471: #endif 472: if (tp->t_flags&RAW) { 473: (void) _spl5(); 474: if (tp->t_rawq.c_cc <= 0) { 475: #ifdef MPX_FILS 476: if ((tp->t_state&CARR_ON)==0 || tp->t_chan!=NULL 477: #else 478: if ((tp->t_state&CARR_ON)==0 479: #endif 480: #ifdef UCB_NET 481: || (tp->t_state&TS_NBIO) 482: #endif 483: ) 484: { 485: (void) _spl0(); 486: return (0); 487: } 488: #ifdef MENLO_JCL 489: if (tp->t_local&LINTRUP && 490: u.u_signal[SIGTINT] != SIG_DFL) { 491: u.u_error = EWOULDBLOCK; 492: (void) _spl0(); 493: return (0); 494: } 495: #endif 496: sleep((caddr_t)&tp->t_rawq, TTIPRI); 497: (void) _spl0(); 498: goto loop; 499: } 500: (void) _spl0(); 501: while (tp->t_rawq.c_cc && passc(getc(&tp->t_rawq))>=0) 502: ; 503: } else { 504: qp = tp->t_flags & CBREAK ? &tp->t_rawq : &tp->t_canq; 505: (void) _spl5(); 506: if (qp->c_cc <= 0) { 507: #ifdef MPX_FILS 508: if ((tp->t_state&CARR_ON)==0 || tp->t_chan!=NULL 509: #else 510: if ((tp->t_state&CARR_ON)==0 511: #endif 512: #ifdef UCB_NET 513: || (tp->t_state&TS_NBIO) 514: #endif 515: ) 516: { 517: (void) _spl0(); 518: return (0); 519: } 520: #ifdef MENLO_JCL 521: if (tp->t_local&LINTRUP && 522: u.u_signal[SIGTINT] != SIG_DFL) { 523: u.u_error = EWOULDBLOCK; 524: (void) _spl0(); 525: return (0); 526: } 527: #endif 528: sleep((caddr_t)&tp->t_rawq, TTIPRI); 529: (void) _spl0(); 530: goto loop; 531: } 532: (void) _spl0(); 533: first = 1; 534: while ((c = getc(qp)) >= 0) { 535: if (tp->t_flags&CRMOD && c == '\r') 536: c = '\n'; 537: if (tp->t_flags&LCASE && c <= 0177) 538: if (tp->t_lstate&LSBKSL) { 539: if (maptab[c]) 540: c = maptab[c]; 541: tp->t_lstate &= ~LSBKSL; 542: } else if (c >= 'A' && c <= 'Z') 543: c += 'a' - 'A'; 544: else if (c == '\\') { 545: tp->t_lstate |= LSBKSL; 546: continue; 547: } 548: #ifdef MENLO_JCL 549: if (c == tlun.t_dsuspc) { 550: ttsignal(tp, SIGTSTP); 551: if (first) { 552: sleep((caddr_t)&lbolt, TTIPRI); 553: goto loop; 554: } 555: break; 556: } 557: #endif 558: if (c == tun.t_eofc && (tp->t_flags&CBREAK)==0) 559: break; 560: if (passc(c & 0177) < 0) 561: break; 562: if ((tp->t_flags&CBREAK)==0 && ntbreakc(c, tp)) 563: break; 564: first = 0; 565: } 566: tp->t_lstate &= ~LSBKSL; 567: } 568: 569: /* 570: * Resume output iff: 571: * is blocked 572: * AND (input < threshold OR (cooked mode AND delim_count == 0)) 573: * This makes tandem mode usable for line-mode input. 574: */ 575: if (tp->t_state&TBLOCK && ((tp->t_rawq.c_cc < TTYHOG/5) || 576: (tp->t_delct==0 && ((tp->t_flags&(CBREAK|RAW)) == 0)))) { 577: if (putc(tun.t_startc, &tp->t_outq)==0) { 578: tp->t_state &= ~TBLOCK; 579: ttstart(tp); 580: } 581: } 582: 583: return (tp->t_rawq.c_cc + tp->t_canq.c_cc); 584: } 585: 586: /* 587: * Called from the device's write routine after it has 588: * calculated the tty-structure given as argument. 589: */ 590: caddr_t 591: ntwrite(tp) 592: register struct tty *tp; 593: { 594: register char *cp; 595: register int cc, ce; 596: register i; 597: char obuf[OBUFSIZ]; 598: register c; 599: int hiwat = TTHIWAT(tp); 600: #ifdef UCB_NET 601: int cnt = u.u_count; 602: #endif 603: 604: if ((tp->t_state&CARR_ON)==0) 605: return (NULL); 606: loop: 607: #ifdef MENLO_JCL 608: while (u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp && 609: (tp->t_local<OSTOP) && 610: u.u_signal[SIGTTOU] != SIG_IGN && 611: u.u_signal[SIGTTOU] != SIG_HOLD && 612: (u.u_procp->p_flag&SDETACH)==0) { 613: gsignal(u.u_procp->p_pgrp, SIGTTOU); 614: sleep((caddr_t)&lbolt, TTIPRI); 615: } 616: #endif 617: while (u.u_count) { 618: cc = MIN(u.u_count, OBUFSIZ); 619: cp = obuf; 620: iomove(cp, (unsigned)cc, B_WRITE); 621: if (u.u_error) 622: break; 623: if (tp->t_outq.c_cc > hiwat) 624: goto ovhiwat; 625: if (tp->t_local&LFLUSHO) 626: continue; 627: if (tp->t_flags&LCASE || tp->t_local<ILDE) { 628: while (cc--) { 629: c = *cp++; 630: tp->t_rocount = 0; 631: while((c = ntyoutput(c, tp)) >= 0) { 632: /* out of clists, wait a bit */ 633: ttstart(tp); 634: sleep((caddr_t)&lbolt, TTOPRI); 635: tp->t_rocount = 0; 636: } 637: if (tp->t_outq.c_cc > hiwat) 638: goto ovhiwat; 639: } 640: continue; 641: } 642: while (cc) { 643: if (tp->t_flags&RAW || tp->t_local&LLITOUT) 644: ce = cc; 645: else { 646: ce=0; 647: while(((partab[(*(cp+ce))&0177]&077)==0)&&(ce<cc)) 648: ce++; 649: if (ce==0) { 650: tp->t_rocount = 0; 651: if (ntyoutput(*cp, tp) >= 0) { 652: ttstart(tp); 653: sleep((caddr_t)&lbolt, TTOPRI); 654: continue; 655: } 656: cp++; 657: cc--; 658: if (tp->t_outq.c_cc > hiwat) 659: goto ovhiwat; 660: } 661: } 662: tp->t_rocount = 0; 663: i=b_to_q(cp,ce,&tp->t_outq); 664: ce-=i; 665: tk_nout+=ce; 666: tp->t_col+=ce; 667: cp+=ce; 668: cc-=ce; 669: if (i) { 670: ttstart(tp); 671: sleep((caddr_t)&lbolt, TTOPRI); 672: } 673: if (ce || tp->t_outq.c_cc > hiwat) 674: goto ovhiwat; 675: } 676: } 677: ttstart(tp); 678: return(NULL); 679: 680: ovhiwat: 681: (void) _spl5(); 682: u.u_base -= cc; 683: u.u_offset -= cc; 684: u.u_count += cc; 685: if (tp->t_outq.c_cc <= hiwat) { 686: (void) _spl0(); 687: goto loop; 688: } 689: ttstart(tp); 690: #ifdef UCB_NET 691: if (tp->t_state & TS_NBIO) { 692: if (u.u_count == cnt) 693: u.u_error = EWOULDBLOCK; 694: return(NULL); 695: } 696: #endif 697: tp->t_state |= ASLEEP; 698: #ifdef MPX_FILS 699: if (tp->t_chan) { 700: (void) _spl0(); 701: return ((caddr_t)&tp->t_outq); 702: } 703: #endif 704: sleep((caddr_t)&tp->t_outq, TTOPRI); 705: (void) _spl0(); 706: goto loop; 707: } 708: 709: /* 710: * Rubout one character from the rawq of tp 711: * as cleanly as possible. 712: */ 713: ntyrub(c, tp) 714: register c; 715: register struct tty *tp; 716: { 717: register char *cp; 718: register int savecol; 719: int s; 720: char *nextc(); 721: 722: if ((tp->t_flags&ECHO)==0) 723: return; 724: tp->t_local &= ~LFLUSHO; 725: c &= 0377; 726: if (tp->t_local&LCRTBS) { 727: if (tp->t_rocount == 0) { 728: /* 729: * Screwed by ttwrite; retype 730: */ 731: ntyretype(tp); 732: return; 733: } 734: if (c==('\t'|0200) || c==('\n'|0200)) 735: ntyrubo(tp, 2); 736: else switch(partab[c&=0177] & 0177) { 737: 738: case ORDINARY: 739: ntyrubo(tp, 1); 740: break; 741: 742: case VTAB: 743: case BACKSPACE: 744: case CONTROL: 745: case RETURN: 746: if (tp->t_local & LCTLECH) 747: ntyrubo(tp, 2); 748: break; 749: 750: case TAB: 751: if (tp->t_rocount < tp->t_rawq.c_cc) { 752: ntyretype(tp); 753: return; 754: } 755: s = spl5(); 756: savecol = tp->t_col; 757: tp->t_lstate |= LSCNTTB; 758: tp->t_local |= LFLUSHO; 759: tp->t_col = tp->t_rocol; 760: for (cp = tp->t_rawq.c_cf; cp; cp = nextc(&tp->t_rawq, cp)) 761: ntyecho(lookc(cp), tp); 762: tp->t_local &= ~LFLUSHO; 763: tp->t_lstate &= ~LSCNTTB; 764: splx(s); 765: /* 766: * savecol will now be length of the tab 767: */ 768: savecol -= tp->t_col; 769: tp->t_col += savecol; 770: if (savecol > 8) 771: savecol = 8; /* overflow screw */ 772: while (--savecol >= 0) 773: (void) ntyoutput('\b', tp); 774: break; 775: 776: default: 777: panic("ttyrub"); 778: } 779: } else if (tp->t_local&LPRTERA) { 780: if ((tp->t_lstate&LSERASE) == 0) { 781: (void) ntyoutput('\\', tp); 782: tp->t_lstate |= LSERASE; 783: } 784: ntyecho(c, tp); 785: } else 786: ntyecho(tp->t_erase, tp); 787: tp->t_rocount--; 788: } 789: 790: /* 791: * Crt back over cnt chars perhaps 792: * erasing them. 793: */ 794: ntyrubo(tp, cnt) 795: register struct tty *tp; 796: register cnt; 797: { 798: 799: while (--cnt >= 0) 800: ntyout(tp->t_local&LCRTERA ? "\b \b" : "\b", tp); 801: } 802: 803: /* 804: * Reprint the rawq line. 805: * We assume c_cc has already been checked. 806: */ 807: ntyretype(tp) 808: register struct tty *tp; 809: { 810: register char *cp; 811: char *nextc(); 812: register s; 813: 814: if (tlun.t_rprntc != 0377) 815: ntyecho(tlun.t_rprntc, tp); 816: (void) ntyoutput('\n', tp); 817: s = spl5(); 818: for (cp = tp->t_canq.c_cf; cp; cp = nextc(&tp->t_canq, cp)) 819: ntyecho(lookc(cp), tp); 820: for (cp = tp->t_rawq.c_cf; cp; cp = nextc(&tp->t_rawq, cp)) 821: ntyecho(lookc(cp), tp); 822: tp->t_lstate &= ~LSERASE; 823: splx(s); 824: tp->t_rocount = tp->t_rawq.c_cc; 825: tp->t_rocol = 0; 826: } 827: 828: /* 829: * Echo a typed character to the terminal 830: */ 831: ntyecho(c, tp) 832: register c; 833: register struct tty *tp; 834: { 835: 836: if ((tp->t_lstate & LSCNTTB) == 0) 837: tp->t_local &= ~LFLUSHO; 838: if ((tp->t_flags&ECHO) == 0) 839: return; 840: c &= 0377; 841: if (tp->t_flags&RAW) { 842: (void) ntyoutput(c, tp); 843: return; 844: } 845: if (c == '\r' && tp->t_flags&CRMOD) 846: c = '\n'; 847: if (tp->t_local&LCTLECH) { 848: if ((c&0177) <= 037 && c!='\t' && c!='\n' || (c&0177)==0177) { 849: (void) ntyoutput('^', tp); 850: c &= 0177; 851: if (c == 0177) 852: c = '?'; 853: else if (tp->t_flags&LCASE) 854: c += 'a' - 1; 855: else 856: c += 'A' - 1; 857: } 858: } 859: (void) ntyoutput(c & 0177, tp); 860: } 861: 862: /* 863: * Is c a break char for tp? 864: */ 865: ntbreakc(c, tp) 866: register c; 867: register struct tty *tp; 868: { 869: return (c == '\n' || c == tun.t_eofc || c == tun.t_brkc || 870: c == '\r' && (tp->t_flags&CRMOD)); 871: } 872: 873: /* 874: * send string cp to tp 875: */ 876: ntyout(cp, tp) 877: register char *cp; 878: register struct tty *tp; 879: { 880: register char c; 881: 882: while (c = *cp++) 883: (void) ntyoutput(c, tp); 884: } 885: 886: #ifdef UCB_NET 887: ttwakeup(tp) 888: struct tty *tp; 889: { 890: if (tp->t_rsel) { 891: selwakeup(tp->t_rsel, tp->t_state&TS_RCOLL); 892: tp->t_state &= ~TS_RCOLL; 893: tp->t_rsel = 0; 894: } 895: wakeup((caddr_t)&tp->t_rawq); 896: } 897: 898: ttsignal(tp, signo) 899: struct tty *tp; 900: int signo; 901: { 902: 903: gsignal(tp->t_pgrp, signo); 904: } 905: #endif UCB_NET 906: #endif UCB_NTTY