|
|
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.