|
|
1.1 ! root 1: #include "sys/param.h" ! 2: #include "sys/stream.h" ! 3: #include "sys/conf.h" ! 4: #include "sys/ttyio.h" ! 5: #include "sys/xttyld.h" ! 6: ! 7: #define ICANBSIZ 256 ! 8: #define CTRL(C) ((C) != '?' ? (C) & 0x1F : 0x7F) ! 9: ! 10: extern int xttycnt; ! 11: extern struct xttyld xttyld[]; ! 12: ! 13: static long open(); ! 14: static close(); ! 15: static rsrv(), wsrv(); ! 16: ! 17: static struct qinit rinit = { putq, rsrv, open, close, 600, 300 }; ! 18: static struct qinit winit = { putq, wsrv, open, close, 600, 300 }; ! 19: struct streamtab xttystream = { &rinit, &winit }; ! 20: ! 21: static struct xttyld xttyproto = { ! 22: B9600, B9600, /* sg_ispeed and sg_ospeed */ ! 23: '\b', '@', /* sg_erase and sg_kill */ ! 24: ECHO | CRMOD, /* sg_flags */ ! 25: CTRL('?'), CTRL('\\'), /* t_intrc and t_quitc */ ! 26: CTRL('Q'), CTRL('S'), /* t_startc and t_stopc */ ! 27: CTRL('D'), 0377, /* t_eofc and t_brkc */ ! 28: }; ! 29: ! 30: static char maptab[] = { ! 31: 000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000, ! 32: 000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000, ! 33: 000,'|',000,000,000,000,000,'`','{','}',000,000,000,000,000,000, ! 34: 000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000, ! 35: 000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000, ! 36: 000,000,000,000,000,000,000,000,000,000,000,000,'\\',000,'~',000, ! 37: 000,'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O', ! 38: 'P','Q','R','S','T','U','V','W','X','Y','Z',000,000,000,000,000, ! 39: }; ! 40: ! 41: static long ! 42: open(qp, dev) ! 43: register struct queue *qp; ! 44: dev_t dev; ! 45: { ! 46: int i; ! 47: ! 48: for (i = 0; i < xttycnt; ++i) ! 49: if (!xttyld[i].qp) { ! 50: xttyld[i] = xttyproto; ! 51: xttyld[i].qp = qp; ! 52: qp->flag |= QDELIM; ! 53: qp->ptr = (caddr_t) &xttyld[i]; ! 54: WR(qp)->flag |= QDELIM; ! 55: WR(qp)->ptr = (caddr_t) &xttyld[i]; ! 56: return 1; ! 57: } ! 58: return 0; ! 59: } ! 60: ! 61: static ! 62: close(qp) ! 63: struct queue *qp; ! 64: { ! 65: register struct xttyld *xt; ! 66: ! 67: xt = (struct xttyld *) qp->ptr; ! 68: if (xt->icanb) { ! 69: freeb(xt->icanb); ! 70: xt->icanb = 0; ! 71: } ! 72: xt->qp = 0; ! 73: } ! 74: ! 75: static void ! 76: ctl(qp, bp) ! 77: struct queue *qp; ! 78: register struct block *bp; ! 79: { ! 80: register struct xttyld *xt; ! 81: register u_char *data; ! 82: ! 83: xt = (struct xttyld *) qp->ptr; ! 84: data = (u_char *) stiodata(bp); ! 85: ! 86: switch (stiocom(bp)) { ! 87: case TIOCGETC: ! 88: *(struct tchars *) data = xt->tc; ! 89: bp->type = M_IOCACK; ! 90: bp->wptr = bp->rptr + STIOCHDR + sizeof (struct tchars); ! 91: break; ! 92: case TIOCSETC: ! 93: xt->tc = *(struct tchars *) data; ! 94: bp->type = M_IOCACK; ! 95: bp->wptr = bp->rptr + STIOCHDR; ! 96: break; ! 97: case TIOCGETP: ! 98: *(struct sgttyb *) data = xt->sg; ! 99: bp->type = M_IOCACK; ! 100: bp->wptr = bp->rptr + STIOCHDR + sizeof (struct sgttyb); ! 101: break; ! 102: case TIOCSETN: ! 103: case TIOCSETP: ! 104: xt->sg = *(struct sgttyb *) data; ! 105: bp->type = M_IOCACK; ! 106: bp->wptr = bp->rptr + STIOCHDR; ! 107: break; ! 108: default: ! 109: (*qp->next->qinfo->putp)(qp->next, bp); ! 110: return; ! 111: } ! 112: (*OTHERQ(qp)->next->qinfo->putp)(OTHERQ(qp)->next, bp); ! 113: if (xt->status & XTTY_FULL && !(xt->sg.sg_flags & TANDEM)) { ! 114: xt->status &= ~XTTY_FULL; ! 115: putctl1d(WR(xt->qp), M_DATA, xt->tc.t_startc); ! 116: } ! 117: if (xt->sg.sg_flags & RAW) { ! 118: xt->status = 0; ! 119: qenable(WR(xt->qp)); ! 120: } ! 121: if (xt->sg.sg_flags & (RAW | CBREAK)) ! 122: xt->qp->flag &= ~QDELIM; ! 123: else ! 124: xt->qp->flag |= QDELIM; ! 125: } ! 126: ! 127: static void ! 128: sig(xt, sig) ! 129: register struct xttyld *xt; ! 130: int sig; ! 131: { ! 132: register struct queue *qp; ! 133: ! 134: qp = xt->qp; ! 135: flushq(qp, 0); ! 136: flushq(WR(qp), 0); ! 137: if (xt->icanb) { ! 138: freeb(xt->icanb); ! 139: xt->icanb = 0; ! 140: } ! 141: xt->status &= ~(XTTY_ESCAPED | XTTY_NEWLINE | XTTY_STOPPED); ! 142: qenable(WR(qp)); ! 143: putctl(qp->next, M_FLUSH); ! 144: putctl1(qp->next, M_SIGNAL, sig); ! 145: putctl(WR(qp)->next, M_FLUSH); ! 146: } ! 147: ! 148: static int ! 149: icanon(xt, bp) ! 150: register struct xttyld *xt; ! 151: register struct block *bp; ! 152: { ! 153: register struct block *icanb; ! 154: register int c, esc; ! 155: ! 156: icanb = xt->icanb; ! 157: esc = xt->sg.sg_flags & CBREAK ? 0 : xt->status & XTTY_ESCAPED; ! 158: xt->status &= ~XTTY_ESCAPED; ! 159: while (bp->rptr < bp->wptr) { ! 160: if (xt->status & XTTY_STOPPED) { ! 161: xt->status &= ~XTTY_STOPPED; ! 162: qenable(WR(xt->qp)); ! 163: } ! 164: c = *bp->rptr++; ! 165: if (xt->sg.sg_flags & CRMOD && c == '\r') ! 166: c = '\n'; ! 167: if (xt->sg.sg_flags & LCASE && c >= 'A' && c <= 'Z') ! 168: c += 'a' - 'A'; ! 169: if (esc) { ! 170: if (icanb->wptr > icanb->rptr ! 171: && (c == xt->sg.sg_erase || c == xt->sg.sg_kill ! 172: || c == xt->tc.t_eofc || c == xt->tc.t_brkc ! 173: || c == xt->tc.t_intrc || c == xt->tc.t_quitc ! 174: || c == xt->tc.t_startc || c == xt->tc.t_stopc)) ! 175: --icanb->wptr; ! 176: if (c < sizeof maptab && maptab[c]) ! 177: c = maptab[c]; ! 178: c |= 0x100; ! 179: } ! 180: if (c == xt->tc.t_intrc || c == xt->tc.t_quitc) { ! 181: bp->rptr = bp->wptr; ! 182: sig(xt, c == xt->tc.t_intrc ? SIGINT : SIGQUIT); ! 183: return 0; ! 184: } ! 185: if (c == xt->tc.t_stopc) { ! 186: xt->status |= XTTY_STOPPED; ! 187: return 0; ! 188: } ! 189: if (c == xt->tc.t_startc) ! 190: return 0; ! 191: if (xt->sg.sg_flags & ECHO) ! 192: putctl1d(WR(xt->qp), M_DATA, c); ! 193: if (!(xt->sg.sg_flags & CBREAK)) { ! 194: if (c == xt->sg.sg_erase) { ! 195: if (icanb->wptr > icanb->rptr) ! 196: --icanb->wptr; ! 197: continue; ! 198: } ! 199: if (c == xt->sg.sg_kill) { ! 200: icanb->wptr = icanb->rptr; ! 201: if (xt->sg.sg_flags & ECHO) ! 202: putctl1d(WR(xt->qp), M_DATA, '\n'); ! 203: continue; ! 204: } ! 205: } ! 206: if ((xt->sg.sg_flags & CBREAK) || c != xt->tc.t_eofc) ! 207: if (icanb->wptr < icanb->lim) ! 208: *icanb->wptr++ = c; ! 209: else { ! 210: *--bp->rptr = c; ! 211: return 1; ! 212: } ! 213: if (!(xt->sg.sg_flags & CBREAK)) { ! 214: if (c == xt->tc.t_eofc || c == xt->tc.t_brkc || c == '\n') ! 215: return 1; ! 216: esc = (c & 0xFF) == '\\' ? XTTY_ESCAPED : 0; ! 217: } ! 218: } ! 219: xt->status |= esc; ! 220: return xt->sg.sg_flags & CBREAK; ! 221: } ! 222: ! 223: static ! 224: rsrv(qp) ! 225: struct queue *qp; ! 226: { ! 227: register struct xttyld *xt; ! 228: struct block *bp; ! 229: ! 230: xt = (struct xttyld *) qp->ptr; ! 231: if (!xt->qp) ! 232: return; ! 233: while ((qp->next->flag & QFULL) == 0) { ! 234: if (xt->sg.sg_flags & RAW && xt->icanb) { ! 235: (*qp->next->qinfo->putp)(qp->next, xt->icanb); ! 236: xt->icanb = 0; ! 237: continue; ! 238: } ! 239: bp = getq(qp); ! 240: if (!bp) ! 241: break; ! 242: if (!(xt->sg.sg_flags & RAW) && bp->type == M_DATA) { ! 243: do { ! 244: if (!xt->icanb) { ! 245: if (xt->sg.sg_flags & CBREAK) ! 246: xt->icanb = allocb(bp->rptr - bp->wptr); ! 247: else ! 248: xt->icanb = allocb(ICANBSIZ); ! 249: if (!xt->icanb) { ! 250: putbq(qp, bp); ! 251: qp->next->flag |= QWANTW; ! 252: return; ! 253: } ! 254: xt->icanb->type = M_DATA; ! 255: } ! 256: if (icanon(xt, bp)) { ! 257: if (!(xt->sg.sg_flags & CBREAK)) ! 258: xt->icanb->class |= S_DELIM; ! 259: (*qp->next->qinfo->putp)(qp->next, xt->icanb); ! 260: xt->icanb = 0; ! 261: } ! 262: } while (bp->rptr != bp->wptr); ! 263: freeb(bp); ! 264: } else if (bp->type == M_IOCTL) ! 265: ctl(qp, bp); ! 266: else { ! 267: switch (bp->type) { ! 268: case M_BREAK: ! 269: if (xt->sg.sg_flags & RAW) { ! 270: bp->type = M_DATA; ! 271: bp->class |= S_DELIM; ! 272: if (bp->wptr < bp->lim) ! 273: *bp->wptr++ = '\0'; ! 274: } else { ! 275: freeb(bp); ! 276: sig(xt, SIGINT); ! 277: return; ! 278: } ! 279: break; ! 280: case M_FLUSH: ! 281: if (xt->icanb) ! 282: xt->icanb->wptr = xt->icanb->rptr; ! 283: break; ! 284: } ! 285: bp->class &= ~S_DELIM; ! 286: (*qp->next->qinfo->putp)(qp->next, bp); ! 287: } ! 288: } ! 289: if ((xt->sg.sg_flags & (RAW | TANDEM)) == TANDEM) { ! 290: if (!(xt->status & XTTY_FULL) && qp->next->flag & QFULL) { ! 291: xt->status |= XTTY_FULL; ! 292: putctl1d(WR(qp), M_DATA, xt->tc.t_stopc); ! 293: } ! 294: if (xt->status & XTTY_FULL && (!qp->next->flag & QFULL)) { ! 295: xt->status &= ~XTTY_FULL; ! 296: putctl1d(WR(qp), M_DATA, xt->tc.t_startc); ! 297: } ! 298: } ! 299: if (qp->count) ! 300: qp->next->flag |= QWANTW; ! 301: } ! 302: ! 303: static int ! 304: ocanon(xt, bp, qp) ! 305: register struct xttyld *xt; ! 306: register struct block *bp; ! 307: struct queue *qp; ! 308: { ! 309: register struct block *ocanb; ! 310: register int c, d, t; ! 311: ! 312: while (bp->rptr < bp->wptr) { ! 313: ocanb = allocb(bp->wptr - bp->rptr + 8); ! 314: if (!ocanb) ! 315: return 0; ! 316: ocanb->class |= S_DELIM; ! 317: d = 0; ! 318: while (bp->rptr < bp->wptr && ocanb->wptr < ocanb->lim - 8) { ! 319: c = *bp->rptr++; ! 320: t = 8 - (xt->col & 7); ! 321: if (xt->status & XTTY_NEWLINE) ! 322: xt->status &= ~XTTY_NEWLINE; ! 323: else if (xt->sg.sg_flags & CRMOD) { ! 324: if (c == '\n') { ! 325: --bp->rptr; ! 326: c = '\r'; ! 327: xt->status |= XTTY_NEWLINE; ! 328: } else if (c == '\r') { ! 329: *--bp->rptr = '\n'; ! 330: xt->status |= XTTY_NEWLINE; ! 331: } ! 332: } ! 333: switch (c) { ! 334: case '\v': ! 335: case '\f': ! 336: xt->col = 0; ! 337: if (xt->sg.sg_flags & VTDELAY) ! 338: d = 127; ! 339: break; ! 340: case '\r': ! 341: xt->col = 0; ! 342: switch (xt->sg.sg_flags & CRDELAY) { ! 343: case CR1: ! 344: d = 5; ! 345: break; ! 346: case CR2: ! 347: d = 10; ! 348: break; ! 349: case CR3: ! 350: d = 20; ! 351: break; ! 352: } ! 353: break; ! 354: case '\t': ! 355: xt->col += t; ! 356: switch (xt->sg.sg_flags & TBDELAY) { ! 357: case TAB1: ! 358: d = t; ! 359: if (d < 5) ! 360: d = 0; ! 361: break; ! 362: case XTABS: ! 363: while (t--) ! 364: *ocanb->wptr++ = ' '; ! 365: continue; ! 366: } ! 367: break; ! 368: case '\n': ! 369: xt->col = 0; ! 370: switch (xt->sg.sg_flags & NLDELAY) { ! 371: case NL1: ! 372: d = max((xt->col >> 4) + 3, 6); ! 373: break; ! 374: case NL2: ! 375: d = 6; ! 376: break; ! 377: } ! 378: break; ! 379: case '\b': ! 380: if (--xt->col < 0) ! 381: xt->col = 0; ! 382: break; ! 383: default: ! 384: ++xt->col; ! 385: break; ! 386: } ! 387: *ocanb->wptr++ = c; ! 388: if (d) ! 389: break; ! 390: } ! 391: (qp->qinfo->putp)(qp, ocanb); ! 392: if (d) ! 393: putctl1d(qp, M_DELAY, d); ! 394: } ! 395: freeb(bp); ! 396: return 1; ! 397: } ! 398: ! 399: static ! 400: wsrv(qp) ! 401: register struct queue *qp; ! 402: { ! 403: register struct xttyld *xt; ! 404: register struct block *bp; ! 405: ! 406: xt = (struct xttyld *) qp->ptr; ! 407: while ((qp->next->flag & QFULL) == 0 && (bp = getq(qp))) { ! 408: if (xt->status & XTTY_STOPPED && bp->type == M_DATA) { ! 409: putbq(qp, bp); ! 410: qp->flag |= QFULL; ! 411: return; ! 412: } ! 413: if (!(xt->sg.sg_flags & RAW) ! 414: && (xt->sg.sg_flags & (ALLDELAY | CRMOD)) ! 415: && bp->type == M_DATA) { ! 416: if (!ocanon(xt, bp, qp->next)) { ! 417: putbq(qp, bp); ! 418: qp->next->flag |= QWANTW; ! 419: return; ! 420: } ! 421: } else if (bp->type == M_IOCTL) ! 422: ctl(qp, bp); ! 423: else ! 424: (*qp->next->qinfo->putp)(qp->next, bp); ! 425: } ! 426: if (qp->count) ! 427: qp->next->flag |= QWANTW; ! 428: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.