lint
[unix-history] / usr / src / sys / kern / tty.c
CommitLineData
da7c5cc6 1/*
0880b18e 2 * Copyright (c) 1982, 1986 Regents of the University of California.
da7c5cc6
KM
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 *
1eebc1a7 6 * @(#)tty.c 7.10 (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"
94368568
JB
18#include "file.h"
19#include "conf.h"
fb1db32c 20#include "dkstat.h"
94368568
JB
21#include "uio.h"
22#include "kernel.h"
89dc6dfb 23
8bba2b8f
RE
24/*
25 * Table giving parity for characters and indicating
26 * character classes to tty driver. In particular,
27 * if the low 6 bits are 0, then the character needs
28 * no special processing on output.
29 */
30
31char partab[] = {
32 0001,0201,0201,0001,0201,0001,0001,0201,
33 0202,0004,0003,0201,0005,0206,0201,0001,
34 0201,0001,0001,0201,0001,0201,0201,0001,
35 0001,0201,0201,0001,0201,0001,0001,0201,
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 0200,0000,0000,0200,0000,0200,0200,0000,
41 0000,0200,0200,0000,0200,0000,0000,0200,
42 0000,0200,0200,0000,0200,0000,0000,0200,
43 0200,0000,0000,0200,0000,0200,0200,0000,
44 0000,0200,0200,0000,0200,0000,0000,0200,
45 0200,0000,0000,0200,0000,0200,0200,0000,
46 0200,0000,0000,0200,0000,0200,0200,0000,
47 0000,0200,0200,0000,0200,0000,0000,0201,
48
49 /*
50 * 7 bit ascii ends with the last character above,
51 * but we contine through all 256 codes for the sake
52 * of the tty output routines which use special vax
53 * instructions which need a 256 character trt table.
54 */
55
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 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};
89dc6dfb 73
89dc6dfb
BJ
74/*
75 * Input mapping table-- if an entry is non-zero, when the
76 * corresponding character is typed preceded by "\" the escape
77 * sequence is replaced by the table value. Mostly used for
78 * upper-case only terminals.
79 */
89dc6dfb
BJ
80char maptab[] ={
81 000,000,000,000,000,000,000,000,
82 000,000,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,'`',
86 '{','}',000,000,000,000,000,000,
87 000,000,000,000,000,000,000,000,
88 000,000,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,
93 000,'A','B','C','D','E','F','G',
94 'H','I','J','K','L','M','N','O',
95 'P','Q','R','S','T','U','V','W',
96 'X','Y','Z',000,000,000,000,000,
97};
98
0d65848d 99short tthiwat[16] =
6f21eede 100 { 100,100,100,100,100,100,100,200,200,400,400,400,650,650,1300,2000 };
0d65848d
BJ
101short ttlowat[16] =
102 { 30, 30, 30, 30, 30, 30, 30, 50, 50,120,120,120,125,125,125,125 };
103
becb115c
SL
104struct ttychars ttydefaults = {
105 CERASE, CKILL, CINTR, CQUIT, CSTART, CSTOP, CEOF,
106 CBRK, CSUSP, CDSUSP, CRPRNT, CFLUSH, CWERASE,CLNEXT
107};
89dc6dfb 108
adf4bc89
MK
109extern struct tty *constty; /* temporary virtual console */
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) &&
9670d122 135 tp->t_state&TS_CARR_ON && tp->t_oproc) {
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{
8062c8a7 225
b482b2c8 226 if (tp->t_oproc) /* kludge for pty */
50e2732b 227 (*tp->t_oproc)(tp);
89dc6dfb
BJ
228}
229
230/*
50e2732b 231 * Common code for tty ioctls.
89dc6dfb 232 */
49c84d3f 233/*ARGSUSED*/
4b72e2f9
SL
234ttioctl(tp, com, data, flag)
235 register struct tty *tp;
236 caddr_t data;
89dc6dfb 237{
840510a3 238 int dev = tp->t_dev;
89dc6dfb 239 extern int nldisp;
fc6972ae 240 int s;
88a7a62a 241 register int newflags;
89dc6dfb 242
adf4bc89 243
50e2732b
BJ
244 /*
245 * If the ioctl involves modification,
4f3a716e 246 * hang if in the background.
50e2732b 247 */
4b72e2f9 248 switch (com) {
50e2732b 249
c6fe3a50
BJ
250 case TIOCSETD:
251 case TIOCSETP:
252 case TIOCSETN:
50e2732b
BJ
253 case TIOCFLUSH:
254 case TIOCSETC:
255 case TIOCSLTC:
256 case TIOCSPGRP:
257 case TIOCLBIS:
258 case TIOCLBIC:
259 case TIOCLSET:
8203fe05 260 case TIOCSTI:
f9eea644 261 case TIOCSWINSZ:
50e2732b
BJ
262 while (tp->t_line == NTTYDISC &&
263 u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp &&
264 (u.u_procp->p_flag&SVFORK) == 0 &&
52c041cd
MK
265 !(u.u_procp->p_sigignore & sigmask(SIGTTOU)) &&
266 !(u.u_procp->p_sigmask & sigmask(SIGTTOU))) {
50e2732b
BJ
267 gsignal(u.u_procp->p_pgrp, SIGTTOU);
268 sleep((caddr_t)&lbolt, TTOPRI);
269 }
270 break;
271 }
272
becb115c
SL
273 /*
274 * Process the ioctl.
275 */
4b72e2f9 276 switch (com) {
89dc6dfb 277
fc6972ae 278 /* get discipline number */
89dc6dfb 279 case TIOCGETD:
4b72e2f9 280 *(int *)data = tp->t_line;
89dc6dfb
BJ
281 break;
282
fc6972ae 283 /* set line discipline */
4b72e2f9
SL
284 case TIOCSETD: {
285 register int t = *(int *)data;
becb115c 286 int error = 0;
4b72e2f9 287
9b905352 288 if ((unsigned) t >= nldisp)
4a003df3 289 return (ENXIO);
2eaeef4d
MK
290 if (t != tp->t_line) {
291 s = spltty();
292 (*linesw[tp->t_line].l_close)(tp);
293 error = (*linesw[t].l_open)(dev, tp);
294 if (error) {
295 (void) (*linesw[tp->t_line].l_open)(dev, tp);
296 splx(s);
297 return (error);
298 }
299 tp->t_line = t;
4a003df3 300 splx(s);
4a003df3 301 }
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:
fb1db32c 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
adf4bc89
MK
504 case TIOCCONS:
505 if (*(int *)data) {
506 if (constty != NULL)
507 return (EBUSY);
508#ifndef UCONSOLE
509 if (!suser())
510 return (EPERM);
511#endif
512 constty = tp;
513 } else if (tp == constty)
1eebc1a7 514 constty = NULL;
adf4bc89
MK
515 break;
516
89dc6dfb 517 default:
fc6972ae 518 return (-1);
89dc6dfb 519 }
fc6972ae 520 return (0);
89dc6dfb 521}
e1d74936
BJ
522
523ttnread(tp)
524 struct tty *tp;
525{
526 int nread = 0;
527
becb115c 528 if (tp->t_flags & PENDIN)
e1d74936
BJ
529 ttypend(tp);
530 nread = tp->t_canq.c_cc;
531 if (tp->t_flags & (RAW|CBREAK))
532 nread += tp->t_rawq.c_cc;
533 return (nread);
534}
535
941944c9 536ttselect(dev, rw)
e1d74936 537 dev_t dev;
941944c9 538 int rw;
e1d74936
BJ
539{
540 register struct tty *tp = &cdevsw[major(dev)].d_ttys[minor(dev)];
541 int nread;
4f3a716e 542 int s = spltty();
e1d74936 543
941944c9 544 switch (rw) {
e1d74936
BJ
545
546 case FREAD:
547 nread = ttnread(tp);
fb1db32c 548 if (nread > 0 || (tp->t_state & TS_CARR_ON) == 0)
941944c9 549 goto win;
89b8a44c 550 if (tp->t_rsel && tp->t_rsel->p_wchan == (caddr_t)&selwait)
941944c9 551 tp->t_state |= TS_RCOLL;
e1d74936
BJ
552 else
553 tp->t_rsel = u.u_procp;
941944c9 554 break;
e1d74936 555
941944c9
BJ
556 case FWRITE:
557 if (tp->t_outq.c_cc <= TTLOWAT(tp))
558 goto win;
941944c9
BJ
559 if (tp->t_wsel && tp->t_wsel->p_wchan == (caddr_t)&selwait)
560 tp->t_state |= TS_WCOLL;
561 else
562 tp->t_wsel = u.u_procp;
563 break;
e1d74936 564 }
941944c9
BJ
565 splx(s);
566 return (0);
567win:
568 splx(s);
569 return (1);
e1d74936 570}
8bba2b8f 571
4147b3f6 572/*
605d7712 573 * Initial open of tty, or (re)entry to line discipline.
becb115c 574 * Establish a process group for distribution of
4147b3f6 575 * quits and interrupts from the tty.
4147b3f6
BJ
576 */
577ttyopen(dev, tp)
4b72e2f9
SL
578 dev_t dev;
579 register struct tty *tp;
4147b3f6
BJ
580{
581 register struct proc *pp;
582
583 pp = u.u_procp;
584 tp->t_dev = dev;
4b72e2f9 585 if (pp->p_pgrp == 0) {
4147b3f6
BJ
586 u.u_ttyp = tp;
587 u.u_ttyd = dev;
588 if (tp->t_pgrp == 0)
589 tp->t_pgrp = pp->p_pid;
590 pp->p_pgrp = tp->t_pgrp;
591 }
592 tp->t_state &= ~TS_WOPEN;
4f3a716e
MK
593 if ((tp->t_state & TS_ISOPEN) == 0) {
594 tp->t_state |= TS_ISOPEN;
f9eea644 595 bzero((caddr_t)&tp->t_winsize, sizeof(tp->t_winsize));
4f3a716e
MK
596 if (tp->t_line != NTTYDISC)
597 ttywflush(tp);
598 }
fc6972ae 599 return (0);
4147b3f6
BJ
600}
601
605d7712
MK
602/*
603 * "close" a line discipline
604 */
605ttylclose(tp)
606 register struct tty *tp;
607{
608
609 ttywflush(tp);
610 tp->t_line = 0;
611}
612
4147b3f6
BJ
613/*
614 * clean tp on last close
615 */
616ttyclose(tp)
4b72e2f9 617 register struct tty *tp;
4147b3f6
BJ
618{
619
adf4bc89
MK
620 if (constty == tp)
621 constty = NULL;
605d7712 622 ttyflush(tp, FREAD|FWRITE);
4147b3f6 623 tp->t_pgrp = 0;
4147b3f6
BJ
624 tp->t_state = 0;
625}
626
605d7712
MK
627/*
628 * Handle modem control transition on a tty.
629 * Flag indicates new state of carrier.
630 * Returns 0 if the line should be turned off, otherwise 1.
631 */
632ttymodem(tp, flag)
633 register struct tty *tp;
634{
635
636 if ((tp->t_state&TS_WOPEN) == 0 && (tp->t_flags & MDMBUF)) {
637 /*
638 * MDMBUF: do flow control according to carrier flag
639 */
640 if (flag) {
641 tp->t_state &= ~TS_TTSTOP;
642 ttstart(tp);
643 } else if ((tp->t_state&TS_TTSTOP) == 0) {
644 tp->t_state |= TS_TTSTOP;
645 (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
646 }
647 } else if (flag == 0) {
648 /*
649 * Lost carrier.
650 */
651 tp->t_state &= ~TS_CARR_ON;
652 if (tp->t_state & TS_ISOPEN) {
653 if ((tp->t_flags & NOHANG) == 0) {
654 gsignal(tp->t_pgrp, SIGHUP);
655 gsignal(tp->t_pgrp, SIGCONT);
656 ttyflush(tp, FREAD|FWRITE);
657 return (0);
658 }
659 }
660 } else {
661 /*
662 * Carrier now on.
663 */
664 tp->t_state |= TS_CARR_ON;
665 wakeup((caddr_t)&tp->t_rawq);
666 }
667 return (1);
668}
669
e3f2038d
MK
670/*
671 * Default modem control routine (for other line disciplines).
672 * Return argument flag, to turn off device on carrier drop.
673 */
2f54b5e8
MK
674nullmodem(tp, flag)
675 register struct tty *tp;
e3f2038d
MK
676 int flag;
677{
678
679 if (flag)
680 tp->t_state |= TS_CARR_ON;
681 else
682 tp->t_state &= ~TS_CARR_ON;
683 return (flag);
684}
685
4147b3f6
BJ
686/*
687 * reinput pending characters after state switch
4f3a716e 688 * call at spltty().
4147b3f6
BJ
689 */
690ttypend(tp)
4b72e2f9 691 register struct tty *tp;
4147b3f6
BJ
692{
693 struct clist tq;
694 register c;
695
becb115c
SL
696 tp->t_flags &= ~PENDIN;
697 tp->t_state |= TS_TYPEN;
4147b3f6
BJ
698 tq = tp->t_rawq;
699 tp->t_rawq.c_cc = 0;
700 tp->t_rawq.c_cf = tp->t_rawq.c_cl = 0;
701 while ((c = getc(&tq)) >= 0)
702 ttyinput(c, tp);
becb115c 703 tp->t_state &= ~TS_TYPEN;
4147b3f6
BJ
704}
705
706/*
becb115c
SL
707 * Place a character on raw TTY input queue,
708 * putting in delimiters and waking up top
709 * half as needed. Also echo if required.
710 * The arguments are the character and the
711 * appropriate tty structure.
4147b3f6
BJ
712 */
713ttyinput(c, tp)
4b72e2f9
SL
714 register c;
715 register struct tty *tp;
4147b3f6 716{
becb115c 717 register int t_flags = tp->t_flags;
4147b3f6
BJ
718 int i;
719
becb115c
SL
720 /*
721 * If input is pending take it first.
722 */
723 if (t_flags&PENDIN)
4147b3f6
BJ
724 ttypend(tp);
725 tk_nin++;
726 c &= 0377;
becb115c
SL
727
728 /*
729 * In tandem mode, check high water mark.
730 */
4147b3f6
BJ
731 if (t_flags&TANDEM)
732 ttyblock(tp);
becb115c
SL
733
734 if (t_flags&RAW) {
735 /*
736 * Raw mode, just put character
737 * in input q w/o interpretation.
738 */
739 if (tp->t_rawq.c_cc > TTYHOG)
88a7a62a 740 ttyflush(tp, FREAD|FWRITE);
becb115c
SL
741 else {
742 if (putc(c, &tp->t_rawq) >= 0)
743 ttwakeup(tp);
744 ttyecho(c, tp);
4147b3f6 745 }
becb115c
SL
746 goto endcase;
747 }
748
749 /*
750 * Ignore any high bit added during
751 * previous ttyinput processing.
752 */
fb01874e 753 if ((tp->t_state&TS_TYPEN) == 0 && (t_flags&PASS8) == 0)
becb115c
SL
754 c &= 0177;
755 /*
756 * Check for literal nexting very first
757 */
758 if (tp->t_state&TS_LNCH) {
759 c |= 0200;
760 tp->t_state &= ~TS_LNCH;
761 }
762
763 /*
764 * Scan for special characters. This code
765 * is really just a big case statement with
766 * non-constant cases. The bottom of the
767 * case statement is labeled ``endcase'', so goto
768 * it after a case match, or similar.
769 */
770 if (tp->t_line == NTTYDISC) {
771 if (c == tp->t_lnextc) {
93d2ecff 772 if (t_flags&ECHO)
4147b3f6 773 ttyout("^\b", tp);
becb115c
SL
774 tp->t_state |= TS_LNCH;
775 goto endcase;
776 }
777 if (c == tp->t_flushc) {
93d2ecff 778 if (t_flags&FLUSHO)
becb115c 779 tp->t_flags &= ~FLUSHO;
4147b3f6 780 else {
88a7a62a 781 ttyflush(tp, FWRITE);
4147b3f6 782 ttyecho(c, tp);
becb115c 783 if (tp->t_rawq.c_cc + tp->t_canq.c_cc)
4147b3f6 784 ttyretype(tp);
becb115c 785 tp->t_flags |= FLUSHO;
4147b3f6 786 }
becb115c
SL
787 goto startoutput;
788 }
789 if (c == tp->t_suspc) {
93d2ecff 790 if ((t_flags&NOFLSH) == 0)
88a7a62a 791 ttyflush(tp, FREAD);
4147b3f6 792 ttyecho(c, tp);
becb115c
SL
793 gsignal(tp->t_pgrp, SIGTSTP);
794 goto endcase;
795 }
796 }
797
798 /*
799 * Handle start/stop characters.
800 */
801 if (c == tp->t_stopc) {
802 if ((tp->t_state&TS_TTSTOP) == 0) {
803 tp->t_state |= TS_TTSTOP;
804 (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
805 return;
806 }
807 if (c != tp->t_startc)
808 return;
809 goto endcase;
810 }
811 if (c == tp->t_startc)
812 goto restartoutput;
813
814 /*
815 * Look for interrupt/quit chars.
816 */
817 if (c == tp->t_intrc || c == tp->t_quitc) {
93d2ecff 818 if ((t_flags&NOFLSH) == 0)
88a7a62a 819 ttyflush(tp, FREAD|FWRITE);
becb115c
SL
820 ttyecho(c, tp);
821 gsignal(tp->t_pgrp, c == tp->t_intrc ? SIGINT : SIGQUIT);
822 goto endcase;
823 }
824
58786a81
JB
825 if (tp->t_flags & LCASE && c <= 0177) {
826 if (tp->t_state&TS_BKSL) {
827 ttyrub(unputc(&tp->t_rawq), tp);
828 if (maptab[c])
829 c = maptab[c];
830 c |= 0200;
831 tp->t_state &= ~(TS_BKSL|TS_QUOT);
832 } else if (c >= 'A' && c <= 'Z')
833 c += 'a' - 'A';
834 else if (c == '\\')
835 tp->t_state |= TS_BKSL;
836 }
837
becb115c
SL
838 /*
839 * Cbreak mode, don't process line editing
840 * characters; check high water mark for wakeup.
841 */
842 if (t_flags&CBREAK) {
843 if (tp->t_rawq.c_cc > TTYHOG) {
4147b3f6
BJ
844 if (tp->t_outq.c_cc < TTHIWAT(tp) &&
845 tp->t_line == NTTYDISC)
7f2567b2 846 (void) ttyoutput(CTRL('g'), tp);
4147b3f6
BJ
847 } else if (putc(c, &tp->t_rawq) >= 0) {
848 ttwakeup(tp);
849 ttyecho(c, tp);
850 }
becb115c
SL
851 goto endcase;
852 }
853
854 /*
855 * From here on down cooked mode character
856 * processing takes place.
857 */
858 if ((tp->t_state&TS_QUOT) &&
859 (c == tp->t_erase || c == tp->t_kill)) {
860 ttyrub(unputc(&tp->t_rawq), tp);
861 c |= 0200;
862 }
863 if (c == tp->t_erase) {
864 if (tp->t_rawq.c_cc)
865 ttyrub(unputc(&tp->t_rawq), tp);
866 goto endcase;
867 }
868 if (c == tp->t_kill) {
93d2ecff 869 if (t_flags&CRTKIL &&
becb115c
SL
870 tp->t_rawq.c_cc == tp->t_rocount) {
871 while (tp->t_rawq.c_cc)
872 ttyrub(unputc(&tp->t_rawq), tp);
873 } else {
874 ttyecho(c, tp);
875 ttyecho('\n', tp);
876 while (getc(&tp->t_rawq) > 0)
877 ;
878 tp->t_rocount = 0;
879 }
880 tp->t_state &= ~TS_LOCAL;
881 goto endcase;
882 }
883
884 /*
885 * New line discipline,
886 * check word erase/reprint line.
887 */
888 if (tp->t_line == NTTYDISC) {
889 if (c == tp->t_werasc) {
890 if (tp->t_rawq.c_cc == 0)
891 goto endcase;
892 do {
893 c = unputc(&tp->t_rawq);
894 if (c != ' ' && c != '\t')
895 goto erasenb;
896 ttyrub(c, tp);
897 } while (tp->t_rawq.c_cc);
898 goto endcase;
899 erasenb:
900 do {
901 ttyrub(c, tp);
902 if (tp->t_rawq.c_cc == 0)
903 goto endcase;
904 c = unputc(&tp->t_rawq);
905 } while (c != ' ' && c != '\t');
906 (void) putc(c, &tp->t_rawq);
907 goto endcase;
908 }
909 if (c == tp->t_rprntc) {
910 ttyretype(tp);
911 goto endcase;
912 }
913 }
914
915 /*
916 * Check for input buffer overflow
917 */
7c9f96c0
SL
918 if (tp->t_rawq.c_cc+tp->t_canq.c_cc >= TTYHOG) {
919 if (tp->t_line == NTTYDISC)
7f2567b2 920 (void) ttyoutput(CTRL('g'), tp);
becb115c 921 goto endcase;
7c9f96c0 922 }
becb115c
SL
923
924 /*
925 * Put data char in q for user and
926 * wakeup on seeing a line delimiter.
927 */
928 if (putc(c, &tp->t_rawq) >= 0) {
becb115c
SL
929 if (ttbreakc(c, tp)) {
930 tp->t_rocount = 0;
931 catq(&tp->t_rawq, &tp->t_canq);
4147b3f6 932 ttwakeup(tp);
becb115c
SL
933 } else if (tp->t_rocount++ == 0)
934 tp->t_rocol = tp->t_col;
935 tp->t_state &= ~TS_QUOT;
936 if (c == '\\')
937 tp->t_state |= TS_QUOT;
938 if (tp->t_state&TS_ERASE) {
939 tp->t_state &= ~TS_ERASE;
940 (void) ttyoutput('/', tp);
941 }
942 i = tp->t_col;
4147b3f6 943 ttyecho(c, tp);
93d2ecff 944 if (c == tp->t_eofc && t_flags&ECHO) {
becb115c
SL
945 i = MIN(2, tp->t_col - i);
946 while (i > 0) {
947 (void) ttyoutput('\b', tp);
948 i--;
949 }
950 }
4147b3f6 951 }
becb115c
SL
952endcase:
953 /*
954 * If DEC-style start/stop is enabled don't restart
955 * output until seeing the start character.
956 */
93d2ecff 957 if (t_flags&DECCTQ && tp->t_state&TS_TTSTOP &&
becb115c 958 tp->t_startc != tp->t_stopc)
4147b3f6 959 return;
becb115c 960restartoutput:
4147b3f6 961 tp->t_state &= ~TS_TTSTOP;
becb115c 962 tp->t_flags &= ~FLUSHO;
becb115c 963startoutput:
4147b3f6
BJ
964 ttstart(tp);
965}
966
967/*
becb115c 968 * Put character on TTY output queue, adding delays,
4147b3f6 969 * expanding tabs, and handling the CR/NL bit.
becb115c
SL
970 * This is called both from the top half for output,
971 * and from interrupt level for echoing.
4147b3f6
BJ
972 * The arguments are the character and the tty structure.
973 * Returns < 0 if putc succeeds, otherwise returns char to resend
974 * Must be recursive.
975 */
976ttyoutput(c, tp)
977 register c;
978 register struct tty *tp;
979{
980 register char *colp;
981 register ctype;
982
becb115c
SL
983 if (tp->t_flags & (RAW|LITOUT)) {
984 if (tp->t_flags&FLUSHO)
4147b3f6
BJ
985 return (-1);
986 if (putc(c, &tp->t_outq))
4b72e2f9 987 return (c);
4147b3f6
BJ
988 tk_nout++;
989 return (-1);
990 }
becb115c 991
4147b3f6 992 /*
becb115c
SL
993 * Ignore EOT in normal mode to avoid
994 * hanging up certain terminals.
4147b3f6
BJ
995 */
996 c &= 0177;
becb115c 997 if (c == CEOT && (tp->t_flags&CBREAK) == 0)
4147b3f6
BJ
998 return (-1);
999 /*
1000 * Turn tabs to spaces as required
1001 */
becb115c 1002 if (c == '\t' && (tp->t_flags&TBDELAY) == XTABS) {
4147b3f6
BJ
1003 register int s;
1004
1005 c = 8 - (tp->t_col&7);
becb115c 1006 if ((tp->t_flags&FLUSHO) == 0) {
4f3a716e 1007 s = spltty(); /* don't interrupt tabs */
4147b3f6
BJ
1008 c -= b_to_q(" ", c, &tp->t_outq);
1009 tk_nout += c;
1010 splx(s);
1011 }
1012 tp->t_col += c;
1013 return (c ? -1 : '\t');
1014 }
1015 tk_nout++;
1016 /*
1017 * for upper-case-only terminals,
1018 * generate escapes.
1019 */
1020 if (tp->t_flags&LCASE) {
1021 colp = "({)}!|^~'`";
4b72e2f9
SL
1022 while (*colp++)
1023 if (c == *colp++) {
4147b3f6
BJ
1024 if (ttyoutput('\\', tp) >= 0)
1025 return (c);
1026 c = colp[-2];
1027 break;
1028 }
becb115c 1029 if ('A' <= c && c <= 'Z') {
4147b3f6
BJ
1030 if (ttyoutput('\\', tp) >= 0)
1031 return (c);
becb115c 1032 } else if ('a' <= c && c <= 'z')
4147b3f6
BJ
1033 c += 'A' - 'a';
1034 }
becb115c 1035
4147b3f6
BJ
1036 /*
1037 * turn <nl> to <cr><lf> if desired.
1038 */
becb115c 1039 if (c == '\n' && tp->t_flags&CRMOD)
4147b3f6
BJ
1040 if (ttyoutput('\r', tp) >= 0)
1041 return (c);
becb115c 1042 if (c == '~' && tp->t_flags&TILDE)
4147b3f6 1043 c = '`';
becb115c 1044 if ((tp->t_flags&FLUSHO) == 0 && putc(c, &tp->t_outq))
4147b3f6
BJ
1045 return (c);
1046 /*
1047 * Calculate delays.
1048 * The numbers here represent clock ticks
1049 * and are not necessarily optimal for all terminals.
1050 * The delays are indicated by characters above 0200.
1051 * In raw mode there are no delays and the
1052 * transmission path is 8 bits wide.
becb115c
SL
1053 *
1054 * SHOULD JUST ALLOW USER TO SPECIFY DELAYS
4147b3f6
BJ
1055 */
1056 colp = &tp->t_col;
1057 ctype = partab[c];
1058 c = 0;
1059 switch (ctype&077) {
1060
1061 case ORDINARY:
1062 (*colp)++;
1063
1064 case CONTROL:
1065 break;
1066
1067 case BACKSPACE:
1068 if (*colp)
1069 (*colp)--;
1070 break;
1071
3686c829
SL
1072 /*
1073 * This macro is close enough to the correct thing;
1074 * it should be replaced by real user settable delays
1075 * in any event...
1076 */
1077#define mstohz(ms) (((ms) * hz) >> 10)
4147b3f6
BJ
1078 case NEWLINE:
1079 ctype = (tp->t_flags >> 8) & 03;
4b72e2f9 1080 if (ctype == 1) { /* tty 37 */
8011f5df
MK
1081 if (*colp > 0) {
1082 c = (((unsigned)*colp) >> 4) + 3;
1083 if ((unsigned)c > 6)
1084 c = 6;
1085 }
becb115c 1086 } else if (ctype == 2) /* vt05 */
3686c829 1087 c = mstohz(100);
4147b3f6
BJ
1088 *colp = 0;
1089 break;
1090
1091 case TAB:
1092 ctype = (tp->t_flags >> 10) & 03;
4b72e2f9 1093 if (ctype == 1) { /* tty 37 */
4147b3f6 1094 c = 1 - (*colp | ~07);
4b72e2f9 1095 if (c < 5)
4147b3f6
BJ
1096 c = 0;
1097 }
1098 *colp |= 07;
1099 (*colp)++;
1100 break;
1101
1102 case VTAB:
becb115c 1103 if (tp->t_flags&VTDELAY) /* tty 37 */
4147b3f6
BJ
1104 c = 0177;
1105 break;
1106
1107 case RETURN:
1108 ctype = (tp->t_flags >> 12) & 03;
becb115c 1109 if (ctype == 1) /* tn 300 */
3686c829 1110 c = mstohz(83);
becb115c 1111 else if (ctype == 2) /* ti 700 */
3686c829 1112 c = mstohz(166);
becb115c 1113 else if (ctype == 3) { /* concept 100 */
4147b3f6 1114 int i;
becb115c 1115
4147b3f6 1116 if ((i = *colp) >= 0)
becb115c 1117 for (; i < 9; i++)
4147b3f6
BJ
1118 (void) putc(0177, &tp->t_outq);
1119 }
1120 *colp = 0;
1121 }
becb115c 1122 if (c && (tp->t_flags&FLUSHO) == 0)
4147b3f6
BJ
1123 (void) putc(c|0200, &tp->t_outq);
1124 return (-1);
1125}
3686c829 1126#undef mstohz
4147b3f6
BJ
1127
1128/*
1129 * Called from device's read routine after it has
1130 * calculated the tty-structure given as argument.
1131 */
d6d7360b 1132ttread(tp, uio)
4b72e2f9 1133 register struct tty *tp;
d6d7360b 1134 struct uio *uio;
4147b3f6
BJ
1135{
1136 register struct clist *qp;
becb115c 1137 register c, t_flags;
875a1e2c 1138 int s, first, error = 0;
4147b3f6 1139
4147b3f6 1140loop:
becb115c
SL
1141 /*
1142 * Take any pending input first.
1143 */
4f3a716e 1144 s = spltty();
becb115c 1145 if (tp->t_flags&PENDIN)
4147b3f6 1146 ttypend(tp);
875a1e2c 1147 splx(s);
becb115c 1148
58786a81
JB
1149 if ((tp->t_state&TS_CARR_ON)==0)
1150 return (EIO);
1151
becb115c
SL
1152 /*
1153 * Hang process if it's in the background.
1154 */
58786a81 1155 if (tp == u.u_ttyp && u.u_procp->p_pgrp != tp->t_pgrp) {
52c041cd
MK
1156 if ((u.u_procp->p_sigignore & sigmask(SIGTTIN)) ||
1157 (u.u_procp->p_sigmask & sigmask(SIGTTIN)) ||
4147b3f6 1158 u.u_procp->p_flag&SVFORK)
840510a3 1159 return (EIO);
4147b3f6
BJ
1160 gsignal(u.u_procp->p_pgrp, SIGTTIN);
1161 sleep((caddr_t)&lbolt, TTIPRI);
58786a81 1162 goto loop;
4147b3f6 1163 }
becb115c
SL
1164 t_flags = tp->t_flags;
1165
1166 /*
1167 * In raw mode take characters directly from the
1168 * raw queue w/o processing. Interlock against
1169 * device interrupts when interrogating rawq.
1170 */
1171 if (t_flags&RAW) {
4f3a716e 1172 s = spltty();
4147b3f6 1173 if (tp->t_rawq.c_cc <= 0) {
becb115c 1174 if ((tp->t_state&TS_CARR_ON) == 0 ||
4147b3f6 1175 (tp->t_state&TS_NBIO)) {
875a1e2c 1176 splx(s);
e0d1a4cb 1177 return (EWOULDBLOCK);
4147b3f6
BJ
1178 }
1179 sleep((caddr_t)&tp->t_rawq, TTIPRI);
875a1e2c 1180 splx(s);
4147b3f6
BJ
1181 goto loop;
1182 }
875a1e2c 1183 splx(s);
9ec65acb
KM
1184 while (!error && tp->t_rawq.c_cc && uio->uio_resid)
1185 error = ureadc(getc(&tp->t_rawq), uio);
875a1e2c 1186 goto checktandem;
becb115c
SL
1187 }
1188
1189 /*
1190 * In cbreak mode use the rawq, otherwise
1191 * take characters from the canonicalized q.
1192 */
1193 qp = t_flags&CBREAK ? &tp->t_rawq : &tp->t_canq;
1194
1195 /*
1196 * No input, sleep on rawq awaiting hardware
1197 * receipt and notification.
1198 */
4f3a716e 1199 s = spltty();
becb115c
SL
1200 if (qp->c_cc <= 0) {
1201 if ((tp->t_state&TS_CARR_ON) == 0 ||
1202 (tp->t_state&TS_NBIO)) {
875a1e2c 1203 splx(s);
becb115c 1204 return (EWOULDBLOCK);
4147b3f6 1205 }
becb115c 1206 sleep((caddr_t)&tp->t_rawq, TTIPRI);
875a1e2c 1207 splx(s);
becb115c
SL
1208 goto loop;
1209 }
875a1e2c 1210 splx(s);
becb115c
SL
1211
1212 /*
1213 * Input present, perform input mapping
1214 * and processing (we're not in raw mode).
1215 */
1216 first = 1;
1217 while ((c = getc(qp)) >= 0) {
1218 if (t_flags&CRMOD && c == '\r')
1219 c = '\n';
becb115c
SL
1220 /*
1221 * Check for delayed suspend character.
1222 */
1223 if (tp->t_line == NTTYDISC && c == tp->t_dsuspc) {
1224 gsignal(tp->t_pgrp, SIGTSTP);
1225 if (first) {
1226 sleep((caddr_t)&lbolt, TTIPRI);
1227 goto loop;
1228 }
1229 break;
4147b3f6 1230 }
becb115c
SL
1231 /*
1232 * Interpret EOF only in cooked mode.
1233 */
1234 if (c == tp->t_eofc && (t_flags&CBREAK) == 0)
1235 break;
1236 /*
1237 * Give user character.
1238 */
fb01874e 1239 error = ureadc(t_flags&PASS8 ? c : c & 0177, uio);
becb115c
SL
1240 if (error)
1241 break;
9ec65acb 1242 if (uio->uio_resid == 0)
becb115c
SL
1243 break;
1244 /*
1245 * In cooked mode check for a "break character"
1246 * marking the end of a "line of input".
1247 */
1248 if ((t_flags&CBREAK) == 0 && ttbreakc(c, tp))
1249 break;
1250 first = 0;
4147b3f6 1251 }
becb115c 1252
875a1e2c 1253checktandem:
becb115c
SL
1254 /*
1255 * Look to unblock output now that (presumably)
1256 * the input queue has gone down.
1257 */
875a1e2c 1258 if (tp->t_state&TS_TBLOCK && tp->t_rawq.c_cc < TTYHOG/5)
becb115c 1259 if (putc(tp->t_startc, &tp->t_outq) == 0) {
4147b3f6
BJ
1260 tp->t_state &= ~TS_TBLOCK;
1261 ttstart(tp);
1262 }
840510a3 1263 return (error);
4147b3f6
BJ
1264}
1265
605d7712
MK
1266/*
1267 * Check the output queue on tp for space for a kernel message
1268 * (from uprintf/tprintf). Allow some space over the normal
1269 * hiwater mark so we don't lose messages due to normal flow
1270 * control, but don't let the tty run amok.
ca9b16e5
MK
1271 * Sleeps here are not interruptible, but we return prematurely
1272 * if new signals come in.
605d7712
MK
1273 */
1274ttycheckoutq(tp, wait)
1275 register struct tty *tp;
1276 int wait;
1277{
ca9b16e5 1278 int hiwat, s, oldsig;
605d7712
MK
1279
1280 hiwat = TTHIWAT(tp);
1281 s = spltty();
ca9b16e5 1282 oldsig = u.u_procp->p_sig;
605d7712 1283 if (tp->t_outq.c_cc > hiwat + 200)
fb1db32c
MK
1284 while (tp->t_outq.c_cc > hiwat) {
1285 ttstart(tp);
ca9b16e5 1286 if (wait == 0 || u.u_procp->p_sig != oldsig) {
fb1db32c
MK
1287 splx(s);
1288 return (0);
1289 }
ca9b16e5 1290 timeout(wakeup, (caddr_t)&tp->t_outq, hz);
fb1db32c 1291 tp->t_state |= TS_ASLEEP;
ca9b16e5 1292 sleep((caddr_t)&tp->t_outq, PZERO - 1);
605d7712 1293 }
605d7712
MK
1294 splx(s);
1295 return (1);
1296}
1297
4147b3f6
BJ
1298/*
1299 * Called from the device's write routine after it has
1300 * calculated the tty-structure given as argument.
1301 */
913ea2d1 1302ttwrite(tp, uio)
4b72e2f9 1303 register struct tty *tp;
becb115c 1304 register struct uio *uio;
4147b3f6 1305{
4147b3f6 1306 register char *cp;
becb115c
SL
1307 register int cc, ce, c;
1308 int i, hiwat, cnt, error, s;
4147b3f6 1309 char obuf[OBUFSIZ];
4147b3f6 1310
becb115c
SL
1311 hiwat = TTHIWAT(tp);
1312 cnt = uio->uio_resid;
1313 error = 0;
4147b3f6 1314loop:
93d2ecff
JB
1315 if ((tp->t_state&TS_CARR_ON) == 0)
1316 return (EIO);
becb115c
SL
1317 /*
1318 * Hang the process if it's in the background.
1319 */
93d2ecff 1320 if (u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp &&
becb115c 1321 (tp->t_flags&TOSTOP) && (u.u_procp->p_flag&SVFORK)==0 &&
52c041cd
MK
1322 !(u.u_procp->p_sigignore & sigmask(SIGTTOU)) &&
1323 !(u.u_procp->p_sigmask & sigmask(SIGTTOU))) {
4147b3f6
BJ
1324 gsignal(u.u_procp->p_pgrp, SIGTTOU);
1325 sleep((caddr_t)&lbolt, TTIPRI);
93d2ecff 1326 goto loop;
4147b3f6 1327 }
becb115c
SL
1328
1329 /*
1330 * Process the user's data in at most OBUFSIZ
1331 * chunks. Perform lower case simulation and
1332 * similar hacks. Keep track of high water
1333 * mark, sleep on overflow awaiting device aid
1334 * in acquiring new space.
1335 */
913ea2d1 1336 while (uio->uio_resid > 0) {
b482b2c8
MK
1337 if (tp->t_outq.c_cc > hiwat) {
1338 cc = 0;
1339 goto ovhiwat;
1340 }
becb115c
SL
1341 /*
1342 * Grab a hunk of data from the user.
1343 */
913ea2d1
BJ
1344 cc = uio->uio_iov->iov_len;
1345 if (cc == 0) {
1346 uio->uio_iovcnt--;
1347 uio->uio_iov++;
93d2ecff 1348 if (uio->uio_iovcnt <= 0)
913ea2d1
BJ
1349 panic("ttwrite");
1350 continue;
1351 }
1352 if (cc > OBUFSIZ)
1353 cc = OBUFSIZ;
4147b3f6 1354 cp = obuf;
88a7a62a 1355 error = uiomove(cp, cc, UIO_WRITE, uio);
840510a3 1356 if (error)
4147b3f6 1357 break;
becb115c 1358 if (tp->t_flags&FLUSHO)
4147b3f6 1359 continue;
becb115c
SL
1360 /*
1361 * If we're mapping lower case or kludging tildes,
1362 * then we've got to look at each character, so
1363 * just feed the stuff to ttyoutput...
1364 */
1365 if (tp->t_flags & (LCASE|TILDE)) {
1366 while (cc > 0) {
4147b3f6
BJ
1367 c = *cp++;
1368 tp->t_rocount = 0;
4b72e2f9 1369 while ((c = ttyoutput(c, tp)) >= 0) {
4147b3f6
BJ
1370 /* out of clists, wait a bit */
1371 ttstart(tp);
1372 sleep((caddr_t)&lbolt, TTOPRI);
1373 tp->t_rocount = 0;
93d2ecff
JB
1374 if (cc != 0) {
1375 uio->uio_iov->iov_base -= cc;
1376 uio->uio_iov->iov_len += cc;
1377 uio->uio_resid += cc;
1378 uio->uio_offset -= cc;
1379 }
1380 goto loop;
4147b3f6
BJ
1381 }
1382 --cc;
1383 if (tp->t_outq.c_cc > hiwat)
1384 goto ovhiwat;
1385 }
1386 continue;
1387 }
becb115c
SL
1388 /*
1389 * If nothing fancy need be done, grab those characters we
1390 * can handle without any of ttyoutput's processing and
1391 * just transfer them to the output q. For those chars
1392 * which require special processing (as indicated by the
1393 * bits in partab), call ttyoutput. After processing
1394 * a hunk of data, look for FLUSHO so ^O's will take effect
1395 * immediately.
1396 */
1397 while (cc > 0) {
1398 if (tp->t_flags & (RAW|LITOUT))
4147b3f6
BJ
1399 ce = cc;
1400 else {
88a7a62a
SL
1401 ce = cc - scanc((unsigned)cc, (caddr_t)cp,
1402 (caddr_t)partab, 077);
becb115c
SL
1403 /*
1404 * If ce is zero, then we're processing
1405 * a special character through ttyoutput.
1406 */
1407 if (ce == 0) {
4147b3f6
BJ
1408 tp->t_rocount = 0;
1409 if (ttyoutput(*cp, tp) >= 0) {
93d2ecff
JB
1410 /* no c-lists, wait a bit */
1411 ttstart(tp);
1412 sleep((caddr_t)&lbolt, TTOPRI);
1413 if (cc != 0) {
1414 uio->uio_iov->iov_base -= cc;
1415 uio->uio_iov->iov_len += cc;
1416 uio->uio_resid += cc;
1417 uio->uio_offset -= cc;
1418 }
1419 goto loop;
4147b3f6 1420 }
becb115c
SL
1421 cp++, cc--;
1422 if (tp->t_flags&FLUSHO ||
1423 tp->t_outq.c_cc > hiwat)
4147b3f6 1424 goto ovhiwat;
becb115c 1425 continue;
4147b3f6
BJ
1426 }
1427 }
becb115c
SL
1428 /*
1429 * A bunch of normal characters have been found,
1430 * transfer them en masse to the output queue and
1431 * continue processing at the top of the loop.
1432 * If there are any further characters in this
1433 * <= OBUFSIZ chunk, the first should be a character
1434 * requiring special handling by ttyoutput.
1435 */
4147b3f6 1436 tp->t_rocount = 0;
becb115c
SL
1437 i = b_to_q(cp, ce, &tp->t_outq);
1438 ce -= i;
1439 tp->t_col += ce;
1440 cp += ce, cc -= ce, tk_nout += ce;
1441 if (i > 0) {
1442 /* out of c-lists, wait a bit */
4147b3f6
BJ
1443 ttstart(tp);
1444 sleep((caddr_t)&lbolt, TTOPRI);
93d2ecff
JB
1445 uio->uio_iov->iov_base -= cc;
1446 uio->uio_iov->iov_len += cc;
1447 uio->uio_resid += cc;
1448 uio->uio_offset -= cc;
1449 goto loop;
4147b3f6 1450 }
becb115c 1451 if (tp->t_flags&FLUSHO || tp->t_outq.c_cc > hiwat)
4147b3f6
BJ
1452 goto ovhiwat;
1453 }
1454 }
1455 ttstart(tp);
840510a3 1456 return (error);
4147b3f6
BJ
1457
1458ovhiwat:
becb115c
SL
1459 if (cc != 0) {
1460 uio->uio_iov->iov_base -= cc;
1461 uio->uio_iov->iov_len += cc;
1462 uio->uio_resid += cc;
1463 uio->uio_offset -= cc;
1464 }
b482b2c8
MK
1465 ttstart(tp);
1466 s = spltty();
becb115c 1467 /*
b482b2c8
MK
1468 * This can only occur if FLUSHO is set in t_flags,
1469 * or if ttstart/oproc is synchronous (or very fast).
becb115c 1470 */
4147b3f6 1471 if (tp->t_outq.c_cc <= hiwat) {
becb115c 1472 splx(s);
4147b3f6
BJ
1473 goto loop;
1474 }
becb115c 1475 if (tp->t_state&TS_NBIO) {
4f3a716e 1476 splx(s);
913ea2d1 1477 if (uio->uio_resid == cnt)
840510a3
BJ
1478 return (EWOULDBLOCK);
1479 return (0);
4147b3f6
BJ
1480 }
1481 tp->t_state |= TS_ASLEEP;
1482 sleep((caddr_t)&tp->t_outq, TTOPRI);
becb115c 1483 splx(s);
4147b3f6
BJ
1484 goto loop;
1485}
1486
1487/*
1488 * Rubout one character from the rawq of tp
1489 * as cleanly as possible.
1490 */
1491ttyrub(c, tp)
4b72e2f9
SL
1492 register c;
1493 register struct tty *tp;
4147b3f6
BJ
1494{
1495 register char *cp;
1496 register int savecol;
1497 int s;
1498 char *nextc();
1499
becb115c 1500 if ((tp->t_flags&ECHO) == 0)
4147b3f6 1501 return;
becb115c 1502 tp->t_flags &= ~FLUSHO;
4147b3f6 1503 c &= 0377;
becb115c 1504 if (tp->t_flags&CRTBS) {
4147b3f6
BJ
1505 if (tp->t_rocount == 0) {
1506 /*
1507 * Screwed by ttwrite; retype
1508 */
1509 ttyretype(tp);
1510 return;
1511 }
becb115c 1512 if (c == ('\t'|0200) || c == ('\n'|0200))
4147b3f6 1513 ttyrubo(tp, 2);
becb115c 1514 else switch (partab[c&=0177]&0177) {
4147b3f6
BJ
1515
1516 case ORDINARY:
1517 if (tp->t_flags&LCASE && c >= 'A' && c <= 'Z')
1518 ttyrubo(tp, 2);
1519 else
1520 ttyrubo(tp, 1);
1521 break;
1522
1523 case VTAB:
1524 case BACKSPACE:
1525 case CONTROL:
1526 case RETURN:
becb115c 1527 if (tp->t_flags&CTLECH)
4147b3f6
BJ
1528 ttyrubo(tp, 2);
1529 break;
1530
1531 case TAB:
1532 if (tp->t_rocount < tp->t_rawq.c_cc) {
1533 ttyretype(tp);
1534 return;
1535 }
4f3a716e 1536 s = spltty();
4147b3f6 1537 savecol = tp->t_col;
becb115c
SL
1538 tp->t_state |= TS_CNTTB;
1539 tp->t_flags |= FLUSHO;
4147b3f6 1540 tp->t_col = tp->t_rocol;
becb115c
SL
1541 cp = tp->t_rawq.c_cf;
1542 for (; cp; cp = nextc(&tp->t_rawq, cp))
4147b3f6 1543 ttyecho(*cp, tp);
becb115c
SL
1544 tp->t_flags &= ~FLUSHO;
1545 tp->t_state &= ~TS_CNTTB;
4147b3f6
BJ
1546 splx(s);
1547 /*
1548 * savecol will now be length of the tab
1549 */
1550 savecol -= tp->t_col;
1551 tp->t_col += savecol;
1552 if (savecol > 8)
1553 savecol = 8; /* overflow screw */
1554 while (--savecol >= 0)
1555 (void) ttyoutput('\b', tp);
1556 break;
1557
1558 default:
1559 panic("ttyrub");
1560 }
becb115c
SL
1561 } else if (tp->t_flags&PRTERA) {
1562 if ((tp->t_state&TS_ERASE) == 0) {
4147b3f6 1563 (void) ttyoutput('\\', tp);
becb115c 1564 tp->t_state |= TS_ERASE;
4147b3f6
BJ
1565 }
1566 ttyecho(c, tp);
1567 } else
1568 ttyecho(tp->t_erase, tp);
1569 tp->t_rocount--;
1570}
1571
1572/*
1573 * Crt back over cnt chars perhaps
1574 * erasing them.
1575 */
1576ttyrubo(tp, cnt)
4b72e2f9
SL
1577 register struct tty *tp;
1578 int cnt;
4147b3f6 1579{
becb115c 1580 register char *rubostring = tp->t_flags&CRTERA ? "\b \b" : "\b";
4147b3f6
BJ
1581
1582 while (--cnt >= 0)
becb115c 1583 ttyout(rubostring, tp);
4147b3f6
BJ
1584}
1585
1586/*
1587 * Reprint the rawq line.
1588 * We assume c_cc has already been checked.
1589 */
1590ttyretype(tp)
4b72e2f9 1591 register struct tty *tp;
4147b3f6
BJ
1592{
1593 register char *cp;
1594 char *nextc();
1595 int s;
1596
becb115c
SL
1597 if (tp->t_rprntc != 0377)
1598 ttyecho(tp->t_rprntc, tp);
4147b3f6 1599 (void) ttyoutput('\n', tp);
4f3a716e 1600 s = spltty();
4147b3f6
BJ
1601 for (cp = tp->t_canq.c_cf; cp; cp = nextc(&tp->t_canq, cp))
1602 ttyecho(*cp, tp);
1603 for (cp = tp->t_rawq.c_cf; cp; cp = nextc(&tp->t_rawq, cp))
1604 ttyecho(*cp, tp);
becb115c 1605 tp->t_state &= ~TS_ERASE;
4147b3f6
BJ
1606 splx(s);
1607 tp->t_rocount = tp->t_rawq.c_cc;
1608 tp->t_rocol = 0;
1609}
1610
1611/*
1612 * Echo a typed character to the terminal
1613 */
1614ttyecho(c, tp)
4b72e2f9
SL
1615 register c;
1616 register struct tty *tp;
4147b3f6
BJ
1617{
1618
becb115c
SL
1619 if ((tp->t_state&TS_CNTTB) == 0)
1620 tp->t_flags &= ~FLUSHO;
4147b3f6
BJ
1621 if ((tp->t_flags&ECHO) == 0)
1622 return;
1623 c &= 0377;
1624 if (tp->t_flags&RAW) {
1625 (void) ttyoutput(c, tp);
1626 return;
1627 }
1628 if (c == '\r' && tp->t_flags&CRMOD)
1629 c = '\n';
becb115c 1630 if (tp->t_flags&CTLECH) {
4147b3f6
BJ
1631 if ((c&0177) <= 037 && c!='\t' && c!='\n' || (c&0177)==0177) {
1632 (void) ttyoutput('^', tp);
1633 c &= 0177;
1634 if (c == 0177)
1635 c = '?';
1636 else if (tp->t_flags&LCASE)
1637 c += 'a' - 1;
1638 else
1639 c += 'A' - 1;
1640 }
1641 }
becb115c 1642 (void) ttyoutput(c&0177, tp);
4147b3f6
BJ
1643}
1644
1645/*
1646 * Is c a break char for tp?
1647 */
1648ttbreakc(c, tp)
4b72e2f9
SL
1649 register c;
1650 register struct tty *tp;
4147b3f6 1651{
becb115c 1652 return (c == '\n' || c == tp->t_eofc || c == tp->t_brkc ||
4147b3f6
BJ
1653 c == '\r' && (tp->t_flags&CRMOD));
1654}
1655
1656/*
1657 * send string cp to tp
1658 */
1659ttyout(cp, tp)
4b72e2f9
SL
1660 register char *cp;
1661 register struct tty *tp;
4147b3f6
BJ
1662{
1663 register char c;
1664
1665 while (c = *cp++)
1666 (void) ttyoutput(c, tp);
1667}
1668
1669ttwakeup(tp)
1670 struct tty *tp;
1671{
1672
1673 if (tp->t_rsel) {
1674 selwakeup(tp->t_rsel, tp->t_state&TS_RCOLL);
1675 tp->t_state &= ~TS_RCOLL;
1676 tp->t_rsel = 0;
1677 }
88a7a62a
SL
1678 if (tp->t_state & TS_ASYNC)
1679 gsignal(tp->t_pgrp, SIGIO);
4147b3f6
BJ
1680 wakeup((caddr_t)&tp->t_rawq);
1681}