|
|
1.1 ! root 1: #include "../h/param.h" ! 2: #include "../h/stream.h" ! 3: #include "../h/ioctl.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_stopc ! 133: || tp->t_chr.t_stopc==tp->t_chr.t_startc) { ! 134: tp->t_state &= ~TTSTOP; ! 135: putctl(wrq->next, M_START); ! 136: } ! 137: } else { ! 138: if (c==tp->t_chr.t_stopc) { ! 139: tp->t_state |= TTSTOP; ! 140: putctl(wrq->next, M_STOP); ! 141: } ! 142: } ! 143: if (c==tp->t_chr.t_stopc || c==tp->t_chr.t_startc) ! 144: continue; ! 145: if (c==tp->t_chr.t_intrc) { ! 146: ttysig(q, SIGINT); ! 147: continue; ! 148: } ! 149: if (c==tp->t_chr.t_quitc) { ! 150: ttysig(q, SIGQUIT); ! 151: continue; ! 152: } ! 153: if (c=='\r' && tp->t_flags&CRMOD) ! 154: c = '\n'; ! 155: if (tp->t_flags&LCASE && c>='A' && c<='Z') ! 156: c += 'a'-'A'; ! 157: escape = 0; ! 158: if (tp->t_flags & CBREAK) { ! 159: if ((q->next->flag&QFULL)==0 && q->count==0) ! 160: putd(q->next->qinfo->putp, q->next, c); ! 161: else ! 162: putd(putq, q, c); ! 163: } else { ! 164: if (tp->t_state&TTESC) { ! 165: escape = 1; ! 166: c |= 0200; ! 167: } ! 168: if (c == '\\') ! 169: tp->t_state |= TTESC; ! 170: else { ! 171: tp->t_state &= ~TTESC; ! 172: if (c == ('\\'|0200)) { ! 173: c &= 0177; ! 174: tp->t_state |= TTESC; ! 175: } ! 176: /* ttyhog? */ ! 177: if (q->count<512 || (c=='\n' && tp->t_delct==0)) ! 178: putd(putq, q, c); ! 179: else ! 180: c = '\007'; ! 181: } ! 182: c &= 0177; ! 183: if (c=='\n'||c==tp->t_chr.t_eofc||c==tp->t_chr.t_brkc) { ! 184: register struct block *bp1; ! 185: if (bp1 = allocb(1)) { ! 186: bp1->type = M_DELIM; ! 187: putq(q, bp1); ! 188: tp->t_delct++; ! 189: } ! 190: qenable(q); ! 191: } ! 192: } ! 193: if (tp->t_flags&TANDEM && (tp->t_state&TTBLOCK) == 0 ! 194: && q->count >= (q->qinfo->limit+q->qinfo->lolimit)/2 ) { ! 195: q->next->flag |= QWANTW; ! 196: tp->t_state |= TTBLOCK; ! 197: putd(putq, wrq, tp->t_chr.t_stopc); ! 198: } ! 199: if (tp->t_flags&ECHO && (wrq->flag&QFULL)==0) { ! 200: register c1 = c&0177; ! 201: if (c1!=CEOT) { ! 202: putd(putq, wrq, c1); ! 203: if(wrq->next->flag&QDELIM && bp->wptr==bp->rptr) ! 204: putctl(wrq, M_DELIM); ! 205: } ! 206: if (c==tp->t_kill && (tp->t_flags&CBREAK)==0 ! 207: && !escape) { ! 208: putd(putq, wrq, '\n'); ! 209: if (wrq->next->flag&QDELIM) ! 210: putctl(wrq, M_DELIM); ! 211: } ! 212: } ! 213: } ! 214: freeb(bp); ! 215: } ! 216: ! 217: /* ! 218: * tty input server processing. Erase-kill and escape processing; ! 219: * gathering into lines. ! 220: */ ! 221: ! 222: ttyinsrv(q) ! 223: register struct queue *q; ! 224: { ! 225: register struct ttyld *tp; ! 226: register struct block *bp; ! 227: register char *op; ! 228: register c; ! 229: static char canonb[CANBSIZ]; ! 230: ! 231: tp = (struct ttyld *)q->ptr; ! 232: if (q->next->flag&QFULL) ! 233: return; ! 234: if (tp->t_flags&(CBREAK|RAW)) { ! 235: while ((q->next->flag&QFULL)==0 && (bp = getq(q))) ! 236: (*q->next->qinfo->putp)(q->next, bp); ! 237: } else { ! 238: op = canonb; ! 239: while (tp->t_delct) { ! 240: bp = getq(q); ! 241: if (bp==NULL || bp->type!=M_DATA) { ! 242: if (op > canonb) ! 243: putcpy(q->next, canonb, op-canonb); ! 244: if (bp) { ! 245: (*q->next->qinfo->putp)(q->next, bp); ! 246: tp->t_delct--; ! 247: op = canonb; ! 248: continue; ! 249: } ! 250: return; ! 251: } ! 252: while (bp->rptr<bp->wptr) { ! 253: c = *bp->rptr++; ! 254: if ((c&0200) == 0) { /* not escaped */ ! 255: if (c == tp->t_erase) { ! 256: if (op > canonb) ! 257: op--; ! 258: continue; ! 259: } ! 260: if (c == tp->t_kill) { ! 261: op = canonb; ! 262: continue; ! 263: } ! 264: if (c == tp->t_chr.t_eofc) ! 265: continue; ! 266: } else { ! 267: c &= 0177; ! 268: if (tp->t_flags&LCASE && maptab[c]) ! 269: c = maptab[c]; ! 270: else if (c==tp->t_erase || c==tp->t_kill ! 271: || c==tp->t_chr.t_eofc) ! 272: ; ! 273: else ! 274: *op++ = '\\'; ! 275: } ! 276: *op++ = c; ! 277: if (op >= &canonb[CANBSIZ-1]) { ! 278: putcpy(q->next, canonb, op-canonb); ! 279: op = canonb; ! 280: } ! 281: } ! 282: freeb(bp); ! 283: } ! 284: } ! 285: if (tp->t_flags&TANDEM && tp->t_state&TTBLOCK ! 286: && q->count <= q->qinfo->lolimit) { ! 287: tp->t_state &= ~TTBLOCK; ! 288: putd(putq, WR(q), tp->t_chr.t_startc); ! 289: } ! 290: } ! 291: ! 292: /* ! 293: * TTY write processing: delays, tabs, CR/NL and the like. ! 294: */ ! 295: ttyosrv(q) ! 296: register struct queue *q; ! 297: { ! 298: register struct ttyld *tp; ! 299: register struct block *bp; ! 300: ! 301: tp = (struct ttyld *)q->ptr; ! 302: while (bp = getq(q)) { ! 303: switch(bp->type) { ! 304: ! 305: default: ! 306: freeb(bp); ! 307: continue; ! 308: ! 309: case M_DELIM: ! 310: if ((q->next->flag & QDELIM) == 0) { ! 311: freeb(bp); ! 312: continue; ! 313: } ! 314: if (q->next->flag & QFULL) { ! 315: putbq(q, bp); ! 316: return; ! 317: } ! 318: (*q->next->qinfo->putp)(q->next, bp); ! 319: continue; ! 320: ! 321: case M_IOCTL: ! 322: if (q->next->flag & QFULL) { ! 323: putbq(q, bp); ! 324: return; ! 325: } ! 326: ttldioc(q, bp, RD(q), 0); ! 327: continue; ! 328: ! 329: case M_FLUSH: ! 330: flushq(q, 0); ! 331: case M_IOCNAK: /* flow through */ ! 332: case M_IOCACK: ! 333: (*q->next->qinfo->putp)(q->next, bp); ! 334: continue; ! 335: ! 336: case M_DATA: ! 337: case M_BREAK: ! 338: if (q->next->flag & QFULL) { ! 339: putbq(q, bp); ! 340: return; ! 341: } ! 342: if (tp->t_flags&RAW || bp->type==M_BREAK) { ! 343: (*q->next->qinfo->putp)(q->next, bp); ! 344: } else ! 345: outconv(q, bp); ! 346: continue; ! 347: } ! 348: } ! 349: } ! 350: ! 351: outconv(q, ibp) ! 352: struct queue *q; ! 353: register struct block *ibp; ! 354: { ! 355: register struct ttyld *tp; ! 356: register struct block *obp = NULL; ! 357: register c; ! 358: register count, ctype; ! 359: ! 360: tp = (struct ttyld *)q->ptr; ! 361: more: ! 362: while (ibp->rptr < ibp->wptr) { ! 363: if (obp==NULL || obp->wptr >= obp->lim) { ! 364: if (obp) ! 365: (*q->next->qinfo->putp)(q->next, obp); ! 366: if (q->next->flag&QFULL || (obp=allocb(QBSIZE))==NULL) { ! 367: putbq(q, ibp); ! 368: return; ! 369: } ! 370: } ! 371: /* ! 372: * The following dance is an inner loop ! 373: */ ! 374: count = ibp->wptr - ibp->rptr; ! 375: if ((c = obp->lim - obp->wptr) < count) ! 376: count = c; ! 377: while ((ctype = partab[c = *ibp->rptr++ & 0177] & 077) == 0) { ! 378: tp->t_col++; ! 379: *obp->wptr++ = c; ! 380: if (--count <= 0) ! 381: goto more; ! 382: } ! 383: if (c=='\t' && (tp->t_flags&TBDELAY)==XTABS) { ! 384: for (;;) { ! 385: *obp->wptr++ = ' '; ! 386: tp->t_col++; ! 387: if ((tp->t_col & 07) == 0) /* every 8 */ ! 388: break; ! 389: if (obp->wptr >= obp->lim) { ! 390: ibp->rptr--; ! 391: break; ! 392: } ! 393: } ! 394: continue; ! 395: } ! 396: ! 397: /* ! 398: * turn <nl> to <cr><lf> if desired. ! 399: */ ! 400: if (c=='\n' && tp->t_flags&CRMOD) { ! 401: if ((tp->t_state&TTCR)==0) { ! 402: tp->t_state |= TTCR; ! 403: c = '\r'; ! 404: ctype = partab['\r'] & 077; ! 405: --ibp->rptr; ! 406: } else ! 407: tp->t_state &= ~TTCR; ! 408: } ! 409: /* ! 410: * store character ! 411: */ ! 412: *obp->wptr++ = c; ! 413: /* ! 414: * Calculate delays and column movement ! 415: */ ! 416: count = 0; ! 417: switch (ctype) { ! 418: ! 419: /* ordinary */ ! 420: case 0: ! 421: tp->t_col++; ! 422: break; ! 423: ! 424: /* non-printing */ ! 425: case 1: ! 426: break; ! 427: ! 428: /* backspace */ ! 429: case 2: ! 430: if (tp->t_col) ! 431: tp->t_col--; ! 432: break; ! 433: ! 434: /* newline */ ! 435: case 3: ! 436: ctype = (tp->t_flags >> 8) & 03; ! 437: if(ctype == 1) { /* tty 37 */ ! 438: if (tp->t_col) ! 439: count = max(((unsigned)tp->t_col>>4) + 3, (unsigned)6); ! 440: } else if (ctype == 2) /* vt05 */ ! 441: count = 6; ! 442: if ((tp->t_flags&CRMOD)==0) ! 443: tp->t_col = 0; ! 444: break; ! 445: ! 446: /* tab */ ! 447: case 4: ! 448: ctype = (tp->t_flags >> 10) & 03; ! 449: if(ctype == 1) { /* tty 37 */ ! 450: count = 1 - (tp->t_col | ~07); ! 451: if (count < 5) ! 452: count = 0; ! 453: } ! 454: tp->t_col |= 07; ! 455: tp->t_col++; ! 456: break; ! 457: ! 458: /* vertical motion */ ! 459: case 5: ! 460: if(tp->t_flags & VTDELAY) ! 461: count = 127; ! 462: break; ! 463: ! 464: /* carriage return */ ! 465: case 6: ! 466: ctype = (tp->t_flags >> 12) & 03; ! 467: if (ctype == 1) /* tn 300 */ ! 468: count = 5; ! 469: else if (ctype == 2) /* ti 700 */ ! 470: count = 10; ! 471: else if (ctype == 3) ! 472: count = 20; ! 473: tp->t_col = 0; ! 474: break; ! 475: } ! 476: if (count) { ! 477: (*q->next->qinfo->putp)(q->next, obp); ! 478: if (obp = allocb(1)) { ! 479: obp->type = M_DELAY; ! 480: *obp->wptr++ = count; ! 481: (*q->next->qinfo->putp)(q->next, obp); ! 482: } ! 483: obp = NULL; ! 484: } ! 485: } ! 486: if (obp) ! 487: (*q->next->qinfo->putp)(q->next, obp); ! 488: freeb(ibp); ! 489: } ! 490: ! 491: /* ! 492: * Reader generates a signal and passes it up ! 493: */ ! 494: ttysig(q, sig) ! 495: register struct queue *q; ! 496: { ! 497: register struct ttyld *tp = (struct ttyld *)q->ptr; ! 498: ! 499: flushq(q, 0); /* flush reader */ ! 500: flushq(WR(q), 0); ! 501: tp->t_state &= ~TTESC; ! 502: tp->t_delct = 0; ! 503: putctl1(q->next, M_FLUSH); ! 504: putctl1(q->next, M_SIGNAL, sig); ! 505: putctl(WR(q)->next, M_FLUSH); ! 506: } ! 507: ! 508: ttldioc(q, bp, rdq, fromdev) ! 509: register struct block *bp; ! 510: struct queue *q, *rdq; ! 511: { ! 512: register struct ttyld *tp; ! 513: register union stmsg *sp; ! 514: register rawcb; ! 515: int s; ! 516: ! 517: sp = (union stmsg *)bp->rptr; ! 518: tp = (struct ttyld *)q->ptr; ! 519: switch (sp->ioc0.com) { ! 520: ! 521: /* ! 522: * Set new parameters ! 523: */ ! 524: case TIOCSETP: ! 525: case TIOCSETN: ! 526: s = spl6(); ! 527: if (sp->ioc1.sb.sg_flags & (RAW|CBREAK) ! 528: && (rdq->next->flag&QFULL)==0) { ! 529: register struct block *bp1; ! 530: ttyinsrv(rdq); ! 531: while (bp1 = getq(rdq)) ! 532: (*rdq->next->qinfo->putp)(rdq->next, bp1); ! 533: } ! 534: tp->t_erase = sp->ioc1.sb.sg_erase; ! 535: tp->t_kill = sp->ioc1.sb.sg_kill; ! 536: tp->t_flags = sp->ioc1.sb.sg_flags; ! 537: splx(s); ! 538: if (fromdev) { ! 539: bp->type = M_IOCACK; ! 540: qreply(rdq, bp); /* reply to device side */ ! 541: } else ! 542: (*q->next->qinfo->putp)(q->next, bp); /* pass to device */ ! 543: if (tp->t_flags & (RAW|CBREAK)) ! 544: rdq->flag &= ~(QDELIM|QNOENB); ! 545: else ! 546: rdq->flag |= QDELIM|QNOENB; ! 547: break; ! 548: ! 549: /* ! 550: * Send current parameters to user ! 551: */ ! 552: case TIOCGETP: ! 553: sp->ioc1.sb.sg_erase = tp->t_erase; ! 554: sp->ioc1.sb.sg_kill = tp->t_kill; ! 555: sp->ioc1.sb.sg_flags = tp->t_flags; ! 556: bp->wptr = bp->rptr+sizeof(struct ioc1); ! 557: if (fromdev) { ! 558: bp->type = M_IOCACK; ! 559: qreply(rdq, bp); /* reply to device side */ ! 560: } else ! 561: (*q->next->qinfo->putp)(q->next, bp); /* pass to device */ ! 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.