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