print variables ($v) in hex; make $<- re-read current file
[unix-history] / usr / src / sys / kern / tty.c
CommitLineData
8bba2b8f 1/* tty.c 4.23 82/07/15 */
89dc6dfb
BJ
2
3/*
50e2732b 4 * TTY subroutines common to more than one line discipline
89dc6dfb
BJ
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"
89dc6dfb
BJ
12#include "../h/inode.h"
13#include "../h/file.h"
14#include "../h/reg.h"
15#include "../h/conf.h"
16#include "../h/buf.h"
d1778415 17#include "../h/dk.h"
89dc6dfb 18
8bba2b8f
RE
19/*
20 * Table giving parity for characters and indicating
21 * character classes to tty driver. In particular,
22 * if the low 6 bits are 0, then the character needs
23 * no special processing on output.
24 */
25
26char partab[] = {
27 0001,0201,0201,0001,0201,0001,0001,0201,
28 0202,0004,0003,0201,0005,0206,0201,0001,
29 0201,0001,0001,0201,0001,0201,0201,0001,
30 0001,0201,0201,0001,0201,0001,0001,0201,
31 0200,0000,0000,0200,0000,0200,0200,0000,
32 0000,0200,0200,0000,0200,0000,0000,0200,
33 0000,0200,0200,0000,0200,0000,0000,0200,
34 0200,0000,0000,0200,0000,0200,0200,0000,
35 0200,0000,0000,0200,0000,0200,0200,0000,
36 0000,0200,0200,0000,0200,0000,0000,0200,
37 0000,0200,0200,0000,0200,0000,0000,0200,
38 0200,0000,0000,0200,0000,0200,0200,0000,
39 0000,0200,0200,0000,0200,0000,0000,0200,
40 0200,0000,0000,0200,0000,0200,0200,0000,
41 0200,0000,0000,0200,0000,0200,0200,0000,
42 0000,0200,0200,0000,0200,0000,0000,0201,
43
44 /*
45 * 7 bit ascii ends with the last character above,
46 * but we contine through all 256 codes for the sake
47 * of the tty output routines which use special vax
48 * instructions which need a 256 character trt table.
49 */
50
51 0007,0007,0007,0007,0007,0007,0007,0007,
52 0007,0007,0007,0007,0007,0007,0007,0007,
53 0007,0007,0007,0007,0007,0007,0007,0007,
54 0007,0007,0007,0007,0007,0007,0007,0007,
55 0007,0007,0007,0007,0007,0007,0007,0007,
56 0007,0007,0007,0007,0007,0007,0007,0007,
57 0007,0007,0007,0007,0007,0007,0007,0007,
58 0007,0007,0007,0007,0007,0007,0007,0007,
59 0007,0007,0007,0007,0007,0007,0007,0007,
60 0007,0007,0007,0007,0007,0007,0007,0007,
61 0007,0007,0007,0007,0007,0007,0007,0007,
62 0007,0007,0007,0007,0007,0007,0007,0007,
63 0007,0007,0007,0007,0007,0007,0007,0007,
64 0007,0007,0007,0007,0007,0007,0007,0007,
65 0007,0007,0007,0007,0007,0007,0007,0007,
66 0007,0007,0007,0007,0007,0007,0007,0007
67};
89dc6dfb 68
89dc6dfb
BJ
69/*
70 * Input mapping table-- if an entry is non-zero, when the
71 * corresponding character is typed preceded by "\" the escape
72 * sequence is replaced by the table value. Mostly used for
73 * upper-case only terminals.
74 */
75
76char maptab[] ={
77 000,000,000,000,000,000,000,000,
78 000,000,000,000,000,000,000,000,
79 000,000,000,000,000,000,000,000,
80 000,000,000,000,000,000,000,000,
81 000,'|',000,000,000,000,000,'`',
82 '{','}',000,000,000,000,000,000,
83 000,000,000,000,000,000,000,000,
84 000,000,000,000,000,000,000,000,
85 000,000,000,000,000,000,000,000,
86 000,000,000,000,000,000,000,000,
87 000,000,000,000,000,000,000,000,
88 000,000,000,000,000,000,'~',000,
89 000,'A','B','C','D','E','F','G',
90 'H','I','J','K','L','M','N','O',
91 'P','Q','R','S','T','U','V','W',
92 'X','Y','Z',000,000,000,000,000,
93};
94
0d65848d
BJ
95short tthiwat[16] =
96 { 100,100,100,100,100,100,100,200,200,400,400,400,650,650,650,650 };
97short ttlowat[16] =
98 { 30, 30, 30, 30, 30, 30, 30, 50, 50,120,120,120,125,125,125,125 };
99
89dc6dfb
BJ
100#define OBUFSIZ 100
101
89dc6dfb
BJ
102/*
103 * set default control characters.
104 */
105ttychars(tp)
106register struct tty *tp;
107{
8062c8a7 108
89dc6dfb
BJ
109 tun.t_intrc = CINTR;
110 tun.t_quitc = CQUIT;
111 tun.t_startc = CSTART;
112 tun.t_stopc = CSTOP;
113 tun.t_eofc = CEOT;
114 tun.t_brkc = CBRK;
115 tp->t_erase = CERASE;
116 tp->t_kill = CKILL;
8062c8a7 117/* begin local */
6fdc0335
BJ
118 tlun.t_suspc = CTRL(z);
119 tlun.t_dsuspc = CTRL(y);
8062c8a7
BJ
120 tlun.t_rprntc = CTRL(r);
121 tlun.t_flushc = CTRL(o);
122 tlun.t_werasc = CTRL(w);
123 tlun.t_lnextc = CTRL(v);
8062c8a7
BJ
124 tp->t_local = 0;
125 tp->t_lstate = 0;
126/* end local */
89dc6dfb
BJ
127}
128
129/*
50e2732b 130 * Wait for output to drain, then flush input waiting.
89dc6dfb 131 */
50e2732b 132wflushtty(tp)
941944c9 133 register struct tty *tp;
89dc6dfb
BJ
134{
135
50e2732b 136 (void) spl5();
4c67f645
BJ
137 while (tp->t_outq.c_cc && tp->t_state&TS_CARR_ON
138 && tp->t_oproc) { /* kludge for pty */
50e2732b 139 (*tp->t_oproc)(tp);
941944c9 140 tp->t_state |= TS_ASLEEP;
50e2732b
BJ
141 sleep((caddr_t)&tp->t_outq, TTOPRI);
142 }
39697bd8 143 flushtty(tp, FREAD);
50e2732b 144 (void) spl0();
89dc6dfb
BJ
145}
146
147/*
50e2732b 148 * flush all TTY queues
89dc6dfb 149 */
50e2732b
BJ
150flushtty(tp, rw)
151register struct tty *tp;
89dc6dfb 152{
50e2732b
BJ
153 register s;
154
50e2732b
BJ
155 s = spl6();
156 if (rw & FREAD) {
157 while (getc(&tp->t_canq) >= 0)
158 ;
159 wakeup((caddr_t)&tp->t_rawq);
160 }
161 if (rw & FWRITE) {
162 wakeup((caddr_t)&tp->t_outq);
941944c9 163 tp->t_state &= ~TS_TTSTOP;
39697bd8 164 (*cdevsw[major(tp->t_dev)].d_stop)(tp, rw);
50e2732b
BJ
165 while (getc(&tp->t_outq) >= 0)
166 ;
167 }
168 if (rw & FREAD) {
169 while (getc(&tp->t_rawq) >= 0)
170 ;
171 tp->t_delct = 0;
172 tp->t_rocount = 0; /* local */
173 tp->t_rocol = 0;
174 tp->t_lstate = 0;
175 }
176 splx(s);
89dc6dfb
BJ
177}
178
50e2732b
BJ
179/*
180 * Send stop character on input overflow.
181 */
182ttyblock(tp)
183register struct tty *tp;
89dc6dfb 184{
50e2732b
BJ
185 register x;
186 x = tp->t_rawq.c_cc + tp->t_canq.c_cc;
187 if (tp->t_rawq.c_cc > TTYHOG) {
188 flushtty(tp, FREAD|FWRITE);
941944c9 189 tp->t_state &= ~TS_TBLOCK;
50e2732b
BJ
190 }
191 if (x >= TTYHOG/2) {
192 if (putc(tun.t_stopc, &tp->t_outq)==0) {
941944c9 193 tp->t_state |= TS_TBLOCK;
50e2732b
BJ
194 tp->t_char++;
195 ttstart(tp);
196 }
197 }
89dc6dfb
BJ
198}
199
101ba270 200/*
50e2732b
BJ
201 * Restart typewriter output following a delay
202 * timeout.
203 * The name of the routine is passed to the timeout
204 * subroutine and it is called during a clock interrupt.
101ba270 205 */
50e2732b 206ttrstrt(tp)
101ba270 207register struct tty *tp;
101ba270
BJ
208{
209
545f5350
BJ
210 if (tp == 0) {
211 printf("ttrstrt: arg was 0!\n");
212 return;
213 }
941944c9 214 tp->t_state &= ~TS_TIMEOUT;
50e2732b 215 ttstart(tp);
101ba270
BJ
216}
217
89dc6dfb 218/*
50e2732b
BJ
219 * Start output on the typewriter. It is used from the top half
220 * after some characters have been put on the output queue,
221 * from the interrupt routine to transmit the next
222 * character, and after a timeout has finished.
89dc6dfb 223 */
50e2732b
BJ
224ttstart(tp)
225register struct tty *tp;
89dc6dfb 226{
50e2732b 227 register s;
8062c8a7 228
50e2732b 229 s = spl5();
4c67f645
BJ
230 if((tp->t_state&(TS_TIMEOUT|TS_TTSTOP|TS_BUSY)) == 0 &&
231 tp->t_oproc) /* kludge for pty */
50e2732b
BJ
232 (*tp->t_oproc)(tp);
233 splx(s);
89dc6dfb
BJ
234}
235
236/*
50e2732b 237 * Common code for tty ioctls.
89dc6dfb 238 */
49c84d3f 239/*ARGSUSED*/
0cbf0d70 240ttioctl(tp, com, addr, flag)
89dc6dfb
BJ
241register struct tty *tp;
242caddr_t addr;
243{
0cbf0d70 244 int dev;
89dc6dfb 245 unsigned t;
8062c8a7 246 struct sgttyb iocb;
de857265 247 struct clist tq;
89dc6dfb 248 extern int nldisp;
50450a20 249 register c;
da1392b6 250 int temp;
89dc6dfb 251
c6fe3a50
BJ
252 /*
253 * This is especially so that isatty() will
254 * fail when carrier is gone.
255 */
941944c9 256 if ((tp->t_state&TS_CARR_ON) == 0) {
c6fe3a50
BJ
257 u.u_error = EBADF;
258 return (1);
259 }
260
0cbf0d70 261 dev = tp->t_dev;
50e2732b
BJ
262 /*
263 * If the ioctl involves modification,
264 * insist on being able to write the device,
265 * and hang if in the background.
266 */
267 switch(com) {
268
c6fe3a50
BJ
269 case TIOCSETD:
270 case TIOCSETP:
271 case TIOCSETN:
50e2732b
BJ
272 case TIOCFLUSH:
273 case TIOCSETC:
274 case TIOCSLTC:
275 case TIOCSPGRP:
276 case TIOCLBIS:
277 case TIOCLBIC:
278 case TIOCLSET:
279 case TIOCSTI:
c6fe3a50 280/* this is reasonable, but impractical...
50e2732b
BJ
281 if ((flag & FWRITE) == 0) {
282 u.u_error = EBADF;
283 return (1);
284 }
c6fe3a50 285 */
50e2732b
BJ
286 while (tp->t_line == NTTYDISC &&
287 u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp &&
288 (u.u_procp->p_flag&SVFORK) == 0 &&
289 u.u_signal[SIGTTOU] != SIG_IGN &&
022f2340
BJ
290 u.u_signal[SIGTTOU] != SIG_HOLD
291/*
292 &&
50e2732b 293 (u.u_procp->p_flag&SDETACH)==0) {
022f2340
BJ
294*/
295 ) {
50e2732b
BJ
296 gsignal(u.u_procp->p_pgrp, SIGTTOU);
297 sleep((caddr_t)&lbolt, TTOPRI);
298 }
299 break;
300 }
301
302 /*
303 * Process the ioctl.
304 */
89dc6dfb
BJ
305 switch(com) {
306
307 /*
50e2732b 308 * Get discipline number
89dc6dfb
BJ
309 */
310 case TIOCGETD:
311 t = tp->t_line;
312 if (copyout((caddr_t)&t, addr, sizeof(t)))
313 u.u_error = EFAULT;
314 break;
315
316 /*
50e2732b 317 * Set line discipline
89dc6dfb
BJ
318 */
319 case TIOCSETD:
320 if (copyin(addr, (caddr_t)&t, sizeof(t))) {
321 u.u_error = EFAULT;
322 break;
323 }
324 if (t >= nldisp) {
325 u.u_error = ENXIO;
326 break;
327 }
8062c8a7 328 (void) spl5();
89dc6dfb
BJ
329 if (tp->t_line)
330 (*linesw[tp->t_line].l_close)(tp);
331 if (t)
332 (*linesw[t].l_open)(dev, tp, addr);
333 if (u.u_error==0)
334 tp->t_line = t;
8062c8a7 335 (void) spl0();
89dc6dfb
BJ
336 break;
337
152c2598
BJ
338 /*
339 * Prevent more opens on channel
340 */
341 case TIOCEXCL:
342 tp->t_state |= TS_XCLUDE;
343 break;
344
345 case TIOCNXCL:
346 tp->t_state &= ~TS_XCLUDE;
347 break;
348
89dc6dfb
BJ
349 /*
350 * Set new parameters
351 */
352 case TIOCSETP:
de857265 353 case TIOCSETN:
89dc6dfb
BJ
354 if (copyin(addr, (caddr_t)&iocb, sizeof(iocb))) {
355 u.u_error = EFAULT;
356 return(1);
357 }
101ba270 358 (void) spl5();
e1d74936
BJ
359 if (tp->t_flags&RAW || iocb.sg_flags&RAW ||
360 com == TIOCSETP)
361 wflushtty(tp);
362 else if ((tp->t_flags&CBREAK) != (iocb.sg_flags&CBREAK)) {
363 if (iocb.sg_flags & CBREAK) {
364 catq(&tp->t_rawq, &tp->t_canq);
365 tq = tp->t_rawq;
366 tp->t_rawq = tp->t_canq;
367 tp->t_canq = tq;
368 } else {
369 tp->t_local |= LPENDIN;
370 ttwakeup(tp);
8062c8a7
BJ
371 }
372 }
e1d74936
BJ
373 tp->t_ispeed = iocb.sg_ispeed;
374 tp->t_ospeed = iocb.sg_ospeed;
8062c8a7
BJ
375 tp->t_erase = iocb.sg_erase;
376 tp->t_kill = iocb.sg_kill;
377 tp->t_flags = iocb.sg_flags;
627c86ee 378 if (tp->t_flags & RAW) {
941944c9 379 tp->t_state &= ~TS_TTSTOP;
627c86ee
KB
380 ttstart(tp);
381 }
101ba270 382 (void) spl0();
89dc6dfb
BJ
383 break;
384
385 /*
50e2732b 386 * Send current parameters to user
89dc6dfb
BJ
387 */
388 case TIOCGETP:
8062c8a7
BJ
389 iocb.sg_ispeed = tp->t_ispeed;
390 iocb.sg_ospeed = tp->t_ospeed;
391 iocb.sg_erase = tp->t_erase;
392 iocb.sg_kill = tp->t_kill;
393 iocb.sg_flags = tp->t_flags;
89dc6dfb
BJ
394 if (copyout((caddr_t)&iocb, addr, sizeof(iocb)))
395 u.u_error = EFAULT;
396 break;
397
398 /*
399 * Hang up line on last close
400 */
89dc6dfb 401 case TIOCHPCL:
941944c9 402 tp->t_state |= TS_HUPCLS;
89dc6dfb
BJ
403 break;
404
7d973a4d
KB
405 case TIOCFLUSH: {
406 int flags;
407 if (addr == 0)
408 flags = FREAD|FWRITE;
409 else if (copyin(addr, (caddr_t)&flags, sizeof (flags))) {
410 u.u_error = EFAULT;
7344d489 411 return(1);
7d973a4d
KB
412 }
413 flushtty(tp, flags);
89dc6dfb 414 break;
4568c08e 415 }
89dc6dfb 416
941944c9
BJ
417 case FIONBIO: {
418 int nbio;
419 if (copyin(addr, (caddr_t)&nbio, sizeof (nbio))) {
420 u.u_error = EFAULT;
421 return(1);
422 }
423 if (nbio)
424 tp->t_state |= TS_NBIO;
425 else
426 tp->t_state &= ~TS_NBIO;
427 break;
428 }
429
a66e4149
BJ
430 case FIOASYNC: {
431 int async;
432 if (copyin(addr, (caddr_t)&async, sizeof (async))) {
433 u.u_error = EFAULT;
434 return(1);
435 }
436 if (async)
437 tp->t_state |= TS_ASYNC;
438 else
439 tp->t_state &= ~TS_ASYNC;
440 break;
441 }
442
89dc6dfb 443 /*
50e2732b 444 * Set and fetch special characters
89dc6dfb
BJ
445 */
446 case TIOCSETC:
8062c8a7 447 if (copyin(addr, (caddr_t)&tun, sizeof(struct tchars)))
89dc6dfb
BJ
448 u.u_error = EFAULT;
449 break;
450
451 case TIOCGETC:
8062c8a7
BJ
452 if (copyout((caddr_t)&tun, addr, sizeof(struct tchars)))
453 u.u_error = EFAULT;
454 break;
455
456/* local ioctls */
50e2732b
BJ
457 /*
458 * Set/get local special characters.
459 */
8062c8a7
BJ
460 case TIOCSLTC:
461 if (copyin(addr, (caddr_t)&tlun, sizeof (struct ltchars)))
462 u.u_error = EFAULT;
463 break;
464
465 case TIOCGLTC:
466 if (copyout((caddr_t)&tlun, addr, sizeof (struct ltchars)))
467 u.u_error = EFAULT;
468 break;
469
50e2732b
BJ
470 /*
471 * Return number of characters immediately available.
472 */
8062c8a7 473 case FIONREAD: {
e1d74936 474 off_t nread = ttnread(tp);
8062c8a7
BJ
475 if (copyout((caddr_t)&nread, addr, sizeof (off_t)))
476 u.u_error = EFAULT;
477 break;
478 }
479
480 /*
481 * Should allow SPGRP and GPGRP only if tty open for reading.
482 */
483 case TIOCSPGRP:
da1392b6
BJ
484 if (copyin(addr, (caddr_t)&tp->t_pgrp, sizeof (tp->t_pgrp)))
485 u.u_error = EFAULT;
8062c8a7
BJ
486 break;
487
488 case TIOCGPGRP:
489 if (copyout((caddr_t)&tp->t_pgrp, addr, sizeof(tp->t_pgrp)))
490 u.u_error = EFAULT;
491 break;
492
493 /*
494 * Modify local mode word.
495 */
496 case TIOCLBIS:
da1392b6
BJ
497 if (copyin(addr, (caddr_t)&temp, sizeof (tp->t_local)))
498 u.u_error = EFAULT;
499 else
500 tp->t_local |= temp;
8062c8a7
BJ
501 break;
502
503 case TIOCLBIC:
da1392b6
BJ
504 if (copyin(addr, (caddr_t)&temp, sizeof (tp->t_local)))
505 u.u_error = EFAULT;
506 else
507 tp->t_local &= ~temp;
8062c8a7
BJ
508 break;
509
510 case TIOCLSET:
da1392b6
BJ
511 if (copyin(addr, (caddr_t)&temp, sizeof (tp->t_local)))
512 u.u_error = EFAULT;
513 else
514 tp->t_local = temp;
8062c8a7
BJ
515 break;
516
517 case TIOCLGET:
518 if (copyout((caddr_t)&tp->t_local, addr, sizeof(tp->t_local)))
89dc6dfb
BJ
519 u.u_error = EFAULT;
520 break;
521
50e2732b
BJ
522 /*
523 * Return number of characters in
524 * the output.
525 */
0dde1c43
BJ
526 case TIOCOUTQ:
527 if (copyout((caddr_t)&tp->t_outq.c_cc, addr, sizeof(tp->t_outq.c_cc)))
528 u.u_error = EFAULT;
529 break;
530
50e2732b
BJ
531 /*
532 * Simulate typing of a character at the terminal.
533 */
50450a20
BJ
534 case TIOCSTI:
535 c = fubyte(addr);
536 if (u.u_uid && u.u_ttyp != tp || c < 0)
537 u.u_error = EFAULT;
538 else
539 (*linesw[tp->t_line].l_rint)(c, tp);
540 break;
bfcf09ee
BJ
541
542 case TIOCSTOP:
543 c = spl5();
544 if ((tp->t_state & TS_TTSTOP) == 0) {
545 tp->t_state |= TS_TTSTOP;
546 (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
547 }
548 splx(c);
549 break;
550
551 case TIOCSTART:
552 c = spl5();
553 if ((tp->t_state & TS_TTSTOP) || (tp->t_local & LFLUSHO)) {
554 tp->t_state &= ~TS_TTSTOP;
555 tp->t_local &= ~LFLUSHO;
556 ttstart(tp);
557 }
558 splx(c);
559 break;
560
8062c8a7 561/* end of locals */
50450a20 562
89dc6dfb
BJ
563 default:
564 return(0);
565 }
566 return(1);
567}
e1d74936
BJ
568
569ttnread(tp)
570 struct tty *tp;
571{
572 int nread = 0;
573
574 if (tp->t_local & LPENDIN)
575 ttypend(tp);
576 nread = tp->t_canq.c_cc;
577 if (tp->t_flags & (RAW|CBREAK))
578 nread += tp->t_rawq.c_cc;
579 return (nread);
580}
581
941944c9 582ttselect(dev, rw)
e1d74936 583 dev_t dev;
941944c9 584 int rw;
e1d74936
BJ
585{
586 register struct tty *tp = &cdevsw[major(dev)].d_ttys[minor(dev)];
587 int nread;
941944c9 588 int s = spl5();
e1d74936 589
941944c9 590 switch (rw) {
e1d74936
BJ
591
592 case FREAD:
593 nread = ttnread(tp);
594 if (nread > 0)
941944c9 595 goto win;
89b8a44c 596 if (tp->t_rsel && tp->t_rsel->p_wchan == (caddr_t)&selwait)
941944c9 597 tp->t_state |= TS_RCOLL;
e1d74936
BJ
598 else
599 tp->t_rsel = u.u_procp;
941944c9 600 break;
e1d74936 601
941944c9
BJ
602 case FWRITE:
603 if (tp->t_outq.c_cc <= TTLOWAT(tp))
604 goto win;
941944c9
BJ
605 if (tp->t_wsel && tp->t_wsel->p_wchan == (caddr_t)&selwait)
606 tp->t_state |= TS_WCOLL;
607 else
608 tp->t_wsel = u.u_procp;
609 break;
e1d74936 610 }
941944c9
BJ
611 splx(s);
612 return (0);
613win:
614 splx(s);
615 return (1);
e1d74936 616}
8bba2b8f 617