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