merge with calder
[unix-history] / usr / src / sys / kern / tty.c
CommitLineData
4147b3f6 1/* tty.c 4.24 82/07/24 */
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
4147b3f6
BJ
618#define OBUFSIZ 100
619
620/*
621 * routine called on opens while tp->t_line == NTTYDISC
622 * establishes a process group for distribution of
623 * quits and interrupts from the tty.
624 * (actually, pp->p_pgrp can't be 0 when this routine
625 * is called since NTTYDISC is not the default discipline)
626 */
627ttyopen(dev, tp)
628dev_t dev;
629register struct tty *tp;
630{
631 register struct proc *pp;
632
633 pp = u.u_procp;
634 tp->t_dev = dev;
635 if(pp->p_pgrp == 0) {
636 u.u_ttyp = tp;
637 u.u_ttyd = dev;
638 if (tp->t_pgrp == 0)
639 tp->t_pgrp = pp->p_pid;
640 pp->p_pgrp = tp->t_pgrp;
641 }
642 tp->t_state &= ~TS_WOPEN;
643 tp->t_state |= TS_ISOPEN;
644 if (tp->t_line != NTTYDISC)
645 wflushtty(tp);
646}
647
648/*
649 * clean tp on last close
650 */
651ttyclose(tp)
652register struct tty *tp;
653{
654
655 if (tp->t_line) {
656 wflushtty(tp);
657 tp->t_line = 0;
658 return;
659 }
660 tp->t_pgrp = 0;
661 wflushtty(tp);
662 tp->t_state = 0;
663}
664
665/*
666 * reinput pending characters after state switch
667 * call at spl5().
668 */
669ttypend(tp)
670register struct tty *tp;
671{
672 struct clist tq;
673 register c;
674
675 tp->t_local &= ~LPENDIN;
676 tp->t_lstate |= LSTYPEN;
677 tq = tp->t_rawq;
678 tp->t_rawq.c_cc = 0;
679 tp->t_rawq.c_cf = tp->t_rawq.c_cl = 0;
680 while ((c = getc(&tq)) >= 0)
681 ttyinput(c, tp);
682 tp->t_lstate &= ~LSTYPEN;
683}
684
685/*
686 * Place a character on raw TTY input queue, putting in delimiters
687 * and waking up top half as needed.
688 * Also echo if required.
689 * The arguments are the character and the appropriate
690 * tty structure.
691 */
692ttyinput(c, tp)
693register c;
694register struct tty *tp;
695{
696 register int t_flags;
697 int i;
698
699 if (tp->t_local&LPENDIN)
700 ttypend(tp);
701 tk_nin++;
702 c &= 0377;
703 t_flags = tp->t_flags;
704 if (t_flags&TANDEM)
705 ttyblock(tp);
706 if ((t_flags&RAW)==0) {
707 if ((tp->t_lstate&LSTYPEN) == 0)
708 c &= 0177;
709 /* check for literal nexting very first */
710 if (tp->t_lstate&LSLNCH) {
711 c |= 0200;
712 tp->t_lstate &= ~LSLNCH;
713 }
714 if (tp->t_line == NTTYDISC && c==tlun.t_lnextc) {
715 if (tp->t_flags&ECHO)
716 ttyout("^\b", tp);
717 tp->t_lstate |= LSLNCH;
718 /* check for output control functions */
719 } else if (c==tun.t_stopc) {
720 if ((tp->t_state&TS_TTSTOP)==0) {
721 tp->t_state |= TS_TTSTOP;
722 (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
723 return;
724 }
725 if (c!=tun.t_startc)
726 return;
727 } else if (c==tun.t_startc) {
728 tp->t_state &= ~TS_TTSTOP;
729 tp->t_local &= ~LFLUSHO;
730 ttstart(tp);
731 return;
732 } else if (tp->t_line == NTTYDISC && c==tlun.t_flushc) {
733 if (tp->t_local & LFLUSHO)
734 tp->t_local &= ~LFLUSHO;
735 else {
736 flushtty(tp, FWRITE);
737 ttyecho(c, tp);
738 if (tp->t_rawq.c_cc+tp->t_canq.c_cc)
739 ttyretype(tp);
740 tp->t_local |= LFLUSHO;
741 }
742 ttstart(tp);
743 return;
744 } else if (c==tun.t_intrc || c==tun.t_quitc ||
745 (tp->t_line == NTTYDISC && c==tlun.t_suspc)) {
746 if ((tp->t_local & LNOFLSH) == 0)
747 flushtty(tp,
748 c==tlun.t_suspc ? FREAD : FREAD|FWRITE);
749 ttyecho(c, tp);
750 c = c==tun.t_intrc ? SIGINT :
751 ((c==tun.t_quitc) ? SIGQUIT : SIGTSTP);
752 ttsignal(tp, c);
753 /* check for buffer editing functions - cooked mode */
754 } else if ((t_flags&CBREAK) == 0) {
755 if ((tp->t_lstate&LSQUOT) &&
756 (c==tp->t_erase||c==tp->t_kill)) {
757 ttyrub(unputc(&tp->t_rawq), tp);
758 c |= 0200;
759 }
760 if (c==tp->t_erase) {
761 if (tp->t_rawq.c_cc)
762 ttyrub(unputc(&tp->t_rawq), tp);
763 } else if (c==tp->t_kill) {
764 if (tp->t_local&LCRTKIL &&
765 tp->t_rawq.c_cc == tp->t_rocount) {
766 while (tp->t_rawq.c_cc)
767 ttyrub(unputc(&tp->t_rawq), tp);
768 } else {
769 ttyecho(c, tp);
770 ttyecho('\n', tp);
771 while (getc(&tp->t_rawq) > 0)
772 ;
773 tp->t_rocount = 0;
774 }
775 tp->t_lstate = 0;
776 } else if (tp->t_line == NTTYDISC && c==tlun.t_werasc) {
777 if (tp->t_rawq.c_cc == 0)
778 goto out;
779 do {
780 c = unputc(&tp->t_rawq);
781 if (c != ' ' && c != '\t')
782 goto erasenb;
783 ttyrub(c, tp);
784 } while (tp->t_rawq.c_cc);
785 goto out;
786 erasenb:
787 do {
788 ttyrub(c, tp);
789 if (tp->t_rawq.c_cc == 0)
790 goto out;
791 c = unputc(&tp->t_rawq);
792 } while (c != ' ' && c != '\t');
793 (void) putc(c, &tp->t_rawq);
794 } else if (tp->t_line == NTTYDISC && c==tlun.t_rprntc) {
795 ttyretype(tp);
796 /* check for cooked mode input buffer overflow */
797 } else if (tp->t_rawq.c_cc+tp->t_canq.c_cc >= TTYHOG) {
798 ;
799 /* put data char in q for user and wakeup if a break char */
800 } else if (putc(c, &tp->t_rawq) >= 0) {
801 if (tp->t_rawq.c_cc+tp->t_canq.c_cc==TTYHOG
802 && tp->t_line == NTTYDISC)
803 (void) ttyoutput(CTRL(g), tp);
804 if (!ttbreakc(c, tp)) {
805 if (tp->t_rocount++ == 0)
806 tp->t_rocol = tp->t_col;
807 } else {
808 tp->t_rocount = 0;
809 catq(&tp->t_rawq, &tp->t_canq);
810 /* IF (TP->T_CHAN) (VOID) SDATA(TP->T_CHAN); */
811 ttwakeup(tp);
812 }
813 tp->t_lstate &= ~LSQUOT;
814 if (c == '\\')
815 tp->t_lstate |= LSQUOT;
816 if (tp->t_lstate&LSERASE) {
817 tp->t_lstate &= ~LSERASE;
818 (void) ttyoutput('/', tp);
819 }
820 i = tp->t_col;
821 ttyecho(c, tp);
822 if (c==tun.t_eofc && tp->t_flags&ECHO) {
823 i = MIN(2, tp->t_col - i);
824 while (i > 0) {
825 (void) ttyoutput('\b', tp);
826 i--;
827 }
828 }
829 }
830 /* CBREAK mode */
831 } else if (tp->t_rawq.c_cc > TTYHOG) {
832 if (tp->t_outq.c_cc < TTHIWAT(tp) &&
833 tp->t_line == NTTYDISC)
834 (void) ttyoutput(CTRL(g), tp);
835 } else if (putc(c, &tp->t_rawq) >= 0) {
836 ttwakeup(tp);
837 ttyecho(c, tp);
838 }
839 /* RAW mode */
840 } else if (tp->t_rawq.c_cc > TTYHOG)
841 flushtty(tp, FREAD|FWRITE);
842 else {
843 if (putc(c, &tp->t_rawq) >= 0)
844 ttwakeup(tp);
845 ttyecho(c, tp);
846 }
847out:
848 if (tp->t_local & LDECCTQ && tp->t_state & TS_TTSTOP &&
849 tun.t_startc != tun.t_stopc)
850 return;
851 tp->t_state &= ~TS_TTSTOP;
852 tp->t_local &= ~LFLUSHO;
853 ttstart(tp);
854}
855
856/*
857 * put character on TTY output queue, adding delays,
858 * expanding tabs, and handling the CR/NL bit.
859 * It is called both from the top half for output, and from
860 * interrupt level for echoing.
861 * The arguments are the character and the tty structure.
862 * Returns < 0 if putc succeeds, otherwise returns char to resend
863 * Must be recursive.
864 */
865ttyoutput(c, tp)
866 register c;
867 register struct tty *tp;
868{
869 register char *colp;
870 register ctype;
871
872 if (tp->t_flags&RAW || tp->t_local&LLITOUT) {
873 if (tp->t_local&LFLUSHO)
874 return (-1);
875 if (putc(c, &tp->t_outq))
876 return(c);
877 tk_nout++;
878 return (-1);
879 }
880 /*
881 * Ignore EOT in normal mode to avoid hanging up
882 * certain terminals.
883 */
884 c &= 0177;
885 if (c==CEOT && (tp->t_flags&CBREAK)==0)
886 return (-1);
887 /*
888 * Turn tabs to spaces as required
889 */
890 if (c=='\t' && (tp->t_flags&TBDELAY)==XTABS) {
891 register int s;
892
893 c = 8 - (tp->t_col&7);
894 if ((tp->t_local&LFLUSHO) == 0) {
895 s = spl5(); /* don't interrupt tabs */
896 c -= b_to_q(" ", c, &tp->t_outq);
897 tk_nout += c;
898 splx(s);
899 }
900 tp->t_col += c;
901 return (c ? -1 : '\t');
902 }
903 tk_nout++;
904 /*
905 * for upper-case-only terminals,
906 * generate escapes.
907 */
908 if (tp->t_flags&LCASE) {
909 colp = "({)}!|^~'`";
910 while(*colp++)
911 if(c == *colp++) {
912 if (ttyoutput('\\', tp) >= 0)
913 return (c);
914 c = colp[-2];
915 break;
916 }
917 if ('A'<=c && c<='Z') {
918 if (ttyoutput('\\', tp) >= 0)
919 return (c);
920 } else if ('a'<=c && c<='z')
921 c += 'A' - 'a';
922 }
923 /*
924 * turn <nl> to <cr><lf> if desired.
925 */
926 if (c=='\n' && tp->t_flags&CRMOD)
927 if (ttyoutput('\r', tp) >= 0)
928 return (c);
929 if (c=='~' && tp->t_local&LTILDE)
930 c = '`';
931 if ((tp->t_local&LFLUSHO) == 0 && putc(c, &tp->t_outq))
932 return (c);
933 /*
934 * Calculate delays.
935 * The numbers here represent clock ticks
936 * and are not necessarily optimal for all terminals.
937 * The delays are indicated by characters above 0200.
938 * In raw mode there are no delays and the
939 * transmission path is 8 bits wide.
940 */
941 colp = &tp->t_col;
942 ctype = partab[c];
943 c = 0;
944 switch (ctype&077) {
945
946 case ORDINARY:
947 (*colp)++;
948
949 case CONTROL:
950 break;
951
952 case BACKSPACE:
953 if (*colp)
954 (*colp)--;
955 break;
956
957 case NEWLINE:
958 ctype = (tp->t_flags >> 8) & 03;
959 if(ctype == 1) { /* tty 37 */
960 if (*colp)
961 c = max(((unsigned)*colp>>4) + 3, (unsigned)6);
962 } else
963 if(ctype == 2) { /* vt05 */
964 c = 6;
965 }
966 *colp = 0;
967 break;
968
969 case TAB:
970 ctype = (tp->t_flags >> 10) & 03;
971 if(ctype == 1) { /* tty 37 */
972 c = 1 - (*colp | ~07);
973 if(c < 5)
974 c = 0;
975 }
976 *colp |= 07;
977 (*colp)++;
978 break;
979
980 case VTAB:
981 if(tp->t_flags & VTDELAY) /* tty 37 */
982 c = 0177;
983 break;
984
985 case RETURN:
986 ctype = (tp->t_flags >> 12) & 03;
987 if(ctype == 1) { /* tn 300 */
988 c = 5;
989 } else if(ctype == 2) { /* ti 700 */
990 c = 10;
991 } else if(ctype == 3) { /* concept 100 */
992 int i;
993 if ((i = *colp) >= 0)
994 for (; i<9; i++)
995 (void) putc(0177, &tp->t_outq);
996 }
997 *colp = 0;
998 }
999 if(c && (tp->t_local&LFLUSHO) == 0)
1000 (void) putc(c|0200, &tp->t_outq);
1001 return (-1);
1002}
1003
1004/*
1005 * Called from device's read routine after it has
1006 * calculated the tty-structure given as argument.
1007 */
1008ttread(tp)
1009register struct tty *tp;
1010{
1011 register struct clist *qp;
1012 register c, first;
1013
1014 if ((tp->t_state&TS_CARR_ON)==0)
1015 return(0);
1016loop:
1017 (void) spl5();
1018 if (tp->t_local&LPENDIN)
1019 ttypend(tp);
1020 (void) spl0();
1021 while (tp == u.u_ttyp && u.u_procp->p_pgrp != tp->t_pgrp) {
1022 if (u.u_signal[SIGTTIN] == SIG_IGN ||
1023 u.u_signal[SIGTTIN] == SIG_HOLD ||
1024/*
1025 (u.u_procp->p_flag&SDETACH) ||
1026*/
1027 u.u_procp->p_flag&SVFORK)
1028 return (0);
1029 gsignal(u.u_procp->p_pgrp, SIGTTIN);
1030 sleep((caddr_t)&lbolt, TTIPRI);
1031 }
1032 if (tp->t_flags&RAW) {
1033 (void) spl5();
1034 if (tp->t_rawq.c_cc <= 0) {
1035 if ((tp->t_state&TS_CARR_ON)==0 ||
1036 (tp->t_state&TS_NBIO)) {
1037 (void) spl0();
1038 return (0);
1039 }
1040 sleep((caddr_t)&tp->t_rawq, TTIPRI);
1041 (void) spl0();
1042 goto loop;
1043 }
1044 (void) spl0();
1045 while (tp->t_rawq.c_cc && passc(getc(&tp->t_rawq))>=0)
1046 ;
1047 return (0);
1048 } else {
1049 qp = tp->t_flags & CBREAK ? &tp->t_rawq : &tp->t_canq;
1050 (void) spl5();
1051 if (qp->c_cc <= 0) {
1052 if ((tp->t_state&TS_CARR_ON)==0 ||
1053 (tp->t_state&TS_NBIO)) {
1054 (void) spl0();
1055 return (0);
1056 }
1057 sleep((caddr_t)&tp->t_rawq, TTIPRI);
1058 (void) spl0();
1059 goto loop;
1060 }
1061 (void) spl0();
1062 first = 1;
1063 while ((c = getc(qp)) >= 0) {
1064 if (tp->t_flags&CRMOD && c == '\r')
1065 c = '\n';
1066 if (tp->t_flags&LCASE && c <= 0177)
1067 if (tp->t_lstate&LSBKSL) {
1068 if (maptab[c])
1069 c = maptab[c];
1070 tp->t_lstate &= ~LSBKSL;
1071 } else if (c >= 'A' && c <= 'Z')
1072 c += 'a' - 'A';
1073 else if (c == '\\') {
1074 tp->t_lstate |= LSBKSL;
1075 continue;
1076 }
1077 if (c == tlun.t_dsuspc) {
1078 ttsignal(tp, SIGTSTP);
1079 if (first) {
1080 sleep((caddr_t)&lbolt, TTIPRI);
1081 goto loop;
1082 }
1083 break;
1084 }
1085 if (c == tun.t_eofc && (tp->t_flags&CBREAK)==0)
1086 break;
1087 if (passc(c & 0177) < 0)
1088 break;
1089 if ((tp->t_flags&CBREAK)==0 && ttbreakc(c, tp))
1090 break;
1091 first = 0;
1092 }
1093 tp->t_lstate &= ~LSBKSL;
1094 }
1095
1096 if (tp->t_state&TS_TBLOCK && tp->t_rawq.c_cc < TTYHOG/5) {
1097 if (putc(tun.t_startc, &tp->t_outq)==0) {
1098 tp->t_state &= ~TS_TBLOCK;
1099 ttstart(tp);
1100 }
1101 tp->t_char = 0;
1102 }
1103
1104 return (tp->t_rawq.c_cc + tp->t_canq.c_cc);
1105}
1106
1107/*
1108 * Called from the device's write routine after it has
1109 * calculated the tty-structure given as argument.
1110 */
1111caddr_t
1112ttwrite(tp)
1113register struct tty *tp;
1114{
1115#ifdef vax
1116 /*
1117 * THE POSITIONING OF CP, CC, AND CE ARE CRITICAL
1118 * AND MUST NOT BE CHANGED WITHOUT PATCHING
1119 * THE 'ASM' INLINES BELOW. WATCH OUT.
1120 */
1121#endif
1122 register char *cp;
1123 register int cc, ce;
1124 register i;
1125 char obuf[OBUFSIZ];
1126 register c;
1127 int hiwat = TTHIWAT(tp);
1128 int cnt = u.u_count;
1129
1130 if ((tp->t_state&TS_CARR_ON)==0)
1131 return (NULL);
1132loop:
1133 while (u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp &&
1134 (tp->t_local&LTOSTOP) && (u.u_procp->p_flag&SVFORK)==0 &&
1135 u.u_signal[SIGTTOU] != SIG_IGN &&
1136 u.u_signal[SIGTTOU] != SIG_HOLD
1137/*
1138 &&
1139 (u.u_procp->p_flag&SDETACH)==0) {
1140*/
1141 ) {
1142 gsignal(u.u_procp->p_pgrp, SIGTTOU);
1143 sleep((caddr_t)&lbolt, TTIPRI);
1144 }
1145 while (u.u_count) {
1146 cc = MIN(u.u_count, OBUFSIZ);
1147 cp = obuf;
1148 iomove(cp, (unsigned)cc, B_WRITE);
1149 if (u.u_error)
1150 break;
1151 if (tp->t_outq.c_cc > hiwat)
1152 goto ovhiwat;
1153 if (tp->t_local&LFLUSHO)
1154 continue;
1155 if (tp->t_flags&LCASE || tp->t_local&LTILDE) {
1156 while (cc) {
1157 c = *cp++;
1158 tp->t_rocount = 0;
1159 while((c = ttyoutput(c, tp)) >= 0) {
1160 /* out of clists, wait a bit */
1161 ttstart(tp);
1162 sleep((caddr_t)&lbolt, TTOPRI);
1163 tp->t_rocount = 0;
1164 }
1165 --cc;
1166 if (tp->t_outq.c_cc > hiwat)
1167 goto ovhiwat;
1168 }
1169 continue;
1170 }
1171 while (cc) {
1172 if (tp->t_flags&RAW || tp->t_local&LLITOUT)
1173 ce = cc;
1174 else {
1175#ifdef vax
1176 asm(" scanc r9,(r10),_partab,$077");
1177 asm(" subl3 r0,r9,r8");
1178#else
1179 ce=0;
1180 while(((partab[*(unsigned char *)(cp+ce)]&077)==0)&&(ce<cc))
1181 ce++;
1182#endif
1183 if (ce==0) {
1184 tp->t_rocount = 0;
1185 if (ttyoutput(*cp, tp) >= 0) {
1186 ttstart(tp);
1187 sleep((caddr_t)&lbolt, TTOPRI);
1188 continue;
1189 }
1190 cp++;
1191 cc--;
1192 if (tp->t_outq.c_cc > hiwat)
1193 goto ovhiwat;
1194 }
1195 }
1196 tp->t_rocount = 0;
1197 i=b_to_q(cp,ce,&tp->t_outq);
1198 ce-=i;
1199 tk_nout+=ce;
1200 tp->t_col+=ce;
1201 cp+=ce;
1202 cc-=ce;
1203 if (i) {
1204 ttstart(tp);
1205 sleep((caddr_t)&lbolt, TTOPRI);
1206 }
1207 if (ce || tp->t_outq.c_cc > hiwat)
1208 goto ovhiwat;
1209 }
1210 }
1211 ttstart(tp);
1212 return(NULL);
1213
1214ovhiwat:
1215 (void) spl5();
1216 u.u_base -= cc;
1217 u.u_offset -= cc;
1218 u.u_count += cc;
1219 if (tp->t_outq.c_cc <= hiwat) {
1220 (void) spl0();
1221 goto loop;
1222 }
1223 ttstart(tp);
1224 if (tp->t_state & TS_NBIO) {
1225 if (u.u_count == cnt)
1226 u.u_error = EWOULDBLOCK;
1227 return (NULL);
1228 }
1229 tp->t_state |= TS_ASLEEP;
1230 sleep((caddr_t)&tp->t_outq, TTOPRI);
1231 (void) spl0();
1232 goto loop;
1233}
1234
1235/*
1236 * Rubout one character from the rawq of tp
1237 * as cleanly as possible.
1238 */
1239ttyrub(c, tp)
1240register c;
1241register struct tty *tp;
1242{
1243 register char *cp;
1244 register int savecol;
1245 int s;
1246 char *nextc();
1247
1248 if ((tp->t_flags&ECHO)==0)
1249 return;
1250 tp->t_local &= ~LFLUSHO;
1251 c &= 0377;
1252 if (tp->t_local&LCRTBS) {
1253 if (tp->t_rocount == 0) {
1254 /*
1255 * Screwed by ttwrite; retype
1256 */
1257 ttyretype(tp);
1258 return;
1259 }
1260 if (c==('\t'|0200) || c==('\n'|0200))
1261 ttyrubo(tp, 2);
1262 else switch(partab[c&=0177] & 0177) {
1263
1264 case ORDINARY:
1265 if (tp->t_flags&LCASE && c >= 'A' && c <= 'Z')
1266 ttyrubo(tp, 2);
1267 else
1268 ttyrubo(tp, 1);
1269 break;
1270
1271 case VTAB:
1272 case BACKSPACE:
1273 case CONTROL:
1274 case RETURN:
1275 if (tp->t_local & LCTLECH)
1276 ttyrubo(tp, 2);
1277 break;
1278
1279 case TAB:
1280 if (tp->t_rocount < tp->t_rawq.c_cc) {
1281 ttyretype(tp);
1282 return;
1283 }
1284 s = spl5();
1285 savecol = tp->t_col;
1286 tp->t_lstate |= LSCNTTB;
1287 tp->t_local |= LFLUSHO;
1288 tp->t_col = tp->t_rocol;
1289 for (cp = tp->t_rawq.c_cf; cp; cp = nextc(&tp->t_rawq, cp))
1290 ttyecho(*cp, tp);
1291 tp->t_local &= ~LFLUSHO;
1292 tp->t_lstate &= ~LSCNTTB;
1293 splx(s);
1294 /*
1295 * savecol will now be length of the tab
1296 */
1297 savecol -= tp->t_col;
1298 tp->t_col += savecol;
1299 if (savecol > 8)
1300 savecol = 8; /* overflow screw */
1301 while (--savecol >= 0)
1302 (void) ttyoutput('\b', tp);
1303 break;
1304
1305 default:
1306 panic("ttyrub");
1307 }
1308 } else if (tp->t_local&LPRTERA) {
1309 if ((tp->t_lstate&LSERASE) == 0) {
1310 (void) ttyoutput('\\', tp);
1311 tp->t_lstate |= LSERASE;
1312 }
1313 ttyecho(c, tp);
1314 } else
1315 ttyecho(tp->t_erase, tp);
1316 tp->t_rocount--;
1317}
1318
1319/*
1320 * Crt back over cnt chars perhaps
1321 * erasing them.
1322 */
1323ttyrubo(tp, cnt)
1324register struct tty *tp;
1325int cnt;
1326{
1327
1328 while (--cnt >= 0)
1329 ttyout(tp->t_local&LCRTERA ? "\b \b" : "\b", tp);
1330}
1331
1332/*
1333 * Reprint the rawq line.
1334 * We assume c_cc has already been checked.
1335 */
1336ttyretype(tp)
1337register struct tty *tp;
1338{
1339 register char *cp;
1340 char *nextc();
1341 int s;
1342
1343 if (tlun.t_rprntc != 0377)
1344 ttyecho(tlun.t_rprntc, tp);
1345 (void) ttyoutput('\n', tp);
1346 s = spl5();
1347 for (cp = tp->t_canq.c_cf; cp; cp = nextc(&tp->t_canq, cp))
1348 ttyecho(*cp, tp);
1349 for (cp = tp->t_rawq.c_cf; cp; cp = nextc(&tp->t_rawq, cp))
1350 ttyecho(*cp, tp);
1351 tp->t_lstate &= ~LSERASE;
1352 splx(s);
1353 tp->t_rocount = tp->t_rawq.c_cc;
1354 tp->t_rocol = 0;
1355}
1356
1357/*
1358 * Echo a typed character to the terminal
1359 */
1360ttyecho(c, tp)
1361register c;
1362register struct tty *tp;
1363{
1364
1365 if ((tp->t_lstate & LSCNTTB) == 0)
1366 tp->t_local &= ~LFLUSHO;
1367 if ((tp->t_flags&ECHO) == 0)
1368 return;
1369 c &= 0377;
1370 if (tp->t_flags&RAW) {
1371 (void) ttyoutput(c, tp);
1372 return;
1373 }
1374 if (c == '\r' && tp->t_flags&CRMOD)
1375 c = '\n';
1376 if (tp->t_local&LCTLECH) {
1377 if ((c&0177) <= 037 && c!='\t' && c!='\n' || (c&0177)==0177) {
1378 (void) ttyoutput('^', tp);
1379 c &= 0177;
1380 if (c == 0177)
1381 c = '?';
1382 else if (tp->t_flags&LCASE)
1383 c += 'a' - 1;
1384 else
1385 c += 'A' - 1;
1386 }
1387 }
1388 if ((tp->t_flags&LCASE) && (c >= 'A' && c <= 'Z'))
1389 c += 'a' - 'A';
1390 (void) ttyoutput(c & 0177, tp);
1391}
1392
1393/*
1394 * Is c a break char for tp?
1395 */
1396ttbreakc(c, tp)
1397register c;
1398register struct tty *tp;
1399{
1400 return (c == '\n' || c == tun.t_eofc || c == tun.t_brkc ||
1401 c == '\r' && (tp->t_flags&CRMOD));
1402}
1403
1404/*
1405 * send string cp to tp
1406 */
1407ttyout(cp, tp)
1408register char *cp;
1409register struct tty *tp;
1410{
1411 register char c;
1412
1413 while (c = *cp++)
1414 (void) ttyoutput(c, tp);
1415}
1416
1417ttwakeup(tp)
1418 struct tty *tp;
1419{
1420
1421 if (tp->t_rsel) {
1422 selwakeup(tp->t_rsel, tp->t_state&TS_RCOLL);
1423 tp->t_state &= ~TS_RCOLL;
1424 tp->t_rsel = 0;
1425 }
1426 wakeup((caddr_t)&tp->t_rawq);
1427}
1428
1429ttsignal(tp, signo)
1430 struct tty *tp;
1431 int signo;
1432{
1433
1434 gsignal(tp->t_pgrp, signo);
1435}