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