|
|
1.1 root 1: /* ttyold.c 4.9 81/07/22 */
2:
3: /*
4: * general TTY subroutines
5: */
6: #include "../h/param.h"
7: #include "../h/systm.h"
8: #include "../h/dir.h"
9: #include "../h/user.h"
10: #include "../h/tty.h"
11: #include "../h/proc.h"
12: #include "../h/mx.h"
13: #include "../h/inode.h"
14: #include "../h/file.h"
15: #include "../h/reg.h"
16: #include "../h/conf.h"
17: #include "../h/buf.h"
18: #include "../h/dk.h"
19:
20: char partab[];
21:
22: /*
23: * Input mapping table-- if an entry is non-zero, when the
24: * corresponding character is typed preceded by "\" the escape
25: * sequence is replaced by the table value. Mostly used for
26: * upper-case only terminals.
27: */
28: char maptab[];
29:
30: #define OBUFSIZ 100
31:
32: /*
33: * routine called on first teletype open.
34: * establishes a process group for distribution
35: * of quits and interrupts from the tty.
36: */
37: ttyopen(dev, tp)
38: dev_t dev;
39: register struct tty *tp;
40: {
41: register struct proc *pp;
42:
43: pp = u.u_procp;
44: tp->t_dev = dev;
45: if(pp->p_pgrp == 0) {
46: u.u_ttyp = tp;
47: u.u_ttyd = dev;
48: if (tp->t_pgrp == 0)
49: tp->t_pgrp = pp->p_pid;
50: pp->p_pgrp = tp->t_pgrp;
51: }
52: tp->t_state &= ~WOPEN;
53: tp->t_state |= ISOPEN;
54: tp->t_line = 0; /* conservative */
55: }
56:
57: /*
58: * clean tp on last close
59: */
60: ttyclose(tp)
61: register struct tty *tp;
62: {
63:
64: tp->t_pgrp = 0;
65: wflushtty(tp);
66: tp->t_state = 0;
67: tp->t_line = 0;
68: }
69:
70: /*
71: * transfer raw input list to canonical list,
72: * doing erase-kill processing and handling escapes.
73: * It waits until a full line has been typed in cooked mode,
74: * or until any character has been typed in raw mode.
75: */
76: canon(tp)
77: register struct tty *tp;
78: {
79: register char *bp;
80: char *bp1;
81: register int c;
82: int mc;
83: int s;
84:
85: if ((tp->t_flags&(RAW|CBREAK))==0 && tp->t_delct==0
86: || (tp->t_flags&(RAW|CBREAK))!=0 && tp->t_rawq.c_cc==0) {
87: return(-1);
88: }
89: s = spl0();
90: loop:
91: bp = &canonb[2];
92: while ((c=getc(&tp->t_rawq)) >= 0) {
93: if ((tp->t_flags&(RAW|CBREAK))==0) {
94: if (c==0377) {
95: tp->t_delct--;
96: break;
97: }
98: if (bp[-1]!='\\') {
99: if (c==tp->t_erase) {
100: if (bp > &canonb[2])
101: bp--;
102: continue;
103: }
104: if (c==tp->t_kill)
105: goto loop;
106: if (c==tun.t_eofc)
107: continue;
108: } else {
109: mc = maptab[c];
110: if (c==tp->t_erase || c==tp->t_kill)
111: mc = c;
112: if (mc && (mc==c || (tp->t_flags&LCASE))) {
113: if (bp[-2] != '\\')
114: c = mc;
115: bp--;
116: }
117: }
118: }
119: *bp++ = c;
120: if (bp>=canonb+CANBSIZ)
121: break;
122: }
123: bp1 = &canonb[2];
124: (void) b_to_q(bp1, bp-bp1, &tp->t_canq);
125:
126: if (tp->t_state&TBLOCK && tp->t_rawq.c_cc < TTYHOG/5) {
127: if (putc(tun.t_startc, &tp->t_outq)==0) {
128: tp->t_state &= ~TBLOCK;
129: ttstart(tp);
130: }
131: tp->t_char = 0;
132: }
133:
134: splx(s);
135: return(0);
136: }
137:
138:
139: /*
140: * block transfer input handler.
141: */
142: ttyrend(tp, pb, pe)
143: register struct tty *tp;
144: register char *pb, *pe;
145: {
146: int tandem;
147:
148: tandem = tp->t_flags&TANDEM;
149: if (tp->t_flags&RAW) {
150: (void) b_to_q(pb, pe-pb, &tp->t_rawq);
151: if (tp->t_chan)
152: (void) sdata(tp->t_chan);
153: wakeup((caddr_t)&tp->t_rawq);
154: } else {
155: tp->t_flags &= ~TANDEM;
156: while (pb < pe)
157: ttyinput(*pb++, tp);
158: tp->t_flags |= tandem;
159: }
160: if (tandem)
161: ttyblock(tp);
162: }
163:
164: /*
165: * Place a character on raw TTY input queue, putting in delimiters
166: * and waking up top half as needed.
167: * Also echo if required.
168: * The arguments are the character and the appropriate
169: * tty structure.
170: */
171: ttyinput(c, tp)
172: register c;
173: register struct tty *tp;
174: {
175: register int t_flags;
176: register struct chan *cp;
177:
178: tk_nin += 1;
179: c &= 0377;
180: t_flags = tp->t_flags;
181: if (t_flags&TANDEM)
182: ttyblock(tp);
183: if ((t_flags&RAW)==0) {
184: c &= 0177;
185: if (tp->t_state&TTSTOP) {
186: if (c==tun.t_startc) {
187: tp->t_state &= ~TTSTOP;
188: ttstart(tp);
189: return;
190: }
191: if (c==tun.t_stopc)
192: return;
193: if ((tp->t_local & LDECCTQ) == 0) {
194: tp->t_state &= ~TTSTOP;
195: ttstart(tp);
196: }
197: } else {
198: if (c==tun.t_stopc) {
199: tp->t_state |= TTSTOP;
200: (*cdevsw[major(tp->t_dev)].d_stop)(tp);
201: return;
202: }
203: if (c==tun.t_startc)
204: return;
205: }
206: if (c==tun.t_quitc || c==tun.t_intrc) {
207: if ((tp->t_local & LNOFLSH) == 0)
208: flushtty(tp, FREAD|FWRITE);
209: c = (c==tun.t_intrc) ? SIGINT:SIGQUIT;
210: if (tp->t_chan)
211: scontrol(tp->t_chan, M_SIG, c);
212: gsignal(tp->t_pgrp, c);
213: return;
214: }
215: if (c=='\r' && t_flags&CRMOD)
216: c = '\n';
217: }
218: if (tp->t_rawq.c_cc>TTYHOG) {
219: flushtty(tp, FREAD|FWRITE);
220: return;
221: }
222: if (t_flags&LCASE && c>='A' && c<='Z')
223: c += 'a'-'A';
224: (void) putc(c, &tp->t_rawq);
225: if (t_flags&(RAW|CBREAK)||(c=='\n'||c==tun.t_eofc||c==tun.t_brkc)) {
226: if ((t_flags&(RAW|CBREAK))==0 && putc(0377, &tp->t_rawq)==0)
227: tp->t_delct++;
228: if ((cp=tp->t_chan)!=NULL)
229: (void) sdata(cp);
230: wakeup((caddr_t)&tp->t_rawq);
231: }
232: if (t_flags&ECHO) {
233: ttyoutput(c, tp);
234: if (c==tp->t_kill && (t_flags&(RAW|CBREAK))==0)
235: ttyoutput('\n', tp);
236: ttstart(tp);
237: }
238: }
239:
240: /*
241: * put character on TTY output queue, adding delays,
242: * expanding tabs, and handling the CR/NL bit.
243: * It is called both from the top half for output, and from
244: * interrupt level for echoing.
245: * The arguments are the character and the tty structure.
246: */
247: ttyoutput(c, tp)
248: register c;
249: register struct tty *tp;
250: {
251: register char *colp;
252: register ctype;
253:
254: /*
255: * Ignore EOT in normal mode to avoid hanging up
256: * certain terminals.
257: * In raw mode dump the char unchanged.
258: */
259: if ((tp->t_flags&RAW)==0) {
260: c &= 0177;
261: if ((tp->t_flags&CBREAK)==0 && c==CEOT)
262: return;
263: } else {
264: tk_nout++;
265: (void) putc(c, &tp->t_outq);
266: return;
267: }
268:
269: /*
270: * Turn tabs to spaces as required
271: */
272: if (c=='\t' && (tp->t_flags&TBDELAY)==XTABS) {
273: c = 8 - (tp->t_col & 7);
274: (void) b_to_q(" ", c, &tp->t_outq);
275: tp->t_col += c;
276: tk_nout += c;
277: return;
278: }
279: tk_nout++;
280: /*
281: * for upper-case-only terminals,
282: * generate escapes.
283: */
284: if (tp->t_flags&LCASE) {
285: colp = "({)}!|^~'`";
286: while(*colp++)
287: if(c == *colp++) {
288: ttyoutput('\\', tp);
289: c = colp[-2];
290: break;
291: }
292: if ('a'<=c && c<='z')
293: c += 'A' - 'a';
294: }
295: /*
296: * turn <nl> to <cr><lf> if desired.
297: */
298: if (c=='\n' && tp->t_flags&CRMOD)
299: ttyoutput('\r', tp);
300: (void) putc(c, &tp->t_outq);
301: /*
302: * Calculate delays.
303: * The numbers here represent clock ticks
304: * and are not necessarily optimal for all terminals.
305: * The delays are indicated by characters above 0200.
306: * In raw mode there are no delays and the
307: * transmission path is 8 bits wide.
308: */
309: colp = &tp->t_col;
310: ctype = partab[c];
311: c = 0;
312: switch (ctype&077) {
313:
314: /* ordinary */
315: case 0:
316: (*colp)++;
317:
318: /* non-printing */
319: case 1:
320: break;
321:
322: /* backspace */
323: case 2:
324: if (*colp)
325: (*colp)--;
326: break;
327:
328: /* newline */
329: case 3:
330: ctype = (tp->t_flags >> 8) & 03;
331: if(ctype == 1) { /* tty 37 */
332: if (*colp)
333: c = max(((unsigned)*colp>>4) + 3, (unsigned)6);
334: } else
335: if(ctype == 2) { /* vt05 */
336: c = 6;
337: }
338: *colp = 0;
339: break;
340:
341: /* tab */
342: case 4:
343: ctype = (tp->t_flags >> 10) & 03;
344: if(ctype == 1) { /* tty 37 */
345: c = 1 - (*colp | ~07);
346: if(c < 5)
347: c = 0;
348: }
349: *colp |= 07;
350: (*colp)++;
351: break;
352:
353: /* vertical motion */
354: case 5:
355: if(tp->t_flags & VTDELAY) /* tty 37 */
356: c = 0177;
357: break;
358:
359: /* carriage return */
360: case 6:
361: ctype = (tp->t_flags >> 12) & 03;
362: if(ctype == 1) { /* tn 300 */
363: c = 5;
364: } else if(ctype == 2) { /* ti 700 */
365: c = 10;
366: } else if(ctype == 3) { /* concept 100 */
367: int i;
368: if ((i = *colp) >= 0)
369: for (; i<9; i++)
370: (void) putc(0177, &tp->t_outq);
371: }
372: *colp = 0;
373: }
374: if(c)
375: (void) putc(c|0200, &tp->t_outq);
376: }
377:
378: /*
379: * Called from device's read routine after it has
380: * calculated the tty-structure given as argument.
381: */
382: ttread(tp)
383: register struct tty *tp;
384: {
385: register s;
386:
387: if ((tp->t_state&CARR_ON)==0)
388: return(-1);
389: s = spl5();
390: if (tp->t_canq.c_cc==0)
391: while (canon(tp)<0)
392: if (tp->t_chan==NULL ||
393: (getf(u.u_ap[0])->f_flag&FMP)==0) {
394: sleep((caddr_t)&tp->t_rawq, TTIPRI);
395: } else {
396: splx(s);
397: return(0);
398: }
399: splx(s);
400: while (tp->t_canq.c_cc && passc(getc(&tp->t_canq))>=0)
401: ;
402: return(tp->t_rawq.c_cc+tp->t_canq.c_cc);
403: }
404:
405: /*
406: * Called from the device's write routine after it has
407: * calculated the tty-structure given as argument.
408: */
409: caddr_t
410: ttwrite(tp)
411: register struct tty *tp;
412: {
413: /*
414: * THE POSITIONING OF CP, CC, AND CE ARE CRITICAL
415: * AND MUST NOT BE CHANGED WITHOUT PATCHING
416: * THE 'ASM' INLINES BELOW. WATCH OUT.
417: */
418: register char *cp;
419: register int cc, ce;
420: register i;
421: char obuf[OBUFSIZ];
422: int hiwat = TTHIWAT(tp);
423:
424: if ((tp->t_state&CARR_ON)==0)
425: return(NULL);
426: while (u.u_count) {
427: cc = MIN(u.u_count, OBUFSIZ);
428: cp = obuf;
429: iomove(cp, (unsigned)cc, B_WRITE);
430: if (u.u_error)
431: break;
432: (void) spl5();
433: while (tp->t_outq.c_cc > hiwat) {
434: ttstart(tp);
435: tp->t_state |= ASLEEP;
436: if (tp->t_chan && u.u_segflg == 0 &&
437: (getf(u.u_ap[0])->f_flag&FMP)) {
438: u.u_base -= cc;
439: u.u_offset -= cc;
440: u.u_count += cc;
441: (void) spl0();
442: return((caddr_t)&tp->t_outq);
443: }
444: sleep((caddr_t)&tp->t_outq, TTOPRI);
445: }
446: (void) spl0();
447: if (tp->t_flags&LCASE) {
448: while (cc--)
449: ttyoutput(*cp++,tp);
450: continue;
451: }
452: while (cc) {
453: if (tp->t_flags&RAW)
454: ce=cc;
455: else {
456: #ifdef vax
457: asm(" scanc r9,(r10),_partab,$077");
458: asm(" subl3 r0,r9,r8");
459: #else
460: ce=0;
461: while(((partab[*(unsigned char *)(cp+ce)]&077)==0)&&(ce<cc))
462: ce++;
463: #endif
464: if (ce==0) {
465: ttyoutput(*cp++,tp);
466: cc--;
467: goto check;
468: }
469: }
470: i=b_to_q(cp,ce,&tp->t_outq);
471: ce-=i;
472: tk_nout+=ce;
473: tp->t_col+=ce;
474: cp+=ce;
475: cc-=ce;
476: check:
477: if (tp->t_outq.c_cc > hiwat) {
478: (void) spl5();
479: while (tp->t_outq.c_cc > hiwat) {
480: ttstart(tp);
481: tp->t_state |= ASLEEP;
482: sleep((caddr_t)&tp->t_outq, TTOPRI);
483: }
484: (void) spl0();
485: }
486: }
487: }
488: ttstart(tp);
489: return(NULL);
490: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.