Don't interrupt the process doing accepts (have a separate process
[unix-history] / usr / src / sys / kern / tty.c
CommitLineData
894cfdb7 1/* tty.c 4.29 82/09/12 */
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{
0cbf0d70 246 int dev;
89dc6dfb
BJ
247 extern int nldisp;
248
c6fe3a50
BJ
249 /*
250 * This is especially so that isatty() will
251 * fail when carrier is gone.
252 */
941944c9 253 if ((tp->t_state&TS_CARR_ON) == 0) {
c6fe3a50
BJ
254 u.u_error = EBADF;
255 return (1);
256 }
257
0cbf0d70 258 dev = tp->t_dev;
50e2732b
BJ
259 /*
260 * If the ioctl involves modification,
261 * insist on being able to write the device,
262 * and hang if in the background.
263 */
4b72e2f9 264 switch (com) {
50e2732b 265
c6fe3a50
BJ
266 case TIOCSETD:
267 case TIOCSETP:
268 case TIOCSETN:
50e2732b
BJ
269 case TIOCFLUSH:
270 case TIOCSETC:
271 case TIOCSLTC:
272 case TIOCSPGRP:
273 case TIOCLBIS:
274 case TIOCLBIC:
275 case TIOCLSET:
c6fe3a50 276/* this is reasonable, but impractical...
50e2732b
BJ
277 if ((flag & FWRITE) == 0) {
278 u.u_error = EBADF;
279 return (1);
280 }
c6fe3a50 281 */
50e2732b
BJ
282 while (tp->t_line == NTTYDISC &&
283 u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp &&
284 (u.u_procp->p_flag&SVFORK) == 0 &&
285 u.u_signal[SIGTTOU] != SIG_IGN &&
022f2340
BJ
286 u.u_signal[SIGTTOU] != SIG_HOLD
287/*
288 &&
50e2732b 289 (u.u_procp->p_flag&SDETACH)==0) {
022f2340
BJ
290*/
291 ) {
50e2732b
BJ
292 gsignal(u.u_procp->p_pgrp, SIGTTOU);
293 sleep((caddr_t)&lbolt, TTOPRI);
294 }
295 break;
296 }
297
298 /*
299 * Process the ioctl.
300 */
4b72e2f9 301 switch (com) {
89dc6dfb
BJ
302
303 /*
50e2732b 304 * Get discipline number
89dc6dfb
BJ
305 */
306 case TIOCGETD:
4b72e2f9 307 *(int *)data = tp->t_line;
89dc6dfb
BJ
308 break;
309
310 /*
50e2732b 311 * Set line discipline
89dc6dfb 312 */
4b72e2f9
SL
313 case TIOCSETD: {
314 register int t = *(int *)data;
315
89dc6dfb
BJ
316 if (t >= nldisp) {
317 u.u_error = ENXIO;
318 break;
319 }
8062c8a7 320 (void) spl5();
89dc6dfb
BJ
321 if (tp->t_line)
322 (*linesw[tp->t_line].l_close)(tp);
323 if (t)
4b72e2f9 324 (*linesw[t].l_open)(dev, tp);
89dc6dfb
BJ
325 if (u.u_error==0)
326 tp->t_line = t;
8062c8a7 327 (void) spl0();
89dc6dfb 328 break;
4b72e2f9 329 }
89dc6dfb 330
152c2598
BJ
331 /*
332 * Prevent more opens on channel
333 */
334 case TIOCEXCL:
335 tp->t_state |= TS_XCLUDE;
336 break;
337
338 case TIOCNXCL:
339 tp->t_state &= ~TS_XCLUDE;
340 break;
341
89dc6dfb
BJ
342 /*
343 * Set new parameters
344 */
345 case TIOCSETP:
4b72e2f9
SL
346 case TIOCSETN: {
347 register struct sgttyb *sg = (struct sgttyb *)data;
348 struct clist tq;
349
101ba270 350 (void) spl5();
4b72e2f9 351 if (tp->t_flags&RAW || sg->sg_flags&RAW || com == TIOCSETP)
e1d74936 352 wflushtty(tp);
4b72e2f9
SL
353 else if ((tp->t_flags&CBREAK) != (sg->sg_flags&CBREAK)) {
354 if (sg->sg_flags & CBREAK) {
e1d74936
BJ
355 catq(&tp->t_rawq, &tp->t_canq);
356 tq = tp->t_rawq;
357 tp->t_rawq = tp->t_canq;
358 tp->t_canq = tq;
359 } else {
360 tp->t_local |= LPENDIN;
361 ttwakeup(tp);
8062c8a7
BJ
362 }
363 }
4b72e2f9
SL
364 tp->t_ispeed = sg->sg_ispeed;
365 tp->t_ospeed = sg->sg_ospeed;
366 tp->t_erase = sg->sg_erase;
367 tp->t_kill = sg->sg_kill;
368 tp->t_flags = sg->sg_flags;
627c86ee 369 if (tp->t_flags & RAW) {
941944c9 370 tp->t_state &= ~TS_TTSTOP;
627c86ee
KB
371 ttstart(tp);
372 }
101ba270 373 (void) spl0();
89dc6dfb 374 break;
4b72e2f9 375 }
89dc6dfb
BJ
376
377 /*
50e2732b 378 * Send current parameters to user
89dc6dfb 379 */
4b72e2f9
SL
380 case TIOCGETP: {
381 register struct sgttyb *sg = (struct sgttyb *)data;
382
383 sg->sg_ispeed = tp->t_ispeed;
384 sg->sg_ospeed = tp->t_ospeed;
385 sg->sg_erase = tp->t_erase;
386 sg->sg_kill = tp->t_kill;
387 sg->sg_flags = tp->t_flags;
89dc6dfb 388 break;
4b72e2f9 389 }
89dc6dfb
BJ
390
391 /*
392 * Hang up line on last close
393 */
89dc6dfb 394 case TIOCHPCL:
941944c9 395 tp->t_state |= TS_HUPCLS;
89dc6dfb
BJ
396 break;
397
7d973a4d 398 case TIOCFLUSH: {
4b72e2f9
SL
399 register int flags = *(int *)data;
400
401 if (flags == 0)
7d973a4d 402 flags = FREAD|FWRITE;
4b72e2f9
SL
403 else
404 flags &= FREAD|FWRITE;
7d973a4d 405 flushtty(tp, flags);
89dc6dfb 406 break;
4568c08e 407 }
89dc6dfb 408
4b72e2f9
SL
409 case FIONBIO:
410 if (*(int *)data)
941944c9
BJ
411 tp->t_state |= TS_NBIO;
412 else
413 tp->t_state &= ~TS_NBIO;
414 break;
941944c9 415
4b72e2f9
SL
416 case FIOASYNC:
417 if (*(int *)data)
a66e4149
BJ
418 tp->t_state |= TS_ASYNC;
419 else
420 tp->t_state &= ~TS_ASYNC;
421 break;
a66e4149 422
89dc6dfb 423 /*
50e2732b 424 * Set and fetch special characters
89dc6dfb
BJ
425 */
426 case TIOCSETC:
4b72e2f9 427 bcopy(data, (caddr_t)&tun, sizeof (struct tchars));
89dc6dfb
BJ
428 break;
429
430 case TIOCGETC:
4b72e2f9 431 bcopy((caddr_t)&tun, data, sizeof (struct tchars));
8062c8a7
BJ
432 break;
433
434/* local ioctls */
50e2732b
BJ
435 /*
436 * Set/get local special characters.
437 */
8062c8a7 438 case TIOCSLTC:
4b72e2f9 439 bcopy(data, (caddr_t)&tlun, sizeof (struct ltchars));
8062c8a7
BJ
440 break;
441
442 case TIOCGLTC:
4b72e2f9 443 bcopy((caddr_t)&tlun, data, sizeof (struct ltchars));
8062c8a7
BJ
444 break;
445
50e2732b
BJ
446 /*
447 * Return number of characters immediately available.
448 */
4b72e2f9
SL
449 case FIONREAD:
450 *(off_t *)data = ttnread(tp);
8062c8a7 451 break;
8062c8a7
BJ
452
453 /*
454 * Should allow SPGRP and GPGRP only if tty open for reading.
455 */
456 case TIOCSPGRP:
4b72e2f9 457 tp->t_pgrp = *(int *)data;
8062c8a7
BJ
458 break;
459
460 case TIOCGPGRP:
4b72e2f9 461 *(int *)data = tp->t_pgrp;
8062c8a7
BJ
462 break;
463
464 /*
465 * Modify local mode word.
466 */
467 case TIOCLBIS:
4b72e2f9 468 tp->t_local |= *(int *)data;
8062c8a7
BJ
469 break;
470
471 case TIOCLBIC:
4b72e2f9 472 tp->t_local &= ~(*(int *)data);
8062c8a7
BJ
473 break;
474
475 case TIOCLSET:
4b72e2f9 476 tp->t_local = *(int *)data;
8062c8a7
BJ
477 break;
478
479 case TIOCLGET:
4b72e2f9 480 *(int *)data = tp->t_local;
0dde1c43
BJ
481 break;
482
4b72e2f9
SL
483 case TIOCSTOP: {
484 int s = spl5();
bfcf09ee 485
bfcf09ee
BJ
486 if ((tp->t_state & TS_TTSTOP) == 0) {
487 tp->t_state |= TS_TTSTOP;
488 (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
489 }
4b72e2f9 490 splx(s);
bfcf09ee 491 break;
4b72e2f9
SL
492 }
493
494 case TIOCSTART: {
495 int s = spl5();
bfcf09ee 496
bfcf09ee
BJ
497 if ((tp->t_state & TS_TTSTOP) || (tp->t_local & LFLUSHO)) {
498 tp->t_state &= ~TS_TTSTOP;
499 tp->t_local &= ~LFLUSHO;
500 ttstart(tp);
501 }
4b72e2f9 502 splx(s);
bfcf09ee 503 break;
4b72e2f9 504 }
bfcf09ee 505
8062c8a7 506/* end of locals */
50450a20 507
89dc6dfb 508 default:
4b72e2f9 509 return (0);
89dc6dfb 510 }
4b72e2f9 511 return (1);
89dc6dfb 512}
e1d74936
BJ
513
514ttnread(tp)
515 struct tty *tp;
516{
517 int nread = 0;
518
519 if (tp->t_local & LPENDIN)
520 ttypend(tp);
521 nread = tp->t_canq.c_cc;
522 if (tp->t_flags & (RAW|CBREAK))
523 nread += tp->t_rawq.c_cc;
524 return (nread);
525}
526
941944c9 527ttselect(dev, rw)
e1d74936 528 dev_t dev;
941944c9 529 int rw;
e1d74936
BJ
530{
531 register struct tty *tp = &cdevsw[major(dev)].d_ttys[minor(dev)];
532 int nread;
941944c9 533 int s = spl5();
e1d74936 534
941944c9 535 switch (rw) {
e1d74936
BJ
536
537 case FREAD:
538 nread = ttnread(tp);
539 if (nread > 0)
941944c9 540 goto win;
89b8a44c 541 if (tp->t_rsel && tp->t_rsel->p_wchan == (caddr_t)&selwait)
941944c9 542 tp->t_state |= TS_RCOLL;
e1d74936
BJ
543 else
544 tp->t_rsel = u.u_procp;
941944c9 545 break;
e1d74936 546
941944c9
BJ
547 case FWRITE:
548 if (tp->t_outq.c_cc <= TTLOWAT(tp))
549 goto win;
941944c9
BJ
550 if (tp->t_wsel && tp->t_wsel->p_wchan == (caddr_t)&selwait)
551 tp->t_state |= TS_WCOLL;
552 else
553 tp->t_wsel = u.u_procp;
554 break;
e1d74936 555 }
941944c9
BJ
556 splx(s);
557 return (0);
558win:
559 splx(s);
560 return (1);
e1d74936 561}
8bba2b8f 562
4147b3f6
BJ
563#define OBUFSIZ 100
564
565/*
566 * routine called on opens while tp->t_line == NTTYDISC
567 * establishes a process group for distribution of
568 * quits and interrupts from the tty.
569 * (actually, pp->p_pgrp can't be 0 when this routine
570 * is called since NTTYDISC is not the default discipline)
571 */
572ttyopen(dev, tp)
4b72e2f9
SL
573 dev_t dev;
574 register struct tty *tp;
4147b3f6
BJ
575{
576 register struct proc *pp;
577
578 pp = u.u_procp;
579 tp->t_dev = dev;
4b72e2f9 580 if (pp->p_pgrp == 0) {
4147b3f6
BJ
581 u.u_ttyp = tp;
582 u.u_ttyd = dev;
583 if (tp->t_pgrp == 0)
584 tp->t_pgrp = pp->p_pid;
585 pp->p_pgrp = tp->t_pgrp;
586 }
587 tp->t_state &= ~TS_WOPEN;
588 tp->t_state |= TS_ISOPEN;
589 if (tp->t_line != NTTYDISC)
590 wflushtty(tp);
591}
592
593/*
594 * clean tp on last close
595 */
596ttyclose(tp)
4b72e2f9 597 register struct tty *tp;
4147b3f6
BJ
598{
599
600 if (tp->t_line) {
601 wflushtty(tp);
602 tp->t_line = 0;
603 return;
604 }
605 tp->t_pgrp = 0;
606 wflushtty(tp);
607 tp->t_state = 0;
608}
609
610/*
611 * reinput pending characters after state switch
612 * call at spl5().
613 */
614ttypend(tp)
4b72e2f9 615 register struct tty *tp;
4147b3f6
BJ
616{
617 struct clist tq;
618 register c;
619
620 tp->t_local &= ~LPENDIN;
621 tp->t_lstate |= LSTYPEN;
622 tq = tp->t_rawq;
623 tp->t_rawq.c_cc = 0;
624 tp->t_rawq.c_cf = tp->t_rawq.c_cl = 0;
625 while ((c = getc(&tq)) >= 0)
626 ttyinput(c, tp);
627 tp->t_lstate &= ~LSTYPEN;
628}
629
630/*
631 * Place a character on raw TTY input queue, putting in delimiters
632 * and waking up top half as needed.
633 * Also echo if required.
634 * The arguments are the character and the appropriate
635 * tty structure.
636 */
637ttyinput(c, tp)
4b72e2f9
SL
638 register c;
639 register struct tty *tp;
4147b3f6
BJ
640{
641 register int t_flags;
642 int i;
643
644 if (tp->t_local&LPENDIN)
645 ttypend(tp);
646 tk_nin++;
647 c &= 0377;
648 t_flags = tp->t_flags;
649 if (t_flags&TANDEM)
650 ttyblock(tp);
651 if ((t_flags&RAW)==0) {
652 if ((tp->t_lstate&LSTYPEN) == 0)
653 c &= 0177;
654 /* check for literal nexting very first */
655 if (tp->t_lstate&LSLNCH) {
656 c |= 0200;
657 tp->t_lstate &= ~LSLNCH;
658 }
659 if (tp->t_line == NTTYDISC && c==tlun.t_lnextc) {
660 if (tp->t_flags&ECHO)
661 ttyout("^\b", tp);
662 tp->t_lstate |= LSLNCH;
663 /* check for output control functions */
664 } else if (c==tun.t_stopc) {
665 if ((tp->t_state&TS_TTSTOP)==0) {
666 tp->t_state |= TS_TTSTOP;
667 (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
668 return;
669 }
670 if (c!=tun.t_startc)
671 return;
672 } else if (c==tun.t_startc) {
673 tp->t_state &= ~TS_TTSTOP;
674 tp->t_local &= ~LFLUSHO;
675 ttstart(tp);
676 return;
677 } else if (tp->t_line == NTTYDISC && c==tlun.t_flushc) {
678 if (tp->t_local & LFLUSHO)
679 tp->t_local &= ~LFLUSHO;
680 else {
681 flushtty(tp, FWRITE);
682 ttyecho(c, tp);
683 if (tp->t_rawq.c_cc+tp->t_canq.c_cc)
684 ttyretype(tp);
685 tp->t_local |= LFLUSHO;
686 }
687 ttstart(tp);
688 return;
689 } else if (c==tun.t_intrc || c==tun.t_quitc ||
690 (tp->t_line == NTTYDISC && c==tlun.t_suspc)) {
691 if ((tp->t_local & LNOFLSH) == 0)
692 flushtty(tp,
693 c==tlun.t_suspc ? FREAD : FREAD|FWRITE);
694 ttyecho(c, tp);
695 c = c==tun.t_intrc ? SIGINT :
696 ((c==tun.t_quitc) ? SIGQUIT : SIGTSTP);
697 ttsignal(tp, c);
698 /* check for buffer editing functions - cooked mode */
699 } else if ((t_flags&CBREAK) == 0) {
700 if ((tp->t_lstate&LSQUOT) &&
701 (c==tp->t_erase||c==tp->t_kill)) {
702 ttyrub(unputc(&tp->t_rawq), tp);
703 c |= 0200;
704 }
705 if (c==tp->t_erase) {
706 if (tp->t_rawq.c_cc)
707 ttyrub(unputc(&tp->t_rawq), tp);
708 } else if (c==tp->t_kill) {
709 if (tp->t_local&LCRTKIL &&
710 tp->t_rawq.c_cc == tp->t_rocount) {
711 while (tp->t_rawq.c_cc)
712 ttyrub(unputc(&tp->t_rawq), tp);
713 } else {
714 ttyecho(c, tp);
715 ttyecho('\n', tp);
716 while (getc(&tp->t_rawq) > 0)
717 ;
718 tp->t_rocount = 0;
719 }
720 tp->t_lstate = 0;
721 } else if (tp->t_line == NTTYDISC && c==tlun.t_werasc) {
722 if (tp->t_rawq.c_cc == 0)
723 goto out;
724 do {
725 c = unputc(&tp->t_rawq);
726 if (c != ' ' && c != '\t')
727 goto erasenb;
728 ttyrub(c, tp);
729 } while (tp->t_rawq.c_cc);
730 goto out;
731 erasenb:
732 do {
733 ttyrub(c, tp);
734 if (tp->t_rawq.c_cc == 0)
735 goto out;
736 c = unputc(&tp->t_rawq);
737 } while (c != ' ' && c != '\t');
738 (void) putc(c, &tp->t_rawq);
739 } else if (tp->t_line == NTTYDISC && c==tlun.t_rprntc) {
740 ttyretype(tp);
741 /* check for cooked mode input buffer overflow */
742 } else if (tp->t_rawq.c_cc+tp->t_canq.c_cc >= TTYHOG) {
743 ;
744 /* put data char in q for user and wakeup if a break char */
745 } else if (putc(c, &tp->t_rawq) >= 0) {
746 if (tp->t_rawq.c_cc+tp->t_canq.c_cc==TTYHOG
747 && tp->t_line == NTTYDISC)
748 (void) ttyoutput(CTRL(g), tp);
749 if (!ttbreakc(c, tp)) {
750 if (tp->t_rocount++ == 0)
751 tp->t_rocol = tp->t_col;
752 } else {
753 tp->t_rocount = 0;
754 catq(&tp->t_rawq, &tp->t_canq);
755 /* IF (TP->T_CHAN) (VOID) SDATA(TP->T_CHAN); */
756 ttwakeup(tp);
757 }
758 tp->t_lstate &= ~LSQUOT;
759 if (c == '\\')
760 tp->t_lstate |= LSQUOT;
761 if (tp->t_lstate&LSERASE) {
762 tp->t_lstate &= ~LSERASE;
763 (void) ttyoutput('/', tp);
764 }
765 i = tp->t_col;
766 ttyecho(c, tp);
767 if (c==tun.t_eofc && tp->t_flags&ECHO) {
768 i = MIN(2, tp->t_col - i);
769 while (i > 0) {
770 (void) ttyoutput('\b', tp);
771 i--;
772 }
773 }
774 }
775 /* CBREAK mode */
776 } else if (tp->t_rawq.c_cc > TTYHOG) {
777 if (tp->t_outq.c_cc < TTHIWAT(tp) &&
778 tp->t_line == NTTYDISC)
779 (void) ttyoutput(CTRL(g), tp);
780 } else if (putc(c, &tp->t_rawq) >= 0) {
781 ttwakeup(tp);
782 ttyecho(c, tp);
783 }
784 /* RAW mode */
785 } else if (tp->t_rawq.c_cc > TTYHOG)
786 flushtty(tp, FREAD|FWRITE);
787 else {
788 if (putc(c, &tp->t_rawq) >= 0)
789 ttwakeup(tp);
790 ttyecho(c, tp);
791 }
792out:
793 if (tp->t_local & LDECCTQ && tp->t_state & TS_TTSTOP &&
794 tun.t_startc != tun.t_stopc)
795 return;
796 tp->t_state &= ~TS_TTSTOP;
797 tp->t_local &= ~LFLUSHO;
798 ttstart(tp);
799}
800
801/*
802 * put character on TTY output queue, adding delays,
803 * expanding tabs, and handling the CR/NL bit.
804 * It is called both from the top half for output, and from
805 * interrupt level for echoing.
806 * The arguments are the character and the tty structure.
807 * Returns < 0 if putc succeeds, otherwise returns char to resend
808 * Must be recursive.
809 */
810ttyoutput(c, tp)
811 register c;
812 register struct tty *tp;
813{
814 register char *colp;
815 register ctype;
816
817 if (tp->t_flags&RAW || tp->t_local&LLITOUT) {
818 if (tp->t_local&LFLUSHO)
819 return (-1);
820 if (putc(c, &tp->t_outq))
4b72e2f9 821 return (c);
4147b3f6
BJ
822 tk_nout++;
823 return (-1);
824 }
825 /*
826 * Ignore EOT in normal mode to avoid hanging up
827 * certain terminals.
828 */
829 c &= 0177;
830 if (c==CEOT && (tp->t_flags&CBREAK)==0)
831 return (-1);
832 /*
833 * Turn tabs to spaces as required
834 */
835 if (c=='\t' && (tp->t_flags&TBDELAY)==XTABS) {
836 register int s;
837
838 c = 8 - (tp->t_col&7);
839 if ((tp->t_local&LFLUSHO) == 0) {
840 s = spl5(); /* don't interrupt tabs */
841 c -= b_to_q(" ", c, &tp->t_outq);
842 tk_nout += c;
843 splx(s);
844 }
845 tp->t_col += c;
846 return (c ? -1 : '\t');
847 }
848 tk_nout++;
849 /*
850 * for upper-case-only terminals,
851 * generate escapes.
852 */
853 if (tp->t_flags&LCASE) {
854 colp = "({)}!|^~'`";
4b72e2f9
SL
855 while (*colp++)
856 if (c == *colp++) {
4147b3f6
BJ
857 if (ttyoutput('\\', tp) >= 0)
858 return (c);
859 c = colp[-2];
860 break;
861 }
862 if ('A'<=c && c<='Z') {
863 if (ttyoutput('\\', tp) >= 0)
864 return (c);
865 } else if ('a'<=c && c<='z')
866 c += 'A' - 'a';
867 }
868 /*
869 * turn <nl> to <cr><lf> if desired.
870 */
871 if (c=='\n' && tp->t_flags&CRMOD)
872 if (ttyoutput('\r', tp) >= 0)
873 return (c);
874 if (c=='~' && tp->t_local&LTILDE)
875 c = '`';
876 if ((tp->t_local&LFLUSHO) == 0 && putc(c, &tp->t_outq))
877 return (c);
878 /*
879 * Calculate delays.
880 * The numbers here represent clock ticks
881 * and are not necessarily optimal for all terminals.
882 * The delays are indicated by characters above 0200.
883 * In raw mode there are no delays and the
884 * transmission path is 8 bits wide.
885 */
886 colp = &tp->t_col;
887 ctype = partab[c];
888 c = 0;
889 switch (ctype&077) {
890
891 case ORDINARY:
892 (*colp)++;
893
894 case CONTROL:
895 break;
896
897 case BACKSPACE:
898 if (*colp)
899 (*colp)--;
900 break;
901
902 case NEWLINE:
903 ctype = (tp->t_flags >> 8) & 03;
4b72e2f9 904 if (ctype == 1) { /* tty 37 */
4147b3f6
BJ
905 if (*colp)
906 c = max(((unsigned)*colp>>4) + 3, (unsigned)6);
907 } else
4b72e2f9 908 if (ctype == 2) { /* vt05 */
4147b3f6
BJ
909 c = 6;
910 }
911 *colp = 0;
912 break;
913
914 case TAB:
915 ctype = (tp->t_flags >> 10) & 03;
4b72e2f9 916 if (ctype == 1) { /* tty 37 */
4147b3f6 917 c = 1 - (*colp | ~07);
4b72e2f9 918 if (c < 5)
4147b3f6
BJ
919 c = 0;
920 }
921 *colp |= 07;
922 (*colp)++;
923 break;
924
925 case VTAB:
4b72e2f9 926 if (tp->t_flags & VTDELAY) /* tty 37 */
4147b3f6
BJ
927 c = 0177;
928 break;
929
930 case RETURN:
931 ctype = (tp->t_flags >> 12) & 03;
4b72e2f9 932 if (ctype == 1) { /* tn 300 */
4147b3f6 933 c = 5;
4b72e2f9 934 } else if (ctype == 2) { /* ti 700 */
4147b3f6 935 c = 10;
4b72e2f9 936 } else if (ctype == 3) { /* concept 100 */
4147b3f6
BJ
937 int i;
938 if ((i = *colp) >= 0)
939 for (; i<9; i++)
940 (void) putc(0177, &tp->t_outq);
941 }
942 *colp = 0;
943 }
4b72e2f9 944 if (c && (tp->t_local&LFLUSHO) == 0)
4147b3f6
BJ
945 (void) putc(c|0200, &tp->t_outq);
946 return (-1);
947}
948
949/*
950 * Called from device's read routine after it has
951 * calculated the tty-structure given as argument.
952 */
d6d7360b 953ttread(tp, uio)
4b72e2f9 954 register struct tty *tp;
d6d7360b 955 struct uio *uio;
4147b3f6
BJ
956{
957 register struct clist *qp;
958 register c, first;
959
960 if ((tp->t_state&TS_CARR_ON)==0)
4b72e2f9 961 return (0);
4147b3f6
BJ
962loop:
963 (void) spl5();
964 if (tp->t_local&LPENDIN)
965 ttypend(tp);
966 (void) spl0();
967 while (tp == u.u_ttyp && u.u_procp->p_pgrp != tp->t_pgrp) {
968 if (u.u_signal[SIGTTIN] == SIG_IGN ||
969 u.u_signal[SIGTTIN] == SIG_HOLD ||
970/*
971 (u.u_procp->p_flag&SDETACH) ||
972*/
973 u.u_procp->p_flag&SVFORK)
974 return (0);
975 gsignal(u.u_procp->p_pgrp, SIGTTIN);
976 sleep((caddr_t)&lbolt, TTIPRI);
977 }
978 if (tp->t_flags&RAW) {
979 (void) spl5();
980 if (tp->t_rawq.c_cc <= 0) {
981 if ((tp->t_state&TS_CARR_ON)==0 ||
982 (tp->t_state&TS_NBIO)) {
983 (void) spl0();
984 return (0);
985 }
986 sleep((caddr_t)&tp->t_rawq, TTIPRI);
987 (void) spl0();
988 goto loop;
989 }
990 (void) spl0();
d6d7360b
BJ
991 while (tp->t_rawq.c_cc && uio->uio_iovcnt) {
992 u.u_error = passuc(getc(&tp->t_rawq), uio);
993 if (u.u_error)
994 break;
995 }
4147b3f6
BJ
996 return (0);
997 } else {
998 qp = tp->t_flags & CBREAK ? &tp->t_rawq : &tp->t_canq;
999 (void) spl5();
1000 if (qp->c_cc <= 0) {
1001 if ((tp->t_state&TS_CARR_ON)==0 ||
1002 (tp->t_state&TS_NBIO)) {
1003 (void) spl0();
1004 return (0);
1005 }
1006 sleep((caddr_t)&tp->t_rawq, TTIPRI);
1007 (void) spl0();
1008 goto loop;
1009 }
1010 (void) spl0();
1011 first = 1;
1012 while ((c = getc(qp)) >= 0) {
1013 if (tp->t_flags&CRMOD && c == '\r')
1014 c = '\n';
1015 if (tp->t_flags&LCASE && c <= 0177)
1016 if (tp->t_lstate&LSBKSL) {
1017 if (maptab[c])
1018 c = maptab[c];
1019 tp->t_lstate &= ~LSBKSL;
1020 } else if (c >= 'A' && c <= 'Z')
1021 c += 'a' - 'A';
1022 else if (c == '\\') {
1023 tp->t_lstate |= LSBKSL;
1024 continue;
1025 }
f2f41cda 1026 if (tp->t_line == NTTYDISC && c == tlun.t_dsuspc) {
4147b3f6
BJ
1027 ttsignal(tp, SIGTSTP);
1028 if (first) {
1029 sleep((caddr_t)&lbolt, TTIPRI);
1030 goto loop;
1031 }
1032 break;
1033 }
1034 if (c == tun.t_eofc && (tp->t_flags&CBREAK)==0)
1035 break;
d6d7360b
BJ
1036 u.u_error = passuc(c & 0177, uio);
1037 if (u.u_error)
1038 break;
1039 if (uio->uio_iovcnt == 0)
4147b3f6
BJ
1040 break;
1041 if ((tp->t_flags&CBREAK)==0 && ttbreakc(c, tp))
1042 break;
1043 first = 0;
1044 }
1045 tp->t_lstate &= ~LSBKSL;
1046 }
1047
1048 if (tp->t_state&TS_TBLOCK && tp->t_rawq.c_cc < TTYHOG/5) {
1049 if (putc(tun.t_startc, &tp->t_outq)==0) {
1050 tp->t_state &= ~TS_TBLOCK;
1051 ttstart(tp);
1052 }
1053 tp->t_char = 0;
1054 }
1055
1056 return (tp->t_rawq.c_cc + tp->t_canq.c_cc);
1057}
1058
1059/*
1060 * Called from the device's write routine after it has
1061 * calculated the tty-structure given as argument.
1062 */
1063caddr_t
913ea2d1 1064ttwrite(tp, uio)
4b72e2f9 1065 register struct tty *tp;
913ea2d1 1066 struct uio *uio;
4147b3f6
BJ
1067{
1068#ifdef vax
1069 /*
1070 * THE POSITIONING OF CP, CC, AND CE ARE CRITICAL
1071 * AND MUST NOT BE CHANGED WITHOUT PATCHING
1072 * THE 'ASM' INLINES BELOW. WATCH OUT.
1073 */
1074#endif
1075 register char *cp;
1076 register int cc, ce;
1077 register i;
1078 char obuf[OBUFSIZ];
1079 register c;
1080 int hiwat = TTHIWAT(tp);
913ea2d1 1081 int cnt = uio->uio_resid;
4147b3f6
BJ
1082
1083 if ((tp->t_state&TS_CARR_ON)==0)
1084 return (NULL);
1085loop:
1086 while (u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp &&
1087 (tp->t_local&LTOSTOP) && (u.u_procp->p_flag&SVFORK)==0 &&
1088 u.u_signal[SIGTTOU] != SIG_IGN &&
1089 u.u_signal[SIGTTOU] != SIG_HOLD
1090/*
1091 &&
1092 (u.u_procp->p_flag&SDETACH)==0) {
1093*/
1094 ) {
1095 gsignal(u.u_procp->p_pgrp, SIGTTOU);
1096 sleep((caddr_t)&lbolt, TTIPRI);
1097 }
913ea2d1
BJ
1098 while (uio->uio_resid > 0) {
1099 cc = uio->uio_iov->iov_len;
1100 if (cc == 0) {
1101 uio->uio_iovcnt--;
1102 uio->uio_iov++;
1103 if (uio->uio_iovcnt < 0)
1104 panic("ttwrite");
1105 continue;
1106 }
1107 if (cc > OBUFSIZ)
1108 cc = OBUFSIZ;
4147b3f6 1109 cp = obuf;
913ea2d1 1110 u.u_error = uiomove(cp, cc, UIO_WRITE, uio);
4147b3f6
BJ
1111 if (u.u_error)
1112 break;
1113 if (tp->t_outq.c_cc > hiwat)
1114 goto ovhiwat;
1115 if (tp->t_local&LFLUSHO)
1116 continue;
1117 if (tp->t_flags&LCASE || tp->t_local&LTILDE) {
1118 while (cc) {
1119 c = *cp++;
1120 tp->t_rocount = 0;
4b72e2f9 1121 while ((c = ttyoutput(c, tp)) >= 0) {
4147b3f6
BJ
1122 /* out of clists, wait a bit */
1123 ttstart(tp);
1124 sleep((caddr_t)&lbolt, TTOPRI);
1125 tp->t_rocount = 0;
1126 }
1127 --cc;
1128 if (tp->t_outq.c_cc > hiwat)
1129 goto ovhiwat;
1130 }
1131 continue;
1132 }
1133 while (cc) {
1134 if (tp->t_flags&RAW || tp->t_local&LLITOUT)
1135 ce = cc;
1136 else {
1137#ifdef vax
1138 asm(" scanc r9,(r10),_partab,$077");
1139 asm(" subl3 r0,r9,r8");
1140#else
1141 ce=0;
4b72e2f9 1142 while (((partab[*(unsigned char *)(cp+ce)]&077)==0)&&(ce<cc))
4147b3f6
BJ
1143 ce++;
1144#endif
1145 if (ce==0) {
1146 tp->t_rocount = 0;
1147 if (ttyoutput(*cp, tp) >= 0) {
1148 ttstart(tp);
1149 sleep((caddr_t)&lbolt, TTOPRI);
1150 continue;
1151 }
1152 cp++;
1153 cc--;
1154 if (tp->t_outq.c_cc > hiwat)
1155 goto ovhiwat;
1156 }
1157 }
1158 tp->t_rocount = 0;
1159 i=b_to_q(cp,ce,&tp->t_outq);
1160 ce-=i;
1161 tk_nout+=ce;
1162 tp->t_col+=ce;
1163 cp+=ce;
1164 cc-=ce;
1165 if (i) {
1166 ttstart(tp);
1167 sleep((caddr_t)&lbolt, TTOPRI);
1168 }
1169 if (ce || tp->t_outq.c_cc > hiwat)
1170 goto ovhiwat;
1171 }
1172 }
1173 ttstart(tp);
4b72e2f9 1174 return (NULL);
4147b3f6
BJ
1175
1176ovhiwat:
1177 (void) spl5();
913ea2d1
BJ
1178 uio->uio_iov->iov_base -= cc;
1179 uio->uio_iov->iov_len += cc;
1180 uio->uio_resid += cc;
1181 uio->uio_offset -= cc;
4147b3f6
BJ
1182 if (tp->t_outq.c_cc <= hiwat) {
1183 (void) spl0();
1184 goto loop;
1185 }
1186 ttstart(tp);
1187 if (tp->t_state & TS_NBIO) {
913ea2d1 1188 if (uio->uio_resid == cnt)
4147b3f6
BJ
1189 u.u_error = EWOULDBLOCK;
1190 return (NULL);
1191 }
1192 tp->t_state |= TS_ASLEEP;
1193 sleep((caddr_t)&tp->t_outq, TTOPRI);
1194 (void) spl0();
1195 goto loop;
1196}
1197
1198/*
1199 * Rubout one character from the rawq of tp
1200 * as cleanly as possible.
1201 */
1202ttyrub(c, tp)
4b72e2f9
SL
1203 register c;
1204 register struct tty *tp;
4147b3f6
BJ
1205{
1206 register char *cp;
1207 register int savecol;
1208 int s;
1209 char *nextc();
1210
1211 if ((tp->t_flags&ECHO)==0)
1212 return;
1213 tp->t_local &= ~LFLUSHO;
1214 c &= 0377;
1215 if (tp->t_local&LCRTBS) {
1216 if (tp->t_rocount == 0) {
1217 /*
1218 * Screwed by ttwrite; retype
1219 */
1220 ttyretype(tp);
1221 return;
1222 }
1223 if (c==('\t'|0200) || c==('\n'|0200))
1224 ttyrubo(tp, 2);
4b72e2f9 1225 else switch (partab[c&=0177] & 0177) {
4147b3f6
BJ
1226
1227 case ORDINARY:
1228 if (tp->t_flags&LCASE && c >= 'A' && c <= 'Z')
1229 ttyrubo(tp, 2);
1230 else
1231 ttyrubo(tp, 1);
1232 break;
1233
1234 case VTAB:
1235 case BACKSPACE:
1236 case CONTROL:
1237 case RETURN:
1238 if (tp->t_local & LCTLECH)
1239 ttyrubo(tp, 2);
1240 break;
1241
1242 case TAB:
1243 if (tp->t_rocount < tp->t_rawq.c_cc) {
1244 ttyretype(tp);
1245 return;
1246 }
1247 s = spl5();
1248 savecol = tp->t_col;
1249 tp->t_lstate |= LSCNTTB;
1250 tp->t_local |= LFLUSHO;
1251 tp->t_col = tp->t_rocol;
1252 for (cp = tp->t_rawq.c_cf; cp; cp = nextc(&tp->t_rawq, cp))
1253 ttyecho(*cp, tp);
1254 tp->t_local &= ~LFLUSHO;
1255 tp->t_lstate &= ~LSCNTTB;
1256 splx(s);
1257 /*
1258 * savecol will now be length of the tab
1259 */
1260 savecol -= tp->t_col;
1261 tp->t_col += savecol;
1262 if (savecol > 8)
1263 savecol = 8; /* overflow screw */
1264 while (--savecol >= 0)
1265 (void) ttyoutput('\b', tp);
1266 break;
1267
1268 default:
1269 panic("ttyrub");
1270 }
1271 } else if (tp->t_local&LPRTERA) {
1272 if ((tp->t_lstate&LSERASE) == 0) {
1273 (void) ttyoutput('\\', tp);
1274 tp->t_lstate |= LSERASE;
1275 }
1276 ttyecho(c, tp);
1277 } else
1278 ttyecho(tp->t_erase, tp);
1279 tp->t_rocount--;
1280}
1281
1282/*
1283 * Crt back over cnt chars perhaps
1284 * erasing them.
1285 */
1286ttyrubo(tp, cnt)
4b72e2f9
SL
1287 register struct tty *tp;
1288 int cnt;
4147b3f6
BJ
1289{
1290
1291 while (--cnt >= 0)
1292 ttyout(tp->t_local&LCRTERA ? "\b \b" : "\b", tp);
1293}
1294
1295/*
1296 * Reprint the rawq line.
1297 * We assume c_cc has already been checked.
1298 */
1299ttyretype(tp)
4b72e2f9 1300 register struct tty *tp;
4147b3f6
BJ
1301{
1302 register char *cp;
1303 char *nextc();
1304 int s;
1305
1306 if (tlun.t_rprntc != 0377)
1307 ttyecho(tlun.t_rprntc, tp);
1308 (void) ttyoutput('\n', tp);
1309 s = spl5();
1310 for (cp = tp->t_canq.c_cf; cp; cp = nextc(&tp->t_canq, cp))
1311 ttyecho(*cp, tp);
1312 for (cp = tp->t_rawq.c_cf; cp; cp = nextc(&tp->t_rawq, cp))
1313 ttyecho(*cp, tp);
1314 tp->t_lstate &= ~LSERASE;
1315 splx(s);
1316 tp->t_rocount = tp->t_rawq.c_cc;
1317 tp->t_rocol = 0;
1318}
1319
1320/*
1321 * Echo a typed character to the terminal
1322 */
1323ttyecho(c, tp)
4b72e2f9
SL
1324 register c;
1325 register struct tty *tp;
4147b3f6
BJ
1326{
1327
1328 if ((tp->t_lstate & LSCNTTB) == 0)
1329 tp->t_local &= ~LFLUSHO;
1330 if ((tp->t_flags&ECHO) == 0)
1331 return;
1332 c &= 0377;
1333 if (tp->t_flags&RAW) {
1334 (void) ttyoutput(c, tp);
1335 return;
1336 }
1337 if (c == '\r' && tp->t_flags&CRMOD)
1338 c = '\n';
1339 if (tp->t_local&LCTLECH) {
1340 if ((c&0177) <= 037 && c!='\t' && c!='\n' || (c&0177)==0177) {
1341 (void) ttyoutput('^', tp);
1342 c &= 0177;
1343 if (c == 0177)
1344 c = '?';
1345 else if (tp->t_flags&LCASE)
1346 c += 'a' - 1;
1347 else
1348 c += 'A' - 1;
1349 }
1350 }
1351 if ((tp->t_flags&LCASE) && (c >= 'A' && c <= 'Z'))
1352 c += 'a' - 'A';
1353 (void) ttyoutput(c & 0177, tp);
1354}
1355
1356/*
1357 * Is c a break char for tp?
1358 */
1359ttbreakc(c, tp)
4b72e2f9
SL
1360 register c;
1361 register struct tty *tp;
4147b3f6
BJ
1362{
1363 return (c == '\n' || c == tun.t_eofc || c == tun.t_brkc ||
1364 c == '\r' && (tp->t_flags&CRMOD));
1365}
1366
1367/*
1368 * send string cp to tp
1369 */
1370ttyout(cp, tp)
4b72e2f9
SL
1371 register char *cp;
1372 register struct tty *tp;
4147b3f6
BJ
1373{
1374 register char c;
1375
1376 while (c = *cp++)
1377 (void) ttyoutput(c, tp);
1378}
1379
1380ttwakeup(tp)
1381 struct tty *tp;
1382{
1383
1384 if (tp->t_rsel) {
1385 selwakeup(tp->t_rsel, tp->t_state&TS_RCOLL);
1386 tp->t_state &= ~TS_RCOLL;
1387 tp->t_rsel = 0;
1388 }
1389 wakeup((caddr_t)&tp->t_rawq);
1390}
1391
1392ttsignal(tp, signo)
1393 struct tty *tp;
1394 int signo;
1395{
1396
1397 gsignal(tp->t_pgrp, signo);
1398}