lint cleanup
[unix-history] / usr / src / sys / kern / tty.c
CommitLineData
fc6972ae 1/* tty.c 4.31 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
4b72e2f9
SL
437 case TIOCSTOP: {
438 int s = spl5();
bfcf09ee 439
bfcf09ee
BJ
440 if ((tp->t_state & TS_TTSTOP) == 0) {
441 tp->t_state |= TS_TTSTOP;
442 (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
443 }
4b72e2f9 444 splx(s);
bfcf09ee 445 break;
4b72e2f9
SL
446 }
447
448 case TIOCSTART: {
449 int s = spl5();
bfcf09ee 450
bfcf09ee
BJ
451 if ((tp->t_state & TS_TTSTOP) || (tp->t_local & LFLUSHO)) {
452 tp->t_state &= ~TS_TTSTOP;
453 tp->t_local &= ~LFLUSHO;
454 ttstart(tp);
455 }
4b72e2f9 456 splx(s);
bfcf09ee 457 break;
4b72e2f9 458 }
bfcf09ee 459
89dc6dfb 460 default:
fc6972ae 461 return (-1);
89dc6dfb 462 }
fc6972ae 463 return (0);
89dc6dfb 464}
e1d74936
BJ
465
466ttnread(tp)
467 struct tty *tp;
468{
469 int nread = 0;
470
471 if (tp->t_local & LPENDIN)
472 ttypend(tp);
473 nread = tp->t_canq.c_cc;
474 if (tp->t_flags & (RAW|CBREAK))
475 nread += tp->t_rawq.c_cc;
476 return (nread);
477}
478
941944c9 479ttselect(dev, rw)
e1d74936 480 dev_t dev;
941944c9 481 int rw;
e1d74936
BJ
482{
483 register struct tty *tp = &cdevsw[major(dev)].d_ttys[minor(dev)];
484 int nread;
941944c9 485 int s = spl5();
e1d74936 486
941944c9 487 switch (rw) {
e1d74936
BJ
488
489 case FREAD:
490 nread = ttnread(tp);
491 if (nread > 0)
941944c9 492 goto win;
89b8a44c 493 if (tp->t_rsel && tp->t_rsel->p_wchan == (caddr_t)&selwait)
941944c9 494 tp->t_state |= TS_RCOLL;
e1d74936
BJ
495 else
496 tp->t_rsel = u.u_procp;
941944c9 497 break;
e1d74936 498
941944c9
BJ
499 case FWRITE:
500 if (tp->t_outq.c_cc <= TTLOWAT(tp))
501 goto win;
941944c9
BJ
502 if (tp->t_wsel && tp->t_wsel->p_wchan == (caddr_t)&selwait)
503 tp->t_state |= TS_WCOLL;
504 else
505 tp->t_wsel = u.u_procp;
506 break;
e1d74936 507 }
941944c9
BJ
508 splx(s);
509 return (0);
510win:
511 splx(s);
512 return (1);
e1d74936 513}
8bba2b8f 514
4147b3f6
BJ
515#define OBUFSIZ 100
516
517/*
518 * routine called on opens while tp->t_line == NTTYDISC
519 * establishes a process group for distribution of
520 * quits and interrupts from the tty.
521 * (actually, pp->p_pgrp can't be 0 when this routine
522 * is called since NTTYDISC is not the default discipline)
523 */
524ttyopen(dev, tp)
4b72e2f9
SL
525 dev_t dev;
526 register struct tty *tp;
4147b3f6
BJ
527{
528 register struct proc *pp;
529
530 pp = u.u_procp;
531 tp->t_dev = dev;
4b72e2f9 532 if (pp->p_pgrp == 0) {
4147b3f6
BJ
533 u.u_ttyp = tp;
534 u.u_ttyd = dev;
535 if (tp->t_pgrp == 0)
536 tp->t_pgrp = pp->p_pid;
537 pp->p_pgrp = tp->t_pgrp;
538 }
539 tp->t_state &= ~TS_WOPEN;
540 tp->t_state |= TS_ISOPEN;
541 if (tp->t_line != NTTYDISC)
542 wflushtty(tp);
fc6972ae 543 return (0);
4147b3f6
BJ
544}
545
546/*
547 * clean tp on last close
548 */
549ttyclose(tp)
4b72e2f9 550 register struct tty *tp;
4147b3f6
BJ
551{
552
553 if (tp->t_line) {
554 wflushtty(tp);
555 tp->t_line = 0;
556 return;
557 }
558 tp->t_pgrp = 0;
559 wflushtty(tp);
560 tp->t_state = 0;
561}
562
563/*
564 * reinput pending characters after state switch
565 * call at spl5().
566 */
567ttypend(tp)
4b72e2f9 568 register struct tty *tp;
4147b3f6
BJ
569{
570 struct clist tq;
571 register c;
572
573 tp->t_local &= ~LPENDIN;
574 tp->t_lstate |= LSTYPEN;
575 tq = tp->t_rawq;
576 tp->t_rawq.c_cc = 0;
577 tp->t_rawq.c_cf = tp->t_rawq.c_cl = 0;
578 while ((c = getc(&tq)) >= 0)
579 ttyinput(c, tp);
580 tp->t_lstate &= ~LSTYPEN;
581}
582
583/*
584 * Place a character on raw TTY input queue, putting in delimiters
585 * and waking up top half as needed.
586 * Also echo if required.
587 * The arguments are the character and the appropriate
588 * tty structure.
589 */
590ttyinput(c, tp)
4b72e2f9
SL
591 register c;
592 register struct tty *tp;
4147b3f6
BJ
593{
594 register int t_flags;
595 int i;
596
597 if (tp->t_local&LPENDIN)
598 ttypend(tp);
599 tk_nin++;
600 c &= 0377;
601 t_flags = tp->t_flags;
602 if (t_flags&TANDEM)
603 ttyblock(tp);
604 if ((t_flags&RAW)==0) {
605 if ((tp->t_lstate&LSTYPEN) == 0)
606 c &= 0177;
607 /* check for literal nexting very first */
608 if (tp->t_lstate&LSLNCH) {
609 c |= 0200;
610 tp->t_lstate &= ~LSLNCH;
611 }
612 if (tp->t_line == NTTYDISC && c==tlun.t_lnextc) {
613 if (tp->t_flags&ECHO)
614 ttyout("^\b", tp);
615 tp->t_lstate |= LSLNCH;
616 /* check for output control functions */
617 } else if (c==tun.t_stopc) {
618 if ((tp->t_state&TS_TTSTOP)==0) {
619 tp->t_state |= TS_TTSTOP;
620 (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
621 return;
622 }
623 if (c!=tun.t_startc)
624 return;
625 } else if (c==tun.t_startc) {
626 tp->t_state &= ~TS_TTSTOP;
627 tp->t_local &= ~LFLUSHO;
628 ttstart(tp);
629 return;
630 } else if (tp->t_line == NTTYDISC && c==tlun.t_flushc) {
631 if (tp->t_local & LFLUSHO)
632 tp->t_local &= ~LFLUSHO;
633 else {
634 flushtty(tp, FWRITE);
635 ttyecho(c, tp);
636 if (tp->t_rawq.c_cc+tp->t_canq.c_cc)
637 ttyretype(tp);
638 tp->t_local |= LFLUSHO;
639 }
640 ttstart(tp);
641 return;
642 } else if (c==tun.t_intrc || c==tun.t_quitc ||
643 (tp->t_line == NTTYDISC && c==tlun.t_suspc)) {
644 if ((tp->t_local & LNOFLSH) == 0)
645 flushtty(tp,
646 c==tlun.t_suspc ? FREAD : FREAD|FWRITE);
647 ttyecho(c, tp);
648 c = c==tun.t_intrc ? SIGINT :
649 ((c==tun.t_quitc) ? SIGQUIT : SIGTSTP);
650 ttsignal(tp, c);
651 /* check for buffer editing functions - cooked mode */
652 } else if ((t_flags&CBREAK) == 0) {
653 if ((tp->t_lstate&LSQUOT) &&
654 (c==tp->t_erase||c==tp->t_kill)) {
655 ttyrub(unputc(&tp->t_rawq), tp);
656 c |= 0200;
657 }
658 if (c==tp->t_erase) {
659 if (tp->t_rawq.c_cc)
660 ttyrub(unputc(&tp->t_rawq), tp);
661 } else if (c==tp->t_kill) {
662 if (tp->t_local&LCRTKIL &&
663 tp->t_rawq.c_cc == tp->t_rocount) {
664 while (tp->t_rawq.c_cc)
665 ttyrub(unputc(&tp->t_rawq), tp);
666 } else {
667 ttyecho(c, tp);
668 ttyecho('\n', tp);
669 while (getc(&tp->t_rawq) > 0)
670 ;
671 tp->t_rocount = 0;
672 }
673 tp->t_lstate = 0;
674 } else if (tp->t_line == NTTYDISC && c==tlun.t_werasc) {
675 if (tp->t_rawq.c_cc == 0)
676 goto out;
677 do {
678 c = unputc(&tp->t_rawq);
679 if (c != ' ' && c != '\t')
680 goto erasenb;
681 ttyrub(c, tp);
682 } while (tp->t_rawq.c_cc);
683 goto out;
684 erasenb:
685 do {
686 ttyrub(c, tp);
687 if (tp->t_rawq.c_cc == 0)
688 goto out;
689 c = unputc(&tp->t_rawq);
690 } while (c != ' ' && c != '\t');
691 (void) putc(c, &tp->t_rawq);
692 } else if (tp->t_line == NTTYDISC && c==tlun.t_rprntc) {
693 ttyretype(tp);
694 /* check for cooked mode input buffer overflow */
695 } else if (tp->t_rawq.c_cc+tp->t_canq.c_cc >= TTYHOG) {
696 ;
697 /* put data char in q for user and wakeup if a break char */
698 } else if (putc(c, &tp->t_rawq) >= 0) {
699 if (tp->t_rawq.c_cc+tp->t_canq.c_cc==TTYHOG
700 && tp->t_line == NTTYDISC)
701 (void) ttyoutput(CTRL(g), tp);
702 if (!ttbreakc(c, tp)) {
703 if (tp->t_rocount++ == 0)
704 tp->t_rocol = tp->t_col;
705 } else {
706 tp->t_rocount = 0;
707 catq(&tp->t_rawq, &tp->t_canq);
708 /* IF (TP->T_CHAN) (VOID) SDATA(TP->T_CHAN); */
709 ttwakeup(tp);
710 }
711 tp->t_lstate &= ~LSQUOT;
712 if (c == '\\')
713 tp->t_lstate |= LSQUOT;
714 if (tp->t_lstate&LSERASE) {
715 tp->t_lstate &= ~LSERASE;
716 (void) ttyoutput('/', tp);
717 }
718 i = tp->t_col;
719 ttyecho(c, tp);
720 if (c==tun.t_eofc && tp->t_flags&ECHO) {
721 i = MIN(2, tp->t_col - i);
722 while (i > 0) {
723 (void) ttyoutput('\b', tp);
724 i--;
725 }
726 }
727 }
728 /* CBREAK mode */
729 } else if (tp->t_rawq.c_cc > TTYHOG) {
730 if (tp->t_outq.c_cc < TTHIWAT(tp) &&
731 tp->t_line == NTTYDISC)
732 (void) ttyoutput(CTRL(g), tp);
733 } else if (putc(c, &tp->t_rawq) >= 0) {
734 ttwakeup(tp);
735 ttyecho(c, tp);
736 }
737 /* RAW mode */
738 } else if (tp->t_rawq.c_cc > TTYHOG)
739 flushtty(tp, FREAD|FWRITE);
740 else {
741 if (putc(c, &tp->t_rawq) >= 0)
742 ttwakeup(tp);
743 ttyecho(c, tp);
744 }
745out:
746 if (tp->t_local & LDECCTQ && tp->t_state & TS_TTSTOP &&
747 tun.t_startc != tun.t_stopc)
748 return;
749 tp->t_state &= ~TS_TTSTOP;
750 tp->t_local &= ~LFLUSHO;
751 ttstart(tp);
752}
753
754/*
755 * put character on TTY output queue, adding delays,
756 * expanding tabs, and handling the CR/NL bit.
757 * It is called both from the top half for output, and from
758 * interrupt level for echoing.
759 * The arguments are the character and the tty structure.
760 * Returns < 0 if putc succeeds, otherwise returns char to resend
761 * Must be recursive.
762 */
763ttyoutput(c, tp)
764 register c;
765 register struct tty *tp;
766{
767 register char *colp;
768 register ctype;
769
770 if (tp->t_flags&RAW || tp->t_local&LLITOUT) {
771 if (tp->t_local&LFLUSHO)
772 return (-1);
773 if (putc(c, &tp->t_outq))
4b72e2f9 774 return (c);
4147b3f6
BJ
775 tk_nout++;
776 return (-1);
777 }
778 /*
779 * Ignore EOT in normal mode to avoid hanging up
780 * certain terminals.
781 */
782 c &= 0177;
783 if (c==CEOT && (tp->t_flags&CBREAK)==0)
784 return (-1);
785 /*
786 * Turn tabs to spaces as required
787 */
788 if (c=='\t' && (tp->t_flags&TBDELAY)==XTABS) {
789 register int s;
790
791 c = 8 - (tp->t_col&7);
792 if ((tp->t_local&LFLUSHO) == 0) {
793 s = spl5(); /* don't interrupt tabs */
794 c -= b_to_q(" ", c, &tp->t_outq);
795 tk_nout += c;
796 splx(s);
797 }
798 tp->t_col += c;
799 return (c ? -1 : '\t');
800 }
801 tk_nout++;
802 /*
803 * for upper-case-only terminals,
804 * generate escapes.
805 */
806 if (tp->t_flags&LCASE) {
807 colp = "({)}!|^~'`";
4b72e2f9
SL
808 while (*colp++)
809 if (c == *colp++) {
4147b3f6
BJ
810 if (ttyoutput('\\', tp) >= 0)
811 return (c);
812 c = colp[-2];
813 break;
814 }
815 if ('A'<=c && c<='Z') {
816 if (ttyoutput('\\', tp) >= 0)
817 return (c);
818 } else if ('a'<=c && c<='z')
819 c += 'A' - 'a';
820 }
821 /*
822 * turn <nl> to <cr><lf> if desired.
823 */
824 if (c=='\n' && tp->t_flags&CRMOD)
825 if (ttyoutput('\r', tp) >= 0)
826 return (c);
827 if (c=='~' && tp->t_local&LTILDE)
828 c = '`';
829 if ((tp->t_local&LFLUSHO) == 0 && putc(c, &tp->t_outq))
830 return (c);
831 /*
832 * Calculate delays.
833 * The numbers here represent clock ticks
834 * and are not necessarily optimal for all terminals.
835 * The delays are indicated by characters above 0200.
836 * In raw mode there are no delays and the
837 * transmission path is 8 bits wide.
838 */
839 colp = &tp->t_col;
840 ctype = partab[c];
841 c = 0;
842 switch (ctype&077) {
843
844 case ORDINARY:
845 (*colp)++;
846
847 case CONTROL:
848 break;
849
850 case BACKSPACE:
851 if (*colp)
852 (*colp)--;
853 break;
854
855 case NEWLINE:
856 ctype = (tp->t_flags >> 8) & 03;
4b72e2f9 857 if (ctype == 1) { /* tty 37 */
4147b3f6
BJ
858 if (*colp)
859 c = max(((unsigned)*colp>>4) + 3, (unsigned)6);
860 } else
4b72e2f9 861 if (ctype == 2) { /* vt05 */
4147b3f6
BJ
862 c = 6;
863 }
864 *colp = 0;
865 break;
866
867 case TAB:
868 ctype = (tp->t_flags >> 10) & 03;
4b72e2f9 869 if (ctype == 1) { /* tty 37 */
4147b3f6 870 c = 1 - (*colp | ~07);
4b72e2f9 871 if (c < 5)
4147b3f6
BJ
872 c = 0;
873 }
874 *colp |= 07;
875 (*colp)++;
876 break;
877
878 case VTAB:
4b72e2f9 879 if (tp->t_flags & VTDELAY) /* tty 37 */
4147b3f6
BJ
880 c = 0177;
881 break;
882
883 case RETURN:
884 ctype = (tp->t_flags >> 12) & 03;
4b72e2f9 885 if (ctype == 1) { /* tn 300 */
4147b3f6 886 c = 5;
4b72e2f9 887 } else if (ctype == 2) { /* ti 700 */
4147b3f6 888 c = 10;
4b72e2f9 889 } else if (ctype == 3) { /* concept 100 */
4147b3f6
BJ
890 int i;
891 if ((i = *colp) >= 0)
892 for (; i<9; i++)
893 (void) putc(0177, &tp->t_outq);
894 }
895 *colp = 0;
896 }
4b72e2f9 897 if (c && (tp->t_local&LFLUSHO) == 0)
4147b3f6
BJ
898 (void) putc(c|0200, &tp->t_outq);
899 return (-1);
900}
901
902/*
903 * Called from device's read routine after it has
904 * calculated the tty-structure given as argument.
905 */
d6d7360b 906ttread(tp, uio)
4b72e2f9 907 register struct tty *tp;
d6d7360b 908 struct uio *uio;
4147b3f6
BJ
909{
910 register struct clist *qp;
911 register c, first;
840510a3 912 int error = 0;
4147b3f6
BJ
913
914 if ((tp->t_state&TS_CARR_ON)==0)
840510a3 915 return (EIO);
4147b3f6
BJ
916loop:
917 (void) spl5();
918 if (tp->t_local&LPENDIN)
919 ttypend(tp);
920 (void) spl0();
921 while (tp == u.u_ttyp && u.u_procp->p_pgrp != tp->t_pgrp) {
922 if (u.u_signal[SIGTTIN] == SIG_IGN ||
923 u.u_signal[SIGTTIN] == SIG_HOLD ||
924/*
925 (u.u_procp->p_flag&SDETACH) ||
926*/
927 u.u_procp->p_flag&SVFORK)
840510a3 928 return (EIO);
4147b3f6
BJ
929 gsignal(u.u_procp->p_pgrp, SIGTTIN);
930 sleep((caddr_t)&lbolt, TTIPRI);
931 }
932 if (tp->t_flags&RAW) {
933 (void) spl5();
934 if (tp->t_rawq.c_cc <= 0) {
935 if ((tp->t_state&TS_CARR_ON)==0 ||
936 (tp->t_state&TS_NBIO)) {
937 (void) spl0();
840510a3 938 return (EWOULDBLOCK);
4147b3f6
BJ
939 }
940 sleep((caddr_t)&tp->t_rawq, TTIPRI);
941 (void) spl0();
942 goto loop;
943 }
944 (void) spl0();
d6d7360b 945 while (tp->t_rawq.c_cc && uio->uio_iovcnt) {
840510a3
BJ
946 error = passuc(getc(&tp->t_rawq), uio);
947 if (error)
d6d7360b
BJ
948 break;
949 }
840510a3 950 return (error);
4147b3f6
BJ
951 } else {
952 qp = tp->t_flags & CBREAK ? &tp->t_rawq : &tp->t_canq;
953 (void) spl5();
954 if (qp->c_cc <= 0) {
955 if ((tp->t_state&TS_CARR_ON)==0 ||
956 (tp->t_state&TS_NBIO)) {
957 (void) spl0();
840510a3 958 return (EWOULDBLOCK);
4147b3f6
BJ
959 }
960 sleep((caddr_t)&tp->t_rawq, TTIPRI);
961 (void) spl0();
962 goto loop;
963 }
964 (void) spl0();
965 first = 1;
966 while ((c = getc(qp)) >= 0) {
967 if (tp->t_flags&CRMOD && c == '\r')
968 c = '\n';
969 if (tp->t_flags&LCASE && c <= 0177)
970 if (tp->t_lstate&LSBKSL) {
971 if (maptab[c])
972 c = maptab[c];
973 tp->t_lstate &= ~LSBKSL;
974 } else if (c >= 'A' && c <= 'Z')
975 c += 'a' - 'A';
976 else if (c == '\\') {
977 tp->t_lstate |= LSBKSL;
978 continue;
979 }
f2f41cda 980 if (tp->t_line == NTTYDISC && c == tlun.t_dsuspc) {
4147b3f6
BJ
981 ttsignal(tp, SIGTSTP);
982 if (first) {
983 sleep((caddr_t)&lbolt, TTIPRI);
984 goto loop;
985 }
986 break;
987 }
988 if (c == tun.t_eofc && (tp->t_flags&CBREAK)==0)
989 break;
840510a3
BJ
990 error = passuc(c & 0177, uio);
991 if (error)
d6d7360b
BJ
992 break;
993 if (uio->uio_iovcnt == 0)
4147b3f6
BJ
994 break;
995 if ((tp->t_flags&CBREAK)==0 && ttbreakc(c, tp))
996 break;
997 first = 0;
998 }
999 tp->t_lstate &= ~LSBKSL;
1000 }
4147b3f6
BJ
1001 if (tp->t_state&TS_TBLOCK && tp->t_rawq.c_cc < TTYHOG/5) {
1002 if (putc(tun.t_startc, &tp->t_outq)==0) {
1003 tp->t_state &= ~TS_TBLOCK;
1004 ttstart(tp);
1005 }
1006 tp->t_char = 0;
1007 }
840510a3 1008 return (error);
4147b3f6
BJ
1009}
1010
1011/*
1012 * Called from the device's write routine after it has
1013 * calculated the tty-structure given as argument.
1014 */
913ea2d1 1015ttwrite(tp, uio)
4b72e2f9 1016 register struct tty *tp;
913ea2d1 1017 struct uio *uio;
4147b3f6
BJ
1018{
1019#ifdef vax
1020 /*
1021 * THE POSITIONING OF CP, CC, AND CE ARE CRITICAL
1022 * AND MUST NOT BE CHANGED WITHOUT PATCHING
1023 * THE 'ASM' INLINES BELOW. WATCH OUT.
1024 */
1025#endif
1026 register char *cp;
1027 register int cc, ce;
1028 register i;
1029 char obuf[OBUFSIZ];
1030 register c;
1031 int hiwat = TTHIWAT(tp);
913ea2d1 1032 int cnt = uio->uio_resid;
840510a3 1033 int error = 0;
4147b3f6
BJ
1034
1035 if ((tp->t_state&TS_CARR_ON)==0)
840510a3 1036 return (EIO);
4147b3f6
BJ
1037loop:
1038 while (u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp &&
1039 (tp->t_local&LTOSTOP) && (u.u_procp->p_flag&SVFORK)==0 &&
1040 u.u_signal[SIGTTOU] != SIG_IGN &&
1041 u.u_signal[SIGTTOU] != SIG_HOLD
1042/*
1043 &&
1044 (u.u_procp->p_flag&SDETACH)==0) {
1045*/
1046 ) {
1047 gsignal(u.u_procp->p_pgrp, SIGTTOU);
1048 sleep((caddr_t)&lbolt, TTIPRI);
1049 }
913ea2d1
BJ
1050 while (uio->uio_resid > 0) {
1051 cc = uio->uio_iov->iov_len;
1052 if (cc == 0) {
1053 uio->uio_iovcnt--;
1054 uio->uio_iov++;
1055 if (uio->uio_iovcnt < 0)
1056 panic("ttwrite");
1057 continue;
1058 }
1059 if (cc > OBUFSIZ)
1060 cc = OBUFSIZ;
4147b3f6 1061 cp = obuf;
840510a3
BJ
1062 error = uiomove(cp, cc, UIO_WRITE, uio);
1063 if (error)
4147b3f6
BJ
1064 break;
1065 if (tp->t_outq.c_cc > hiwat)
1066 goto ovhiwat;
1067 if (tp->t_local&LFLUSHO)
1068 continue;
1069 if (tp->t_flags&LCASE || tp->t_local&LTILDE) {
1070 while (cc) {
1071 c = *cp++;
1072 tp->t_rocount = 0;
4b72e2f9 1073 while ((c = ttyoutput(c, tp)) >= 0) {
4147b3f6
BJ
1074 /* out of clists, wait a bit */
1075 ttstart(tp);
1076 sleep((caddr_t)&lbolt, TTOPRI);
1077 tp->t_rocount = 0;
1078 }
1079 --cc;
1080 if (tp->t_outq.c_cc > hiwat)
1081 goto ovhiwat;
1082 }
1083 continue;
1084 }
1085 while (cc) {
1086 if (tp->t_flags&RAW || tp->t_local&LLITOUT)
1087 ce = cc;
1088 else {
1089#ifdef vax
1090 asm(" scanc r9,(r10),_partab,$077");
1091 asm(" subl3 r0,r9,r8");
1092#else
1093 ce=0;
4b72e2f9 1094 while (((partab[*(unsigned char *)(cp+ce)]&077)==0)&&(ce<cc))
4147b3f6
BJ
1095 ce++;
1096#endif
1097 if (ce==0) {
1098 tp->t_rocount = 0;
1099 if (ttyoutput(*cp, tp) >= 0) {
1100 ttstart(tp);
1101 sleep((caddr_t)&lbolt, TTOPRI);
1102 continue;
1103 }
1104 cp++;
1105 cc--;
1106 if (tp->t_outq.c_cc > hiwat)
1107 goto ovhiwat;
1108 }
1109 }
1110 tp->t_rocount = 0;
1111 i=b_to_q(cp,ce,&tp->t_outq);
1112 ce-=i;
1113 tk_nout+=ce;
1114 tp->t_col+=ce;
1115 cp+=ce;
1116 cc-=ce;
1117 if (i) {
1118 ttstart(tp);
1119 sleep((caddr_t)&lbolt, TTOPRI);
1120 }
1121 if (ce || tp->t_outq.c_cc > hiwat)
1122 goto ovhiwat;
1123 }
1124 }
1125 ttstart(tp);
840510a3 1126 return (error);
4147b3f6
BJ
1127
1128ovhiwat:
1129 (void) spl5();
913ea2d1
BJ
1130 uio->uio_iov->iov_base -= cc;
1131 uio->uio_iov->iov_len += cc;
1132 uio->uio_resid += cc;
1133 uio->uio_offset -= cc;
4147b3f6
BJ
1134 if (tp->t_outq.c_cc <= hiwat) {
1135 (void) spl0();
1136 goto loop;
1137 }
1138 ttstart(tp);
1139 if (tp->t_state & TS_NBIO) {
913ea2d1 1140 if (uio->uio_resid == cnt)
840510a3
BJ
1141 return (EWOULDBLOCK);
1142 return (0);
4147b3f6
BJ
1143 }
1144 tp->t_state |= TS_ASLEEP;
1145 sleep((caddr_t)&tp->t_outq, TTOPRI);
1146 (void) spl0();
1147 goto loop;
1148}
1149
1150/*
1151 * Rubout one character from the rawq of tp
1152 * as cleanly as possible.
1153 */
1154ttyrub(c, tp)
4b72e2f9
SL
1155 register c;
1156 register struct tty *tp;
4147b3f6
BJ
1157{
1158 register char *cp;
1159 register int savecol;
1160 int s;
1161 char *nextc();
1162
1163 if ((tp->t_flags&ECHO)==0)
1164 return;
1165 tp->t_local &= ~LFLUSHO;
1166 c &= 0377;
1167 if (tp->t_local&LCRTBS) {
1168 if (tp->t_rocount == 0) {
1169 /*
1170 * Screwed by ttwrite; retype
1171 */
1172 ttyretype(tp);
1173 return;
1174 }
1175 if (c==('\t'|0200) || c==('\n'|0200))
1176 ttyrubo(tp, 2);
4b72e2f9 1177 else switch (partab[c&=0177] & 0177) {
4147b3f6
BJ
1178
1179 case ORDINARY:
1180 if (tp->t_flags&LCASE && c >= 'A' && c <= 'Z')
1181 ttyrubo(tp, 2);
1182 else
1183 ttyrubo(tp, 1);
1184 break;
1185
1186 case VTAB:
1187 case BACKSPACE:
1188 case CONTROL:
1189 case RETURN:
1190 if (tp->t_local & LCTLECH)
1191 ttyrubo(tp, 2);
1192 break;
1193
1194 case TAB:
1195 if (tp->t_rocount < tp->t_rawq.c_cc) {
1196 ttyretype(tp);
1197 return;
1198 }
1199 s = spl5();
1200 savecol = tp->t_col;
1201 tp->t_lstate |= LSCNTTB;
1202 tp->t_local |= LFLUSHO;
1203 tp->t_col = tp->t_rocol;
1204 for (cp = tp->t_rawq.c_cf; cp; cp = nextc(&tp->t_rawq, cp))
1205 ttyecho(*cp, tp);
1206 tp->t_local &= ~LFLUSHO;
1207 tp->t_lstate &= ~LSCNTTB;
1208 splx(s);
1209 /*
1210 * savecol will now be length of the tab
1211 */
1212 savecol -= tp->t_col;
1213 tp->t_col += savecol;
1214 if (savecol > 8)
1215 savecol = 8; /* overflow screw */
1216 while (--savecol >= 0)
1217 (void) ttyoutput('\b', tp);
1218 break;
1219
1220 default:
1221 panic("ttyrub");
1222 }
1223 } else if (tp->t_local&LPRTERA) {
1224 if ((tp->t_lstate&LSERASE) == 0) {
1225 (void) ttyoutput('\\', tp);
1226 tp->t_lstate |= LSERASE;
1227 }
1228 ttyecho(c, tp);
1229 } else
1230 ttyecho(tp->t_erase, tp);
1231 tp->t_rocount--;
1232}
1233
1234/*
1235 * Crt back over cnt chars perhaps
1236 * erasing them.
1237 */
1238ttyrubo(tp, cnt)
4b72e2f9
SL
1239 register struct tty *tp;
1240 int cnt;
4147b3f6
BJ
1241{
1242
1243 while (--cnt >= 0)
1244 ttyout(tp->t_local&LCRTERA ? "\b \b" : "\b", tp);
1245}
1246
1247/*
1248 * Reprint the rawq line.
1249 * We assume c_cc has already been checked.
1250 */
1251ttyretype(tp)
4b72e2f9 1252 register struct tty *tp;
4147b3f6
BJ
1253{
1254 register char *cp;
1255 char *nextc();
1256 int s;
1257
1258 if (tlun.t_rprntc != 0377)
1259 ttyecho(tlun.t_rprntc, tp);
1260 (void) ttyoutput('\n', tp);
1261 s = spl5();
1262 for (cp = tp->t_canq.c_cf; cp; cp = nextc(&tp->t_canq, cp))
1263 ttyecho(*cp, tp);
1264 for (cp = tp->t_rawq.c_cf; cp; cp = nextc(&tp->t_rawq, cp))
1265 ttyecho(*cp, tp);
1266 tp->t_lstate &= ~LSERASE;
1267 splx(s);
1268 tp->t_rocount = tp->t_rawq.c_cc;
1269 tp->t_rocol = 0;
1270}
1271
1272/*
1273 * Echo a typed character to the terminal
1274 */
1275ttyecho(c, tp)
4b72e2f9
SL
1276 register c;
1277 register struct tty *tp;
4147b3f6
BJ
1278{
1279
1280 if ((tp->t_lstate & LSCNTTB) == 0)
1281 tp->t_local &= ~LFLUSHO;
1282 if ((tp->t_flags&ECHO) == 0)
1283 return;
1284 c &= 0377;
1285 if (tp->t_flags&RAW) {
1286 (void) ttyoutput(c, tp);
1287 return;
1288 }
1289 if (c == '\r' && tp->t_flags&CRMOD)
1290 c = '\n';
1291 if (tp->t_local&LCTLECH) {
1292 if ((c&0177) <= 037 && c!='\t' && c!='\n' || (c&0177)==0177) {
1293 (void) ttyoutput('^', tp);
1294 c &= 0177;
1295 if (c == 0177)
1296 c = '?';
1297 else if (tp->t_flags&LCASE)
1298 c += 'a' - 1;
1299 else
1300 c += 'A' - 1;
1301 }
1302 }
1303 if ((tp->t_flags&LCASE) && (c >= 'A' && c <= 'Z'))
1304 c += 'a' - 'A';
1305 (void) ttyoutput(c & 0177, tp);
1306}
1307
1308/*
1309 * Is c a break char for tp?
1310 */
1311ttbreakc(c, tp)
4b72e2f9
SL
1312 register c;
1313 register struct tty *tp;
4147b3f6
BJ
1314{
1315 return (c == '\n' || c == tun.t_eofc || c == tun.t_brkc ||
1316 c == '\r' && (tp->t_flags&CRMOD));
1317}
1318
1319/*
1320 * send string cp to tp
1321 */
1322ttyout(cp, tp)
4b72e2f9
SL
1323 register char *cp;
1324 register struct tty *tp;
4147b3f6
BJ
1325{
1326 register char c;
1327
1328 while (c = *cp++)
1329 (void) ttyoutput(c, tp);
1330}
1331
1332ttwakeup(tp)
1333 struct tty *tp;
1334{
1335
1336 if (tp->t_rsel) {
1337 selwakeup(tp->t_rsel, tp->t_state&TS_RCOLL);
1338 tp->t_state &= ~TS_RCOLL;
1339 tp->t_rsel = 0;
1340 }
1341 wakeup((caddr_t)&tp->t_rawq);
1342}
1343
1344ttsignal(tp, signo)
1345 struct tty *tp;
1346 int signo;
1347{
1348
1349 gsignal(tp->t_pgrp, signo);
1350}