|
|
1.1 ! root 1: #include "ntty.h" ! 2: #if NNTTY > 0 ! 3: #include "../h/param.h" ! 4: #include "../h/stream.h" ! 5: #include "../h/ioctl.h" ! 6: #include "../h/ttyld.h" ! 7: #include "../h/nttyld.h" ! 8: #include "../h/conf.h" ! 9: #include "../h/file.h" ! 10: ! 11: ! 12: extern char maptab[], /* see dev/ttyld.c */ ! 13: partab[]; /* see sys/partab.c */ ! 14: ! 15: extern int tk_nin, tk_nout; ! 16: ! 17: ! 18: struct nttyld ntty[NNTTY]; ! 19: ! 20: int ntclose(), /* queue close routine */ ! 21: ntin(), /* reader queue put routine */ ! 22: ntinsrv(), /* reader queue service routine */ ! 23: ntopen(), /* queue open routine */ ! 24: ntout(), /* writer queue put routine */ ! 25: ntoutsrv(); /* writer queue service routine */ ! 26: ! 27: static struct qinit rinit = { ntin, ntinsrv, ntopen, ntclose, 300, 0 }, ! 28: winit = { ntout, ntoutsrv, ntopen, ntclose, 300, 200 }; ! 29: struct streamtab nttyinfo = { &rinit, &winit }; ! 30: ! 31: ! 32: /* ! 33: * Backspace over "n" characters, perhaps erasing them. ! 34: * Called from ntrubout(). ! 35: */ ! 36: ! 37: ntbs (nt, n) ! 38: register struct nttyld *nt; ! 39: register int n; ! 40: { ! 41: while (--n >= 0) ! 42: if (putd (putq, nt->nt_outq, '\b')) { ! 43: nt->nt_state |= NT_ECHO; ! 44: if (nt->nt_local & LCRTERA) { ! 45: (void) putd (putq, nt->nt_outq, ' '); ! 46: (void) putd (putq, nt->nt_outq, '\b'); ! 47: } ! 48: } ! 49: return; ! 50: } ! 51: ! 52: ! 53: /* ! 54: * Set default control characters. ! 55: * Called by ntopen(). ! 56: */ ! 57: ! 58: ntchars (nt) ! 59: register struct nttyld *nt; ! 60: { ! 61: static struct tchars tchars = { CINTR, CQUIT, CSTART, CSTOP, CEOT, ! 62: 0377 }; ! 63: static struct ltchars ltchars = { CSUSP, CDSUSP, CRPRNT, CFLUSH, ! 64: CWERAS, CLNEXT }; ! 65: ! 66: nt->nt_erase = CERASE; ! 67: nt->nt_kill = CKILL; ! 68: nt->nt_tchr = tchars; ! 69: nt->nt_ltchr = ltchars; ! 70: return; ! 71: } ! 72: ! 73: ! 74: ntclose (q) ! 75: register struct queue *q; ! 76: { ! 77: register struct nttyld *nt = (struct nttyld *) q->ptr; ! 78: ! 79: nt->nt_state = 0; ! 80: return; ! 81: } ! 82: ! 83: ! 84: /* ! 85: * Put input buffer on read queue followed by a delimiter. ! 86: * Called from ntinc() when a line break character is read, ! 87: * and from ntioctl() when switching from cooked to raw or cbreak mode. ! 88: */ ! 89: ! 90: ntcooked (nt) ! 91: register struct nttyld *nt; ! 92: { ! 93: register char *s, *t; ! 94: register struct block *b; ! 95: register struct queue *q = RD (nt->nt_outq); ! 96: ! 97: if (!(q->flag & QFULL) && (b = allocb (1))) { ! 98: for (t = (s = nt->nt_in) + nt->nt_nin; s < t; s++) ! 99: (void) putd (putq, q, *s); ! 100: b->type = M_DELIM; ! 101: putq (q, b); ! 102: nt->nt_delct++; ! 103: } ! 104: qenable (q); ! 105: nt->nt_nin = 0; ! 106: nt->nt_trash = 0; ! 107: return; ! 108: } ! 109: ! 110: ! 111: /* ! 112: * Echo a typed character to a terminal. ! 113: */ ! 114: ! 115: ntecho (c, nt) ! 116: register int c; ! 117: register struct nttyld *nt; ! 118: { ! 119: register struct queue *echoq = nt->nt_outq; ! 120: ! 121: nt->nt_local &= ~LFLUSHO; ! 122: if (!(nt->nt_flags & ECHO) || echoq->flag & QFULL) ! 123: return; ! 124: c &= 0377; ! 125: if (nt->nt_flags & RAW) ! 126: goto out; ! 127: if (c == '\r' && nt->nt_flags & CRMOD) ! 128: c = '\n'; ! 129: if (c != '\n' && c != '\t' && nt->nt_local & LCTLECH) ! 130: if ((c &= 0177) <= 037 || c == 0177) { ! 131: (void) putd (putq, echoq, '^'); ! 132: if (c == 0177) ! 133: c = '?'; ! 134: else if (nt->nt_flags & LCASE) ! 135: c += 'a' - 1; ! 136: else c += 'A' - 1; ! 137: goto out; ! 138: } ! 139: ! 140: if ((c &= 0177) == CEOT) /* terminals don't like it */ ! 141: return; ! 142: ! 143: out: ! 144: if (putd (putq, echoq, c)) ! 145: nt->nt_state |= NT_ECHO; ! 146: return; ! 147: } ! 148: ! 149: ! 150: /* ! 151: * Flush all input and/or all output tty queues. ! 152: */ ! 153: ! 154: ntflush (nt, rw) ! 155: struct nttyld *nt; ! 156: int rw; ! 157: { ! 158: struct queue *wrq = nt->nt_outq, ! 159: *rdq = RD (wrq); ! 160: ! 161: if (rw & FREAD) { ! 162: flushq (rdq, 0); ! 163: (void) putctl (rdq->next, M_FLUSH); ! 164: nt->nt_delct = 0; ! 165: nt->nt_nin = 0; ! 166: nt->nt_trash = 0; ! 167: nt->nt_lstate = 0; ! 168: } ! 169: if (rw & FWRITE) { ! 170: flushq (wrq, 0); ! 171: (void) putctl (wrq->next, M_FLUSH); ! 172: } ! 173: return; ! 174: } ! 175: ! 176: ! 177: /* ! 178: * Reader queue (input from tty) put routine. ! 179: */ ! 180: ! 181: ntin (q, b) ! 182: struct queue *q; ! 183: register struct block *b; ! 184: { ! 185: register struct nttyld *nt = (struct nttyld *) q->ptr; ! 186: ! 187: switch (b->type) { ! 188: case M_DATA: ! 189: if (nt->nt_flags & RAW && !(nt->nt_flags & ECHO)) ! 190: break; ! 191: nt->nt_state &= ~NT_ECHO; ! 192: while (b->rptr < b->wptr) ! 193: ntinc ((int) *b->rptr++, nt); ! 194: freeb (b); ! 195: if (nt->nt_state & NT_ECHO && nt->nt_outq->next->flag & QDELIM) ! 196: (void) putctl (nt->nt_outq, M_DELIM); ! 197: return; ! 198: case M_DELIM: ! 199: freeb (b); ! 200: return; ! 201: case M_BREAK: ! 202: if (nt->nt_flags & RAW) { /* speed-change hack */ ! 203: b->type = M_DATA; ! 204: if (b->wptr < b->lim) ! 205: *b->wptr++ = '\0'; ! 206: break; ! 207: } ! 208: (void) putctl1 (q->next, M_SIGNAL, SIGINT); ! 209: ntflush (nt, FREAD | FWRITE); ! 210: freeb (b); ! 211: return; ! 212: case M_HANGUP: ! 213: (*q->next->qinfo->putp)(q->next, b); ! 214: return; ! 215: } ! 216: ! 217: if (q->next->flag & QFULL) ! 218: freeb (b); ! 219: else (*q->next->qinfo->putp)(q->next, b); ! 220: return; ! 221: } ! 222: ! 223: ! 224: /* ! 225: * Process a single input character. ! 226: * Called (at interrupt level) by ntin(). ! 227: */ ! 228: ! 229: ntinc (c, nt) ! 230: register c; ! 231: register struct nttyld *nt; ! 232: { ! 233: register int t_flags; ! 234: ! 235: tk_nin++; ! 236: c &= 0377; ! 237: t_flags = nt->nt_flags; ! 238: ! 239: if (t_flags & RAW) { ! 240: if (!(nt->nt_readq->next->flag & QFULL)) ! 241: if (putd (nt->nt_readq->next->qinfo->putp, nt->nt_readq->next, c)) ! 242: ntecho (c, nt); ! 243: return; ! 244: } ! 245: ! 246: if (!(nt->nt_lstate & LSTYPEN)) ! 247: c &= 0177; ! 248: ! 249: /* ! 250: * Interpret literal-next-character control character (^V). ! 251: */ ! 252: if (nt->nt_lstate & LSLNCH) { ! 253: c |= 0200; ! 254: nt->nt_lstate &= ~LSLNCH; ! 255: } ! 256: if (c == nt->nt_lnextc) { ! 257: nt->nt_lstate |= LSLNCH; ! 258: if (nt->nt_flags & ECHO) ! 259: if (putd (putq, nt->nt_outq, '^')) { ! 260: nt->nt_state |= NT_ECHO; ! 261: (void) putd (putq, nt->nt_outq, '\b'); ! 262: } ! 263: return; ! 264: } ! 265: ! 266: if (ntstst (c, nt) || /* start, stop */ ! 267: ntoflush (c, nt) || /* flush output */ ! 268: ntsigc (c, nt)) /* interrupt/quit/stop */ ! 269: return; ! 270: ! 271: if (c == '\r' && t_flags & CRMOD) ! 272: c = '\n'; ! 273: if (t_flags & LCASE && c >= 'A' && c <= 'Z') ! 274: c += 'a' - 'A'; ! 275: ! 276: if (t_flags & CBREAK) { ! 277: if (nt->nt_readq->next->flag & QFULL) { ! 278: if (putd (putq, nt->nt_outq, CTRL(g))) ! 279: nt->nt_state |= NT_ECHO; ! 280: } ! 281: #ifdef notdef ! 282: else if (c == nt->nt_dsuspc) ! 283: (void) putctl1 (nt->nt_readq->next, M_SSIGNAL, SIGTSTP); ! 284: #endif ! 285: else if (putd (nt->nt_readq->next->qinfo->putp, nt->nt_readq->next, c&0177)) ! 286: ntecho (c, nt); ! 287: return; ! 288: } ! 289: ! 290: if (nt->nt_lstate & LSQUOT) { ! 291: nt->nt_lstate &= ~LSQUOT; ! 292: if (c == nt->nt_erase || c == nt->nt_kill) { ! 293: c |= 0200; ! 294: ntrubout (nt); ! 295: } ! 296: } ! 297: if (c == '\\') ! 298: nt->nt_lstate |= LSQUOT; ! 299: ! 300: if (c == nt->nt_erase) ! 301: ntrubout (nt); /* erase character */ ! 302: else if (c == nt->nt_kill) ! 303: ntkill (nt); /* erase line */ ! 304: else if (c == nt->nt_werasc) ! 305: ntwerase (nt); /* erase word */ ! 306: else if (c == nt->nt_rprntc) ! 307: ntreprint (nt); /* reprint line */ ! 308: else { ! 309: if (nt->nt_nin < NT_NIN) { ! 310: if (nt->nt_nin == 0) ! 311: nt->nt_rocol = nt->nt_col; ! 312: nt->nt_in[nt->nt_nin++] = c; ! 313: } ! 314: else { ! 315: if (putd (putq, nt->nt_outq, CTRL(g))) ! 316: nt->nt_state |= NT_ECHO; ! 317: return; ! 318: } ! 319: ! 320: if (c == '\n' || c == nt->nt_eofc || c == nt->nt_brkc || ! 321: c == '\r' && (nt->nt_flags & CRMOD)) ! 322: ntcooked (nt); ! 323: ! 324: if (nt->nt_lstate & LSERASE) { ! 325: nt->nt_lstate &= ~LSERASE; ! 326: if (putd (putq, nt->nt_outq, '/')) ! 327: nt->nt_state |= NT_ECHO; ! 328: } ! 329: ! 330: ntecho (c, nt); ! 331: if (c == nt->nt_eofc && nt->nt_flags & ECHO && ! 332: nt->nt_local & LCTLECH) ! 333: if (putd (putq, nt->nt_outq, '\b')) { ! 334: nt->nt_state |= NT_ECHO; ! 335: (void) putd (putq, nt->nt_outq, '\b'); ! 336: } ! 337: } ! 338: return; ! 339: } ! 340: ! 341: ! 342: /* ! 343: * Reader queue (tty input) service routine. ! 344: * Only cooked mode data and delimiters come through here, via ntcooked(). ! 345: */ ! 346: ! 347: ntinsrv (q) ! 348: register struct queue *q; ! 349: { ! 350: register struct nttyld *nt; ! 351: register struct block *b; ! 352: register char *op; ! 353: register int c; ! 354: static char canonb[CANBSIZ]; ! 355: ! 356: if (q->next->flag & QFULL) ! 357: return; ! 358: nt = (struct nttyld *) q->ptr; ! 359: op = canonb; ! 360: while (nt->nt_delct) { ! 361: b = getq(q); ! 362: if (b == NULL || b->type != M_DATA) { ! 363: if (op > canonb) ! 364: putcpy (q->next, canonb, op - canonb); ! 365: if (b) { ! 366: (*q->next->qinfo->putp)(q->next, b); ! 367: nt->nt_delct--; ! 368: op = canonb; ! 369: continue; ! 370: } ! 371: return; ! 372: } ! 373: while (b->rptr < b->wptr) { ! 374: c = *b->rptr++; ! 375: if (c & 0200) { /* escaped */ ! 376: c &= 0177; ! 377: if (nt->nt_flags & LCASE && maptab[c]) ! 378: c = maptab[c]; ! 379: else if (c != nt->nt_erase && ! 380: c != nt->nt_kill && c != nt->nt_eofc) ! 381: *op++ = '\\'; ! 382: } ! 383: else { ! 384: #ifdef notdef ! 385: /* ! 386: * Interpret delayed stop process ! 387: * control character (^Y). ! 388: */ ! 389: if (c == nt->nt_dsuspc) { ! 390: putcpy (q->next, canonb, op - canonb); ! 391: op = canonb; ! 392: (void) putctl1 (q->next, M_SSIGNAL, ! 393: SIGTSTP); ! 394: continue; ! 395: } ! 396: #endif ! 397: if (c == nt->nt_eofc) ! 398: continue; ! 399: } ! 400: *op++ = c; ! 401: if (op >= &canonb[CANBSIZ-1]) { ! 402: putcpy (q->next, canonb, op - canonb); ! 403: op = canonb; ! 404: } ! 405: } ! 406: freeb (b); ! 407: } ! 408: ! 409: return; ! 410: } ! 411: ! 412: ! 413: /* ! 414: * Acknowledge ioctl message. ! 415: * Called by ntioctl(). ! 416: */ ! 417: ! 418: ntiocack (q, b, n) ! 419: register struct queue *q; ! 420: register struct block *b; ! 421: register int n; ! 422: { ! 423: if (n > 0) ! 424: n += sizeof (int); /* for ioctl command */ ! 425: b->wptr = b->rptr + n; ! 426: b->type = M_IOCACK; ! 427: qreply (q, b); ! 428: return; ! 429: } ! 430: ! 431: ! 432: /* ! 433: * Terminal I/O control operations. ! 434: * Called by ntoutsrv(). ! 435: */ ! 436: ! 437: ntioctl (q, b) ! 438: register struct queue *q; ! 439: register struct block *b; ! 440: { ! 441: register struct nttyld *nt = (struct nttyld *) q->ptr; ! 442: register struct ntioc *ioc = (struct ntioc *) b->rptr; ! 443: int s; ! 444: ! 445: switch (ioc->command) { ! 446: ! 447: /* ! 448: * Set new parameters ! 449: */ ! 450: case TIOCSETP: ! 451: case TIOCSETN: ! 452: s = spl6(); ! 453: if (ioc->arg.sg.sg_flags & (RAW|CBREAK) && ! 454: !(nt->nt_flags & (RAW|CBREAK))) { ! 455: /* ! 456: * Before leaving cooked mode, push through ! 457: * any characters that made it to ntin(). ! 458: */ ! 459: if (nt->nt_nin > 0) ! 460: ntcooked (nt); ! 461: ntinsrv (RD (nt->nt_outq)); ! 462: } ! 463: nt->nt_erase = ioc->arg.sg.sg_erase; ! 464: nt->nt_kill = ioc->arg.sg.sg_kill; ! 465: nt->nt_flags = ioc->arg.sg.sg_flags; ! 466: nt->nt_readq->flag &= ~QDELIM; ! 467: if ((nt->nt_flags & (RAW|CBREAK))==0) ! 468: nt->nt_readq->flag |= QDELIM; ! 469: splx (s); ! 470: ! 471: (*q->next->qinfo->putp)(q->next, b); /* send it on down */ ! 472: break; ! 473: ! 474: /* ! 475: * Send current parameters to user ! 476: */ ! 477: case TIOCGETP: ! 478: ioc->arg.sg.sg_erase = nt->nt_erase; ! 479: ioc->arg.sg.sg_kill = nt->nt_kill; ! 480: ioc->arg.sg.sg_flags = nt->nt_flags; ! 481: ! 482: b->wptr = b->rptr + sizeof (int) + sizeof (struct sgttyb); ! 483: b->wptr = 2 + b->rptr + sizeof (int) + sizeof (struct sgttyb); ! 484: (*q->next->qinfo->putp)(q->next, b); ! 485: break; ! 486: ! 487: /* ! 488: * Set/get special characters ! 489: */ ! 490: case TIOCSETC: ! 491: nt->nt_tchr = ioc->arg.tchr; ! 492: ntiocack (q, b, 0); ! 493: break; ! 494: ! 495: case TIOCGETC: ! 496: ioc->arg.tchr = nt->nt_tchr; ! 497: ntiocack (q, b, sizeof (struct tchars)); ! 498: break; ! 499: ! 500: /* ! 501: * Set/get local special characters. ! 502: */ ! 503: case TIOCSLTC: ! 504: nt->nt_ltchr = ioc->arg.ltchr; ! 505: ntiocack (q, b, 0); ! 506: break; ! 507: ! 508: case TIOCGLTC: ! 509: ioc->arg.ltchr = nt->nt_ltchr; ! 510: ntiocack (q, b, sizeof (struct ltchars)); ! 511: break; ! 512: ! 513: /* ! 514: * Modify local mode word. ! 515: */ ! 516: case TIOCLBIS: ! 517: nt->nt_local |= ioc->arg.local; ! 518: ntiocack (q, b, 0); ! 519: break; ! 520: ! 521: case TIOCLBIC: ! 522: nt->nt_local &= ~ioc->arg.local; ! 523: ntiocack (q, b, 0); ! 524: break; ! 525: ! 526: case TIOCLSET: ! 527: nt->nt_local = ioc->arg.local; ! 528: ntiocack (q, b, 0); ! 529: break; ! 530: ! 531: case TIOCLGET: ! 532: ioc->arg.local = nt->nt_local; ! 533: ntiocack (q, b, sizeof (short)); ! 534: break; ! 535: ! 536: /* ! 537: * Return number of characters in the output. ! 538: */ ! 539: case TIOCOUTQ: ! 540: ! 541: default: ! 542: (*q->next->qinfo->putp)(q->next, b); ! 543: break; ! 544: } ! 545: ! 546: return; ! 547: } ! 548: ! 549: ! 550: /* ! 551: * Erase entire input buffer. ! 552: * Called by ntinc(). ! 553: */ ! 554: ! 555: ntkill (nt) ! 556: register struct nttyld *nt; ! 557: { ! 558: if (nt->nt_local & LCRTKIL && !nt->nt_trash) { ! 559: while (nt->nt_nin > 0) ! 560: ntrubout (nt); ! 561: } ! 562: else { ! 563: ntecho (nt->nt_kill, nt); ! 564: ntecho ('\n', nt); ! 565: nt->nt_nin = 0; ! 566: nt->nt_trash = 0; ! 567: } ! 568: nt->nt_lstate = 0; ! 569: return; ! 570: } ! 571: ! 572: ! 573: /* ! 574: * Interpret the flush-output (^O) control character. ! 575: * Called by ntinc(). ! 576: */ ! 577: ! 578: int ! 579: ntoflush (c, nt) ! 580: register int c; ! 581: register struct nttyld *nt; ! 582: { ! 583: if (nt->nt_local & LFLUSHO) { ! 584: nt->nt_local &= ~LFLUSHO; ! 585: if (c == nt->nt_flushc) ! 586: return (1); ! 587: } ! 588: else if (c == nt->nt_flushc) { ! 589: ntflush (nt, FWRITE); ! 590: ntecho (c, nt); ! 591: ntreprint (nt); ! 592: nt->nt_local |= LFLUSHO; ! 593: return (1); ! 594: } ! 595: ! 596: return (0); ! 597: } ! 598: ! 599: ! 600: /*ARGSUSED*/ ! 601: ! 602: int ! 603: ntopen (q, dev) ! 604: register struct queue *q; ! 605: int dev; ! 606: { ! 607: register struct nttyld *nt; ! 608: ! 609: if (q->ptr) ! 610: return (1); /* already attached */ ! 611: ! 612: for (nt = ntty; nt->nt_state & NT_USE; nt++) ! 613: if (nt >= &ntty[NNTTY-1]) ! 614: return (0); ! 615: ! 616: WR (q)->ptr = q->ptr = (caddr_t) nt; ! 617: nt->nt_outq = WR (q); ! 618: nt->nt_readq = q; ! 619: nt->nt_nin = 0; ! 620: nt->nt_state = NT_USE; ! 621: nt->nt_flags = ECHO | CRMOD; ! 622: nt->nt_col = 0; ! 623: nt->nt_delct = 0; ! 624: ntchars (nt); /* set default control characters */ ! 625: nt->nt_trash = 0; ! 626: nt->nt_local = 0; ! 627: nt->nt_lstate = 0; ! 628: q->flag |= QDELIM; ! 629: return (1); ! 630: } ! 631: ! 632: ! 633: /* ! 634: * Writer queue (output to tty) put routine. ! 635: */ ! 636: ! 637: ntout (wrq, b) ! 638: register struct queue *wrq; ! 639: register struct block *b; ! 640: { ! 641: if (b->type == M_DATA) ! 642: b->type = M_CTL; /* see ntoutsrv() */ ! 643: putq (wrq, b); ! 644: return; ! 645: } ! 646: ! 647: ! 648: /* ! 649: * Output a block of data to a terminal. ! 650: * Handle tab expansion, case conversion, turning CR to CRLF, delays, etc. ! 651: * Called from ntoutsrv(). ! 652: */ ! 653: ! 654: ntoutb (nt, ib) ! 655: register struct nttyld *nt; ! 656: register struct block *ib; ! 657: { ! 658: register struct block *ob = 0; ! 659: register struct queue *q = nt->nt_outq; ! 660: register int c, delay, ctype; ! 661: char *colp; ! 662: ! 663: while (ib->rptr < ib->wptr) { ! 664: if (!ob || ob->wptr >= ob->lim) { ! 665: if (ob) { ! 666: if (nt->nt_local & LFLUSHO) ! 667: break; ! 668: tk_nout += ob->wptr - ob->rptr; ! 669: (*q->next->qinfo->putp)(q->next, ob); ! 670: } ! 671: if (q->next->flag & QFULL || !(ob = allocb (QBSIZE))) { ! 672: putbq (q, ib); ! 673: return; ! 674: } ! 675: } ! 676: ! 677: switch (c = *ib->rptr++ & 0177) { ! 678: case '\t': ! 679: if ((nt->nt_flags & TBDELAY) != XTABS) ! 680: break; ! 681: ! 682: /* ! 683: * Expand tabs to spaces. ! 684: */ ! 685: for (;;) { ! 686: *ob->wptr++ = ' '; ! 687: nt->nt_col++; ! 688: if ((nt->nt_col & 07) == 0) /* every 8 */ ! 689: break; ! 690: if (ob->wptr >= ob->lim) { ! 691: ib->rptr--; ! 692: break; ! 693: } ! 694: } ! 695: continue; ! 696: case '\n': ! 697: if (!(nt->nt_flags & CRMOD)) ! 698: break; ! 699: ! 700: /* ! 701: * Turn <nl> to <cr><lf>. ! 702: */ ! 703: if (nt->nt_state & NT_CR) ! 704: nt->nt_state &= ~NT_CR; ! 705: else { ! 706: nt->nt_state |= NT_CR; ! 707: c = '\r'; ! 708: ib->rptr--; ! 709: } ! 710: break; ! 711: case '~': ! 712: if (nt->nt_local & LTILDE) ! 713: c = '`'; ! 714: /* no break */ ! 715: default: ! 716: if (!(nt->nt_flags & LCASE)) ! 717: break; ! 718: ! 719: /* ! 720: * Generate escapes for upper-case-only terminals. ! 721: */ ! 722: if (nt->nt_state & NT_CASE) { ! 723: nt->nt_state &= ~NT_CASE; ! 724: break; ! 725: } ! 726: ! 727: for (colp = "{(})|!~^`'"; *colp && c != *colp; ! 728: colp += 2); ! 729: ! 730: if (*colp || c >= 'A' && c <= 'Z') { ! 731: *--ib->rptr = *colp ? colp[1] : c; ! 732: nt->nt_state |= NT_CASE; ! 733: c = '\\'; ! 734: } ! 735: else if (c >= 'a' && c <= 'z') ! 736: c += 'A' - 'a'; ! 737: break; ! 738: } ! 739: ! 740: /* ! 741: * Store character. ! 742: */ ! 743: *ob->wptr++ = c; ! 744: ! 745: /* ! 746: * Calculate delays and column movement. ! 747: * The delay values are in clock ticks and aren't ! 748: * necessarily optimal for all terminals. ! 749: */ ! 750: delay = 0; ! 751: ! 752: switch (ctype = partab[c] & 077) { ! 753: case ORDINARY: ! 754: nt->nt_col++; ! 755: break; ! 756: case CONTROL: ! 757: break; ! 758: case BACKSPACE: ! 759: if (nt->nt_col) ! 760: nt->nt_col--; ! 761: break; ! 762: case NEWLINE: ! 763: ctype = (nt->nt_flags >> 8) & 03; ! 764: if (ctype == 1) { /* tty 37 */ ! 765: if (nt->nt_col) ! 766: if ((delay = nt->nt_col >> 4) < 6) ! 767: delay = 6; ! 768: } ! 769: else if (ctype == 2) /* vt05 */ ! 770: delay = 6; ! 771: if (!(nt->nt_flags & CRMOD)) ! 772: nt->nt_col = 0; ! 773: break; ! 774: case TAB: ! 775: ctype = (nt->nt_flags >> 10) & 03; ! 776: if (ctype == 1) /* tty 37 */ ! 777: if ((delay = 1 - (nt->nt_col | ~07)) < 5) ! 778: delay = 0; ! 779: nt->nt_col |= 07; ! 780: nt->nt_col++; ! 781: break; ! 782: case VTAB: ! 783: if (nt->nt_flags & VTDELAY) ! 784: delay = 127; ! 785: break; ! 786: case RETURN: ! 787: ctype = (nt->nt_flags >> 12) & 03; ! 788: if (ctype == 1) /* tn 300 */ ! 789: delay = 5; ! 790: else if (ctype == 2) /* ti 700 */ ! 791: delay = 10; ! 792: else if (ctype == 3) /* concept 100 */ ! 793: if ((delay = 9 - nt->nt_col) < 0) ! 794: delay = 0; ! 795: nt->nt_col = 0; ! 796: break; ! 797: } ! 798: ! 799: if (delay) { ! 800: if (nt->nt_local & LFLUSHO) ! 801: break; ! 802: tk_nout += ob->wptr - ob->rptr; ! 803: (*q->next->qinfo->putp)(q->next, ob); ! 804: if (ob = allocb(1)) { ! 805: ob->type = M_DELAY; ! 806: *ob->wptr++ = delay; ! 807: (*q->next->qinfo->putp)(q->next, ob); ! 808: } ! 809: ob = 0; ! 810: } ! 811: } ! 812: ! 813: freeb (ib); ! 814: if (ob) ! 815: if (nt->nt_local & LFLUSHO) ! 816: freeb (ob); ! 817: else { ! 818: tk_nout += ob->wptr - ob->rptr; ! 819: (*q->next->qinfo->putp)(q->next, ob); ! 820: } ! 821: return; ! 822: } ! 823: ! 824: ! 825: /* ! 826: * Writer queue (tty output) service routine. ! 827: * All tty output comes through here. Upstream data comes in M_CTL ! 828: * blocks via ntout(); echoed data comes in M_DATA blocks. ! 829: */ ! 830: ! 831: ntoutsrv (q) ! 832: register struct queue *q; ! 833: { ! 834: register struct nttyld *nt = (struct nttyld *) q->ptr; ! 835: register struct block *b; ! 836: ! 837: while (b = getq (q)) ! 838: switch (b->type) { ! 839: default: ! 840: freeb (b); ! 841: continue; ! 842: case M_BREAK: ! 843: if (q->next->flag & QFULL) { ! 844: putbq (q, b); ! 845: return; ! 846: } ! 847: (*q->next->qinfo->putp)(q->next, b); ! 848: continue; ! 849: case M_DELIM: ! 850: if (!(q->next->flag & QDELIM)) { ! 851: freeb (b); ! 852: continue; ! 853: } ! 854: if (nt->nt_local & LFLUSHO) { ! 855: freeb (b); ! 856: continue; ! 857: } ! 858: if (q->next->flag & QFULL) { ! 859: putbq (q, b); ! 860: return; ! 861: } ! 862: (*q->next->qinfo->putp)(q->next, b); ! 863: continue; ! 864: case M_IOCTL: ! 865: if (q->next->flag & QFULL) { ! 866: putbq (q, b); ! 867: return; ! 868: } ! 869: ntioctl (q, b); ! 870: continue; ! 871: case M_FLUSH: ! 872: flushq (q, 0); ! 873: /* no break */ ! 874: case M_IOCNAK: ! 875: case M_IOCACK: ! 876: (*q->next->qinfo->putp)(q->next, b); ! 877: continue; ! 878: case M_CTL: ! 879: case M_DATA: ! 880: if (nt->nt_local & LFLUSHO) { ! 881: freeb (b); ! 882: continue; ! 883: } ! 884: if (q->next->flag & QFULL) { ! 885: putbq (q, b); ! 886: return; ! 887: } ! 888: if (b->type == M_CTL) { ! 889: b->type = M_DATA; ! 890: nt->nt_trash = nt->nt_nin; ! 891: } ! 892: if (nt->nt_flags & RAW || nt->nt_local & LLITOUT) { ! 893: tk_nout += b->wptr - b->rptr; ! 894: (*q->next->qinfo->putp)(q->next, b); ! 895: } ! 896: else ntoutb (nt, b); ! 897: continue; ! 898: } ! 899: ! 900: return; ! 901: } ! 902: ! 903: ! 904: /* ! 905: * Reprint input buffer. ! 906: */ ! 907: ! 908: ntreprint (nt) ! 909: register struct nttyld *nt; ! 910: { ! 911: register char *in; ! 912: register int nin; ! 913: ! 914: if (nt->nt_rprntc != 0377) ! 915: ntecho ((int) nt->nt_rprntc, nt); ! 916: (void) putd (putq, nt->nt_outq, '\n'); ! 917: for (in = nt->nt_in, nin = nt->nt_nin; nin > 0; in++, nin--) ! 918: ntecho (*in, nt); ! 919: nt->nt_lstate &= ~LSERASE; ! 920: nt->nt_trash = 0; ! 921: return; ! 922: } ! 923: ! 924: ! 925: /* ! 926: * Rubout the last character of the input buffer. ! 927: */ ! 928: ! 929: ntrubout (nt) ! 930: register struct nttyld *nt; ! 931: { ! 932: register int c, cc, col, i; ! 933: ! 934: if (nt->nt_nin <= 0) ! 935: return; ! 936: c = nt->nt_in[--nt->nt_nin]; ! 937: ! 938: if (!(nt->nt_flags & ECHO)) ! 939: return; ! 940: ! 941: nt->nt_local &= ~LFLUSHO; ! 942: ! 943: if (nt->nt_local & LPRTERA) { ! 944: if (!(nt->nt_lstate & LSERASE)) { ! 945: (void) putd (putq, nt->nt_outq, '\\'); ! 946: nt->nt_lstate |= LSERASE; ! 947: } ! 948: ntecho (c, nt); ! 949: return; ! 950: } ! 951: ! 952: if (!(nt->nt_local & LCRTBS)) { ! 953: ntecho (nt->nt_erase, nt); ! 954: return; ! 955: } ! 956: ! 957: if (nt->nt_trash > nt->nt_nin) { ! 958: ntreprint (nt); ! 959: return; ! 960: } ! 961: ! 962: if (c == ('\t'|0200) || c == ('\n'|0200)) { ! 963: ntbs (nt, 2); ! 964: return; ! 965: } ! 966: ! 967: switch (partab[c&=0177] & 0177) { ! 968: case ORDINARY: ! 969: if (nt->nt_flags&LCASE && c >= 'A' && c <= 'Z') ! 970: ntbs (nt, 2); ! 971: else ntbs (nt, 1); ! 972: break; ! 973: case TAB: ! 974: for (col = nt->nt_rocol, i = 0; i < nt->nt_nin; i++) { ! 975: cc = nt->nt_in[i]; ! 976: if (cc == ('\t'|0200) || cc == ('\n'|0200)) { ! 977: col += 2; ! 978: continue; ! 979: } ! 980: switch (partab[cc&=0177] & 0177) { ! 981: case ORDINARY: ! 982: if (nt->nt_flags&LCASE && cc>='A' && cc<='Z') ! 983: col += 2; ! 984: else col++; ! 985: break; ! 986: case TAB: ! 987: col = (col + 8) & ~7; ! 988: break; ! 989: default: ! 990: if (nt->nt_local & LCTLECH) ! 991: col += 2; ! 992: break; ! 993: } ! 994: } ! 995: ntbs (nt, 8 - (col & 7)); ! 996: break; ! 997: default: ! 998: if (nt->nt_local & LCTLECH) ! 999: ntbs (nt, 2); ! 1000: break; ! 1001: } ! 1002: ! 1003: return; ! 1004: } ! 1005: ! 1006: ! 1007: /* ! 1008: * Interpret the control characters that cause signals to be generated ! 1009: * immediately: interrupt (^?), quit (^\), stop (^Z). ! 1010: * Called from ntinc(). ! 1011: */ ! 1012: ! 1013: int ! 1014: ntsigc (c, nt) ! 1015: register c; ! 1016: register struct nttyld *nt; ! 1017: { ! 1018: if (c == nt->nt_intrc) { ! 1019: ntflush (nt, FREAD | FWRITE); ! 1020: (void) putctl1 (nt->nt_readq->next, M_SIGNAL, SIGINT); ! 1021: } ! 1022: else if (c == nt->nt_quitc) { ! 1023: ntflush (nt, FREAD | FWRITE); ! 1024: (void) putctl1 (nt->nt_readq->next, M_SIGNAL, SIGQUIT); ! 1025: } ! 1026: else if (c == nt->nt_suspc) { ! 1027: ntflush (nt, FREAD); ! 1028: (void) putctl1 (nt->nt_readq->next, M_SIGNAL, SIGTSTP); ! 1029: } ! 1030: else return (0); ! 1031: ! 1032: ntecho (c, nt); ! 1033: return (1); ! 1034: } ! 1035: ! 1036: ! 1037: /* ! 1038: * Interpret the start (^S) and stop (^Q) control characters. ! 1039: * Called from ntinc(). ! 1040: */ ! 1041: ! 1042: int ! 1043: ntstst (c, nt) ! 1044: register int c; ! 1045: register struct nttyld *nt; ! 1046: { ! 1047: if (nt->nt_state & NT_STOP) { ! 1048: if (c == nt->nt_startc || ! 1049: !(nt->nt_local & LDECCTQ) && ! 1050: (c != nt->nt_stopc || nt->nt_stopc == nt->nt_startc)) { ! 1051: if (putctl (nt->nt_outq->next, M_START)) ! 1052: nt->nt_state &= ~NT_STOP; ! 1053: } ! 1054: } ! 1055: else if (c == nt->nt_stopc) { ! 1056: if (putctl (nt->nt_outq->next, M_STOP)) ! 1057: nt->nt_state |= NT_STOP; ! 1058: } ! 1059: ! 1060: return (c == nt->nt_startc || c == nt->nt_stopc); ! 1061: } ! 1062: ! 1063: ! 1064: /* ! 1065: * Erase the last word of the input buffer. ! 1066: * Called from ntinc(). ! 1067: */ ! 1068: ! 1069: ntwerase (nt) ! 1070: register struct nttyld *nt; ! 1071: { ! 1072: register char *s; ! 1073: ! 1074: for (s = nt->nt_in + nt->nt_nin - 1; s >= nt->nt_in; s--) ! 1075: if (*s == ' ' || *s == '\t') ! 1076: ntrubout (nt); ! 1077: else break; ! 1078: ! 1079: for (; s >= nt->nt_in; s--) ! 1080: if (*s == ' ' || *s == '\t') ! 1081: break; ! 1082: else ntrubout (nt); ! 1083: ! 1084: return; ! 1085: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.