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