1 /* $OpenBSD: tty.c,v 1.178 2024/12/30 02:46:00 guenther Exp $ */
2 /* $NetBSD: tty.c,v 1.68.4.2 1996/06/06 16:04:52 thorpej Exp $ */
3
4 /*-
5 * Copyright (c) 1982, 1986, 1990, 1991, 1993
6 * The Regents of the University of California. All rights reserved.
7 * (c) UNIX System Laboratories, Inc.
8 * All or some portions of this file are derived from material licensed
9 * to the University of California by American Telephone and Telegraph
10 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
11 * the permission of UNIX System Laboratories, Inc.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 * 3. Neither the name of the University nor the names of its contributors
22 * may be used to endorse or promote products derived from this software
23 * without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 *
37 * @(#)tty.c 8.8 (Berkeley) 1/21/94
38 */
39
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/ioctl.h>
43 #include <sys/proc.h>
44 #define TTYDEFCHARS
45 #include <sys/tty.h>
46 #undef TTYDEFCHARS
47 #include <sys/fcntl.h>
48 #include <sys/conf.h>
49 #include <sys/uio.h>
50 #include <sys/kernel.h>
51 #include <sys/vnode.h>
52 #include <sys/lock.h>
53 #include <sys/malloc.h>
54 #include <sys/msgbuf.h>
55 #include <sys/signalvar.h>
56 #include <sys/resourcevar.h>
57 #include <sys/sysctl.h>
58 #include <sys/pool.h>
59 #include <sys/unistd.h>
60 #include <sys/pledge.h>
61
62 #include <sys/namei.h>
63
64 #include <uvm/uvm_extern.h>
65
66 #include <dev/cons.h>
67
68 #include "pty.h"
69
70 static int ttnread(struct tty *);
71 static void ttyblock(struct tty *);
72 void ttyunblock(struct tty *);
73 static void ttyecho(int, struct tty *);
74 static void ttyrubo(struct tty *, int);
75 int filt_ttyread(struct knote *kn, long hint);
76 void filt_ttyrdetach(struct knote *kn);
77 int filt_ttywrite(struct knote *kn, long hint);
78 void filt_ttywdetach(struct knote *kn);
79 int filt_ttyexcept(struct knote *kn, long hint);
80 void ttystats_init(struct itty **, int *, size_t *);
81 int ttywait_nsec(struct tty *, uint64_t);
82 int ttysleep_nsec(struct tty *, void *, int, char *, uint64_t);
83
84 /* Symbolic sleep message strings. */
85 char ttclos[] = "ttycls";
86 char ttopen[] = "ttyopn";
87 char ttybg[] = "ttybg";
88 char ttyin[] = "ttyin";
89 char ttyout[] = "ttyout";
90
91 /*
92 * Table with character classes and parity. The 8th bit indicates parity,
93 * the 7th bit indicates the character is an alphameric or underscore (for
94 * ALTWERASE), and the low 6 bits indicate delay type. If the low 6 bits
95 * are 0 then the character needs no special processing on output; classes
96 * other than 0 might be translated or (not currently) require delays.
97 */
98 #define E 0x00 /* Even parity. */
99 #define O 0x80 /* Odd parity. */
100 #define PARITY(c) (char_type[c] & O)
101
102 #define ALPHA 0x40 /* Alpha or underscore. */
103 #define ISALPHA(c) (char_type[(c) & TTY_CHARMASK] & ALPHA)
104
105 #define CCLASSMASK 0x3f
106 #define CCLASS(c) (char_type[c] & CCLASSMASK)
107
108 #define BS BACKSPACE
109 #define CC CONTROL
110 #define CR RETURN
111 #define NA ORDINARY | ALPHA
112 #define NL NEWLINE
113 #define NO ORDINARY
114 #define TB TAB
115 #define VT VTAB
116
117 u_char const char_type[] = {
118 E|CC, O|CC, O|CC, E|CC, O|CC, E|CC, E|CC, O|CC, /* nul - bel */
119 O|BS, E|TB, E|NL, O|CC, E|VT, O|CR, O|CC, E|CC, /* bs - si */
120 O|CC, E|CC, E|CC, O|CC, E|CC, O|CC, O|CC, E|CC, /* dle - etb */
121 E|CC, O|CC, O|CC, E|CC, O|CC, E|CC, E|CC, O|CC, /* can - us */
122 O|NO, E|NO, E|NO, O|NO, E|NO, O|NO, O|NO, E|NO, /* sp - ' */
123 E|NO, O|NO, O|NO, E|NO, O|NO, E|NO, E|NO, O|NO, /* ( - / */
124 E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* 0 - 7 */
125 O|NA, E|NA, E|NO, O|NO, E|NO, O|NO, O|NO, E|NO, /* 8 - ? */
126 O|NO, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA, /* @ - G */
127 E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* H - O */
128 E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* P - W */
129 O|NA, E|NA, E|NA, O|NO, E|NO, O|NO, O|NO, O|NA, /* X - _ */
130 E|NO, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* ` - g */
131 O|NA, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA, /* h - o */
132 O|NA, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA, /* p - w */
133 E|NA, O|NA, O|NA, E|NO, O|NO, E|NO, E|NO, O|CC, /* x - del */
134 /*
135 * Meta chars; should be settable per character set;
136 * for now, treat them all as normal characters.
137 */
138 NA, NA, NA, NA, NA, NA, NA, NA,
139 NA, NA, NA, NA, NA, NA, NA, NA,
140 NA, NA, NA, NA, NA, NA, NA, NA,
141 NA, NA, NA, NA, NA, NA, NA, NA,
142 NA, NA, NA, NA, NA, NA, NA, NA,
143 NA, NA, NA, NA, NA, NA, NA, NA,
144 NA, NA, NA, NA, NA, NA, NA, NA,
145 NA, NA, NA, NA, NA, NA, NA, NA,
146 NA, NA, NA, NA, NA, NA, NA, NA,
147 NA, NA, NA, NA, NA, NA, NA, NA,
148 NA, NA, NA, NA, NA, NA, NA, NA,
149 NA, NA, NA, NA, NA, NA, NA, NA,
150 NA, NA, NA, NA, NA, NA, NA, NA,
151 NA, NA, NA, NA, NA, NA, NA, NA,
152 NA, NA, NA, NA, NA, NA, NA, NA,
153 NA, NA, NA, NA, NA, NA, NA, NA,
154 };
155 #undef BS
156 #undef CC
157 #undef CR
158 #undef NA
159 #undef NL
160 #undef NO
161 #undef TB
162 #undef VT
163
164 #define islower(c) ((c) >= 'a' && (c) <= 'z')
165 #define isupper(c) ((c) >= 'A' && (c) <= 'Z')
166
167 #define tolower(c) ((c) - 'A' + 'a')
168 #define toupper(c) ((c) - 'a' + 'A')
169
170 struct ttylist_head ttylist; /* TAILQ_HEAD */
171 int tty_count;
172 struct rwlock ttylist_lock = RWLOCK_INITIALIZER("ttylist");
173
174 int64_t tk_cancc, tk_nin, tk_nout, tk_rawcc;
175
176 /*
177 * Initial open of tty, or (re)entry to standard tty line discipline.
178 */
179 int
ttyopen(dev_t device,struct tty * tp,struct proc * p)180 ttyopen(dev_t device, struct tty *tp, struct proc *p)
181 {
182 int s;
183
184 s = spltty();
185 tp->t_dev = device;
186 if (!ISSET(tp->t_state, TS_ISOPEN)) {
187 SET(tp->t_state, TS_ISOPEN);
188 memset(&tp->t_winsize, 0, sizeof(tp->t_winsize));
189 tp->t_column = 0;
190 }
191 CLR(tp->t_state, TS_WOPEN);
192 splx(s);
193 return (0);
194 }
195
196 /*
197 * Handle close() on a tty line: flush and set to initial state,
198 * bumping generation number so that pending read/write calls
199 * can detect recycling of the tty.
200 */
201 int
ttyclose(struct tty * tp)202 ttyclose(struct tty *tp)
203 {
204 if (constty == tp)
205 constty = NULL;
206
207 ttyflush(tp, FREAD | FWRITE);
208
209 tp->t_gen++;
210 tp->t_pgrp = NULL;
211 if (tp->t_session)
212 SESSRELE(tp->t_session);
213 tp->t_session = NULL;
214 tp->t_state = 0;
215 return (0);
216 }
217
218 #define FLUSHQ(q) { \
219 if ((q)->c_cc) \
220 ndflush(q, (q)->c_cc); \
221 }
222
223 /* Is 'c' a line delimiter ("break" character)? */
224 #define TTBREAKC(c, lflag) \
225 ((c) == '\n' || (((c) == cc[VEOF] || (c) == cc[VEOL] || \
226 ((c) == cc[VEOL2] && (lflag & IEXTEN))) && (c) != _POSIX_VDISABLE))
227
228
229 /*
230 * Process input of a single character received on a tty. Returns 0 normally,
231 * 1 if a costly operation was reached.
232 */
233 int
ttyinput(int c,struct tty * tp)234 ttyinput(int c, struct tty *tp)
235 {
236 int iflag, lflag;
237 u_char *cc;
238 int i, error, ret = 0;
239 int s;
240
241 enqueue_randomness(tp->t_dev << 8 | c);
242 /*
243 * If receiver is not enabled, drop it.
244 */
245 if (!ISSET(tp->t_cflag, CREAD))
246 return (0);
247
248 /*
249 * If input is pending take it first.
250 */
251 lflag = tp->t_lflag;
252 s = spltty();
253 if (ISSET(lflag, PENDIN))
254 ttypend(tp);
255 splx(s);
256 /*
257 * Gather stats.
258 */
259 if (ISSET(lflag, ICANON)) {
260 ++tk_cancc;
261 ++tp->t_cancc;
262 } else {
263 ++tk_rawcc;
264 ++tp->t_rawcc;
265 }
266 ++tk_nin;
267
268 /* Handle exceptional conditions (break, parity, framing). */
269 cc = tp->t_cc;
270 iflag = tp->t_iflag;
271 if ((error = (ISSET(c, TTY_ERRORMASK))) != 0) {
272 CLR(c, TTY_ERRORMASK);
273 if (ISSET(error, TTY_FE) && !c) { /* Break. */
274 if (ISSET(iflag, IGNBRK))
275 return (0);
276 ttyflush(tp, FREAD | FWRITE);
277 if (ISSET(iflag, BRKINT)) {
278 pgsignal(tp->t_pgrp, SIGINT, 1);
279 goto endcase;
280 }
281 else if (ISSET(iflag, PARMRK))
282 goto parmrk;
283 } else if ((ISSET(error, TTY_PE) && ISSET(iflag, INPCK)) ||
284 ISSET(error, TTY_FE)) {
285 if (ISSET(iflag, IGNPAR))
286 goto endcase;
287 else if (ISSET(iflag, PARMRK)) {
288 parmrk: (void)putc(0377 | TTY_QUOTE, &tp->t_rawq);
289 if (ISSET(iflag, ISTRIP) || c != 0377)
290 (void)putc(0 | TTY_QUOTE, &tp->t_rawq);
291 (void)putc(c | TTY_QUOTE, &tp->t_rawq);
292 goto endcase;
293 } else
294 c = 0;
295 }
296 }
297 if (c == 0377 && !ISSET(iflag, ISTRIP) && ISSET(iflag, PARMRK))
298 goto parmrk;
299
300 /*
301 * In tandem mode, check high water mark.
302 */
303 if (ISSET(iflag, IXOFF) || ISSET(tp->t_cflag, CHWFLOW))
304 ttyblock(tp);
305 if (!ISSET(tp->t_state, TS_TYPEN) && ISSET(iflag, ISTRIP))
306 CLR(c, 0x80);
307 if (!ISSET(lflag, EXTPROC)) {
308 /*
309 * Check for literal nexting very first
310 */
311 if (ISSET(tp->t_state, TS_LNCH)) {
312 SET(c, TTY_QUOTE);
313 CLR(tp->t_state, TS_LNCH);
314 }
315 /*
316 * Scan for special characters. This code
317 * is really just a big case statement with
318 * non-constant cases. The bottom of the
319 * case statement is labeled ``endcase'', so goto
320 * it after a case match, or similar.
321 */
322
323 /*
324 * Control chars which aren't controlled
325 * by ICANON, ISIG, or IXON.
326 */
327 if (ISSET(lflag, IEXTEN)) {
328 if (CCEQ(cc[VLNEXT], c)) {
329 if (ISSET(lflag, ECHO)) {
330 if (ISSET(lflag, ECHOE)) {
331 (void)ttyoutput('^', tp);
332 (void)ttyoutput('\b', tp);
333 } else
334 ttyecho(c, tp);
335 }
336 SET(tp->t_state, TS_LNCH);
337 goto endcase;
338 }
339 if (CCEQ(cc[VDISCARD], c)) {
340 if (ISSET(lflag, FLUSHO))
341 CLR(tp->t_lflag, FLUSHO);
342 else {
343 ttyflush(tp, FWRITE);
344 ttyecho(c, tp);
345 if (tp->t_rawq.c_cc + tp->t_canq.c_cc)
346 ret = ttyretype(tp);
347 SET(tp->t_lflag, FLUSHO);
348 }
349 goto startoutput;
350 }
351 }
352 /*
353 * Signals.
354 */
355 if (ISSET(lflag, ISIG)) {
356 if (CCEQ(cc[VINTR], c) || CCEQ(cc[VQUIT], c)) {
357 if (!ISSET(lflag, NOFLSH))
358 ttyflush(tp, FREAD | FWRITE);
359 ttyecho(c, tp);
360 pgsignal(tp->t_pgrp,
361 CCEQ(cc[VINTR], c) ? SIGINT : SIGQUIT, 1);
362 goto endcase;
363 }
364 if (CCEQ(cc[VSUSP], c)) {
365 if (!ISSET(lflag, NOFLSH))
366 ttyflush(tp, FREAD);
367 ttyecho(c, tp);
368 pgsignal(tp->t_pgrp, SIGTSTP, 1);
369 goto endcase;
370 }
371 }
372 /*
373 * Handle start/stop characters.
374 */
375 if (ISSET(iflag, IXON)) {
376 if (CCEQ(cc[VSTOP], c)) {
377 if (!ISSET(tp->t_state, TS_TTSTOP)) {
378 SET(tp->t_state, TS_TTSTOP);
379 (*cdevsw[major(tp->t_dev)].d_stop)(tp,
380 0);
381 return (0);
382 }
383 if (!CCEQ(cc[VSTART], c))
384 return (0);
385 /*
386 * if VSTART == VSTOP then toggle
387 */
388 goto endcase;
389 }
390 if (CCEQ(cc[VSTART], c))
391 goto restartoutput;
392 }
393 /*
394 * IGNCR, ICRNL, & INLCR
395 */
396 if (c == '\r') {
397 if (ISSET(iflag, IGNCR))
398 goto endcase;
399 else if (ISSET(iflag, ICRNL))
400 c = '\n';
401 } else if (c == '\n' && ISSET(iflag, INLCR))
402 c = '\r';
403 }
404 if (!ISSET(tp->t_lflag, EXTPROC) && ISSET(lflag, ICANON)) {
405 /*
406 * From here on down canonical mode character
407 * processing takes place.
408 */
409 /*
410 * upper case or specials with IUCLC and XCASE
411 */
412 if (ISSET(lflag, XCASE) && ISSET(iflag, IUCLC)) {
413 if (ISSET(tp->t_state, TS_BKSL)) {
414 CLR(tp->t_state, TS_BKSL);
415 switch (c) {
416 case '\'':
417 c = '`';
418 break;
419 case '!':
420 c = '|';
421 break;
422 case '^':
423 c = '~';
424 break;
425 case '(':
426 c = '{';
427 break;
428 case ')':
429 c = '}';
430 break;
431 }
432 }
433 else if (c == '\\') {
434 SET(tp->t_state, TS_BKSL);
435 goto endcase;
436 }
437 else if (isupper(c))
438 c = tolower(c);
439 }
440 else if (ISSET(iflag, IUCLC) && isupper(c))
441 c = tolower(c);
442 /*
443 * erase (^H / ^?)
444 */
445 if (CCEQ(cc[VERASE], c)) {
446 if (tp->t_rawq.c_cc)
447 ret = ttyrub(unputc(&tp->t_rawq), tp);
448 goto endcase;
449 }
450 /*
451 * kill (^U)
452 */
453 if (CCEQ(cc[VKILL], c)) {
454 if (ISSET(lflag, ECHOKE) &&
455 tp->t_rawq.c_cc == tp->t_rocount &&
456 !ISSET(lflag, ECHOPRT)) {
457 while (tp->t_rawq.c_cc)
458 if (ttyrub(unputc(&tp->t_rawq), tp))
459 ret = 1;
460 } else {
461 ttyecho(c, tp);
462 if (ISSET(lflag, ECHOK) ||
463 ISSET(lflag, ECHOKE))
464 ttyecho('\n', tp);
465 FLUSHQ(&tp->t_rawq);
466 tp->t_rocount = 0;
467 }
468 CLR(tp->t_state, TS_LOCAL);
469 goto endcase;
470 }
471 /*
472 * word erase (^W)
473 */
474 if (CCEQ(cc[VWERASE], c) && ISSET(lflag, IEXTEN)) {
475 int alt = ISSET(lflag, ALTWERASE);
476 int ctype;
477
478 /*
479 * erase whitespace
480 */
481 while ((c = unputc(&tp->t_rawq)) == ' ' || c == '\t')
482 if (ttyrub(c, tp))
483 ret = 1;
484 if (c == -1)
485 goto endcase;
486 /*
487 * erase last char of word and remember the
488 * next chars type (for ALTWERASE)
489 */
490 if (ttyrub(c, tp))
491 ret = 1;
492 c = unputc(&tp->t_rawq);
493 if (c == -1)
494 goto endcase;
495 if (c == ' ' || c == '\t') {
496 (void)putc(c, &tp->t_rawq);
497 goto endcase;
498 }
499 ctype = ISALPHA(c);
500 /*
501 * erase rest of word
502 */
503 do {
504 if (ttyrub(c, tp))
505 ret = 1;
506 c = unputc(&tp->t_rawq);
507 if (c == -1)
508 goto endcase;
509 } while (c != ' ' && c != '\t' &&
510 (alt == 0 || ISALPHA(c) == ctype));
511 (void)putc(c, &tp->t_rawq);
512 goto endcase;
513 }
514 /*
515 * reprint line (^R)
516 */
517 if (CCEQ(cc[VREPRINT], c) && ISSET(lflag, IEXTEN)) {
518 ret = ttyretype(tp);
519 goto endcase;
520 }
521 /*
522 * ^T - kernel info and generate SIGINFO
523 */
524 if (CCEQ(cc[VSTATUS], c) && ISSET(lflag, IEXTEN)) {
525 if (ISSET(lflag, ISIG))
526 pgsignal(tp->t_pgrp, SIGINFO, 1);
527 if (!ISSET(lflag, NOKERNINFO))
528 ttyinfo(tp);
529 goto endcase;
530 }
531 }
532 /*
533 * Check for input buffer overflow
534 */
535 if (tp->t_rawq.c_cc + tp->t_canq.c_cc >= TTYHOG(tp)) {
536 if (ISSET(iflag, IMAXBEL)) {
537 if (tp->t_outq.c_cc < tp->t_hiwat)
538 (void)ttyoutput(CTRL('g'), tp);
539 } else
540 ttyflush(tp, FREAD | FWRITE);
541 goto endcase;
542 }
543 /*
544 * Put data char in q for user and
545 * wakeup on seeing a line delimiter.
546 */
547 if (putc(c, &tp->t_rawq) >= 0) {
548 if (!ISSET(lflag, ICANON)) {
549 ttwakeup(tp);
550 ttyecho(c, tp);
551 goto endcase;
552 }
553 if (TTBREAKC(c, lflag)) {
554 tp->t_rocount = 0;
555 catq(&tp->t_rawq, &tp->t_canq);
556 ttwakeup(tp);
557 } else if (tp->t_rocount++ == 0)
558 tp->t_rocol = tp->t_column;
559 if (ISSET(tp->t_state, TS_ERASE)) {
560 /*
561 * end of prterase \.../
562 */
563 CLR(tp->t_state, TS_ERASE);
564 (void)ttyoutput('/', tp);
565 }
566 i = tp->t_column;
567 ttyecho(c, tp);
568 if (CCEQ(cc[VEOF], c) && ISSET(lflag, ECHO)) {
569 /*
570 * Place the cursor over the '^' of the ^D.
571 */
572 i = min(2, tp->t_column - i);
573 while (i > 0) {
574 (void)ttyoutput('\b', tp);
575 i--;
576 }
577 }
578 }
579 endcase:
580 /*
581 * IXANY means allow any character to restart output.
582 */
583 if (ISSET(tp->t_state, TS_TTSTOP) &&
584 !ISSET(iflag, IXANY) && cc[VSTART] != cc[VSTOP])
585 return (ret);
586 restartoutput:
587 CLR(tp->t_lflag, FLUSHO);
588 CLR(tp->t_state, TS_TTSTOP);
589 startoutput:
590 ttstart(tp);
591 return (ret);
592 }
593
594 /*
595 * Output a single character on a tty, doing output processing
596 * as needed (expanding tabs, newline processing, etc.).
597 * Returns < 0 if succeeds, otherwise returns char to resend.
598 * Must be recursive.
599 */
600 int
ttyoutput(int c,struct tty * tp)601 ttyoutput(int c, struct tty *tp)
602 {
603 long oflag;
604 int col, notout, s, c2;
605
606 oflag = tp->t_oflag;
607 if (!ISSET(oflag, OPOST)) {
608 tk_nout++;
609 tp->t_outcc++;
610 if (!ISSET(tp->t_lflag, FLUSHO) && putc(c, &tp->t_outq))
611 return (c);
612 return (-1);
613 }
614 /*
615 * Do tab expansion if OXTABS is set. Special case if we external
616 * processing, we don't do the tab expansion because we'll probably
617 * get it wrong. If tab expansion needs to be done, let it happen
618 * externally.
619 */
620 CLR(c, ~TTY_CHARMASK);
621 if (c == '\t' &&
622 ISSET(oflag, OXTABS) && !ISSET(tp->t_lflag, EXTPROC)) {
623 c = 8 - (tp->t_column & 7);
624 if (ISSET(tp->t_lflag, FLUSHO)) {
625 notout = 0;
626 } else {
627 s = spltty(); /* Don't interrupt tabs. */
628 notout = b_to_q(" ", c, &tp->t_outq);
629 c -= notout;
630 tk_nout += c;
631 tp->t_outcc += c;
632 splx(s);
633 }
634 tp->t_column += c;
635 return (notout ? '\t' : -1);
636 }
637 if (c == CEOT && ISSET(oflag, ONOEOT))
638 return (-1);
639
640 /*
641 * Newline translation: if ONLCR is set,
642 * translate newline into "\r\n". If OCRNL
643 * is set, translate '\r' into '\n'.
644 */
645 if (c == '\n' && ISSET(tp->t_oflag, ONLCR)) {
646 tk_nout++;
647 tp->t_outcc++;
648 if (!ISSET(tp->t_lflag, FLUSHO) && putc('\r', &tp->t_outq))
649 return (c);
650 tp->t_column = 0;
651 }
652 else if (c == '\r' && ISSET(tp->t_oflag, OCRNL))
653 c = '\n';
654
655 if (ISSET(tp->t_oflag, OLCUC) && islower(c))
656 c = toupper(c);
657 else if (ISSET(tp->t_oflag, OLCUC) && ISSET(tp->t_lflag, XCASE)) {
658 c2 = c;
659 switch (c) {
660 case '`':
661 c2 = '\'';
662 break;
663 case '|':
664 c2 = '!';
665 break;
666 case '~':
667 c2 = '^';
668 break;
669 case '{':
670 c2 = '(';
671 break;
672 case '}':
673 c2 = ')';
674 break;
675 }
676 if (c == '\\' || isupper(c) || c != c2) {
677 tk_nout++;
678 tp->t_outcc++;
679 if (putc('\\', &tp->t_outq))
680 return (c);
681 c = c2;
682 }
683 }
684 if (ISSET(tp->t_oflag, ONOCR) && c == '\r' && tp->t_column == 0)
685 return (-1);
686
687 tk_nout++;
688 tp->t_outcc++;
689 if (!ISSET(tp->t_lflag, FLUSHO) && putc(c, &tp->t_outq))
690 return (c);
691
692 col = tp->t_column;
693 switch (CCLASS(c)) {
694 case BACKSPACE:
695 if (col > 0)
696 --col;
697 break;
698 case CONTROL:
699 break;
700 case NEWLINE:
701 if (ISSET(tp->t_oflag, ONLRET) || ISSET(tp->t_oflag, OCRNL))
702 col = 0;
703 break;
704 case RETURN:
705 col = 0;
706 break;
707 case ORDINARY:
708 ++col;
709 break;
710 case TAB:
711 col = (col + 8) & ~7;
712 break;
713 }
714 tp->t_column = col;
715 return (-1);
716 }
717
718 /*
719 * Ioctls for all tty devices. Called after line-discipline specific ioctl
720 * has been called to do discipline-specific functions and/or reject any
721 * of these ioctl commands.
722 */
723 int
ttioctl(struct tty * tp,u_long cmd,caddr_t data,int flag,struct proc * p)724 ttioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, struct proc *p)
725 {
726 extern int nlinesw;
727 struct process *pr = p->p_p;
728 int s, error;
729
730 /* If the ioctl involves modification, hang if in the background. */
731 switch (cmd) {
732 case FIOSETOWN:
733 case TIOCFLUSH:
734 case TIOCDRAIN:
735 case TIOCSBRK:
736 case TIOCCBRK:
737 case TIOCSETA:
738 case TIOCSETD:
739 case TIOCSETAF:
740 case TIOCSETAW:
741 case TIOCSPGRP:
742 case TIOCSTAT:
743 case TIOCSWINSZ:
744 while (isbackground(pr, tp) &&
745 (pr->ps_flags & PS_PPWAIT) == 0 &&
746 !sigismasked(p, SIGTTOU)) {
747 if (pr->ps_pgrp->pg_jobc == 0)
748 return (EIO);
749 pgsignal(pr->ps_pgrp, SIGTTOU, 1);
750 error = ttysleep(tp, &lbolt, TTOPRI | PCATCH,
751 ttybg);
752 if (error)
753 return (error);
754 }
755 break;
756 }
757
758 switch (cmd) { /* Process the ioctl. */
759 case FIOASYNC: /* set/clear async i/o */
760 s = spltty();
761 if (*(int *)data)
762 SET(tp->t_state, TS_ASYNC);
763 else
764 CLR(tp->t_state, TS_ASYNC);
765 splx(s);
766 break;
767 case FIONREAD: /* get # bytes to read */
768 s = spltty();
769 *(int *)data = ttnread(tp);
770 splx(s);
771 break;
772 case TIOCEXCL: /* set exclusive use of tty */
773 s = spltty();
774 SET(tp->t_state, TS_XCLUDE);
775 splx(s);
776 break;
777 case TIOCFLUSH: { /* flush buffers */
778 int flags = *(int *)data;
779
780 if (flags == 0)
781 flags = FREAD | FWRITE;
782 else
783 flags &= FREAD | FWRITE;
784 ttyflush(tp, flags);
785 break;
786 }
787 case TIOCCONS: { /* become virtual console */
788 if (*(int *)data) {
789 struct nameidata nid;
790
791 if (constty != NULL && constty != tp &&
792 ISSET(constty->t_state, TS_CARR_ON | TS_ISOPEN) ==
793 (TS_CARR_ON | TS_ISOPEN))
794 return (EBUSY);
795
796 /* ensure user can open the real console */
797 NDINIT(&nid, LOOKUP, FOLLOW, UIO_SYSSPACE, "/dev/console", p);
798 nid.ni_pledge = PLEDGE_RPATH | PLEDGE_WPATH;
799 nid.ni_unveil = UNVEIL_READ | UNVEIL_WRITE;
800 error = namei(&nid);
801 if (error)
802 return (error);
803 vn_lock(nid.ni_vp, LK_EXCLUSIVE | LK_RETRY);
804 error = VOP_ACCESS(nid.ni_vp, VREAD, p->p_ucred, p);
805 VOP_UNLOCK(nid.ni_vp);
806 vrele(nid.ni_vp);
807 if (error)
808 return (error);
809
810 constty = tp;
811 } else if (tp == constty)
812 constty = NULL;
813 break;
814 }
815 case TIOCDRAIN: /* wait till output drained */
816 if ((error = ttywait(tp)) != 0)
817 return (error);
818 break;
819 case TIOCGETA: { /* get termios struct */
820 struct termios *t = (struct termios *)data;
821
822 memcpy(t, &tp->t_termios, sizeof(struct termios));
823 break;
824 }
825 case TIOCGETD: /* get line discipline */
826 *(int *)data = tp->t_line;
827 break;
828 case TIOCGWINSZ: /* get window size */
829 *(struct winsize *)data = tp->t_winsize;
830 break;
831 case TIOCGTSTAMP:
832 s = spltty();
833 *(struct timeval *)data = tp->t_tv;
834 splx(s);
835 break;
836 case FIOGETOWN: /* get pgrp of tty */
837 if (!isctty(pr, tp) && suser(p))
838 return (ENOTTY);
839 *(int *)data = tp->t_pgrp ? -tp->t_pgrp->pg_id : 0;
840 break;
841 case TIOCGPGRP: /* get pgrp of tty */
842 if (!isctty(pr, tp) && suser(p))
843 return (ENOTTY);
844 *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
845 break;
846 case TIOCGSID: /* get sid of tty */
847 if (!isctty(pr, tp))
848 return (ENOTTY);
849 *(int *)data = tp->t_session->s_leader->ps_pid;
850 break;
851 case TIOCNXCL: /* reset exclusive use of tty */
852 s = spltty();
853 CLR(tp->t_state, TS_XCLUDE);
854 splx(s);
855 break;
856 case TIOCOUTQ: /* output queue size */
857 *(int *)data = tp->t_outq.c_cc;
858 break;
859 case TIOCSETA: /* set termios struct */
860 case TIOCSETAW: /* drain output, set */
861 case TIOCSETAF: { /* drn out, fls in, set */
862 struct termios *t = (struct termios *)data;
863
864 s = spltty();
865 if (cmd == TIOCSETAW || cmd == TIOCSETAF) {
866 if ((error = ttywait(tp)) != 0) {
867 splx(s);
868 return (error);
869 }
870 if (cmd == TIOCSETAF)
871 ttyflush(tp, FREAD);
872 }
873 if (!ISSET(t->c_cflag, CIGNORE)) {
874 /*
875 * Some minor validation is necessary.
876 */
877 if (t->c_ispeed < 0 || t->c_ospeed < 0) {
878 splx(s);
879 return (EINVAL);
880 }
881 /*
882 * Set device hardware.
883 */
884 if (tp->t_param && (error = (*tp->t_param)(tp, t))) {
885 splx(s);
886 return (error);
887 } else {
888 if (!ISSET(tp->t_state, TS_CARR_ON) &&
889 ISSET(tp->t_cflag, CLOCAL) &&
890 !ISSET(t->c_cflag, CLOCAL)) {
891 CLR(tp->t_state, TS_ISOPEN);
892 SET(tp->t_state, TS_WOPEN);
893 ttwakeup(tp);
894 }
895 tp->t_cflag = t->c_cflag;
896 tp->t_ispeed = t->c_ispeed;
897 tp->t_ospeed = t->c_ospeed;
898 if (t->c_ospeed == 0 && tp->t_session &&
899 tp->t_session->s_leader)
900 prsignal(tp->t_session->s_leader,
901 SIGHUP);
902 }
903 ttsetwater(tp);
904 }
905 if (cmd != TIOCSETAF) {
906 if (ISSET(t->c_lflag, ICANON) !=
907 ISSET(tp->t_lflag, ICANON)) {
908 if (ISSET(t->c_lflag, ICANON)) {
909 SET(tp->t_lflag, PENDIN);
910 ttwakeup(tp);
911 } else {
912 struct clist tq;
913
914 catq(&tp->t_rawq, &tp->t_canq);
915 tq = tp->t_rawq;
916 tp->t_rawq = tp->t_canq;
917 tp->t_canq = tq;
918 CLR(tp->t_lflag, PENDIN);
919 }
920 }
921 }
922 tp->t_iflag = t->c_iflag;
923 tp->t_oflag = t->c_oflag;
924 /*
925 * Make the EXTPROC bit read only.
926 */
927 if (ISSET(tp->t_lflag, EXTPROC))
928 SET(t->c_lflag, EXTPROC);
929 else
930 CLR(t->c_lflag, EXTPROC);
931 tp->t_lflag = t->c_lflag | ISSET(tp->t_lflag, PENDIN);
932 memcpy(tp->t_cc, t->c_cc, sizeof(t->c_cc));
933 splx(s);
934 break;
935 }
936 case TIOCSETD: { /* set line discipline */
937 int t = *(int *)data;
938 dev_t device = tp->t_dev;
939
940 if ((u_int)t >= nlinesw)
941 return (ENXIO);
942 if (t != tp->t_line) {
943 s = spltty();
944 (*linesw[tp->t_line].l_close)(tp, flag, p);
945 error = (*linesw[t].l_open)(device, tp, p);
946 if (error) {
947 (*linesw[tp->t_line].l_open)(device, tp, p);
948 splx(s);
949 return (error);
950 }
951 tp->t_line = t;
952 splx(s);
953 }
954 break;
955 }
956 case TIOCSTART: /* start output, like ^Q */
957 s = spltty();
958 if (ISSET(tp->t_state, TS_TTSTOP) ||
959 ISSET(tp->t_lflag, FLUSHO)) {
960 CLR(tp->t_lflag, FLUSHO);
961 CLR(tp->t_state, TS_TTSTOP);
962 ttstart(tp);
963 }
964 splx(s);
965 break;
966 case TIOCSTOP: /* stop output, like ^S */
967 s = spltty();
968 if (!ISSET(tp->t_state, TS_TTSTOP)) {
969 SET(tp->t_state, TS_TTSTOP);
970 (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
971 }
972 splx(s);
973 break;
974 case TIOCSCTTY: /* become controlling tty */
975 /* Session ctty vnode pointer set in vnode layer. */
976 if (!SESS_LEADER(pr) ||
977 ((pr->ps_session->s_ttyvp || tp->t_session) &&
978 (tp->t_session != pr->ps_session)))
979 return (EPERM);
980 if (tp->t_session)
981 SESSRELE(tp->t_session);
982 SESSHOLD(pr->ps_session);
983 tp->t_session = pr->ps_session;
984 tp->t_pgrp = pr->ps_pgrp;
985 pr->ps_session->s_ttyp = tp;
986 atomic_setbits_int(&pr->ps_flags, PS_CONTROLT);
987 break;
988 case FIOSETOWN: { /* set pgrp of tty */
989 struct pgrp *pgrp;
990 struct process *pr1;
991 pid_t pgid = *(int *)data;
992
993 if (!isctty(pr, tp))
994 return (ENOTTY);
995 if (pgid < 0) {
996 pgrp = pgfind(-pgid);
997 } else {
998 pr1 = prfind(pgid);
999 if (pr1 == NULL)
1000 return (ESRCH);
1001 pgrp = pr1->ps_pgrp;
1002 }
1003 if (pgrp == NULL)
1004 return (EINVAL);
1005 else if (pgrp->pg_session != pr->ps_session)
1006 return (EPERM);
1007 tp->t_pgrp = pgrp;
1008 break;
1009 }
1010 case TIOCSPGRP: { /* set pgrp of tty */
1011 struct pgrp *pgrp = pgfind(*(int *)data);
1012
1013 if (!isctty(pr, tp))
1014 return (ENOTTY);
1015 else if (pgrp == NULL)
1016 return (EINVAL);
1017 else if (pgrp->pg_session != pr->ps_session)
1018 return (EPERM);
1019 tp->t_pgrp = pgrp;
1020 break;
1021 }
1022 case TIOCSTAT: /* get load avg stats */
1023 ttyinfo(tp);
1024 break;
1025 case TIOCSWINSZ: /* set window size */
1026 if (bcmp((caddr_t)&tp->t_winsize, data,
1027 sizeof (struct winsize))) {
1028 tp->t_winsize = *(struct winsize *)data;
1029 pgsignal(tp->t_pgrp, SIGWINCH, 1);
1030 }
1031 break;
1032 case TIOCSTSTAMP: {
1033 struct tstamps *ts = (struct tstamps *)data;
1034
1035 s = spltty();
1036 CLR(tp->t_flags, TS_TSTAMPDCDSET);
1037 CLR(tp->t_flags, TS_TSTAMPCTSSET);
1038 CLR(tp->t_flags, TS_TSTAMPDCDCLR);
1039 CLR(tp->t_flags, TS_TSTAMPCTSCLR);
1040 if (ISSET(ts->ts_set, TIOCM_CAR))
1041 SET(tp->t_flags, TS_TSTAMPDCDSET);
1042 if (ISSET(ts->ts_set, TIOCM_CTS))
1043 SET(tp->t_flags, TS_TSTAMPCTSSET);
1044 if (ISSET(ts->ts_clr, TIOCM_CAR))
1045 SET(tp->t_flags, TS_TSTAMPDCDCLR);
1046 if (ISSET(ts->ts_clr, TIOCM_CTS))
1047 SET(tp->t_flags, TS_TSTAMPCTSCLR);
1048 splx(s);
1049 break;
1050 }
1051 default:
1052 return (-1);
1053 }
1054 return (0);
1055 }
1056
1057 const struct filterops ttyread_filtops = {
1058 .f_flags = FILTEROP_ISFD,
1059 .f_attach = NULL,
1060 .f_detach = filt_ttyrdetach,
1061 .f_event = filt_ttyread,
1062 };
1063
1064 const struct filterops ttywrite_filtops = {
1065 .f_flags = FILTEROP_ISFD,
1066 .f_attach = NULL,
1067 .f_detach = filt_ttywdetach,
1068 .f_event = filt_ttywrite,
1069 };
1070
1071 const struct filterops ttyexcept_filtops = {
1072 .f_flags = FILTEROP_ISFD,
1073 .f_attach = NULL,
1074 .f_detach = filt_ttyrdetach,
1075 .f_event = filt_ttyexcept,
1076 };
1077
1078 int
ttkqfilter(dev_t dev,struct knote * kn)1079 ttkqfilter(dev_t dev, struct knote *kn)
1080 {
1081 struct tty *tp = (*cdevsw[major(dev)].d_tty)(dev);
1082 struct klist *klist;
1083 int s;
1084
1085 switch (kn->kn_filter) {
1086 case EVFILT_READ:
1087 klist = &tp->t_rsel.si_note;
1088 kn->kn_fop = &ttyread_filtops;
1089 break;
1090 case EVFILT_WRITE:
1091 klist = &tp->t_wsel.si_note;
1092 kn->kn_fop = &ttywrite_filtops;
1093 break;
1094 case EVFILT_EXCEPT:
1095 if (kn->kn_flags & __EV_SELECT) {
1096 /* Prevent triggering exceptfds. */
1097 return (EPERM);
1098 }
1099 if ((kn->kn_flags & __EV_POLL) == 0) {
1100 /* Disallow usage through kevent(2). */
1101 return (EINVAL);
1102 }
1103 klist = &tp->t_rsel.si_note;
1104 kn->kn_fop = &ttyexcept_filtops;
1105 break;
1106 default:
1107 return (EINVAL);
1108 }
1109
1110 kn->kn_hook = tp;
1111
1112 s = spltty();
1113 klist_insert_locked(klist, kn);
1114 splx(s);
1115
1116 return (0);
1117 }
1118
1119 void
filt_ttyrdetach(struct knote * kn)1120 filt_ttyrdetach(struct knote *kn)
1121 {
1122 struct tty *tp = kn->kn_hook;
1123 int s;
1124
1125 s = spltty();
1126 klist_remove_locked(&tp->t_rsel.si_note, kn);
1127 splx(s);
1128 }
1129
1130 int
filt_ttyread(struct knote * kn,long hint)1131 filt_ttyread(struct knote *kn, long hint)
1132 {
1133 struct tty *tp = kn->kn_hook;
1134 int active, s;
1135
1136 s = spltty();
1137 kn->kn_data = ttnread(tp);
1138 active = (kn->kn_data > 0);
1139 if (!ISSET(tp->t_cflag, CLOCAL) && !ISSET(tp->t_state, TS_CARR_ON)) {
1140 kn->kn_flags |= EV_EOF;
1141 if (kn->kn_flags & __EV_POLL)
1142 kn->kn_flags |= __EV_HUP;
1143 active = 1;
1144 } else {
1145 kn->kn_flags &= ~(EV_EOF | __EV_HUP);
1146 }
1147 splx(s);
1148 return (active);
1149 }
1150
1151 void
filt_ttywdetach(struct knote * kn)1152 filt_ttywdetach(struct knote *kn)
1153 {
1154 struct tty *tp = kn->kn_hook;
1155 int s;
1156
1157 s = spltty();
1158 klist_remove_locked(&tp->t_wsel.si_note, kn);
1159 splx(s);
1160 }
1161
1162 int
filt_ttywrite(struct knote * kn,long hint)1163 filt_ttywrite(struct knote *kn, long hint)
1164 {
1165 struct tty *tp = kn->kn_hook;
1166 int active, s;
1167
1168 s = spltty();
1169 kn->kn_data = tp->t_outq.c_cn - tp->t_outq.c_cc;
1170 active = (tp->t_outq.c_cc <= tp->t_lowat);
1171
1172 /* Write-side HUP condition is only for poll(2) and select(2). */
1173 if (kn->kn_flags & (__EV_POLL | __EV_SELECT)) {
1174 if (!ISSET(tp->t_cflag, CLOCAL) &&
1175 !ISSET(tp->t_state, TS_CARR_ON)) {
1176 kn->kn_flags |= __EV_HUP;
1177 active = 1;
1178 } else {
1179 kn->kn_flags &= ~__EV_HUP;
1180 }
1181 }
1182 splx(s);
1183 return (active);
1184 }
1185
1186 int
filt_ttyexcept(struct knote * kn,long hint)1187 filt_ttyexcept(struct knote *kn, long hint)
1188 {
1189 struct tty *tp = kn->kn_hook;
1190 int active = 0;
1191 int s;
1192
1193 s = spltty();
1194 if (kn->kn_flags & __EV_POLL) {
1195 if (!ISSET(tp->t_cflag, CLOCAL) &&
1196 !ISSET(tp->t_state, TS_CARR_ON)) {
1197 kn->kn_flags |= __EV_HUP;
1198 active = 1;
1199 } else {
1200 kn->kn_flags &= ~__EV_HUP;
1201 }
1202 }
1203 splx(s);
1204 return (active);
1205 }
1206
1207 static int
ttnread(struct tty * tp)1208 ttnread(struct tty *tp)
1209 {
1210 int nread;
1211
1212 splassert(IPL_TTY);
1213
1214 if (ISSET(tp->t_lflag, PENDIN))
1215 ttypend(tp);
1216 nread = tp->t_canq.c_cc;
1217 if (!ISSET(tp->t_lflag, ICANON)) {
1218 nread += tp->t_rawq.c_cc;
1219 if (nread < tp->t_cc[VMIN] && !tp->t_cc[VTIME])
1220 nread = 0;
1221 }
1222 return (nread);
1223 }
1224
1225 /*
1226 * Wait for output to drain, or if this times out, flush it.
1227 */
1228 int
ttywait_nsec(struct tty * tp,uint64_t nsecs)1229 ttywait_nsec(struct tty *tp, uint64_t nsecs)
1230 {
1231 int error, s;
1232
1233 error = 0;
1234 s = spltty();
1235 while ((tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)) &&
1236 (ISSET(tp->t_state, TS_CARR_ON) || ISSET(tp->t_cflag, CLOCAL)) &&
1237 tp->t_oproc) {
1238 (*tp->t_oproc)(tp);
1239 if ((tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)) &&
1240 (ISSET(tp->t_state, TS_CARR_ON) || ISSET(tp->t_cflag, CLOCAL))
1241 && tp->t_oproc) {
1242 SET(tp->t_state, TS_ASLEEP);
1243 error = ttysleep_nsec(tp, &tp->t_outq, TTOPRI | PCATCH,
1244 ttyout, nsecs);
1245 if (error == EWOULDBLOCK)
1246 ttyflush(tp, FWRITE);
1247 if (error)
1248 break;
1249 } else
1250 break;
1251 }
1252 splx(s);
1253 return (error);
1254 }
1255
1256 int
ttywait(struct tty * tp)1257 ttywait(struct tty *tp)
1258 {
1259 return (ttywait_nsec(tp, INFSLP));
1260 }
1261
1262 /*
1263 * Flush if successfully wait.
1264 */
1265 int
ttywflush(struct tty * tp)1266 ttywflush(struct tty *tp)
1267 {
1268 int error;
1269
1270 error = ttywait_nsec(tp, SEC_TO_NSEC(5));
1271 if (error == 0 || error == EWOULDBLOCK)
1272 ttyflush(tp, FREAD);
1273 return (error);
1274 }
1275
1276 /*
1277 * Flush tty read and/or write queues, notifying anyone waiting.
1278 */
1279 void
ttyflush(struct tty * tp,int rw)1280 ttyflush(struct tty *tp, int rw)
1281 {
1282 int s;
1283
1284 s = spltty();
1285 if (rw & FREAD) {
1286 FLUSHQ(&tp->t_canq);
1287 FLUSHQ(&tp->t_rawq);
1288 tp->t_rocount = 0;
1289 tp->t_rocol = 0;
1290 CLR(tp->t_state, TS_LOCAL);
1291 ttyunblock(tp);
1292 ttwakeup(tp);
1293 }
1294 if (rw & FWRITE) {
1295 CLR(tp->t_state, TS_TTSTOP);
1296 (*cdevsw[major(tp->t_dev)].d_stop)(tp, rw);
1297 FLUSHQ(&tp->t_outq);
1298 wakeup((caddr_t)&tp->t_outq);
1299 selwakeup(&tp->t_wsel);
1300 }
1301 splx(s);
1302 }
1303
1304 /*
1305 * Copy in the default termios characters.
1306 */
1307 void
ttychars(struct tty * tp)1308 ttychars(struct tty *tp)
1309 {
1310
1311 memcpy(tp->t_cc, ttydefchars, sizeof(ttydefchars));
1312 }
1313
1314 /*
1315 * Send stop character on input overflow.
1316 */
1317 static void
ttyblock(struct tty * tp)1318 ttyblock(struct tty *tp)
1319 {
1320 int total;
1321
1322 total = tp->t_rawq.c_cc + tp->t_canq.c_cc;
1323 if (tp->t_rawq.c_cc > TTYHOG(tp)) {
1324 ttyflush(tp, FREAD | FWRITE);
1325 CLR(tp->t_state, TS_TBLOCK);
1326 }
1327 /*
1328 * Block further input iff: current input > threshold
1329 * AND input is available to user program.
1330 */
1331 if ((total >= TTYHOG(tp) / 2 &&
1332 !ISSET(tp->t_state, TS_TBLOCK) &&
1333 !ISSET(tp->t_lflag, ICANON)) || tp->t_canq.c_cc > 0) {
1334 if (ISSET(tp->t_iflag, IXOFF) &&
1335 tp->t_cc[VSTOP] != _POSIX_VDISABLE &&
1336 putc(tp->t_cc[VSTOP], &tp->t_outq) == 0) {
1337 SET(tp->t_state, TS_TBLOCK);
1338 ttstart(tp);
1339 }
1340 /* Try to block remote output via hardware flow control. */
1341 if (ISSET(tp->t_cflag, CHWFLOW) && tp->t_hwiflow &&
1342 (*tp->t_hwiflow)(tp, 1) != 0)
1343 SET(tp->t_state, TS_TBLOCK);
1344 }
1345 }
1346
1347 void
ttrstrt(void * arg)1348 ttrstrt(void *arg)
1349 {
1350 struct tty *tp = (struct tty *)arg;
1351 int s;
1352
1353 #ifdef DIAGNOSTIC
1354 if (tp == NULL)
1355 panic("ttrstrt");
1356 #endif
1357 s = spltty();
1358 CLR(tp->t_state, TS_TIMEOUT);
1359 ttstart(tp);
1360 splx(s);
1361 }
1362
1363 int
ttstart(struct tty * tp)1364 ttstart(struct tty *tp)
1365 {
1366
1367 if (tp->t_oproc != NULL) /* XXX: Kludge for pty. */
1368 (*tp->t_oproc)(tp);
1369 return (0);
1370 }
1371
1372 /*
1373 * "close" a line discipline
1374 */
1375 int
ttylclose(struct tty * tp,int flag,struct proc * p)1376 ttylclose(struct tty *tp, int flag, struct proc *p)
1377 {
1378
1379 if (flag & FNONBLOCK)
1380 ttyflush(tp, FREAD | FWRITE);
1381 else
1382 ttywflush(tp);
1383 return (0);
1384 }
1385
1386 /*
1387 * Handle modem control transition on a tty.
1388 * Flag indicates new state of carrier.
1389 * Returns 0 if the line should be turned off, otherwise 1.
1390 */
1391 int
ttymodem(struct tty * tp,int flag)1392 ttymodem(struct tty *tp, int flag)
1393 {
1394
1395 if (!ISSET(tp->t_state, TS_WOPEN) && ISSET(tp->t_cflag, MDMBUF)) {
1396 /*
1397 * MDMBUF: do flow control according to carrier flag
1398 */
1399 if (flag) {
1400 CLR(tp->t_state, TS_TTSTOP);
1401 ttstart(tp);
1402 } else if (!ISSET(tp->t_state, TS_TTSTOP)) {
1403 SET(tp->t_state, TS_TTSTOP);
1404 (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
1405 }
1406 } else if (flag == 0) {
1407 /*
1408 * Lost carrier.
1409 */
1410 CLR(tp->t_state, TS_CARR_ON);
1411 if (ISSET(tp->t_state, TS_ISOPEN) &&
1412 !ISSET(tp->t_cflag, CLOCAL)) {
1413 if (tp->t_session && tp->t_session->s_leader)
1414 prsignal(tp->t_session->s_leader, SIGHUP);
1415 ttyflush(tp, FREAD | FWRITE);
1416 return (0);
1417 }
1418 } else {
1419 /*
1420 * Carrier now on.
1421 */
1422 SET(tp->t_state, TS_CARR_ON);
1423 ttwakeup(tp);
1424 }
1425 return (1);
1426 }
1427
1428 /*
1429 * Default modem control routine (for other line disciplines).
1430 * Return argument flag, to turn off device on carrier drop.
1431 */
1432 int
nullmodem(struct tty * tp,int flag)1433 nullmodem(struct tty *tp, int flag)
1434 {
1435
1436 if (flag)
1437 SET(tp->t_state, TS_CARR_ON);
1438 else {
1439 CLR(tp->t_state, TS_CARR_ON);
1440 if (ISSET(tp->t_state, TS_ISOPEN) &&
1441 !ISSET(tp->t_cflag, CLOCAL)) {
1442 if (tp->t_session && tp->t_session->s_leader)
1443 prsignal(tp->t_session->s_leader, SIGHUP);
1444 ttyflush(tp, FREAD | FWRITE);
1445 return (0);
1446 }
1447 }
1448 return (1);
1449 }
1450
1451 /*
1452 * Reinput pending characters after state switch
1453 * call at spltty().
1454 */
1455 void
ttypend(struct tty * tp)1456 ttypend(struct tty *tp)
1457 {
1458 struct clist tq;
1459 int c;
1460
1461 splassert(IPL_TTY);
1462
1463 CLR(tp->t_lflag, PENDIN);
1464 SET(tp->t_state, TS_TYPEN);
1465 tq = tp->t_rawq;
1466 tp->t_rawq.c_cc = 0;
1467 tp->t_rawq.c_cf = tp->t_rawq.c_cl = NULL;
1468 while ((c = getc(&tq)) >= 0)
1469 ttyinput(c, tp);
1470 CLR(tp->t_state, TS_TYPEN);
1471 }
1472
1473 void ttvtimeout(void *);
1474
1475 void
ttvtimeout(void * arg)1476 ttvtimeout(void *arg)
1477 {
1478 struct tty *tp = (struct tty *)arg;
1479
1480 wakeup(&tp->t_rawq);
1481 }
1482
1483 /*
1484 * Process a read call on a tty device.
1485 */
1486 int
ttread(struct tty * tp,struct uio * uio,int flag)1487 ttread(struct tty *tp, struct uio *uio, int flag)
1488 {
1489 struct timeout *stime = NULL;
1490 struct proc *p = curproc;
1491 struct process *pr = p->p_p;
1492 int s, first, error = 0;
1493 u_char *cc = tp->t_cc;
1494 struct clist *qp;
1495 int last_cc = 0;
1496 long lflag;
1497 int c;
1498
1499 loop: lflag = tp->t_lflag;
1500 s = spltty();
1501 /*
1502 * take pending input first
1503 */
1504 if (ISSET(lflag, PENDIN))
1505 ttypend(tp);
1506 splx(s);
1507
1508 /*
1509 * Hang process if it's in the background.
1510 */
1511 if (isbackground(pr, tp)) {
1512 if (sigismasked(p, SIGTTIN) ||
1513 pr->ps_flags & PS_PPWAIT || pr->ps_pgrp->pg_jobc == 0) {
1514 error = EIO;
1515 goto out;
1516 }
1517 pgsignal(pr->ps_pgrp, SIGTTIN, 1);
1518 error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, ttybg);
1519 if (error)
1520 goto out;
1521 goto loop;
1522 }
1523
1524 s = spltty();
1525 if (!ISSET(lflag, ICANON)) {
1526 int min = cc[VMIN];
1527 int time = cc[VTIME] * 100; /* tenths of a second (ms) */
1528
1529 qp = &tp->t_rawq;
1530 /*
1531 * Check each of the four combinations.
1532 * (min > 0 && time == 0) is the normal read case.
1533 * It should be fairly efficient, so we check that and its
1534 * companion case (min == 0 && time == 0) first.
1535 */
1536 if (time == 0) {
1537 if (qp->c_cc < min)
1538 goto sleep;
1539 goto read;
1540 }
1541 if (min > 0) {
1542 if (qp->c_cc <= 0)
1543 goto sleep;
1544 if (qp->c_cc >= min)
1545 goto read;
1546 if (stime == NULL) {
1547 alloc_timer:
1548 stime = malloc(sizeof(*stime), M_TEMP, M_WAITOK);
1549 timeout_set(stime, ttvtimeout, tp);
1550 timeout_add_msec(stime, time);
1551 } else if (qp->c_cc > last_cc) {
1552 /* got a character, restart timer */
1553 timeout_add_msec(stime, time);
1554 }
1555 } else { /* min == 0 */
1556 if (qp->c_cc > 0)
1557 goto read;
1558 if (stime == NULL) {
1559 goto alloc_timer;
1560 }
1561 }
1562 last_cc = qp->c_cc;
1563 if (stime && !timeout_triggered(stime)) {
1564 goto sleep;
1565 }
1566 } else if ((qp = &tp->t_canq)->c_cc <= 0) {
1567 int carrier;
1568
1569 sleep:
1570 /*
1571 * If there is no input, sleep on rawq
1572 * awaiting hardware receipt and notification.
1573 * If we have data, we don't need to check for carrier.
1574 */
1575 carrier = ISSET(tp->t_state, TS_CARR_ON) ||
1576 ISSET(tp->t_cflag, CLOCAL);
1577 if (!carrier && ISSET(tp->t_state, TS_ISOPEN)) {
1578 splx(s);
1579 error = 0;
1580 goto out;
1581 }
1582 if (flag & IO_NDELAY) {
1583 splx(s);
1584 error = EWOULDBLOCK;
1585 goto out;
1586 }
1587 error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH,
1588 carrier ? ttyin : ttopen);
1589 splx(s);
1590 if (stime && timeout_triggered(stime))
1591 error = EWOULDBLOCK;
1592 if (cc[VMIN] == 0 && error == EWOULDBLOCK) {
1593 error = 0;
1594 goto out;
1595 }
1596 if (error && error != EWOULDBLOCK)
1597 goto out;
1598 error = 0;
1599 goto loop;
1600 }
1601 read:
1602 splx(s);
1603
1604 /*
1605 * Input present, check for input mapping and processing.
1606 */
1607 first = 1;
1608 while ((c = getc(qp)) >= 0) {
1609 /*
1610 * delayed suspend (^Y)
1611 */
1612 if (CCEQ(cc[VDSUSP], c) &&
1613 ISSET(lflag, IEXTEN | ISIG) == (IEXTEN | ISIG)) {
1614 pgsignal(tp->t_pgrp, SIGTSTP, 1);
1615 if (first) {
1616 error = ttysleep(tp, &lbolt, TTIPRI | PCATCH,
1617 ttybg);
1618 if (error)
1619 break;
1620 goto loop;
1621 }
1622 break;
1623 }
1624 /*
1625 * Interpret EOF only in canonical mode.
1626 */
1627 if (CCEQ(cc[VEOF], c) && ISSET(lflag, ICANON))
1628 break;
1629 /*
1630 * Give user character.
1631 */
1632 error = ureadc(c, uio);
1633 if (error)
1634 break;
1635 if (uio->uio_resid == 0)
1636 break;
1637 /*
1638 * In canonical mode check for a "break character"
1639 * marking the end of a "line of input".
1640 */
1641 if (ISSET(lflag, ICANON) && TTBREAKC(c, lflag))
1642 break;
1643 first = 0;
1644 }
1645 /*
1646 * Look to unblock output now that (presumably)
1647 * the input queue has gone down.
1648 */
1649 s = spltty();
1650 if (tp->t_rawq.c_cc < TTYHOG(tp)/5)
1651 ttyunblock(tp);
1652 splx(s);
1653
1654 out:
1655 if (stime) {
1656 timeout_del(stime);
1657 free(stime, M_TEMP, sizeof(*stime));
1658 }
1659 return (error);
1660 }
1661
1662 /* Call at spltty */
1663 void
ttyunblock(struct tty * tp)1664 ttyunblock(struct tty *tp)
1665 {
1666 u_char *cc = tp->t_cc;
1667
1668 splassert(IPL_TTY);
1669
1670 if (ISSET(tp->t_state, TS_TBLOCK)) {
1671 if (ISSET(tp->t_iflag, IXOFF) &&
1672 cc[VSTART] != _POSIX_VDISABLE &&
1673 putc(cc[VSTART], &tp->t_outq) == 0) {
1674 CLR(tp->t_state, TS_TBLOCK);
1675 ttstart(tp);
1676 }
1677 /* Try to unblock remote output via hardware flow control. */
1678 if (ISSET(tp->t_cflag, CHWFLOW) && tp->t_hwiflow &&
1679 (*tp->t_hwiflow)(tp, 0) != 0)
1680 CLR(tp->t_state, TS_TBLOCK);
1681 }
1682 }
1683
1684 /*
1685 * Check the output queue on tp for space for a kernel message (from uprintf
1686 * or tprintf). Allow some space over the normal hiwater mark so we don't
1687 * lose messages due to normal flow control, but don't let the tty run amok.
1688 * Sleeps here are not interruptible, but we return prematurely if new signals
1689 * arrive.
1690 */
1691 int
ttycheckoutq(struct tty * tp,int wait)1692 ttycheckoutq(struct tty *tp, int wait)
1693 {
1694 int hiwat, s, oldsig;
1695
1696 hiwat = tp->t_hiwat;
1697 s = spltty();
1698 oldsig = wait ? SIGPENDING(curproc) : 0;
1699 if (tp->t_outq.c_cc > hiwat + TTHIWATMINSPACE)
1700 while (tp->t_outq.c_cc > hiwat) {
1701 ttstart(tp);
1702 if (wait == 0 || SIGPENDING(curproc) != oldsig) {
1703 splx(s);
1704 return (0);
1705 }
1706 SET(tp->t_state, TS_ASLEEP);
1707 tsleep_nsec(&tp->t_outq, PZERO - 1, "ttckoutq",
1708 SEC_TO_NSEC(1));
1709 }
1710 splx(s);
1711 return (1);
1712 }
1713
1714 /*
1715 * Process a write call on a tty device.
1716 */
1717 int
ttwrite(struct tty * tp,struct uio * uio,int flag)1718 ttwrite(struct tty *tp, struct uio *uio, int flag)
1719 {
1720 u_char *cp = NULL;
1721 int cc, ce, obufcc = 0;
1722 struct proc *p;
1723 struct process *pr;
1724 int hiwat, error, s;
1725 size_t cnt;
1726 u_char obuf[OBUFSIZ];
1727
1728 hiwat = tp->t_hiwat;
1729 cnt = uio->uio_resid;
1730 error = 0;
1731 cc = 0;
1732 loop:
1733 s = spltty();
1734 if (!ISSET(tp->t_state, TS_CARR_ON) &&
1735 !ISSET(tp->t_cflag, CLOCAL)) {
1736 if (ISSET(tp->t_state, TS_ISOPEN)) {
1737 splx(s);
1738 error = EIO;
1739 goto done;
1740 } else if (flag & IO_NDELAY) {
1741 splx(s);
1742 error = EWOULDBLOCK;
1743 goto out;
1744 } else {
1745 /* Sleep awaiting carrier. */
1746 error = ttysleep(tp,
1747 &tp->t_rawq, TTIPRI | PCATCH, ttopen);
1748 splx(s);
1749 if (error)
1750 goto out;
1751 goto loop;
1752 }
1753 }
1754 splx(s);
1755 /*
1756 * Hang the process if it's in the background.
1757 */
1758 p = curproc;
1759 pr = p->p_p;
1760 if (isbackground(pr, tp) &&
1761 ISSET(tp->t_lflag, TOSTOP) && (pr->ps_flags & PS_PPWAIT) == 0 &&
1762 !sigismasked(p, SIGTTOU)) {
1763 if (pr->ps_pgrp->pg_jobc == 0) {
1764 error = EIO;
1765 goto out;
1766 }
1767 pgsignal(pr->ps_pgrp, SIGTTOU, 1);
1768 error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, ttybg);
1769 if (error)
1770 goto out;
1771 goto loop;
1772 }
1773 /*
1774 * Process the user's data in at most OBUFSIZ chunks. Perform any
1775 * output translation. Keep track of high water mark, sleep on
1776 * overflow awaiting device aid in acquiring new space.
1777 */
1778 while (uio->uio_resid > 0 || cc > 0) {
1779 if (ISSET(tp->t_lflag, FLUSHO)) {
1780 uio->uio_resid = 0;
1781 goto done;
1782 }
1783 if (tp->t_outq.c_cc > hiwat)
1784 goto ovhiwat;
1785 /*
1786 * Grab a hunk of data from the user, unless we have some
1787 * leftover from last time.
1788 */
1789 if (cc == 0) {
1790 cc = MIN(uio->uio_resid, OBUFSIZ);
1791 cp = obuf;
1792 error = uiomove(cp, cc, uio);
1793 if (error) {
1794 cc = 0;
1795 break;
1796 }
1797 if (cc > obufcc)
1798 obufcc = cc;
1799
1800 /* duplicate /dev/console output into console buffer */
1801 if (consbufp && cn_tab &&
1802 cn_tab->cn_dev == tp->t_dev && tp->t_gen == 0) {
1803 int i;
1804 for (i = 0; i < cc; i++) {
1805 char c = cp[i];
1806 if (c != '\0' && c != '\r' && c != 0177)
1807 msgbuf_putchar(consbufp, c);
1808 }
1809 }
1810 }
1811 /*
1812 * If nothing fancy need be done, grab those characters we
1813 * can handle without any of ttyoutput's processing and
1814 * just transfer them to the output q. For those chars
1815 * which require special processing (as indicated by the
1816 * bits in char_type), call ttyoutput. After processing
1817 * a hunk of data, look for FLUSHO so ^O's will take effect
1818 * immediately.
1819 */
1820 while (cc > 0) {
1821 int i;
1822 if (!ISSET(tp->t_oflag, OPOST))
1823 ce = cc;
1824 else {
1825 ce = cc - scanc((u_int)cc, cp, char_type,
1826 CCLASSMASK);
1827 /*
1828 * If ce is zero, then we're processing
1829 * a special character through ttyoutput.
1830 */
1831 if (ce == 0) {
1832 tp->t_rocount = 0;
1833 if (ttyoutput(*cp, tp) >= 0) {
1834 /* out of space */
1835 goto ovhiwat;
1836 }
1837 cp++;
1838 cc--;
1839 if (ISSET(tp->t_lflag, FLUSHO) ||
1840 tp->t_outq.c_cc > hiwat)
1841 goto ovhiwat;
1842 continue;
1843 }
1844 }
1845 /*
1846 * A bunch of normal characters have been found.
1847 * Transfer them en masse to the output queue and
1848 * continue processing at the top of the loop.
1849 * If there are any further characters in this
1850 * <= OBUFSIZ chunk, the first should be a character
1851 * requiring special handling by ttyoutput.
1852 */
1853 tp->t_rocount = 0;
1854 i = b_to_q(cp, ce, &tp->t_outq);
1855 ce -= i;
1856 tp->t_column += ce;
1857 cp += ce, cc -= ce, tk_nout += ce;
1858 tp->t_outcc += ce;
1859 if (i > 0) {
1860 /* out of space */
1861 goto ovhiwat;
1862 }
1863 if (ISSET(tp->t_lflag, FLUSHO) ||
1864 tp->t_outq.c_cc > hiwat)
1865 break;
1866 }
1867 ttstart(tp);
1868 }
1869 out:
1870 /*
1871 * If cc is nonzero, we leave the uio structure inconsistent, as the
1872 * offset and iov pointers have moved forward, but it doesn't matter
1873 * (the call will either return short or restart with a new uio).
1874 */
1875 uio->uio_resid += cc;
1876 done:
1877 if (obufcc)
1878 explicit_bzero(obuf, obufcc);
1879 return (error);
1880
1881 ovhiwat:
1882 ttstart(tp);
1883 s = spltty();
1884 /*
1885 * This can only occur if FLUSHO is set in t_lflag,
1886 * or if ttstart/oproc is synchronous (or very fast).
1887 */
1888 if (tp->t_outq.c_cc <= hiwat) {
1889 splx(s);
1890 goto loop;
1891 }
1892 if (flag & IO_NDELAY) {
1893 splx(s);
1894 uio->uio_resid += cc;
1895 if (obufcc)
1896 explicit_bzero(obuf, obufcc);
1897 return (uio->uio_resid == cnt ? EWOULDBLOCK : 0);
1898 }
1899 SET(tp->t_state, TS_ASLEEP);
1900 error = ttysleep(tp, &tp->t_outq, TTOPRI | PCATCH, ttyout);
1901 splx(s);
1902 if (error)
1903 goto out;
1904 goto loop;
1905 }
1906
1907 /*
1908 * Rubout one character from the rawq of tp
1909 * as cleanly as possible.
1910 */
1911 int
ttyrub(int c,struct tty * tp)1912 ttyrub(int c, struct tty *tp)
1913 {
1914 u_char *cp;
1915 int savecol;
1916 int tabc, s, cc;
1917
1918 if (!ISSET(tp->t_lflag, ECHO) || ISSET(tp->t_lflag, EXTPROC))
1919 return 0;
1920 CLR(tp->t_lflag, FLUSHO);
1921 if (ISSET(tp->t_lflag, ECHOE)) {
1922 if (tp->t_rocount == 0) {
1923 /*
1924 * Screwed by ttwrite; retype
1925 */
1926 return ttyretype(tp);
1927 }
1928 if (c == ('\t' | TTY_QUOTE) || c == ('\n' | TTY_QUOTE))
1929 ttyrubo(tp, 2);
1930 else {
1931 CLR(c, ~TTY_CHARMASK);
1932 switch (CCLASS(c)) {
1933 case ORDINARY:
1934 ttyrubo(tp, 1);
1935 break;
1936 case BACKSPACE:
1937 case CONTROL:
1938 case NEWLINE:
1939 case RETURN:
1940 case VTAB:
1941 if (ISSET(tp->t_lflag, ECHOCTL))
1942 ttyrubo(tp, 2);
1943 break;
1944 case TAB:
1945 if (tp->t_rocount < tp->t_rawq.c_cc)
1946 return ttyretype(tp);
1947 s = spltty();
1948 savecol = tp->t_column;
1949 SET(tp->t_state, TS_CNTTB);
1950 SET(tp->t_lflag, FLUSHO);
1951 tp->t_column = tp->t_rocol;
1952 for (cp = firstc(&tp->t_rawq, &tabc, &cc); cp;
1953 cp = nextc(&tp->t_rawq, cp, &tabc, &cc))
1954 ttyecho(tabc, tp);
1955 CLR(tp->t_lflag, FLUSHO);
1956 CLR(tp->t_state, TS_CNTTB);
1957 splx(s);
1958
1959 /* savecol will now be length of the tab. */
1960 savecol -= tp->t_column;
1961 tp->t_column += savecol;
1962 if (savecol > 8)
1963 savecol = 8; /* overflow screw */
1964 while (--savecol >= 0)
1965 (void)ttyoutput('\b', tp);
1966 break;
1967 default: /* XXX */
1968 #define PANICSTR "ttyrub: would panic c = %d, val = %d"
1969 (void)printf(PANICSTR "\n", c, CCLASS(c));
1970 #ifdef notdef
1971 panic(PANICSTR, c, CCLASS(c));
1972 #endif
1973 }
1974 }
1975 } else if (ISSET(tp->t_lflag, ECHOPRT)) {
1976 if (!ISSET(tp->t_state, TS_ERASE)) {
1977 SET(tp->t_state, TS_ERASE);
1978 (void)ttyoutput('\\', tp);
1979 }
1980 ttyecho(c, tp);
1981 } else
1982 ttyecho(tp->t_cc[VERASE], tp);
1983 --tp->t_rocount;
1984 return 0;
1985 }
1986
1987 /*
1988 * Back over cnt characters, erasing them.
1989 */
1990 static void
ttyrubo(struct tty * tp,int cnt)1991 ttyrubo(struct tty *tp, int cnt)
1992 {
1993
1994 while (cnt-- > 0) {
1995 (void)ttyoutput('\b', tp);
1996 (void)ttyoutput(' ', tp);
1997 (void)ttyoutput('\b', tp);
1998 }
1999 }
2000
2001 /*
2002 * ttyretype --
2003 * Reprint the rawq line. Note, it is assumed that c_cc has already
2004 * been checked.
2005 */
2006 int
ttyretype(struct tty * tp)2007 ttyretype(struct tty *tp)
2008 {
2009 u_char *cp;
2010 int s, c, cc;
2011
2012 /* Echo the reprint character. */
2013 if (tp->t_cc[VREPRINT] != _POSIX_VDISABLE)
2014 ttyecho(tp->t_cc[VREPRINT], tp);
2015
2016 (void)ttyoutput('\n', tp);
2017
2018 s = spltty();
2019 for (cp = firstc(&tp->t_canq, &c, &cc); cp;
2020 cp = nextc(&tp->t_canq, cp, &c, &cc))
2021 ttyecho(c, tp);
2022 for (cp = firstc(&tp->t_rawq, &c, &cc); cp;
2023 cp = nextc(&tp->t_rawq, cp, &c, &cc))
2024 ttyecho(c, tp);
2025 CLR(tp->t_state, TS_ERASE);
2026 splx(s);
2027
2028 tp->t_rocount = tp->t_rawq.c_cc;
2029 tp->t_rocol = 0;
2030 return (1);
2031 }
2032
2033 /*
2034 * Echo a typed character to the terminal.
2035 */
2036 static void
ttyecho(int c,struct tty * tp)2037 ttyecho(int c, struct tty *tp)
2038 {
2039
2040 if (!ISSET(tp->t_state, TS_CNTTB))
2041 CLR(tp->t_lflag, FLUSHO);
2042 if ((!ISSET(tp->t_lflag, ECHO) &&
2043 (!ISSET(tp->t_lflag, ECHONL) || c != '\n')) ||
2044 ISSET(tp->t_lflag, EXTPROC))
2045 return;
2046 if (((ISSET(tp->t_lflag, ECHOCTL) &&
2047 (ISSET(c, TTY_CHARMASK) <= 037 && c != '\t' && c != '\n')) ||
2048 ISSET(c, TTY_CHARMASK) == 0177)) {
2049 (void)ttyoutput('^', tp);
2050 CLR(c, ~TTY_CHARMASK);
2051 if (c == 0177)
2052 c = '?';
2053 else
2054 c += 'A' - 1;
2055 }
2056 (void)ttyoutput(c, tp);
2057 }
2058
2059 /*
2060 * Wakeup any writers if necessary.
2061 */
2062 void
ttwakeupwr(struct tty * tp)2063 ttwakeupwr(struct tty *tp)
2064 {
2065
2066 if (tp->t_outq.c_cc <= tp->t_lowat) {
2067 if (ISSET(tp->t_state, TS_ASLEEP)) {
2068 CLR(tp->t_state, TS_ASLEEP);
2069 wakeup(&tp->t_outq);
2070 }
2071 selwakeup(&tp->t_wsel);
2072 }
2073 }
2074
2075 /*
2076 * Wake up any readers on a tty.
2077 */
2078 void
ttwakeup(struct tty * tp)2079 ttwakeup(struct tty *tp)
2080 {
2081
2082 selwakeup(&tp->t_rsel);
2083 if (ISSET(tp->t_state, TS_ASYNC))
2084 pgsignal(tp->t_pgrp, SIGIO, 1);
2085 wakeup((caddr_t)&tp->t_rawq);
2086 }
2087
2088 /*
2089 * Look up a code for a specified speed in a conversion table;
2090 * used by drivers to map software speed values to hardware parameters.
2091 */
2092 int
ttspeedtab(int speed,const struct speedtab * table)2093 ttspeedtab(int speed, const struct speedtab *table)
2094 {
2095
2096 for ( ; table->sp_speed != -1; table++)
2097 if (table->sp_speed == speed)
2098 return (table->sp_code);
2099 return (-1);
2100 }
2101
2102 /*
2103 * Set tty hi and low water marks.
2104 *
2105 * Try to arrange the dynamics so there's about one second
2106 * from hi to low water.
2107 */
2108 void
ttsetwater(struct tty * tp)2109 ttsetwater(struct tty *tp)
2110 {
2111 int cps, x;
2112
2113 #define CLAMP(x, h, l) ((x) > h ? h : ((x) < l) ? l : (x))
2114
2115 cps = tp->t_ospeed / 10;
2116 tp->t_lowat = x = CLAMP(cps / 2, TTMAXLOWAT, TTMINLOWAT);
2117 x += cps;
2118 tp->t_hiwat = CLAMP(x, tp->t_outq.c_cn - TTHIWATMINSPACE, TTMINHIWAT);
2119 #undef CLAMP
2120 }
2121
2122 /*
2123 * Get the total estcpu for a process, summing across threads.
2124 * Returns true if at least one thread is runnable/running.
2125 */
2126 static int
process_sum(struct process * pr,fixpt_t * estcpup)2127 process_sum(struct process *pr, fixpt_t *estcpup)
2128 {
2129 struct proc *p;
2130 fixpt_t estcpu;
2131 int ret;
2132
2133 ret = 0;
2134 estcpu = 0;
2135 TAILQ_FOREACH(p, &pr->ps_threads, p_thr_link) {
2136 if (p->p_stat == SRUN || p->p_stat == SONPROC)
2137 ret = 1;
2138 estcpu += p->p_pctcpu;
2139 }
2140
2141 *estcpup = estcpu;
2142 return (ret);
2143 }
2144
2145 /*
2146 * Report on state of foreground process group.
2147 */
2148 void
ttyinfo(struct tty * tp)2149 ttyinfo(struct tty *tp)
2150 {
2151 struct process *pr, *pickpr;
2152 struct proc *p, *pick;
2153 struct tusage tu;
2154 struct timespec utime, stime;
2155 int tmp;
2156
2157 if (ttycheckoutq(tp,0) == 0)
2158 return;
2159
2160 /* Print load average. */
2161 tmp = (averunnable.ldavg[0] * 100 + FSCALE / 2) >> FSHIFT;
2162 ttyprintf(tp, "load: %d.%02d ", tmp / 100, tmp % 100);
2163
2164 if (tp->t_session == NULL)
2165 ttyprintf(tp, "not a controlling terminal\n");
2166 else if (tp->t_pgrp == NULL)
2167 ttyprintf(tp, "no foreground process group\n");
2168 else if ((pr = LIST_FIRST(&tp->t_pgrp->pg_members)) == NULL)
2169 empty: ttyprintf(tp, "empty foreground process group\n");
2170 else {
2171 const char *state;
2172 fixpt_t pctcpu, pctcpu2;
2173 int run, run2;
2174 int calc_pctcpu;
2175 long rss = 0;
2176
2177 /*
2178 * Pick the most active process:
2179 * - prefer at least one running/runnable thread
2180 * - prefer higher total pctcpu
2181 * - prefer non-zombie
2182 * Otherwise take the most recently added to this process group
2183 */
2184 pickpr = pr;
2185 run = process_sum(pickpr, &pctcpu);
2186 while ((pr = LIST_NEXT(pr, ps_pglist)) != NULL) {
2187 run2 = process_sum(pr, &pctcpu2);
2188 if (run) {
2189 /*
2190 * pick is running; is p running w/same or
2191 * more cpu?
2192 */
2193 if (run2 && pctcpu2 >= pctcpu)
2194 goto update_pickpr;
2195 continue;
2196 }
2197 /* pick isn't running; is p running *or* w/more cpu? */
2198 if (run2 || pctcpu2 > pctcpu)
2199 goto update_pickpr;
2200
2201 /* if p has less cpu or is zombie, then it's worse */
2202 if (pctcpu2 < pctcpu || (pr->ps_flags & PS_ZOMBIE))
2203 continue;
2204 update_pickpr:
2205 pickpr = pr;
2206 run = run2;
2207 pctcpu = pctcpu2;
2208 }
2209
2210 /* Calculate percentage cpu, resident set size. */
2211 calc_pctcpu = (pctcpu * 10000 + FSCALE / 2) >> FSHIFT;
2212 if ((pickpr->ps_flags & (PS_EMBRYO | PS_ZOMBIE)) == 0 &&
2213 pickpr->ps_vmspace != NULL)
2214 rss = vm_resident_count(pickpr->ps_vmspace);
2215
2216 tuagg_get_process(&tu, pickpr);
2217 calctsru(&tu, &utime, &stime, NULL);
2218
2219 /* Round up and print user time. */
2220 utime.tv_nsec += 5000000;
2221 if (utime.tv_nsec >= 1000000000) {
2222 utime.tv_sec += 1;
2223 utime.tv_nsec -= 1000000000;
2224 }
2225
2226 /* Round up and print system time. */
2227 stime.tv_nsec += 5000000;
2228 if (stime.tv_nsec >= 1000000000) {
2229 stime.tv_sec += 1;
2230 stime.tv_nsec -= 1000000000;
2231 }
2232
2233 /*
2234 * Find the most active thread:
2235 * - prefer runnable
2236 * - prefer higher pctcpu
2237 * - prefer living
2238 * Otherwise take the newest thread
2239 */
2240 pick = p = TAILQ_FIRST(&pickpr->ps_threads);
2241 if (p == NULL)
2242 goto empty;
2243 run = p->p_stat == SRUN || p->p_stat == SONPROC;
2244 pctcpu = p->p_pctcpu;
2245 while ((p = TAILQ_NEXT(p, p_thr_link)) != NULL) {
2246 run2 = p->p_stat == SRUN || p->p_stat == SONPROC;
2247 pctcpu2 = p->p_pctcpu;
2248 if (run) {
2249 /*
2250 * pick is running; is p running w/same or
2251 * more cpu?
2252 */
2253 if (run2 && pctcpu2 >= pctcpu)
2254 goto update_pick;
2255 continue;
2256 }
2257 /* pick isn't running; is p running *or* w/more cpu? */
2258 if (run2 || pctcpu2 > pctcpu)
2259 goto update_pick;
2260
2261 /* if p has less cpu or is exiting, then it's worse */
2262 if (pctcpu2 < pctcpu || p->p_flag & P_WEXIT)
2263 continue;
2264 update_pick:
2265 pick = p;
2266 run = run2;
2267 pctcpu = p->p_pctcpu;
2268 }
2269 state = pick->p_stat == SONPROC ? "running" :
2270 pick->p_stat == SRUN ? "runnable" :
2271 pick->p_wmesg ? pick->p_wmesg : "iowait";
2272
2273 ttyprintf(tp,
2274 " cmd: %s %d [%s] %lld.%02ldu %lld.%02lds %d%% %ldk\n",
2275 pickpr->ps_comm, pickpr->ps_pid, state,
2276 (long long)utime.tv_sec, utime.tv_nsec / 10000000,
2277 (long long)stime.tv_sec, stime.tv_nsec / 10000000,
2278 calc_pctcpu / 100, rss);
2279 }
2280 tp->t_rocount = 0; /* so pending input will be retyped if BS */
2281 }
2282
2283 /*
2284 * Output char to tty; console putchar style.
2285 */
2286 int
tputchar(int c,struct tty * tp)2287 tputchar(int c, struct tty *tp)
2288 {
2289 int s;
2290
2291 s = spltty();
2292 if (ISSET(tp->t_state, TS_ISOPEN) == 0 ||
2293 !(ISSET(tp->t_state, TS_CARR_ON) || ISSET(tp->t_cflag, CLOCAL))) {
2294 splx(s);
2295 return (-1);
2296 }
2297 if (c == '\n')
2298 (void)ttyoutput('\r', tp);
2299 (void)ttyoutput(c, tp);
2300 ttstart(tp);
2301 splx(s);
2302 return (0);
2303 }
2304
2305 /*
2306 * Sleep on chan, returning ERESTART if tty changed while we napped and
2307 * returning any errors (e.g. EINTR/ETIMEDOUT) reported by tsleep. If
2308 * the tty is revoked, restarting a pending call will redo validation done
2309 * at the start of the call.
2310 */
2311 int
ttysleep(struct tty * tp,void * chan,int pri,char * wmesg)2312 ttysleep(struct tty *tp, void *chan, int pri, char *wmesg)
2313 {
2314 return (ttysleep_nsec(tp, chan, pri, wmesg, INFSLP));
2315 }
2316
2317 int
ttysleep_nsec(struct tty * tp,void * chan,int pri,char * wmesg,uint64_t nsecs)2318 ttysleep_nsec(struct tty *tp, void *chan, int pri, char *wmesg, uint64_t nsecs)
2319 {
2320 int error;
2321 short gen;
2322
2323 gen = tp->t_gen;
2324 if ((error = tsleep_nsec(chan, pri, wmesg, nsecs)) != 0)
2325 return (error);
2326 return (tp->t_gen == gen ? 0 : ERESTART);
2327 }
2328
2329 /*
2330 * Initialise the global tty list.
2331 */
2332 void
tty_init(void)2333 tty_init(void)
2334 {
2335
2336 TAILQ_INIT(&ttylist);
2337 tty_count = 0;
2338 }
2339
2340 /*
2341 * Allocate a tty structure and its associated buffers, and attach it to the
2342 * tty list.
2343 */
2344 struct tty *
ttymalloc(int baud)2345 ttymalloc(int baud)
2346 {
2347 struct tty *tp;
2348
2349 tp = malloc(sizeof(struct tty), M_TTYS, M_WAITOK|M_ZERO);
2350
2351 if (baud == 0)
2352 baud = 115200;
2353
2354 if (baud <= 9600)
2355 tp->t_qlen = 1024;
2356 else if (baud <= 115200)
2357 tp->t_qlen = 4096;
2358 else
2359 tp->t_qlen = 8192;
2360 clalloc(&tp->t_rawq, tp->t_qlen, 1);
2361 clalloc(&tp->t_canq, tp->t_qlen, 1);
2362 /* output queue doesn't need quoting */
2363 clalloc(&tp->t_outq, tp->t_qlen, 0);
2364
2365 rw_enter_write(&ttylist_lock);
2366 TAILQ_INSERT_TAIL(&ttylist, tp, tty_link);
2367 ++tty_count;
2368 rw_exit_write(&ttylist_lock);
2369
2370 timeout_set(&tp->t_rstrt_to, ttrstrt, tp);
2371
2372 return(tp);
2373 }
2374
2375
2376 /*
2377 * Free a tty structure and its buffers, after removing it from the tty list.
2378 */
2379 void
ttyfree(struct tty * tp)2380 ttyfree(struct tty *tp)
2381 {
2382 int s;
2383
2384 rw_enter_write(&ttylist_lock);
2385 --tty_count;
2386 #ifdef DIAGNOSTIC
2387 if (tty_count < 0)
2388 panic("ttyfree: tty_count < 0");
2389 #endif
2390 TAILQ_REMOVE(&ttylist, tp, tty_link);
2391 rw_exit_write(&ttylist_lock);
2392
2393 s = spltty();
2394 klist_invalidate(&tp->t_rsel.si_note);
2395 klist_invalidate(&tp->t_wsel.si_note);
2396 splx(s);
2397
2398 clfree(&tp->t_rawq);
2399 clfree(&tp->t_canq);
2400 clfree(&tp->t_outq);
2401 free(tp, M_TTYS, sizeof(*tp));
2402 }
2403
2404 void
ttystats_init(struct itty ** ttystats,int * ttycp,size_t * ttystatssiz)2405 ttystats_init(struct itty **ttystats, int *ttycp, size_t *ttystatssiz)
2406 {
2407 int ntty = 0, ttyc;
2408 struct itty *itp;
2409 struct tty *tp;
2410
2411 ttyc = tty_count;
2412 *ttystatssiz = ttyc * sizeof(struct itty);
2413 *ttystats = mallocarray(ttyc, sizeof(struct itty),
2414 M_SYSCTL, M_WAITOK|M_ZERO);
2415
2416 rw_enter_write(&ttylist_lock);
2417 for (tp = TAILQ_FIRST(&ttylist), itp = *ttystats; tp && ntty++ < ttyc;
2418 tp = TAILQ_NEXT(tp, tty_link), itp++) {
2419 itp->t_dev = tp->t_dev;
2420 itp->t_rawq_c_cc = tp->t_rawq.c_cc;
2421 itp->t_canq_c_cc = tp->t_canq.c_cc;
2422 itp->t_outq_c_cc = tp->t_outq.c_cc;
2423 itp->t_hiwat = tp->t_hiwat;
2424 itp->t_lowat = tp->t_lowat;
2425 if (ISSET(tp->t_oflag, OPOST))
2426 itp->t_column = tp->t_column;
2427 itp->t_state = tp->t_state;
2428 itp->t_session = tp->t_session;
2429 if (tp->t_pgrp)
2430 itp->t_pgrp_pg_id = tp->t_pgrp->pg_id;
2431 else
2432 itp->t_pgrp_pg_id = 0;
2433 itp->t_line = tp->t_line;
2434 }
2435 rw_exit_write(&ttylist_lock);
2436 *ttycp = ntty;
2437 }
2438
2439 /*
2440 * Return tty-related information.
2441 */
2442 int
sysctl_tty(int * name,u_int namelen,void * oldp,size_t * oldlenp,void * newp,size_t newlen)2443 sysctl_tty(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
2444 size_t newlen)
2445 {
2446 int err;
2447
2448 if (namelen != 1)
2449 return (ENOTDIR);
2450
2451 switch (name[0]) {
2452 case KERN_TTY_TKNIN:
2453 return (sysctl_rdquad(oldp, oldlenp, newp, tk_nin));
2454 case KERN_TTY_TKNOUT:
2455 return (sysctl_rdquad(oldp, oldlenp, newp, tk_nout));
2456 case KERN_TTY_TKRAWCC:
2457 return (sysctl_rdquad(oldp, oldlenp, newp, tk_rawcc));
2458 case KERN_TTY_TKCANCC:
2459 return (sysctl_rdquad(oldp, oldlenp, newp, tk_cancc));
2460 case KERN_TTY_INFO:
2461 {
2462 struct itty *ttystats;
2463 size_t ttystatssiz;
2464 int ttyc;
2465
2466 ttystats_init(&ttystats, &ttyc, &ttystatssiz);
2467 err = sysctl_rdstruct(oldp, oldlenp, newp, ttystats,
2468 ttyc * sizeof(struct itty));
2469 free(ttystats, M_SYSCTL, ttystatssiz);
2470 return (err);
2471 }
2472 default:
2473 #if NPTY > 0
2474 return (sysctl_pty(name, namelen, oldp, oldlenp, newp, newlen));
2475 #else
2476 return (EOPNOTSUPP);
2477 #endif
2478 }
2479 /* NOTREACHED */
2480 }
2481
2482 void
ttytstamp(struct tty * tp,int octs,int ncts,int odcd,int ndcd)2483 ttytstamp(struct tty *tp, int octs, int ncts, int odcd, int ndcd)
2484 {
2485 int doit = 0;
2486
2487 if (ncts ^ octs)
2488 doit |= ncts ? ISSET(tp->t_flags, TS_TSTAMPCTSSET) :
2489 ISSET(tp->t_flags, TS_TSTAMPCTSCLR);
2490 if (ndcd ^ odcd)
2491 doit |= ndcd ? ISSET(tp->t_flags, TS_TSTAMPDCDSET) :
2492 ISSET(tp->t_flags, TS_TSTAMPDCDCLR);
2493
2494 if (doit)
2495 microtime(&tp->t_tv);
2496 }
2497