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