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