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