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