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