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