|
|
1.1 root 1: #include "sys/param.h"
2: #include "sys/stream.h"
3: #include "sys/ttyio.h"
4: #include "sys/nttyio.h"
5: #include "sys/ttyld.h"
6: #include "sys/nttyld.h"
7: #include "sys/conf.h"
8: #include "sys/file.h"
9:
10: extern char maptab[], /* see dev/ttyld.c */
11: partab[]; /* see sys/partab.c */
12:
13:
14: extern struct nttyld ntty[];
15: extern int nttycnt;
16:
17: int ntclose(), /* queue close routine */
18: ntin(), /* reader queue put routine */
19: ntinsrv(), /* reader queue service routine */
20: ntout(), /* writer queue put routine */
21: ntoutsrv(); /* writer queue service routine */
22: long ntopen(); /* queue open routine */
23:
24: static struct qinit rinit = { ntin, ntinsrv, ntopen, ntclose, 300, 0 },
25: winit = { ntout, ntoutsrv, ntopen, ntclose, 300, 200 };
26: struct streamtab nttystream = { &rinit, &winit };
27:
28: #define CANBSIZ 256 /* why not NT_NIN? */
29:
30: /*
31: * Backspace over "n" characters, perhaps erasing them.
32: * Called from ntrubout().
33: */
34:
35: ntbs (nt, n)
36: register struct nttyld *nt;
37: register int n;
38: {
39: while (--n >= 0)
40: if (putd (putq, nt->nt_outq, '\b')) {
41: nt->nt_state |= NT_ECHO;
42: if (nt->nt_local & LCRTERA) {
43: (void) putd (putq, nt->nt_outq, ' ');
44: (void) putd (putq, nt->nt_outq, '\b');
45: }
46: }
47: return;
48: }
49:
50:
51: /*
52: * Set default control characters.
53: * Called by ntopen().
54: */
55:
56: ntchars (nt)
57: register struct nttyld *nt;
58: {
59: static struct tchars tchars = { CINTR, CQUIT, CSTART, CSTOP, CEOT,
60: 0377 };
61: static struct ltchars ltchars = { CSUSP, CDSUSP, CRPRNT, CFLUSH,
62: CWERAS, CLNEXT };
63:
64: nt->nt_erase = CERASE;
65: nt->nt_kill = CKILL;
66: nt->nt_tchr = tchars;
67: nt->nt_ltchr = ltchars;
68: return;
69: }
70:
71:
72: ntclose (q)
73: register struct queue *q;
74: {
75: register struct nttyld *nt = (struct nttyld *) q->ptr;
76:
77: nt->nt_state = 0;
78: return;
79: }
80:
81:
82: /*
83: * Put input buffer on read queue followed by a delimiter.
84: * Called from ntinc() when a line break character is read,
85: * and from ntioctl() when switching from cooked to raw or cbreak mode.
86: */
87:
88: ntcooked (nt)
89: register struct nttyld *nt;
90: {
91: register char *s, *t;
92: register struct block *b;
93: register struct queue *q = RD (nt->nt_outq);
94:
95: if (!(q->flag & QFULL) && (b = allocb (1))) {
96: for (t = (s = nt->nt_in) + nt->nt_nin; s < t; s++)
97: (void) putd (putq, q, *s);
98: b->class |= S_DELIM;
99: putq (q, b);
100: nt->nt_delct++;
101: }
102: qenable (q);
103: nt->nt_nin = 0;
104: nt->nt_trash = 0;
105: return;
106: }
107:
108:
109: /*
110: * Echo a typed character to a terminal.
111: */
112:
113: ntecho (c, nt)
114: register int c;
115: register struct nttyld *nt;
116: {
117: register struct queue *echoq = nt->nt_outq;
118:
119: nt->nt_local &= ~LFLUSHO;
120: if (!(nt->nt_flags & ECHO) || echoq->flag & QFULL)
121: return;
122: c &= 0377;
123: if (nt->nt_flags & RAW)
124: goto out;
125: if (c == '\r' && nt->nt_flags & CRMOD)
126: c = '\n';
127: if (c != '\n' && c != '\t' && nt->nt_local & LCTLECH)
128: if ((c &= 0177) <= 037 || c == 0177) {
129: (void) putd (putq, echoq, '^');
130: if (c == 0177)
131: c = '?';
132: else if (nt->nt_flags & LCASE)
133: c += 'a' - 1;
134: else c += 'A' - 1;
135: goto out;
136: }
137:
138: if ((c &= 0177) == CEOT) /* terminals don't like it */
139: return;
140:
141: out:
142: if (putd (putq, echoq, c))
143: nt->nt_state |= NT_ECHO;
144: return;
145: }
146:
147:
148: /*
149: * Flush all input and/or all output tty queues.
150: */
151:
152: ntflush (nt, rw)
153: struct nttyld *nt;
154: int rw;
155: {
156: struct queue *wrq = nt->nt_outq,
157: *rdq = RD (wrq);
158:
159: if (rw & FREAD) {
160: flushq (rdq, 0);
161: (void) putctl (rdq->next, M_FLUSH);
162: nt->nt_delct = 0;
163: nt->nt_nin = 0;
164: nt->nt_trash = 0;
165: nt->nt_lstate = 0;
166: }
167: if (rw & FWRITE) {
168: flushq (wrq, 0);
169: (void) putctl (wrq->next, M_FLUSH);
170: }
171: return;
172: }
173:
174:
175: /*
176: * Reader queue (input from tty) put routine.
177: */
178:
179: ntin (q, b)
180: struct queue *q;
181: register struct block *b;
182: {
183: register struct nttyld *nt = (struct nttyld *) q->ptr;
184:
185: switch (b->type) {
186: case M_DATA:
187: if (nt->nt_flags & RAW && !(nt->nt_flags & ECHO))
188: break;
189: nt->nt_state &= ~NT_ECHO;
190: while (b->rptr < b->wptr)
191: ntinc ((int) *b->rptr++, nt);
192: freeb (b);
193: if (nt->nt_state & NT_ECHO && nt->nt_outq->next->flag & QDELIM)
194: (void) qpctld (nt->nt_outq, M_DATA);
195: return;
196: case M_BREAK:
197: if (nt->nt_flags & RAW) { /* speed-change hack */
198: b->type = M_DATA;
199: if (b->wptr < b->lim)
200: *b->wptr++ = '\0';
201: break;
202: }
203: (void) putctl1 (q->next, M_SIGNAL, SIGINT);
204: ntflush (nt, FREAD | FWRITE);
205: freeb (b);
206: return;
207: case M_HANGUP:
208: (*q->next->qinfo->putp)(q->next, b);
209: return;
210: }
211:
212: if (q->next->flag & QFULL)
213: freeb (b);
214: else (*q->next->qinfo->putp)(q->next, b);
215: return;
216: }
217:
218:
219: /*
220: * Process a single input character.
221: * Called (at interrupt level) by ntin().
222: */
223:
224: ntinc (c, nt)
225: register c;
226: register struct nttyld *nt;
227: {
228: register int t_flags;
229:
230: c &= 0377;
231: t_flags = nt->nt_flags;
232:
233: if (t_flags & RAW) {
234: if (!(nt->nt_readq->next->flag & QFULL))
235: if (putd (nt->nt_readq->next->qinfo->putp, nt->nt_readq->next, c))
236: ntecho (c, nt);
237: return;
238: }
239:
240: if (!(nt->nt_lstate & LSTYPEN))
241: c &= 0177;
242:
243: /*
244: * Interpret literal-next-character control character (^V).
245: */
246: if (nt->nt_lstate & LSLNCH) {
247: c |= 0200;
248: nt->nt_lstate &= ~LSLNCH;
249: }
250: if (c == nt->nt_lnextc) {
251: nt->nt_lstate |= LSLNCH;
252: if (nt->nt_flags & ECHO)
253: if (putd (putq, nt->nt_outq, '^')) {
254: nt->nt_state |= NT_ECHO;
255: (void) putd (putq, nt->nt_outq, '\b');
256: }
257: return;
258: }
259:
260: if (ntstst (c, nt) || /* start, stop */
261: ntoflush (c, nt) || /* flush output */
262: ntsigc (c, nt)) /* interrupt/quit/stop */
263: return;
264:
265: if (c == '\r' && t_flags & CRMOD)
266: c = '\n';
267: if (t_flags & LCASE && c >= 'A' && c <= 'Z')
268: c += 'a' - 'A';
269:
270: if (t_flags & CBREAK) {
271: if (nt->nt_readq->next->flag & QFULL) {
272: if (putd (putq, nt->nt_outq, CTRL('g')))
273: nt->nt_state |= NT_ECHO;
274: }
275: #ifdef notdef
276: else if (c == nt->nt_dsuspc)
277: (void) putctl1 (nt->nt_readq->next, M_SSIGNAL, SIGTSTP);
278: #endif
279: else if (putd (nt->nt_readq->next->qinfo->putp, nt->nt_readq->next, c&0177))
280: ntecho (c, nt);
281: return;
282: }
283:
284: if (nt->nt_lstate & LSQUOT) {
285: nt->nt_lstate &= ~LSQUOT;
286: if (c == nt->nt_erase || c == nt->nt_kill) {
287: c |= 0200;
288: ntrubout (nt);
289: }
290: }
291: if (c == '\\')
292: nt->nt_lstate |= LSQUOT;
293:
294: if (c == nt->nt_erase)
295: ntrubout (nt); /* erase character */
296: else if (c == nt->nt_kill)
297: ntkill (nt); /* erase line */
298: else if (c == nt->nt_werasc)
299: ntwerase (nt); /* erase word */
300: else if (c == nt->nt_rprntc)
301: ntreprint (nt); /* reprint line */
302: else {
303: if (nt->nt_nin < NT_NIN) {
304: if (nt->nt_nin == 0)
305: nt->nt_rocol = nt->nt_col;
306: nt->nt_in[nt->nt_nin++] = c;
307: }
308: else {
309: if (putd (putq, nt->nt_outq, CTRL('g')))
310: nt->nt_state |= NT_ECHO;
311: return;
312: }
313:
314: if (c == '\n' || c == nt->nt_eofc || c == nt->nt_brkc ||
315: c == '\r' && (nt->nt_flags & CRMOD))
316: ntcooked (nt);
317:
318: if (nt->nt_lstate & LSERASE) {
319: nt->nt_lstate &= ~LSERASE;
320: if (putd (putq, nt->nt_outq, '/'))
321: nt->nt_state |= NT_ECHO;
322: }
323:
324: ntecho (c, nt);
325: if (c == nt->nt_eofc && nt->nt_flags & ECHO &&
326: nt->nt_local & LCTLECH)
327: if (putd (putq, nt->nt_outq, '\b')) {
328: nt->nt_state |= NT_ECHO;
329: (void) putd (putq, nt->nt_outq, '\b');
330: }
331: }
332: return;
333: }
334:
335:
336: /*
337: * Reader queue (tty input) service routine.
338: * Only cooked mode data and delimiters come through here, via ntcooked().
339: */
340:
341: ntinsrv (q)
342: register struct queue *q;
343: {
344: register struct nttyld *nt;
345: register struct block *b;
346: register char *op;
347: register int c;
348: static char canonb[CANBSIZ];
349:
350: if (q->next->flag & QFULL)
351: return;
352: nt = (struct nttyld *) q->ptr;
353: op = canonb;
354: while (nt->nt_delct) {
355: b = getq(q);
356: if (b == NULL) {
357: if (op > canonb)
358: putcpy (q->next, canonb, op - canonb);
359: return;
360: }
361: while (b->rptr < b->wptr) {
362: c = *b->rptr++;
363: if (c & 0200) { /* escaped */
364: c &= 0177;
365: if (nt->nt_flags & LCASE && maptab[c])
366: c = maptab[c];
367: else if (c != nt->nt_erase &&
368: c != nt->nt_kill && c != nt->nt_eofc)
369: *op++ = '\\';
370: }
371: else {
372: #ifdef notdef
373: /*
374: * Interpret delayed stop process
375: * control character (^Y).
376: */
377: if (c == nt->nt_dsuspc) {
378: putcpy (q->next, canonb, op - canonb);
379: op = canonb;
380: (void) putctl1 (q->next, M_SSIGNAL,
381: SIGTSTP);
382: continue;
383: }
384: #endif
385: if (c == nt->nt_eofc)
386: continue;
387: }
388: *op++ = c;
389: if (op >= &canonb[CANBSIZ-1]) {
390: putcpy (q->next, canonb, op - canonb);
391: op = canonb;
392: }
393: }
394: if ((b->class & S_DELIM) == 0)
395: freeb(b);
396: else { /* end of line */
397: if (op > canonb)
398: putcpy(q->next, canonb, op - canonb);
399: (*q->next->qinfo->putp)(q->next, b); /* empty S_DELIM */
400: nt->nt_delct--;
401: op = canonb;
402: }
403: }
404:
405: return;
406: }
407:
408:
409: /*
410: * Acknowledge ioctl message.
411: * Called by ntioctl().
412: */
413:
414: ntiocack (q, b, n)
415: register struct queue *q;
416: register struct block *b;
417: register int n;
418: {
419: if (n > 0)
420: n += sizeof (int); /* for ioctl command */
421: b->wptr = b->rptr + n;
422: b->type = M_IOCACK;
423: qreply (q, b);
424: return;
425: }
426:
427:
428: /*
429: * Terminal I/O control operations.
430: * Called by ntoutsrv().
431: */
432:
433: ntioctl (q, b)
434: register struct queue *q;
435: register struct block *b;
436: {
437: register struct nttyld *nt = (struct nttyld *) q->ptr;
438: register struct ntioc *ioc = (struct ntioc *) b->rptr;
439: int s;
440:
441: switch (ioc->command) {
442:
443: /*
444: * Set new parameters
445: */
446: case TIOCSETP:
447: case TIOCSETN:
448: s = spl6();
449: if (ioc->arg.sg.sg_flags & (RAW|CBREAK) &&
450: !(nt->nt_flags & (RAW|CBREAK))) {
451: /*
452: * Before leaving cooked mode, push through
453: * any characters that made it to ntin().
454: */
455: if (nt->nt_nin > 0)
456: ntcooked (nt);
457: ntinsrv (RD (nt->nt_outq));
458: }
459: nt->nt_erase = ioc->arg.sg.sg_erase;
460: nt->nt_kill = ioc->arg.sg.sg_kill;
461: nt->nt_flags = ioc->arg.sg.sg_flags;
462: nt->nt_readq->flag &= ~QDELIM;
463: if ((nt->nt_flags & (RAW|CBREAK))==0)
464: nt->nt_readq->flag |= QDELIM;
465: splx (s);
466:
467: ntiocack (q, b, 0);
468: break;
469:
470: /*
471: * Send current parameters to user
472: */
473: case TIOCGETP:
474: ioc->arg.sg.sg_erase = nt->nt_erase;
475: ioc->arg.sg.sg_kill = nt->nt_kill;
476: ioc->arg.sg.sg_flags = nt->nt_flags;
477: ioc->arg.sg.sg_ispeed =
478: ioc->arg.sg.sg_ospeed = B9600;
479:
480: b->wptr = b->rptr + sizeof (int) + sizeof (struct sgttyb);
481: b->wptr = 2 + b->rptr + sizeof (int) + sizeof (struct sgttyb);
482: ntiocack (q, b, sizeof (struct sgttyb));
483: break;
484:
485: /*
486: * Set/get special characters
487: */
488: case TIOCSETC:
489: nt->nt_tchr = ioc->arg.tchr;
490: ntiocack (q, b, 0);
491: break;
492:
493: case TIOCGETC:
494: ioc->arg.tchr = nt->nt_tchr;
495: ntiocack (q, b, sizeof (struct tchars));
496: break;
497:
498: /*
499: * Set/get local special characters.
500: */
501: case TIOCSLTC:
502: nt->nt_ltchr = ioc->arg.ltchr;
503: ntiocack (q, b, 0);
504: break;
505:
506: case TIOCGLTC:
507: ioc->arg.ltchr = nt->nt_ltchr;
508: ntiocack (q, b, sizeof (struct ltchars));
509: break;
510:
511: /*
512: * Modify local mode word.
513: */
514: case TIOCLBIS:
515: nt->nt_local |= ioc->arg.local;
516: ntiocack (q, b, 0);
517: break;
518:
519: case TIOCLBIC:
520: nt->nt_local &= ~ioc->arg.local;
521: ntiocack (q, b, 0);
522: break;
523:
524: case TIOCLSET:
525: nt->nt_local = ioc->arg.local;
526: ntiocack (q, b, 0);
527: break;
528:
529: case TIOCLGET:
530: ioc->arg.local = nt->nt_local;
531: ntiocack (q, b, sizeof (short));
532: break;
533:
534: /*
535: * Return number of characters in the output.
536: */
537: case TIOCOUTQ:
538:
539: default:
540: (*q->next->qinfo->putp)(q->next, b);
541: break;
542: }
543:
544: return;
545: }
546:
547:
548: /*
549: * Erase entire input buffer.
550: * Called by ntinc().
551: */
552:
553: ntkill (nt)
554: register struct nttyld *nt;
555: {
556: if (nt->nt_local & LCRTKIL && !nt->nt_trash) {
557: while (nt->nt_nin > 0)
558: ntrubout (nt);
559: }
560: else {
561: ntecho (nt->nt_kill, nt);
562: ntecho ('\n', nt);
563: nt->nt_nin = 0;
564: nt->nt_trash = 0;
565: }
566: nt->nt_lstate = 0;
567: return;
568: }
569:
570:
571: /*
572: * Interpret the flush-output (^O) control character.
573: * Called by ntinc().
574: */
575:
576: int
577: ntoflush (c, nt)
578: register int c;
579: register struct nttyld *nt;
580: {
581: if (nt->nt_local & LFLUSHO) {
582: nt->nt_local &= ~LFLUSHO;
583: if (c == nt->nt_flushc)
584: return (1);
585: }
586: else if (c == nt->nt_flushc) {
587: ntflush (nt, FWRITE);
588: ntecho (c, nt);
589: ntreprint (nt);
590: nt->nt_local |= LFLUSHO;
591: return (1);
592: }
593:
594: return (0);
595: }
596:
597:
598: /*ARGSUSED*/
599:
600: long
601: ntopen (q, dev)
602: register struct queue *q;
603: int dev;
604: {
605: register struct nttyld *nt;
606:
607: if (q->ptr)
608: return (1); /* already attached */
609:
610: for (nt = ntty; nt->nt_state & NT_USE; nt++)
611: if (nt >= &ntty[nttycnt-1])
612: return (0);
613:
614: WR (q)->ptr = q->ptr = (caddr_t) nt;
615: nt->nt_outq = WR (q);
616: nt->nt_readq = q;
617: nt->nt_nin = 0;
618: nt->nt_state = NT_USE;
619: nt->nt_flags = ECHO | CRMOD;
620: nt->nt_col = 0;
621: nt->nt_delct = 0;
622: ntchars (nt); /* set default control characters */
623: nt->nt_trash = 0;
624: nt->nt_local = 0;
625: nt->nt_lstate = 0;
626: q->flag |= QDELIM;
627: return (1);
628: }
629:
630:
631: /*
632: * Writer queue (output to tty) put routine.
633: */
634:
635: ntout (wrq, b)
636: register struct queue *wrq;
637: register struct block *b;
638: {
639: if (b->type == M_DATA)
640: b->type = M_CTL; /* see ntoutsrv() */
641: putq (wrq, b);
642: return;
643: }
644:
645:
646: /*
647: * Output a block of data to a terminal.
648: * Handle tab expansion, case conversion, turning CR to CRLF, delays, etc.
649: * Called from ntoutsrv().
650: */
651:
652: ntoutb (nt, ib)
653: register struct nttyld *nt;
654: register struct block *ib;
655: {
656: register struct block *ob = 0;
657: register struct queue *q = nt->nt_outq;
658: register int c, delay, ctype;
659: char *colp;
660:
661: while (ib->rptr < ib->wptr) {
662: if (!ob || ob->wptr >= ob->lim) {
663: if (ob) {
664: if (nt->nt_local & LFLUSHO)
665: break;
666: (*q->next->qinfo->putp)(q->next, ob);
667: }
668: if (q->next->flag & QFULL || !(ob = allocb (QBSIZE))) {
669: putbq (q, ib);
670: return;
671: }
672: }
673:
674: switch (c = *ib->rptr++ & 0177) {
675: case '\t':
676: if ((nt->nt_flags & TBDELAY) != XTABS)
677: break;
678:
679: /*
680: * Expand tabs to spaces.
681: */
682: for (;;) {
683: *ob->wptr++ = ' ';
684: nt->nt_col++;
685: if ((nt->nt_col & 07) == 0) /* every 8 */
686: break;
687: if (ob->wptr >= ob->lim) {
688: ib->rptr--;
689: break;
690: }
691: }
692: continue;
693: case '\n':
694: if (!(nt->nt_flags & CRMOD))
695: break;
696:
697: /*
698: * Turn <nl> to <cr><lf>.
699: */
700: if (nt->nt_state & NT_CR)
701: nt->nt_state &= ~NT_CR;
702: else {
703: nt->nt_state |= NT_CR;
704: c = '\r';
705: ib->rptr--;
706: }
707: break;
708: case '~':
709: if (nt->nt_local & LTILDE)
710: c = '`';
711: /* no break */
712: default:
713: if (!(nt->nt_flags & LCASE))
714: break;
715:
716: /*
717: * Generate escapes for upper-case-only terminals.
718: */
719: if (nt->nt_state & NT_CASE) {
720: nt->nt_state &= ~NT_CASE;
721: break;
722: }
723:
724: for (colp = "{(})|!~^`'"; *colp && c != *colp;
725: colp += 2);
726:
727: if (*colp || c >= 'A' && c <= 'Z') {
728: *--ib->rptr = *colp ? colp[1] : c;
729: nt->nt_state |= NT_CASE;
730: c = '\\';
731: }
732: else if (c >= 'a' && c <= 'z')
733: c += 'A' - 'a';
734: break;
735: }
736:
737: /*
738: * Store character.
739: */
740: *ob->wptr++ = c;
741:
742: /*
743: * Calculate delays and column movement.
744: * The delay values are in clock ticks and aren't
745: * necessarily optimal for all terminals.
746: */
747: delay = 0;
748:
749: switch (ctype = partab[c] & 077) {
750: case ORDINARY:
751: nt->nt_col++;
752: break;
753: case CONTROL:
754: break;
755: case BACKSPACE:
756: if (nt->nt_col)
757: nt->nt_col--;
758: break;
759: case NEWLINE:
760: ctype = (nt->nt_flags >> 8) & 03;
761: if (ctype == 1) { /* tty 37 */
762: if (nt->nt_col)
763: if ((delay = nt->nt_col >> 4) < 6)
764: delay = 6;
765: }
766: else if (ctype == 2) /* vt05 */
767: delay = 6;
768: if (!(nt->nt_flags & CRMOD))
769: nt->nt_col = 0;
770: break;
771: case TAB:
772: ctype = (nt->nt_flags >> 10) & 03;
773: if (ctype == 1) /* tty 37 */
774: if ((delay = 1 - (nt->nt_col | ~07)) < 5)
775: delay = 0;
776: nt->nt_col |= 07;
777: nt->nt_col++;
778: break;
779: case VTAB:
780: if (nt->nt_flags & VTDELAY)
781: delay = 127;
782: break;
783: case RETURN:
784: ctype = (nt->nt_flags >> 12) & 03;
785: if (ctype == 1) /* tn 300 */
786: delay = 5;
787: else if (ctype == 2) /* ti 700 */
788: delay = 10;
789: else if (ctype == 3) /* concept 100 */
790: if ((delay = 9 - nt->nt_col) < 0)
791: delay = 0;
792: nt->nt_col = 0;
793: break;
794: }
795:
796: if (delay) {
797: if (nt->nt_local & LFLUSHO)
798: break;
799: (*q->next->qinfo->putp)(q->next, ob);
800: if (ob = allocb(1)) {
801: ob->type = M_DELAY;
802: *ob->wptr++ = delay;
803: (*q->next->qinfo->putp)(q->next, ob);
804: }
805: ob = 0;
806: }
807: }
808:
809: if (ib->class & S_DELIM) {
810: if (ob == NULL)
811: ob = allocb(0);
812: if (ob)
813: ob->class |= S_DELIM;
814: }
815: freeb(ib);
816: if (ob) {
817: if (nt->nt_local & LFLUSHO)
818: freeb(ob);
819: else
820: (*q->next->qinfo->putp)(q->next, ob);
821: }
822: }
823:
824:
825: /*
826: * Writer queue (tty output) service routine.
827: * All tty output comes through here. Upstream data comes in M_CTL
828: * blocks via ntout(); echoed data comes in M_DATA blocks.
829: */
830:
831: ntoutsrv (q)
832: register struct queue *q;
833: {
834: register struct nttyld *nt = (struct nttyld *) q->ptr;
835: register struct block *b;
836:
837: while (b = getq (q))
838: switch (b->type) {
839: default:
840: freeb (b);
841: continue;
842: case M_BREAK:
843: if (q->next->flag & QFULL) {
844: putbq (q, b);
845: return;
846: }
847: (*q->next->qinfo->putp)(q->next, b);
848: continue;
849: case M_IOCTL:
850: if (q->next->flag & QFULL) {
851: putbq (q, b);
852: return;
853: }
854: ntioctl (q, b);
855: continue;
856: case M_FLUSH:
857: flushq (q, 0);
858: /* no break */
859: case M_IOCNAK:
860: case M_IOCACK:
861: (*q->next->qinfo->putp)(q->next, b);
862: continue;
863: case M_CTL:
864: case M_DATA:
865: if (nt->nt_local & LFLUSHO) {
866: freeb (b);
867: continue;
868: }
869: if (q->next->flag & QFULL) {
870: putbq (q, b);
871: return;
872: }
873: if (b->type == M_CTL) {
874: b->type = M_DATA;
875: nt->nt_trash = nt->nt_nin;
876: }
877: if (nt->nt_flags & RAW || nt->nt_local & LLITOUT) {
878: (*q->next->qinfo->putp)(q->next, b);
879: }
880: else ntoutb (nt, b);
881: continue;
882: }
883:
884: return;
885: }
886:
887:
888: /*
889: * Reprint input buffer.
890: */
891:
892: ntreprint (nt)
893: register struct nttyld *nt;
894: {
895: register char *in;
896: register int nin;
897:
898: if (nt->nt_rprntc != 0377)
899: ntecho ((int) nt->nt_rprntc, nt);
900: (void) putd (putq, nt->nt_outq, '\n');
901: for (in = nt->nt_in, nin = nt->nt_nin; nin > 0; in++, nin--)
902: ntecho (*in, nt);
903: nt->nt_lstate &= ~LSERASE;
904: nt->nt_trash = 0;
905: return;
906: }
907:
908:
909: /*
910: * Rubout the last character of the input buffer.
911: */
912:
913: ntrubout (nt)
914: register struct nttyld *nt;
915: {
916: register int c, cc, col, i;
917:
918: if (nt->nt_nin <= 0)
919: return;
920: c = nt->nt_in[--nt->nt_nin];
921:
922: if (!(nt->nt_flags & ECHO))
923: return;
924:
925: nt->nt_local &= ~LFLUSHO;
926:
927: if (nt->nt_local & LPRTERA) {
928: if (!(nt->nt_lstate & LSERASE)) {
929: (void) putd (putq, nt->nt_outq, '\\');
930: nt->nt_lstate |= LSERASE;
931: }
932: ntecho (c, nt);
933: return;
934: }
935:
936: if (!(nt->nt_local & LCRTBS)) {
937: ntecho (nt->nt_erase, nt);
938: return;
939: }
940:
941: if (nt->nt_trash > nt->nt_nin) {
942: ntreprint (nt);
943: return;
944: }
945:
946: if (c == ('\t'|0200) || c == ('\n'|0200)) {
947: ntbs (nt, 2);
948: return;
949: }
950:
951: switch (partab[c&=0177] & 0177) {
952: case ORDINARY:
953: if (nt->nt_flags&LCASE && c >= 'A' && c <= 'Z')
954: ntbs (nt, 2);
955: else ntbs (nt, 1);
956: break;
957: case TAB:
958: for (col = nt->nt_rocol, i = 0; i < nt->nt_nin; i++) {
959: cc = nt->nt_in[i];
960: if (cc == ('\t'|0200) || cc == ('\n'|0200)) {
961: col += 2;
962: continue;
963: }
964: switch (partab[cc&=0177] & 0177) {
965: case ORDINARY:
966: if (nt->nt_flags&LCASE && cc>='A' && cc<='Z')
967: col += 2;
968: else col++;
969: break;
970: case TAB:
971: col = (col + 8) & ~7;
972: break;
973: default:
974: if (nt->nt_local & LCTLECH)
975: col += 2;
976: break;
977: }
978: }
979: ntbs (nt, 8 - (col & 7));
980: break;
981: default:
982: if (nt->nt_local & LCTLECH)
983: ntbs (nt, 2);
984: break;
985: }
986:
987: return;
988: }
989:
990:
991: /*
992: * Interpret the control characters that cause signals to be generated
993: * immediately: interrupt (^?), quit (^\), stop (^Z).
994: * Called from ntinc().
995: */
996:
997: int
998: ntsigc (c, nt)
999: register c;
1000: register struct nttyld *nt;
1001: {
1002: if (c == nt->nt_intrc) {
1003: ntflush (nt, FREAD | FWRITE);
1004: (void) putctl1 (nt->nt_readq->next, M_SIGNAL, SIGINT);
1005: }
1006: else if (c == nt->nt_quitc) {
1007: ntflush (nt, FREAD | FWRITE);
1008: (void) putctl1 (nt->nt_readq->next, M_SIGNAL, SIGQUIT);
1009: }
1010: else if (c == nt->nt_suspc) {
1011: ntflush (nt, FREAD);
1012: (void) putctl1 (nt->nt_readq->next, M_SIGNAL, SIGTSTP);
1013: }
1014: else return (0);
1015:
1016: ntecho (c, nt);
1017: return (1);
1018: }
1019:
1020:
1021: /*
1022: * Interpret the start (^S) and stop (^Q) control characters.
1023: * Called from ntinc().
1024: */
1025:
1026: int
1027: ntstst (c, nt)
1028: register int c;
1029: register struct nttyld *nt;
1030: {
1031: if (nt->nt_state & NT_STOP) {
1032: if (c == nt->nt_startc ||
1033: !(nt->nt_local & LDECCTQ) &&
1034: (c != nt->nt_stopc || nt->nt_stopc == nt->nt_startc)) {
1035: if (putctl (nt->nt_outq->next, M_START))
1036: nt->nt_state &= ~NT_STOP;
1037: }
1038: }
1039: else if (c == nt->nt_stopc) {
1040: if (putctl (nt->nt_outq->next, M_STOP))
1041: nt->nt_state |= NT_STOP;
1042: }
1043:
1044: return (c == nt->nt_startc || c == nt->nt_stopc);
1045: }
1046:
1047:
1048: /*
1049: * Erase the last word of the input buffer.
1050: * Called from ntinc().
1051: */
1052:
1053: ntwerase (nt)
1054: register struct nttyld *nt;
1055: {
1056: register char *s;
1057:
1058: for (s = nt->nt_in + nt->nt_nin - 1; s >= nt->nt_in; s--)
1059: if (*s == ' ' || *s == '\t')
1060: ntrubout (nt);
1061: else break;
1062:
1063: for (; s >= nt->nt_in; s--)
1064: if (*s == ' ' || *s == '\t')
1065: break;
1066: else ntrubout (nt);
1067:
1068: return;
1069: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.