have direnter return errors so new inodes can be thrown away
[unix-history] / usr / src / sys / kern / tty.c
CommitLineData
7c9f96c0 1/* tty.c 4.39 83/01/17 */
961945a8
SL
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 117{
875a1e2c 118 int s;
89dc6dfb 119
875a1e2c 120 s = spl5();
4c67f645
BJ
121 while (tp->t_outq.c_cc && tp->t_state&TS_CARR_ON
122 && tp->t_oproc) { /* kludge for pty */
50e2732b 123 (*tp->t_oproc)(tp);
941944c9 124 tp->t_state |= TS_ASLEEP;
50e2732b
BJ
125 sleep((caddr_t)&tp->t_outq, TTOPRI);
126 }
39697bd8 127 flushtty(tp, FREAD);
875a1e2c 128 splx(s);
89dc6dfb
BJ
129}
130
131/*
becb115c 132 * Flush all TTY queues
89dc6dfb 133 */
50e2732b 134flushtty(tp, rw)
4b72e2f9 135 register struct tty *tp;
89dc6dfb 136{
50e2732b
BJ
137 register s;
138
50e2732b
BJ
139 s = spl6();
140 if (rw & FREAD) {
141 while (getc(&tp->t_canq) >= 0)
142 ;
143 wakeup((caddr_t)&tp->t_rawq);
144 }
145 if (rw & FWRITE) {
146 wakeup((caddr_t)&tp->t_outq);
941944c9 147 tp->t_state &= ~TS_TTSTOP;
39697bd8 148 (*cdevsw[major(tp->t_dev)].d_stop)(tp, rw);
50e2732b
BJ
149 while (getc(&tp->t_outq) >= 0)
150 ;
151 }
152 if (rw & FREAD) {
153 while (getc(&tp->t_rawq) >= 0)
154 ;
155 tp->t_delct = 0;
becb115c 156 tp->t_rocount = 0;
50e2732b 157 tp->t_rocol = 0;
becb115c 158 tp->t_state &= ~TS_LOCAL;
50e2732b
BJ
159 }
160 splx(s);
89dc6dfb
BJ
161}
162
50e2732b
BJ
163/*
164 * Send stop character on input overflow.
165 */
166ttyblock(tp)
4b72e2f9 167 register struct tty *tp;
89dc6dfb 168{
50e2732b 169 register x;
becb115c 170
50e2732b
BJ
171 x = tp->t_rawq.c_cc + tp->t_canq.c_cc;
172 if (tp->t_rawq.c_cc > TTYHOG) {
173 flushtty(tp, FREAD|FWRITE);
941944c9 174 tp->t_state &= ~TS_TBLOCK;
50e2732b 175 }
becb115c
SL
176 if (x >= TTYHOG/2 && putc(tp->t_stopc, &tp->t_outq) == 0) {
177 tp->t_state |= TS_TBLOCK;
becb115c 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 */
7c9f96c0
SL
738 if (tp->t_rawq.c_cc+tp->t_canq.c_cc >= TTYHOG) {
739 if (tp->t_line == NTTYDISC)
740 (void) ttyoutput(CTRL(g), tp);
becb115c 741 goto endcase;
7c9f96c0 742 }
becb115c
SL
743
744 /*
745 * Put data char in q for user and
746 * wakeup on seeing a line delimiter.
747 */
748 if (putc(c, &tp->t_rawq) >= 0) {
becb115c
SL
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 950 register c, t_flags;
875a1e2c 951 int s, 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 */
875a1e2c 959 s = spl5();
becb115c 960 if (tp->t_flags&PENDIN)
4147b3f6 961 ttypend(tp);
875a1e2c 962 splx(s);
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) {
875a1e2c 986 s = spl5();
4147b3f6 987 if (tp->t_rawq.c_cc <= 0) {
becb115c 988 if ((tp->t_state&TS_CARR_ON) == 0 ||
4147b3f6 989 (tp->t_state&TS_NBIO)) {
875a1e2c 990 splx(s);
becb115c 991 return (0);
4147b3f6
BJ
992 }
993 sleep((caddr_t)&tp->t_rawq, TTIPRI);
875a1e2c 994 splx(s);
4147b3f6
BJ
995 goto loop;
996 }
875a1e2c
SL
997 splx(s);
998 while (!error && tp->t_rawq.c_cc && uio->uio_iovcnt)
840510a3 999 error = passuc(getc(&tp->t_rawq), uio);
875a1e2c 1000 goto checktandem;
becb115c
SL
1001 }
1002
1003 /*
1004 * In cbreak mode use the rawq, otherwise
1005 * take characters from the canonicalized q.
1006 */
1007 qp = t_flags&CBREAK ? &tp->t_rawq : &tp->t_canq;
1008
1009 /*
1010 * No input, sleep on rawq awaiting hardware
1011 * receipt and notification.
1012 */
875a1e2c 1013 s = spl5();
becb115c
SL
1014 if (qp->c_cc <= 0) {
1015 if ((tp->t_state&TS_CARR_ON) == 0 ||
1016 (tp->t_state&TS_NBIO)) {
875a1e2c 1017 splx(s);
becb115c 1018 return (EWOULDBLOCK);
4147b3f6 1019 }
becb115c 1020 sleep((caddr_t)&tp->t_rawq, TTIPRI);
875a1e2c 1021 splx(s);
becb115c
SL
1022 goto loop;
1023 }
875a1e2c 1024 splx(s);
becb115c
SL
1025
1026 /*
1027 * Input present, perform input mapping
1028 * and processing (we're not in raw mode).
1029 */
1030 first = 1;
1031 while ((c = getc(qp)) >= 0) {
1032 if (t_flags&CRMOD && c == '\r')
1033 c = '\n';
1034 /*
1035 * Hack lower case simulation on
1036 * upper case only terminals.
1037 */
1038 if (t_flags&LCASE && c <= 0177)
1039 if (tp->t_state&TS_BKSL) {
1040 if (maptab[c])
1041 c = maptab[c];
1042 tp->t_state &= ~TS_BKSL;
1043 } else if (c >= 'A' && c <= 'Z')
1044 c += 'a' - 'A';
1045 else if (c == '\\') {
1046 tp->t_state |= TS_BKSL;
1047 continue;
4147b3f6 1048 }
becb115c
SL
1049 /*
1050 * Check for delayed suspend character.
1051 */
1052 if (tp->t_line == NTTYDISC && c == tp->t_dsuspc) {
1053 gsignal(tp->t_pgrp, SIGTSTP);
1054 if (first) {
1055 sleep((caddr_t)&lbolt, TTIPRI);
1056 goto loop;
1057 }
1058 break;
4147b3f6 1059 }
becb115c
SL
1060 /*
1061 * Interpret EOF only in cooked mode.
1062 */
1063 if (c == tp->t_eofc && (t_flags&CBREAK) == 0)
1064 break;
1065 /*
1066 * Give user character.
1067 */
1068 error = passuc(c & 0177, uio);
1069 if (error)
1070 break;
1071 if (uio->uio_iovcnt == 0)
1072 break;
1073 /*
1074 * In cooked mode check for a "break character"
1075 * marking the end of a "line of input".
1076 */
1077 if ((t_flags&CBREAK) == 0 && ttbreakc(c, tp))
1078 break;
1079 first = 0;
4147b3f6 1080 }
becb115c
SL
1081 tp->t_state &= ~TS_BKSL;
1082
875a1e2c 1083checktandem:
becb115c
SL
1084 /*
1085 * Look to unblock output now that (presumably)
1086 * the input queue has gone down.
1087 */
875a1e2c 1088 if (tp->t_state&TS_TBLOCK && tp->t_rawq.c_cc < TTYHOG/5)
becb115c 1089 if (putc(tp->t_startc, &tp->t_outq) == 0) {
4147b3f6
BJ
1090 tp->t_state &= ~TS_TBLOCK;
1091 ttstart(tp);
1092 }
840510a3 1093 return (error);
4147b3f6
BJ
1094}
1095
1096/*
1097 * Called from the device's write routine after it has
1098 * calculated the tty-structure given as argument.
1099 */
913ea2d1 1100ttwrite(tp, uio)
4b72e2f9 1101 register struct tty *tp;
becb115c 1102 register struct uio *uio;
4147b3f6 1103{
4147b3f6 1104 register char *cp;
becb115c
SL
1105 register int cc, ce, c;
1106 int i, hiwat, cnt, error, s;
4147b3f6 1107 char obuf[OBUFSIZ];
4147b3f6 1108
becb115c 1109 if ((tp->t_state&TS_CARR_ON) == 0)
840510a3 1110 return (EIO);
becb115c
SL
1111 hiwat = TTHIWAT(tp);
1112 cnt = uio->uio_resid;
1113 error = 0;
4147b3f6 1114loop:
becb115c
SL
1115 /*
1116 * Hang the process if it's in the background.
1117 */
4147b3f6 1118 while (u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp &&
becb115c 1119 (tp->t_flags&TOSTOP) && (u.u_procp->p_flag&SVFORK)==0 &&
4147b3f6
BJ
1120 u.u_signal[SIGTTOU] != SIG_IGN &&
1121 u.u_signal[SIGTTOU] != SIG_HOLD
1122/*
1123 &&
1124 (u.u_procp->p_flag&SDETACH)==0) {
1125*/
1126 ) {
1127 gsignal(u.u_procp->p_pgrp, SIGTTOU);
1128 sleep((caddr_t)&lbolt, TTIPRI);
1129 }
becb115c
SL
1130
1131 /*
1132 * Process the user's data in at most OBUFSIZ
1133 * chunks. Perform lower case simulation and
1134 * similar hacks. Keep track of high water
1135 * mark, sleep on overflow awaiting device aid
1136 * in acquiring new space.
1137 */
913ea2d1 1138 while (uio->uio_resid > 0) {
becb115c
SL
1139 /*
1140 * Grab a hunk of data from the user.
1141 */
913ea2d1
BJ
1142 cc = uio->uio_iov->iov_len;
1143 if (cc == 0) {
1144 uio->uio_iovcnt--;
1145 uio->uio_iov++;
1146 if (uio->uio_iovcnt < 0)
1147 panic("ttwrite");
1148 continue;
1149 }
1150 if (cc > OBUFSIZ)
1151 cc = OBUFSIZ;
4147b3f6 1152 cp = obuf;
becb115c 1153 error = uiomove(cp, (unsigned)cc, UIO_WRITE, uio);
840510a3 1154 if (error)
4147b3f6
BJ
1155 break;
1156 if (tp->t_outq.c_cc > hiwat)
1157 goto ovhiwat;
becb115c 1158 if (tp->t_flags&FLUSHO)
4147b3f6 1159 continue;
becb115c
SL
1160 /*
1161 * If we're mapping lower case or kludging tildes,
1162 * then we've got to look at each character, so
1163 * just feed the stuff to ttyoutput...
1164 */
1165 if (tp->t_flags & (LCASE|TILDE)) {
1166 while (cc > 0) {
4147b3f6
BJ
1167 c = *cp++;
1168 tp->t_rocount = 0;
4b72e2f9 1169 while ((c = ttyoutput(c, tp)) >= 0) {
4147b3f6
BJ
1170 /* out of clists, wait a bit */
1171 ttstart(tp);
1172 sleep((caddr_t)&lbolt, TTOPRI);
1173 tp->t_rocount = 0;
1174 }
1175 --cc;
1176 if (tp->t_outq.c_cc > hiwat)
1177 goto ovhiwat;
1178 }
1179 continue;
1180 }
becb115c
SL
1181 /*
1182 * If nothing fancy need be done, grab those characters we
1183 * can handle without any of ttyoutput's processing and
1184 * just transfer them to the output q. For those chars
1185 * which require special processing (as indicated by the
1186 * bits in partab), call ttyoutput. After processing
1187 * a hunk of data, look for FLUSHO so ^O's will take effect
1188 * immediately.
1189 */
1190 while (cc > 0) {
1191 if (tp->t_flags & (RAW|LITOUT))
4147b3f6
BJ
1192 ce = cc;
1193 else {
becb115c
SL
1194 ce = cc - scanc(cc, cp, partab, 077);
1195 /*
1196 * If ce is zero, then we're processing
1197 * a special character through ttyoutput.
1198 */
1199 if (ce == 0) {
4147b3f6
BJ
1200 tp->t_rocount = 0;
1201 if (ttyoutput(*cp, tp) >= 0) {
becb115c 1202 /* no c-lists, wait a bit */
4147b3f6
BJ
1203 ttstart(tp);
1204 sleep((caddr_t)&lbolt, TTOPRI);
1205 continue;
1206 }
becb115c
SL
1207 cp++, cc--;
1208 if (tp->t_flags&FLUSHO ||
1209 tp->t_outq.c_cc > hiwat)
4147b3f6 1210 goto ovhiwat;
becb115c 1211 continue;
4147b3f6
BJ
1212 }
1213 }
becb115c
SL
1214 /*
1215 * A bunch of normal characters have been found,
1216 * transfer them en masse to the output queue and
1217 * continue processing at the top of the loop.
1218 * If there are any further characters in this
1219 * <= OBUFSIZ chunk, the first should be a character
1220 * requiring special handling by ttyoutput.
1221 */
4147b3f6 1222 tp->t_rocount = 0;
becb115c
SL
1223 i = b_to_q(cp, ce, &tp->t_outq);
1224 ce -= i;
1225 tp->t_col += ce;
1226 cp += ce, cc -= ce, tk_nout += ce;
1227 if (i > 0) {
1228 /* out of c-lists, wait a bit */
4147b3f6
BJ
1229 ttstart(tp);
1230 sleep((caddr_t)&lbolt, TTOPRI);
1231 }
becb115c 1232 if (tp->t_flags&FLUSHO || tp->t_outq.c_cc > hiwat)
4147b3f6
BJ
1233 goto ovhiwat;
1234 }
1235 }
1236 ttstart(tp);
840510a3 1237 return (error);
4147b3f6
BJ
1238
1239ovhiwat:
becb115c
SL
1240 s = spl5();
1241 if (cc != 0) {
1242 uio->uio_iov->iov_base -= cc;
1243 uio->uio_iov->iov_len += cc;
1244 uio->uio_resid += cc;
1245 uio->uio_offset -= cc;
1246 }
1247 /*
1248 * This can only occur if FLUSHO
1249 * is also set in t_flags.
1250 */
4147b3f6 1251 if (tp->t_outq.c_cc <= hiwat) {
becb115c 1252 splx(s);
4147b3f6
BJ
1253 goto loop;
1254 }
1255 ttstart(tp);
becb115c 1256 if (tp->t_state&TS_NBIO) {
913ea2d1 1257 if (uio->uio_resid == cnt)
840510a3
BJ
1258 return (EWOULDBLOCK);
1259 return (0);
4147b3f6
BJ
1260 }
1261 tp->t_state |= TS_ASLEEP;
1262 sleep((caddr_t)&tp->t_outq, TTOPRI);
becb115c 1263 splx(s);
4147b3f6
BJ
1264 goto loop;
1265}
1266
1267/*
1268 * Rubout one character from the rawq of tp
1269 * as cleanly as possible.
1270 */
1271ttyrub(c, tp)
4b72e2f9
SL
1272 register c;
1273 register struct tty *tp;
4147b3f6
BJ
1274{
1275 register char *cp;
1276 register int savecol;
1277 int s;
1278 char *nextc();
1279
becb115c 1280 if ((tp->t_flags&ECHO) == 0)
4147b3f6 1281 return;
becb115c 1282 tp->t_flags &= ~FLUSHO;
4147b3f6 1283 c &= 0377;
becb115c 1284 if (tp->t_flags&CRTBS) {
4147b3f6
BJ
1285 if (tp->t_rocount == 0) {
1286 /*
1287 * Screwed by ttwrite; retype
1288 */
1289 ttyretype(tp);
1290 return;
1291 }
becb115c 1292 if (c == ('\t'|0200) || c == ('\n'|0200))
4147b3f6 1293 ttyrubo(tp, 2);
becb115c 1294 else switch (partab[c&=0177]&0177) {
4147b3f6
BJ
1295
1296 case ORDINARY:
1297 if (tp->t_flags&LCASE && c >= 'A' && c <= 'Z')
1298 ttyrubo(tp, 2);
1299 else
1300 ttyrubo(tp, 1);
1301 break;
1302
1303 case VTAB:
1304 case BACKSPACE:
1305 case CONTROL:
1306 case RETURN:
becb115c 1307 if (tp->t_flags&CTLECH)
4147b3f6
BJ
1308 ttyrubo(tp, 2);
1309 break;
1310
1311 case TAB:
1312 if (tp->t_rocount < tp->t_rawq.c_cc) {
1313 ttyretype(tp);
1314 return;
1315 }
1316 s = spl5();
1317 savecol = tp->t_col;
becb115c
SL
1318 tp->t_state |= TS_CNTTB;
1319 tp->t_flags |= FLUSHO;
4147b3f6 1320 tp->t_col = tp->t_rocol;
becb115c
SL
1321 cp = tp->t_rawq.c_cf;
1322 for (; cp; cp = nextc(&tp->t_rawq, cp))
4147b3f6 1323 ttyecho(*cp, tp);
becb115c
SL
1324 tp->t_flags &= ~FLUSHO;
1325 tp->t_state &= ~TS_CNTTB;
4147b3f6
BJ
1326 splx(s);
1327 /*
1328 * savecol will now be length of the tab
1329 */
1330 savecol -= tp->t_col;
1331 tp->t_col += savecol;
1332 if (savecol > 8)
1333 savecol = 8; /* overflow screw */
1334 while (--savecol >= 0)
1335 (void) ttyoutput('\b', tp);
1336 break;
1337
1338 default:
1339 panic("ttyrub");
1340 }
becb115c
SL
1341 } else if (tp->t_flags&PRTERA) {
1342 if ((tp->t_state&TS_ERASE) == 0) {
4147b3f6 1343 (void) ttyoutput('\\', tp);
becb115c 1344 tp->t_state |= TS_ERASE;
4147b3f6
BJ
1345 }
1346 ttyecho(c, tp);
1347 } else
1348 ttyecho(tp->t_erase, tp);
1349 tp->t_rocount--;
1350}
1351
1352/*
1353 * Crt back over cnt chars perhaps
1354 * erasing them.
1355 */
1356ttyrubo(tp, cnt)
4b72e2f9
SL
1357 register struct tty *tp;
1358 int cnt;
4147b3f6 1359{
becb115c 1360 register char *rubostring = tp->t_flags&CRTERA ? "\b \b" : "\b";
4147b3f6
BJ
1361
1362 while (--cnt >= 0)
becb115c 1363 ttyout(rubostring, tp);
4147b3f6
BJ
1364}
1365
1366/*
1367 * Reprint the rawq line.
1368 * We assume c_cc has already been checked.
1369 */
1370ttyretype(tp)
4b72e2f9 1371 register struct tty *tp;
4147b3f6
BJ
1372{
1373 register char *cp;
1374 char *nextc();
1375 int s;
1376
becb115c
SL
1377 if (tp->t_rprntc != 0377)
1378 ttyecho(tp->t_rprntc, tp);
4147b3f6
BJ
1379 (void) ttyoutput('\n', tp);
1380 s = spl5();
1381 for (cp = tp->t_canq.c_cf; cp; cp = nextc(&tp->t_canq, cp))
1382 ttyecho(*cp, tp);
1383 for (cp = tp->t_rawq.c_cf; cp; cp = nextc(&tp->t_rawq, cp))
1384 ttyecho(*cp, tp);
becb115c 1385 tp->t_state &= ~TS_ERASE;
4147b3f6
BJ
1386 splx(s);
1387 tp->t_rocount = tp->t_rawq.c_cc;
1388 tp->t_rocol = 0;
1389}
1390
1391/*
1392 * Echo a typed character to the terminal
1393 */
1394ttyecho(c, tp)
4b72e2f9
SL
1395 register c;
1396 register struct tty *tp;
4147b3f6
BJ
1397{
1398
becb115c
SL
1399 if ((tp->t_state&TS_CNTTB) == 0)
1400 tp->t_flags &= ~FLUSHO;
4147b3f6
BJ
1401 if ((tp->t_flags&ECHO) == 0)
1402 return;
1403 c &= 0377;
1404 if (tp->t_flags&RAW) {
1405 (void) ttyoutput(c, tp);
1406 return;
1407 }
1408 if (c == '\r' && tp->t_flags&CRMOD)
1409 c = '\n';
becb115c 1410 if (tp->t_flags&CTLECH) {
4147b3f6
BJ
1411 if ((c&0177) <= 037 && c!='\t' && c!='\n' || (c&0177)==0177) {
1412 (void) ttyoutput('^', tp);
1413 c &= 0177;
1414 if (c == 0177)
1415 c = '?';
1416 else if (tp->t_flags&LCASE)
1417 c += 'a' - 1;
1418 else
1419 c += 'A' - 1;
1420 }
1421 }
1422 if ((tp->t_flags&LCASE) && (c >= 'A' && c <= 'Z'))
1423 c += 'a' - 'A';
becb115c 1424 (void) ttyoutput(c&0177, tp);
4147b3f6
BJ
1425}
1426
1427/*
1428 * Is c a break char for tp?
1429 */
1430ttbreakc(c, tp)
4b72e2f9
SL
1431 register c;
1432 register struct tty *tp;
4147b3f6 1433{
becb115c 1434 return (c == '\n' || c == tp->t_eofc || c == tp->t_brkc ||
4147b3f6
BJ
1435 c == '\r' && (tp->t_flags&CRMOD));
1436}
1437
1438/*
1439 * send string cp to tp
1440 */
1441ttyout(cp, tp)
4b72e2f9
SL
1442 register char *cp;
1443 register struct tty *tp;
4147b3f6
BJ
1444{
1445 register char c;
1446
1447 while (c = *cp++)
1448 (void) ttyoutput(c, tp);
1449}
1450
1451ttwakeup(tp)
1452 struct tty *tp;
1453{
1454
1455 if (tp->t_rsel) {
1456 selwakeup(tp->t_rsel, tp->t_state&TS_RCOLL);
1457 tp->t_state &= ~TS_RCOLL;
1458 tp->t_rsel = 0;
1459 }
1460 wakeup((caddr_t)&tp->t_rawq);
1461}
1462
7c9f96c0 1463#if !defined(vax) && !defined(sun)
becb115c
SL
1464scanc(size, cp, table, mask)
1465 register int size;
1466 register char *cp, table[];
1467 register int mask;
4147b3f6 1468{
becb115c 1469 register int i = 0;
4147b3f6 1470
becb115c
SL
1471 while ((table[*(u_char *)(cp + i)]&mask) == 0 && i < size)
1472 i++;
1473 return (i);
4147b3f6 1474}
becb115c 1475#endif