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