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