sun merge
[unix-history] / usr / src / sys / kern / tty.c
CommitLineData
961945a8
SL
1/* tty.c 4.37 82/12/17 */
2
3#include "../machine/reg.h"
89dc6dfb 4
89dc6dfb
BJ
5#include "../h/param.h"
6#include "../h/systm.h"
7#include "../h/dir.h"
8#include "../h/user.h"
becb115c 9#include "../h/ioctl.h"
89dc6dfb
BJ
10#include "../h/tty.h"
11#include "../h/proc.h"
89dc6dfb
BJ
12#include "../h/inode.h"
13#include "../h/file.h"
89dc6dfb
BJ
14#include "../h/conf.h"
15#include "../h/buf.h"
d1778415 16#include "../h/dk.h"
d6d7360b 17#include "../h/uio.h"
894cfdb7 18#include "../h/kernel.h"
89dc6dfb 19
8bba2b8f
RE
20/*
21 * Table giving parity for characters and indicating
22 * character classes to tty driver. In particular,
23 * if the low 6 bits are 0, then the character needs
24 * no special processing on output.
25 */
26
27char partab[] = {
28 0001,0201,0201,0001,0201,0001,0001,0201,
29 0202,0004,0003,0201,0005,0206,0201,0001,
30 0201,0001,0001,0201,0001,0201,0201,0001,
31 0001,0201,0201,0001,0201,0001,0001,0201,
32 0200,0000,0000,0200,0000,0200,0200,0000,
33 0000,0200,0200,0000,0200,0000,0000,0200,
34 0000,0200,0200,0000,0200,0000,0000,0200,
35 0200,0000,0000,0200,0000,0200,0200,0000,
36 0200,0000,0000,0200,0000,0200,0200,0000,
37 0000,0200,0200,0000,0200,0000,0000,0200,
38 0000,0200,0200,0000,0200,0000,0000,0200,
39 0200,0000,0000,0200,0000,0200,0200,0000,
40 0000,0200,0200,0000,0200,0000,0000,0200,
41 0200,0000,0000,0200,0000,0200,0200,0000,
42 0200,0000,0000,0200,0000,0200,0200,0000,
43 0000,0200,0200,0000,0200,0000,0000,0201,
44
45 /*
46 * 7 bit ascii ends with the last character above,
47 * but we contine through all 256 codes for the sake
48 * of the tty output routines which use special vax
49 * instructions which need a 256 character trt table.
50 */
51
52 0007,0007,0007,0007,0007,0007,0007,0007,
53 0007,0007,0007,0007,0007,0007,0007,0007,
54 0007,0007,0007,0007,0007,0007,0007,0007,
55 0007,0007,0007,0007,0007,0007,0007,0007,
56 0007,0007,0007,0007,0007,0007,0007,0007,
57 0007,0007,0007,0007,0007,0007,0007,0007,
58 0007,0007,0007,0007,0007,0007,0007,0007,
59 0007,0007,0007,0007,0007,0007,0007,0007,
60 0007,0007,0007,0007,0007,0007,0007,0007,
61 0007,0007,0007,0007,0007,0007,0007,0007,
62 0007,0007,0007,0007,0007,0007,0007,0007,
63 0007,0007,0007,0007,0007,0007,0007,0007,
64 0007,0007,0007,0007,0007,0007,0007,0007,
65 0007,0007,0007,0007,0007,0007,0007,0007,
66 0007,0007,0007,0007,0007,0007,0007,0007,
67 0007,0007,0007,0007,0007,0007,0007,0007
68};
89dc6dfb 69
89dc6dfb
BJ
70/*
71 * Input mapping table-- if an entry is non-zero, when the
72 * corresponding character is typed preceded by "\" the escape
73 * sequence is replaced by the table value. Mostly used for
74 * upper-case only terminals.
75 */
89dc6dfb
BJ
76char maptab[] ={
77 000,000,000,000,000,000,000,000,
78 000,000,000,000,000,000,000,000,
79 000,000,000,000,000,000,000,000,
80 000,000,000,000,000,000,000,000,
81 000,'|',000,000,000,000,000,'`',
82 '{','}',000,000,000,000,000,000,
83 000,000,000,000,000,000,000,000,
84 000,000,000,000,000,000,000,000,
85 000,000,000,000,000,000,000,000,
86 000,000,000,000,000,000,000,000,
87 000,000,000,000,000,000,000,000,
88 000,000,000,000,000,000,'~',000,
89 000,'A','B','C','D','E','F','G',
90 'H','I','J','K','L','M','N','O',
91 'P','Q','R','S','T','U','V','W',
92 'X','Y','Z',000,000,000,000,000,
93};
94
0d65848d 95short tthiwat[16] =
6f21eede 96 { 100,100,100,100,100,100,100,200,200,400,400,400,650,650,1300,2000 };
0d65848d
BJ
97short ttlowat[16] =
98 { 30, 30, 30, 30, 30, 30, 30, 50, 50,120,120,120,125,125,125,125 };
99
becb115c
SL
100struct ttychars ttydefaults = {
101 CERASE, CKILL, CINTR, CQUIT, CSTART, CSTOP, CEOF,
102 CBRK, CSUSP, CDSUSP, CRPRNT, CFLUSH, CWERASE,CLNEXT
103};
89dc6dfb 104
89dc6dfb 105ttychars(tp)
becb115c 106 struct tty *tp;
89dc6dfb 107{
8062c8a7 108
becb115c 109 tp->t_chars = ttydefaults;
89dc6dfb
BJ
110}
111
112/*
50e2732b 113 * Wait for output to drain, then flush input waiting.
89dc6dfb 114 */
50e2732b 115wflushtty(tp)
941944c9 116 register struct tty *tp;
89dc6dfb
BJ
117{
118
50e2732b 119 (void) spl5();
4c67f645
BJ
120 while (tp->t_outq.c_cc && tp->t_state&TS_CARR_ON
121 && tp->t_oproc) { /* kludge for pty */
50e2732b 122 (*tp->t_oproc)(tp);
941944c9 123 tp->t_state |= TS_ASLEEP;
50e2732b
BJ
124 sleep((caddr_t)&tp->t_outq, TTOPRI);
125 }
39697bd8 126 flushtty(tp, FREAD);
50e2732b 127 (void) spl0();
89dc6dfb
BJ
128}
129
130/*
becb115c 131 * Flush all TTY queues
89dc6dfb 132 */
50e2732b 133flushtty(tp, rw)
4b72e2f9 134 register struct tty *tp;
89dc6dfb 135{
50e2732b
BJ
136 register s;
137
50e2732b
BJ
138 s = spl6();
139 if (rw & FREAD) {
140 while (getc(&tp->t_canq) >= 0)
141 ;
142 wakeup((caddr_t)&tp->t_rawq);
143 }
144 if (rw & FWRITE) {
145 wakeup((caddr_t)&tp->t_outq);
941944c9 146 tp->t_state &= ~TS_TTSTOP;
39697bd8 147 (*cdevsw[major(tp->t_dev)].d_stop)(tp, rw);
50e2732b
BJ
148 while (getc(&tp->t_outq) >= 0)
149 ;
150 }
151 if (rw & FREAD) {
152 while (getc(&tp->t_rawq) >= 0)
153 ;
154 tp->t_delct = 0;
becb115c 155 tp->t_rocount = 0;
50e2732b 156 tp->t_rocol = 0;
becb115c 157 tp->t_state &= ~TS_LOCAL;
50e2732b
BJ
158 }
159 splx(s);
89dc6dfb
BJ
160}
161
50e2732b
BJ
162/*
163 * Send stop character on input overflow.
164 */
165ttyblock(tp)
4b72e2f9 166 register struct tty *tp;
89dc6dfb 167{
50e2732b 168 register x;
becb115c 169
50e2732b
BJ
170 x = tp->t_rawq.c_cc + tp->t_canq.c_cc;
171 if (tp->t_rawq.c_cc > TTYHOG) {
172 flushtty(tp, FREAD|FWRITE);
941944c9 173 tp->t_state &= ~TS_TBLOCK;
50e2732b 174 }
becb115c
SL
175 if (x >= TTYHOG/2 && putc(tp->t_stopc, &tp->t_outq) == 0) {
176 tp->t_state |= TS_TBLOCK;
177 tp->t_char++;
178 ttstart(tp);
50e2732b 179 }
89dc6dfb
BJ
180}
181
101ba270 182/*
50e2732b
BJ
183 * Restart typewriter output following a delay
184 * timeout.
185 * The name of the routine is passed to the timeout
186 * subroutine and it is called during a clock interrupt.
101ba270 187 */
50e2732b 188ttrstrt(tp)
4b72e2f9 189 register struct tty *tp;
101ba270
BJ
190{
191
becb115c
SL
192 if (tp == 0)
193 panic("ttrstrt");
941944c9 194 tp->t_state &= ~TS_TIMEOUT;
50e2732b 195 ttstart(tp);
101ba270
BJ
196}
197
89dc6dfb 198/*
50e2732b
BJ
199 * Start output on the typewriter. It is used from the top half
200 * after some characters have been put on the output queue,
201 * from the interrupt routine to transmit the next
202 * character, and after a timeout has finished.
89dc6dfb 203 */
50e2732b 204ttstart(tp)
4b72e2f9 205 register struct tty *tp;
89dc6dfb 206{
50e2732b 207 register s;
8062c8a7 208
50e2732b 209 s = spl5();
becb115c 210 if ((tp->t_state & (TS_TIMEOUT|TS_TTSTOP|TS_BUSY)) == 0 &&
4c67f645 211 tp->t_oproc) /* kludge for pty */
50e2732b
BJ
212 (*tp->t_oproc)(tp);
213 splx(s);
89dc6dfb
BJ
214}
215
216/*
50e2732b 217 * Common code for tty ioctls.
89dc6dfb 218 */
49c84d3f 219/*ARGSUSED*/
4b72e2f9
SL
220ttioctl(tp, com, data, flag)
221 register struct tty *tp;
222 caddr_t data;
89dc6dfb 223{
840510a3 224 int dev = tp->t_dev;
89dc6dfb 225 extern int nldisp;
fc6972ae 226 int s;
89dc6dfb 227
50e2732b
BJ
228 /*
229 * If the ioctl involves modification,
230 * insist on being able to write the device,
231 * and hang if in the background.
232 */
4b72e2f9 233 switch (com) {
50e2732b 234
c6fe3a50
BJ
235 case TIOCSETD:
236 case TIOCSETP:
237 case TIOCSETN:
50e2732b
BJ
238 case TIOCFLUSH:
239 case TIOCSETC:
240 case TIOCSLTC:
241 case TIOCSPGRP:
242 case TIOCLBIS:
243 case TIOCLBIC:
244 case TIOCLSET:
67ba7f0d
SL
245 case TIOCBIS:
246 case TIOCBIC:
247 case TIOCSET:
8203fe05 248 case TIOCSTI:
50e2732b
BJ
249 while (tp->t_line == NTTYDISC &&
250 u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp &&
251 (u.u_procp->p_flag&SVFORK) == 0 &&
252 u.u_signal[SIGTTOU] != SIG_IGN &&
fc6972ae 253 u.u_signal[SIGTTOU] != SIG_HOLD) {
50e2732b
BJ
254 gsignal(u.u_procp->p_pgrp, SIGTTOU);
255 sleep((caddr_t)&lbolt, TTOPRI);
256 }
257 break;
258 }
259
becb115c
SL
260 /*
261 * Process the ioctl.
262 */
4b72e2f9 263 switch (com) {
89dc6dfb 264
fc6972ae 265 /* get discipline number */
89dc6dfb 266 case TIOCGETD:
4b72e2f9 267 *(int *)data = tp->t_line;
89dc6dfb
BJ
268 break;
269
fc6972ae 270 /* set line discipline */
4b72e2f9
SL
271 case TIOCSETD: {
272 register int t = *(int *)data;
becb115c 273 int error = 0;
4b72e2f9 274
becb115c
SL
275 if (t >= nldisp) {
276 u.u_error = ENXIO;
277 break;
278 }
fc6972ae 279 s = spl5();
89dc6dfb
BJ
280 if (tp->t_line)
281 (*linesw[tp->t_line].l_close)(tp);
282 if (t)
fc6972ae
BJ
283 error = (*linesw[t].l_open)(dev, tp);
284 splx(s);
285 if (error)
286 return (error);
287 tp->t_line = t;
89dc6dfb 288 break;
4b72e2f9 289 }
89dc6dfb 290
fc6972ae 291 /* prevent more opens on channel */
152c2598
BJ
292 case TIOCEXCL:
293 tp->t_state |= TS_XCLUDE;
294 break;
295
296 case TIOCNXCL:
297 tp->t_state &= ~TS_XCLUDE;
298 break;
299
67ba7f0d
SL
300 case TIOCSET:
301 case TIOCBIS: {
302 u_long newflags = *(u_long *)data;
4b72e2f9 303
67ba7f0d
SL
304 s = spl5();
305 if (tp->t_flags&RAW || newflags&RAW)
e1d74936 306 wflushtty(tp);
67ba7f0d
SL
307 else if ((tp->t_flags&CBREAK) != (newflags&CBREAK))
308 if (newflags&CBREAK) {
309 struct clist tq;
310
e1d74936
BJ
311 catq(&tp->t_rawq, &tp->t_canq);
312 tq = tp->t_rawq;
313 tp->t_rawq = tp->t_canq;
314 tp->t_canq = tq;
315 } else {
becb115c 316 tp->t_flags |= PENDIN;
e1d74936 317 ttwakeup(tp);
8062c8a7 318 }
67ba7f0d
SL
319 if (com == TIOCSET)
320 tp->t_flags = newflags;
321 else
322 tp->t_flags |= newflags;
becb115c 323 if (tp->t_flags&RAW) {
941944c9 324 tp->t_state &= ~TS_TTSTOP;
627c86ee
KB
325 ttstart(tp);
326 }
67ba7f0d 327 splx(s);
89dc6dfb 328 break;
4b72e2f9 329 }
89dc6dfb 330
67ba7f0d
SL
331 case TIOCBIC: {
332 u_long newflags = *(long *)data;
4b72e2f9 333
67ba7f0d
SL
334 if (tp->t_flags&RAW)
335 wflushtty(tp);
336 else if ((tp->t_flags&CBREAK) != (CBREAK&~newflags))
337 if (newflags&CBREAK) {
338 tp->t_flags |= PENDIN;
339 ttwakeup(tp);
340 } else {
341 struct clist tq;
342
343 catq(&tp->t_rawq, &tp->t_canq);
344 tq = tp->t_rawq;
345 tp->t_rawq = tp->t_canq;
346 tp->t_canq = tq;
347 }
348 if (tp->t_flags&RAW) {
349 tp->t_state &= ~TS_TTSTOP;
350 ttstart(tp);
351 }
352 splx(s);
89dc6dfb 353 break;
4b72e2f9 354 }
89dc6dfb 355
67ba7f0d
SL
356 case TIOCGET:
357 *(long *)data = tp->t_flags;
358 break;
359
360 case TIOCCGET:
361 bcopy((caddr_t)&tp->t_chars, data, sizeof (struct ttychars));
362 break;
363
364 case TIOCCSET:
365 bcopy(data, (caddr_t)&tp->t_chars, sizeof (struct ttychars));
366 break;
367
fc6972ae 368 /* hang up line on last close */
89dc6dfb 369 case TIOCHPCL:
941944c9 370 tp->t_state |= TS_HUPCLS;
89dc6dfb
BJ
371 break;
372
7d973a4d 373 case TIOCFLUSH: {
4b72e2f9
SL
374 register int flags = *(int *)data;
375
376 if (flags == 0)
7d973a4d 377 flags = FREAD|FWRITE;
4b72e2f9
SL
378 else
379 flags &= FREAD|FWRITE;
7d973a4d 380 flushtty(tp, flags);
89dc6dfb 381 break;
4568c08e 382 }
89dc6dfb 383
fc6972ae 384 /* return number of characters immediately available */
4b72e2f9
SL
385 case FIONREAD:
386 *(off_t *)data = ttnread(tp);
8062c8a7 387 break;
8062c8a7 388
a8d3bf7f
BJ
389 case TIOCSTOP:
390 s = spl5();
becb115c 391 if ((tp->t_state&TS_TTSTOP) == 0) {
bfcf09ee
BJ
392 tp->t_state |= TS_TTSTOP;
393 (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
394 }
4b72e2f9 395 splx(s);
bfcf09ee
BJ
396 break;
397
a8d3bf7f
BJ
398 case TIOCSTART:
399 s = spl5();
becb115c 400 if ((tp->t_state&TS_TTSTOP) || (tp->t_flags&FLUSHO)) {
bfcf09ee 401 tp->t_state &= ~TS_TTSTOP;
becb115c 402 tp->t_flags &= ~FLUSHO;
bfcf09ee
BJ
403 ttstart(tp);
404 }
4b72e2f9 405 splx(s);
bfcf09ee
BJ
406 break;
407
8203fe05
SL
408 /*
409 * Simulate typing of a character at the terminal.
410 */
411 case TIOCSTI:
412 if (u.u_uid && u.u_ttyp != tp)
413 return (EACCES);
becb115c 414 (*linesw[tp->t_line].l_rint)(*(char *)data, tp);
8203fe05
SL
415 break;
416
89dc6dfb 417 default:
67ba7f0d
SL
418#ifndef NOCOMPAT
419 return (ottioctl(tp, com, data, flag));
420#else
fc6972ae 421 return (-1);
67ba7f0d 422#endif
89dc6dfb 423 }
fc6972ae 424 return (0);
89dc6dfb 425}
e1d74936
BJ
426
427ttnread(tp)
428 struct tty *tp;
429{
430 int nread = 0;
431
becb115c 432 if (tp->t_flags & PENDIN)
e1d74936
BJ
433 ttypend(tp);
434 nread = tp->t_canq.c_cc;
435 if (tp->t_flags & (RAW|CBREAK))
436 nread += tp->t_rawq.c_cc;
437 return (nread);
438}
439
941944c9 440ttselect(dev, rw)
e1d74936 441 dev_t dev;
941944c9 442 int rw;
e1d74936
BJ
443{
444 register struct tty *tp = &cdevsw[major(dev)].d_ttys[minor(dev)];
445 int nread;
941944c9 446 int s = spl5();
e1d74936 447
941944c9 448 switch (rw) {
e1d74936
BJ
449
450 case FREAD:
451 nread = ttnread(tp);
452 if (nread > 0)
941944c9 453 goto win;
89b8a44c 454 if (tp->t_rsel && tp->t_rsel->p_wchan == (caddr_t)&selwait)
941944c9 455 tp->t_state |= TS_RCOLL;
e1d74936
BJ
456 else
457 tp->t_rsel = u.u_procp;
941944c9 458 break;
e1d74936 459
941944c9
BJ
460 case FWRITE:
461 if (tp->t_outq.c_cc <= TTLOWAT(tp))
462 goto win;
941944c9
BJ
463 if (tp->t_wsel && tp->t_wsel->p_wchan == (caddr_t)&selwait)
464 tp->t_state |= TS_WCOLL;
465 else
466 tp->t_wsel = u.u_procp;
467 break;
e1d74936 468 }
941944c9
BJ
469 splx(s);
470 return (0);
471win:
472 splx(s);
473 return (1);
e1d74936 474}
8bba2b8f 475
4147b3f6 476/*
becb115c 477 * Establish a process group for distribution of
4147b3f6 478 * quits and interrupts from the tty.
4147b3f6
BJ
479 */
480ttyopen(dev, tp)
4b72e2f9
SL
481 dev_t dev;
482 register struct tty *tp;
4147b3f6
BJ
483{
484 register struct proc *pp;
485
486 pp = u.u_procp;
487 tp->t_dev = dev;
4b72e2f9 488 if (pp->p_pgrp == 0) {
4147b3f6
BJ
489 u.u_ttyp = tp;
490 u.u_ttyd = dev;
491 if (tp->t_pgrp == 0)
492 tp->t_pgrp = pp->p_pid;
493 pp->p_pgrp = tp->t_pgrp;
494 }
495 tp->t_state &= ~TS_WOPEN;
496 tp->t_state |= TS_ISOPEN;
497 if (tp->t_line != NTTYDISC)
498 wflushtty(tp);
fc6972ae 499 return (0);
4147b3f6
BJ
500}
501
502/*
503 * clean tp on last close
504 */
505ttyclose(tp)
4b72e2f9 506 register struct tty *tp;
4147b3f6
BJ
507{
508
509 if (tp->t_line) {
510 wflushtty(tp);
511 tp->t_line = 0;
512 return;
513 }
514 tp->t_pgrp = 0;
515 wflushtty(tp);
516 tp->t_state = 0;
517}
518
519/*
520 * reinput pending characters after state switch
521 * call at spl5().
522 */
523ttypend(tp)
4b72e2f9 524 register struct tty *tp;
4147b3f6
BJ
525{
526 struct clist tq;
527 register c;
528
becb115c
SL
529 tp->t_flags &= ~PENDIN;
530 tp->t_state |= TS_TYPEN;
4147b3f6
BJ
531 tq = tp->t_rawq;
532 tp->t_rawq.c_cc = 0;
533 tp->t_rawq.c_cf = tp->t_rawq.c_cl = 0;
534 while ((c = getc(&tq)) >= 0)
535 ttyinput(c, tp);
becb115c 536 tp->t_state &= ~TS_TYPEN;
4147b3f6
BJ
537}
538
539/*
becb115c
SL
540 * Place a character on raw TTY input queue,
541 * putting in delimiters and waking up top
542 * half as needed. Also echo if required.
543 * The arguments are the character and the
544 * appropriate tty structure.
4147b3f6
BJ
545 */
546ttyinput(c, tp)
4b72e2f9
SL
547 register c;
548 register struct tty *tp;
4147b3f6 549{
becb115c 550 register int t_flags = tp->t_flags;
4147b3f6
BJ
551 int i;
552
becb115c
SL
553 /*
554 * If input is pending take it first.
555 */
556 if (t_flags&PENDIN)
4147b3f6
BJ
557 ttypend(tp);
558 tk_nin++;
559 c &= 0377;
becb115c
SL
560
561 /*
562 * In tandem mode, check high water mark.
563 */
4147b3f6
BJ
564 if (t_flags&TANDEM)
565 ttyblock(tp);
becb115c
SL
566
567 if (t_flags&RAW) {
568 /*
569 * Raw mode, just put character
570 * in input q w/o interpretation.
571 */
572 if (tp->t_rawq.c_cc > TTYHOG)
573 flushtty(tp, FREAD|FWRITE);
574 else {
575 if (putc(c, &tp->t_rawq) >= 0)
576 ttwakeup(tp);
577 ttyecho(c, tp);
4147b3f6 578 }
becb115c
SL
579 goto endcase;
580 }
581
582 /*
583 * Ignore any high bit added during
584 * previous ttyinput processing.
585 */
586 if ((tp->t_state&TS_TYPEN) == 0)
587 c &= 0177;
588 /*
589 * Check for literal nexting very first
590 */
591 if (tp->t_state&TS_LNCH) {
592 c |= 0200;
593 tp->t_state &= ~TS_LNCH;
594 }
595
596 /*
597 * Scan for special characters. This code
598 * is really just a big case statement with
599 * non-constant cases. The bottom of the
600 * case statement is labeled ``endcase'', so goto
601 * it after a case match, or similar.
602 */
603 if (tp->t_line == NTTYDISC) {
604 if (c == tp->t_lnextc) {
4147b3f6
BJ
605 if (tp->t_flags&ECHO)
606 ttyout("^\b", tp);
becb115c
SL
607 tp->t_state |= TS_LNCH;
608 goto endcase;
609 }
610 if (c == tp->t_flushc) {
611 if (tp->t_flags&FLUSHO)
612 tp->t_flags &= ~FLUSHO;
4147b3f6
BJ
613 else {
614 flushtty(tp, FWRITE);
615 ttyecho(c, tp);
becb115c 616 if (tp->t_rawq.c_cc + tp->t_canq.c_cc)
4147b3f6 617 ttyretype(tp);
becb115c 618 tp->t_flags |= FLUSHO;
4147b3f6 619 }
becb115c
SL
620 goto startoutput;
621 }
622 if (c == tp->t_suspc) {
623 if ((tp->t_flags&NOFLSH) == 0)
624 flushtty(tp, FREAD);
4147b3f6 625 ttyecho(c, tp);
becb115c
SL
626 gsignal(tp->t_pgrp, SIGTSTP);
627 goto endcase;
628 }
629 }
630
631 /*
632 * Handle start/stop characters.
633 */
634 if (c == tp->t_stopc) {
635 if ((tp->t_state&TS_TTSTOP) == 0) {
636 tp->t_state |= TS_TTSTOP;
637 (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
638 return;
639 }
640 if (c != tp->t_startc)
641 return;
642 goto endcase;
643 }
644 if (c == tp->t_startc)
645 goto restartoutput;
646
647 /*
648 * Look for interrupt/quit chars.
649 */
650 if (c == tp->t_intrc || c == tp->t_quitc) {
651 if ((tp->t_flags&NOFLSH) == 0)
652 flushtty(tp, FREAD|FWRITE);
653 ttyecho(c, tp);
654 gsignal(tp->t_pgrp, c == tp->t_intrc ? SIGINT : SIGQUIT);
655 goto endcase;
656 }
657
658 /*
659 * Cbreak mode, don't process line editing
660 * characters; check high water mark for wakeup.
661 */
662 if (t_flags&CBREAK) {
663 if (tp->t_rawq.c_cc > TTYHOG) {
4147b3f6
BJ
664 if (tp->t_outq.c_cc < TTHIWAT(tp) &&
665 tp->t_line == NTTYDISC)
666 (void) ttyoutput(CTRL(g), tp);
667 } else if (putc(c, &tp->t_rawq) >= 0) {
668 ttwakeup(tp);
669 ttyecho(c, tp);
670 }
becb115c
SL
671 goto endcase;
672 }
673
674 /*
675 * From here on down cooked mode character
676 * processing takes place.
677 */
678 if ((tp->t_state&TS_QUOT) &&
679 (c == tp->t_erase || c == tp->t_kill)) {
680 ttyrub(unputc(&tp->t_rawq), tp);
681 c |= 0200;
682 }
683 if (c == tp->t_erase) {
684 if (tp->t_rawq.c_cc)
685 ttyrub(unputc(&tp->t_rawq), tp);
686 goto endcase;
687 }
688 if (c == tp->t_kill) {
689 if (tp->t_flags&CRTKIL &&
690 tp->t_rawq.c_cc == tp->t_rocount) {
691 while (tp->t_rawq.c_cc)
692 ttyrub(unputc(&tp->t_rawq), tp);
693 } else {
694 ttyecho(c, tp);
695 ttyecho('\n', tp);
696 while (getc(&tp->t_rawq) > 0)
697 ;
698 tp->t_rocount = 0;
699 }
700 tp->t_state &= ~TS_LOCAL;
701 goto endcase;
702 }
703
704 /*
705 * New line discipline,
706 * check word erase/reprint line.
707 */
708 if (tp->t_line == NTTYDISC) {
709 if (c == tp->t_werasc) {
710 if (tp->t_rawq.c_cc == 0)
711 goto endcase;
712 do {
713 c = unputc(&tp->t_rawq);
714 if (c != ' ' && c != '\t')
715 goto erasenb;
716 ttyrub(c, tp);
717 } while (tp->t_rawq.c_cc);
718 goto endcase;
719 erasenb:
720 do {
721 ttyrub(c, tp);
722 if (tp->t_rawq.c_cc == 0)
723 goto endcase;
724 c = unputc(&tp->t_rawq);
725 } while (c != ' ' && c != '\t');
726 (void) putc(c, &tp->t_rawq);
727 goto endcase;
728 }
729 if (c == tp->t_rprntc) {
730 ttyretype(tp);
731 goto endcase;
732 }
733 }
734
735 /*
736 * Check for input buffer overflow
737 */
738 if (tp->t_rawq.c_cc+tp->t_canq.c_cc >= TTYHOG)
739 goto endcase;
740
741 /*
742 * Put data char in q for user and
743 * wakeup on seeing a line delimiter.
744 */
745 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 tp->t_rocount = 0;
751 catq(&tp->t_rawq, &tp->t_canq);
4147b3f6 752 ttwakeup(tp);
becb115c
SL
753 } else if (tp->t_rocount++ == 0)
754 tp->t_rocol = tp->t_col;
755 tp->t_state &= ~TS_QUOT;
756 if (c == '\\')
757 tp->t_state |= TS_QUOT;
758 if (tp->t_state&TS_ERASE) {
759 tp->t_state &= ~TS_ERASE;
760 (void) ttyoutput('/', tp);
761 }
762 i = tp->t_col;
4147b3f6 763 ttyecho(c, tp);
becb115c
SL
764 if (c == tp->t_eofc && tp->t_flags&ECHO) {
765 i = MIN(2, tp->t_col - i);
766 while (i > 0) {
767 (void) ttyoutput('\b', tp);
768 i--;
769 }
770 }
4147b3f6 771 }
becb115c
SL
772
773endcase:
774 /*
775 * If DEC-style start/stop is enabled don't restart
776 * output until seeing the start character.
777 */
778 if (tp->t_flags&DECCTQ && tp->t_state&TS_TTSTOP &&
779 tp->t_startc != tp->t_stopc)
4147b3f6 780 return;
becb115c
SL
781
782restartoutput:
4147b3f6 783 tp->t_state &= ~TS_TTSTOP;
becb115c
SL
784 tp->t_flags &= ~FLUSHO;
785
786startoutput:
4147b3f6
BJ
787 ttstart(tp);
788}
789
790/*
becb115c 791 * Put character on TTY output queue, adding delays,
4147b3f6 792 * expanding tabs, and handling the CR/NL bit.
becb115c
SL
793 * This is called both from the top half for output,
794 * and from interrupt level for echoing.
4147b3f6
BJ
795 * The arguments are the character and the tty structure.
796 * Returns < 0 if putc succeeds, otherwise returns char to resend
797 * Must be recursive.
798 */
799ttyoutput(c, tp)
800 register c;
801 register struct tty *tp;
802{
803 register char *colp;
804 register ctype;
805
becb115c
SL
806 if (tp->t_flags & (RAW|LITOUT)) {
807 if (tp->t_flags&FLUSHO)
4147b3f6
BJ
808 return (-1);
809 if (putc(c, &tp->t_outq))
4b72e2f9 810 return (c);
4147b3f6
BJ
811 tk_nout++;
812 return (-1);
813 }
becb115c 814
4147b3f6 815 /*
becb115c
SL
816 * Ignore EOT in normal mode to avoid
817 * hanging up certain terminals.
4147b3f6
BJ
818 */
819 c &= 0177;
becb115c 820 if (c == CEOT && (tp->t_flags&CBREAK) == 0)
4147b3f6
BJ
821 return (-1);
822 /*
823 * Turn tabs to spaces as required
824 */
becb115c 825 if (c == '\t' && (tp->t_flags&TBDELAY) == XTABS) {
4147b3f6
BJ
826 register int s;
827
828 c = 8 - (tp->t_col&7);
becb115c 829 if ((tp->t_flags&FLUSHO) == 0) {
4147b3f6
BJ
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 }
becb115c 852 if ('A' <= c && c <= 'Z') {
4147b3f6
BJ
853 if (ttyoutput('\\', tp) >= 0)
854 return (c);
becb115c 855 } else if ('a' <= c && c <= 'z')
4147b3f6
BJ
856 c += 'A' - 'a';
857 }
becb115c 858
4147b3f6
BJ
859 /*
860 * turn <nl> to <cr><lf> if desired.
861 */
becb115c 862 if (c == '\n' && tp->t_flags&CRMOD)
4147b3f6
BJ
863 if (ttyoutput('\r', tp) >= 0)
864 return (c);
becb115c 865 if (c == '~' && tp->t_flags&TILDE)
4147b3f6 866 c = '`';
becb115c 867 if ((tp->t_flags&FLUSHO) == 0 && putc(c, &tp->t_outq))
4147b3f6
BJ
868 return (c);
869 /*
870 * Calculate delays.
871 * The numbers here represent clock ticks
872 * and are not necessarily optimal for all terminals.
873 * The delays are indicated by characters above 0200.
874 * In raw mode there are no delays and the
875 * transmission path is 8 bits wide.
becb115c
SL
876 *
877 * SHOULD JUST ALLOW USER TO SPECIFY DELAYS
4147b3f6
BJ
878 */
879 colp = &tp->t_col;
880 ctype = partab[c];
881 c = 0;
882 switch (ctype&077) {
883
884 case ORDINARY:
885 (*colp)++;
886
887 case CONTROL:
888 break;
889
890 case BACKSPACE:
891 if (*colp)
892 (*colp)--;
893 break;
894
895 case NEWLINE:
896 ctype = (tp->t_flags >> 8) & 03;
4b72e2f9 897 if (ctype == 1) { /* tty 37 */
4147b3f6
BJ
898 if (*colp)
899 c = max(((unsigned)*colp>>4) + 3, (unsigned)6);
becb115c 900 } else if (ctype == 2) /* vt05 */
4147b3f6 901 c = 6;
4147b3f6
BJ
902 *colp = 0;
903 break;
904
905 case TAB:
906 ctype = (tp->t_flags >> 10) & 03;
4b72e2f9 907 if (ctype == 1) { /* tty 37 */
4147b3f6 908 c = 1 - (*colp | ~07);
4b72e2f9 909 if (c < 5)
4147b3f6
BJ
910 c = 0;
911 }
912 *colp |= 07;
913 (*colp)++;
914 break;
915
916 case VTAB:
becb115c 917 if (tp->t_flags&VTDELAY) /* tty 37 */
4147b3f6
BJ
918 c = 0177;
919 break;
920
921 case RETURN:
922 ctype = (tp->t_flags >> 12) & 03;
becb115c 923 if (ctype == 1) /* tn 300 */
4147b3f6 924 c = 5;
becb115c 925 else if (ctype == 2) /* ti 700 */
4147b3f6 926 c = 10;
becb115c 927 else if (ctype == 3) { /* concept 100 */
4147b3f6 928 int i;
becb115c 929
4147b3f6 930 if ((i = *colp) >= 0)
becb115c 931 for (; i < 9; i++)
4147b3f6
BJ
932 (void) putc(0177, &tp->t_outq);
933 }
934 *colp = 0;
935 }
becb115c 936 if (c && (tp->t_flags&FLUSHO) == 0)
4147b3f6
BJ
937 (void) putc(c|0200, &tp->t_outq);
938 return (-1);
939}
940
941/*
942 * Called from device's read routine after it has
943 * calculated the tty-structure given as argument.
944 */
d6d7360b 945ttread(tp, uio)
4b72e2f9 946 register struct tty *tp;
d6d7360b 947 struct uio *uio;
4147b3f6
BJ
948{
949 register struct clist *qp;
becb115c
SL
950 register c, t_flags;
951 int first, error = 0;
4147b3f6
BJ
952
953 if ((tp->t_state&TS_CARR_ON)==0)
840510a3 954 return (EIO);
4147b3f6 955loop:
becb115c
SL
956 /*
957 * Take any pending input first.
958 */
4147b3f6 959 (void) spl5();
becb115c 960 if (tp->t_flags&PENDIN)
4147b3f6
BJ
961 ttypend(tp);
962 (void) spl0();
becb115c
SL
963
964 /*
965 * Hang process if it's in the background.
966 */
4147b3f6
BJ
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)
840510a3 974 return (EIO);
4147b3f6
BJ
975 gsignal(u.u_procp->p_pgrp, SIGTTIN);
976 sleep((caddr_t)&lbolt, TTIPRI);
977 }
becb115c
SL
978 t_flags = tp->t_flags;
979
980 /*
981 * In raw mode take characters directly from the
982 * raw queue w/o processing. Interlock against
983 * device interrupts when interrogating rawq.
984 */
985 if (t_flags&RAW) {
4147b3f6
BJ
986 (void) spl5();
987 if (tp->t_rawq.c_cc <= 0) {
becb115c 988 if ((tp->t_state&TS_CARR_ON) == 0 ||
4147b3f6
BJ
989 (tp->t_state&TS_NBIO)) {
990 (void) spl0();
becb115c 991 return (0);
4147b3f6
BJ
992 }
993 sleep((caddr_t)&tp->t_rawq, TTIPRI);
994 (void) spl0();
995 goto loop;
996 }
997 (void) spl0();
d6d7360b 998 while (tp->t_rawq.c_cc && uio->uio_iovcnt) {
840510a3
BJ
999 error = passuc(getc(&tp->t_rawq), uio);
1000 if (error)
d6d7360b
BJ
1001 break;
1002 }
840510a3 1003 return (error);
becb115c
SL
1004 }
1005
1006 /*
1007 * In cbreak mode use the rawq, otherwise
1008 * take characters from the canonicalized q.
1009 */
1010 qp = t_flags&CBREAK ? &tp->t_rawq : &tp->t_canq;
1011
1012 /*
1013 * No input, sleep on rawq awaiting hardware
1014 * receipt and notification.
1015 */
1016 (void) spl5();
1017 if (qp->c_cc <= 0) {
1018 if ((tp->t_state&TS_CARR_ON) == 0 ||
1019 (tp->t_state&TS_NBIO)) {
4147b3f6 1020 (void) spl0();
becb115c 1021 return (EWOULDBLOCK);
4147b3f6 1022 }
becb115c 1023 sleep((caddr_t)&tp->t_rawq, TTIPRI);
4147b3f6 1024 (void) spl0();
becb115c
SL
1025 goto loop;
1026 }
1027 (void) spl0();
1028
1029 /*
1030 * Input present, perform input mapping
1031 * and processing (we're not in raw mode).
1032 */
1033 first = 1;
1034 while ((c = getc(qp)) >= 0) {
1035 if (t_flags&CRMOD && c == '\r')
1036 c = '\n';
1037 /*
1038 * Hack lower case simulation on
1039 * upper case only terminals.
1040 */
1041 if (t_flags&LCASE && c <= 0177)
1042 if (tp->t_state&TS_BKSL) {
1043 if (maptab[c])
1044 c = maptab[c];
1045 tp->t_state &= ~TS_BKSL;
1046 } else if (c >= 'A' && c <= 'Z')
1047 c += 'a' - 'A';
1048 else if (c == '\\') {
1049 tp->t_state |= TS_BKSL;
1050 continue;
4147b3f6 1051 }
becb115c
SL
1052 /*
1053 * Check for delayed suspend character.
1054 */
1055 if (tp->t_line == NTTYDISC && c == tp->t_dsuspc) {
1056 gsignal(tp->t_pgrp, SIGTSTP);
1057 if (first) {
1058 sleep((caddr_t)&lbolt, TTIPRI);
1059 goto loop;
1060 }
1061 break;
4147b3f6 1062 }
becb115c
SL
1063 /*
1064 * Interpret EOF only in cooked mode.
1065 */
1066 if (c == tp->t_eofc && (t_flags&CBREAK) == 0)
1067 break;
1068 /*
1069 * Give user character.
1070 */
1071 error = passuc(c & 0177, uio);
1072 if (error)
1073 break;
1074 if (uio->uio_iovcnt == 0)
1075 break;
1076 /*
1077 * In cooked mode check for a "break character"
1078 * marking the end of a "line of input".
1079 */
1080 if ((t_flags&CBREAK) == 0 && ttbreakc(c, tp))
1081 break;
1082 first = 0;
4147b3f6 1083 }
becb115c
SL
1084 tp->t_state &= ~TS_BKSL;
1085
1086 /*
1087 * Look to unblock output now that (presumably)
1088 * the input queue has gone down.
1089 */
4147b3f6 1090 if (tp->t_state&TS_TBLOCK && tp->t_rawq.c_cc < TTYHOG/5) {
becb115c 1091 if (putc(tp->t_startc, &tp->t_outq) == 0) {
4147b3f6
BJ
1092 tp->t_state &= ~TS_TBLOCK;
1093 ttstart(tp);
1094 }
1095 tp->t_char = 0;
1096 }
840510a3 1097 return (error);
4147b3f6
BJ
1098}
1099
1100/*
1101 * Called from the device's write routine after it has
1102 * calculated the tty-structure given as argument.
1103 */
913ea2d1 1104ttwrite(tp, uio)
4b72e2f9 1105 register struct tty *tp;
becb115c 1106 register struct uio *uio;
4147b3f6 1107{
4147b3f6 1108 register char *cp;
becb115c
SL
1109 register int cc, ce, c;
1110 int i, hiwat, cnt, error, s;
4147b3f6 1111 char obuf[OBUFSIZ];
4147b3f6 1112
becb115c 1113 if ((tp->t_state&TS_CARR_ON) == 0)
840510a3 1114 return (EIO);
becb115c
SL
1115 hiwat = TTHIWAT(tp);
1116 cnt = uio->uio_resid;
1117 error = 0;
4147b3f6 1118loop:
becb115c
SL
1119 /*
1120 * Hang the process if it's in the background.
1121 */
4147b3f6 1122 while (u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp &&
becb115c 1123 (tp->t_flags&TOSTOP) && (u.u_procp->p_flag&SVFORK)==0 &&
4147b3f6
BJ
1124 u.u_signal[SIGTTOU] != SIG_IGN &&
1125 u.u_signal[SIGTTOU] != SIG_HOLD
1126/*
1127 &&
1128 (u.u_procp->p_flag&SDETACH)==0) {
1129*/
1130 ) {
1131 gsignal(u.u_procp->p_pgrp, SIGTTOU);
1132 sleep((caddr_t)&lbolt, TTIPRI);
1133 }
becb115c
SL
1134
1135 /*
1136 * Process the user's data in at most OBUFSIZ
1137 * chunks. Perform lower case simulation and
1138 * similar hacks. Keep track of high water
1139 * mark, sleep on overflow awaiting device aid
1140 * in acquiring new space.
1141 */
913ea2d1 1142 while (uio->uio_resid > 0) {
becb115c
SL
1143 /*
1144 * Grab a hunk of data from the user.
1145 */
913ea2d1
BJ
1146 cc = uio->uio_iov->iov_len;
1147 if (cc == 0) {
1148 uio->uio_iovcnt--;
1149 uio->uio_iov++;
1150 if (uio->uio_iovcnt < 0)
1151 panic("ttwrite");
1152 continue;
1153 }
1154 if (cc > OBUFSIZ)
1155 cc = OBUFSIZ;
4147b3f6 1156 cp = obuf;
becb115c 1157 error = uiomove(cp, (unsigned)cc, UIO_WRITE, uio);
840510a3 1158 if (error)
4147b3f6
BJ
1159 break;
1160 if (tp->t_outq.c_cc > hiwat)
1161 goto ovhiwat;
becb115c 1162 if (tp->t_flags&FLUSHO)
4147b3f6 1163 continue;
becb115c
SL
1164 /*
1165 * If we're mapping lower case or kludging tildes,
1166 * then we've got to look at each character, so
1167 * just feed the stuff to ttyoutput...
1168 */
1169 if (tp->t_flags & (LCASE|TILDE)) {
1170 while (cc > 0) {
4147b3f6
BJ
1171 c = *cp++;
1172 tp->t_rocount = 0;
4b72e2f9 1173 while ((c = ttyoutput(c, tp)) >= 0) {
4147b3f6
BJ
1174 /* out of clists, wait a bit */
1175 ttstart(tp);
1176 sleep((caddr_t)&lbolt, TTOPRI);
1177 tp->t_rocount = 0;
1178 }
1179 --cc;
1180 if (tp->t_outq.c_cc > hiwat)
1181 goto ovhiwat;
1182 }
1183 continue;
1184 }
becb115c
SL
1185 /*
1186 * If nothing fancy need be done, grab those characters we
1187 * can handle without any of ttyoutput's processing and
1188 * just transfer them to the output q. For those chars
1189 * which require special processing (as indicated by the
1190 * bits in partab), call ttyoutput. After processing
1191 * a hunk of data, look for FLUSHO so ^O's will take effect
1192 * immediately.
1193 */
1194 while (cc > 0) {
1195 if (tp->t_flags & (RAW|LITOUT))
4147b3f6
BJ
1196 ce = cc;
1197 else {
becb115c
SL
1198 ce = cc - scanc(cc, cp, partab, 077);
1199 /*
1200 * If ce is zero, then we're processing
1201 * a special character through ttyoutput.
1202 */
1203 if (ce == 0) {
4147b3f6
BJ
1204 tp->t_rocount = 0;
1205 if (ttyoutput(*cp, tp) >= 0) {
becb115c 1206 /* no c-lists, wait a bit */
4147b3f6
BJ
1207 ttstart(tp);
1208 sleep((caddr_t)&lbolt, TTOPRI);
1209 continue;
1210 }
becb115c
SL
1211 cp++, cc--;
1212 if (tp->t_flags&FLUSHO ||
1213 tp->t_outq.c_cc > hiwat)
4147b3f6 1214 goto ovhiwat;
becb115c 1215 continue;
4147b3f6
BJ
1216 }
1217 }
becb115c
SL
1218 /*
1219 * A bunch of normal characters have been found,
1220 * transfer them en masse to the output queue and
1221 * continue processing at the top of the loop.
1222 * If there are any further characters in this
1223 * <= OBUFSIZ chunk, the first should be a character
1224 * requiring special handling by ttyoutput.
1225 */
4147b3f6 1226 tp->t_rocount = 0;
becb115c
SL
1227 i = b_to_q(cp, ce, &tp->t_outq);
1228 ce -= i;
1229 tp->t_col += ce;
1230 cp += ce, cc -= ce, tk_nout += ce;
1231 if (i > 0) {
1232 /* out of c-lists, wait a bit */
4147b3f6
BJ
1233 ttstart(tp);
1234 sleep((caddr_t)&lbolt, TTOPRI);
1235 }
becb115c 1236 if (tp->t_flags&FLUSHO || tp->t_outq.c_cc > hiwat)
4147b3f6
BJ
1237 goto ovhiwat;
1238 }
1239 }
1240 ttstart(tp);
840510a3 1241 return (error);
4147b3f6
BJ
1242
1243ovhiwat:
becb115c
SL
1244 s = spl5();
1245 if (cc != 0) {
1246 uio->uio_iov->iov_base -= cc;
1247 uio->uio_iov->iov_len += cc;
1248 uio->uio_resid += cc;
1249 uio->uio_offset -= cc;
1250 }
1251 /*
1252 * This can only occur if FLUSHO
1253 * is also set in t_flags.
1254 */
4147b3f6 1255 if (tp->t_outq.c_cc <= hiwat) {
becb115c 1256 splx(s);
4147b3f6
BJ
1257 goto loop;
1258 }
1259 ttstart(tp);
becb115c 1260 if (tp->t_state&TS_NBIO) {
913ea2d1 1261 if (uio->uio_resid == cnt)
840510a3
BJ
1262 return (EWOULDBLOCK);
1263 return (0);
4147b3f6
BJ
1264 }
1265 tp->t_state |= TS_ASLEEP;
1266 sleep((caddr_t)&tp->t_outq, TTOPRI);
becb115c 1267 splx(s);
4147b3f6
BJ
1268 goto loop;
1269}
1270
1271/*
1272 * Rubout one character from the rawq of tp
1273 * as cleanly as possible.
1274 */
1275ttyrub(c, tp)
4b72e2f9
SL
1276 register c;
1277 register struct tty *tp;
4147b3f6
BJ
1278{
1279 register char *cp;
1280 register int savecol;
1281 int s;
1282 char *nextc();
1283
becb115c 1284 if ((tp->t_flags&ECHO) == 0)
4147b3f6 1285 return;
becb115c 1286 tp->t_flags &= ~FLUSHO;
4147b3f6 1287 c &= 0377;
becb115c 1288 if (tp->t_flags&CRTBS) {
4147b3f6
BJ
1289 if (tp->t_rocount == 0) {
1290 /*
1291 * Screwed by ttwrite; retype
1292 */
1293 ttyretype(tp);
1294 return;
1295 }
becb115c 1296 if (c == ('\t'|0200) || c == ('\n'|0200))
4147b3f6 1297 ttyrubo(tp, 2);
becb115c 1298 else switch (partab[c&=0177]&0177) {
4147b3f6
BJ
1299
1300 case ORDINARY:
1301 if (tp->t_flags&LCASE && c >= 'A' && c <= 'Z')
1302 ttyrubo(tp, 2);
1303 else
1304 ttyrubo(tp, 1);
1305 break;
1306
1307 case VTAB:
1308 case BACKSPACE:
1309 case CONTROL:
1310 case RETURN:
becb115c 1311 if (tp->t_flags&CTLECH)
4147b3f6
BJ
1312 ttyrubo(tp, 2);
1313 break;
1314
1315 case TAB:
1316 if (tp->t_rocount < tp->t_rawq.c_cc) {
1317 ttyretype(tp);
1318 return;
1319 }
1320 s = spl5();
1321 savecol = tp->t_col;
becb115c
SL
1322 tp->t_state |= TS_CNTTB;
1323 tp->t_flags |= FLUSHO;
4147b3f6 1324 tp->t_col = tp->t_rocol;
becb115c
SL
1325 cp = tp->t_rawq.c_cf;
1326 for (; cp; cp = nextc(&tp->t_rawq, cp))
4147b3f6 1327 ttyecho(*cp, tp);
becb115c
SL
1328 tp->t_flags &= ~FLUSHO;
1329 tp->t_state &= ~TS_CNTTB;
4147b3f6
BJ
1330 splx(s);
1331 /*
1332 * savecol will now be length of the tab
1333 */
1334 savecol -= tp->t_col;
1335 tp->t_col += savecol;
1336 if (savecol > 8)
1337 savecol = 8; /* overflow screw */
1338 while (--savecol >= 0)
1339 (void) ttyoutput('\b', tp);
1340 break;
1341
1342 default:
1343 panic("ttyrub");
1344 }
becb115c
SL
1345 } else if (tp->t_flags&PRTERA) {
1346 if ((tp->t_state&TS_ERASE) == 0) {
4147b3f6 1347 (void) ttyoutput('\\', tp);
becb115c 1348 tp->t_state |= TS_ERASE;
4147b3f6
BJ
1349 }
1350 ttyecho(c, tp);
1351 } else
1352 ttyecho(tp->t_erase, tp);
1353 tp->t_rocount--;
1354}
1355
1356/*
1357 * Crt back over cnt chars perhaps
1358 * erasing them.
1359 */
1360ttyrubo(tp, cnt)
4b72e2f9
SL
1361 register struct tty *tp;
1362 int cnt;
4147b3f6 1363{
becb115c 1364 register char *rubostring = tp->t_flags&CRTERA ? "\b \b" : "\b";
4147b3f6
BJ
1365
1366 while (--cnt >= 0)
becb115c 1367 ttyout(rubostring, tp);
4147b3f6
BJ
1368}
1369
1370/*
1371 * Reprint the rawq line.
1372 * We assume c_cc has already been checked.
1373 */
1374ttyretype(tp)
4b72e2f9 1375 register struct tty *tp;
4147b3f6
BJ
1376{
1377 register char *cp;
1378 char *nextc();
1379 int s;
1380
becb115c
SL
1381 if (tp->t_rprntc != 0377)
1382 ttyecho(tp->t_rprntc, tp);
4147b3f6
BJ
1383 (void) ttyoutput('\n', tp);
1384 s = spl5();
1385 for (cp = tp->t_canq.c_cf; cp; cp = nextc(&tp->t_canq, cp))
1386 ttyecho(*cp, tp);
1387 for (cp = tp->t_rawq.c_cf; cp; cp = nextc(&tp->t_rawq, cp))
1388 ttyecho(*cp, tp);
becb115c 1389 tp->t_state &= ~TS_ERASE;
4147b3f6
BJ
1390 splx(s);
1391 tp->t_rocount = tp->t_rawq.c_cc;
1392 tp->t_rocol = 0;
1393}
1394
1395/*
1396 * Echo a typed character to the terminal
1397 */
1398ttyecho(c, tp)
4b72e2f9
SL
1399 register c;
1400 register struct tty *tp;
4147b3f6
BJ
1401{
1402
becb115c
SL
1403 if ((tp->t_state&TS_CNTTB) == 0)
1404 tp->t_flags &= ~FLUSHO;
4147b3f6
BJ
1405 if ((tp->t_flags&ECHO) == 0)
1406 return;
1407 c &= 0377;
1408 if (tp->t_flags&RAW) {
1409 (void) ttyoutput(c, tp);
1410 return;
1411 }
1412 if (c == '\r' && tp->t_flags&CRMOD)
1413 c = '\n';
becb115c 1414 if (tp->t_flags&CTLECH) {
4147b3f6
BJ
1415 if ((c&0177) <= 037 && c!='\t' && c!='\n' || (c&0177)==0177) {
1416 (void) ttyoutput('^', tp);
1417 c &= 0177;
1418 if (c == 0177)
1419 c = '?';
1420 else if (tp->t_flags&LCASE)
1421 c += 'a' - 1;
1422 else
1423 c += 'A' - 1;
1424 }
1425 }
1426 if ((tp->t_flags&LCASE) && (c >= 'A' && c <= 'Z'))
1427 c += 'a' - 'A';
becb115c 1428 (void) ttyoutput(c&0177, tp);
4147b3f6
BJ
1429}
1430
1431/*
1432 * Is c a break char for tp?
1433 */
1434ttbreakc(c, tp)
4b72e2f9
SL
1435 register c;
1436 register struct tty *tp;
4147b3f6 1437{
becb115c 1438 return (c == '\n' || c == tp->t_eofc || c == tp->t_brkc ||
4147b3f6
BJ
1439 c == '\r' && (tp->t_flags&CRMOD));
1440}
1441
1442/*
1443 * send string cp to tp
1444 */
1445ttyout(cp, tp)
4b72e2f9
SL
1446 register char *cp;
1447 register struct tty *tp;
4147b3f6
BJ
1448{
1449 register char c;
1450
1451 while (c = *cp++)
1452 (void) ttyoutput(c, tp);
1453}
1454
1455ttwakeup(tp)
1456 struct tty *tp;
1457{
1458
1459 if (tp->t_rsel) {
1460 selwakeup(tp->t_rsel, tp->t_state&TS_RCOLL);
1461 tp->t_state &= ~TS_RCOLL;
1462 tp->t_rsel = 0;
1463 }
1464 wakeup((caddr_t)&tp->t_rawq);
1465}
1466
becb115c
SL
1467#ifndef vax
1468scanc(size, cp, table, mask)
1469 register int size;
1470 register char *cp, table[];
1471 register int mask;
4147b3f6 1472{
becb115c 1473 register int i = 0;
4147b3f6 1474
becb115c
SL
1475 while ((table[*(u_char *)(cp + i)]&mask) == 0 && i < size)
1476 i++;
1477 return (i);
4147b3f6 1478}
becb115c 1479#endif