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