|
|
1.1 root 1: /* tty.c 4.2 11/9/80 */
2:
3: /*
4: * TTY subroutines common to more than one line discipline
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: * When running dz's using only SAE (silo alarm) on input
24: * it is necessary to call dzrint() at clock interrupt time.
25: * This is unsafe unless spl5()s in tty code are changed to
26: * spl6()s to block clock interrupts. Note that the dh driver
27: * currently in use works the same way as the dz, even though
28: * we could try to more intelligently manage its silo.
29: * Thus don't take this out if you have no dz's unless you
30: * change clock.c and dhtimer().
31: */
32: #define spl5 spl6
33:
34: /*
35: * Input mapping table-- if an entry is non-zero, when the
36: * corresponding character is typed preceded by "\" the escape
37: * sequence is replaced by the table value. Mostly used for
38: * upper-case only terminals.
39: */
40:
41: char maptab[] ={
42: 000,000,000,000,000,000,000,000,
43: 000,000,000,000,000,000,000,000,
44: 000,000,000,000,000,000,000,000,
45: 000,000,000,000,000,000,000,000,
46: 000,'|',000,000,000,000,000,'`',
47: '{','}',000,000,000,000,000,000,
48: 000,000,000,000,000,000,000,000,
49: 000,000,000,000,000,000,000,000,
50: 000,000,000,000,000,000,000,000,
51: 000,000,000,000,000,000,000,000,
52: 000,000,000,000,000,000,000,000,
53: 000,000,000,000,000,000,'~',000,
54: 000,'A','B','C','D','E','F','G',
55: 'H','I','J','K','L','M','N','O',
56: 'P','Q','R','S','T','U','V','W',
57: 'X','Y','Z',000,000,000,000,000,
58: };
59:
60: short tthiwat[16] =
61: { 100,100,100,100,100,100,100,200,200,400,400,400,650,650,650,650 };
62: short ttlowat[16] =
63: { 30, 30, 30, 30, 30, 30, 30, 50, 50,120,120,120,125,125,125,125 };
64:
65: #define OBUFSIZ 100
66:
67: /*
68: * set default control characters.
69: */
70: ttychars(tp)
71: register struct tty *tp;
72: {
73:
74: tun.t_intrc = CINTR;
75: tun.t_quitc = CQUIT;
76: tun.t_startc = CSTART;
77: tun.t_stopc = CSTOP;
78: tun.t_eofc = CEOT;
79: tun.t_brkc = CBRK;
80: tp->t_erase = CERASE;
81: tp->t_kill = CKILL;
82: /* begin local */
83: tlun.t_suspc = CTRL(z);
84: tlun.t_dsuspc = CTRL(y);
85: tlun.t_rprntc = CTRL(r);
86: tlun.t_flushc = CTRL(o);
87: tlun.t_werasc = CTRL(w);
88: tlun.t_lnextc = CTRL(v);
89: tp->t_local = 0;
90: tp->t_lstate = 0;
91: /* end local */
92: }
93:
94: /*
95: * Wait for output to drain, then flush input waiting.
96: */
97: wflushtty(tp)
98: register struct tty *tp;
99: {
100:
101: (void) spl5();
102: while (tp->t_outq.c_cc && tp->t_state&CARR_ON) {
103: (*tp->t_oproc)(tp);
104: tp->t_state |= ASLEEP;
105: sleep((caddr_t)&tp->t_outq, TTOPRI);
106: }
107: flushtty(tp, FREAD|FWRITE);
108: (void) spl0();
109: }
110:
111: /*
112: * flush all TTY queues
113: */
114: flushtty(tp, rw)
115: register struct tty *tp;
116: {
117: register s;
118:
119: if (tp->t_line == NETLDISC)
120: return;
121: s = spl6();
122: if (rw & FREAD) {
123: while (getc(&tp->t_canq) >= 0)
124: ;
125: wakeup((caddr_t)&tp->t_rawq);
126: }
127: if (rw & FWRITE) {
128: wakeup((caddr_t)&tp->t_outq);
129: tp->t_state &= ~TTSTOP;
130: (*cdevsw[major(tp->t_dev)].d_stop)(tp);
131: while (getc(&tp->t_outq) >= 0)
132: ;
133: }
134: if (rw & FREAD) {
135: while (getc(&tp->t_rawq) >= 0)
136: ;
137: tp->t_delct = 0;
138: tp->t_rocount = 0; /* local */
139: tp->t_rocol = 0;
140: tp->t_lstate = 0;
141: }
142: splx(s);
143: }
144:
145: /*
146: * Send stop character on input overflow.
147: */
148: ttyblock(tp)
149: register struct tty *tp;
150: {
151: register x;
152: x = tp->t_rawq.c_cc + tp->t_canq.c_cc;
153: if (tp->t_rawq.c_cc > TTYHOG) {
154: flushtty(tp, FREAD|FWRITE);
155: tp->t_state &= ~TBLOCK;
156: }
157: if (x >= TTYHOG/2) {
158: if (putc(tun.t_stopc, &tp->t_outq)==0) {
159: tp->t_state |= TBLOCK;
160: tp->t_char++;
161: ttstart(tp);
162: }
163: }
164: }
165:
166: /*
167: * Restart typewriter output following a delay
168: * timeout.
169: * The name of the routine is passed to the timeout
170: * subroutine and it is called during a clock interrupt.
171: */
172: ttrstrt(tp)
173: register struct tty *tp;
174: {
175:
176: tp->t_state &= ~TIMEOUT;
177: ttstart(tp);
178: }
179:
180: /*
181: * Start output on the typewriter. It is used from the top half
182: * after some characters have been put on the output queue,
183: * from the interrupt routine to transmit the next
184: * character, and after a timeout has finished.
185: */
186: ttstart(tp)
187: register struct tty *tp;
188: {
189: register s;
190:
191: s = spl5();
192: if((tp->t_state&(TIMEOUT|TTSTOP|BUSY)) == 0)
193: (*tp->t_oproc)(tp);
194: splx(s);
195: }
196:
197: /*
198: * Common code for tty ioctls.
199: */
200: /*ARGSUSED*/
201: ttioctl(com, tp, addr, dev, flag)
202: register struct tty *tp;
203: caddr_t addr;
204: {
205: unsigned t;
206: struct sgttyb iocb;
207: struct clist tq;
208: extern int nldisp;
209: register c;
210: int temp;
211:
212: /*
213: * This is especially so that isatty() will
214: * fail when carrier is gone.
215: */
216: if ((tp->t_state&CARR_ON) == 0) {
217: u.u_error = EBADF;
218: return (1);
219: }
220:
221: /*
222: * If the ioctl involves modification,
223: * insist on being able to write the device,
224: * and hang if in the background.
225: */
226: switch(com) {
227:
228: case TIOCSETD:
229: case TIOCSETP:
230: case TIOCSETN:
231: case TIOCFLUSH:
232: case TIOCSETC:
233: case TIOCSLTC:
234: case TIOCSPGRP:
235: case TIOCLBIS:
236: case TIOCLBIC:
237: case TIOCLSET:
238: case TIOCSTI:
239: /* this is reasonable, but impractical...
240: if ((flag & FWRITE) == 0) {
241: u.u_error = EBADF;
242: return (1);
243: }
244: */
245: while (tp->t_line == NTTYDISC &&
246: u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp &&
247: (u.u_procp->p_flag&SVFORK) == 0 &&
248: u.u_signal[SIGTTOU] != SIG_IGN &&
249: u.u_signal[SIGTTOU] != SIG_HOLD &&
250: (u.u_procp->p_flag&SDETACH)==0) {
251: gsignal(u.u_procp->p_pgrp, SIGTTOU);
252: sleep((caddr_t)&lbolt, TTOPRI);
253: }
254: break;
255: }
256:
257: /*
258: * Process the ioctl.
259: */
260: switch(com) {
261:
262: /*
263: * Get discipline number
264: */
265: case TIOCGETD:
266: t = tp->t_line;
267: if (copyout((caddr_t)&t, addr, sizeof(t)))
268: u.u_error = EFAULT;
269: break;
270:
271: /*
272: * Set line discipline
273: */
274: case TIOCSETD:
275: if (copyin(addr, (caddr_t)&t, sizeof(t))) {
276: u.u_error = EFAULT;
277: break;
278: }
279: if (t >= nldisp) {
280: u.u_error = ENXIO;
281: break;
282: }
283: (void) spl5();
284: if (tp->t_line)
285: (*linesw[tp->t_line].l_close)(tp);
286: if (t)
287: (*linesw[t].l_open)(dev, tp, addr);
288: if (u.u_error==0)
289: tp->t_line = t;
290: (void) spl0();
291: break;
292:
293: /*
294: * Prevent more opens on channel
295: */
296: case TIOCEXCL:
297: tp->t_state |= XCLUDE;
298: break;
299:
300: case TIOCNXCL:
301: tp->t_state &= ~XCLUDE;
302: break;
303:
304: /*
305: * Set new parameters
306: */
307: case TIOCSETP:
308: case TIOCSETN:
309: if (copyin(addr, (caddr_t)&iocb, sizeof(iocb))) {
310: u.u_error = EFAULT;
311: return(1);
312: }
313: (void) spl5();
314: if (tp->t_line == 0) {
315: if (com == TIOCSETP)
316: wflushtty(tp);
317: while (canon(tp)>=0)
318: ;
319: #ifdef notdef
320: wakeup((caddr_t)&tp->t_rawq);
321: #endif
322: } else if (tp->t_line == NTTYDISC) {
323: if (tp->t_flags&RAW || iocb.sg_flags&RAW ||
324: com == TIOCSETP)
325: wflushtty(tp);
326: else if ((tp->t_flags&CBREAK) != (iocb.sg_flags&CBREAK)) {
327: if (iocb.sg_flags & CBREAK) {
328: catq(&tp->t_rawq, &tp->t_canq);
329: tq = tp->t_rawq;
330: tp->t_rawq = tp->t_canq;
331: tp->t_canq = tq;
332: } else {
333: tp->t_local |= LPENDIN;
334: if (tp->t_canq.c_cc)
335: panic("ioccom canq");
336: #ifdef notdef
337: if (tp->t_chan)
338: (void) sdata(tp->t_chan);
339: else
340: #endif
341: wakeup((caddr_t)&tp->t_rawq);
342: }
343: }
344: }
345: if ((tp->t_state&SPEEDS)==0) {
346: tp->t_ispeed = iocb.sg_ispeed;
347: tp->t_ospeed = iocb.sg_ospeed;
348: }
349: tp->t_erase = iocb.sg_erase;
350: tp->t_kill = iocb.sg_kill;
351: tp->t_flags = iocb.sg_flags;
352: (void) spl0();
353: break;
354:
355: /*
356: * Send current parameters to user
357: */
358: case TIOCGETP:
359: iocb.sg_ispeed = tp->t_ispeed;
360: iocb.sg_ospeed = tp->t_ospeed;
361: iocb.sg_erase = tp->t_erase;
362: iocb.sg_kill = tp->t_kill;
363: iocb.sg_flags = tp->t_flags;
364: if (copyout((caddr_t)&iocb, addr, sizeof(iocb)))
365: u.u_error = EFAULT;
366: break;
367:
368: /*
369: * Hang up line on last close
370: */
371: case TIOCHPCL:
372: tp->t_state |= HUPCLS;
373: break;
374:
375: case TIOCFLUSH:
376: flushtty(tp, FREAD|FWRITE);
377: break;
378:
379: /*
380: * Ioctl entries to line discipline
381: */
382: case DIOCSETP:
383: case DIOCGETP:
384: if ((*linesw[tp->t_line].l_ioctl)(com, tp, addr))
385: u.u_error = ENOTTY;
386: break;
387:
388: /*
389: * Set and fetch special characters
390: */
391: case TIOCSETC:
392: if (copyin(addr, (caddr_t)&tun, sizeof(struct tchars)))
393: u.u_error = EFAULT;
394: break;
395:
396: case TIOCGETC:
397: if (copyout((caddr_t)&tun, addr, sizeof(struct tchars)))
398: u.u_error = EFAULT;
399: break;
400:
401: /* local ioctls */
402: /*
403: * Set/get local special characters.
404: */
405: case TIOCSLTC:
406: if (copyin(addr, (caddr_t)&tlun, sizeof (struct ltchars)))
407: u.u_error = EFAULT;
408: break;
409:
410: case TIOCGLTC:
411: if (copyout((caddr_t)&tlun, addr, sizeof (struct ltchars)))
412: u.u_error = EFAULT;
413: break;
414:
415: /*
416: * Return number of characters immediately available.
417: */
418: case FIONREAD: {
419: off_t nread;
420:
421: switch (tp->t_line) {
422:
423: case NETLDISC:
424: nread = tp->t_rec ? tp->t_inbuf : 0;
425: break;
426:
427: case 0:
428: (void) spl5();
429: while (canon(tp)>=0)
430: ;
431: (void) spl0();
432: /* fall into ... */
433:
434: case NTTYDISC:
435: nread = tp->t_canq.c_cc;
436: if (tp->t_flags & (RAW|CBREAK))
437: nread += tp->t_rawq.c_cc;
438: break;
439:
440: }
441: if (copyout((caddr_t)&nread, addr, sizeof (off_t)))
442: u.u_error = EFAULT;
443: break;
444: }
445:
446: /*
447: * Should allow SPGRP and GPGRP only if tty open for reading.
448: */
449: case TIOCSPGRP:
450: if (copyin(addr, (caddr_t)&tp->t_pgrp, sizeof (tp->t_pgrp)))
451: u.u_error = EFAULT;
452: break;
453:
454: case TIOCGPGRP:
455: if (copyout((caddr_t)&tp->t_pgrp, addr, sizeof(tp->t_pgrp)))
456: u.u_error = EFAULT;
457: break;
458:
459: /*
460: * Modify local mode word.
461: */
462: case TIOCLBIS:
463: if (copyin(addr, (caddr_t)&temp, sizeof (tp->t_local)))
464: u.u_error = EFAULT;
465: else
466: tp->t_local |= temp;
467: break;
468:
469: case TIOCLBIC:
470: if (copyin(addr, (caddr_t)&temp, sizeof (tp->t_local)))
471: u.u_error = EFAULT;
472: else
473: tp->t_local &= ~temp;
474: break;
475:
476: case TIOCLSET:
477: if (copyin(addr, (caddr_t)&temp, sizeof (tp->t_local)))
478: u.u_error = EFAULT;
479: else
480: tp->t_local = temp;
481: break;
482:
483: case TIOCLGET:
484: if (copyout((caddr_t)&tp->t_local, addr, sizeof(tp->t_local)))
485: u.u_error = EFAULT;
486: break;
487:
488: /*
489: * Return number of characters in
490: * the output.
491: */
492: case TIOCOUTQ:
493: if (copyout((caddr_t)&tp->t_outq.c_cc, addr, sizeof(tp->t_outq.c_cc)))
494: u.u_error = EFAULT;
495: break;
496:
497: /*
498: * Simulate typing of a character at the terminal.
499: */
500: case TIOCSTI:
501: c = fubyte(addr);
502: if (u.u_uid && u.u_ttyp != tp || c < 0)
503: u.u_error = EFAULT;
504: else
505: (*linesw[tp->t_line].l_rint)(c, tp);
506: break;
507: /* end of locals */
508:
509: default:
510: return(0);
511: }
512: return(1);
513: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.