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