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