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