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