|
|
1.1 root 1: #include "ntty.h"
2: #if NNTTY > 0
3: #include "../h/param.h"
4: #include "../h/stream.h"
5: #include "../h/ioctl.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: (*q->next->qinfo->putp)(q->next, b); /* send it on down */
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:
482: b->wptr = b->rptr + sizeof (int) + sizeof (struct sgttyb);
483: b->wptr = 2 + b->rptr + sizeof (int) + sizeof (struct sgttyb);
484: (*q->next->qinfo->putp)(q->next, b);
485: break;
486:
487: /*
488: * Set/get special characters
489: */
490: case TIOCSETC:
491: nt->nt_tchr = ioc->arg.tchr;
492: ntiocack (q, b, 0);
493: break;
494:
495: case TIOCGETC:
496: ioc->arg.tchr = nt->nt_tchr;
497: ntiocack (q, b, sizeof (struct tchars));
498: break;
499:
500: /*
501: * Set/get local special characters.
502: */
503: case TIOCSLTC:
504: nt->nt_ltchr = ioc->arg.ltchr;
505: ntiocack (q, b, 0);
506: break;
507:
508: case TIOCGLTC:
509: ioc->arg.ltchr = nt->nt_ltchr;
510: ntiocack (q, b, sizeof (struct ltchars));
511: break;
512:
513: /*
514: * Modify local mode word.
515: */
516: case TIOCLBIS:
517: nt->nt_local |= ioc->arg.local;
518: ntiocack (q, b, 0);
519: break;
520:
521: case TIOCLBIC:
522: nt->nt_local &= ~ioc->arg.local;
523: ntiocack (q, b, 0);
524: break;
525:
526: case TIOCLSET:
527: nt->nt_local = ioc->arg.local;
528: ntiocack (q, b, 0);
529: break;
530:
531: case TIOCLGET:
532: ioc->arg.local = nt->nt_local;
533: ntiocack (q, b, sizeof (short));
534: break;
535:
536: /*
537: * Return number of characters in the output.
538: */
539: case TIOCOUTQ:
540:
541: default:
542: (*q->next->qinfo->putp)(q->next, b);
543: break;
544: }
545:
546: return;
547: }
548:
549:
550: /*
551: * Erase entire input buffer.
552: * Called by ntinc().
553: */
554:
555: ntkill (nt)
556: register struct nttyld *nt;
557: {
558: if (nt->nt_local & LCRTKIL && !nt->nt_trash) {
559: while (nt->nt_nin > 0)
560: ntrubout (nt);
561: }
562: else {
563: ntecho (nt->nt_kill, nt);
564: ntecho ('\n', nt);
565: nt->nt_nin = 0;
566: nt->nt_trash = 0;
567: }
568: nt->nt_lstate = 0;
569: return;
570: }
571:
572:
573: /*
574: * Interpret the flush-output (^O) control character.
575: * Called by ntinc().
576: */
577:
578: int
579: ntoflush (c, nt)
580: register int c;
581: register struct nttyld *nt;
582: {
583: if (nt->nt_local & LFLUSHO) {
584: nt->nt_local &= ~LFLUSHO;
585: if (c == nt->nt_flushc)
586: return (1);
587: }
588: else if (c == nt->nt_flushc) {
589: ntflush (nt, FWRITE);
590: ntecho (c, nt);
591: ntreprint (nt);
592: nt->nt_local |= LFLUSHO;
593: return (1);
594: }
595:
596: return (0);
597: }
598:
599:
600: /*ARGSUSED*/
601:
602: int
603: ntopen (q, dev)
604: register struct queue *q;
605: int dev;
606: {
607: register struct nttyld *nt;
608:
609: if (q->ptr)
610: return (1); /* already attached */
611:
612: for (nt = ntty; nt->nt_state & NT_USE; nt++)
613: if (nt >= &ntty[NNTTY-1])
614: return (0);
615:
616: WR (q)->ptr = q->ptr = (caddr_t) nt;
617: nt->nt_outq = WR (q);
618: nt->nt_readq = q;
619: nt->nt_nin = 0;
620: nt->nt_state = NT_USE;
621: nt->nt_flags = ECHO | CRMOD;
622: nt->nt_col = 0;
623: nt->nt_delct = 0;
624: ntchars (nt); /* set default control characters */
625: nt->nt_trash = 0;
626: nt->nt_local = 0;
627: nt->nt_lstate = 0;
628: q->flag |= QDELIM;
629: return (1);
630: }
631:
632:
633: /*
634: * Writer queue (output to tty) put routine.
635: */
636:
637: ntout (wrq, b)
638: register struct queue *wrq;
639: register struct block *b;
640: {
641: if (b->type == M_DATA)
642: b->type = M_CTL; /* see ntoutsrv() */
643: putq (wrq, b);
644: return;
645: }
646:
647:
648: /*
649: * Output a block of data to a terminal.
650: * Handle tab expansion, case conversion, turning CR to CRLF, delays, etc.
651: * Called from ntoutsrv().
652: */
653:
654: ntoutb (nt, ib)
655: register struct nttyld *nt;
656: register struct block *ib;
657: {
658: register struct block *ob = 0;
659: register struct queue *q = nt->nt_outq;
660: register int c, delay, ctype;
661: char *colp;
662:
663: while (ib->rptr < ib->wptr) {
664: if (!ob || ob->wptr >= ob->lim) {
665: if (ob) {
666: if (nt->nt_local & LFLUSHO)
667: break;
668: tk_nout += ob->wptr - ob->rptr;
669: (*q->next->qinfo->putp)(q->next, ob);
670: }
671: if (q->next->flag & QFULL || !(ob = allocb (QBSIZE))) {
672: putbq (q, ib);
673: return;
674: }
675: }
676:
677: switch (c = *ib->rptr++ & 0177) {
678: case '\t':
679: if ((nt->nt_flags & TBDELAY) != XTABS)
680: break;
681:
682: /*
683: * Expand tabs to spaces.
684: */
685: for (;;) {
686: *ob->wptr++ = ' ';
687: nt->nt_col++;
688: if ((nt->nt_col & 07) == 0) /* every 8 */
689: break;
690: if (ob->wptr >= ob->lim) {
691: ib->rptr--;
692: break;
693: }
694: }
695: continue;
696: case '\n':
697: if (!(nt->nt_flags & CRMOD))
698: break;
699:
700: /*
701: * Turn <nl> to <cr><lf>.
702: */
703: if (nt->nt_state & NT_CR)
704: nt->nt_state &= ~NT_CR;
705: else {
706: nt->nt_state |= NT_CR;
707: c = '\r';
708: ib->rptr--;
709: }
710: break;
711: case '~':
712: if (nt->nt_local & LTILDE)
713: c = '`';
714: /* no break */
715: default:
716: if (!(nt->nt_flags & LCASE))
717: break;
718:
719: /*
720: * Generate escapes for upper-case-only terminals.
721: */
722: if (nt->nt_state & NT_CASE) {
723: nt->nt_state &= ~NT_CASE;
724: break;
725: }
726:
727: for (colp = "{(})|!~^`'"; *colp && c != *colp;
728: colp += 2);
729:
730: if (*colp || c >= 'A' && c <= 'Z') {
731: *--ib->rptr = *colp ? colp[1] : c;
732: nt->nt_state |= NT_CASE;
733: c = '\\';
734: }
735: else if (c >= 'a' && c <= 'z')
736: c += 'A' - 'a';
737: break;
738: }
739:
740: /*
741: * Store character.
742: */
743: *ob->wptr++ = c;
744:
745: /*
746: * Calculate delays and column movement.
747: * The delay values are in clock ticks and aren't
748: * necessarily optimal for all terminals.
749: */
750: delay = 0;
751:
752: switch (ctype = partab[c] & 077) {
753: case ORDINARY:
754: nt->nt_col++;
755: break;
756: case CONTROL:
757: break;
758: case BACKSPACE:
759: if (nt->nt_col)
760: nt->nt_col--;
761: break;
762: case NEWLINE:
763: ctype = (nt->nt_flags >> 8) & 03;
764: if (ctype == 1) { /* tty 37 */
765: if (nt->nt_col)
766: if ((delay = nt->nt_col >> 4) < 6)
767: delay = 6;
768: }
769: else if (ctype == 2) /* vt05 */
770: delay = 6;
771: if (!(nt->nt_flags & CRMOD))
772: nt->nt_col = 0;
773: break;
774: case TAB:
775: ctype = (nt->nt_flags >> 10) & 03;
776: if (ctype == 1) /* tty 37 */
777: if ((delay = 1 - (nt->nt_col | ~07)) < 5)
778: delay = 0;
779: nt->nt_col |= 07;
780: nt->nt_col++;
781: break;
782: case VTAB:
783: if (nt->nt_flags & VTDELAY)
784: delay = 127;
785: break;
786: case RETURN:
787: ctype = (nt->nt_flags >> 12) & 03;
788: if (ctype == 1) /* tn 300 */
789: delay = 5;
790: else if (ctype == 2) /* ti 700 */
791: delay = 10;
792: else if (ctype == 3) /* concept 100 */
793: if ((delay = 9 - nt->nt_col) < 0)
794: delay = 0;
795: nt->nt_col = 0;
796: break;
797: }
798:
799: if (delay) {
800: if (nt->nt_local & LFLUSHO)
801: break;
802: tk_nout += ob->wptr - ob->rptr;
803: (*q->next->qinfo->putp)(q->next, ob);
804: if (ob = allocb(1)) {
805: ob->type = M_DELAY;
806: *ob->wptr++ = delay;
807: (*q->next->qinfo->putp)(q->next, ob);
808: }
809: ob = 0;
810: }
811: }
812:
813: freeb (ib);
814: if (ob)
815: if (nt->nt_local & LFLUSHO)
816: freeb (ob);
817: else {
818: tk_nout += ob->wptr - ob->rptr;
819: (*q->next->qinfo->putp)(q->next, ob);
820: }
821: return;
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_DELIM:
850: if (!(q->next->flag & QDELIM)) {
851: freeb (b);
852: continue;
853: }
854: if (nt->nt_local & LFLUSHO) {
855: freeb (b);
856: continue;
857: }
858: if (q->next->flag & QFULL) {
859: putbq (q, b);
860: return;
861: }
862: (*q->next->qinfo->putp)(q->next, b);
863: continue;
864: case M_IOCTL:
865: if (q->next->flag & QFULL) {
866: putbq (q, b);
867: return;
868: }
869: ntioctl (q, b);
870: continue;
871: case M_FLUSH:
872: flushq (q, 0);
873: /* no break */
874: case M_IOCNAK:
875: case M_IOCACK:
876: (*q->next->qinfo->putp)(q->next, b);
877: continue;
878: case M_CTL:
879: case M_DATA:
880: if (nt->nt_local & LFLUSHO) {
881: freeb (b);
882: continue;
883: }
884: if (q->next->flag & QFULL) {
885: putbq (q, b);
886: return;
887: }
888: if (b->type == M_CTL) {
889: b->type = M_DATA;
890: nt->nt_trash = nt->nt_nin;
891: }
892: if (nt->nt_flags & RAW || nt->nt_local & LLITOUT) {
893: tk_nout += b->wptr - b->rptr;
894: (*q->next->qinfo->putp)(q->next, b);
895: }
896: else ntoutb (nt, b);
897: continue;
898: }
899:
900: return;
901: }
902:
903:
904: /*
905: * Reprint input buffer.
906: */
907:
908: ntreprint (nt)
909: register struct nttyld *nt;
910: {
911: register char *in;
912: register int nin;
913:
914: if (nt->nt_rprntc != 0377)
915: ntecho ((int) nt->nt_rprntc, nt);
916: (void) putd (putq, nt->nt_outq, '\n');
917: for (in = nt->nt_in, nin = nt->nt_nin; nin > 0; in++, nin--)
918: ntecho (*in, nt);
919: nt->nt_lstate &= ~LSERASE;
920: nt->nt_trash = 0;
921: return;
922: }
923:
924:
925: /*
926: * Rubout the last character of the input buffer.
927: */
928:
929: ntrubout (nt)
930: register struct nttyld *nt;
931: {
932: register int c, cc, col, i;
933:
934: if (nt->nt_nin <= 0)
935: return;
936: c = nt->nt_in[--nt->nt_nin];
937:
938: if (!(nt->nt_flags & ECHO))
939: return;
940:
941: nt->nt_local &= ~LFLUSHO;
942:
943: if (nt->nt_local & LPRTERA) {
944: if (!(nt->nt_lstate & LSERASE)) {
945: (void) putd (putq, nt->nt_outq, '\\');
946: nt->nt_lstate |= LSERASE;
947: }
948: ntecho (c, nt);
949: return;
950: }
951:
952: if (!(nt->nt_local & LCRTBS)) {
953: ntecho (nt->nt_erase, nt);
954: return;
955: }
956:
957: if (nt->nt_trash > nt->nt_nin) {
958: ntreprint (nt);
959: return;
960: }
961:
962: if (c == ('\t'|0200) || c == ('\n'|0200)) {
963: ntbs (nt, 2);
964: return;
965: }
966:
967: switch (partab[c&=0177] & 0177) {
968: case ORDINARY:
969: if (nt->nt_flags&LCASE && c >= 'A' && c <= 'Z')
970: ntbs (nt, 2);
971: else ntbs (nt, 1);
972: break;
973: case TAB:
974: for (col = nt->nt_rocol, i = 0; i < nt->nt_nin; i++) {
975: cc = nt->nt_in[i];
976: if (cc == ('\t'|0200) || cc == ('\n'|0200)) {
977: col += 2;
978: continue;
979: }
980: switch (partab[cc&=0177] & 0177) {
981: case ORDINARY:
982: if (nt->nt_flags&LCASE && cc>='A' && cc<='Z')
983: col += 2;
984: else col++;
985: break;
986: case TAB:
987: col = (col + 8) & ~7;
988: break;
989: default:
990: if (nt->nt_local & LCTLECH)
991: col += 2;
992: break;
993: }
994: }
995: ntbs (nt, 8 - (col & 7));
996: break;
997: default:
998: if (nt->nt_local & LCTLECH)
999: ntbs (nt, 2);
1000: break;
1001: }
1002:
1003: return;
1004: }
1005:
1006:
1007: /*
1008: * Interpret the control characters that cause signals to be generated
1009: * immediately: interrupt (^?), quit (^\), stop (^Z).
1010: * Called from ntinc().
1011: */
1012:
1013: int
1014: ntsigc (c, nt)
1015: register c;
1016: register struct nttyld *nt;
1017: {
1018: if (c == nt->nt_intrc) {
1019: ntflush (nt, FREAD | FWRITE);
1020: (void) putctl1 (nt->nt_readq->next, M_SIGNAL, SIGINT);
1021: }
1022: else if (c == nt->nt_quitc) {
1023: ntflush (nt, FREAD | FWRITE);
1024: (void) putctl1 (nt->nt_readq->next, M_SIGNAL, SIGQUIT);
1025: }
1026: else if (c == nt->nt_suspc) {
1027: ntflush (nt, FREAD);
1028: (void) putctl1 (nt->nt_readq->next, M_SIGNAL, SIGTSTP);
1029: }
1030: else return (0);
1031:
1032: ntecho (c, nt);
1033: return (1);
1034: }
1035:
1036:
1037: /*
1038: * Interpret the start (^S) and stop (^Q) control characters.
1039: * Called from ntinc().
1040: */
1041:
1042: int
1043: ntstst (c, nt)
1044: register int c;
1045: register struct nttyld *nt;
1046: {
1047: if (nt->nt_state & NT_STOP) {
1048: if (c == nt->nt_startc ||
1049: !(nt->nt_local & LDECCTQ) &&
1050: (c != nt->nt_stopc || nt->nt_stopc == nt->nt_startc)) {
1051: if (putctl (nt->nt_outq->next, M_START))
1052: nt->nt_state &= ~NT_STOP;
1053: }
1054: }
1055: else if (c == nt->nt_stopc) {
1056: if (putctl (nt->nt_outq->next, M_STOP))
1057: nt->nt_state |= NT_STOP;
1058: }
1059:
1060: return (c == nt->nt_startc || c == nt->nt_stopc);
1061: }
1062:
1063:
1064: /*
1065: * Erase the last word of the input buffer.
1066: * Called from ntinc().
1067: */
1068:
1069: ntwerase (nt)
1070: register struct nttyld *nt;
1071: {
1072: register char *s;
1073:
1074: for (s = nt->nt_in + nt->nt_nin - 1; s >= nt->nt_in; s--)
1075: if (*s == ' ' || *s == '\t')
1076: ntrubout (nt);
1077: else break;
1078:
1079: for (; s >= nt->nt_in; s--)
1080: if (*s == ' ' || *s == '\t')
1081: break;
1082: else ntrubout (nt);
1083:
1084: return;
1085: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.