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