reformat messages
[unix-history] / usr / src / sys / kern / tty.c
CommitLineData
0cbf0d70 1/* tty.c 4.3 %G% */
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"
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"
d1778415 18#include "../h/dk.h"
89dc6dfb
BJ
19
20char partab[];
21
d3ebf5ee
BJ
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
89dc6dfb
BJ
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
41char 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
0d65848d
BJ
60short tthiwat[16] =
61 { 100,100,100,100,100,100,100,200,200,400,400,400,650,650,650,650 };
62short ttlowat[16] =
63 { 30, 30, 30, 30, 30, 30, 30, 50, 50,120,120,120,125,125,125,125 };
64
89dc6dfb
BJ
65#define OBUFSIZ 100
66
89dc6dfb
BJ
67/*
68 * set default control characters.
69 */
70ttychars(tp)
71register struct tty *tp;
72{
8062c8a7 73
89dc6dfb
BJ
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;
8062c8a7 82/* begin local */
6fdc0335
BJ
83 tlun.t_suspc = CTRL(z);
84 tlun.t_dsuspc = CTRL(y);
8062c8a7
BJ
85 tlun.t_rprntc = CTRL(r);
86 tlun.t_flushc = CTRL(o);
87 tlun.t_werasc = CTRL(w);
88 tlun.t_lnextc = CTRL(v);
8062c8a7
BJ
89 tp->t_local = 0;
90 tp->t_lstate = 0;
91/* end local */
89dc6dfb
BJ
92}
93
94/*
50e2732b 95 * Wait for output to drain, then flush input waiting.
89dc6dfb 96 */
50e2732b 97wflushtty(tp)
89dc6dfb
BJ
98register struct tty *tp;
99{
100
50e2732b
BJ
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();
89dc6dfb
BJ
109}
110
111/*
50e2732b 112 * flush all TTY queues
89dc6dfb 113 */
50e2732b
BJ
114flushtty(tp, rw)
115register struct tty *tp;
89dc6dfb 116{
50e2732b
BJ
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);
89dc6dfb
BJ
143}
144
50e2732b
BJ
145/*
146 * Send stop character on input overflow.
147 */
148ttyblock(tp)
149register struct tty *tp;
89dc6dfb 150{
50e2732b
BJ
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 }
89dc6dfb
BJ
164}
165
101ba270 166/*
50e2732b
BJ
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.
101ba270 171 */
50e2732b 172ttrstrt(tp)
101ba270 173register struct tty *tp;
101ba270
BJ
174{
175
50e2732b
BJ
176 tp->t_state &= ~TIMEOUT;
177 ttstart(tp);
101ba270
BJ
178}
179
89dc6dfb 180/*
50e2732b
BJ
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.
89dc6dfb 185 */
50e2732b
BJ
186ttstart(tp)
187register struct tty *tp;
89dc6dfb 188{
50e2732b 189 register s;
8062c8a7 190
50e2732b
BJ
191 s = spl5();
192 if((tp->t_state&(TIMEOUT|TTSTOP|BUSY)) == 0)
193 (*tp->t_oproc)(tp);
194 splx(s);
89dc6dfb
BJ
195}
196
197/*
50e2732b 198 * Common code for tty ioctls.
89dc6dfb 199 */
49c84d3f 200/*ARGSUSED*/
0cbf0d70 201ttioctl(tp, com, addr, flag)
89dc6dfb
BJ
202register struct tty *tp;
203caddr_t addr;
204{
0cbf0d70 205 int dev;
89dc6dfb 206 unsigned t;
8062c8a7 207 struct sgttyb iocb;
de857265 208 struct clist tq;
89dc6dfb 209 extern int nldisp;
50450a20 210 register c;
da1392b6 211 int temp;
89dc6dfb 212
c6fe3a50
BJ
213 /*
214 * This is especially so that isatty() will
215 * fail when carrier is gone.
216 */
217 if ((tp->t_state&CARR_ON) == 0) {
218 u.u_error = EBADF;
219 return (1);
220 }
221
0cbf0d70 222 dev = tp->t_dev;
50e2732b
BJ
223 /*
224 * If the ioctl involves modification,
225 * insist on being able to write the device,
226 * and hang if in the background.
227 */
228 switch(com) {
229
c6fe3a50
BJ
230 case TIOCSETD:
231 case TIOCSETP:
232 case TIOCSETN:
50e2732b
BJ
233 case TIOCFLUSH:
234 case TIOCSETC:
235 case TIOCSLTC:
236 case TIOCSPGRP:
237 case TIOCLBIS:
238 case TIOCLBIC:
239 case TIOCLSET:
240 case TIOCSTI:
c6fe3a50 241/* this is reasonable, but impractical...
50e2732b
BJ
242 if ((flag & FWRITE) == 0) {
243 u.u_error = EBADF;
244 return (1);
245 }
c6fe3a50 246 */
50e2732b
BJ
247 while (tp->t_line == NTTYDISC &&
248 u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp &&
249 (u.u_procp->p_flag&SVFORK) == 0 &&
250 u.u_signal[SIGTTOU] != SIG_IGN &&
251 u.u_signal[SIGTTOU] != SIG_HOLD &&
252 (u.u_procp->p_flag&SDETACH)==0) {
253 gsignal(u.u_procp->p_pgrp, SIGTTOU);
254 sleep((caddr_t)&lbolt, TTOPRI);
255 }
256 break;
257 }
258
259 /*
260 * Process the ioctl.
261 */
89dc6dfb
BJ
262 switch(com) {
263
264 /*
50e2732b 265 * Get discipline number
89dc6dfb
BJ
266 */
267 case TIOCGETD:
268 t = tp->t_line;
269 if (copyout((caddr_t)&t, addr, sizeof(t)))
270 u.u_error = EFAULT;
271 break;
272
273 /*
50e2732b 274 * Set line discipline
89dc6dfb
BJ
275 */
276 case TIOCSETD:
277 if (copyin(addr, (caddr_t)&t, sizeof(t))) {
278 u.u_error = EFAULT;
279 break;
280 }
281 if (t >= nldisp) {
282 u.u_error = ENXIO;
283 break;
284 }
8062c8a7 285 (void) spl5();
89dc6dfb
BJ
286 if (tp->t_line)
287 (*linesw[tp->t_line].l_close)(tp);
288 if (t)
289 (*linesw[t].l_open)(dev, tp, addr);
290 if (u.u_error==0)
291 tp->t_line = t;
8062c8a7 292 (void) spl0();
89dc6dfb
BJ
293 break;
294
295 /*
50e2732b 296 * Prevent more opens on channel
89dc6dfb
BJ
297 */
298 case TIOCEXCL:
299 tp->t_state |= XCLUDE;
300 break;
301
302 case TIOCNXCL:
303 tp->t_state &= ~XCLUDE;
304 break;
305
306 /*
307 * Set new parameters
308 */
309 case TIOCSETP:
de857265 310 case TIOCSETN:
89dc6dfb
BJ
311 if (copyin(addr, (caddr_t)&iocb, sizeof(iocb))) {
312 u.u_error = EFAULT;
313 return(1);
314 }
101ba270 315 (void) spl5();
8062c8a7
BJ
316 if (tp->t_line == 0) {
317 if (com == TIOCSETP)
318 wflushtty(tp);
319 while (canon(tp)>=0)
320 ;
e7c0dc62
BJ
321#ifdef notdef
322 wakeup((caddr_t)&tp->t_rawq);
323#endif
8062c8a7
BJ
324 } else if (tp->t_line == NTTYDISC) {
325 if (tp->t_flags&RAW || iocb.sg_flags&RAW ||
326 com == TIOCSETP)
327 wflushtty(tp);
328 else if ((tp->t_flags&CBREAK) != (iocb.sg_flags&CBREAK)) {
329 if (iocb.sg_flags & CBREAK) {
330 catq(&tp->t_rawq, &tp->t_canq);
331 tq = tp->t_rawq;
332 tp->t_rawq = tp->t_canq;
333 tp->t_canq = tq;
334 } else {
335 tp->t_local |= LPENDIN;
336 if (tp->t_canq.c_cc)
337 panic("ioccom canq");
e7c0dc62 338#ifdef notdef
8062c8a7
BJ
339 if (tp->t_chan)
340 (void) sdata(tp->t_chan);
341 else
e7c0dc62 342#endif
8062c8a7
BJ
343 wakeup((caddr_t)&tp->t_rawq);
344 }
345 }
346 }
89dc6dfb 347 if ((tp->t_state&SPEEDS)==0) {
8062c8a7
BJ
348 tp->t_ispeed = iocb.sg_ispeed;
349 tp->t_ospeed = iocb.sg_ospeed;
89dc6dfb 350 }
8062c8a7
BJ
351 tp->t_erase = iocb.sg_erase;
352 tp->t_kill = iocb.sg_kill;
353 tp->t_flags = iocb.sg_flags;
101ba270 354 (void) spl0();
89dc6dfb
BJ
355 break;
356
357 /*
50e2732b 358 * Send current parameters to user
89dc6dfb
BJ
359 */
360 case TIOCGETP:
8062c8a7
BJ
361 iocb.sg_ispeed = tp->t_ispeed;
362 iocb.sg_ospeed = tp->t_ospeed;
363 iocb.sg_erase = tp->t_erase;
364 iocb.sg_kill = tp->t_kill;
365 iocb.sg_flags = tp->t_flags;
89dc6dfb
BJ
366 if (copyout((caddr_t)&iocb, addr, sizeof(iocb)))
367 u.u_error = EFAULT;
368 break;
369
370 /*
371 * Hang up line on last close
372 */
89dc6dfb
BJ
373 case TIOCHPCL:
374 tp->t_state |= HUPCLS;
375 break;
376
377 case TIOCFLUSH:
07f8c7d2 378 flushtty(tp, FREAD|FWRITE);
89dc6dfb
BJ
379 break;
380
89dc6dfb 381 /*
50e2732b 382 * Set and fetch special characters
89dc6dfb
BJ
383 */
384 case TIOCSETC:
8062c8a7 385 if (copyin(addr, (caddr_t)&tun, sizeof(struct tchars)))
89dc6dfb
BJ
386 u.u_error = EFAULT;
387 break;
388
389 case TIOCGETC:
8062c8a7
BJ
390 if (copyout((caddr_t)&tun, addr, sizeof(struct tchars)))
391 u.u_error = EFAULT;
392 break;
393
394/* local ioctls */
50e2732b
BJ
395 /*
396 * Set/get local special characters.
397 */
8062c8a7
BJ
398 case TIOCSLTC:
399 if (copyin(addr, (caddr_t)&tlun, sizeof (struct ltchars)))
400 u.u_error = EFAULT;
401 break;
402
403 case TIOCGLTC:
404 if (copyout((caddr_t)&tlun, addr, sizeof (struct ltchars)))
405 u.u_error = EFAULT;
406 break;
407
50e2732b
BJ
408 /*
409 * Return number of characters immediately available.
410 */
8062c8a7 411 case FIONREAD: {
d1778415 412 off_t nread;
8062c8a7 413
d1778415
BJ
414 switch (tp->t_line) {
415
416 case NETLDISC:
417 nread = tp->t_rec ? tp->t_inbuf : 0;
418 break;
419
6d27b2c6
BJ
420 case 0:
421 (void) spl5();
422 while (canon(tp)>=0)
423 ;
424 (void) spl0();
425 /* fall into ... */
426
d1778415
BJ
427 case NTTYDISC:
428 nread = tp->t_canq.c_cc;
429 if (tp->t_flags & (RAW|CBREAK))
430 nread += tp->t_rawq.c_cc;
431 break;
432
d1778415 433 }
8062c8a7
BJ
434 if (copyout((caddr_t)&nread, addr, sizeof (off_t)))
435 u.u_error = EFAULT;
436 break;
437 }
438
439 /*
440 * Should allow SPGRP and GPGRP only if tty open for reading.
441 */
442 case TIOCSPGRP:
da1392b6
BJ
443 if (copyin(addr, (caddr_t)&tp->t_pgrp, sizeof (tp->t_pgrp)))
444 u.u_error = EFAULT;
8062c8a7
BJ
445 break;
446
447 case TIOCGPGRP:
448 if (copyout((caddr_t)&tp->t_pgrp, addr, sizeof(tp->t_pgrp)))
449 u.u_error = EFAULT;
450 break;
451
452 /*
453 * Modify local mode word.
454 */
455 case TIOCLBIS:
da1392b6
BJ
456 if (copyin(addr, (caddr_t)&temp, sizeof (tp->t_local)))
457 u.u_error = EFAULT;
458 else
459 tp->t_local |= temp;
8062c8a7
BJ
460 break;
461
462 case TIOCLBIC:
da1392b6
BJ
463 if (copyin(addr, (caddr_t)&temp, sizeof (tp->t_local)))
464 u.u_error = EFAULT;
465 else
466 tp->t_local &= ~temp;
8062c8a7
BJ
467 break;
468
469 case TIOCLSET:
da1392b6
BJ
470 if (copyin(addr, (caddr_t)&temp, sizeof (tp->t_local)))
471 u.u_error = EFAULT;
472 else
473 tp->t_local = temp;
8062c8a7
BJ
474 break;
475
476 case TIOCLGET:
477 if (copyout((caddr_t)&tp->t_local, addr, sizeof(tp->t_local)))
89dc6dfb
BJ
478 u.u_error = EFAULT;
479 break;
480
50e2732b
BJ
481 /*
482 * Return number of characters in
483 * the output.
484 */
0dde1c43
BJ
485 case TIOCOUTQ:
486 if (copyout((caddr_t)&tp->t_outq.c_cc, addr, sizeof(tp->t_outq.c_cc)))
487 u.u_error = EFAULT;
488 break;
489
50e2732b
BJ
490 /*
491 * Simulate typing of a character at the terminal.
492 */
50450a20
BJ
493 case TIOCSTI:
494 c = fubyte(addr);
495 if (u.u_uid && u.u_ttyp != tp || c < 0)
496 u.u_error = EFAULT;
497 else
498 (*linesw[tp->t_line].l_rint)(c, tp);
499 break;
8062c8a7 500/* end of locals */
50450a20 501
89dc6dfb
BJ
502 default:
503 return(0);
504 }
505 return(1);
506}