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