typo
[unix-history] / usr / src / sys / kern / tty.c
CommitLineData
a8d3bf7f 1/* tty.c 4.32 82/10/17 */
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"
d6d7360b 18#include "../h/uio.h"
894cfdb7 19#include "../h/kernel.h"
89dc6dfb 20
8bba2b8f
RE
21/*
22 * Table giving parity for characters and indicating
23 * character classes to tty driver. In particular,
24 * if the low 6 bits are 0, then the character needs
25 * no special processing on output.
26 */
27
28char partab[] = {
29 0001,0201,0201,0001,0201,0001,0001,0201,
30 0202,0004,0003,0201,0005,0206,0201,0001,
31 0201,0001,0001,0201,0001,0201,0201,0001,
32 0001,0201,0201,0001,0201,0001,0001,0201,
33 0200,0000,0000,0200,0000,0200,0200,0000,
34 0000,0200,0200,0000,0200,0000,0000,0200,
35 0000,0200,0200,0000,0200,0000,0000,0200,
36 0200,0000,0000,0200,0000,0200,0200,0000,
37 0200,0000,0000,0200,0000,0200,0200,0000,
38 0000,0200,0200,0000,0200,0000,0000,0200,
39 0000,0200,0200,0000,0200,0000,0000,0200,
40 0200,0000,0000,0200,0000,0200,0200,0000,
41 0000,0200,0200,0000,0200,0000,0000,0200,
42 0200,0000,0000,0200,0000,0200,0200,0000,
43 0200,0000,0000,0200,0000,0200,0200,0000,
44 0000,0200,0200,0000,0200,0000,0000,0201,
45
46 /*
47 * 7 bit ascii ends with the last character above,
48 * but we contine through all 256 codes for the sake
49 * of the tty output routines which use special vax
50 * instructions which need a 256 character trt table.
51 */
52
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 0007,0007,0007,0007,0007,0007,0007,0007,
68 0007,0007,0007,0007,0007,0007,0007,0007
69};
89dc6dfb 70
89dc6dfb
BJ
71/*
72 * Input mapping table-- if an entry is non-zero, when the
73 * corresponding character is typed preceded by "\" the escape
74 * sequence is replaced by the table value. Mostly used for
75 * upper-case only terminals.
76 */
77
78char maptab[] ={
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,000,000,
82 000,000,000,000,000,000,000,000,
83 000,'|',000,000,000,000,000,'`',
84 '{','}',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,000,
89 000,000,000,000,000,000,000,000,
90 000,000,000,000,000,000,'~',000,
91 000,'A','B','C','D','E','F','G',
92 'H','I','J','K','L','M','N','O',
93 'P','Q','R','S','T','U','V','W',
94 'X','Y','Z',000,000,000,000,000,
95};
96
0d65848d
BJ
97short tthiwat[16] =
98 { 100,100,100,100,100,100,100,200,200,400,400,400,650,650,650,650 };
99short ttlowat[16] =
100 { 30, 30, 30, 30, 30, 30, 30, 50, 50,120,120,120,125,125,125,125 };
101
89dc6dfb
BJ
102#define OBUFSIZ 100
103
89dc6dfb
BJ
104/*
105 * set default control characters.
106 */
107ttychars(tp)
4b72e2f9 108 register struct tty *tp;
89dc6dfb 109{
8062c8a7 110
89dc6dfb
BJ
111 tun.t_intrc = CINTR;
112 tun.t_quitc = CQUIT;
113 tun.t_startc = CSTART;
114 tun.t_stopc = CSTOP;
115 tun.t_eofc = CEOT;
116 tun.t_brkc = CBRK;
117 tp->t_erase = CERASE;
118 tp->t_kill = CKILL;
8062c8a7 119/* begin local */
6fdc0335
BJ
120 tlun.t_suspc = CTRL(z);
121 tlun.t_dsuspc = CTRL(y);
8062c8a7
BJ
122 tlun.t_rprntc = CTRL(r);
123 tlun.t_flushc = CTRL(o);
124 tlun.t_werasc = CTRL(w);
125 tlun.t_lnextc = CTRL(v);
8062c8a7
BJ
126 tp->t_local = 0;
127 tp->t_lstate = 0;
128/* end local */
89dc6dfb
BJ
129}
130
131/*
50e2732b 132 * Wait for output to drain, then flush input waiting.
89dc6dfb 133 */
50e2732b 134wflushtty(tp)
941944c9 135 register struct tty *tp;
89dc6dfb
BJ
136{
137
50e2732b 138 (void) spl5();
4c67f645
BJ
139 while (tp->t_outq.c_cc && tp->t_state&TS_CARR_ON
140 && tp->t_oproc) { /* kludge for pty */
50e2732b 141 (*tp->t_oproc)(tp);
941944c9 142 tp->t_state |= TS_ASLEEP;
50e2732b
BJ
143 sleep((caddr_t)&tp->t_outq, TTOPRI);
144 }
39697bd8 145 flushtty(tp, FREAD);
50e2732b 146 (void) spl0();
89dc6dfb
BJ
147}
148
149/*
50e2732b 150 * flush all TTY queues
89dc6dfb 151 */
50e2732b 152flushtty(tp, rw)
4b72e2f9 153 register struct tty *tp;
89dc6dfb 154{
50e2732b
BJ
155 register s;
156
50e2732b
BJ
157 s = spl6();
158 if (rw & FREAD) {
159 while (getc(&tp->t_canq) >= 0)
160 ;
161 wakeup((caddr_t)&tp->t_rawq);
162 }
163 if (rw & FWRITE) {
164 wakeup((caddr_t)&tp->t_outq);
941944c9 165 tp->t_state &= ~TS_TTSTOP;
39697bd8 166 (*cdevsw[major(tp->t_dev)].d_stop)(tp, rw);
50e2732b
BJ
167 while (getc(&tp->t_outq) >= 0)
168 ;
169 }
170 if (rw & FREAD) {
171 while (getc(&tp->t_rawq) >= 0)
172 ;
173 tp->t_delct = 0;
174 tp->t_rocount = 0; /* local */
175 tp->t_rocol = 0;
176 tp->t_lstate = 0;
177 }
178 splx(s);
89dc6dfb
BJ
179}
180
50e2732b
BJ
181/*
182 * Send stop character on input overflow.
183 */
184ttyblock(tp)
4b72e2f9 185 register struct tty *tp;
89dc6dfb 186{
50e2732b
BJ
187 register x;
188 x = tp->t_rawq.c_cc + tp->t_canq.c_cc;
189 if (tp->t_rawq.c_cc > TTYHOG) {
190 flushtty(tp, FREAD|FWRITE);
941944c9 191 tp->t_state &= ~TS_TBLOCK;
50e2732b
BJ
192 }
193 if (x >= TTYHOG/2) {
194 if (putc(tun.t_stopc, &tp->t_outq)==0) {
941944c9 195 tp->t_state |= TS_TBLOCK;
50e2732b
BJ
196 tp->t_char++;
197 ttstart(tp);
198 }
199 }
89dc6dfb
BJ
200}
201
101ba270 202/*
50e2732b
BJ
203 * Restart typewriter output following a delay
204 * timeout.
205 * The name of the routine is passed to the timeout
206 * subroutine and it is called during a clock interrupt.
101ba270 207 */
50e2732b 208ttrstrt(tp)
4b72e2f9 209 register struct tty *tp;
101ba270
BJ
210{
211
545f5350
BJ
212 if (tp == 0) {
213 printf("ttrstrt: arg was 0!\n");
214 return;
215 }
941944c9 216 tp->t_state &= ~TS_TIMEOUT;
50e2732b 217 ttstart(tp);
101ba270
BJ
218}
219
89dc6dfb 220/*
50e2732b
BJ
221 * Start output on the typewriter. It is used from the top half
222 * after some characters have been put on the output queue,
223 * from the interrupt routine to transmit the next
224 * character, and after a timeout has finished.
89dc6dfb 225 */
50e2732b 226ttstart(tp)
4b72e2f9 227 register struct tty *tp;
89dc6dfb 228{
50e2732b 229 register s;
8062c8a7 230
50e2732b 231 s = spl5();
4b72e2f9 232 if ((tp->t_state&(TS_TIMEOUT|TS_TTSTOP|TS_BUSY)) == 0 &&
4c67f645 233 tp->t_oproc) /* kludge for pty */
50e2732b
BJ
234 (*tp->t_oproc)(tp);
235 splx(s);
89dc6dfb
BJ
236}
237
238/*
50e2732b 239 * Common code for tty ioctls.
89dc6dfb 240 */
49c84d3f 241/*ARGSUSED*/
4b72e2f9
SL
242ttioctl(tp, com, data, flag)
243 register struct tty *tp;
244 caddr_t data;
89dc6dfb 245{
840510a3 246 int dev = tp->t_dev;
89dc6dfb 247 extern int nldisp;
fc6972ae 248 int s;
89dc6dfb 249
50e2732b
BJ
250 /*
251 * If the ioctl involves modification,
252 * insist on being able to write the device,
253 * and hang if in the background.
254 */
4b72e2f9 255 switch (com) {
50e2732b 256
c6fe3a50
BJ
257 case TIOCSETD:
258 case TIOCSETP:
259 case TIOCSETN:
50e2732b
BJ
260 case TIOCFLUSH:
261 case TIOCSETC:
262 case TIOCSLTC:
263 case TIOCSPGRP:
264 case TIOCLBIS:
265 case TIOCLBIC:
266 case TIOCLSET:
50e2732b
BJ
267 while (tp->t_line == NTTYDISC &&
268 u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp &&
269 (u.u_procp->p_flag&SVFORK) == 0 &&
270 u.u_signal[SIGTTOU] != SIG_IGN &&
fc6972ae 271 u.u_signal[SIGTTOU] != SIG_HOLD) {
50e2732b
BJ
272 gsignal(u.u_procp->p_pgrp, SIGTTOU);
273 sleep((caddr_t)&lbolt, TTOPRI);
274 }
275 break;
276 }
277
4b72e2f9 278 switch (com) {
89dc6dfb 279
fc6972ae 280 /* get discipline number */
89dc6dfb 281 case TIOCGETD:
4b72e2f9 282 *(int *)data = tp->t_line;
89dc6dfb
BJ
283 break;
284
fc6972ae 285 /* set line discipline */
4b72e2f9
SL
286 case TIOCSETD: {
287 register int t = *(int *)data;
fc6972ae 288 int error;
4b72e2f9 289
fc6972ae
BJ
290 if (t >= nldisp)
291 return (ENXIO);
292 s = spl5();
89dc6dfb
BJ
293 if (tp->t_line)
294 (*linesw[tp->t_line].l_close)(tp);
295 if (t)
fc6972ae
BJ
296 error = (*linesw[t].l_open)(dev, tp);
297 splx(s);
298 if (error)
299 return (error);
300 tp->t_line = t;
89dc6dfb 301 break;
4b72e2f9 302 }
89dc6dfb 303
fc6972ae 304 /* prevent more opens on channel */
152c2598
BJ
305 case TIOCEXCL:
306 tp->t_state |= TS_XCLUDE;
307 break;
308
309 case TIOCNXCL:
310 tp->t_state &= ~TS_XCLUDE;
311 break;
312
fc6972ae 313 /* set new parameters */
89dc6dfb 314 case TIOCSETP:
4b72e2f9
SL
315 case TIOCSETN: {
316 register struct sgttyb *sg = (struct sgttyb *)data;
317 struct clist tq;
318
101ba270 319 (void) spl5();
4b72e2f9 320 if (tp->t_flags&RAW || sg->sg_flags&RAW || com == TIOCSETP)
e1d74936 321 wflushtty(tp);
4b72e2f9
SL
322 else if ((tp->t_flags&CBREAK) != (sg->sg_flags&CBREAK)) {
323 if (sg->sg_flags & CBREAK) {
e1d74936
BJ
324 catq(&tp->t_rawq, &tp->t_canq);
325 tq = tp->t_rawq;
326 tp->t_rawq = tp->t_canq;
327 tp->t_canq = tq;
328 } else {
329 tp->t_local |= LPENDIN;
330 ttwakeup(tp);
8062c8a7
BJ
331 }
332 }
4b72e2f9
SL
333 tp->t_ispeed = sg->sg_ispeed;
334 tp->t_ospeed = sg->sg_ospeed;
335 tp->t_erase = sg->sg_erase;
336 tp->t_kill = sg->sg_kill;
337 tp->t_flags = sg->sg_flags;
627c86ee 338 if (tp->t_flags & RAW) {
941944c9 339 tp->t_state &= ~TS_TTSTOP;
627c86ee
KB
340 ttstart(tp);
341 }
101ba270 342 (void) spl0();
89dc6dfb 343 break;
4b72e2f9 344 }
89dc6dfb 345
fc6972ae 346 /* send current parameters to user */
4b72e2f9
SL
347 case TIOCGETP: {
348 register struct sgttyb *sg = (struct sgttyb *)data;
349
350 sg->sg_ispeed = tp->t_ispeed;
351 sg->sg_ospeed = tp->t_ospeed;
352 sg->sg_erase = tp->t_erase;
353 sg->sg_kill = tp->t_kill;
354 sg->sg_flags = tp->t_flags;
89dc6dfb 355 break;
4b72e2f9 356 }
89dc6dfb 357
fc6972ae 358 /* hang up line on last close */
89dc6dfb 359 case TIOCHPCL:
941944c9 360 tp->t_state |= TS_HUPCLS;
89dc6dfb
BJ
361 break;
362
7d973a4d 363 case TIOCFLUSH: {
4b72e2f9
SL
364 register int flags = *(int *)data;
365
366 if (flags == 0)
7d973a4d 367 flags = FREAD|FWRITE;
4b72e2f9
SL
368 else
369 flags &= FREAD|FWRITE;
7d973a4d 370 flushtty(tp, flags);
89dc6dfb 371 break;
4568c08e 372 }
89dc6dfb 373
4b72e2f9
SL
374 case FIONBIO:
375 if (*(int *)data)
941944c9
BJ
376 tp->t_state |= TS_NBIO;
377 else
378 tp->t_state &= ~TS_NBIO;
379 break;
941944c9 380
4b72e2f9
SL
381 case FIOASYNC:
382 if (*(int *)data)
a66e4149
BJ
383 tp->t_state |= TS_ASYNC;
384 else
385 tp->t_state &= ~TS_ASYNC;
386 break;
a66e4149 387
fc6972ae 388 /* set and fetch special characters */
89dc6dfb 389 case TIOCSETC:
4b72e2f9 390 bcopy(data, (caddr_t)&tun, sizeof (struct tchars));
89dc6dfb
BJ
391 break;
392
393 case TIOCGETC:
4b72e2f9 394 bcopy((caddr_t)&tun, data, sizeof (struct tchars));
8062c8a7
BJ
395 break;
396
fc6972ae 397 /* set/get local special characters */
8062c8a7 398 case TIOCSLTC:
4b72e2f9 399 bcopy(data, (caddr_t)&tlun, sizeof (struct ltchars));
8062c8a7
BJ
400 break;
401
402 case TIOCGLTC:
4b72e2f9 403 bcopy((caddr_t)&tlun, data, sizeof (struct ltchars));
8062c8a7
BJ
404 break;
405
fc6972ae 406 /* return number of characters immediately available */
4b72e2f9
SL
407 case FIONREAD:
408 *(off_t *)data = ttnread(tp);
8062c8a7 409 break;
8062c8a7 410
fc6972ae 411 /* should allow SPGRP and GPGRP only if tty open for reading */
8062c8a7 412 case TIOCSPGRP:
4b72e2f9 413 tp->t_pgrp = *(int *)data;
8062c8a7
BJ
414 break;
415
416 case TIOCGPGRP:
4b72e2f9 417 *(int *)data = tp->t_pgrp;
8062c8a7
BJ
418 break;
419
fc6972ae 420 /* Modify local mode word */
8062c8a7 421 case TIOCLBIS:
4b72e2f9 422 tp->t_local |= *(int *)data;
8062c8a7
BJ
423 break;
424
425 case TIOCLBIC:
4b72e2f9 426 tp->t_local &= ~(*(int *)data);
8062c8a7
BJ
427 break;
428
429 case TIOCLSET:
4b72e2f9 430 tp->t_local = *(int *)data;
8062c8a7
BJ
431 break;
432
433 case TIOCLGET:
4b72e2f9 434 *(int *)data = tp->t_local;
0dde1c43
BJ
435 break;
436
a8d3bf7f
BJ
437 case TIOCSTOP:
438 s = spl5();
bfcf09ee
BJ
439 if ((tp->t_state & TS_TTSTOP) == 0) {
440 tp->t_state |= TS_TTSTOP;
441 (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
442 }
4b72e2f9 443 splx(s);
bfcf09ee
BJ
444 break;
445
a8d3bf7f
BJ
446 case TIOCSTART:
447 s = spl5();
bfcf09ee
BJ
448 if ((tp->t_state & TS_TTSTOP) || (tp->t_local & LFLUSHO)) {
449 tp->t_state &= ~TS_TTSTOP;
450 tp->t_local &= ~LFLUSHO;
451 ttstart(tp);
452 }
4b72e2f9 453 splx(s);
bfcf09ee
BJ
454 break;
455
89dc6dfb 456 default:
fc6972ae 457 return (-1);
89dc6dfb 458 }
fc6972ae 459 return (0);
89dc6dfb 460}
e1d74936
BJ
461
462ttnread(tp)
463 struct tty *tp;
464{
465 int nread = 0;
466
467 if (tp->t_local & LPENDIN)
468 ttypend(tp);
469 nread = tp->t_canq.c_cc;
470 if (tp->t_flags & (RAW|CBREAK))
471 nread += tp->t_rawq.c_cc;
472 return (nread);
473}
474
941944c9 475ttselect(dev, rw)
e1d74936 476 dev_t dev;
941944c9 477 int rw;
e1d74936
BJ
478{
479 register struct tty *tp = &cdevsw[major(dev)].d_ttys[minor(dev)];
480 int nread;
941944c9 481 int s = spl5();
e1d74936 482
941944c9 483 switch (rw) {
e1d74936
BJ
484
485 case FREAD:
486 nread = ttnread(tp);
487 if (nread > 0)
941944c9 488 goto win;
89b8a44c 489 if (tp->t_rsel && tp->t_rsel->p_wchan == (caddr_t)&selwait)
941944c9 490 tp->t_state |= TS_RCOLL;
e1d74936
BJ
491 else
492 tp->t_rsel = u.u_procp;
941944c9 493 break;
e1d74936 494
941944c9
BJ
495 case FWRITE:
496 if (tp->t_outq.c_cc <= TTLOWAT(tp))
497 goto win;
941944c9
BJ
498 if (tp->t_wsel && tp->t_wsel->p_wchan == (caddr_t)&selwait)
499 tp->t_state |= TS_WCOLL;
500 else
501 tp->t_wsel = u.u_procp;
502 break;
e1d74936 503 }
941944c9
BJ
504 splx(s);
505 return (0);
506win:
507 splx(s);
508 return (1);
e1d74936 509}
8bba2b8f 510
4147b3f6
BJ
511#define OBUFSIZ 100
512
513/*
514 * routine called on opens while tp->t_line == NTTYDISC
515 * establishes a process group for distribution of
516 * quits and interrupts from the tty.
517 * (actually, pp->p_pgrp can't be 0 when this routine
518 * is called since NTTYDISC is not the default discipline)
519 */
520ttyopen(dev, tp)
4b72e2f9
SL
521 dev_t dev;
522 register struct tty *tp;
4147b3f6
BJ
523{
524 register struct proc *pp;
525
526 pp = u.u_procp;
527 tp->t_dev = dev;
4b72e2f9 528 if (pp->p_pgrp == 0) {
4147b3f6
BJ
529 u.u_ttyp = tp;
530 u.u_ttyd = dev;
531 if (tp->t_pgrp == 0)
532 tp->t_pgrp = pp->p_pid;
533 pp->p_pgrp = tp->t_pgrp;
534 }
535 tp->t_state &= ~TS_WOPEN;
536 tp->t_state |= TS_ISOPEN;
537 if (tp->t_line != NTTYDISC)
538 wflushtty(tp);
fc6972ae 539 return (0);
4147b3f6
BJ
540}
541
542/*
543 * clean tp on last close
544 */
545ttyclose(tp)
4b72e2f9 546 register struct tty *tp;
4147b3f6
BJ
547{
548
549 if (tp->t_line) {
550 wflushtty(tp);
551 tp->t_line = 0;
552 return;
553 }
554 tp->t_pgrp = 0;
555 wflushtty(tp);
556 tp->t_state = 0;
557}
558
559/*
560 * reinput pending characters after state switch
561 * call at spl5().
562 */
563ttypend(tp)
4b72e2f9 564 register struct tty *tp;
4147b3f6
BJ
565{
566 struct clist tq;
567 register c;
568
569 tp->t_local &= ~LPENDIN;
570 tp->t_lstate |= LSTYPEN;
571 tq = tp->t_rawq;
572 tp->t_rawq.c_cc = 0;
573 tp->t_rawq.c_cf = tp->t_rawq.c_cl = 0;
574 while ((c = getc(&tq)) >= 0)
575 ttyinput(c, tp);
576 tp->t_lstate &= ~LSTYPEN;
577}
578
579/*
580 * Place a character on raw TTY input queue, putting in delimiters
581 * and waking up top half as needed.
582 * Also echo if required.
583 * The arguments are the character and the appropriate
584 * tty structure.
585 */
586ttyinput(c, tp)
4b72e2f9
SL
587 register c;
588 register struct tty *tp;
4147b3f6
BJ
589{
590 register int t_flags;
591 int i;
592
593 if (tp->t_local&LPENDIN)
594 ttypend(tp);
595 tk_nin++;
596 c &= 0377;
597 t_flags = tp->t_flags;
598 if (t_flags&TANDEM)
599 ttyblock(tp);
600 if ((t_flags&RAW)==0) {
601 if ((tp->t_lstate&LSTYPEN) == 0)
602 c &= 0177;
603 /* check for literal nexting very first */
604 if (tp->t_lstate&LSLNCH) {
605 c |= 0200;
606 tp->t_lstate &= ~LSLNCH;
607 }
608 if (tp->t_line == NTTYDISC && c==tlun.t_lnextc) {
609 if (tp->t_flags&ECHO)
610 ttyout("^\b", tp);
611 tp->t_lstate |= LSLNCH;
612 /* check for output control functions */
613 } else if (c==tun.t_stopc) {
614 if ((tp->t_state&TS_TTSTOP)==0) {
615 tp->t_state |= TS_TTSTOP;
616 (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
617 return;
618 }
619 if (c!=tun.t_startc)
620 return;
621 } else if (c==tun.t_startc) {
622 tp->t_state &= ~TS_TTSTOP;
623 tp->t_local &= ~LFLUSHO;
624 ttstart(tp);
625 return;
626 } else if (tp->t_line == NTTYDISC && c==tlun.t_flushc) {
627 if (tp->t_local & LFLUSHO)
628 tp->t_local &= ~LFLUSHO;
629 else {
630 flushtty(tp, FWRITE);
631 ttyecho(c, tp);
632 if (tp->t_rawq.c_cc+tp->t_canq.c_cc)
633 ttyretype(tp);
634 tp->t_local |= LFLUSHO;
635 }
636 ttstart(tp);
637 return;
638 } else if (c==tun.t_intrc || c==tun.t_quitc ||
639 (tp->t_line == NTTYDISC && c==tlun.t_suspc)) {
640 if ((tp->t_local & LNOFLSH) == 0)
641 flushtty(tp,
642 c==tlun.t_suspc ? FREAD : FREAD|FWRITE);
643 ttyecho(c, tp);
644 c = c==tun.t_intrc ? SIGINT :
645 ((c==tun.t_quitc) ? SIGQUIT : SIGTSTP);
646 ttsignal(tp, c);
647 /* check for buffer editing functions - cooked mode */
648 } else if ((t_flags&CBREAK) == 0) {
649 if ((tp->t_lstate&LSQUOT) &&
650 (c==tp->t_erase||c==tp->t_kill)) {
651 ttyrub(unputc(&tp->t_rawq), tp);
652 c |= 0200;
653 }
654 if (c==tp->t_erase) {
655 if (tp->t_rawq.c_cc)
656 ttyrub(unputc(&tp->t_rawq), tp);
657 } else if (c==tp->t_kill) {
658 if (tp->t_local&LCRTKIL &&
659 tp->t_rawq.c_cc == tp->t_rocount) {
660 while (tp->t_rawq.c_cc)
661 ttyrub(unputc(&tp->t_rawq), tp);
662 } else {
663 ttyecho(c, tp);
664 ttyecho('\n', tp);
665 while (getc(&tp->t_rawq) > 0)
666 ;
667 tp->t_rocount = 0;
668 }
669 tp->t_lstate = 0;
670 } else if (tp->t_line == NTTYDISC && c==tlun.t_werasc) {
671 if (tp->t_rawq.c_cc == 0)
672 goto out;
673 do {
674 c = unputc(&tp->t_rawq);
675 if (c != ' ' && c != '\t')
676 goto erasenb;
677 ttyrub(c, tp);
678 } while (tp->t_rawq.c_cc);
679 goto out;
680 erasenb:
681 do {
682 ttyrub(c, tp);
683 if (tp->t_rawq.c_cc == 0)
684 goto out;
685 c = unputc(&tp->t_rawq);
686 } while (c != ' ' && c != '\t');
687 (void) putc(c, &tp->t_rawq);
688 } else if (tp->t_line == NTTYDISC && c==tlun.t_rprntc) {
689 ttyretype(tp);
690 /* check for cooked mode input buffer overflow */
691 } else if (tp->t_rawq.c_cc+tp->t_canq.c_cc >= TTYHOG) {
692 ;
693 /* put data char in q for user and wakeup if a break char */
694 } else if (putc(c, &tp->t_rawq) >= 0) {
695 if (tp->t_rawq.c_cc+tp->t_canq.c_cc==TTYHOG
696 && tp->t_line == NTTYDISC)
697 (void) ttyoutput(CTRL(g), tp);
698 if (!ttbreakc(c, tp)) {
699 if (tp->t_rocount++ == 0)
700 tp->t_rocol = tp->t_col;
701 } else {
702 tp->t_rocount = 0;
703 catq(&tp->t_rawq, &tp->t_canq);
704 /* IF (TP->T_CHAN) (VOID) SDATA(TP->T_CHAN); */
705 ttwakeup(tp);
706 }
707 tp->t_lstate &= ~LSQUOT;
708 if (c == '\\')
709 tp->t_lstate |= LSQUOT;
710 if (tp->t_lstate&LSERASE) {
711 tp->t_lstate &= ~LSERASE;
712 (void) ttyoutput('/', tp);
713 }
714 i = tp->t_col;
715 ttyecho(c, tp);
716 if (c==tun.t_eofc && tp->t_flags&ECHO) {
717 i = MIN(2, tp->t_col - i);
718 while (i > 0) {
719 (void) ttyoutput('\b', tp);
720 i--;
721 }
722 }
723 }
724 /* CBREAK mode */
725 } else if (tp->t_rawq.c_cc > TTYHOG) {
726 if (tp->t_outq.c_cc < TTHIWAT(tp) &&
727 tp->t_line == NTTYDISC)
728 (void) ttyoutput(CTRL(g), tp);
729 } else if (putc(c, &tp->t_rawq) >= 0) {
730 ttwakeup(tp);
731 ttyecho(c, tp);
732 }
733 /* RAW mode */
734 } else if (tp->t_rawq.c_cc > TTYHOG)
735 flushtty(tp, FREAD|FWRITE);
736 else {
737 if (putc(c, &tp->t_rawq) >= 0)
738 ttwakeup(tp);
739 ttyecho(c, tp);
740 }
741out:
742 if (tp->t_local & LDECCTQ && tp->t_state & TS_TTSTOP &&
743 tun.t_startc != tun.t_stopc)
744 return;
745 tp->t_state &= ~TS_TTSTOP;
746 tp->t_local &= ~LFLUSHO;
747 ttstart(tp);
748}
749
750/*
751 * put character on TTY output queue, adding delays,
752 * expanding tabs, and handling the CR/NL bit.
753 * It is called both from the top half for output, and from
754 * interrupt level for echoing.
755 * The arguments are the character and the tty structure.
756 * Returns < 0 if putc succeeds, otherwise returns char to resend
757 * Must be recursive.
758 */
759ttyoutput(c, tp)
760 register c;
761 register struct tty *tp;
762{
763 register char *colp;
764 register ctype;
765
766 if (tp->t_flags&RAW || tp->t_local&LLITOUT) {
767 if (tp->t_local&LFLUSHO)
768 return (-1);
769 if (putc(c, &tp->t_outq))
4b72e2f9 770 return (c);
4147b3f6
BJ
771 tk_nout++;
772 return (-1);
773 }
774 /*
775 * Ignore EOT in normal mode to avoid hanging up
776 * certain terminals.
777 */
778 c &= 0177;
779 if (c==CEOT && (tp->t_flags&CBREAK)==0)
780 return (-1);
781 /*
782 * Turn tabs to spaces as required
783 */
784 if (c=='\t' && (tp->t_flags&TBDELAY)==XTABS) {
785 register int s;
786
787 c = 8 - (tp->t_col&7);
788 if ((tp->t_local&LFLUSHO) == 0) {
789 s = spl5(); /* don't interrupt tabs */
790 c -= b_to_q(" ", c, &tp->t_outq);
791 tk_nout += c;
792 splx(s);
793 }
794 tp->t_col += c;
795 return (c ? -1 : '\t');
796 }
797 tk_nout++;
798 /*
799 * for upper-case-only terminals,
800 * generate escapes.
801 */
802 if (tp->t_flags&LCASE) {
803 colp = "({)}!|^~'`";
4b72e2f9
SL
804 while (*colp++)
805 if (c == *colp++) {
4147b3f6
BJ
806 if (ttyoutput('\\', tp) >= 0)
807 return (c);
808 c = colp[-2];
809 break;
810 }
811 if ('A'<=c && c<='Z') {
812 if (ttyoutput('\\', tp) >= 0)
813 return (c);
814 } else if ('a'<=c && c<='z')
815 c += 'A' - 'a';
816 }
817 /*
818 * turn <nl> to <cr><lf> if desired.
819 */
820 if (c=='\n' && tp->t_flags&CRMOD)
821 if (ttyoutput('\r', tp) >= 0)
822 return (c);
823 if (c=='~' && tp->t_local&LTILDE)
824 c = '`';
825 if ((tp->t_local&LFLUSHO) == 0 && putc(c, &tp->t_outq))
826 return (c);
827 /*
828 * Calculate delays.
829 * The numbers here represent clock ticks
830 * and are not necessarily optimal for all terminals.
831 * The delays are indicated by characters above 0200.
832 * In raw mode there are no delays and the
833 * transmission path is 8 bits wide.
834 */
835 colp = &tp->t_col;
836 ctype = partab[c];
837 c = 0;
838 switch (ctype&077) {
839
840 case ORDINARY:
841 (*colp)++;
842
843 case CONTROL:
844 break;
845
846 case BACKSPACE:
847 if (*colp)
848 (*colp)--;
849 break;
850
851 case NEWLINE:
852 ctype = (tp->t_flags >> 8) & 03;
4b72e2f9 853 if (ctype == 1) { /* tty 37 */
4147b3f6
BJ
854 if (*colp)
855 c = max(((unsigned)*colp>>4) + 3, (unsigned)6);
856 } else
4b72e2f9 857 if (ctype == 2) { /* vt05 */
4147b3f6
BJ
858 c = 6;
859 }
860 *colp = 0;
861 break;
862
863 case TAB:
864 ctype = (tp->t_flags >> 10) & 03;
4b72e2f9 865 if (ctype == 1) { /* tty 37 */
4147b3f6 866 c = 1 - (*colp | ~07);
4b72e2f9 867 if (c < 5)
4147b3f6
BJ
868 c = 0;
869 }
870 *colp |= 07;
871 (*colp)++;
872 break;
873
874 case VTAB:
4b72e2f9 875 if (tp->t_flags & VTDELAY) /* tty 37 */
4147b3f6
BJ
876 c = 0177;
877 break;
878
879 case RETURN:
880 ctype = (tp->t_flags >> 12) & 03;
4b72e2f9 881 if (ctype == 1) { /* tn 300 */
4147b3f6 882 c = 5;
4b72e2f9 883 } else if (ctype == 2) { /* ti 700 */
4147b3f6 884 c = 10;
4b72e2f9 885 } else if (ctype == 3) { /* concept 100 */
4147b3f6
BJ
886 int i;
887 if ((i = *colp) >= 0)
888 for (; i<9; i++)
889 (void) putc(0177, &tp->t_outq);
890 }
891 *colp = 0;
892 }
4b72e2f9 893 if (c && (tp->t_local&LFLUSHO) == 0)
4147b3f6
BJ
894 (void) putc(c|0200, &tp->t_outq);
895 return (-1);
896}
897
898/*
899 * Called from device's read routine after it has
900 * calculated the tty-structure given as argument.
901 */
d6d7360b 902ttread(tp, uio)
4b72e2f9 903 register struct tty *tp;
d6d7360b 904 struct uio *uio;
4147b3f6
BJ
905{
906 register struct clist *qp;
907 register c, first;
840510a3 908 int error = 0;
4147b3f6
BJ
909
910 if ((tp->t_state&TS_CARR_ON)==0)
840510a3 911 return (EIO);
4147b3f6
BJ
912loop:
913 (void) spl5();
914 if (tp->t_local&LPENDIN)
915 ttypend(tp);
916 (void) spl0();
917 while (tp == u.u_ttyp && u.u_procp->p_pgrp != tp->t_pgrp) {
918 if (u.u_signal[SIGTTIN] == SIG_IGN ||
919 u.u_signal[SIGTTIN] == SIG_HOLD ||
920/*
921 (u.u_procp->p_flag&SDETACH) ||
922*/
923 u.u_procp->p_flag&SVFORK)
840510a3 924 return (EIO);
4147b3f6
BJ
925 gsignal(u.u_procp->p_pgrp, SIGTTIN);
926 sleep((caddr_t)&lbolt, TTIPRI);
927 }
928 if (tp->t_flags&RAW) {
929 (void) spl5();
930 if (tp->t_rawq.c_cc <= 0) {
931 if ((tp->t_state&TS_CARR_ON)==0 ||
932 (tp->t_state&TS_NBIO)) {
933 (void) spl0();
840510a3 934 return (EWOULDBLOCK);
4147b3f6
BJ
935 }
936 sleep((caddr_t)&tp->t_rawq, TTIPRI);
937 (void) spl0();
938 goto loop;
939 }
940 (void) spl0();
d6d7360b 941 while (tp->t_rawq.c_cc && uio->uio_iovcnt) {
840510a3
BJ
942 error = passuc(getc(&tp->t_rawq), uio);
943 if (error)
d6d7360b
BJ
944 break;
945 }
840510a3 946 return (error);
4147b3f6
BJ
947 } else {
948 qp = tp->t_flags & CBREAK ? &tp->t_rawq : &tp->t_canq;
949 (void) spl5();
950 if (qp->c_cc <= 0) {
951 if ((tp->t_state&TS_CARR_ON)==0 ||
952 (tp->t_state&TS_NBIO)) {
953 (void) spl0();
840510a3 954 return (EWOULDBLOCK);
4147b3f6
BJ
955 }
956 sleep((caddr_t)&tp->t_rawq, TTIPRI);
957 (void) spl0();
958 goto loop;
959 }
960 (void) spl0();
961 first = 1;
962 while ((c = getc(qp)) >= 0) {
963 if (tp->t_flags&CRMOD && c == '\r')
964 c = '\n';
965 if (tp->t_flags&LCASE && c <= 0177)
966 if (tp->t_lstate&LSBKSL) {
967 if (maptab[c])
968 c = maptab[c];
969 tp->t_lstate &= ~LSBKSL;
970 } else if (c >= 'A' && c <= 'Z')
971 c += 'a' - 'A';
972 else if (c == '\\') {
973 tp->t_lstate |= LSBKSL;
974 continue;
975 }
f2f41cda 976 if (tp->t_line == NTTYDISC && c == tlun.t_dsuspc) {
4147b3f6
BJ
977 ttsignal(tp, SIGTSTP);
978 if (first) {
979 sleep((caddr_t)&lbolt, TTIPRI);
980 goto loop;
981 }
982 break;
983 }
984 if (c == tun.t_eofc && (tp->t_flags&CBREAK)==0)
985 break;
840510a3
BJ
986 error = passuc(c & 0177, uio);
987 if (error)
d6d7360b
BJ
988 break;
989 if (uio->uio_iovcnt == 0)
4147b3f6
BJ
990 break;
991 if ((tp->t_flags&CBREAK)==0 && ttbreakc(c, tp))
992 break;
993 first = 0;
994 }
995 tp->t_lstate &= ~LSBKSL;
996 }
4147b3f6
BJ
997 if (tp->t_state&TS_TBLOCK && tp->t_rawq.c_cc < TTYHOG/5) {
998 if (putc(tun.t_startc, &tp->t_outq)==0) {
999 tp->t_state &= ~TS_TBLOCK;
1000 ttstart(tp);
1001 }
1002 tp->t_char = 0;
1003 }
840510a3 1004 return (error);
4147b3f6
BJ
1005}
1006
1007/*
1008 * Called from the device's write routine after it has
1009 * calculated the tty-structure given as argument.
1010 */
913ea2d1 1011ttwrite(tp, uio)
4b72e2f9 1012 register struct tty *tp;
913ea2d1 1013 struct uio *uio;
4147b3f6
BJ
1014{
1015#ifdef vax
1016 /*
1017 * THE POSITIONING OF CP, CC, AND CE ARE CRITICAL
1018 * AND MUST NOT BE CHANGED WITHOUT PATCHING
1019 * THE 'ASM' INLINES BELOW. WATCH OUT.
1020 */
1021#endif
1022 register char *cp;
1023 register int cc, ce;
1024 register i;
1025 char obuf[OBUFSIZ];
1026 register c;
1027 int hiwat = TTHIWAT(tp);
913ea2d1 1028 int cnt = uio->uio_resid;
840510a3 1029 int error = 0;
4147b3f6
BJ
1030
1031 if ((tp->t_state&TS_CARR_ON)==0)
840510a3 1032 return (EIO);
4147b3f6
BJ
1033loop:
1034 while (u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp &&
1035 (tp->t_local&LTOSTOP) && (u.u_procp->p_flag&SVFORK)==0 &&
1036 u.u_signal[SIGTTOU] != SIG_IGN &&
1037 u.u_signal[SIGTTOU] != SIG_HOLD
1038/*
1039 &&
1040 (u.u_procp->p_flag&SDETACH)==0) {
1041*/
1042 ) {
1043 gsignal(u.u_procp->p_pgrp, SIGTTOU);
1044 sleep((caddr_t)&lbolt, TTIPRI);
1045 }
913ea2d1
BJ
1046 while (uio->uio_resid > 0) {
1047 cc = uio->uio_iov->iov_len;
1048 if (cc == 0) {
1049 uio->uio_iovcnt--;
1050 uio->uio_iov++;
1051 if (uio->uio_iovcnt < 0)
1052 panic("ttwrite");
1053 continue;
1054 }
1055 if (cc > OBUFSIZ)
1056 cc = OBUFSIZ;
4147b3f6 1057 cp = obuf;
840510a3
BJ
1058 error = uiomove(cp, cc, UIO_WRITE, uio);
1059 if (error)
4147b3f6
BJ
1060 break;
1061 if (tp->t_outq.c_cc > hiwat)
1062 goto ovhiwat;
1063 if (tp->t_local&LFLUSHO)
1064 continue;
1065 if (tp->t_flags&LCASE || tp->t_local&LTILDE) {
1066 while (cc) {
1067 c = *cp++;
1068 tp->t_rocount = 0;
4b72e2f9 1069 while ((c = ttyoutput(c, tp)) >= 0) {
4147b3f6
BJ
1070 /* out of clists, wait a bit */
1071 ttstart(tp);
1072 sleep((caddr_t)&lbolt, TTOPRI);
1073 tp->t_rocount = 0;
1074 }
1075 --cc;
1076 if (tp->t_outq.c_cc > hiwat)
1077 goto ovhiwat;
1078 }
1079 continue;
1080 }
1081 while (cc) {
1082 if (tp->t_flags&RAW || tp->t_local&LLITOUT)
1083 ce = cc;
1084 else {
1085#ifdef vax
1086 asm(" scanc r9,(r10),_partab,$077");
1087 asm(" subl3 r0,r9,r8");
1088#else
1089 ce=0;
4b72e2f9 1090 while (((partab[*(unsigned char *)(cp+ce)]&077)==0)&&(ce<cc))
4147b3f6
BJ
1091 ce++;
1092#endif
1093 if (ce==0) {
1094 tp->t_rocount = 0;
1095 if (ttyoutput(*cp, tp) >= 0) {
1096 ttstart(tp);
1097 sleep((caddr_t)&lbolt, TTOPRI);
1098 continue;
1099 }
1100 cp++;
1101 cc--;
1102 if (tp->t_outq.c_cc > hiwat)
1103 goto ovhiwat;
1104 }
1105 }
1106 tp->t_rocount = 0;
1107 i=b_to_q(cp,ce,&tp->t_outq);
1108 ce-=i;
1109 tk_nout+=ce;
1110 tp->t_col+=ce;
1111 cp+=ce;
1112 cc-=ce;
1113 if (i) {
1114 ttstart(tp);
1115 sleep((caddr_t)&lbolt, TTOPRI);
1116 }
1117 if (ce || tp->t_outq.c_cc > hiwat)
1118 goto ovhiwat;
1119 }
1120 }
1121 ttstart(tp);
840510a3 1122 return (error);
4147b3f6
BJ
1123
1124ovhiwat:
1125 (void) spl5();
913ea2d1
BJ
1126 uio->uio_iov->iov_base -= cc;
1127 uio->uio_iov->iov_len += cc;
1128 uio->uio_resid += cc;
1129 uio->uio_offset -= cc;
4147b3f6
BJ
1130 if (tp->t_outq.c_cc <= hiwat) {
1131 (void) spl0();
1132 goto loop;
1133 }
1134 ttstart(tp);
1135 if (tp->t_state & TS_NBIO) {
913ea2d1 1136 if (uio->uio_resid == cnt)
840510a3
BJ
1137 return (EWOULDBLOCK);
1138 return (0);
4147b3f6
BJ
1139 }
1140 tp->t_state |= TS_ASLEEP;
1141 sleep((caddr_t)&tp->t_outq, TTOPRI);
1142 (void) spl0();
1143 goto loop;
1144}
1145
1146/*
1147 * Rubout one character from the rawq of tp
1148 * as cleanly as possible.
1149 */
1150ttyrub(c, tp)
4b72e2f9
SL
1151 register c;
1152 register struct tty *tp;
4147b3f6
BJ
1153{
1154 register char *cp;
1155 register int savecol;
1156 int s;
1157 char *nextc();
1158
1159 if ((tp->t_flags&ECHO)==0)
1160 return;
1161 tp->t_local &= ~LFLUSHO;
1162 c &= 0377;
1163 if (tp->t_local&LCRTBS) {
1164 if (tp->t_rocount == 0) {
1165 /*
1166 * Screwed by ttwrite; retype
1167 */
1168 ttyretype(tp);
1169 return;
1170 }
1171 if (c==('\t'|0200) || c==('\n'|0200))
1172 ttyrubo(tp, 2);
4b72e2f9 1173 else switch (partab[c&=0177] & 0177) {
4147b3f6
BJ
1174
1175 case ORDINARY:
1176 if (tp->t_flags&LCASE && c >= 'A' && c <= 'Z')
1177 ttyrubo(tp, 2);
1178 else
1179 ttyrubo(tp, 1);
1180 break;
1181
1182 case VTAB:
1183 case BACKSPACE:
1184 case CONTROL:
1185 case RETURN:
1186 if (tp->t_local & LCTLECH)
1187 ttyrubo(tp, 2);
1188 break;
1189
1190 case TAB:
1191 if (tp->t_rocount < tp->t_rawq.c_cc) {
1192 ttyretype(tp);
1193 return;
1194 }
1195 s = spl5();
1196 savecol = tp->t_col;
1197 tp->t_lstate |= LSCNTTB;
1198 tp->t_local |= LFLUSHO;
1199 tp->t_col = tp->t_rocol;
1200 for (cp = tp->t_rawq.c_cf; cp; cp = nextc(&tp->t_rawq, cp))
1201 ttyecho(*cp, tp);
1202 tp->t_local &= ~LFLUSHO;
1203 tp->t_lstate &= ~LSCNTTB;
1204 splx(s);
1205 /*
1206 * savecol will now be length of the tab
1207 */
1208 savecol -= tp->t_col;
1209 tp->t_col += savecol;
1210 if (savecol > 8)
1211 savecol = 8; /* overflow screw */
1212 while (--savecol >= 0)
1213 (void) ttyoutput('\b', tp);
1214 break;
1215
1216 default:
1217 panic("ttyrub");
1218 }
1219 } else if (tp->t_local&LPRTERA) {
1220 if ((tp->t_lstate&LSERASE) == 0) {
1221 (void) ttyoutput('\\', tp);
1222 tp->t_lstate |= LSERASE;
1223 }
1224 ttyecho(c, tp);
1225 } else
1226 ttyecho(tp->t_erase, tp);
1227 tp->t_rocount--;
1228}
1229
1230/*
1231 * Crt back over cnt chars perhaps
1232 * erasing them.
1233 */
1234ttyrubo(tp, cnt)
4b72e2f9
SL
1235 register struct tty *tp;
1236 int cnt;
4147b3f6
BJ
1237{
1238
1239 while (--cnt >= 0)
1240 ttyout(tp->t_local&LCRTERA ? "\b \b" : "\b", tp);
1241}
1242
1243/*
1244 * Reprint the rawq line.
1245 * We assume c_cc has already been checked.
1246 */
1247ttyretype(tp)
4b72e2f9 1248 register struct tty *tp;
4147b3f6
BJ
1249{
1250 register char *cp;
1251 char *nextc();
1252 int s;
1253
1254 if (tlun.t_rprntc != 0377)
1255 ttyecho(tlun.t_rprntc, tp);
1256 (void) ttyoutput('\n', tp);
1257 s = spl5();
1258 for (cp = tp->t_canq.c_cf; cp; cp = nextc(&tp->t_canq, cp))
1259 ttyecho(*cp, tp);
1260 for (cp = tp->t_rawq.c_cf; cp; cp = nextc(&tp->t_rawq, cp))
1261 ttyecho(*cp, tp);
1262 tp->t_lstate &= ~LSERASE;
1263 splx(s);
1264 tp->t_rocount = tp->t_rawq.c_cc;
1265 tp->t_rocol = 0;
1266}
1267
1268/*
1269 * Echo a typed character to the terminal
1270 */
1271ttyecho(c, tp)
4b72e2f9
SL
1272 register c;
1273 register struct tty *tp;
4147b3f6
BJ
1274{
1275
1276 if ((tp->t_lstate & LSCNTTB) == 0)
1277 tp->t_local &= ~LFLUSHO;
1278 if ((tp->t_flags&ECHO) == 0)
1279 return;
1280 c &= 0377;
1281 if (tp->t_flags&RAW) {
1282 (void) ttyoutput(c, tp);
1283 return;
1284 }
1285 if (c == '\r' && tp->t_flags&CRMOD)
1286 c = '\n';
1287 if (tp->t_local&LCTLECH) {
1288 if ((c&0177) <= 037 && c!='\t' && c!='\n' || (c&0177)==0177) {
1289 (void) ttyoutput('^', tp);
1290 c &= 0177;
1291 if (c == 0177)
1292 c = '?';
1293 else if (tp->t_flags&LCASE)
1294 c += 'a' - 1;
1295 else
1296 c += 'A' - 1;
1297 }
1298 }
1299 if ((tp->t_flags&LCASE) && (c >= 'A' && c <= 'Z'))
1300 c += 'a' - 'A';
1301 (void) ttyoutput(c & 0177, tp);
1302}
1303
1304/*
1305 * Is c a break char for tp?
1306 */
1307ttbreakc(c, tp)
4b72e2f9
SL
1308 register c;
1309 register struct tty *tp;
4147b3f6
BJ
1310{
1311 return (c == '\n' || c == tun.t_eofc || c == tun.t_brkc ||
1312 c == '\r' && (tp->t_flags&CRMOD));
1313}
1314
1315/*
1316 * send string cp to tp
1317 */
1318ttyout(cp, tp)
4b72e2f9
SL
1319 register char *cp;
1320 register struct tty *tp;
4147b3f6
BJ
1321{
1322 register char c;
1323
1324 while (c = *cp++)
1325 (void) ttyoutput(c, tp);
1326}
1327
1328ttwakeup(tp)
1329 struct tty *tp;
1330{
1331
1332 if (tp->t_rsel) {
1333 selwakeup(tp->t_rsel, tp->t_state&TS_RCOLL);
1334 tp->t_state &= ~TS_RCOLL;
1335 tp->t_rsel = 0;
1336 }
1337 wakeup((caddr_t)&tp->t_rawq);
1338}
1339
1340ttsignal(tp, signo)
1341 struct tty *tp;
1342 int signo;
1343{
1344
1345 gsignal(tp->t_pgrp, signo);
1346}