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