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