|
|
1.1 root 1: /* ttynew.c 4.3 11/9/80 */
2:
3: /*
4: * New version of tty driver, supported
5: * as NTTYDISC. Adapted from a tty.c written
6: * by J.E.Kulp of IIASA, Austria (jekulp@mc)
7: */
8: #include "../h/param.h"
9: #include "../h/systm.h"
10: #include "../h/dir.h"
11: #include "../h/user.h"
12: #include "../h/tty.h"
13: #include "../h/proc.h"
14: #include "../h/mx.h"
15: #include "../h/inode.h"
16: #include "../h/file.h"
17: #include "../h/reg.h"
18: #include "../h/conf.h"
19: #include "../h/buf.h"
20: #include "../h/dk.h"
21:
22: char partab[];
23:
24: /*
25: * When running dz's using only SAE (silo alarm) on input
26: * it is necessary to call dzrint() at clock interrupt time.
27: * This is unsafe unless spl5()s in tty code are changed to
28: * spl6()s to block clock interrupts. Note that the dh driver
29: * currently in use works the same way as the dz, even though
30: * we could try to more intelligently manage its silo.
31: * Thus don't take this out if you have no dz's unless you
32: * change clock.c and dhtimer().
33: */
34: #define spl5 spl6
35:
36: /*
37: * Input mapping table-- if an entry is non-zero, when the
38: * corresponding character is typed preceded by "\" the escape
39: * sequence is replaced by the table value. Mostly used for
40: * upper-case only terminals.
41: */
42:
43: char maptab[]; /* see tty.c */
44:
45: /*
46: * shorthand
47: */
48: #define q1 tp->t_rawq
49: #define q2 tp->t_canq
50: #define q3 tp->t_outq
51: #define q4 tp->t_un.t_ctlq
52:
53: #define OBUFSIZ 100
54:
55: /*
56: * routine called on opens while tp->t_line == NTTYDISC
57: * establishes a process group for distribution of
58: * quits and interrupts from the tty.
59: * (actually, pp->p_pgrp can't be 0 when this routine
60: * is called since NTTYDISC is not the default discipline)
61: */
62: ntyopen(dev, tp)
63: dev_t dev;
64: register struct tty *tp;
65: {
66: register struct proc *pp;
67:
68: pp = u.u_procp;
69: tp->t_dev = dev;
70: if(pp->p_pgrp == 0) {
71: u.u_ttyp = tp;
72: u.u_ttyd = dev;
73: if (tp->t_pgrp == 0)
74: tp->t_pgrp = pp->p_pid;
75: pp->p_pgrp = tp->t_pgrp;
76: }
77: tp->t_state &= ~WOPEN;
78: tp->t_state |= ISOPEN;
79: if (tp->t_line != NTTYDISC)
80: wflushtty(tp);
81: }
82:
83: /*
84: * clean tp on last close
85: */
86: ntyclose(tp)
87: register struct tty *tp;
88: {
89:
90: wflushtty(tp);
91: /* let ttyclose do the work if we are really closing */
92: }
93:
94: /*
95: * block transfer input handler.
96: */
97: ntyrend(tp, pb, pe)
98: register struct tty *tp;
99: register char *pb, *pe;
100: {
101: int tandem;
102:
103: tandem = tp->t_flags&TANDEM;
104: if (tp->t_flags&RAW) {
105: (void) b_to_q(pb, pe-pb, &tp->t_rawq);
106: if (tp->t_chan)
107: (void) sdata(tp->t_chan);
108: else
109: wakeup((caddr_t)&tp->t_rawq);
110: } else {
111: tp->t_flags &= ~TANDEM;
112: while (pb < pe)
113: ntyinput(*pb++, tp);
114: tp->t_flags |= tandem;
115: }
116: if (tandem)
117: ttyblock(tp);
118: }
119:
120: /*
121: * reinput pending characters after state switch
122: * call at spl5().
123: */
124: ntypend(tp)
125: register struct tty *tp;
126: {
127: struct clist tq;
128: register c;
129:
130: tp->t_local &= ~LPENDIN;
131: tp->t_lstate |= LSTYPEN;
132: tq = tp->t_rawq;
133: tp->t_rawq.c_cc = 0;
134: tp->t_rawq.c_cf = tp->t_rawq.c_cl = 0;
135: while ((c = getc(&tq)) >= 0)
136: ntyinput(c, tp);
137: tp->t_lstate &= ~LSTYPEN;
138: }
139:
140: /*
141: * Place a character on raw TTY input queue, putting in delimiters
142: * and waking up top half as needed.
143: * Also echo if required.
144: * The arguments are the character and the appropriate
145: * tty structure.
146: */
147: ntyinput(c, tp)
148: register c;
149: register struct tty *tp;
150: {
151: register int t_flags;
152: int i;
153:
154: if (tp->t_local&LPENDIN)
155: ntypend(tp);
156: tk_nin++;
157: c &= 0377;
158: t_flags = tp->t_flags;
159: if (t_flags&TANDEM)
160: ttyblock(tp);
161: if ((t_flags&RAW)==0) {
162: if ((tp->t_lstate&LSTYPEN) == 0)
163: c &= 0177;
164: /* check for literal nexting very first */
165: if (tp->t_lstate&LSLNCH) {
166: c |= 0200;
167: tp->t_lstate &= ~LSLNCH;
168: }
169: if (c==tlun.t_lnextc) {
170: if (tp->t_flags&ECHO)
171: ntyout("^\b", tp);
172: tp->t_lstate |= LSLNCH;
173: /* check for output control functions */
174: } else if (c==tun.t_stopc) {
175: if ((tp->t_state&TTSTOP)==0) {
176: tp->t_state |= TTSTOP;
177: (*cdevsw[major(tp->t_dev)].d_stop)(tp);
178: return;
179: }
180: if (c!=tun.t_startc)
181: return;
182: } else if (c==tun.t_startc)
183: ;
184: /* check for input interrupts (and flushed output) */
185: else if (c==tlun.t_flushc) {
186: if (tp->t_local & LFLUSHO)
187: tp->t_local &= ~LFLUSHO;
188: else {
189: flushtty(tp, FWRITE);
190: ntyecho(c, tp);
191: if (tp->t_rawq.c_cc+tp->t_canq.c_cc)
192: ntyretype(tp);
193: tp->t_local |= LFLUSHO;
194: }
195: ttstart(tp);
196: return;
197: } else if (c==tlun.t_suspc || c==tun.t_intrc ||
198: c==tun.t_quitc) {
199: flushtty(tp, c==tlun.t_suspc ? FREAD : FREAD|FWRITE);
200: ntyecho(c, tp);
201: c = c==tun.t_intrc ? SIGINT :
202: ((c==tun.t_quitc) ? SIGQUIT : SIGTSTP);
203: if (tp->t_chan)
204: scontrol(tp->t_chan, M_SIG, c);
205: else
206: gsignal(tp->t_pgrp, c);
207: /* check for buffer editing functions - cooked mode */
208: } else if ((t_flags&CBREAK) == 0) {
209: if ((tp->t_lstate&LSQUOT) &&
210: (c==tp->t_erase||c==tp->t_kill)) {
211: ntyrub(unputc(&tp->t_rawq), tp);
212: c |= 0200;
213: }
214: if (c==tp->t_erase) {
215: if (tp->t_rawq.c_cc)
216: ntyrub(unputc(&tp->t_rawq), tp);
217: } else if (c==tp->t_kill) {
218: if (tp->t_local&LCRTKIL &&
219: tp->t_rawq.c_cc == tp->t_rocount) {
220: while (tp->t_rawq.c_cc)
221: ntyrub(unputc(&tp->t_rawq), tp);
222: } else {
223: ntyecho(c, tp);
224: ntyecho('\n', tp);
225: while (getc(&tp->t_rawq) > 0)
226: ;
227: tp->t_rocount = 0;
228: }
229: tp->t_lstate = 0;
230: } else if (c==tlun.t_werasc) {
231: if (tp->t_rawq.c_cc == 0)
232: goto out;
233: do {
234: c = unputc(&tp->t_rawq);
235: if (c != ' ' && c != '\t')
236: goto erasenb;
237: ntyrub(c, tp);
238: } while (tp->t_rawq.c_cc);
239: goto out;
240: erasenb:
241: do {
242: ntyrub(c, tp);
243: if (tp->t_rawq.c_cc == 0)
244: goto out;
245: c = unputc(&tp->t_rawq);
246: } while (c != ' ' && c != '\t');
247: (void) putc(c, &tp->t_rawq);
248: } else if (c==tlun.t_rprntc) {
249: ntyretype(tp);
250: /* check for cooked mode input buffer overflow */
251: } else if (tp->t_rawq.c_cc + tp->t_canq.c_cc > TTYHOG) {
252: /* we should start a timeout that flushes the
253: buffer if it stays full - same in CBREAK */
254: if (tp->t_outq.c_cc < TTHIWAT(tp))
255: (void) ntyoutput(CTRL(g), tp);
256: /* put data char in q for user and wakeup if a break char */
257: } else if (putc(c, &tp->t_rawq) >= 0) {
258: if (!ntbreakc(c, tp)) {
259: if (tp->t_rocount++ == 0)
260: tp->t_rocol = tp->t_col;
261: } else {
262: tp->t_rocount = 0;
263: catq(&tp->t_rawq, &tp->t_canq);
264: if (tp->t_chan)
265: (void) sdata(tp->t_chan);
266: else
267: wakeup((caddr_t)&tp->t_rawq);
268: if (tp->t_local&LINTRUP)
269: gsignal(tp->t_pgrp, SIGTINT);
270: }
271: tp->t_lstate &= ~LSQUOT;
272: if (c == '\\')
273: tp->t_lstate |= LSQUOT;
274: if (tp->t_lstate&LSERASE) {
275: tp->t_lstate &= ~LSERASE;
276: (void) ntyoutput('/', tp);
277: }
278: i = tp->t_col;
279: ntyecho(c, tp);
280: if (c==tun.t_eofc && tp->t_flags&ECHO) {
281: i = MIN(2, tp->t_col - i);
282: while (i > 0) {
283: (void) ntyoutput('\b', tp);
284: i--;
285: }
286: }
287: }
288: /* CBREAK mode */
289: } else if (tp->t_rawq.c_cc > TTYHOG) {
290: if (tp->t_outq.c_cc < TTHIWAT(tp))
291: (void) ntyoutput(CTRL(g), tp);
292: } else if (putc(c, &tp->t_rawq) >= 0) {
293: if (tp->t_local&LINTRUP)
294: gsignal(tp->t_pgrp, SIGTINT);
295: if (tp->t_chan)
296: (void) sdata(tp->t_chan);
297: else
298: wakeup((caddr_t)&tp->t_rawq);
299: ntyecho(c, tp);
300: }
301: /* RAW mode */
302: } else if (tp->t_rawq.c_cc > TTYHOG)
303: flushtty(tp, FREAD|FWRITE);
304: else if (putc(c, &tp->t_rawq) >= 0) {
305: if (tp->t_local&LINTRUP)
306: gsignal(tp->t_pgrp, SIGTINT);
307: if (tp->t_chan)
308: (void) sdata(tp->t_chan);
309: else
310: wakeup((caddr_t)&tp->t_rawq);
311: }
312: out:
313: tp->t_state &= ~TTSTOP;
314: tp->t_local &= ~LFLUSHO;
315: ttstart(tp);
316: }
317:
318: /*
319: * put character on TTY output queue, adding delays,
320: * expanding tabs, and handling the CR/NL bit.
321: * It is called both from the top half for output, and from
322: * interrupt level for echoing.
323: * The arguments are the character and the tty structure.
324: * Returns < 0 if putc succeeds, otherwise returns char to resend
325: * Must be recursive.
326: */
327: ntyoutput(c, tp)
328: register c;
329: register struct tty *tp;
330: {
331: register char *colp;
332: register ctype;
333:
334: if (tp->t_flags&RAW || tp->t_local&LLITOUT) {
335: if (tp->t_local&LFLUSHO)
336: return (-1);
337: if (putc(c, &tp->t_outq))
338: return(c);
339: tk_nout++;
340: return (-1);
341: }
342: /*
343: * Ignore EOT in normal mode to avoid hanging up
344: * certain terminals.
345: */
346: c &= 0177;
347: if (c==CEOT && (tp->t_flags&CBREAK)==0)
348: return (-1);
349: /*
350: * Turn tabs to spaces as required
351: */
352: if (c=='\t' && (tp->t_flags&TBDELAY)==XTABS) {
353: register int s;
354:
355: c = 8 - (tp->t_col&7);
356: if ((tp->t_local&LFLUSHO) == 0) {
357: s = spl5(); /* don't interrupt tabs */
358: c -= b_to_q(" ", c, &tp->t_outq);
359: tk_nout += c;
360: splx(s);
361: }
362: tp->t_col += c;
363: return (c ? -1 : '\t');
364: }
365: tk_nout++;
366: /*
367: * for upper-case-only terminals,
368: * generate escapes.
369: */
370: if (tp->t_flags&LCASE) {
371: colp = "({)}!|^~'`";
372: while(*colp++)
373: if(c == *colp++) {
374: if (ntyoutput('\\', tp) >= 0)
375: return (c);
376: c = colp[-2];
377: break;
378: }
379: if ('A'<=c && c<='Z') {
380: if (ntyoutput('\\', tp) >= 0)
381: return (c);
382: } else if ('a'<=c && c<='z')
383: c += 'A' - 'a';
384: }
385: /*
386: * turn <nl> to <cr><lf> if desired.
387: */
388: if (c=='\n' && tp->t_flags&CRMOD)
389: if (ntyoutput('\r', tp) >= 0)
390: return (c);
391: if (c=='~' && tp->t_local<ILDE)
392: c = '`';
393: if ((tp->t_local&LFLUSHO) == 0 && putc(c, &tp->t_outq))
394: return (c);
395: /*
396: * Calculate delays.
397: * The numbers here represent clock ticks
398: * and are not necessarily optimal for all terminals.
399: * The delays are indicated by characters above 0200.
400: * In raw mode there are no delays and the
401: * transmission path is 8 bits wide.
402: */
403: colp = &tp->t_col;
404: ctype = partab[c];
405: c = 0;
406: switch (ctype&077) {
407:
408: case ORDINARY:
409: (*colp)++;
410:
411: case CONTROL:
412: break;
413:
414: case BACKSPACE:
415: if (*colp)
416: (*colp)--;
417: break;
418:
419: case NEWLINE:
420: ctype = (tp->t_flags >> 8) & 03;
421: if(ctype == 1) { /* tty 37 */
422: if (*colp)
423: c = max(((unsigned)*colp>>4) + 3, (unsigned)6);
424: } else
425: if(ctype == 2) { /* vt05 */
426: c = 6;
427: }
428: *colp = 0;
429: break;
430:
431: case TAB:
432: ctype = (tp->t_flags >> 10) & 03;
433: if(ctype == 1) { /* tty 37 */
434: c = 1 - (*colp | ~07);
435: if(c < 5)
436: c = 0;
437: }
438: *colp |= 07;
439: (*colp)++;
440: break;
441:
442: case VTAB:
443: if(tp->t_flags & VTDELAY) /* tty 37 */
444: c = 0177;
445: break;
446:
447: case RETURN:
448: ctype = (tp->t_flags >> 12) & 03;
449: if(ctype == 1) { /* tn 300 */
450: c = 5;
451: } else if(ctype == 2) { /* ti 700 */
452: c = 10;
453: } else if(ctype == 3) { /* concept 100 */
454: int i;
455: if ((i = *colp) >= 0)
456: for (; i<9; i++)
457: (void) putc(0177, &tp->t_outq);
458: }
459: *colp = 0;
460: }
461: if(c && (tp->t_local&LFLUSHO) == 0)
462: (void) putc(c|0200, &tp->t_outq);
463: return (-1);
464: }
465:
466: /*
467: * Called from device's read routine after it has
468: * calculated the tty-structure given as argument.
469: */
470: ntread(tp)
471: register struct tty *tp;
472: {
473: register struct clist *qp;
474: register c, first;
475:
476: if ((tp->t_state&CARR_ON)==0)
477: return(0);
478: loop:
479: (void) spl5();
480: if (tp->t_local&LPENDIN)
481: ntypend(tp);
482: (void) spl0();
483: while (tp == u.u_ttyp && u.u_procp->p_pgrp != tp->t_pgrp) {
484: if (u.u_signal[SIGTTIN] == SIG_IGN ||
485: u.u_signal[SIGTTIN] == SIG_HOLD ||
486: (u.u_procp->p_flag&SDETACH) ||
487: u.u_procp->p_flag&SVFORK)
488: return (0);
489: gsignal(u.u_procp->p_pgrp, SIGTTIN);
490: sleep((caddr_t)&lbolt, TTIPRI);
491: }
492: if (tp->t_flags&RAW) {
493: (void) spl5();
494: if (tp->t_rawq.c_cc <= 0) {
495: if ((tp->t_state&CARR_ON)==0 || tp->t_chan!=NULL) {
496: (void) spl0();
497: return (0);
498: }
499: if (tp->t_local&LINTRUP &&
500: u.u_signal[SIGTINT] != SIG_DFL) {
501: u.u_error = EIO;
502: (void) spl0();
503: return (0);
504: }
505: sleep((caddr_t)&tp->t_rawq, TTIPRI);
506: (void) spl0();
507: goto loop;
508: }
509: (void) spl0();
510: while (tp->t_rawq.c_cc && passc(getc(&tp->t_rawq))>=0)
511: ;
512: return (0);
513: } else {
514: qp = tp->t_flags & CBREAK ? &tp->t_rawq : &tp->t_canq;
515: (void) spl5();
516: if (qp->c_cc <= 0) {
517: if ((tp->t_state&CARR_ON)==0 || tp->t_chan!=NULL) {
518: (void) spl0();
519: return (0);
520: }
521: if (tp->t_local&LINTRUP &&
522: u.u_signal[SIGTINT] != SIG_DFL) {
523: u.u_error = EIO;
524: (void) spl0();
525: return (0);
526: }
527: sleep((caddr_t)&tp->t_rawq, TTIPRI);
528: (void) spl0();
529: goto loop;
530: }
531: (void) spl0();
532: first = 1;
533: while ((c = getc(qp)) >= 0) {
534: if (tp->t_flags&CRMOD && c == '\r')
535: c = '\n';
536: if (tp->t_flags&LCASE && c <= 0177)
537: if (tp->t_lstate&LSBKSL) {
538: if (maptab[c])
539: c = maptab[c];
540: tp->t_lstate &= ~LSBKSL;
541: } else if (c >= 'A' && c <= 'Z')
542: c += 'a' - 'A';
543: else if (c == '\\') {
544: tp->t_lstate |= LSBKSL;
545: continue;
546: }
547: if (c == tlun.t_dsuspc) {
548: gsignal(tp->t_pgrp, SIGTSTP);
549: if (first) {
550: sleep((caddr_t)&lbolt, TTIPRI);
551: goto loop;
552: }
553: break;
554: }
555: if (c == tun.t_eofc && (tp->t_flags&CBREAK)==0)
556: break;
557: if (passc(c & 0177) < 0)
558: break;
559: if ((tp->t_flags&CBREAK)==0 && ntbreakc(c, tp))
560: break;
561: first = 0;
562: }
563: tp->t_lstate &= ~LSBKSL;
564: }
565:
566: if (tp->t_state&TBLOCK && tp->t_rawq.c_cc < TTYHOG/5) {
567: if (putc(tun.t_startc, &tp->t_outq)==0) {
568: tp->t_state &= ~TBLOCK;
569: ttstart(tp);
570: }
571: tp->t_char = 0;
572: }
573:
574: return (tp->t_rawq.c_cc + tp->t_canq.c_cc);
575: }
576:
577: /*
578: * Called from the device's write routine after it has
579: * calculated the tty-structure given as argument.
580: */
581: caddr_t
582: ntwrite(tp)
583: register struct tty *tp;
584: {
585: #ifdef VAX
586: /*
587: * THE POSITIONING OF CP, CC, AND CE ARE CRITICAL
588: * AND MUST NOT BE CHANGED WITHOUT PATCHING
589: * THE 'ASM' INLINES BELOW. WATCH OUT.
590: */
591: #endif
592: register char *cp;
593: register int cc, ce;
594: register i;
595: char obuf[OBUFSIZ];
596: register c;
597: int hiwat = TTHIWAT(tp);
598:
599: if ((tp->t_state&CARR_ON)==0)
600: return (NULL);
601: loop:
602: while (u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp &&
603: (tp->t_local<OSTOP) && (u.u_procp->p_flag&SVFORK)==0 &&
604: u.u_signal[SIGTTOU] != SIG_IGN &&
605: u.u_signal[SIGTTOU] != SIG_HOLD &&
606: (u.u_procp->p_flag&SDETACH)==0) {
607: gsignal(u.u_procp->p_pgrp, SIGTTOU);
608: sleep((caddr_t)&lbolt, TTIPRI);
609: }
610: while (u.u_count) {
611: cc = MIN(u.u_count, OBUFSIZ);
612: cp = obuf;
613: iomove(cp, (unsigned)cc, B_WRITE);
614: if (u.u_error)
615: break;
616: if (tp->t_outq.c_cc > hiwat)
617: goto ovhiwat;
618: if (tp->t_local&LFLUSHO)
619: continue;
620: if (tp->t_flags&LCASE || tp->t_local<ILDE) {
621: while (cc--) {
622: c = *cp++;
623: tp->t_rocount = 0;
624: while((c = ntyoutput(c, tp)) >= 0) {
625: /* out of clists, wait a bit */
626: ttstart(tp);
627: sleep((caddr_t)&lbolt, TTOPRI);
628: tp->t_rocount = 0;
629: }
630: if (tp->t_outq.c_cc > hiwat)
631: goto ovhiwat;
632: }
633: continue;
634: }
635: while (cc) {
636: if (tp->t_flags&RAW || tp->t_local&LLITOUT)
637: ce = cc;
638: else {
639: #ifdef VAX
640: asm(" scanc r9,(r10),_partab,$077");
641: asm(" subl3 r0,r9,r8");
642: #else
643: ce=0;
644: while(((partab[*(unsigned char *)(cp+ce)]&077)==0)&&(ce<cc))
645: ce++;
646: #endif
647: if (ce==0) {
648: tp->t_rocount = 0;
649: if (ntyoutput(*cp, tp) >= 0) {
650: ttstart(tp);
651: sleep((caddr_t)&lbolt, TTOPRI);
652: continue;
653: }
654: cp++;
655: cc--;
656: if (tp->t_outq.c_cc > hiwat)
657: goto ovhiwat;
658: }
659: }
660: tp->t_rocount = 0;
661: i=b_to_q(cp,ce,&tp->t_outq);
662: ce-=i;
663: tk_nout+=ce;
664: tp->t_col+=ce;
665: cp+=ce;
666: cc-=ce;
667: if (i) {
668: ttstart(tp);
669: sleep((caddr_t)&lbolt, TTOPRI);
670: }
671: if (ce || tp->t_outq.c_cc > hiwat)
672: goto ovhiwat;
673: }
674: }
675: ttstart(tp);
676: return(NULL);
677:
678: ovhiwat:
679: (void) spl5();
680: u.u_base -= cc;
681: u.u_offset -= cc;
682: u.u_count += cc;
683: if (tp->t_outq.c_cc <= hiwat) {
684: (void) spl0();
685: goto loop;
686: }
687: ttstart(tp);
688: tp->t_state |= ASLEEP;
689: if (tp->t_chan) {
690: (void) spl0();
691: return ((caddr_t)&tp->t_outq);
692: }
693: sleep((caddr_t)&tp->t_outq, TTOPRI);
694: (void) spl0();
695: goto loop;
696: }
697:
698: /*
699: * Rubout one character from the rawq of tp
700: * as cleanly as possible.
701: */
702: ntyrub(c, tp)
703: register c;
704: register struct tty *tp;
705: {
706: register char *cp;
707: register int savecol;
708: int s;
709: char *nextc();
710:
711: if ((tp->t_flags&ECHO)==0)
712: return;
713: tp->t_local &= ~LFLUSHO;
714: c &= 0377;
715: if (tp->t_local&LCRTBS) {
716: if (tp->t_rocount == 0) {
717: /*
718: * Screwed by ttwrite; retype
719: */
720: ntyretype(tp);
721: return;
722: }
723: if (c==('\t'|0200) || c==('\n'|0200))
724: ntyrubo(tp, 2);
725: else switch(partab[c&=0177] & 0177) {
726:
727: case ORDINARY:
728: if (tp->t_flags&LCASE && c >= 'A' && c <= 'Z')
729: ntyrubo(tp, 2);
730: else
731: ntyrubo(tp, 1);
732: break;
733:
734: case VTAB:
735: case BACKSPACE:
736: case CONTROL:
737: case RETURN:
738: if (tp->t_local & LCTLECH)
739: ntyrubo(tp, 2);
740: break;
741:
742: case TAB:
743: if (tp->t_rocount < tp->t_rawq.c_cc) {
744: ntyretype(tp);
745: return;
746: }
747: s = spl5();
748: savecol = tp->t_col;
749: tp->t_lstate |= LSCNTTB;
750: tp->t_local |= LFLUSHO;
751: tp->t_col = tp->t_rocol;
752: for (cp = tp->t_rawq.c_cf; cp; cp = nextc(&tp->t_rawq, cp))
753: ntyecho(*cp, tp);
754: tp->t_local &= ~LFLUSHO;
755: tp->t_lstate &= ~LSCNTTB;
756: splx(s);
757: /*
758: * savecol will now be length of the tab
759: */
760: savecol -= tp->t_col;
761: tp->t_col += savecol;
762: if (savecol > 8)
763: savecol = 8; /* overflow screw */
764: while (--savecol >= 0)
765: (void) ntyoutput('\b', tp);
766: break;
767:
768: default:
769: panic("ttyrub");
770: }
771: } else if (tp->t_local&LPRTERA) {
772: if ((tp->t_lstate&LSERASE) == 0) {
773: (void) ntyoutput('\\', tp);
774: tp->t_lstate |= LSERASE;
775: }
776: ntyecho(c, tp);
777: } else
778: ntyecho(tp->t_erase, tp);
779: tp->t_rocount--;
780: }
781:
782: /*
783: * Crt back over cnt chars perhaps
784: * erasing them.
785: */
786: ntyrubo(tp, cnt)
787: register struct tty *tp;
788: int cnt;
789: {
790:
791: while (--cnt >= 0)
792: ntyout(tp->t_local&LCRTERA ? "\b \b" : "\b", tp);
793: }
794:
795: /*
796: * Reprint the rawq line.
797: * We assume c_cc has already been checked.
798: */
799: ntyretype(tp)
800: register struct tty *tp;
801: {
802: register char *cp;
803: char *nextc();
804: int s;
805:
806: if (tlun.t_rprntc != 0377)
807: ntyecho(tlun.t_rprntc, tp);
808: (void) ntyoutput('\n', tp);
809: s = spl5();
810: for (cp = tp->t_canq.c_cf; cp; cp = nextc(&tp->t_canq, cp))
811: ntyecho(*cp, tp);
812: for (cp = tp->t_rawq.c_cf; cp; cp = nextc(&tp->t_rawq, cp))
813: ntyecho(*cp, tp);
814: tp->t_lstate &= ~LSERASE;
815: splx(s);
816: tp->t_rocount = tp->t_rawq.c_cc;
817: tp->t_rocol = 0;
818: }
819:
820: /*
821: * Echo a typed character to the terminal
822: */
823: ntyecho(c, tp)
824: register c;
825: register struct tty *tp;
826: {
827:
828: if ((tp->t_lstate & LSCNTTB) == 0)
829: tp->t_local &= ~LFLUSHO;
830: c &= 0377;
831: if (tp->t_flags&ECHO) {
832: if (c == '\r' && tp->t_flags&CRMOD)
833: c = '\n';
834: if (tp->t_local&LCTLECH) {
835: if ((c&0177) <= 037 && c!='\t' && c!='\n' || (c&0177)==0177) {
836: (void) ntyoutput('^', tp);
837: c &= 0177;
838: if (c == 0177)
839: c = '?';
840: else if (tp->t_flags&LCASE)
841: c += 'a' - 1;
842: else
843: c += 'A' - 1;
844: }
845: }
846: (void) ntyoutput(c & 0177, tp);
847: }
848: }
849:
850: /*
851: * Is c a break char for tp?
852: */
853: ntbreakc(c, tp)
854: register c;
855: register struct tty *tp;
856: {
857: return (c == '\n' || c == tun.t_eofc || c == tun.t_brkc ||
858: c == '\r' && (tp->t_flags&CRMOD));
859: }
860:
861: /*
862: * send string cp to tp
863: */
864: ntyout(cp, tp)
865: register char *cp;
866: register struct tty *tp;
867: {
868: register char c;
869:
870: while (c = *cp++)
871: (void) ntyoutput(c, tp);
872: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.