|
|
1.1 ! root 1: #include "ntty.h" ! 2: #include "../h/param.h" ! 3: #include "../h/stream.h" ! 4: #include "../h/ttyio.h" ! 5: #include "../h/nttyio.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: ntiocack (q, b, 0); ! 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: ioc->arg.sg.sg_ispeed = ! 482: ioc->arg.sg.sg_ospeed = B9600; ! 483: ! 484: b->wptr = b->rptr + sizeof (int) + sizeof (struct sgttyb); ! 485: b->wptr = 2 + b->rptr + sizeof (int) + sizeof (struct sgttyb); ! 486: ntiocack (q, b, sizeof (struct sgttyb)); ! 487: break; ! 488: ! 489: /* ! 490: * Set/get special characters ! 491: */ ! 492: case TIOCSETC: ! 493: nt->nt_tchr = ioc->arg.tchr; ! 494: ntiocack (q, b, 0); ! 495: break; ! 496: ! 497: case TIOCGETC: ! 498: ioc->arg.tchr = nt->nt_tchr; ! 499: ntiocack (q, b, sizeof (struct tchars)); ! 500: break; ! 501: ! 502: /* ! 503: * Set/get local special characters. ! 504: */ ! 505: case TIOCSLTC: ! 506: nt->nt_ltchr = ioc->arg.ltchr; ! 507: ntiocack (q, b, 0); ! 508: break; ! 509: ! 510: case TIOCGLTC: ! 511: ioc->arg.ltchr = nt->nt_ltchr; ! 512: ntiocack (q, b, sizeof (struct ltchars)); ! 513: break; ! 514: ! 515: /* ! 516: * Modify local mode word. ! 517: */ ! 518: case TIOCLBIS: ! 519: nt->nt_local |= ioc->arg.local; ! 520: ntiocack (q, b, 0); ! 521: break; ! 522: ! 523: case TIOCLBIC: ! 524: nt->nt_local &= ~ioc->arg.local; ! 525: ntiocack (q, b, 0); ! 526: break; ! 527: ! 528: case TIOCLSET: ! 529: nt->nt_local = ioc->arg.local; ! 530: ntiocack (q, b, 0); ! 531: break; ! 532: ! 533: case TIOCLGET: ! 534: ioc->arg.local = nt->nt_local; ! 535: ntiocack (q, b, sizeof (short)); ! 536: break; ! 537: ! 538: /* ! 539: * Return number of characters in the output. ! 540: */ ! 541: case TIOCOUTQ: ! 542: ! 543: default: ! 544: (*q->next->qinfo->putp)(q->next, b); ! 545: break; ! 546: } ! 547: ! 548: return; ! 549: } ! 550: ! 551: ! 552: /* ! 553: * Erase entire input buffer. ! 554: * Called by ntinc(). ! 555: */ ! 556: ! 557: ntkill (nt) ! 558: register struct nttyld *nt; ! 559: { ! 560: if (nt->nt_local & LCRTKIL && !nt->nt_trash) { ! 561: while (nt->nt_nin > 0) ! 562: ntrubout (nt); ! 563: } ! 564: else { ! 565: ntecho (nt->nt_kill, nt); ! 566: ntecho ('\n', nt); ! 567: nt->nt_nin = 0; ! 568: nt->nt_trash = 0; ! 569: } ! 570: nt->nt_lstate = 0; ! 571: return; ! 572: } ! 573: ! 574: ! 575: /* ! 576: * Interpret the flush-output (^O) control character. ! 577: * Called by ntinc(). ! 578: */ ! 579: ! 580: int ! 581: ntoflush (c, nt) ! 582: register int c; ! 583: register struct nttyld *nt; ! 584: { ! 585: if (nt->nt_local & LFLUSHO) { ! 586: nt->nt_local &= ~LFLUSHO; ! 587: if (c == nt->nt_flushc) ! 588: return (1); ! 589: } ! 590: else if (c == nt->nt_flushc) { ! 591: ntflush (nt, FWRITE); ! 592: ntecho (c, nt); ! 593: ntreprint (nt); ! 594: nt->nt_local |= LFLUSHO; ! 595: return (1); ! 596: } ! 597: ! 598: return (0); ! 599: } ! 600: ! 601: ! 602: /*ARGSUSED*/ ! 603: ! 604: int ! 605: ntopen (q, dev) ! 606: register struct queue *q; ! 607: int dev; ! 608: { ! 609: register struct nttyld *nt; ! 610: ! 611: if (q->ptr) ! 612: return (1); /* already attached */ ! 613: ! 614: for (nt = ntty; nt->nt_state & NT_USE; nt++) ! 615: if (nt >= &ntty[NNTTY-1]) ! 616: return (0); ! 617: ! 618: WR (q)->ptr = q->ptr = (caddr_t) nt; ! 619: nt->nt_outq = WR (q); ! 620: nt->nt_readq = q; ! 621: nt->nt_nin = 0; ! 622: nt->nt_state = NT_USE; ! 623: nt->nt_flags = ECHO | CRMOD; ! 624: nt->nt_col = 0; ! 625: nt->nt_delct = 0; ! 626: ntchars (nt); /* set default control characters */ ! 627: nt->nt_trash = 0; ! 628: nt->nt_local = 0; ! 629: nt->nt_lstate = 0; ! 630: q->flag |= QDELIM; ! 631: return (1); ! 632: } ! 633: ! 634: ! 635: /* ! 636: * Writer queue (output to tty) put routine. ! 637: */ ! 638: ! 639: ntout (wrq, b) ! 640: register struct queue *wrq; ! 641: register struct block *b; ! 642: { ! 643: if (b->type == M_DATA) ! 644: b->type = M_CTL; /* see ntoutsrv() */ ! 645: putq (wrq, b); ! 646: return; ! 647: } ! 648: ! 649: ! 650: /* ! 651: * Output a block of data to a terminal. ! 652: * Handle tab expansion, case conversion, turning CR to CRLF, delays, etc. ! 653: * Called from ntoutsrv(). ! 654: */ ! 655: ! 656: ntoutb (nt, ib) ! 657: register struct nttyld *nt; ! 658: register struct block *ib; ! 659: { ! 660: register struct block *ob = 0; ! 661: register struct queue *q = nt->nt_outq; ! 662: register int c, delay, ctype; ! 663: char *colp; ! 664: ! 665: while (ib->rptr < ib->wptr) { ! 666: if (!ob || ob->wptr >= ob->lim) { ! 667: if (ob) { ! 668: if (nt->nt_local & LFLUSHO) ! 669: break; ! 670: tk_nout += ob->wptr - ob->rptr; ! 671: (*q->next->qinfo->putp)(q->next, ob); ! 672: } ! 673: if (q->next->flag & QFULL || !(ob = allocb (QBSIZE))) { ! 674: putbq (q, ib); ! 675: return; ! 676: } ! 677: } ! 678: ! 679: switch (c = *ib->rptr++ & 0177) { ! 680: case '\t': ! 681: if ((nt->nt_flags & TBDELAY) != XTABS) ! 682: break; ! 683: ! 684: /* ! 685: * Expand tabs to spaces. ! 686: */ ! 687: for (;;) { ! 688: *ob->wptr++ = ' '; ! 689: nt->nt_col++; ! 690: if ((nt->nt_col & 07) == 0) /* every 8 */ ! 691: break; ! 692: if (ob->wptr >= ob->lim) { ! 693: ib->rptr--; ! 694: break; ! 695: } ! 696: } ! 697: continue; ! 698: case '\n': ! 699: if (!(nt->nt_flags & CRMOD)) ! 700: break; ! 701: ! 702: /* ! 703: * Turn <nl> to <cr><lf>. ! 704: */ ! 705: if (nt->nt_state & NT_CR) ! 706: nt->nt_state &= ~NT_CR; ! 707: else { ! 708: nt->nt_state |= NT_CR; ! 709: c = '\r'; ! 710: ib->rptr--; ! 711: } ! 712: break; ! 713: case '~': ! 714: if (nt->nt_local & LTILDE) ! 715: c = '`'; ! 716: /* no break */ ! 717: default: ! 718: if (!(nt->nt_flags & LCASE)) ! 719: break; ! 720: ! 721: /* ! 722: * Generate escapes for upper-case-only terminals. ! 723: */ ! 724: if (nt->nt_state & NT_CASE) { ! 725: nt->nt_state &= ~NT_CASE; ! 726: break; ! 727: } ! 728: ! 729: for (colp = "{(})|!~^`'"; *colp && c != *colp; ! 730: colp += 2); ! 731: ! 732: if (*colp || c >= 'A' && c <= 'Z') { ! 733: *--ib->rptr = *colp ? colp[1] : c; ! 734: nt->nt_state |= NT_CASE; ! 735: c = '\\'; ! 736: } ! 737: else if (c >= 'a' && c <= 'z') ! 738: c += 'A' - 'a'; ! 739: break; ! 740: } ! 741: ! 742: /* ! 743: * Store character. ! 744: */ ! 745: *ob->wptr++ = c; ! 746: ! 747: /* ! 748: * Calculate delays and column movement. ! 749: * The delay values are in clock ticks and aren't ! 750: * necessarily optimal for all terminals. ! 751: */ ! 752: delay = 0; ! 753: ! 754: switch (ctype = partab[c] & 077) { ! 755: case ORDINARY: ! 756: nt->nt_col++; ! 757: break; ! 758: case CONTROL: ! 759: break; ! 760: case BACKSPACE: ! 761: if (nt->nt_col) ! 762: nt->nt_col--; ! 763: break; ! 764: case NEWLINE: ! 765: ctype = (nt->nt_flags >> 8) & 03; ! 766: if (ctype == 1) { /* tty 37 */ ! 767: if (nt->nt_col) ! 768: if ((delay = nt->nt_col >> 4) < 6) ! 769: delay = 6; ! 770: } ! 771: else if (ctype == 2) /* vt05 */ ! 772: delay = 6; ! 773: if (!(nt->nt_flags & CRMOD)) ! 774: nt->nt_col = 0; ! 775: break; ! 776: case TAB: ! 777: ctype = (nt->nt_flags >> 10) & 03; ! 778: if (ctype == 1) /* tty 37 */ ! 779: if ((delay = 1 - (nt->nt_col | ~07)) < 5) ! 780: delay = 0; ! 781: nt->nt_col |= 07; ! 782: nt->nt_col++; ! 783: break; ! 784: case VTAB: ! 785: if (nt->nt_flags & VTDELAY) ! 786: delay = 127; ! 787: break; ! 788: case RETURN: ! 789: ctype = (nt->nt_flags >> 12) & 03; ! 790: if (ctype == 1) /* tn 300 */ ! 791: delay = 5; ! 792: else if (ctype == 2) /* ti 700 */ ! 793: delay = 10; ! 794: else if (ctype == 3) /* concept 100 */ ! 795: if ((delay = 9 - nt->nt_col) < 0) ! 796: delay = 0; ! 797: nt->nt_col = 0; ! 798: break; ! 799: } ! 800: ! 801: if (delay) { ! 802: if (nt->nt_local & LFLUSHO) ! 803: break; ! 804: tk_nout += ob->wptr - ob->rptr; ! 805: (*q->next->qinfo->putp)(q->next, ob); ! 806: if (ob = allocb(1)) { ! 807: ob->type = M_DELAY; ! 808: *ob->wptr++ = delay; ! 809: (*q->next->qinfo->putp)(q->next, ob); ! 810: } ! 811: ob = 0; ! 812: } ! 813: } ! 814: ! 815: freeb (ib); ! 816: if (ob) ! 817: if (nt->nt_local & LFLUSHO) ! 818: freeb (ob); ! 819: else { ! 820: tk_nout += ob->wptr - ob->rptr; ! 821: (*q->next->qinfo->putp)(q->next, ob); ! 822: } ! 823: return; ! 824: } ! 825: ! 826: ! 827: /* ! 828: * Writer queue (tty output) service routine. ! 829: * All tty output comes through here. Upstream data comes in M_CTL ! 830: * blocks via ntout(); echoed data comes in M_DATA blocks. ! 831: */ ! 832: ! 833: ntoutsrv (q) ! 834: register struct queue *q; ! 835: { ! 836: register struct nttyld *nt = (struct nttyld *) q->ptr; ! 837: register struct block *b; ! 838: ! 839: while (b = getq (q)) ! 840: switch (b->type) { ! 841: default: ! 842: freeb (b); ! 843: continue; ! 844: case M_BREAK: ! 845: if (q->next->flag & QFULL) { ! 846: putbq (q, b); ! 847: return; ! 848: } ! 849: (*q->next->qinfo->putp)(q->next, b); ! 850: continue; ! 851: case M_DELIM: ! 852: if (!(q->next->flag & QDELIM)) { ! 853: freeb (b); ! 854: continue; ! 855: } ! 856: if (nt->nt_local & LFLUSHO) { ! 857: freeb (b); ! 858: continue; ! 859: } ! 860: if (q->next->flag & QFULL) { ! 861: putbq (q, b); ! 862: return; ! 863: } ! 864: (*q->next->qinfo->putp)(q->next, b); ! 865: continue; ! 866: case M_IOCTL: ! 867: if (q->next->flag & QFULL) { ! 868: putbq (q, b); ! 869: return; ! 870: } ! 871: ntioctl (q, b); ! 872: continue; ! 873: case M_FLUSH: ! 874: flushq (q, 0); ! 875: /* no break */ ! 876: case M_IOCNAK: ! 877: case M_IOCACK: ! 878: (*q->next->qinfo->putp)(q->next, b); ! 879: continue; ! 880: case M_CTL: ! 881: case M_DATA: ! 882: if (nt->nt_local & LFLUSHO) { ! 883: freeb (b); ! 884: continue; ! 885: } ! 886: if (q->next->flag & QFULL) { ! 887: putbq (q, b); ! 888: return; ! 889: } ! 890: if (b->type == M_CTL) { ! 891: b->type = M_DATA; ! 892: nt->nt_trash = nt->nt_nin; ! 893: } ! 894: if (nt->nt_flags & RAW || nt->nt_local & LLITOUT) { ! 895: tk_nout += b->wptr - b->rptr; ! 896: (*q->next->qinfo->putp)(q->next, b); ! 897: } ! 898: else ntoutb (nt, b); ! 899: continue; ! 900: } ! 901: ! 902: return; ! 903: } ! 904: ! 905: ! 906: /* ! 907: * Reprint input buffer. ! 908: */ ! 909: ! 910: ntreprint (nt) ! 911: register struct nttyld *nt; ! 912: { ! 913: register char *in; ! 914: register int nin; ! 915: ! 916: if (nt->nt_rprntc != 0377) ! 917: ntecho ((int) nt->nt_rprntc, nt); ! 918: (void) putd (putq, nt->nt_outq, '\n'); ! 919: for (in = nt->nt_in, nin = nt->nt_nin; nin > 0; in++, nin--) ! 920: ntecho (*in, nt); ! 921: nt->nt_lstate &= ~LSERASE; ! 922: nt->nt_trash = 0; ! 923: return; ! 924: } ! 925: ! 926: ! 927: /* ! 928: * Rubout the last character of the input buffer. ! 929: */ ! 930: ! 931: ntrubout (nt) ! 932: register struct nttyld *nt; ! 933: { ! 934: register int c, cc, col, i; ! 935: ! 936: if (nt->nt_nin <= 0) ! 937: return; ! 938: c = nt->nt_in[--nt->nt_nin]; ! 939: ! 940: if (!(nt->nt_flags & ECHO)) ! 941: return; ! 942: ! 943: nt->nt_local &= ~LFLUSHO; ! 944: ! 945: if (nt->nt_local & LPRTERA) { ! 946: if (!(nt->nt_lstate & LSERASE)) { ! 947: (void) putd (putq, nt->nt_outq, '\\'); ! 948: nt->nt_lstate |= LSERASE; ! 949: } ! 950: ntecho (c, nt); ! 951: return; ! 952: } ! 953: ! 954: if (!(nt->nt_local & LCRTBS)) { ! 955: ntecho (nt->nt_erase, nt); ! 956: return; ! 957: } ! 958: ! 959: if (nt->nt_trash > nt->nt_nin) { ! 960: ntreprint (nt); ! 961: return; ! 962: } ! 963: ! 964: if (c == ('\t'|0200) || c == ('\n'|0200)) { ! 965: ntbs (nt, 2); ! 966: return; ! 967: } ! 968: ! 969: switch (partab[c&=0177] & 0177) { ! 970: case ORDINARY: ! 971: if (nt->nt_flags&LCASE && c >= 'A' && c <= 'Z') ! 972: ntbs (nt, 2); ! 973: else ntbs (nt, 1); ! 974: break; ! 975: case TAB: ! 976: for (col = nt->nt_rocol, i = 0; i < nt->nt_nin; i++) { ! 977: cc = nt->nt_in[i]; ! 978: if (cc == ('\t'|0200) || cc == ('\n'|0200)) { ! 979: col += 2; ! 980: continue; ! 981: } ! 982: switch (partab[cc&=0177] & 0177) { ! 983: case ORDINARY: ! 984: if (nt->nt_flags&LCASE && cc>='A' && cc<='Z') ! 985: col += 2; ! 986: else col++; ! 987: break; ! 988: case TAB: ! 989: col = (col + 8) & ~7; ! 990: break; ! 991: default: ! 992: if (nt->nt_local & LCTLECH) ! 993: col += 2; ! 994: break; ! 995: } ! 996: } ! 997: ntbs (nt, 8 - (col & 7)); ! 998: break; ! 999: default: ! 1000: if (nt->nt_local & LCTLECH) ! 1001: ntbs (nt, 2); ! 1002: break; ! 1003: } ! 1004: ! 1005: return; ! 1006: } ! 1007: ! 1008: ! 1009: /* ! 1010: * Interpret the control characters that cause signals to be generated ! 1011: * immediately: interrupt (^?), quit (^\), stop (^Z). ! 1012: * Called from ntinc(). ! 1013: */ ! 1014: ! 1015: int ! 1016: ntsigc (c, nt) ! 1017: register c; ! 1018: register struct nttyld *nt; ! 1019: { ! 1020: if (c == nt->nt_intrc) { ! 1021: ntflush (nt, FREAD | FWRITE); ! 1022: (void) putctl1 (nt->nt_readq->next, M_SIGNAL, SIGINT); ! 1023: } ! 1024: else if (c == nt->nt_quitc) { ! 1025: ntflush (nt, FREAD | FWRITE); ! 1026: (void) putctl1 (nt->nt_readq->next, M_SIGNAL, SIGQUIT); ! 1027: } ! 1028: else if (c == nt->nt_suspc) { ! 1029: ntflush (nt, FREAD); ! 1030: (void) putctl1 (nt->nt_readq->next, M_SIGNAL, SIGTSTP); ! 1031: } ! 1032: else return (0); ! 1033: ! 1034: ntecho (c, nt); ! 1035: return (1); ! 1036: } ! 1037: ! 1038: ! 1039: /* ! 1040: * Interpret the start (^S) and stop (^Q) control characters. ! 1041: * Called from ntinc(). ! 1042: */ ! 1043: ! 1044: int ! 1045: ntstst (c, nt) ! 1046: register int c; ! 1047: register struct nttyld *nt; ! 1048: { ! 1049: if (nt->nt_state & NT_STOP) { ! 1050: if (c == nt->nt_startc || ! 1051: !(nt->nt_local & LDECCTQ) && ! 1052: (c != nt->nt_stopc || nt->nt_stopc == nt->nt_startc)) { ! 1053: if (putctl (nt->nt_outq->next, M_START)) ! 1054: nt->nt_state &= ~NT_STOP; ! 1055: } ! 1056: } ! 1057: else if (c == nt->nt_stopc) { ! 1058: if (putctl (nt->nt_outq->next, M_STOP)) ! 1059: nt->nt_state |= NT_STOP; ! 1060: } ! 1061: ! 1062: return (c == nt->nt_startc || c == nt->nt_stopc); ! 1063: } ! 1064: ! 1065: ! 1066: /* ! 1067: * Erase the last word of the input buffer. ! 1068: * Called from ntinc(). ! 1069: */ ! 1070: ! 1071: ntwerase (nt) ! 1072: register struct nttyld *nt; ! 1073: { ! 1074: register char *s; ! 1075: ! 1076: for (s = nt->nt_in + nt->nt_nin - 1; s >= nt->nt_in; s--) ! 1077: if (*s == ' ' || *s == '\t') ! 1078: ntrubout (nt); ! 1079: else break; ! 1080: ! 1081: for (; s >= nt->nt_in; s--) ! 1082: if (*s == ' ' || *s == '\t') ! 1083: break; ! 1084: else ntrubout (nt); ! 1085: ! 1086: return; ! 1087: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.