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