|
|
1.1 ! root 1: #include "../h/param.h" ! 2: #include "../h/stream.h" ! 3: #include "../h/ttyio.h" ! 4: #include "../h/ttyld.h" ! 5: #include "../h/conf.h" ! 6: #include "tty.h" ! 7: ! 8: extern char partab[]; ! 9: ! 10: #define CANBSIZ 256 /* size of largest input line */ ! 11: ! 12: struct ttyld tty[NTTY]; ! 13: ! 14: char maptab[] = { ! 15: 000,000,000,000,000,000,000,000, ! 16: 000,000,000,000,000,000,000,000, ! 17: 000,000,000,000,000,000,000,000, ! 18: 000,000,000,000,000,000,000,000, ! 19: 000,'|',000,000,000,000,000,'`', ! 20: '{','}',000,000,000,000,000,000, ! 21: 000,000,000,000,000,000,000,000, ! 22: 000,000,000,000,000,000,000,000, ! 23: 000,000,000,000,000,000,000,000, ! 24: 000,000,000,000,000,000,000,000, ! 25: 000,000,000,000,000,000,000,000, ! 26: 000,000,000,000,'\\',000,'~',000, ! 27: 000,'A','B','C','D','E','F','G', ! 28: 'H','I','J','K','L','M','N','O', ! 29: 'P','Q','R','S','T','U','V','W', ! 30: 'X','Y','Z',000,000,000,000,000, ! 31: }; ! 32: ! 33: int ttyopen(), ttyclose(), ttyldin(), ttyinsrv(), ttyosrv(); ! 34: static struct qinit ttrinit = { ttyldin, ttyinsrv, ttyopen, ttyclose, 600, 60}; ! 35: static struct qinit ttwinit = { putq, ttyosrv, ttyopen, ttyclose, 300, 200}; ! 36: struct streamtab ttyinfo = { &ttrinit, &ttwinit}; ! 37: ! 38: /* ! 39: * TTY open ! 40: */ ! 41: ttyopen(qp, dev) ! 42: register struct queue *qp; ! 43: { ! 44: register struct ttyld *tp; ! 45: static struct tchars tchars = {CINTR,CQUIT,CSTART,CSTOP,CEOT,0377}; ! 46: ! 47: if (qp->ptr) /* already attached */ ! 48: return(1); ! 49: for (tp = tty; tp->t_state&TTUSE; tp++) ! 50: if (tp >= &tty[NTTY-1]) ! 51: return(0); ! 52: tp->t_state = TTUSE; ! 53: tp->t_flags = ECHO|CRMOD; ! 54: tp->t_delct = 0; ! 55: tp->t_col = 0; ! 56: tp->t_erase = CERASE; ! 57: tp->t_kill = CKILL; ! 58: tp->t_chr = tchars; ! 59: qp->ptr = (caddr_t)tp; ! 60: qp->flag |= QDELIM|QNOENB; ! 61: WR(qp)->ptr = (caddr_t)tp; ! 62: return(1); ! 63: } ! 64: ! 65: ttyclose(qp) ! 66: register struct queue *qp; ! 67: { ! 68: register struct ttyld *tp = (struct ttyld *)qp->ptr; ! 69: ! 70: tp->t_state = 0; ! 71: } ! 72: ! 73: /* ! 74: * Queue put procedure for tty input ! 75: */ ! 76: ttyldin(q, bp) ! 77: struct queue *q; ! 78: register struct block *bp; ! 79: { ! 80: register struct ttyld *tp; ! 81: register c; ! 82: register struct queue *wrq = WR(q); /* writer side */ ! 83: int escape, flags; ! 84: ! 85: tp = (struct ttyld *)q->ptr; ! 86: flags = tp->t_flags; ! 87: if (bp->type!=M_DATA) { ! 88: switch(bp->type) { ! 89: ! 90: case M_DELIM: ! 91: freeb(bp); ! 92: return; ! 93: ! 94: case M_BREAK: ! 95: if (tp->t_flags&RAW) { /* speed-change hack*/ ! 96: bp->type = M_DATA; ! 97: if (bp->wptr<bp->lim) ! 98: *bp->wptr++ = '\0'; ! 99: break; ! 100: } ! 101: ttysig(q, SIGINT); ! 102: freeb(bp); ! 103: return; ! 104: ! 105: case M_HANGUP: ! 106: case M_IOCACK: ! 107: case M_IOCNAK: ! 108: (*q->next->qinfo->putp)(q->next, bp); ! 109: return; ! 110: ! 111: case M_IOCTL: ! 112: ttldioc(WR(q), bp, q, 1); ! 113: return; ! 114: } ! 115: flags |= RAW; ! 116: } ! 117: if (tp->t_flags&TANDEM && tp->t_state&TTBLOCK ! 118: && q->count <= q->qinfo->lolimit) { ! 119: tp->t_state &= ~TTBLOCK; ! 120: putd(putq, WR(q), tp->t_chr.t_startc); ! 121: } ! 122: if (flags&RAW) { ! 123: if ((q->next->flag&QFULL)==0 && q->count==0) ! 124: (*q->next->qinfo->putp)(q->next, bp); ! 125: else ! 126: putq(q, bp); ! 127: return; ! 128: } ! 129: while (bp->rptr<bp->wptr) { ! 130: c = *bp->rptr++ & 0177; ! 131: if (tp->t_state&TTSTOP) { ! 132: if (c==tp->t_chr.t_startc || c==tp->t_chr.t_intrc) { ! 133: tp->t_state &= ~TTSTOP; ! 134: putctl(wrq->next, M_START); ! 135: } ! 136: } else { ! 137: if (c==tp->t_chr.t_stopc) { ! 138: tp->t_state |= TTSTOP; ! 139: putctl(wrq->next, M_STOP); ! 140: } ! 141: } ! 142: if (c==tp->t_chr.t_stopc || c==tp->t_chr.t_startc) ! 143: continue; ! 144: if (c==tp->t_chr.t_intrc) { ! 145: ttysig(q, SIGINT); ! 146: continue; ! 147: } ! 148: if (c==tp->t_chr.t_quitc) { ! 149: ttysig(q, SIGQUIT); ! 150: continue; ! 151: } ! 152: if (c=='\r' && tp->t_flags&CRMOD) ! 153: c = '\n'; ! 154: if (tp->t_flags&LCASE && c>='A' && c<='Z') ! 155: c += 'a'-'A'; ! 156: escape = 0; ! 157: if (tp->t_flags & CBREAK) { ! 158: if ((q->next->flag&QFULL)==0 && q->count==0) ! 159: putd(q->next->qinfo->putp, q->next, c); ! 160: else ! 161: putd(putq, q, c); ! 162: } else { ! 163: if (tp->t_state&TTESC) { ! 164: escape = 1; ! 165: c |= 0200; ! 166: } ! 167: if (c == '\\') ! 168: tp->t_state |= TTESC; ! 169: else { ! 170: tp->t_state &= ~TTESC; ! 171: if (c == ('\\'|0200)) { ! 172: c &= 0177; ! 173: tp->t_state |= TTESC; ! 174: } ! 175: /* ttyhog? */ ! 176: if (q->count<512 || (c=='\n' && tp->t_delct==0)) ! 177: putd(putq, q, c); ! 178: else ! 179: c = '\007'; ! 180: } ! 181: c &= 0177; ! 182: if (c=='\n'||c==tp->t_chr.t_eofc||c==tp->t_chr.t_brkc) { ! 183: register struct block *bp1; ! 184: if (bp1 = allocb(1)) { ! 185: bp1->type = M_DELIM; ! 186: putq(q, bp1); ! 187: tp->t_delct++; ! 188: } ! 189: qenable(q); ! 190: } ! 191: } ! 192: if (tp->t_flags&TANDEM && (tp->t_state&TTBLOCK) == 0 ! 193: && q->count >= (q->qinfo->limit+q->qinfo->lolimit)/2 ) { ! 194: q->next->flag |= QWANTW; ! 195: tp->t_state |= TTBLOCK; ! 196: putd(putq, wrq, tp->t_chr.t_stopc); ! 197: } ! 198: if (tp->t_flags&ECHO && (wrq->flag&QFULL)==0) { ! 199: register c1 = c&0177; ! 200: if (c1!=CEOT) { ! 201: putd(putq, wrq, c1); ! 202: if(wrq->next->flag&QDELIM && bp->wptr==bp->rptr) ! 203: putctl(wrq, M_DELIM); ! 204: } ! 205: if (c==tp->t_kill && (tp->t_flags&CBREAK)==0 ! 206: && !escape) { ! 207: putd(putq, wrq, '\n'); ! 208: if (wrq->next->flag&QDELIM) ! 209: putctl(wrq, M_DELIM); ! 210: } ! 211: } ! 212: } ! 213: freeb(bp); ! 214: } ! 215: ! 216: /* ! 217: * tty input server processing. Erase-kill and escape processing; ! 218: * gathering into lines. ! 219: */ ! 220: ! 221: ttyinsrv(q) ! 222: register struct queue *q; ! 223: { ! 224: register struct ttyld *tp; ! 225: register struct block *bp; ! 226: register char *op; ! 227: register c; ! 228: static char canonb[CANBSIZ]; ! 229: ! 230: tp = (struct ttyld *)q->ptr; ! 231: if (q->next->flag&QFULL) ! 232: return; ! 233: if (tp->t_flags&(CBREAK|RAW)) { ! 234: while ((q->next->flag&QFULL)==0 && (bp = getq(q))) ! 235: (*q->next->qinfo->putp)(q->next, bp); ! 236: } else { ! 237: op = canonb; ! 238: while (tp->t_delct) { ! 239: bp = getq(q); ! 240: if (bp==NULL || bp->type!=M_DATA) { ! 241: if (op > canonb) ! 242: putcpy(q->next, canonb, op-canonb); ! 243: if (bp) { ! 244: (*q->next->qinfo->putp)(q->next, bp); ! 245: tp->t_delct--; ! 246: op = canonb; ! 247: continue; ! 248: } ! 249: return; ! 250: } ! 251: while (bp->rptr<bp->wptr) { ! 252: c = *bp->rptr++; ! 253: if ((c&0200) == 0) { /* not escaped */ ! 254: if (c == tp->t_erase) { ! 255: if (op > canonb) ! 256: op--; ! 257: continue; ! 258: } ! 259: if (c == tp->t_kill) { ! 260: op = canonb; ! 261: continue; ! 262: } ! 263: if (c == tp->t_chr.t_eofc) ! 264: continue; ! 265: } else { ! 266: c &= 0177; ! 267: if (tp->t_flags&LCASE && maptab[c]) ! 268: c = maptab[c]; ! 269: else if (c==tp->t_erase || c==tp->t_kill ! 270: || c==tp->t_chr.t_eofc) ! 271: ; ! 272: else ! 273: *op++ = '\\'; ! 274: } ! 275: *op++ = c; ! 276: if (op >= &canonb[CANBSIZ-1]) { ! 277: putcpy(q->next, canonb, op-canonb); ! 278: op = canonb; ! 279: } ! 280: } ! 281: freeb(bp); ! 282: } ! 283: } ! 284: if (tp->t_flags&TANDEM && tp->t_state&TTBLOCK ! 285: && q->count <= q->qinfo->lolimit) { ! 286: tp->t_state &= ~TTBLOCK; ! 287: putd(putq, WR(q), tp->t_chr.t_startc); ! 288: } ! 289: } ! 290: ! 291: /* ! 292: * TTY write processing: delays, tabs, CR/NL and the like. ! 293: */ ! 294: ttyosrv(q) ! 295: register struct queue *q; ! 296: { ! 297: register struct ttyld *tp; ! 298: register struct block *bp; ! 299: ! 300: tp = (struct ttyld *)q->ptr; ! 301: while (bp = getq(q)) { ! 302: switch(bp->type) { ! 303: ! 304: default: ! 305: freeb(bp); ! 306: continue; ! 307: ! 308: case M_DELIM: ! 309: if ((q->next->flag & QDELIM) == 0) { ! 310: freeb(bp); ! 311: continue; ! 312: } ! 313: if (q->next->flag & QFULL) { ! 314: putbq(q, bp); ! 315: return; ! 316: } ! 317: (*q->next->qinfo->putp)(q->next, bp); ! 318: continue; ! 319: ! 320: case M_IOCTL: ! 321: if (q->next->flag & QFULL) { ! 322: putbq(q, bp); ! 323: return; ! 324: } ! 325: ttldioc(q, bp, RD(q), 0); ! 326: continue; ! 327: ! 328: case M_FLUSH: ! 329: flushq(q, 0); ! 330: case M_IOCNAK: /* flow through */ ! 331: case M_IOCACK: ! 332: (*q->next->qinfo->putp)(q->next, bp); ! 333: continue; ! 334: ! 335: case M_DATA: ! 336: case M_BREAK: ! 337: if (q->next->flag & QFULL) { ! 338: putbq(q, bp); ! 339: return; ! 340: } ! 341: if (tp->t_flags&RAW || bp->type==M_BREAK) { ! 342: (*q->next->qinfo->putp)(q->next, bp); ! 343: } else ! 344: outconv(q, bp); ! 345: continue; ! 346: } ! 347: } ! 348: } ! 349: ! 350: outconv(q, ibp) ! 351: struct queue *q; ! 352: register struct block *ibp; ! 353: { ! 354: register struct ttyld *tp; ! 355: register struct block *obp = NULL; ! 356: register c; ! 357: register count, ctype; ! 358: ! 359: tp = (struct ttyld *)q->ptr; ! 360: more: ! 361: while (ibp->rptr < ibp->wptr) { ! 362: if (obp==NULL || obp->wptr >= obp->lim) { ! 363: if (obp) ! 364: (*q->next->qinfo->putp)(q->next, obp); ! 365: if (q->next->flag&QFULL || (obp=allocb(QBSIZE))==NULL) { ! 366: putbq(q, ibp); ! 367: return; ! 368: } ! 369: } ! 370: /* ! 371: * The following dance is an inner loop ! 372: */ ! 373: count = ibp->wptr - ibp->rptr; ! 374: if ((c = obp->lim - obp->wptr) < count) ! 375: count = c; ! 376: while ((ctype = partab[c = *ibp->rptr++ & 0177] & 077) == 0) { ! 377: tp->t_col++; ! 378: *obp->wptr++ = c; ! 379: if (--count <= 0) ! 380: goto more; ! 381: } ! 382: if (c=='\t' && (tp->t_flags&TBDELAY)==XTABS) { ! 383: for (;;) { ! 384: *obp->wptr++ = ' '; ! 385: tp->t_col++; ! 386: if ((tp->t_col & 07) == 0) /* every 8 */ ! 387: break; ! 388: if (obp->wptr >= obp->lim) { ! 389: ibp->rptr--; ! 390: break; ! 391: } ! 392: } ! 393: continue; ! 394: } ! 395: ! 396: /* ! 397: * turn <nl> to <cr><lf> if desired. ! 398: */ ! 399: if (c=='\n' && tp->t_flags&CRMOD) { ! 400: if ((tp->t_state&TTCR)==0) { ! 401: tp->t_state |= TTCR; ! 402: c = '\r'; ! 403: ctype = partab['\r'] & 077; ! 404: --ibp->rptr; ! 405: } else ! 406: tp->t_state &= ~TTCR; ! 407: } ! 408: /* ! 409: * store character ! 410: */ ! 411: *obp->wptr++ = c; ! 412: /* ! 413: * Calculate delays and column movement ! 414: */ ! 415: count = 0; ! 416: switch (ctype) { ! 417: ! 418: /* ordinary */ ! 419: case 0: ! 420: tp->t_col++; ! 421: break; ! 422: ! 423: /* non-printing */ ! 424: case 1: ! 425: break; ! 426: ! 427: /* backspace */ ! 428: case 2: ! 429: if (tp->t_col) ! 430: tp->t_col--; ! 431: break; ! 432: ! 433: /* newline */ ! 434: case 3: ! 435: ctype = (tp->t_flags >> 8) & 03; ! 436: if(ctype == 1) { /* tty 37 */ ! 437: if (tp->t_col) ! 438: count = max(((unsigned)tp->t_col>>4) + 3, (unsigned)6); ! 439: } else if (ctype == 2) /* vt05 */ ! 440: count = 6; ! 441: if ((tp->t_flags&CRMOD)==0) ! 442: tp->t_col = 0; ! 443: break; ! 444: ! 445: /* tab */ ! 446: case 4: ! 447: ctype = (tp->t_flags >> 10) & 03; ! 448: if(ctype == 1) { /* tty 37 */ ! 449: count = 1 - (tp->t_col | ~07); ! 450: if (count < 5) ! 451: count = 0; ! 452: } ! 453: tp->t_col |= 07; ! 454: tp->t_col++; ! 455: break; ! 456: ! 457: /* vertical motion */ ! 458: case 5: ! 459: if(tp->t_flags & VTDELAY) ! 460: count = 127; ! 461: break; ! 462: ! 463: /* carriage return */ ! 464: case 6: ! 465: ctype = (tp->t_flags >> 12) & 03; ! 466: if (ctype == 1) /* tn 300 */ ! 467: count = 5; ! 468: else if (ctype == 2) /* ti 700 */ ! 469: count = 10; ! 470: else if (ctype == 3) ! 471: count = 20; ! 472: tp->t_col = 0; ! 473: break; ! 474: } ! 475: if (count) { ! 476: (*q->next->qinfo->putp)(q->next, obp); ! 477: if (obp = allocb(1)) { ! 478: obp->type = M_DELAY; ! 479: *obp->wptr++ = count; ! 480: (*q->next->qinfo->putp)(q->next, obp); ! 481: } ! 482: obp = NULL; ! 483: } ! 484: } ! 485: if (obp) ! 486: (*q->next->qinfo->putp)(q->next, obp); ! 487: freeb(ibp); ! 488: } ! 489: ! 490: /* ! 491: * Reader generates a signal and passes it up ! 492: */ ! 493: ttysig(q, sig) ! 494: register struct queue *q; ! 495: { ! 496: register struct ttyld *tp = (struct ttyld *)q->ptr; ! 497: ! 498: flushq(q, 0); /* flush reader */ ! 499: flushq(WR(q), 0); ! 500: tp->t_state &= ~TTESC; ! 501: tp->t_delct = 0; ! 502: putctl(q->next, M_FLUSH); ! 503: putctl1(q->next, M_SIGNAL, sig); ! 504: putctl(WR(q)->next, M_FLUSH); ! 505: } ! 506: ! 507: ttldioc(q, bp, rdq, fromdev) ! 508: register struct block *bp; ! 509: struct queue *q, *rdq; ! 510: { ! 511: register struct ttyld *tp; ! 512: register union stmsg *sp; ! 513: int s; ! 514: ! 515: sp = (union stmsg *)bp->rptr; ! 516: tp = (struct ttyld *)q->ptr; ! 517: switch (sp->ioc0.com) { ! 518: ! 519: /* ! 520: * Set new parameters ! 521: */ ! 522: case TIOCSETP: ! 523: case TIOCSETN: ! 524: s = spl6(); ! 525: if (sp->ioc1.sb.sg_flags & (RAW|CBREAK) ! 526: && (rdq->next->flag&QFULL)==0) { ! 527: register struct block *bp1; ! 528: ttyinsrv(rdq); ! 529: while (bp1 = getq(rdq)) ! 530: (*rdq->next->qinfo->putp)(rdq->next, bp1); ! 531: } ! 532: tp->t_erase = sp->ioc1.sb.sg_erase; ! 533: tp->t_kill = sp->ioc1.sb.sg_kill; ! 534: tp->t_flags = sp->ioc1.sb.sg_flags; ! 535: splx(s); ! 536: bp->type = M_IOCACK; ! 537: if (fromdev) ! 538: qreply(rdq, bp); /* reply to device side */ ! 539: else ! 540: qreply(q, bp); /* reply to process side */ ! 541: if (tp->t_flags & (RAW|CBREAK)) ! 542: rdq->flag &= ~(QDELIM|QNOENB); ! 543: else ! 544: rdq->flag |= QDELIM|QNOENB; ! 545: break; ! 546: ! 547: /* ! 548: * Send current parameters to user ! 549: */ ! 550: case TIOCGETP: ! 551: sp->ioc1.sb.sg_erase = tp->t_erase; ! 552: sp->ioc1.sb.sg_kill = tp->t_kill; ! 553: sp->ioc1.sb.sg_flags = tp->t_flags; ! 554: sp->ioc1.sb.sg_ispeed = ! 555: sp->ioc1.sb.sg_ospeed = B9600; ! 556: bp->wptr = bp->rptr+sizeof(struct ioc1); ! 557: bp->type = M_IOCACK; ! 558: if (fromdev) ! 559: qreply(rdq, bp); /* reply to device side */ ! 560: else ! 561: qreply(q, bp); /* reply to process side */ ! 562: break; ! 563: ! 564: /* ! 565: * Set and fetch special characters ! 566: */ ! 567: case TIOCSETC: ! 568: tp->t_chr = sp->ioc2.sb; ! 569: bp->wptr = bp->rptr; ! 570: bp->type = M_IOCACK; ! 571: if (fromdev) ! 572: qreply(rdq, bp); /* reply to device side */ ! 573: else ! 574: qreply(q, bp); /* reply to process side */ ! 575: break; ! 576: ! 577: case TIOCGETC: ! 578: sp->ioc2.sb = tp->t_chr; ! 579: bp->wptr = bp->rptr+sizeof(struct ioc2); ! 580: bp->type = M_IOCACK; ! 581: if (fromdev) ! 582: qreply(rdq, bp); /* reply to device side */ ! 583: else ! 584: qreply(q, bp); /* reply to process side */ ! 585: break; ! 586: ! 587: default: ! 588: if (fromdev) { ! 589: bp->type = M_IOCACK; ! 590: qreply(rdq, bp); /* reply to device side */ ! 591: } else ! 592: (*q->next->qinfo->putp)(q->next, bp); /* pass to device */ ! 593: break; ! 594: ! 595: } ! 596: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.