|
|
1.1 ! root 1: #include "sys/param.h" ! 2: #include "sys/stream.h" ! 3: #include "sys/ttyio.h" ! 4: #include "sys/ttyld.h" ! 5: #include "sys/conf.h" ! 6: ! 7: extern char partab[]; ! 8: ! 9: #define CANBSIZ 256 /* size of largest input line */ ! 10: ! 11: extern struct ttyld ttyld[]; ! 12: extern int ttycnt; ! 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: struct block *canonblock(); ! 34: ! 35: long ttyopen(); ! 36: int ttyclose(), ttyldin(), ttyinsrv(), ttyosrv(); ! 37: static struct qinit ttrinit = { ttyldin, ttyinsrv, ttyopen, ttyclose, 3*1024, 60}; ! 38: static struct qinit ttwinit = { putq, ttyosrv, ttyopen, ttyclose, 3*1024, 200}; ! 39: struct streamtab ttystream = { &ttrinit, &ttwinit}; ! 40: ! 41: /* ! 42: * TTY open ! 43: */ ! 44: long ! 45: ttyopen(qp, dev) ! 46: register struct queue *qp; ! 47: { ! 48: register struct ttyld *tp; ! 49: static struct tchars tchars = {CINTR,CQUIT,CSTART,CSTOP,CEOT,0377}; ! 50: ! 51: if (qp->ptr) /* already attached */ ! 52: return(1); ! 53: for (tp = ttyld; tp->t_state&TTUSE; tp++) ! 54: if (tp >= &ttyld[ttycnt-1]) ! 55: return(0); ! 56: tp->t_state = TTUSE; ! 57: tp->t_flags = ECHO|CRMOD; ! 58: tp->t_delct = 0; ! 59: tp->t_col = 0; ! 60: tp->t_erase = CERASE; ! 61: tp->t_kill = CKILL; ! 62: tp->t_chr = tchars; ! 63: qp->ptr = (caddr_t)tp; ! 64: qp->flag |= QDELIM|QNOENB; ! 65: WR(qp)->ptr = (caddr_t)tp; ! 66: return(1); ! 67: } ! 68: ! 69: ttyclose(qp) ! 70: struct queue *qp; ! 71: { ! 72: struct ttyld *tp = (struct ttyld *)qp->ptr; ! 73: ! 74: if (tp->t_state & TTSTOP) ! 75: putctl(WR(qp)->next, M_START); /* what else can we do? */ ! 76: tp->t_state = 0; ! 77: } ! 78: ! 79: /* ! 80: * Queue put procedure for tty input ! 81: */ ! 82: ttyldin(q, bp) ! 83: struct queue *q; ! 84: register struct block *bp; ! 85: { ! 86: register struct ttyld *tp; ! 87: register c; ! 88: register struct queue *wrq = WR(q); /* writer side */ ! 89: int escape, flags; ! 90: ! 91: tp = (struct ttyld *)q->ptr; ! 92: flags = tp->t_flags; ! 93: bp->class &= ~S_DELIM; ! 94: if (bp->type!=M_DATA) { ! 95: switch(bp->type) { ! 96: ! 97: case M_BREAK: ! 98: if (tp->t_flags&RAW) { /* speed-change hack*/ ! 99: bp->type = M_DATA; ! 100: bp->class &= ~S_DELIM; ! 101: if (bp->wptr<bp->lim) ! 102: *bp->wptr++ = '\0'; ! 103: break; ! 104: } ! 105: ttysig(q, SIGINT); ! 106: freeb(bp); ! 107: return; ! 108: ! 109: case M_HANGUP: ! 110: case M_IOCACK: ! 111: case M_IOCNAK: ! 112: (*q->next->qinfo->putp)(q->next, bp); ! 113: return; ! 114: ! 115: case M_IOCTL: ! 116: ttldioc(WR(q), bp, q, 1); ! 117: return; ! 118: } ! 119: flags |= RAW; ! 120: } ! 121: if (tp->t_flags&TANDEM && tp->t_state&TTBLOCK ! 122: && q->count <= q->qinfo->lolimit) { ! 123: tp->t_state &= ~TTBLOCK; ! 124: putd(putq, WR(q), tp->t_chr.t_startc); ! 125: } ! 126: if (flags&RAW) { ! 127: if ((q->next->flag&QFULL)==0 && q->count==0) ! 128: (*q->next->qinfo->putp)(q->next, bp); ! 129: else ! 130: putq(q, bp); ! 131: return; ! 132: } ! 133: while (bp->rptr<bp->wptr) { ! 134: c = *bp->rptr++ & 0177; ! 135: if (tp->t_state&TTSTOP) { ! 136: if (c!=tp->t_chr.t_stopc ! 137: || tp->t_chr.t_stopc==tp->t_chr.t_startc) { ! 138: tp->t_state &= ~TTSTOP; ! 139: putctl(wrq->next, M_START); ! 140: } ! 141: } else { ! 142: if (c==tp->t_chr.t_stopc) { ! 143: tp->t_state |= TTSTOP; ! 144: putctl(wrq->next, M_STOP); ! 145: } ! 146: } ! 147: if (c==tp->t_chr.t_stopc || c==tp->t_chr.t_startc) ! 148: continue; ! 149: if (c==tp->t_chr.t_intrc) { ! 150: ttysig(q, SIGINT); ! 151: continue; ! 152: } ! 153: if (c==tp->t_chr.t_quitc) { ! 154: ttysig(q, SIGQUIT); ! 155: continue; ! 156: } ! 157: if (c=='\r' && tp->t_flags&CRMOD) ! 158: c = '\n'; ! 159: if (tp->t_flags&LCASE && c>='A' && c<='Z') ! 160: c += 'a'-'A'; ! 161: escape = 0; ! 162: if (tp->t_flags & CBREAK) { ! 163: if ((q->next->flag&QFULL)==0 && q->count==0) ! 164: putd(q->next->qinfo->putp, q->next, c); ! 165: else ! 166: putd(putq, q, c); ! 167: } else { ! 168: if (tp->t_state&TTESC) { ! 169: escape = 1; ! 170: c |= 0200; ! 171: } ! 172: if (c == '\\') ! 173: tp->t_state |= TTESC; ! 174: else { ! 175: tp->t_state &= ~TTESC; ! 176: if (c == ('\\'|0200)) { ! 177: c &= 0177; ! 178: tp->t_state |= TTESC; ! 179: } ! 180: /* ttyhog? */ ! 181: if ((q->flag&QFULL) == 0 || (c=='\n' && tp->t_delct==0)) ! 182: putd(putq, q, c); ! 183: else ! 184: c = '\007'; ! 185: } ! 186: if ((c&0177)=='\n'||c==tp->t_chr.t_eofc ! 187: ||c==tp->t_chr.t_brkc) { ! 188: register struct block *bp1; ! 189: if (bp1 = allocb(1)) { ! 190: bp1->class |= S_DELIM; ! 191: tp->t_delct++; ! 192: putq(q, bp1); ! 193: } ! 194: qenable(q); ! 195: } ! 196: } ! 197: if (tp->t_flags&TANDEM && (tp->t_state&TTBLOCK) == 0 ! 198: && q->count >= (q->qinfo->limit+q->qinfo->lolimit)/2 ) { ! 199: q->next->flag |= QWANTW; ! 200: tp->t_state |= TTBLOCK; ! 201: putctl1d(wrq, M_DATA, tp->t_chr.t_stopc); ! 202: } ! 203: if (tp->t_flags&ECHO && (wrq->flag&QFULL)==0) { ! 204: c &= 0177; ! 205: if(bp->rptr == bp->wptr) ! 206: putctl1d(wrq, M_DATA, c); ! 207: else ! 208: putd(wrq->qinfo->putp, wrq, c); ! 209: if (c==tp->t_kill && (tp->t_flags&CBREAK)==0 ! 210: && !escape) ! 211: putctl1d(wrq, M_DATA, '\n'); ! 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, *bp1; ! 227: ! 228: tp = (struct ttyld *)q->ptr; ! 229: if (q->next->flag&QFULL) ! 230: return; ! 231: if (tp->t_flags&(CBREAK|RAW)) { ! 232: while ((q->next->flag&QFULL)==0 && (bp = getq(q))) ! 233: (*q->next->qinfo->putp)(q->next, bp); ! 234: } else { ! 235: while (tp->t_delct && q->first) { ! 236: bp1 = allocb(CANBSIZ); ! 237: if (bp1==NULL) ! 238: return; ! 239: while (bp = getq(q)) { ! 240: bp1 = canonblock(q, bp, bp1, tp); ! 241: if (bp1->class&S_DELIM) { ! 242: tp->t_delct--; ! 243: break; ! 244: } ! 245: } ! 246: (*q->next->qinfo->putp)(q->next, bp1); ! 247: } ! 248: } ! 249: if (tp->t_flags&TANDEM && tp->t_state&TTBLOCK ! 250: && q->count <= q->qinfo->lolimit) { ! 251: tp->t_state &= ~TTBLOCK; ! 252: putd(putq, WR(q), tp->t_chr.t_startc); ! 253: } ! 254: } ! 255: ! 256: /* ! 257: * canonicalize bp into bp1, noticing delimiter. bp is freed. ! 258: */ ! 259: struct block * ! 260: canonblock(q, bp, bp1, tp) ! 261: register struct queue *q; ! 262: register struct block *bp, *bp1; ! 263: register struct ttyld *tp; ! 264: { ! 265: register c; ! 266: ! 267: while (bp->rptr<bp->wptr) { ! 268: if (bp1->wptr >= bp1->lim-1) { ! 269: (*q->next->qinfo->putp)(q->next, bp1); ! 270: bp1 = allocb(CANBSIZ); ! 271: } ! 272: c = *bp->rptr++; ! 273: if ((c&0200) == 0) { /* not escaped */ ! 274: if (c == tp->t_erase) { ! 275: if (bp1->wptr > bp1->rptr) ! 276: bp1->wptr--; ! 277: continue; ! 278: } ! 279: if (c == tp->t_kill) { ! 280: bp1->wptr = bp1->rptr; ! 281: continue; ! 282: } ! 283: if (c == tp->t_chr.t_eofc) ! 284: continue; ! 285: } else { ! 286: c &= 0177; ! 287: if (tp->t_flags&LCASE && maptab[c]) ! 288: c = maptab[c]; ! 289: else if (c==tp->t_erase || c==tp->t_kill ! 290: || c==tp->t_chr.t_eofc) ! 291: ; ! 292: else ! 293: *bp1->wptr++ = '\\'; ! 294: } ! 295: *bp1->wptr++ = c; ! 296: } ! 297: if (bp->class&S_DELIM) ! 298: bp1->class |= S_DELIM; ! 299: freeb(bp); ! 300: return(bp1); ! 301: } ! 302: ! 303: /* ! 304: * TTY write processing: delays, tabs, CR/NL and the like. ! 305: */ ! 306: ttyosrv(q) ! 307: register struct queue *q; ! 308: { ! 309: register struct ttyld *tp; ! 310: register struct block *bp; ! 311: ! 312: tp = (struct ttyld *)q->ptr; ! 313: while (bp = getq(q)) { ! 314: switch(bp->type) { ! 315: ! 316: default: ! 317: freeb(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: putctl1(q->next, M_DELAY, count); ! 478: obp = NULL; ! 479: } ! 480: } ! 481: if (obp) { ! 482: obp->class |= ibp->class&S_DELIM; ! 483: (*q->next->qinfo->putp)(q->next, obp); ! 484: } else if (ibp->class&S_DELIM) ! 485: putctld(q->next, M_DATA); ! 486: freeb(ibp); ! 487: } ! 488: ! 489: /* ! 490: * Reader generates a signal and passes it up ! 491: */ ! 492: ttysig(q, sig) ! 493: register struct queue *q; ! 494: { ! 495: register struct ttyld *tp = (struct ttyld *)q->ptr; ! 496: ! 497: flushq(q, 0); /* flush reader */ ! 498: flushq(WR(q), 0); ! 499: tp->t_state &= ~TTESC; ! 500: tp->t_delct = 0; ! 501: putctl(q->next, M_FLUSH); ! 502: putctl1(q->next, M_SIGNAL, sig); ! 503: putctl(WR(q)->next, M_FLUSH); ! 504: } ! 505: ! 506: ttldioc(q, bp, rdq, fromdev) ! 507: register struct block *bp; ! 508: struct queue *q, *rdq; ! 509: { ! 510: register struct ttyld *tp; ! 511: register struct sgttyb *sp; ! 512: int s; ! 513: ! 514: sp = (struct sgttyb *)stiodata(bp); ! 515: tp = (struct ttyld *)q->ptr; ! 516: switch (stiocom(bp)) { ! 517: ! 518: /* ! 519: * Set new parameters ! 520: */ ! 521: case TIOCSETP: ! 522: case TIOCSETN: ! 523: s = spl6(); ! 524: if (sp->sg_flags & (RAW|CBREAK) ! 525: && (rdq->next->flag&QFULL)==0) { ! 526: register struct block *bp1; ! 527: ttyinsrv(rdq); ! 528: while (bp1 = getq(rdq)) ! 529: (*rdq->next->qinfo->putp)(rdq->next, bp1); ! 530: } ! 531: tp->t_erase = sp->sg_erase; ! 532: tp->t_kill = sp->sg_kill; ! 533: tp->t_flags = sp->sg_flags; ! 534: splx(s); ! 535: bp->type = M_IOCACK; ! 536: if (tp->t_flags & (RAW|CBREAK)) ! 537: rdq->flag &= ~(QDELIM|QNOENB); ! 538: else ! 539: rdq->flag |= QDELIM|QNOENB; ! 540: if (tp->t_flags & RAW && tp->t_state & TTSTOP) { ! 541: putctl(q->next, M_START); /* else it is stuck forever */ ! 542: tp->t_state &=~ TTSTOP; ! 543: } ! 544: break; ! 545: ! 546: /* ! 547: * Send current parameters to user ! 548: */ ! 549: case TIOCGETP: ! 550: sp->sg_erase = tp->t_erase; ! 551: sp->sg_kill = tp->t_kill; ! 552: sp->sg_flags = tp->t_flags; ! 553: sp->sg_ispeed = sp->sg_ospeed = B9600; ! 554: bp->wptr = bp->rptr+sizeof(struct sgttyb)+STIOCHDR; ! 555: bp->type = M_IOCACK; ! 556: break; ! 557: ! 558: /* ! 559: * Set and fetch special characters ! 560: */ ! 561: case TIOCSETC: ! 562: tp->t_chr = *(struct tchars *)((struct stioctl *)bp->rptr)->data; ! 563: bp->wptr = bp->rptr; ! 564: bp->type = M_IOCACK; ! 565: break; ! 566: ! 567: case TIOCGETC: ! 568: *(struct tchars *)((struct stioctl *)bp->rptr)->data = tp->t_chr; ! 569: bp->wptr = bp->rptr+sizeof(struct tchars)+STIOCHDR; ! 570: bp->type = M_IOCACK; ! 571: break; ! 572: ! 573: default: ! 574: if (fromdev) { ! 575: bp->type = M_IOCACK; ! 576: qreply(rdq, bp); /* reply to device side */ ! 577: } else ! 578: (*q->next->qinfo->putp)(q->next, bp); /* pass to device */ ! 579: return; ! 580: ! 581: } ! 582: if (fromdev) ! 583: qreply(rdq, bp); /* to device side */ ! 584: else ! 585: qreply(q, bp); /* to process side */ ! 586: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.