add null bmap routine; add printing routine; now flush dev vnode directly
[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 *
232c0273 6 * @(#)tty.c 7.19 (Berkeley) %G%
da7c5cc6 7 */
961945a8 8
94368568
JB
9#include "param.h"
10#include "systm.h"
94368568
JB
11#include "user.h"
12#include "ioctl.h"
2c6a4e11 13#define TTYDEFCHARS
52004850 14#include "tty.h"
2c6a4e11 15#undef TTYDEFCHARS
e39f9ea6
MT
16#define TTYDEFCHARS
17#include "ttydefaults.h"
18#undef TTYDEFCHARS
19#include "termios.h"
94368568 20#include "proc.h"
94368568
JB
21#include "file.h"
22#include "conf.h"
fb1db32c 23#include "dkstat.h"
94368568
JB
24#include "uio.h"
25#include "kernel.h"
c4ec2128 26#include "vnode.h"
2c6a4e11 27#include "syslog.h"
d301d150
KM
28
29#include "machine/reg.h"
e39f9ea6 30#include "syslog.h"
89dc6dfb 31
8bba2b8f
RE
32/*
33 * Table giving parity for characters and indicating
e39f9ea6
MT
34 * character classes to tty driver. The 8th bit
35 * indicates parity, the 7th bit indicates the character
36 * is an alphameric or underscore (for ALTWERASE), and the
37 * low 6 bits indicate delay type. If the low 6 bits are 0
38 * then the character needs no special processing on output.
8bba2b8f
RE
39 */
40
41char partab[] = {
e39f9ea6
MT
42 0001,0201,0201,0001,0201,0001,0001,0201, /* nul - bel */
43 0202,0004,0003,0201,0005,0206,0201,0001, /* bs - si */
44 0201,0001,0001,0201,0001,0201,0201,0001, /* dle - etb */
45 0001,0201,0201,0001,0201,0001,0001,0201, /* can - us */
46 0200,0000,0000,0200,0000,0200,0200,0000, /* sp - ' */
47 0000,0200,0200,0000,0200,0000,0000,0200, /* ( - / */
48 0100,0300,0300,0100,0300,0100,0100,0300, /* 0 - 7 */
49 0300,0100,0000,0200,0000,0200,0200,0000, /* 8 - ? */
50 0200,0100,0100,0300,0100,0300,0300,0100, /* @ - G */
51 0100,0300,0300,0100,0300,0100,0100,0300, /* H - O */
52 0100,0300,0300,0100,0300,0100,0100,0300, /* P - W */
53 0300,0100,0100,0200,0000,0200,0200,0300, /* X - _ */
54 0000,0300,0300,0100,0300,0100,0100,0300, /* ` - g */
55 0300,0100,0100,0300,0100,0300,0300,0100, /* h - o */
56 0300,0100,0100,0300,0100,0300,0300,0100, /* p - w */
57 0100,0300,0300,0000,0200,0000,0000,0201, /* x - del */
8bba2b8f 58 /*
e39f9ea6 59 * meta chars
8bba2b8f 60 */
e39f9ea6
MT
61 0001,0201,0201,0001,0201,0001,0001,0201, /* nul - bel */
62 0202,0004,0003,0201,0005,0206,0201,0001, /* bs - si */
63 0201,0001,0001,0201,0001,0201,0201,0001, /* dle - etb */
64 0001,0201,0201,0001,0201,0001,0001,0201, /* can - us */
65 0200,0000,0000,0200,0000,0200,0200,0000, /* sp - ' */
66 0000,0200,0200,0000,0200,0000,0000,0200, /* ( - / */
67 0100,0300,0300,0100,0300,0100,0100,0300, /* 0 - 7 */
68 0300,0100,0000,0200,0000,0200,0200,0000, /* 8 - ? */
69 0200,0100,0100,0300,0100,0300,0300,0100, /* @ - G */
70 0100,0300,0300,0100,0300,0100,0100,0300, /* H - O */
71 0100,0300,0300,0100,0300,0100,0100,0300, /* P - W */
72 0300,0100,0100,0200,0000,0200,0200,0300, /* X - _ */
73 0000,0300,0300,0100,0300,0100,0100,0300, /* ` - g */
74 0300,0100,0100,0300,0100,0300,0300,0100, /* h - o */
75 0300,0100,0100,0300,0100,0300,0300,0100, /* p - w */
76 0100,0300,0300,0000,0200,0000,0000,0201, /* x - del */
89dc6dfb
BJ
77};
78
adf4bc89 79extern struct tty *constty; /* temporary virtual console */
2c6a4e11
MT
80extern char partab[], maptab[];
81
e39f9ea6
MT
82/*
83 * Is 'c' a line delimiter ("break" character)?
84 */
85#define ttbreakc(c) (c == '\n' || CCEQ(cc[VEOF], c) || \
86 CCEQ(cc[VEOL], c) || CCEQ(cc[VEOL2], c))
87
2c6a4e11
MT
88/*
89 * Debugging aids
90 */
91#define dprintf if (tp->t_trace & TTRACE_IO)printf
92
93/*
94 * Is 'c' a line delimiter ("break" character)?
95 */
96#define ttbreakc(c) (c == '\n' || CCEQ(cc[VEOF], c) || \
97 CCEQ(cc[VEOL], c) || CCEQ(cc[VEOL2], c))
adf4bc89 98
89dc6dfb 99ttychars(tp)
becb115c 100 struct tty *tp;
89dc6dfb 101{
2c6a4e11 102 bcopy(ttydefchars, tp->t_cc, sizeof(ttydefchars));
89dc6dfb
BJ
103}
104
105/*
2c6a4e11 106 *
50e2732b 107 * Wait for output to drain, then flush input waiting.
89dc6dfb 108 */
88a7a62a 109ttywflush(tp)
66ad69d6 110 struct tty *tp;
89dc6dfb
BJ
111{
112
88a7a62a
SL
113 ttywait(tp);
114 ttyflush(tp, FREAD);
115}
116
e39f9ea6
MT
117/*
118 * Wait for output to drain.
119 */
2c6a4e11
MT
120/*
121 * Wait for output to drain.
122 */
88a7a62a
SL
123ttywait(tp)
124 register struct tty *tp;
125{
66ad69d6 126 int s = spltty();
88a7a62a 127
5de287d9 128 while ((tp->t_outq.c_cc || tp->t_state&TS_BUSY) &&
66ad69d6
MT
129 (tp->t_state&TS_CARR_ON || tp->t_cflag&CLOCAL) &&
130 tp->t_oproc) {
50e2732b 131 (*tp->t_oproc)(tp);
941944c9 132 tp->t_state |= TS_ASLEEP;
50e2732b
BJ
133 sleep((caddr_t)&tp->t_outq, TTOPRI);
134 }
875a1e2c 135 splx(s);
89dc6dfb
BJ
136}
137
138/*
becb115c 139 * Flush all TTY queues
89dc6dfb 140 */
88a7a62a 141ttyflush(tp, rw)
4b72e2f9 142 register struct tty *tp;
89dc6dfb 143{
50e2732b
BJ
144 register s;
145
4f3a716e 146 s = spltty();
50e2732b
BJ
147 if (rw & FREAD) {
148 while (getc(&tp->t_canq) >= 0)
149 ;
66ad69d6 150 ttwakeup(tp);
50e2732b
BJ
151 }
152 if (rw & FWRITE) {
66ad69d6 153 wakeup((caddr_t)&tp->t_outq); /* XXX? what about selwakeup? */
941944c9 154 tp->t_state &= ~TS_TTSTOP;
39697bd8 155 (*cdevsw[major(tp->t_dev)].d_stop)(tp, rw);
50e2732b
BJ
156 while (getc(&tp->t_outq) >= 0)
157 ;
158 }
159 if (rw & FREAD) {
160 while (getc(&tp->t_rawq) >= 0)
161 ;
becb115c 162 tp->t_rocount = 0;
50e2732b 163 tp->t_rocol = 0;
becb115c 164 tp->t_state &= ~TS_LOCAL;
50e2732b
BJ
165 }
166 splx(s);
89dc6dfb
BJ
167}
168
50e2732b
BJ
169/*
170 * Send stop character on input overflow.
171 */
172ttyblock(tp)
4b72e2f9 173 register struct tty *tp;
89dc6dfb 174{
50e2732b 175 register x;
becb115c 176
50e2732b
BJ
177 x = tp->t_rawq.c_cc + tp->t_canq.c_cc;
178 if (tp->t_rawq.c_cc > TTYHOG) {
88a7a62a 179 ttyflush(tp, FREAD|FWRITE);
941944c9 180 tp->t_state &= ~TS_TBLOCK;
50e2732b 181 }
600d5712
MK
182 /*
183 * Block further input iff:
184 * Current input > threshold AND input is available to user program
185 */
28b2d854 186 if (x >= TTYHOG/2 &&
2c6a4e11
MT
187 (!(tp->t_lflag&ICANON)) || (tp->t_canq.c_cc > 0) &&
188 tp->t_cc[VSTOP] != POSIX_V_DISABLE) {
189 if (putc(tp->t_cc[VSTOP], &tp->t_outq)==0) {
600d5712
MK
190 tp->t_state |= TS_TBLOCK;
191 ttstart(tp);
192 }
50e2732b 193 }
89dc6dfb
BJ
194}
195
101ba270 196/*
50e2732b
BJ
197 * Restart typewriter output following a delay
198 * timeout.
199 * The name of the routine is passed to the timeout
200 * subroutine and it is called during a clock interrupt.
101ba270 201 */
50e2732b 202ttrstrt(tp)
66ad69d6 203 struct tty *tp;
101ba270
BJ
204{
205
becb115c
SL
206 if (tp == 0)
207 panic("ttrstrt");
941944c9 208 tp->t_state &= ~TS_TIMEOUT;
50e2732b 209 ttstart(tp);
101ba270
BJ
210}
211
89dc6dfb 212/*
50e2732b
BJ
213 * Start output on the typewriter. It is used from the top half
214 * after some characters have been put on the output queue,
215 * from the interrupt routine to transmit the next
216 * character, and after a timeout has finished.
89dc6dfb 217 */
50e2732b 218ttstart(tp)
66ad69d6 219 struct tty *tp;
89dc6dfb 220{
8062c8a7 221
b482b2c8 222 if (tp->t_oproc) /* kludge for pty */
50e2732b 223 (*tp->t_oproc)(tp);
89dc6dfb
BJ
224}
225
226/*
50e2732b 227 * Common code for tty ioctls.
89dc6dfb 228 */
49c84d3f 229/*ARGSUSED*/
4b72e2f9
SL
230ttioctl(tp, com, data, flag)
231 register struct tty *tp;
232 caddr_t data;
89dc6dfb 233{
89dc6dfb 234 extern int nldisp;
2c6a4e11 235 int soft;
849cbd39 236 int s, error;
89dc6dfb 237
50e2732b
BJ
238 /*
239 * If the ioctl involves modification,
4f3a716e 240 * hang if in the background.
50e2732b 241 */
4b72e2f9 242 switch (com) {
50e2732b 243
2c6a4e11 244 case TIOCSETD:
50e2732b 245 case TIOCFLUSH:
8203fe05 246 case TIOCSTI:
f9eea644 247 case TIOCSWINSZ:
2c6a4e11
MT
248 case TIOCSETA:
249 case TIOCSETAW:
250 case TIOCSETAF:
52004850 251/**** these get removed ****
2c6a4e11
MT
252 case TIOCSETAS:
253 case TIOCSETAWS:
254 case TIOCSETAFS:
52004850 255/***************************/
232c0273 256 while (isbackground(u.u_procp, tp) &&
e39f9ea6 257 u.u_procp->p_pgrp->pg_jobc &&
50e2732b 258 (u.u_procp->p_flag&SVFORK) == 0 &&
52c041cd
MK
259 !(u.u_procp->p_sigignore & sigmask(SIGTTOU)) &&
260 !(u.u_procp->p_sigmask & sigmask(SIGTTOU))) {
e39f9ea6 261 pgsignal(u.u_procp->p_pgrp, SIGTTOU);
50e2732b
BJ
262 sleep((caddr_t)&lbolt, TTOPRI);
263 }
264 break;
265 }
266
becb115c
SL
267 /*
268 * Process the ioctl.
269 */
4b72e2f9 270 switch (com) {
89dc6dfb 271
fc6972ae 272 /* get discipline number */
89dc6dfb 273 case TIOCGETD:
4b72e2f9 274 *(int *)data = tp->t_line;
89dc6dfb
BJ
275 break;
276
fc6972ae 277 /* set line discipline */
4b72e2f9
SL
278 case TIOCSETD: {
279 register int t = *(int *)data;
2c6a4e11 280 dev_t dev = tp->t_dev;
e39f9ea6 281 dev_t dev = tp->t_dev;
becb115c 282 int error = 0;
4b72e2f9 283
e39f9ea6 284 if ((unsigned)t >= nldisp)
4a003df3 285 return (ENXIO);
2eaeef4d
MK
286 if (t != tp->t_line) {
287 s = spltty();
288 (*linesw[tp->t_line].l_close)(tp);
289 error = (*linesw[t].l_open)(dev, tp);
290 if (error) {
2c6a4e11 291 (void)(*linesw[tp->t_line].l_open)(dev, tp);
2eaeef4d
MK
292 splx(s);
293 return (error);
294 }
295 tp->t_line = t;
4a003df3 296 splx(s);
4a003df3 297 }
2c6a4e11
MT
298 if (tp->t_trace & TTRACE_STATE)
299 ttytrace(com, tp);
89dc6dfb 300 break;
4b72e2f9 301 }
89dc6dfb 302
fc6972ae 303 /* prevent more opens on channel */
152c2598
BJ
304 case TIOCEXCL:
305 tp->t_state |= TS_XCLUDE;
306 break;
307
308 case TIOCNXCL:
309 tp->t_state &= ~TS_XCLUDE;
310 break;
311
89dc6dfb 312 case TIOCHPCL:
2c6a4e11 313 tp->t_cflag |= HUPCL;
89dc6dfb
BJ
314 break;
315
7d973a4d 316 case TIOCFLUSH: {
4b72e2f9
SL
317 register int flags = *(int *)data;
318
319 if (flags == 0)
7d973a4d 320 flags = FREAD|FWRITE;
4b72e2f9
SL
321 else
322 flags &= FREAD|FWRITE;
88a7a62a 323 ttyflush(tp, flags);
89dc6dfb 324 break;
4568c08e 325 }
89dc6dfb 326
66ad69d6
MT
327 case FIOASYNC:
328 if (*(int *)data)
329 tp->t_state |= TS_ASYNC;
330 else
331 tp->t_state &= ~TS_ASYNC;
332 break;
333
334 case FIONBIO:
335 break; /* XXX remove */
336
fc6972ae 337 /* return number of characters immediately available */
4b72e2f9
SL
338 case FIONREAD:
339 *(off_t *)data = ttnread(tp);
8062c8a7 340 break;
8062c8a7 341
b968e450
SL
342 case TIOCOUTQ:
343 *(int *)data = tp->t_outq.c_cc;
344 break;
345
a8d3bf7f 346 case TIOCSTOP:
4f3a716e 347 s = spltty();
becb115c 348 if ((tp->t_state&TS_TTSTOP) == 0) {
bfcf09ee
BJ
349 tp->t_state |= TS_TTSTOP;
350 (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
351 }
4b72e2f9 352 splx(s);
bfcf09ee
BJ
353 break;
354
a8d3bf7f 355 case TIOCSTART:
4f3a716e 356 s = spltty();
2c6a4e11 357 if ((tp->t_state&TS_TTSTOP) || (tp->t_lflag&FLUSHO)) {
bfcf09ee 358 tp->t_state &= ~TS_TTSTOP;
2c6a4e11 359 tp->t_lflag &= ~FLUSHO;
bfcf09ee
BJ
360 ttstart(tp);
361 }
4b72e2f9 362 splx(s);
bfcf09ee
BJ
363 break;
364
8203fe05
SL
365 /*
366 * Simulate typing of a character at the terminal.
367 */
368 case TIOCSTI:
477d62ec
KM
369 if (u.u_uid && (flag & FREAD) == 0)
370 return (EPERM);
232c0273 371 if (u.u_uid && !isctty(u.u_procp, tp))
8203fe05 372 return (EACCES);
becb115c 373 (*linesw[tp->t_line].l_rint)(*(char *)data, tp);
8203fe05
SL
374 break;
375
2c6a4e11
MT
376 case TIOCGETA: {
377 struct termios *t = (struct termios *)data;
378 bcopy(&tp->t_termio, t, sizeof(struct termios));
379 if (tp->t_trace & TTRACE_STATE)
380 ttytrace(com, tp);
381 break;
382 }
383
2c6a4e11
MT
384 if (com == TIOCSETAF || com == TIOCSETAFS)
385 ttywflush(tp);
386 else {
387 if (com == TIOCSETAW || com == TIOCSETAWS)
388 ttywait(tp);
389 if ((t->c_lflag&ICANON) != (tp->t_lflag&ICANON))
390 if (t->c_lflag&ICANON) {
391 tp->t_lflag |= PENDIN;
392 ttwakeup(tp);
393 }
394 else {
395 struct clist tq;
396
397 catq(&tp->t_rawq, &tp->t_canq);
398 tq = tp->t_rawq;
399 tp->t_rawq = tp->t_canq;
400 tp->t_canq = tq;
401 }
88a7a62a 402 }
2c6a4e11
MT
403 tp->t_iflag = t->c_iflag;
404 tp->t_oflag = t->c_oflag;
405 tp->t_lflag = t->c_lflag;
406 bcopy(t->c_cc, tp->t_cc, sizeof(t->c_cc));
407 if (!soft) {
408 tp->t_cflag = t->c_cflag;
409 tp->t_ispeed = t->c_ispeed;
410 tp->t_ospeed = t->c_ospeed;
88a7a62a 411 }
e39f9ea6
MT
412 tp->t_iflag = t->c_iflag;
413 tp->t_oflag = t->c_oflag;
414 tp->t_lflag = t->c_lflag;
415 bcopy(t->c_cc, tp->t_cc, sizeof(t->c_cc));
88a7a62a 416 splx(s);
2c6a4e11
MT
417 if (tp->t_trace & TTRACE_STATE)
418 ttytrace(com, tp);
88a7a62a
SL
419 break;
420 }
421
4f3a716e 422 /*
e39f9ea6 423 * Set terminal process group.
4f3a716e 424 */
245aeefa 425 case TIOCSPGRP: {
e39f9ea6
MT
426 register struct proc *p = u.u_procp;
427 register struct pgrp *pgrp = pgfind(*(int *)data);
428
232c0273
MT
429 if (!isctty(p, tp))
430 return (ENOTTY);
431 else if (pgrp->pg_session != p->p_session)
432 return (EPERM);
433 tp->t_pgrp = pgrp;
88a7a62a 434 break;
245aeefa 435 }
88a7a62a
SL
436
437 case TIOCGPGRP:
232c0273
MT
438 if (!isctty(u.u_procp, tp))
439 return (ENOTTY);
440 *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0;
88a7a62a
SL
441 break;
442
f9eea644 443 case TIOCSWINSZ:
245aeefa
JB
444 if (bcmp((caddr_t)&tp->t_winsize, data,
445 sizeof (struct winsize))) {
f9eea644 446 tp->t_winsize = *(struct winsize *)data;
232c0273 447 pgsignal(tp->t_pgrp, SIGWINCH);
f9eea644
JB
448 }
449 break;
450
451 case TIOCGWINSZ:
452 *(struct winsize *)data = tp->t_winsize;
453 break;
454
adf4bc89
MK
455 case TIOCCONS:
456 if (*(int *)data) {
457 if (constty != NULL)
458 return (EBUSY);
459#ifndef UCONSOLE
849cbd39
KM
460 if (error = suser(u.u_cred, &u.u_acflag))
461 return (error);
adf4bc89
MK
462#endif
463 constty = tp;
464 } else if (tp == constty)
1eebc1a7 465 constty = NULL;
adf4bc89
MK
466 break;
467
e39f9ea6
MT
468#ifdef COMPAT_43
469 case TIOCGETP:
470 case TIOCSETP:
471 case TIOCSETN:
472 case TIOCGETC:
473 case TIOCSETC:
474 case TIOCSLTC:
475 case TIOCGLTC:
476 case TIOCLBIS:
477 case TIOCLBIC:
478 case TIOCLSET:
479 case TIOCLGET:
52004850
MT
480 case OTIOCGETD:
481 case OTIOCSETD:
e39f9ea6
MT
482 return(ttcompat(tp, com, data, flag));
483#endif
484
2c6a4e11
MT
485 /* allow old ioctls for now */
486 case TIOCGETP:
487 case TIOCSETP:
488 case TIOCSETN:
489 case TIOCGETC:
490 case TIOCSETC:
491 case TIOCSLTC:
492 case TIOCGLTC:
493 case TIOCLBIS:
494 case TIOCLBIC:
495 case TIOCLSET:
496 case TIOCLGET:
497 return(ottioctl(tp, com, data, flag));
498
89dc6dfb 499 default:
fc6972ae 500 return (-1);
89dc6dfb 501 }
fc6972ae 502 return (0);
89dc6dfb 503}
e1d74936 504
2c6a4e11
MT
505/*
506 * DEBUG - to be removed
507 */
508ttytrace(ioc, tp)
509 struct tty *tp;
510{
511 register u_char *cc = tp->t_cc;
512 char comm[MAXCOMLEN+1];
513 static int seq = 0;
514
515 bcopy(u.u_comm, comm, MAXCOMLEN+1);
516 comm[MAXCOMLEN] = '\0';
517
518 /* trace changes to line disciplines */
519 if (ioc == TIOCSETD) {
520 log(LOG_LOCAL4|LOG_DEBUG, "%s:%x:%x:%x:%x\n",
521 comm, ioc, u.u_procp->p_pid, tp->t_dev, tp->t_line);
522 return;
523 }
524
525 /*
526 * format for the trace record is:
527 *
528 * u_comm:ioctl:pid:dev_t:ldisc:iflag:oflag:lflag:cflag:ispeed:
529 * ospeed:cc's...:seq
530 *
531 * u_comm is a string and all other values are hex. "cc's..."
532 * stands for control chars 0 through NCC-1. seq is a sequence #
533 * to force syslogd to log every entry (rather than hold them to
534 * print "last message repeated...".
535 */
536 log(LOG_LOCAL4|LOG_DEBUG, "%s:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x\n",
537 comm, ioc, u.u_procp->p_pid, tp->t_dev, tp->t_line,
538 tp->t_iflag, tp->t_oflag, tp->t_lflag, tp->t_cflag,
539 tp->t_ispeed, tp->t_ospeed, cc[0], cc[1], cc[2], cc[3],
540 cc[4], cc[5], cc[6], cc[7], cc[8], cc[9], cc[10], cc[11],
541 cc[12], cc[13], cc[14], cc[15], cc[16], cc[17], cc[18],
542 cc[19], seq++);
543}
544
e1d74936
BJ
545ttnread(tp)
546 struct tty *tp;
547{
548 int nread = 0;
549
2c6a4e11 550 if (tp->t_lflag & PENDIN)
e1d74936
BJ
551 ttypend(tp);
552 nread = tp->t_canq.c_cc;
2c6a4e11 553 if (tp->t_lflag & ICANON == 0)
e1d74936
BJ
554 nread += tp->t_rawq.c_cc;
555 return (nread);
556}
557
941944c9 558ttselect(dev, rw)
e1d74936 559 dev_t dev;
941944c9 560 int rw;
e1d74936
BJ
561{
562 register struct tty *tp = &cdevsw[major(dev)].d_ttys[minor(dev)];
563 int nread;
4f3a716e 564 int s = spltty();
e1d74936 565
941944c9 566 switch (rw) {
e1d74936
BJ
567
568 case FREAD:
569 nread = ttnread(tp);
66ad69d6
MT
570 if (nread > 0 ||
571 (!(tp->t_cflag&CLOCAL) && !(tp->t_state&TS_CARR_ON)))
941944c9 572 goto win;
89b8a44c 573 if (tp->t_rsel && tp->t_rsel->p_wchan == (caddr_t)&selwait)
941944c9 574 tp->t_state |= TS_RCOLL;
e1d74936
BJ
575 else
576 tp->t_rsel = u.u_procp;
941944c9 577 break;
e1d74936 578
941944c9 579 case FWRITE:
e39f9ea6 580 if (tp->t_outq.c_cc <= tp->t_lowat)
941944c9 581 goto win;
941944c9
BJ
582 if (tp->t_wsel && tp->t_wsel->p_wchan == (caddr_t)&selwait)
583 tp->t_state |= TS_WCOLL;
584 else
585 tp->t_wsel = u.u_procp;
586 break;
e1d74936 587 }
941944c9
BJ
588 splx(s);
589 return (0);
590win:
591 splx(s);
592 return (1);
e1d74936 593}
8bba2b8f 594
4147b3f6 595/*
605d7712 596 * Initial open of tty, or (re)entry to line discipline.
4147b3f6
BJ
597 */
598ttyopen(dev, tp)
4b72e2f9
SL
599 dev_t dev;
600 register struct tty *tp;
4147b3f6 601{
4147b3f6 602
4147b3f6 603 tp->t_dev = dev;
e39f9ea6 604
4147b3f6 605 tp->t_state &= ~TS_WOPEN;
4f3a716e
MK
606 if ((tp->t_state & TS_ISOPEN) == 0) {
607 tp->t_state |= TS_ISOPEN;
f9eea644 608 bzero((caddr_t)&tp->t_winsize, sizeof(tp->t_winsize));
2c6a4e11
MT
609 /*
610 * CHANGE: used to do a ttywflush() if it was the
611 * old (old) line discipline.
612 */
4f3a716e 613 }
fc6972ae 614 return (0);
4147b3f6
BJ
615}
616
605d7712
MK
617/*
618 * "close" a line discipline
619 */
620ttylclose(tp)
621 register struct tty *tp;
622{
623
624 ttywflush(tp);
605d7712
MK
625}
626
4147b3f6
BJ
627/*
628 * clean tp on last close
629 */
630ttyclose(tp)
4b72e2f9 631 register struct tty *tp;
4147b3f6 632{
adf4bc89
MK
633 if (constty == tp)
634 constty = NULL;
605d7712 635 ttyflush(tp, FREAD|FWRITE);
232c0273
MT
636 tp->t_session = NULL;
637 tp->t_pgrp = NULL;
4147b3f6
BJ
638 tp->t_state = 0;
639}
640
605d7712
MK
641/*
642 * Handle modem control transition on a tty.
643 * Flag indicates new state of carrier.
644 * Returns 0 if the line should be turned off, otherwise 1.
645 */
646ttymodem(tp, flag)
647 register struct tty *tp;
648{
649
2c6a4e11 650 if ((tp->t_state&TS_WOPEN) == 0 && (tp->t_lflag & MDMBUF)) {
605d7712
MK
651 /*
652 * MDMBUF: do flow control according to carrier flag
653 */
654 if (flag) {
655 tp->t_state &= ~TS_TTSTOP;
656 ttstart(tp);
657 } else if ((tp->t_state&TS_TTSTOP) == 0) {
658 tp->t_state |= TS_TTSTOP;
659 (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
660 }
661 } else if (flag == 0) {
662 /*
663 * Lost carrier.
664 */
665 tp->t_state &= ~TS_CARR_ON;
666 if (tp->t_state & TS_ISOPEN) {
2c6a4e11 667 if ((tp->t_lflag & NOHANG) == 0) {
232c0273
MT
668 pgsignal(tp->t_pgrp, SIGHUP);
669 pgsignal(tp->t_pgrp, SIGCONT);
605d7712
MK
670 ttyflush(tp, FREAD|FWRITE);
671 return (0);
672 }
673 }
674 } else {
675 /*
676 * Carrier now on.
677 */
678 tp->t_state |= TS_CARR_ON;
66ad69d6 679 ttwakeup(tp);
605d7712
MK
680 }
681 return (1);
682}
683
e3f2038d
MK
684/*
685 * Default modem control routine (for other line disciplines).
686 * Return argument flag, to turn off device on carrier drop.
687 */
2f54b5e8
MK
688nullmodem(tp, flag)
689 register struct tty *tp;
e3f2038d
MK
690 int flag;
691{
692
693 if (flag)
694 tp->t_state |= TS_CARR_ON;
52004850 695 else {
e3f2038d 696 tp->t_state &= ~TS_CARR_ON;
52004850 697 if ((tp->t_lflag & NOHANG) == 0)
232c0273 698 pgsignal(tp->t_pgrp, SIGHUP);
52004850 699 }
e3f2038d
MK
700 return (flag);
701}
702
4147b3f6
BJ
703/*
704 * reinput pending characters after state switch
4f3a716e 705 * call at spltty().
4147b3f6
BJ
706 */
707ttypend(tp)
4b72e2f9 708 register struct tty *tp;
4147b3f6
BJ
709{
710 struct clist tq;
711 register c;
712
2c6a4e11 713 tp->t_lflag &= ~PENDIN;
becb115c 714 tp->t_state |= TS_TYPEN;
4147b3f6
BJ
715 tq = tp->t_rawq;
716 tp->t_rawq.c_cc = 0;
717 tp->t_rawq.c_cf = tp->t_rawq.c_cl = 0;
718 while ((c = getc(&tq)) >= 0)
719 ttyinput(c, tp);
becb115c 720 tp->t_state &= ~TS_TYPEN;
4147b3f6
BJ
721}
722
723/*
e39f9ea6 724 *
2c6a4e11 725 *
becb115c
SL
726 * Place a character on raw TTY input queue,
727 * putting in delimiters and waking up top
728 * half as needed. Also echo if required.
729 * The arguments are the character and the
730 * appropriate tty structure.
4147b3f6
BJ
731 */
732ttyinput(c, tp)
4b72e2f9
SL
733 register c;
734 register struct tty *tp;
4147b3f6 735{
2c6a4e11
MT
736 register int iflag = tp->t_iflag;
737 register int lflag = tp->t_lflag;
738 register u_char *cc = tp->t_cc;
739 int i, err;
4147b3f6 740
becb115c
SL
741 /*
742 * If input is pending take it first.
743 */
2c6a4e11 744 if (lflag&PENDIN)
4147b3f6 745 ttypend(tp);
e39f9ea6
MT
746 /*
747 * Gather stats.
748 */
2c6a4e11 749
4147b3f6 750 tk_nin++;
e39f9ea6
MT
751 if (lflag&ICANON) {
752 tk_cancc++;
753 tp->t_cancc++;
754 } else {
755 tk_rawcc++;
756 tp->t_rawcc++;
757 }
becb115c 758 /*
2c6a4e11 759 * Handle exceptional conditions (break, parity, framing).
becb115c 760 */
2c6a4e11
MT
761 if (err = (c&TTY_ERRORMASK)) {
762 c &= TTY_CHARMASK;
763 if (err&TTY_FE && !c) { /* break */
764 if (iflag&IGNBRK)
765 goto endcase;
766 else if (iflag&BRKINT && lflag&ISIG &&
767 (cc[VINTR] != POSIX_V_DISABLE))
768 c = cc[VINTR];
769 else
770 c = 0;
771 } else if ((err&TTY_PE && iflag&INPCK) || err&TTY_FE) {
772 if (iflag&IGNPAR)
773 goto endcase;
774 else if (iflag&PARMRK) {
775 ttyinput(0377, tp);
776 ttyinput(0, tp);
777 } else
778 c = 0;
4147b3f6 779 }
becb115c 780 }
2c6a4e11
MT
781 dprintf("<%o>\n", c);
782
783 /*
784 * In tandem mode, check high water mark.
785 */
786 if (iflag&IXOFF)
787 ttyblock(tp);
788
becb115c 789 /*
e39f9ea6 790 * In tandem mode, check high water mark.
becb115c 791 */
2c6a4e11 792 if ((tp->t_state&TS_TYPEN) == 0 && (iflag&ISTRIP))
becb115c
SL
793 c &= 0177;
794 /*
795 * Check for literal nexting very first
796 */
797 if (tp->t_state&TS_LNCH) {
e39f9ea6 798 c |= TTY_QUOTE;
becb115c
SL
799 tp->t_state &= ~TS_LNCH;
800 }
becb115c
SL
801 /*
802 * Scan for special characters. This code
803 * is really just a big case statement with
804 * non-constant cases. The bottom of the
805 * case statement is labeled ``endcase'', so goto
806 * it after a case match, or similar.
807 */
2c6a4e11
MT
808
809 /*
810 * Extensions to POSIX input modes which aren't controlled
811 * by ICANON, ISIG, or IXON.
812 */
813 if (iflag&IEXTEN) {
814 if (CCEQ(cc[VLNEXT],c) && (iflag&ISTRIP)) {
815 if (lflag&ECHO)
816 ttyout("^\b", tp); /*XXX - presumes too much */
becb115c
SL
817 tp->t_state |= TS_LNCH;
818 goto endcase;
819 }
2c6a4e11
MT
820 if (CCEQ(cc[VFLUSHO],c)) {
821 if (lflag&FLUSHO)
822 tp->t_lflag &= ~FLUSHO;
4147b3f6 823 else {
88a7a62a 824 ttyflush(tp, FWRITE);
4147b3f6 825 ttyecho(c, tp);
becb115c 826 if (tp->t_rawq.c_cc + tp->t_canq.c_cc)
4147b3f6 827 ttyretype(tp);
2c6a4e11 828 tp->t_lflag |= FLUSHO;
4147b3f6 829 }
becb115c
SL
830 goto startoutput;
831 }
2c6a4e11
MT
832 }
833
834 /*
835 * Signals.
836 */
837 if (lflag&ISIG) {
838 if (CCEQ(cc[VINTR], c) || CCEQ(cc[VQUIT], c)) {
839 if ((lflag&NOFLSH) == 0)
840 ttyflush(tp, FREAD|FWRITE);
841 ttyecho(c, tp);
842 gsignal(tp->t_pgrp, CCEQ(cc[VINTR],c) ?
843 SIGINT : SIGQUIT);
844 goto endcase;
845 }
846 if (CCEQ(cc[VSUSP],c)) {
847 if ((lflag&NOFLSH) == 0)
88a7a62a 848 ttyflush(tp, FREAD);
4147b3f6 849 ttyecho(c, tp);
232c0273 850 pgsignal(tp->t_pgrp, SIGTSTP);
becb115c
SL
851 goto endcase;
852 }
52004850
MT
853 if (CCEQ(cc[VINFO],c)) {
854 ttyinfo(tp);
855 goto endcase;
856 }
becb115c 857 }
becb115c
SL
858 /*
859 * Handle start/stop characters.
860 */
2c6a4e11
MT
861 if (iflag&IXON) {
862 if (CCEQ(cc[VSTOP],c)) {
863 if ((tp->t_state&TS_TTSTOP) == 0) {
864 tp->t_state |= TS_TTSTOP;
865 (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
866 return;
867 }
868 if (!CCEQ(cc[VSTART], c))
869 return;
870 /*
871 * if VSTART == VSTOP we toggle
872 */
873 goto endcase;
becb115c 874 }
2c6a4e11
MT
875 if (CCEQ(cc[VSTART], c))
876 goto restartoutput;
becb115c 877 }
becb115c 878 /*
2c6a4e11 879 * IGNCR, ICRNL, & INLCR
becb115c 880 */
2c6a4e11
MT
881 if (c == '\r') {
882 if (iflag&IGNCR)
883 goto endcase;
884 else if (iflag&ICRNL)
885 c = '\n';
becb115c 886 }
2c6a4e11
MT
887 else if (c == '\n' && iflag&INLCR)
888 c = '\r';
e39f9ea6
MT
889 else if (c == '\n' && iflag&INLCR)
890 c = '\r';
becb115c 891 /*
2c6a4e11 892 * Non canonical mode, don't process line editing
becb115c 893 * characters; check high water mark for wakeup.
2c6a4e11 894 *
e39f9ea6 895 *
becb115c 896 */
2c6a4e11 897 if (!(lflag&ICANON)) {
becb115c 898 if (tp->t_rawq.c_cc > TTYHOG) {
2c6a4e11 899 if (iflag&IMAXBEL) {
e39f9ea6 900 if (tp->t_outq.c_cc < tp->t_hiwat)
2c6a4e11
MT
901 (void) ttyoutput(CTRL('g'), tp);
902 } else
903 ttyflush(tp, FREAD | FWRITE);
e39f9ea6
MT
904 } else {
905 if (putc(c, &tp->t_rawq) >= 0) {
906 ttwakeup(tp);
907 ttyecho(c, tp);
908 }
4147b3f6 909 }
becb115c
SL
910 goto endcase;
911 }
becb115c 912 /*
2c6a4e11 913 * From here on down canonical mode character
becb115c
SL
914 * processing takes place.
915 */
2c6a4e11
MT
916
917 /*
918 * Oldstyle quoting of erase, kill, and eof chars.
919 *
920 * Historically is '\' , but can be changed (read: disabled)
921 * with the VQUOTE subscript.
922 */
2c6a4e11
MT
923
924 /*
925 * erase (^H / ^?)
926 */
927 if (CCEQ(cc[VERASE], c)) {
becb115c
SL
928 if (tp->t_rawq.c_cc)
929 ttyrub(unputc(&tp->t_rawq), tp);
930 goto endcase;
931 }
66ad69d6
MT
932 if (lflag&ECHOKE && tp->t_rawq.c_cc == tp->t_rocount &&
933 !(lflag&ECHOPRT)) {
becb115c
SL
934 while (tp->t_rawq.c_cc)
935 ttyrub(unputc(&tp->t_rawq), tp);
936 } else {
937 ttyecho(c, tp);
2c6a4e11
MT
938 if (lflag&ECHOK || lflag&ECHOKE)
939 ttyecho('\n', tp);
becb115c
SL
940 while (getc(&tp->t_rawq) > 0)
941 ;
942 tp->t_rocount = 0;
943 }
944 tp->t_state &= ~TS_LOCAL;
945 goto endcase;
946 }
becb115c 947 /*
2c6a4e11 948 * word erase (^W)
becb115c 949 */
2c6a4e11
MT
950 c = unputc(&tp->t_rawq);
951 } while (c != ' ' && c != '\t');
952 (void) putc(c, &tp->t_rawq);
953 goto endcase;
954 }
955 /*
956 * reprint line (^R)
957 */
958 if (CCEQ(cc[VREPRINT], c)) {
959 ttyretype(tp);
960 goto endcase;
becb115c 961 }
e39f9ea6
MT
962 /*
963 * reprint line (^R)
964 */
965 if (CCEQ(cc[VREPRINT], c)) {
966 ttyretype(tp);
967 goto endcase;
968 }
becb115c
SL
969 /*
970 * Check for input buffer overflow
971 */
7c9f96c0 972 if (tp->t_rawq.c_cc+tp->t_canq.c_cc >= TTYHOG) {
2c6a4e11
MT
973 if (iflag&IMAXBEL) {
974 if (tp->t_outq.c_cc < TTHIWAT(tp))
975 (void) ttyoutput(CTRL('g'), tp);
976 } else
977 ttyflush(tp, FREAD | FWRITE);
becb115c 978 goto endcase;
7c9f96c0 979 }
becb115c
SL
980 /*
981 * Put data char in q for user and
982 * wakeup on seeing a line delimiter.
983 */
984 if (putc(c, &tp->t_rawq) >= 0) {
2c6a4e11 985 if (ttbreakc(c)) {
becb115c
SL
986 tp->t_rocount = 0;
987 catq(&tp->t_rawq, &tp->t_canq);
4147b3f6 988 ttwakeup(tp);
becb115c
SL
989 } else if (tp->t_rocount++ == 0)
990 tp->t_rocol = tp->t_col;
2c6a4e11
MT
991 if (CCEQ(cc[VQUOTE], c) && (iflag&ISTRIP))
992 tp->t_state |= TS_QUOT; /* '\' escape */
becb115c 993 if (tp->t_state&TS_ERASE) {
e39f9ea6
MT
994 /*
995 * end of prterase \.../
996 */
2c6a4e11
MT
997 /*
998 * end of prterase \.../
999 */
becb115c
SL
1000 tp->t_state &= ~TS_ERASE;
1001 (void) ttyoutput('/', tp);
1002 }
1003 i = tp->t_col;
4147b3f6 1004 ttyecho(c, tp);
2c6a4e11
MT
1005 if (CCEQ(cc[VEOF], c) && lflag&ECHO) {
1006 /*
1007 * Place the cursor over the '^' of the ^D.
1008 */
becb115c
SL
1009 i = MIN(2, tp->t_col - i);
1010 while (i > 0) {
1011 (void) ttyoutput('\b', tp);
1012 i--;
1013 }
1014 }
4147b3f6 1015 }
becb115c
SL
1016endcase:
1017 /*
2c6a4e11 1018 * IXANY means allow any character to restart output.
becb115c 1019 */
2c6a4e11
MT
1020 if (tp->t_state&TS_TTSTOP && (iflag&IXANY == 0)
1021 && cc[VSTART] != cc[VSTOP])
4147b3f6 1022 return;
2c6a4e11 1023
becb115c 1024restartoutput:
4147b3f6 1025 tp->t_state &= ~TS_TTSTOP;
2c6a4e11 1026 tp->t_lflag &= ~FLUSHO;
becb115c 1027startoutput:
4147b3f6
BJ
1028 ttstart(tp);
1029}
1030
1031/*
becb115c 1032 * Put character on TTY output queue, adding delays,
4147b3f6 1033 * expanding tabs, and handling the CR/NL bit.
becb115c
SL
1034 * This is called both from the top half for output,
1035 * and from interrupt level for echoing.
4147b3f6
BJ
1036 * The arguments are the character and the tty structure.
1037 * Returns < 0 if putc succeeds, otherwise returns char to resend
1038 * Must be recursive.
1039 */
1040ttyoutput(c, tp)
1041 register c;
1042 register struct tty *tp;
1043{
1044 register char *colp;
1045 register ctype;
2c6a4e11
MT
1046 if (!(tp->t_oflag&OPOST)) {
1047 if (tp->t_lflag&FLUSHO)
4147b3f6
BJ
1048 return (-1);
1049 if (putc(c, &tp->t_outq))
4b72e2f9 1050 return (c);
4147b3f6 1051 tk_nout++;
e39f9ea6 1052 tp->t_outcc++;
4147b3f6
BJ
1053 return (-1);
1054 }
2c6a4e11 1055 c &= 0377;
4147b3f6
BJ
1056 /*
1057 * Turn tabs to spaces as required
1058 */
2c6a4e11 1059 if (c == '\t' && tp->t_oflag&OXTABS ) {
4147b3f6
BJ
1060 register int s;
1061
1062 c = 8 - (tp->t_col&7);
2c6a4e11 1063 if ((tp->t_lflag&FLUSHO) == 0) {
4f3a716e 1064 s = spltty(); /* don't interrupt tabs */
4147b3f6
BJ
1065 c -= b_to_q(" ", c, &tp->t_outq);
1066 tk_nout += c;
e39f9ea6 1067 tp->t_outcc += c;
4147b3f6
BJ
1068 splx(s);
1069 }
1070 tp->t_col += c;
1071 return (c ? -1 : '\t');
1072 }
e39f9ea6
MT
1073 if (c == CEOT && oflag&ONOEOT)
1074 return(-1);
4147b3f6 1075 tk_nout++;
e39f9ea6 1076 tp->t_outcc++;
2c6a4e11 1077#ifdef notdef
4147b3f6
BJ
1078 /*
1079 * turn <nl> to <cr><lf> if desired.
1080 */
2c6a4e11 1081#endif
e39f9ea6
MT
1082 if ((tp->t_lflag&FLUSHO) == 0 && putc(c, &tp->t_outq))
1083 return (c);
2c6a4e11 1084 if ((tp->t_lflag&FLUSHO) == 0 && putc(c, &tp->t_outq))
4147b3f6
BJ
1085 return (c);
1086 /*
1087 * Calculate delays.
1088 * The numbers here represent clock ticks
1089 * and are not necessarily optimal for all terminals.
becb115c
SL
1090 *
1091 * SHOULD JUST ALLOW USER TO SPECIFY DELAYS
e39f9ea6
MT
1092 *
1093 * (actually, should THROW AWAY terminals which need delays)
4147b3f6
BJ
1094 */
1095 colp = &tp->t_col;
1096 ctype = partab[c];
1097 c = 0;
1098 switch (ctype&077) {
1099
1100 case ORDINARY:
1101 (*colp)++;
1102
1103 case CONTROL:
1104 break;
1105
1106 case BACKSPACE:
1107 if (*colp)
1108 (*colp)--;
1109 break;
1110
3686c829
SL
1111 /*
1112 * This macro is close enough to the correct thing;
1113 * it should be replaced by real user settable delays
1114 * in any event...
1115 */
1116#define mstohz(ms) (((ms) * hz) >> 10)
4147b3f6
BJ
1117 case NEWLINE:
1118 ctype = (tp->t_flags >> 8) & 03;
4b72e2f9 1119 if (ctype == 1) { /* tty 37 */
8011f5df
MK
1120 if (*colp > 0) {
1121 c = (((unsigned)*colp) >> 4) + 3;
1122 if ((unsigned)c > 6)
1123 c = 6;
1124 }
becb115c 1125 } else if (ctype == 2) /* vt05 */
3686c829 1126 c = mstohz(100);
4147b3f6
BJ
1127 *colp = 0;
1128 break;
1129
1130 case TAB:
1131 ctype = (tp->t_flags >> 10) & 03;
4b72e2f9 1132 if (ctype == 1) { /* tty 37 */
4147b3f6 1133 c = 1 - (*colp | ~07);
4b72e2f9 1134 if (c < 5)
4147b3f6
BJ
1135 c = 0;
1136 }
1137 *colp |= 07;
1138 (*colp)++;
1139 break;
1140
1141 case VTAB:
becb115c 1142 if (tp->t_flags&VTDELAY) /* tty 37 */
4147b3f6
BJ
1143 c = 0177;
1144 break;
1145
1146 case RETURN:
1147 ctype = (tp->t_flags >> 12) & 03;
becb115c 1148 if (ctype == 1) /* tn 300 */
3686c829 1149 c = mstohz(83);
becb115c 1150 else if (ctype == 2) /* ti 700 */
3686c829 1151 c = mstohz(166);
becb115c 1152 else if (ctype == 3) { /* concept 100 */
4147b3f6 1153 int i;
becb115c 1154
4147b3f6 1155 if ((i = *colp) >= 0)
becb115c 1156 for (; i < 9; i++)
4147b3f6
BJ
1157 (void) putc(0177, &tp->t_outq);
1158 }
1159 *colp = 0;
1160 }
2c6a4e11 1161 if (c && (tp->t_lflag&FLUSHO) == 0)
e39f9ea6 1162 (void) putc(c|TTY_QUOTE, &tp->t_outq);
4147b3f6
BJ
1163 return (-1);
1164}
3686c829 1165#undef mstohz
4147b3f6
BJ
1166
1167/*
1168 * Called from device's read routine after it has
1169 * calculated the tty-structure given as argument.
1170 */
66ad69d6 1171ttread(tp, uio, flag)
4b72e2f9 1172 register struct tty *tp;
d6d7360b 1173 struct uio *uio;
4147b3f6
BJ
1174{
1175 register struct clist *qp;
2c6a4e11
MT
1176 register int c, t_flags;
1177 register long lflag = tp->t_lflag;
1178 register long iflag = tp->t_iflag;
1179 register u_char *cc = tp->t_cc;
875a1e2c 1180 int s, first, error = 0;
4147b3f6 1181
2c6a4e11 1182
4147b3f6 1183loop:
66ad69d6 1184 s = spltty();
becb115c 1185 /*
66ad69d6 1186 * take pending input first
becb115c 1187 */
2c6a4e11 1188 if (tp->t_lflag&PENDIN)
4147b3f6 1189 ttypend(tp);
66ad69d6
MT
1190 /*
1191 * Handle carrier.
1192 */
1193 if (!(tp->t_state&TS_CARR_ON) && !(tp->t_cflag&CLOCAL)) {
1194 if (tp->t_state&TS_ISOPEN) {
1195 splx(s);
1196 return (0); /* EOF */
c4ec2128 1197 } else if (flag & IO_NDELAY) {
66ad69d6
MT
1198 splx(s);
1199 return (EWOULDBLOCK);
1200 } else {
1201 /*
1202 * sleep awaiting carrier
1203 */
1204 sleep((caddr_t)&tp->t_rawq, TTIPRI);
1205 splx(s);
1206 goto loop;
1207 }
1208 }
875a1e2c 1209 splx(s);
becb115c
SL
1210 /*
1211 * Hang process if it's in the background.
1212 */
232c0273 1213 if (isbackground(u.u_procp, tp)) {
52c041cd
MK
1214 if ((u.u_procp->p_sigignore & sigmask(SIGTTIN)) ||
1215 (u.u_procp->p_sigmask & sigmask(SIGTTIN)) ||
e39f9ea6 1216 u.u_procp->p_flag&SVFORK || u.u_procp->p_pgrp->pg_jobc == 0)
840510a3 1217 return (EIO);
e39f9ea6 1218 pgsignal(u.u_procp->p_pgrp, SIGTTIN);
4147b3f6 1219 sleep((caddr_t)&lbolt, TTIPRI);
58786a81 1220 goto loop;
4147b3f6 1221 }
becb115c 1222 /*
2c6a4e11
MT
1223 * If canonical, use the canonical queue,
1224 * else use the raw queue.
becb115c 1225 */
2c6a4e11 1226 qp = lflag&ICANON ? &tp->t_canq : &tp->t_rawq;
becb115c
SL
1227 /*
1228 * No input, sleep on rawq awaiting hardware
1229 * receipt and notification.
1230 */
4f3a716e 1231 s = spltty();
becb115c 1232 if (qp->c_cc <= 0) {
66ad69d6 1233 /** XXX ??? ask mike why TS_CARR_ON was (once) necessary here
becb115c
SL
1234 if ((tp->t_state&TS_CARR_ON) == 0 ||
1235 (tp->t_state&TS_NBIO)) {
875a1e2c 1236 splx(s);
becb115c 1237 return (EWOULDBLOCK);
4147b3f6 1238 }
66ad69d6 1239 **/
c4ec2128 1240 if (flag & IO_NDELAY) {
66ad69d6
MT
1241 splx(s);
1242 return (EWOULDBLOCK);
1243 }
becb115c 1244 sleep((caddr_t)&tp->t_rawq, TTIPRI);
875a1e2c 1245 splx(s);
becb115c
SL
1246 goto loop;
1247 }
875a1e2c 1248 splx(s);
becb115c 1249 /*
2c6a4e11 1250 * Input present, check for input mapping and processing.
becb115c
SL
1251 */
1252 first = 1;
1253 while ((c = getc(qp)) >= 0) {
becb115c 1254 /*
2c6a4e11 1255 * delayed suspend (^Y)
becb115c 1256 */
2c6a4e11 1257 if (CCEQ(cc[VDSUSP], c) && lflag&ISIG) {
232c0273 1258 pgsignal(tp->t_pgrp, SIGTSTP);
becb115c
SL
1259 if (first) {
1260 sleep((caddr_t)&lbolt, TTIPRI);
1261 goto loop;
1262 }
1263 break;
4147b3f6 1264 }
becb115c 1265 /*
2c6a4e11 1266 * Interpret EOF only in canonical mode.
becb115c 1267 */
2c6a4e11 1268 if (CCEQ(cc[VEOF], c) && lflag&ICANON)
becb115c
SL
1269 break;
1270 /*
1271 * Give user character.
1272 */
2c6a4e11 1273 error = ureadc(iflag&ISTRIP ? c & 0177 : c , uio);
becb115c
SL
1274 if (error)
1275 break;
9ec65acb 1276 if (uio->uio_resid == 0)
becb115c
SL
1277 break;
1278 /*
2c6a4e11 1279 * In canonical mode check for a "break character"
becb115c
SL
1280 * marking the end of a "line of input".
1281 */
2c6a4e11 1282 if (lflag&ICANON && ttbreakc(c)) {
becb115c 1283 break;
2c6a4e11 1284 }
e39f9ea6 1285 }
becb115c 1286 first = 0;
4147b3f6 1287 }
becb115c
SL
1288 /*
1289 * Look to unblock output now that (presumably)
1290 * the input queue has gone down.
1291 */
2c6a4e11
MT
1292 if (tp->t_state&TS_TBLOCK && tp->t_rawq.c_cc < TTYHOG/5) {
1293 if (cc[VSTART] != POSIX_V_DISABLE
1294 && putc(cc[VSTART], &tp->t_outq) == 0) {
4147b3f6
BJ
1295 tp->t_state &= ~TS_TBLOCK;
1296 ttstart(tp);
1297 }
2c6a4e11 1298 }
e39f9ea6 1299 }
840510a3 1300 return (error);
4147b3f6
BJ
1301}
1302
605d7712
MK
1303/*
1304 * Check the output queue on tp for space for a kernel message
1305 * (from uprintf/tprintf). Allow some space over the normal
1306 * hiwater mark so we don't lose messages due to normal flow
1307 * control, but don't let the tty run amok.
ca9b16e5
MK
1308 * Sleeps here are not interruptible, but we return prematurely
1309 * if new signals come in.
605d7712
MK
1310 */
1311ttycheckoutq(tp, wait)
1312 register struct tty *tp;
1313 int wait;
1314{
ca9b16e5 1315 int hiwat, s, oldsig;
605d7712 1316
e39f9ea6 1317 hiwat = tp->t_hiwat;
605d7712 1318 s = spltty();
ca9b16e5 1319 oldsig = u.u_procp->p_sig;
605d7712 1320 if (tp->t_outq.c_cc > hiwat + 200)
fb1db32c
MK
1321 while (tp->t_outq.c_cc > hiwat) {
1322 ttstart(tp);
ca9b16e5 1323 if (wait == 0 || u.u_procp->p_sig != oldsig) {
fb1db32c
MK
1324 splx(s);
1325 return (0);
1326 }
ca9b16e5 1327 timeout(wakeup, (caddr_t)&tp->t_outq, hz);
fb1db32c 1328 tp->t_state |= TS_ASLEEP;
ca9b16e5 1329 sleep((caddr_t)&tp->t_outq, PZERO - 1);
605d7712 1330 }
605d7712
MK
1331 splx(s);
1332 return (1);
1333}
1334
4147b3f6
BJ
1335/*
1336 * Called from the device's write routine after it has
1337 * calculated the tty-structure given as argument.
1338 */
66ad69d6 1339ttwrite(tp, uio, flag)
4b72e2f9 1340 register struct tty *tp;
becb115c 1341 register struct uio *uio;
4147b3f6 1342{
4147b3f6 1343 register char *cp;
c4ec2128 1344 register int cc, ce;
becb115c 1345 int i, hiwat, cnt, error, s;
4147b3f6 1346 char obuf[OBUFSIZ];
4147b3f6 1347
e39f9ea6 1348 hiwat = tp->t_hiwat;
becb115c
SL
1349 cnt = uio->uio_resid;
1350 error = 0;
4147b3f6 1351loop:
66ad69d6
MT
1352 s = spltty();
1353 if (!(tp->t_state&TS_CARR_ON) && !(tp->t_cflag&CLOCAL)) {
1354 if (tp->t_state&TS_ISOPEN) {
1355 splx(s);
1356 return (EIO);
c4ec2128 1357 } else if (flag & IO_NDELAY) {
66ad69d6
MT
1358 splx(s);
1359 return (EWOULDBLOCK);
1360 } else {
1361 /*
1362 * sleep awaiting carrier
1363 */
1364 sleep((caddr_t)&tp->t_rawq, TTIPRI);
1365 splx(s);
1366 goto loop;
1367 }
1368 }
1369 splx(s);
becb115c
SL
1370 /*
1371 * Hang the process if it's in the background.
1372 */
2c6a4e11 1373 (tp->t_lflag&TOSTOP) && (u.u_procp->p_flag&SVFORK)==0 &&
52c041cd 1374 !(u.u_procp->p_sigignore & sigmask(SIGTTOU)) &&
e39f9ea6
MT
1375 !(u.u_procp->p_sigmask & sigmask(SIGTTOU)) &&
1376 u.u_procp->p_pgrp->pg_jobc) {
1377 pgsignal(u.u_procp->p_pgrp, SIGTTOU);
4147b3f6 1378 sleep((caddr_t)&lbolt, TTIPRI);
93d2ecff 1379 goto loop;
4147b3f6 1380 }
becb115c
SL
1381 /*
1382 * Process the user's data in at most OBUFSIZ
1383 * chunks. Perform lower case simulation and
1384 * similar hacks. Keep track of high water
1385 * mark, sleep on overflow awaiting device aid
1386 * in acquiring new space.
1387 */
913ea2d1 1388 while (uio->uio_resid > 0) {
b482b2c8
MK
1389 if (tp->t_outq.c_cc > hiwat) {
1390 cc = 0;
1391 goto ovhiwat;
1392 }
becb115c
SL
1393 /*
1394 * Grab a hunk of data from the user.
1395 */
913ea2d1
BJ
1396 cc = uio->uio_iov->iov_len;
1397 if (cc == 0) {
1398 uio->uio_iovcnt--;
1399 uio->uio_iov++;
93d2ecff 1400 if (uio->uio_iovcnt <= 0)
913ea2d1
BJ
1401 panic("ttwrite");
1402 continue;
1403 }
1404 if (cc > OBUFSIZ)
1405 cc = OBUFSIZ;
4147b3f6 1406 cp = obuf;
c4ec2128 1407 error = uiomove(cp, cc, uio);
840510a3 1408 if (error)
4147b3f6 1409 break;
2c6a4e11 1410 if (tp->t_lflag&FLUSHO)
4147b3f6 1411 continue;
2c6a4e11 1412#ifdef notdef
becb115c
SL
1413 /*
1414 * If nothing fancy need be done, grab those characters we
1415 * can handle without any of ttyoutput's processing and
1416 * just transfer them to the output q. For those chars
1417 * which require special processing (as indicated by the
1418 * bits in partab), call ttyoutput. After processing
1419 * a hunk of data, look for FLUSHO so ^O's will take effect
1420 * immediately.
1421 */
1422 while (cc > 0) {
2c6a4e11 1423 if (!(tp->t_oflag&OPOST))
4147b3f6
BJ
1424 ce = cc;
1425 else {
3f36033f
MK
1426 ce = cc - scanc((unsigned)cc, (u_char *)cp,
1427 (u_char *)partab, 077);
becb115c
SL
1428 /*
1429 * If ce is zero, then we're processing
1430 * a special character through ttyoutput.
1431 */
1432 if (ce == 0) {
4147b3f6
BJ
1433 tp->t_rocount = 0;
1434 if (ttyoutput(*cp, tp) >= 0) {
93d2ecff
JB
1435 /* no c-lists, wait a bit */
1436 ttstart(tp);
1437 sleep((caddr_t)&lbolt, TTOPRI);
1438 if (cc != 0) {
1439 uio->uio_iov->iov_base -= cc;
1440 uio->uio_iov->iov_len += cc;
1441 uio->uio_resid += cc;
1442 uio->uio_offset -= cc;
1443 }
1444 goto loop;
4147b3f6 1445 }
becb115c 1446 cp++, cc--;
2c6a4e11 1447 if (tp->t_lflag&FLUSHO ||
becb115c 1448 tp->t_outq.c_cc > hiwat)
4147b3f6 1449 goto ovhiwat;
becb115c 1450 continue;
4147b3f6
BJ
1451 }
1452 }
becb115c
SL
1453 /*
1454 * A bunch of normal characters have been found,
1455 * transfer them en masse to the output queue and
1456 * continue processing at the top of the loop.
1457 * If there are any further characters in this
1458 * <= OBUFSIZ chunk, the first should be a character
1459 * requiring special handling by ttyoutput.
1460 */
4147b3f6 1461 tp->t_rocount = 0;
becb115c
SL
1462 i = b_to_q(cp, ce, &tp->t_outq);
1463 ce -= i;
1464 tp->t_col += ce;
1465 cp += ce, cc -= ce, tk_nout += ce;
e39f9ea6 1466 tp->t_outcc += ce;
becb115c
SL
1467 if (i > 0) {
1468 /* out of c-lists, wait a bit */
4147b3f6
BJ
1469 ttstart(tp);
1470 sleep((caddr_t)&lbolt, TTOPRI);
93d2ecff
JB
1471 uio->uio_iov->iov_base -= cc;
1472 uio->uio_iov->iov_len += cc;
1473 uio->uio_resid += cc;
1474 uio->uio_offset -= cc;
1475 goto loop;
4147b3f6 1476 }
2c6a4e11 1477 if (tp->t_lflag&FLUSHO || tp->t_outq.c_cc > hiwat)
4147b3f6
BJ
1478 goto ovhiwat;
1479 }
2c6a4e11 1480 ttstart(tp);
e39f9ea6 1481 ttstart(tp);
4147b3f6 1482 }
840510a3 1483 return (error);
4147b3f6 1484ovhiwat:
becb115c
SL
1485 if (cc != 0) {
1486 uio->uio_iov->iov_base -= cc;
1487 uio->uio_iov->iov_len += cc;
1488 uio->uio_resid += cc;
1489 uio->uio_offset -= cc;
1490 }
b482b2c8
MK
1491 ttstart(tp);
1492 s = spltty();
becb115c 1493 /*
2c6a4e11 1494 * This can only occur if FLUSHO is set in t_lflag,
b482b2c8 1495 * or if ttstart/oproc is synchronous (or very fast).
becb115c 1496 */
4147b3f6 1497 if (tp->t_outq.c_cc <= hiwat) {
becb115c 1498 splx(s);
4147b3f6
BJ
1499 goto loop;
1500 }
c4ec2128 1501 if (flag & IO_NDELAY) {
4f3a716e 1502 splx(s);
913ea2d1 1503 if (uio->uio_resid == cnt)
840510a3
BJ
1504 return (EWOULDBLOCK);
1505 return (0);
4147b3f6
BJ
1506 }
1507 tp->t_state |= TS_ASLEEP;
1508 sleep((caddr_t)&tp->t_outq, TTOPRI);
becb115c 1509 splx(s);
4147b3f6
BJ
1510 goto loop;
1511}
1512
1513/*
1514 * Rubout one character from the rawq of tp
1515 * as cleanly as possible.
1516 */
1517ttyrub(c, tp)
4b72e2f9
SL
1518 register c;
1519 register struct tty *tp;
4147b3f6
BJ
1520{
1521 register char *cp;
1522 register int savecol;
1523 int s;
1524 char *nextc();
1525
2c6a4e11 1526 if ((tp->t_lflag&ECHO) == 0)
4147b3f6 1527 return;
2c6a4e11 1528 if (tp->t_lflag&ECHOE) {
4147b3f6
BJ
1529 if (tp->t_rocount == 0) {
1530 /*
1531 * Screwed by ttwrite; retype
1532 */
1533 ttyretype(tp);
1534 return;
1535 }
2c6a4e11 1536 /* if tab or newline was escaped - XXX - not 8bit */
e39f9ea6 1537 if (c == ('\t'|TTY_QUOTE) || c == ('\n'|TTY_QUOTE))
4147b3f6 1538 ttyrubo(tp, 2);
e39f9ea6 1539 else switch (partab[c&=0377]&077) {
4147b3f6
BJ
1540
1541 case ORDINARY:
2c6a4e11 1542#ifdef notdef
e39f9ea6 1543 ttyrubo(tp, 1);
4147b3f6
BJ
1544 break;
1545
1546 case VTAB:
1547 case BACKSPACE:
1548 case CONTROL:
1549 case RETURN:
2c6a4e11 1550 if (tp->t_lflag&ECHOCTL)
4147b3f6
BJ
1551 ttyrubo(tp, 2);
1552 break;
1553
e39f9ea6
MT
1554 case TAB: {
1555 int c;
1556
4147b3f6
BJ
1557 if (tp->t_rocount < tp->t_rawq.c_cc) {
1558 ttyretype(tp);
1559 return;
1560 }
4f3a716e 1561 s = spltty();
4147b3f6 1562 savecol = tp->t_col;
becb115c 1563 tp->t_state |= TS_CNTTB;
2c6a4e11 1564 tp->t_lflag |= FLUSHO;
4147b3f6 1565 tp->t_col = tp->t_rocol;
becb115c 1566 cp = tp->t_rawq.c_cf;
2c6a4e11 1567 tp->t_lflag &= ~FLUSHO;
becb115c 1568 tp->t_state &= ~TS_CNTTB;
4147b3f6
BJ
1569 splx(s);
1570 /*
1571 * savecol will now be length of the tab
1572 */
1573 savecol -= tp->t_col;
1574 tp->t_col += savecol;
1575 if (savecol > 8)
1576 savecol = 8; /* overflow screw */
1577 while (--savecol >= 0)
1578 (void) ttyoutput('\b', tp);
1579 break;
e39f9ea6 1580 }
4147b3f6
BJ
1581
1582 default:
66ad69d6 1583 /* XXX */
e39f9ea6
MT
1584 printf("ttyrub: would panic c = %d, val = %d\n",
1585 c, partab[c&=0377]&077);
1586 /*panic("ttyrub");*/
4147b3f6 1587 }
2c6a4e11 1588 } else if (tp->t_lflag&ECHOPRT) {
becb115c 1589 if ((tp->t_state&TS_ERASE) == 0) {
4147b3f6 1590 (void) ttyoutput('\\', tp);
becb115c 1591 tp->t_state |= TS_ERASE;
4147b3f6
BJ
1592 }
1593 ttyecho(c, tp);
1594 } else
2c6a4e11 1595 ttyecho(tp->t_cc[VERASE], tp);
4147b3f6
BJ
1596 tp->t_rocount--;
1597}
1598
1599/*
1600 * Crt back over cnt chars perhaps
1601 * erasing them.
1602 */
1603ttyrubo(tp, cnt)
4b72e2f9
SL
1604 register struct tty *tp;
1605 int cnt;
4147b3f6 1606{
2c6a4e11 1607 register char *rubostring = tp->t_lflag&ECHOE ? "\b \b" : "\b";
4147b3f6
BJ
1608
1609 while (--cnt >= 0)
e39f9ea6 1610 ttyout("\b \b", tp);
4147b3f6
BJ
1611}
1612
1613/*
1614 * Reprint the rawq line.
1615 * We assume c_cc has already been checked.
1616 */
1617ttyretype(tp)
4b72e2f9 1618 register struct tty *tp;
4147b3f6
BJ
1619{
1620 register char *cp;
1621 char *nextc();
e39f9ea6 1622 int s, c;
4147b3f6 1623
2c6a4e11
MT
1624 if (tp->t_cc[VREPRINT] != POSIX_V_DISABLE)
1625 ttyecho(tp->t_cc[VREPRINT], tp);
4147b3f6 1626 (void) ttyoutput('\n', tp);
4f3a716e 1627 s = spltty();
e39f9ea6
MT
1628 /*** XXX *** FIX *** NEXTC IS BROKEN - DOESN'T CHECK QUOTE
1629 BIT OF FIRST CHAR ****/
1630 for (cp = tp->t_canq.c_cf, c=(cp?*cp:0); cp; cp = nextc(&tp->t_canq, cp, &c)) {
1631 ttyecho(c, tp);
1632 }
1633 for (cp = tp->t_rawq.c_cf, c=(cp?*cp:0); cp; cp = nextc(&tp->t_rawq, cp, &c)) {
1634 ttyecho(c, tp);
1635 }
becb115c 1636 tp->t_state &= ~TS_ERASE;
4147b3f6
BJ
1637 splx(s);
1638 tp->t_rocount = tp->t_rawq.c_cc;
1639 tp->t_rocol = 0;
1640}
1641
1642/*
2c6a4e11 1643 * Echo a typed character to the terminal.
4147b3f6
BJ
1644 */
1645ttyecho(c, tp)
4b72e2f9
SL
1646 register c;
1647 register struct tty *tp;
4147b3f6 1648{
4147b3f6 1649 c &= 0377;
2c6a4e11
MT
1650 if ((tp->t_state&TS_CNTTB) == 0)
1651 tp->t_lflag &= ~FLUSHO;
1652 if ((tp->t_lflag&ECHO) == 0 && !(tp->t_lflag&ECHONL && c == '\n'))
4147b3f6 1653 return;
2c6a4e11 1654 if (tp->t_lflag&ECHOCTL) {
e39f9ea6 1655 if ((c&TTY_CHARMASK)<=037 && c!='\t' && c!='\n' || c==0177) {
4147b3f6 1656 (void) ttyoutput('^', tp);
e39f9ea6 1657 c &= TTY_CHARMASK;
4147b3f6
BJ
1658 if (c == 0177)
1659 c = '?';
2c6a4e11 1660#ifdef notdef
2c6a4e11 1661#endif
4147b3f6
BJ
1662 else
1663 c += 'A' - 1;
1664 }
1665 }
e39f9ea6 1666 (void) ttyoutput(c, tp);
4147b3f6
BJ
1667 * send string cp to tp
1668 */
1669ttyout(cp, tp)
4b72e2f9
SL
1670 register char *cp;
1671 register struct tty *tp;
4147b3f6
BJ
1672{
1673 register char c;
1674
1675 while (c = *cp++)
1676 (void) ttyoutput(c, tp);
1677}
1678
1679ttwakeup(tp)
1680 struct tty *tp;
1681{
1682
1683 if (tp->t_rsel) {
1684 selwakeup(tp->t_rsel, tp->t_state&TS_RCOLL);
1685 tp->t_state &= ~TS_RCOLL;
1686 tp->t_rsel = 0;
1687 }
88a7a62a 1688 if (tp->t_state & TS_ASYNC)
232c0273 1689 pgsignal(tp->t_pgrp, SIGIO);
4147b3f6
BJ
1690 wakeup((caddr_t)&tp->t_rawq);
1691}
e39f9ea6
MT
1692
1693/*
1694 * set tty hi and low water marks
1695 *
1696 * Try to arrange the dynamics so there's about one second
1697 * from hi to low water.
1698 *
1699 */
1700ttsetwater(tp)
1701 struct tty *tp;
1702{
1703 register cps = tp->t_ospeed / 10;
1704 register x;
1705
1706#define clamp(x, h, l) ((x)>h ? h : ((x)<l) ? l : (x))
1707 tp->t_lowat = x = clamp(cps/2, TTMAXLOWAT, TTMINLOWAT);
1708 x += cps;
1709 x = clamp(x, TTMAXHIWAT, TTMINHIWAT);
1710 tp->t_hiwat = roundup(x, CBSIZE);
1711#undef clamp
1712}
1713
1714ttspeedtab(speed, table)
1715 struct speedtab table[];
1716{
1717 register int i;
1718
1719 for (i = 0; table[i].sp_speed != -1; i++)
1720 if (table[i].sp_speed == speed)
1721 return(table[i].sp_code);
1722 return(-1);
1723}
52004850
MT
1724
1725/*
1726 * (^T)
1727 * Report on state of foreground process group.
1728 */
1729ttyinfo(tp)
1730 struct tty *tp;
1731{
1732 register struct proc *p;
52004850
MT
1733
1734 if (ttycheckoutq(tp,0) == 0)
1735 return;
232c0273
MT
1736 if (tp->t_session == NULL)
1737 ttyprintf(tp, "kernel: not a controlling terminal\n");
1738 else if (tp->t_pgrp == NULL ||
1739 (p = tp->t_pgrp->pg_mem) == NULL)
52004850 1740 ttyprintf(tp, "kernel: no foreground process group\n");
52004850
MT
1741 else {
1742 int i = 0;
232c0273 1743
52004850
MT
1744 for (; p != NULL; p = p->p_pgrpnxt) {
1745 ttyprintf(tp,
1746 "kernel: pid: %d state: %x wchan: %x ticks: %d\n",
1747 p->p_pid, p->p_stat, p->p_wchan, p->p_cpticks);
1748 if (++i > 6) {
1749 ttyprintf(tp, "kernel: more...\n");
1750 break;
1751 }
1752 }
1753 }
1754}
1755
1756#define TOTTY 0x2 /* XXX should be in header */
1757/*VARARGS2*/
1758ttyprintf(tp, fmt, x1)
232c0273 1759 struct tty *tp;
52004850
MT
1760 char *fmt;
1761 unsigned x1;
1762{
232c0273
MT
1763 prf(fmt, &x1, TOTTY, (caddr_t)tp);
1764}
1765
1766/*
1767 * Output char to tty; console putchar style.
1768 */
1769tputchar(c, tp)
1770 int c;
1771 struct tty *tp;
1772{
1773 register s = spltty();
1774
1775 if ((tp->t_state & (TS_CARR_ON | TS_ISOPEN))
1776 == (TS_CARR_ON | TS_ISOPEN)) {
1777 if (c == '\n')
1778 (void) ttyoutput('\r', tp);
1779 (void) ttyoutput(c, tp);
1780 ttstart(tp);
1781 splx(s);
1782 return (0);
1783 }
1784 splx(s);
1785 return (-1);
52004850 1786}