|
|
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: struct block *canonblock();
34:
35: long ttyopen();
36: int ttyclose(), ttyldin(), ttyinsrv(), ttyosrv();
37: static struct qinit ttrinit = { ttyldin, ttyinsrv, ttyopen, ttyclose, 3*1024, 60};
38: static struct qinit ttwinit = { putq, ttyosrv, ttyopen, ttyclose, 3*1024, 200};
39: struct streamtab ttystream = { &ttrinit, &ttwinit};
40:
41: /*
42: * TTY open
43: */
44: long
45: ttyopen(qp, dev)
46: register struct queue *qp;
47: {
48: register struct ttyld *tp;
49: static struct tchars tchars = {CINTR,CQUIT,CSTART,CSTOP,CEOT,0377};
50:
51: if (qp->ptr) /* already attached */
52: return(1);
53: for (tp = ttyld; tp->t_state&TTUSE; tp++)
54: if (tp >= &ttyld[ttycnt-1])
55: return(0);
56: tp->t_state = TTUSE;
57: tp->t_flags = ECHO|CRMOD;
58: tp->t_delct = 0;
59: tp->t_col = 0;
60: tp->t_erase = CERASE;
61: tp->t_kill = CKILL;
62: tp->t_chr = tchars;
63: qp->ptr = (caddr_t)tp;
64: qp->flag |= QDELIM|QNOENB;
65: WR(qp)->ptr = (caddr_t)tp;
66: return(1);
67: }
68:
69: ttyclose(qp)
70: struct queue *qp;
71: {
72: struct ttyld *tp = (struct ttyld *)qp->ptr;
73:
74: if (tp->t_state & TTSTOP)
75: putctl(WR(qp)->next, M_START); /* what else can we do? */
76: tp->t_state = 0;
77: }
78:
79: /*
80: * Queue put procedure for tty input
81: */
82: ttyldin(q, bp)
83: struct queue *q;
84: register struct block *bp;
85: {
86: register struct ttyld *tp;
87: register c;
88: register struct queue *wrq = WR(q); /* writer side */
89: int escape, flags;
90:
91: tp = (struct ttyld *)q->ptr;
92: flags = tp->t_flags;
93: bp->class &= ~S_DELIM;
94: if (bp->type!=M_DATA) {
95: switch(bp->type) {
96:
97: case M_BREAK:
98: if (tp->t_flags&RAW) { /* speed-change hack*/
99: bp->type = M_DATA;
100: bp->class &= ~S_DELIM;
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->count <= q->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 && q->count==0)
128: (*q->next->qinfo->putp)(q->next, bp);
129: else
130: putq(q, bp);
131: return;
132: }
133: while (bp->rptr<bp->wptr) {
134: c = *bp->rptr++ & 0177;
135: if (tp->t_state&TTSTOP) {
136: if (c!=tp->t_chr.t_stopc
137: || tp->t_chr.t_stopc==tp->t_chr.t_startc) {
138: tp->t_state &= ~TTSTOP;
139: putctl(wrq->next, M_START);
140: }
141: } else {
142: if (c==tp->t_chr.t_stopc) {
143: tp->t_state |= TTSTOP;
144: putctl(wrq->next, M_STOP);
145: }
146: }
147: if (c==tp->t_chr.t_stopc || c==tp->t_chr.t_startc)
148: continue;
149: if (c==tp->t_chr.t_intrc) {
150: ttysig(q, SIGINT);
151: continue;
152: }
153: if (c==tp->t_chr.t_quitc) {
154: ttysig(q, SIGQUIT);
155: continue;
156: }
157: if (c=='\r' && tp->t_flags&CRMOD)
158: c = '\n';
159: if (tp->t_flags&LCASE && c>='A' && c<='Z')
160: c += 'a'-'A';
161: escape = 0;
162: if (tp->t_flags & CBREAK) {
163: if ((q->next->flag&QFULL)==0 && q->count==0)
164: putd(q->next->qinfo->putp, q->next, c);
165: else
166: putd(putq, q, c);
167: } else {
168: if (tp->t_state&TTESC) {
169: escape = 1;
170: c |= 0200;
171: }
172: if (c == '\\')
173: tp->t_state |= TTESC;
174: else {
175: tp->t_state &= ~TTESC;
176: if (c == ('\\'|0200)) {
177: c &= 0177;
178: tp->t_state |= TTESC;
179: }
180: /* ttyhog? */
181: if ((q->flag&QFULL) == 0 || (c=='\n' && tp->t_delct==0))
182: putd(putq, q, c);
183: else
184: c = '\007';
185: }
186: if ((c&0177)=='\n'||c==tp->t_chr.t_eofc
187: ||c==tp->t_chr.t_brkc) {
188: register struct block *bp1;
189: if (bp1 = allocb(1)) {
190: bp1->class |= S_DELIM;
191: tp->t_delct++;
192: putq(q, bp1);
193: }
194: qenable(q);
195: }
196: }
197: if (tp->t_flags&TANDEM && (tp->t_state&TTBLOCK) == 0
198: && q->count >= (q->qinfo->limit+q->qinfo->lolimit)/2 ) {
199: q->next->flag |= QWANTW;
200: tp->t_state |= TTBLOCK;
201: putctl1d(wrq, M_DATA, tp->t_chr.t_stopc);
202: }
203: if (tp->t_flags&ECHO && (wrq->flag&QFULL)==0) {
204: c &= 0177;
205: if(bp->rptr == bp->wptr)
206: putctl1d(wrq, M_DATA, c);
207: else
208: putd(wrq->qinfo->putp, wrq, c);
209: if (c==tp->t_kill && (tp->t_flags&CBREAK)==0
210: && !escape)
211: putctl1d(wrq, M_DATA, '\n');
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, *bp1;
227:
228: tp = (struct ttyld *)q->ptr;
229: if (q->next->flag&QFULL)
230: return;
231: if (tp->t_flags&(CBREAK|RAW)) {
232: while ((q->next->flag&QFULL)==0 && (bp = getq(q)))
233: (*q->next->qinfo->putp)(q->next, bp);
234: } else {
235: while (tp->t_delct && q->first) {
236: bp1 = allocb(CANBSIZ);
237: if (bp1==NULL)
238: return;
239: while (bp = getq(q)) {
240: bp1 = canonblock(q, bp, bp1, tp);
241: if (bp1->class&S_DELIM) {
242: tp->t_delct--;
243: break;
244: }
245: }
246: (*q->next->qinfo->putp)(q->next, bp1);
247: }
248: }
249: if (tp->t_flags&TANDEM && tp->t_state&TTBLOCK
250: && q->count <= q->qinfo->lolimit) {
251: tp->t_state &= ~TTBLOCK;
252: putd(putq, WR(q), tp->t_chr.t_startc);
253: }
254: }
255:
256: /*
257: * canonicalize bp into bp1, noticing delimiter. bp is freed.
258: */
259: struct block *
260: canonblock(q, bp, bp1, tp)
261: register struct queue *q;
262: register struct block *bp, *bp1;
263: register struct ttyld *tp;
264: {
265: register c;
266:
267: while (bp->rptr<bp->wptr) {
268: if (bp1->wptr >= bp1->lim-1) {
269: (*q->next->qinfo->putp)(q->next, bp1);
270: bp1 = allocb(CANBSIZ);
271: }
272: c = *bp->rptr++;
273: if ((c&0200) == 0) { /* not escaped */
274: if (c == tp->t_erase) {
275: if (bp1->wptr > bp1->rptr)
276: bp1->wptr--;
277: continue;
278: }
279: if (c == tp->t_kill) {
280: bp1->wptr = bp1->rptr;
281: continue;
282: }
283: if (c == tp->t_chr.t_eofc)
284: continue;
285: } else {
286: c &= 0177;
287: if (tp->t_flags&LCASE && maptab[c])
288: c = maptab[c];
289: else if (c==tp->t_erase || c==tp->t_kill
290: || c==tp->t_chr.t_eofc)
291: ;
292: else
293: *bp1->wptr++ = '\\';
294: }
295: *bp1->wptr++ = c;
296: }
297: if (bp->class&S_DELIM)
298: bp1->class |= S_DELIM;
299: freeb(bp);
300: return(bp1);
301: }
302:
303: /*
304: * TTY write processing: delays, tabs, CR/NL and the like.
305: */
306: ttyosrv(q)
307: register struct queue *q;
308: {
309: register struct ttyld *tp;
310: register struct block *bp;
311:
312: tp = (struct ttyld *)q->ptr;
313: while (bp = getq(q)) {
314: switch(bp->type) {
315:
316: default:
317: freeb(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: putctl1(q->next, M_DELAY, count);
478: obp = NULL;
479: }
480: }
481: if (obp) {
482: obp->class |= ibp->class&S_DELIM;
483: (*q->next->qinfo->putp)(q->next, obp);
484: } else if (ibp->class&S_DELIM)
485: putctld(q->next, M_DATA);
486: freeb(ibp);
487: }
488:
489: /*
490: * Reader generates a signal and passes it up
491: */
492: ttysig(q, sig)
493: register struct queue *q;
494: {
495: register struct ttyld *tp = (struct ttyld *)q->ptr;
496:
497: flushq(q, 0); /* flush reader */
498: flushq(WR(q), 0);
499: tp->t_state &= ~TTESC;
500: tp->t_delct = 0;
501: putctl(q->next, M_FLUSH);
502: putctl1(q->next, M_SIGNAL, sig);
503: putctl(WR(q)->next, M_FLUSH);
504: }
505:
506: ttldioc(q, bp, rdq, fromdev)
507: register struct block *bp;
508: struct queue *q, *rdq;
509: {
510: register struct ttyld *tp;
511: register struct sgttyb *sp;
512: int s;
513:
514: sp = (struct sgttyb *)stiodata(bp);
515: tp = (struct ttyld *)q->ptr;
516: switch (stiocom(bp)) {
517:
518: /*
519: * Set new parameters
520: */
521: case TIOCSETP:
522: case TIOCSETN:
523: s = spl6();
524: if (sp->sg_flags & (RAW|CBREAK)
525: && (rdq->next->flag&QFULL)==0) {
526: register struct block *bp1;
527: ttyinsrv(rdq);
528: while (bp1 = getq(rdq))
529: (*rdq->next->qinfo->putp)(rdq->next, bp1);
530: }
531: tp->t_erase = sp->sg_erase;
532: tp->t_kill = sp->sg_kill;
533: tp->t_flags = sp->sg_flags;
534: splx(s);
535: bp->type = M_IOCACK;
536: if (tp->t_flags & (RAW|CBREAK))
537: rdq->flag &= ~(QDELIM|QNOENB);
538: else
539: rdq->flag |= QDELIM|QNOENB;
540: if (tp->t_flags & RAW && tp->t_state & TTSTOP) {
541: putctl(q->next, M_START); /* else it is stuck forever */
542: tp->t_state &=~ TTSTOP;
543: }
544: break;
545:
546: /*
547: * Send current parameters to user
548: */
549: case TIOCGETP:
550: sp->sg_erase = tp->t_erase;
551: sp->sg_kill = tp->t_kill;
552: sp->sg_flags = tp->t_flags;
553: sp->sg_ispeed = sp->sg_ospeed = B9600;
554: bp->wptr = bp->rptr+sizeof(struct sgttyb)+STIOCHDR;
555: bp->type = M_IOCACK;
556: break;
557:
558: /*
559: * Set and fetch special characters
560: */
561: case TIOCSETC:
562: tp->t_chr = *(struct tchars *)((struct stioctl *)bp->rptr)->data;
563: bp->wptr = bp->rptr;
564: bp->type = M_IOCACK;
565: break;
566:
567: case TIOCGETC:
568: *(struct tchars *)((struct stioctl *)bp->rptr)->data = tp->t_chr;
569: bp->wptr = bp->rptr+sizeof(struct tchars)+STIOCHDR;
570: bp->type = M_IOCACK;
571: break;
572:
573: default:
574: if (fromdev) {
575: bp->type = M_IOCACK;
576: qreply(rdq, bp); /* reply to device side */
577: } else
578: (*q->next->qinfo->putp)(q->next, bp); /* pass to device */
579: return;
580:
581: }
582: if (fromdev)
583: qreply(rdq, bp); /* to device side */
584: else
585: qreply(q, bp); /* to process side */
586: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.