|
|
1.1 root 1: #include "../h/param.h"
2: #include "../h/stream.h"
3: #include "../h/ioctl.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_stopc
133: || tp->t_chr.t_stopc==tp->t_chr.t_startc) {
134: tp->t_state &= ~TTSTOP;
135: putctl(wrq->next, M_START);
136: }
137: } else {
138: if (c==tp->t_chr.t_stopc) {
139: tp->t_state |= TTSTOP;
140: putctl(wrq->next, M_STOP);
141: }
142: }
143: if (c==tp->t_chr.t_stopc || c==tp->t_chr.t_startc)
144: continue;
145: if (c==tp->t_chr.t_intrc) {
146: ttysig(q, SIGINT);
147: continue;
148: }
149: if (c==tp->t_chr.t_quitc) {
150: ttysig(q, SIGQUIT);
151: continue;
152: }
153: if (c=='\r' && tp->t_flags&CRMOD)
154: c = '\n';
155: if (tp->t_flags&LCASE && c>='A' && c<='Z')
156: c += 'a'-'A';
157: escape = 0;
158: if (tp->t_flags & CBREAK) {
159: if ((q->next->flag&QFULL)==0 && q->count==0)
160: putd(q->next->qinfo->putp, q->next, c);
161: else
162: putd(putq, q, c);
163: } else {
164: if (tp->t_state&TTESC) {
165: escape = 1;
166: c |= 0200;
167: }
168: if (c == '\\')
169: tp->t_state |= TTESC;
170: else {
171: tp->t_state &= ~TTESC;
172: if (c == ('\\'|0200)) {
173: c &= 0177;
174: tp->t_state |= TTESC;
175: }
176: /* ttyhog? */
177: if (q->count<512 || (c=='\n' && tp->t_delct==0))
178: putd(putq, q, c);
179: else
180: c = '\007';
181: }
182: c &= 0177;
183: if (c=='\n'||c==tp->t_chr.t_eofc||c==tp->t_chr.t_brkc) {
184: register struct block *bp1;
185: if (bp1 = allocb(1)) {
186: bp1->type = M_DELIM;
187: putq(q, bp1);
188: tp->t_delct++;
189: }
190: qenable(q);
191: }
192: }
193: if (tp->t_flags&TANDEM && (tp->t_state&TTBLOCK) == 0
194: && q->count >= (q->qinfo->limit+q->qinfo->lolimit)/2 ) {
195: q->next->flag |= QWANTW;
196: tp->t_state |= TTBLOCK;
197: putd(putq, wrq, tp->t_chr.t_stopc);
198: }
199: if (tp->t_flags&ECHO && (wrq->flag&QFULL)==0) {
200: register c1 = c&0177;
201: if (c1!=CEOT) {
202: putd(putq, wrq, c1);
203: if(wrq->next->flag&QDELIM && bp->wptr==bp->rptr)
204: putctl(wrq, M_DELIM);
205: }
206: if (c==tp->t_kill && (tp->t_flags&CBREAK)==0
207: && !escape) {
208: putd(putq, wrq, '\n');
209: if (wrq->next->flag&QDELIM)
210: putctl(wrq, M_DELIM);
211: }
212: }
213: }
214: freeb(bp);
215: }
216:
217: /*
218: * tty input server processing. Erase-kill and escape processing;
219: * gathering into lines.
220: */
221:
222: ttyinsrv(q)
223: register struct queue *q;
224: {
225: register struct ttyld *tp;
226: register struct block *bp;
227: register char *op;
228: register c;
229: static char canonb[CANBSIZ];
230:
231: tp = (struct ttyld *)q->ptr;
232: if (q->next->flag&QFULL)
233: return;
234: if (tp->t_flags&(CBREAK|RAW)) {
235: while ((q->next->flag&QFULL)==0 && (bp = getq(q)))
236: (*q->next->qinfo->putp)(q->next, bp);
237: } else {
238: op = canonb;
239: while (tp->t_delct) {
240: bp = getq(q);
241: if (bp==NULL || bp->type!=M_DATA) {
242: if (op > canonb)
243: putcpy(q->next, canonb, op-canonb);
244: if (bp) {
245: (*q->next->qinfo->putp)(q->next, bp);
246: tp->t_delct--;
247: op = canonb;
248: continue;
249: }
250: return;
251: }
252: while (bp->rptr<bp->wptr) {
253: c = *bp->rptr++;
254: if ((c&0200) == 0) { /* not escaped */
255: if (c == tp->t_erase) {
256: if (op > canonb)
257: op--;
258: continue;
259: }
260: if (c == tp->t_kill) {
261: op = canonb;
262: continue;
263: }
264: if (c == tp->t_chr.t_eofc)
265: continue;
266: } else {
267: c &= 0177;
268: if (tp->t_flags&LCASE && maptab[c])
269: c = maptab[c];
270: else if (c==tp->t_erase || c==tp->t_kill
271: || c==tp->t_chr.t_eofc)
272: ;
273: else
274: *op++ = '\\';
275: }
276: *op++ = c;
277: if (op >= &canonb[CANBSIZ-1]) {
278: putcpy(q->next, canonb, op-canonb);
279: op = canonb;
280: }
281: }
282: freeb(bp);
283: }
284: }
285: if (tp->t_flags&TANDEM && tp->t_state&TTBLOCK
286: && q->count <= q->qinfo->lolimit) {
287: tp->t_state &= ~TTBLOCK;
288: putd(putq, WR(q), tp->t_chr.t_startc);
289: }
290: }
291:
292: /*
293: * TTY write processing: delays, tabs, CR/NL and the like.
294: */
295: ttyosrv(q)
296: register struct queue *q;
297: {
298: register struct ttyld *tp;
299: register struct block *bp;
300:
301: tp = (struct ttyld *)q->ptr;
302: while (bp = getq(q)) {
303: switch(bp->type) {
304:
305: default:
306: freeb(bp);
307: continue;
308:
309: case M_DELIM:
310: if ((q->next->flag & QDELIM) == 0) {
311: freeb(bp);
312: continue;
313: }
314: if (q->next->flag & QFULL) {
315: putbq(q, bp);
316: return;
317: }
318: (*q->next->qinfo->putp)(q->next, bp);
319: continue;
320:
321: case M_IOCTL:
322: if (q->next->flag & QFULL) {
323: putbq(q, bp);
324: return;
325: }
326: ttldioc(q, bp, RD(q), 0);
327: continue;
328:
329: case M_FLUSH:
330: flushq(q, 0);
331: case M_IOCNAK: /* flow through */
332: case M_IOCACK:
333: (*q->next->qinfo->putp)(q->next, bp);
334: continue;
335:
336: case M_DATA:
337: case M_BREAK:
338: if (q->next->flag & QFULL) {
339: putbq(q, bp);
340: return;
341: }
342: if (tp->t_flags&RAW || bp->type==M_BREAK) {
343: (*q->next->qinfo->putp)(q->next, bp);
344: } else
345: outconv(q, bp);
346: continue;
347: }
348: }
349: }
350:
351: outconv(q, ibp)
352: struct queue *q;
353: register struct block *ibp;
354: {
355: register struct ttyld *tp;
356: register struct block *obp = NULL;
357: register c;
358: register count, ctype;
359:
360: tp = (struct ttyld *)q->ptr;
361: more:
362: while (ibp->rptr < ibp->wptr) {
363: if (obp==NULL || obp->wptr >= obp->lim) {
364: if (obp)
365: (*q->next->qinfo->putp)(q->next, obp);
366: if (q->next->flag&QFULL || (obp=allocb(QBSIZE))==NULL) {
367: putbq(q, ibp);
368: return;
369: }
370: }
371: /*
372: * The following dance is an inner loop
373: */
374: count = ibp->wptr - ibp->rptr;
375: if ((c = obp->lim - obp->wptr) < count)
376: count = c;
377: while ((ctype = partab[c = *ibp->rptr++ & 0177] & 077) == 0) {
378: tp->t_col++;
379: *obp->wptr++ = c;
380: if (--count <= 0)
381: goto more;
382: }
383: if (c=='\t' && (tp->t_flags&TBDELAY)==XTABS) {
384: for (;;) {
385: *obp->wptr++ = ' ';
386: tp->t_col++;
387: if ((tp->t_col & 07) == 0) /* every 8 */
388: break;
389: if (obp->wptr >= obp->lim) {
390: ibp->rptr--;
391: break;
392: }
393: }
394: continue;
395: }
396:
397: /*
398: * turn <nl> to <cr><lf> if desired.
399: */
400: if (c=='\n' && tp->t_flags&CRMOD) {
401: if ((tp->t_state&TTCR)==0) {
402: tp->t_state |= TTCR;
403: c = '\r';
404: ctype = partab['\r'] & 077;
405: --ibp->rptr;
406: } else
407: tp->t_state &= ~TTCR;
408: }
409: /*
410: * store character
411: */
412: *obp->wptr++ = c;
413: /*
414: * Calculate delays and column movement
415: */
416: count = 0;
417: switch (ctype) {
418:
419: /* ordinary */
420: case 0:
421: tp->t_col++;
422: break;
423:
424: /* non-printing */
425: case 1:
426: break;
427:
428: /* backspace */
429: case 2:
430: if (tp->t_col)
431: tp->t_col--;
432: break;
433:
434: /* newline */
435: case 3:
436: ctype = (tp->t_flags >> 8) & 03;
437: if(ctype == 1) { /* tty 37 */
438: if (tp->t_col)
439: count = max(((unsigned)tp->t_col>>4) + 3, (unsigned)6);
440: } else if (ctype == 2) /* vt05 */
441: count = 6;
442: if ((tp->t_flags&CRMOD)==0)
443: tp->t_col = 0;
444: break;
445:
446: /* tab */
447: case 4:
448: ctype = (tp->t_flags >> 10) & 03;
449: if(ctype == 1) { /* tty 37 */
450: count = 1 - (tp->t_col | ~07);
451: if (count < 5)
452: count = 0;
453: }
454: tp->t_col |= 07;
455: tp->t_col++;
456: break;
457:
458: /* vertical motion */
459: case 5:
460: if(tp->t_flags & VTDELAY)
461: count = 127;
462: break;
463:
464: /* carriage return */
465: case 6:
466: ctype = (tp->t_flags >> 12) & 03;
467: if (ctype == 1) /* tn 300 */
468: count = 5;
469: else if (ctype == 2) /* ti 700 */
470: count = 10;
471: else if (ctype == 3)
472: count = 20;
473: tp->t_col = 0;
474: break;
475: }
476: if (count) {
477: (*q->next->qinfo->putp)(q->next, obp);
478: if (obp = allocb(1)) {
479: obp->type = M_DELAY;
480: *obp->wptr++ = count;
481: (*q->next->qinfo->putp)(q->next, obp);
482: }
483: obp = NULL;
484: }
485: }
486: if (obp)
487: (*q->next->qinfo->putp)(q->next, obp);
488: freeb(ibp);
489: }
490:
491: /*
492: * Reader generates a signal and passes it up
493: */
494: ttysig(q, sig)
495: register struct queue *q;
496: {
497: register struct ttyld *tp = (struct ttyld *)q->ptr;
498:
499: flushq(q, 0); /* flush reader */
500: flushq(WR(q), 0);
501: tp->t_state &= ~TTESC;
502: tp->t_delct = 0;
503: putctl1(q->next, M_FLUSH);
504: putctl1(q->next, M_SIGNAL, sig);
505: putctl(WR(q)->next, M_FLUSH);
506: }
507:
508: ttldioc(q, bp, rdq, fromdev)
509: register struct block *bp;
510: struct queue *q, *rdq;
511: {
512: register struct ttyld *tp;
513: register union stmsg *sp;
514: register rawcb;
515: int s;
516:
517: sp = (union stmsg *)bp->rptr;
518: tp = (struct ttyld *)q->ptr;
519: switch (sp->ioc0.com) {
520:
521: /*
522: * Set new parameters
523: */
524: case TIOCSETP:
525: case TIOCSETN:
526: s = spl6();
527: if (sp->ioc1.sb.sg_flags & (RAW|CBREAK)
528: && (rdq->next->flag&QFULL)==0) {
529: register struct block *bp1;
530: ttyinsrv(rdq);
531: while (bp1 = getq(rdq))
532: (*rdq->next->qinfo->putp)(rdq->next, bp1);
533: }
534: tp->t_erase = sp->ioc1.sb.sg_erase;
535: tp->t_kill = sp->ioc1.sb.sg_kill;
536: tp->t_flags = sp->ioc1.sb.sg_flags;
537: splx(s);
538: if (fromdev) {
539: bp->type = M_IOCACK;
540: qreply(rdq, bp); /* reply to device side */
541: } else
542: (*q->next->qinfo->putp)(q->next, bp); /* pass to device */
543: if (tp->t_flags & (RAW|CBREAK))
544: rdq->flag &= ~(QDELIM|QNOENB);
545: else
546: rdq->flag |= QDELIM|QNOENB;
547: break;
548:
549: /*
550: * Send current parameters to user
551: */
552: case TIOCGETP:
553: sp->ioc1.sb.sg_erase = tp->t_erase;
554: sp->ioc1.sb.sg_kill = tp->t_kill;
555: sp->ioc1.sb.sg_flags = tp->t_flags;
556: bp->wptr = bp->rptr+sizeof(struct ioc1);
557: if (fromdev) {
558: bp->type = M_IOCACK;
559: qreply(rdq, bp); /* reply to device side */
560: } else
561: (*q->next->qinfo->putp)(q->next, bp); /* pass to device */
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.