drm/linux: Remove a redundant definition of NSEC_PER_SEC
[dragonfly.git] / sys / kern / tty.c
blob8c2ec29d2a8ff862dddc8272ad16270ba43d2c0e
1 /*-
2 * (MPSAFE)
4 * Copyright (c) 1982, 1986, 1990, 1991, 1993
5 * The Regents of the University of California. All rights reserved.
6 * (c) UNIX System Laboratories, Inc.
7 * All or some portions of this file are derived from material licensed
8 * to the University of California by American Telephone and Telegraph
9 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
10 * the permission of UNIX System Laboratories, Inc.
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
36 * @(#)tty.c 8.8 (Berkeley) 1/21/94
37 * $FreeBSD: src/sys/kern/tty.c,v 1.129.2.5 2002/03/11 01:32:31 dd Exp $
41 * MPSAFE NOTE:
42 * Almost all functions in this file are acquiring the tty token due to their
43 * access and modifications of the 'tp' (struct tty) objects.
46 /*-
47 * TODO:
48 * o Fix races for sending the start char in ttyflush().
49 * o Handle inter-byte timeout for "MIN > 0, TIME > 0" in ttyselect().
50 * With luck, there will be MIN chars before select() returns().
51 * o Handle CLOCAL consistently for ptys. Perhaps disallow setting it.
52 * o Don't allow input in TS_ZOMBIE case. It would be visible through
53 * FIONREAD.
54 * o Do the new sio locking stuff here and use it to avoid special
55 * case for EXTPROC?
56 * o Lock PENDIN too?
57 * o Move EXTPROC and/or PENDIN to t_state?
58 * o Wrap most of ttioctl in spltty/splx.
59 * o Implement TIOCNOTTY or remove it from <sys/ioctl.h>.
60 * o Send STOP if IXOFF is toggled off while TS_TBLOCK is set.
61 * o Don't allow certain termios flags to affect disciplines other
62 * than TTYDISC. Cancel their effects before switch disciplines
63 * and ignore them if they are set while we are in another
64 * discipline.
65 * o Now that historical speed conversions are handled here, don't
66 * do them in drivers.
67 * o Check for TS_CARR_ON being set while everything is closed and not
68 * waiting for carrier. TS_CARR_ON isn't cleared if nothing is open,
69 * so it would live until the next open even if carrier drops.
70 * o Restore TS_WOPEN since it is useful in pstat. It must be cleared
71 * only when _all_ openers leave open().
74 #include "opt_uconsole.h"
76 #include <sys/param.h>
77 #include <sys/systm.h>
78 #include <sys/filio.h>
79 #include <sys/proc.h>
80 #include <sys/priv.h>
81 #define TTYDEFCHARS
82 #include <sys/tty.h>
83 #include <sys/clist.h>
84 #undef TTYDEFCHARS
85 #include <sys/fcntl.h>
86 #include <sys/conf.h>
87 #include <sys/dkstat.h>
88 #include <sys/kernel.h>
89 #include <sys/vnode.h>
90 #include <sys/signalvar.h>
91 #include <sys/signal2.h>
92 #include <sys/resourcevar.h>
93 #include <sys/malloc.h>
94 #include <sys/filedesc.h>
95 #include <sys/sysctl.h>
96 #include <sys/thread2.h>
98 #include <vm/vm.h>
99 #include <sys/lock.h>
100 #include <vm/pmap.h>
101 #include <vm/vm_map.h>
102 #include <vm/vm_extern.h>
104 MALLOC_DEFINE(M_TTYS, "ttys", "tty data structures");
106 static int proc_compare (struct proc *p1, struct proc *p2);
107 static int ttnread (struct tty *tp);
108 static void ttyecho (int c, struct tty *tp);
109 static int ttyoutput (int c, struct tty *tp);
110 static void ttypend (struct tty *tp);
111 static void ttyretype (struct tty *tp);
112 static void ttyrub (int c, struct tty *tp);
113 static void ttyrubo (struct tty *tp, int cnt);
114 static void ttyunblock (struct tty *tp);
115 static int ttywflush (struct tty *tp);
116 static int filt_ttyread (struct knote *kn, long hint);
117 static void filt_ttyrdetach (struct knote *kn);
118 static int filt_ttywrite (struct knote *kn, long hint);
119 static void filt_ttywdetach (struct knote *kn);
122 * Table with character classes and parity. The 8th bit indicates parity,
123 * the 7th bit indicates the character is an alphameric or underscore (for
124 * ALTWERASE), and the low 6 bits indicate delay type. If the low 6 bits
125 * are 0 then the character needs no special processing on output; classes
126 * other than 0 might be translated or (not currently) require delays.
128 #define E 0x00 /* Even parity. */
129 #define O 0x80 /* Odd parity. */
130 #define PARITY(c) (char_type[c] & O)
132 #define ALPHA 0x40 /* Alpha or underscore. */
133 #define ISALPHA(c) (char_type[(c) & TTY_CHARMASK] & ALPHA)
135 #define CCLASSMASK 0x3f
136 #define CCLASS(c) (char_type[c] & CCLASSMASK)
138 #define BS BACKSPACE
139 #define CC CONTROL
140 #define CR RETURN
141 #define NA ORDINARY | ALPHA
142 #define NL NEWLINE
143 #define NO ORDINARY
144 #define TB TAB
145 #define VT VTAB
147 static u_char const char_type[] = {
148 E|CC, O|CC, O|CC, E|CC, O|CC, E|CC, E|CC, O|CC, /* nul - bel */
149 O|BS, E|TB, E|NL, O|CC, E|VT, O|CR, O|CC, E|CC, /* bs - si */
150 O|CC, E|CC, E|CC, O|CC, E|CC, O|CC, O|CC, E|CC, /* dle - etb */
151 E|CC, O|CC, O|CC, E|CC, O|CC, E|CC, E|CC, O|CC, /* can - us */
152 O|NO, E|NO, E|NO, O|NO, E|NO, O|NO, O|NO, E|NO, /* sp - ' */
153 E|NO, O|NO, O|NO, E|NO, O|NO, E|NO, E|NO, O|NO, /* ( - / */
154 E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* 0 - 7 */
155 O|NA, E|NA, E|NO, O|NO, E|NO, O|NO, O|NO, E|NO, /* 8 - ? */
156 O|NO, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA, /* @ - G */
157 E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* H - O */
158 E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* P - W */
159 O|NA, E|NA, E|NA, O|NO, E|NO, O|NO, O|NO, O|NA, /* X - _ */
160 E|NO, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* ` - g */
161 O|NA, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA, /* h - o */
162 O|NA, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA, /* p - w */
163 E|NA, O|NA, O|NA, E|NO, O|NO, E|NO, E|NO, O|CC, /* x - del */
165 * Meta chars; should be settable per character set;
166 * for now, treat them all as normal characters.
168 NA, NA, NA, NA, NA, NA, NA, NA,
169 NA, NA, NA, NA, NA, NA, NA, NA,
170 NA, NA, NA, NA, NA, NA, NA, NA,
171 NA, NA, NA, NA, NA, NA, NA, NA,
172 NA, NA, NA, NA, NA, NA, NA, NA,
173 NA, NA, NA, NA, NA, NA, NA, NA,
174 NA, NA, NA, NA, NA, NA, NA, NA,
175 NA, NA, NA, NA, NA, NA, NA, NA,
176 NA, NA, NA, NA, NA, NA, NA, NA,
177 NA, NA, NA, NA, NA, NA, NA, NA,
178 NA, NA, NA, NA, NA, NA, NA, NA,
179 NA, NA, NA, NA, NA, NA, NA, NA,
180 NA, NA, NA, NA, NA, NA, NA, NA,
181 NA, NA, NA, NA, NA, NA, NA, NA,
182 NA, NA, NA, NA, NA, NA, NA, NA,
183 NA, NA, NA, NA, NA, NA, NA, NA,
185 #undef BS
186 #undef CC
187 #undef CR
188 #undef NA
189 #undef NL
190 #undef NO
191 #undef TB
192 #undef VT
194 /* Macros to clear/set/test flags. */
195 #define SET(t, f) (t) |= (f)
196 #define CLR(t, f) (t) &= ~(f)
197 #define ISSET(t, f) ((t) & (f))
199 #undef MAX_INPUT /* XXX wrong in <sys/syslimits.h> */
200 #define MAX_INPUT TTYHOG /* XXX limit is usually larger for !ICANON */
202 uint64_t tk_nin;
203 SYSCTL_OPAQUE(_kern, OID_AUTO, tk_nin, CTLFLAG_RD, &tk_nin, sizeof(tk_nin),
204 "LU", "TTY input statistic");
205 uint64_t tk_nout;
206 SYSCTL_OPAQUE(_kern, OID_AUTO, tk_nout, CTLFLAG_RD, &tk_nout, sizeof(tk_nout),
207 "LU", "TTY output statistic");
208 uint64_t tk_rawcc;
211 * list of struct tty where pstat(8) can pick it up with sysctl
213 static TAILQ_HEAD(, tty) tty_list = TAILQ_HEAD_INITIALIZER(tty_list);
216 * Initial open of tty, or (re)entry to standard tty line discipline.
219 ttyopen(cdev_t device, struct tty *tp)
221 crit_enter();
222 lwkt_gettoken(&tty_token);
223 tp->t_dev = device;
224 if (!ISSET(tp->t_state, TS_ISOPEN)) {
225 SET(tp->t_state, TS_ISOPEN);
226 if (ISSET(tp->t_cflag, CLOCAL)) {
227 SET(tp->t_state, TS_CONNECTED);
229 bzero(&tp->t_winsize, sizeof(tp->t_winsize));
231 ttsetwater(tp);
232 lwkt_reltoken(&tty_token);
233 crit_exit();
234 return (0);
238 * Handle close() on a tty line: flush and set to initial state,
239 * bumping generation number so that pending read/write calls
240 * can detect recycling of the tty.
242 * XXX our caller should have done `spltty(); l_close(); ttyclose();'
243 * and l_close() should have flushed, but we repeat the spltty() and
244 * the flush in case there are buggy callers.
247 ttyclose(struct tty *tp)
249 crit_enter();
250 lwkt_gettoken(&tty_token);
251 funsetown(&tp->t_sigio);
252 if (constty == tp)
253 constty = NULL;
255 ttyflush(tp, FREAD | FWRITE);
256 clist_free_cblocks(&tp->t_canq);
257 clist_free_cblocks(&tp->t_outq);
258 clist_free_cblocks(&tp->t_rawq);
260 tp->t_gen++;
261 tp->t_line = TTYDISC;
262 ttyclearsession(tp);
263 tp->t_state &= TS_REGISTERED; /* clear all bits except */
264 lwkt_reltoken(&tty_token);
265 crit_exit();
266 return (0);
270 * Disassociate the tty from its session. Traditionally this has only been
271 * a half-close, meaning that the session was still allowed to point at the
272 * tty (resulting in the tty in the ps command showing something like 'p0-'),
273 * even though the tty is no longer pointing at the session.
275 * The half close seems to be useful only for 'ps' output but there is as
276 * yet no reason to remove the feature. The full-close code is currently
277 * #if 0'd out. See also sess_rele() in kern/kern_proc.c.
279 void
280 ttyclearsession(struct tty *tp)
282 struct session *sp;
283 struct pgrp *opgrp;
285 lwkt_gettoken(&tty_token);
286 opgrp = tp->t_pgrp;
287 tp->t_pgrp = NULL;
288 if (opgrp) {
289 pgrel(opgrp);
290 opgrp = NULL;
293 if ((sp = tp->t_session) != NULL) {
294 tp->t_session = NULL;
295 #ifdef TTY_DO_FULL_CLOSE
296 /* FULL CLOSE (not yet) */
297 if (sp->s_ttyp == tp) {
298 sp->s_ttyp = NULL;
299 ttyunhold(tp);
300 } else {
301 kprintf("ttyclearsession: warning: sp->s_ttyp != tp "
302 "%p/%p\n", sp->s_ttyp, tp);
304 #endif
306 lwkt_reltoken(&tty_token);
310 * Release the tty vnode association for a session. This is the
311 * 'other half' of the close. Because multiple opens of /dev/tty
312 * only generate a single open to the actual tty, the file modes
313 * are locked to FREAD|FWRITE.
315 * If dorevoke is non-zero, the session is also revoked. We have to
316 * close the vnode if VCTTYISOPEN is set.
318 void
319 ttyclosesession(struct session *sp, int dorevoke)
321 struct vnode *vp;
323 lwkt_gettoken(&tty_token);
324 retry:
326 * There may not be a controlling terminal or it may have been closed
327 * out from under us.
329 if ((vp = sp->s_ttyvp) == NULL) {
330 lwkt_reltoken(&tty_token);
331 return;
335 * We need a lock if we have to close or revoke.
337 if ((vp->v_flag & VCTTYISOPEN) || dorevoke) {
338 vhold(vp);
339 if (vn_lock(vp, LK_EXCLUSIVE | LK_RETRY | LK_FAILRECLAIM)) {
340 vdrop(vp);
341 goto retry;
345 * Retry if the vnode was ripped out from under us
347 if (vp != sp->s_ttyvp) {
348 vn_unlock(vp);
349 vdrop(vp);
350 goto retry;
354 * Close and revoke as needed
356 sp->s_ttyvp = NULL;
357 if (vp->v_flag & VCTTYISOPEN) {
358 vclrflags(vp, VCTTYISOPEN);
359 VOP_CLOSE(vp, FREAD|FWRITE, NULL);
361 vn_unlock(vp);
362 if (dorevoke)
363 vrevoke(vp, proc0.p_ucred);
364 vdrop(vp);
365 } else {
366 sp->s_ttyvp = NULL;
368 vrele(vp);
369 lwkt_reltoken(&tty_token);
372 #define FLUSHQ(q) { \
373 if ((q)->c_cc) \
374 ndflush(q, (q)->c_cc); \
377 /* Is 'c' a line delimiter ("break" character)? */
378 #define TTBREAKC(c, lflag) \
379 ((c) == '\n' || (((c) == cc[VEOF] || \
380 (c) == cc[VEOL] || ((c) == cc[VEOL2] && lflag & IEXTEN)) && \
381 (c) != _POSIX_VDISABLE))
384 * Process input of a single character received on a tty.
387 ttyinput(int c, struct tty *tp)
389 tcflag_t iflag, lflag;
390 cc_t *cc;
391 int i, err;
393 lwkt_gettoken(&tty_token);
395 * If input is pending take it first.
397 lflag = tp->t_lflag;
398 if (ISSET(lflag, PENDIN))
399 ttypend(tp);
401 * Gather stats.
403 if (ISSET(lflag, ICANON))
404 ++tp->t_cancc;
405 else
406 ++tp->t_rawcc;
407 ++tk_nin;
410 * Block further input iff:
411 * current input > threshold AND input is available to user program
412 * AND input flow control is enabled and not yet invoked.
413 * The 3 is slop for PARMRK.
415 iflag = tp->t_iflag;
416 if (tp->t_rawq.c_cc + tp->t_canq.c_cc > tp->t_ihiwat - 3 &&
417 (!ISSET(lflag, ICANON) || tp->t_canq.c_cc != 0) &&
418 (ISSET(tp->t_cflag, CRTS_IFLOW) || ISSET(iflag, IXOFF)) &&
419 !ISSET(tp->t_state, TS_TBLOCK))
420 ttyblock(tp);
422 /* Handle exceptional conditions (break, parity, framing). */
423 cc = tp->t_cc;
424 err = (ISSET(c, TTY_ERRORMASK));
425 if (err) {
426 CLR(c, TTY_ERRORMASK);
427 if (ISSET(err, TTY_BI)) {
428 if (ISSET(iflag, IGNBRK)) {
429 lwkt_reltoken(&tty_token);
430 return (0);
432 if (ISSET(iflag, BRKINT)) {
433 ttyflush(tp, FREAD | FWRITE);
434 pgsignal(tp->t_pgrp, SIGINT, 1);
435 goto endcase;
437 if (ISSET(iflag, PARMRK))
438 goto parmrk;
439 } else if ((ISSET(err, TTY_PE) && ISSET(iflag, INPCK))
440 || ISSET(err, TTY_FE)) {
441 if (ISSET(iflag, IGNPAR)) {
442 lwkt_reltoken(&tty_token);
443 return (0);
445 else if (ISSET(iflag, PARMRK)) {
446 parmrk:
447 if (tp->t_rawq.c_cc + tp->t_canq.c_cc >
448 MAX_INPUT - 3)
449 goto input_overflow;
450 clist_putc(0377 | TTY_QUOTE, &tp->t_rawq);
451 clist_putc(0 | TTY_QUOTE, &tp->t_rawq);
452 clist_putc(c | TTY_QUOTE, &tp->t_rawq);
453 goto endcase;
454 } else
455 c = 0;
459 if (!ISSET(tp->t_state, TS_TYPEN) && ISSET(iflag, ISTRIP))
460 CLR(c, 0x80);
461 if (!ISSET(lflag, EXTPROC)) {
463 * Check for literal nexting very first
465 if (ISSET(tp->t_state, TS_LNCH)) {
466 SET(c, TTY_QUOTE);
467 CLR(tp->t_state, TS_LNCH);
470 * Scan for special characters. This code
471 * is really just a big case statement with
472 * non-constant cases. The bottom of the
473 * case statement is labeled ``endcase'', so goto
474 * it after a case match, or similar.
478 * Control chars which aren't controlled
479 * by ICANON, ISIG, or IXON.
481 if (ISSET(lflag, IEXTEN)) {
482 if (CCEQ(cc[VLNEXT], c)) {
483 if (ISSET(lflag, ECHO)) {
484 if (ISSET(lflag, ECHOE)) {
485 (void)ttyoutput('^', tp);
486 (void)ttyoutput('\b', tp);
487 } else
488 ttyecho(c, tp);
490 SET(tp->t_state, TS_LNCH);
491 goto endcase;
493 if (CCEQ(cc[VDISCARD], c)) {
494 if (ISSET(lflag, FLUSHO))
495 CLR(tp->t_lflag, FLUSHO);
496 else {
497 ttyflush(tp, FWRITE);
498 ttyecho(c, tp);
499 if (tp->t_rawq.c_cc + tp->t_canq.c_cc)
500 ttyretype(tp);
501 SET(tp->t_lflag, FLUSHO);
503 goto startoutput;
507 * Signals.
509 if (ISSET(lflag, ISIG)) {
510 if (CCEQ(cc[VINTR], c) || CCEQ(cc[VQUIT], c)) {
511 if (!ISSET(lflag, NOFLSH))
512 ttyflush(tp, FREAD | FWRITE);
513 ttyecho(c, tp);
514 pgsignal(tp->t_pgrp,
515 CCEQ(cc[VINTR], c) ? SIGINT : SIGQUIT, 1);
516 goto endcase;
518 if (CCEQ(cc[VSUSP], c)) {
519 if (!ISSET(lflag, NOFLSH))
520 ttyflush(tp, FREAD);
521 ttyecho(c, tp);
522 pgsignal(tp->t_pgrp, SIGTSTP, 1);
523 goto endcase;
527 * Handle start/stop characters.
529 if (ISSET(iflag, IXON)) {
530 if (CCEQ(cc[VSTOP], c)) {
531 if (!ISSET(tp->t_state, TS_TTSTOP)) {
532 SET(tp->t_state, TS_TTSTOP);
533 (*tp->t_stop)(tp, 0);
534 lwkt_reltoken(&tty_token);
535 return (0);
537 if (!CCEQ(cc[VSTART], c)) {
538 lwkt_reltoken(&tty_token);
539 return (0);
542 * if VSTART == VSTOP then toggle
544 goto endcase;
546 if (CCEQ(cc[VSTART], c))
547 goto restartoutput;
550 * IGNCR, ICRNL, & INLCR
552 if (c == '\r') {
553 if (ISSET(iflag, IGNCR)) {
554 lwkt_reltoken(&tty_token);
555 return (0);
557 else if (ISSET(iflag, ICRNL))
558 c = '\n';
559 } else if (c == '\n' && ISSET(iflag, INLCR))
560 c = '\r';
562 if (!ISSET(tp->t_lflag, EXTPROC) && ISSET(lflag, ICANON)) {
564 * From here on down canonical mode character
565 * processing takes place.
568 * erase or erase2 (^H / ^?)
570 if (CCEQ(cc[VERASE], c) || CCEQ(cc[VERASE2], c) ) {
571 if (tp->t_rawq.c_cc)
572 ttyrub(clist_unputc(&tp->t_rawq), tp);
573 goto endcase;
576 * kill (^U)
578 if (CCEQ(cc[VKILL], c)) {
579 if (ISSET(lflag, ECHOKE) &&
580 tp->t_rawq.c_cc == tp->t_rocount &&
581 !ISSET(lflag, ECHOPRT))
582 while (tp->t_rawq.c_cc)
583 ttyrub(clist_unputc(&tp->t_rawq), tp);
584 else {
585 ttyecho(c, tp);
586 if (ISSET(lflag, ECHOK) ||
587 ISSET(lflag, ECHOKE))
588 ttyecho('\n', tp);
589 FLUSHQ(&tp->t_rawq);
590 tp->t_rocount = 0;
592 CLR(tp->t_state, TS_LOCAL);
593 goto endcase;
596 * word erase (^W)
598 if (CCEQ(cc[VWERASE], c) && ISSET(lflag, IEXTEN)) {
599 int ctype;
602 * erase whitespace
604 while ((c = clist_unputc(&tp->t_rawq)) == ' ' || c == '\t')
605 ttyrub(c, tp);
606 if (c == -1)
607 goto endcase;
609 * erase last char of word and remember the
610 * next chars type (for ALTWERASE)
612 ttyrub(c, tp);
613 c = clist_unputc(&tp->t_rawq);
614 if (c == -1)
615 goto endcase;
616 if (c == ' ' || c == '\t') {
617 clist_putc(c, &tp->t_rawq);
618 goto endcase;
620 ctype = ISALPHA(c);
622 * erase rest of word
624 do {
625 ttyrub(c, tp);
626 c = clist_unputc(&tp->t_rawq);
627 if (c == -1)
628 goto endcase;
629 } while (c != ' ' && c != '\t' &&
630 (!ISSET(lflag, ALTWERASE) || ISALPHA(c) == ctype));
631 clist_putc(c, &tp->t_rawq);
632 goto endcase;
635 * reprint line (^R)
637 if (CCEQ(cc[VREPRINT], c) && ISSET(lflag, IEXTEN)) {
638 ttyretype(tp);
639 goto endcase;
642 * ^T - kernel info and generate SIGINFO
644 if (CCEQ(cc[VSTATUS], c) && ISSET(lflag, IEXTEN)) {
645 if (ISSET(lflag, ISIG))
646 pgsignal(tp->t_pgrp, SIGINFO, 1);
647 if (!ISSET(lflag, NOKERNINFO))
648 ttyinfo(tp);
649 goto endcase;
651 if (CCEQ(cc[VCHECKPT], c) && ISSET(lflag, IEXTEN)) {
652 if (ISSET(lflag, ISIG))
653 pgsignal(tp->t_pgrp, SIGCKPT, 1);
654 goto endcase;
658 * Check for input buffer overflow
660 if (tp->t_rawq.c_cc + tp->t_canq.c_cc >= MAX_INPUT) {
661 input_overflow:
662 if (ISSET(iflag, IMAXBEL)) {
663 if (tp->t_outq.c_cc < tp->t_ohiwat)
664 (void)ttyoutput(CTRL('g'), tp);
666 goto endcase;
669 if ( c == 0377 && ISSET(iflag, PARMRK) && !ISSET(iflag, ISTRIP)
670 && ISSET(iflag, IGNBRK|IGNPAR) != (IGNBRK|IGNPAR))
671 clist_putc(0377 | TTY_QUOTE, &tp->t_rawq);
674 * Put data char in q for user and
675 * wakeup on seeing a line delimiter.
677 if (clist_putc(c, &tp->t_rawq) >= 0) {
678 if (!ISSET(lflag, ICANON)) {
679 ttwakeup(tp);
680 ttyecho(c, tp);
681 goto endcase;
683 if (TTBREAKC(c, lflag)) {
684 tp->t_rocount = 0;
685 catq(&tp->t_rawq, &tp->t_canq);
686 ttwakeup(tp);
687 } else if (tp->t_rocount++ == 0)
688 tp->t_rocol = tp->t_column;
689 if (ISSET(tp->t_state, TS_ERASE)) {
691 * end of prterase \.../
693 CLR(tp->t_state, TS_ERASE);
694 (void)ttyoutput('/', tp);
696 i = tp->t_column;
697 ttyecho(c, tp);
698 if (CCEQ(cc[VEOF], c) && ISSET(lflag, ECHO)) {
700 * Place the cursor over the '^' of the ^D.
702 i = imin(2, tp->t_column - i);
703 while (i > 0) {
704 (void)ttyoutput('\b', tp);
705 i--;
709 endcase:
711 * IXANY means allow any character to restart output.
713 if (ISSET(tp->t_state, TS_TTSTOP) &&
714 !ISSET(iflag, IXANY) && cc[VSTART] != cc[VSTOP]) {
715 lwkt_reltoken(&tty_token);
716 return (0);
718 restartoutput:
719 CLR(tp->t_lflag, FLUSHO);
720 CLR(tp->t_state, TS_TTSTOP);
721 startoutput:
722 lwkt_reltoken(&tty_token);
723 return (ttstart(tp));
727 * Output a single character on a tty, doing output processing
728 * as needed (expanding tabs, newline processing, etc.).
729 * Returns < 0 if succeeds, otherwise returns char to resend.
730 * Must be recursive.
732 static int
733 ttyoutput(int c, struct tty *tp)
735 tcflag_t oflag;
736 int col;
738 lwkt_gettoken(&tty_token);
739 oflag = tp->t_oflag;
740 if (!ISSET(oflag, OPOST)) {
741 if (ISSET(tp->t_lflag, FLUSHO)) {
742 lwkt_reltoken(&tty_token);
743 return (-1);
745 if (clist_putc(c, &tp->t_outq)) {
746 lwkt_reltoken(&tty_token);
747 return (c);
749 tk_nout++;
750 tp->t_outcc++;
751 lwkt_reltoken(&tty_token);
752 return (-1);
755 * Do tab expansion if OXTABS is set. Special case if we external
756 * processing, we don't do the tab expansion because we'll probably
757 * get it wrong. If tab expansion needs to be done, let it happen
758 * externally.
760 CLR(c, ~TTY_CHARMASK);
761 if (c == '\t' &&
762 ISSET(oflag, OXTABS) && !ISSET(tp->t_lflag, EXTPROC)) {
763 c = 8 - (tp->t_column & 7);
764 if (!ISSET(tp->t_lflag, FLUSHO)) {
765 crit_enter(); /* Don't interrupt tabs. */
766 c -= b_to_q(" ", c, &tp->t_outq);
767 tk_nout += c;
768 tp->t_outcc += c;
769 crit_exit();
771 tp->t_column += c;
772 lwkt_reltoken(&tty_token);
773 return (c ? -1 : '\t');
775 if (c == CEOT && ISSET(oflag, ONOEOT)) {
776 lwkt_reltoken(&tty_token);
777 return (-1);
781 * Newline translation: if ONLCR is set,
782 * translate newline into "\r\n".
784 if (c == '\n' && ISSET(tp->t_oflag, ONLCR)) {
785 tk_nout++;
786 tp->t_outcc++;
787 if (!ISSET(tp->t_lflag, FLUSHO) && clist_putc('\r', &tp->t_outq)) {
788 lwkt_reltoken(&tty_token);
789 return (c);
792 /* If OCRNL is set, translate "\r" into "\n". */
793 else if (c == '\r' && ISSET(tp->t_oflag, OCRNL))
794 c = '\n';
795 /* If ONOCR is set, don't transmit CRs when on column 0. */
796 else if (c == '\r' && ISSET(tp->t_oflag, ONOCR) && tp->t_column == 0) {
797 lwkt_reltoken(&tty_token);
798 return (-1);
801 tk_nout++;
802 tp->t_outcc++;
803 if (!ISSET(tp->t_lflag, FLUSHO) && clist_putc(c, &tp->t_outq)) {
804 lwkt_reltoken(&tty_token);
805 return (c);
808 col = tp->t_column;
809 switch (CCLASS(c)) {
810 case BACKSPACE:
811 if (col > 0)
812 --col;
813 break;
814 case CONTROL:
815 break;
816 case NEWLINE:
817 if (ISSET(tp->t_oflag, ONLCR | ONLRET))
818 col = 0;
819 break;
820 case RETURN:
821 col = 0;
822 break;
823 case ORDINARY:
824 ++col;
825 break;
826 case TAB:
827 col = (col + 8) & ~7;
828 break;
830 tp->t_column = col;
831 lwkt_reltoken(&tty_token);
832 return (-1);
836 * Ioctls for all tty devices. Called after line-discipline specific ioctl
837 * has been called to do discipline-specific functions and/or reject any
838 * of these ioctl commands.
840 /* ARGSUSED */
842 ttioctl(struct tty *tp, u_long cmd, void *data, int flag)
844 struct thread *td = curthread;
845 struct lwp *lp = td->td_lwp;
846 struct proc *p = td->td_proc;
847 struct pgrp *opgrp;
848 struct tty *otp;
849 int error;
851 KKASSERT(p);
852 lwkt_gettoken(&tty_token);
853 lwkt_gettoken(&p->p_token);
855 /* If the ioctl involves modification, hang if in the background. */
856 switch (cmd) {
857 case TIOCCBRK:
858 case TIOCCONS:
859 case TIOCDRAIN:
860 case TIOCEXCL:
861 case TIOCFLUSH:
862 #ifdef TIOCHPCL
863 case TIOCHPCL:
864 #endif
865 case TIOCNXCL:
866 case TIOCSBRK:
867 case TIOCSCTTY:
868 case TIOCSDRAINWAIT:
869 case TIOCSETA:
870 case TIOCSETAF:
871 case TIOCSETAW:
872 case TIOCSETD:
873 case TIOCSPGRP:
874 case TIOCSTART:
875 case TIOCSTAT:
876 case TIOCSTI:
877 case TIOCSTOP:
878 case TIOCSWINSZ:
879 while (isbackground(p, tp) && !(p->p_flags & P_PPWAIT) &&
880 !SIGISMEMBER(p->p_sigignore, SIGTTOU) &&
881 !SIGISMEMBER(lp->lwp_sigmask, SIGTTOU)) {
882 if (p->p_pgrp->pg_jobc == 0) {
883 lwkt_reltoken(&p->p_token);
884 lwkt_reltoken(&tty_token);
885 return (EIO);
887 pgsignal(p->p_pgrp, SIGTTOU, 1);
888 error = ttysleep(tp, &lbolt, PCATCH, "ttybg1",
890 if (error) {
891 lwkt_reltoken(&p->p_token);
892 lwkt_reltoken(&tty_token);
893 return (error);
896 break;
899 switch (cmd) { /* Process the ioctl. */
900 case FIOASYNC: /* set/clear async i/o */
901 crit_enter();
902 if (*(int *)data)
903 SET(tp->t_state, TS_ASYNC);
904 else
905 CLR(tp->t_state, TS_ASYNC);
906 crit_exit();
907 break;
908 case FIONREAD: /* get # bytes to read */
909 crit_enter();
910 *(int *)data = ttnread(tp);
911 crit_exit();
912 break;
914 case FIOSETOWN:
916 * Policy -- Don't allow FIOSETOWN on someone else's
917 * controlling tty
919 if (tp->t_session != NULL && !isctty(p, tp)) {
920 lwkt_reltoken(&p->p_token);
921 lwkt_reltoken(&tty_token);
922 return (ENOTTY);
925 error = fsetown(*(int *)data, &tp->t_sigio);
926 if (error) {
927 lwkt_reltoken(&p->p_token);
928 lwkt_reltoken(&tty_token);
929 return (error);
931 break;
932 case FIOGETOWN:
933 if (tp->t_session != NULL && !isctty(p, tp)) {
934 lwkt_reltoken(&p->p_token);
935 lwkt_reltoken(&tty_token);
936 return (ENOTTY);
938 *(int *)data = fgetown(&tp->t_sigio);
939 break;
941 case TIOCEXCL: /* set exclusive use of tty */
942 crit_enter();
943 SET(tp->t_state, TS_XCLUDE);
944 crit_exit();
945 break;
946 case TIOCFLUSH: { /* flush buffers */
947 int flags = *(int *)data;
949 if (flags == 0)
950 flags = FREAD | FWRITE;
951 else
952 flags &= FREAD | FWRITE;
953 ttyflush(tp, flags);
954 break;
956 case TIOCCONS: /* become virtual console */
957 if (*(int *)data) {
958 if (constty && constty != tp &&
959 ISSET(constty->t_state, TS_CONNECTED)) {
960 lwkt_reltoken(&p->p_token);
961 lwkt_reltoken(&tty_token);
962 return (EBUSY);
964 #ifndef UCONSOLE
965 if ((error = priv_check(td, PRIV_ROOT)) != 0) {
966 lwkt_reltoken(&p->p_token);
967 lwkt_reltoken(&tty_token);
968 return (error);
970 #endif
971 constty = tp;
972 } else if (tp == constty)
973 constty = NULL;
974 break;
975 case TIOCDRAIN: /* wait till output drained */
976 error = ttywait(tp);
977 if (error) {
978 lwkt_reltoken(&p->p_token);
979 lwkt_reltoken(&tty_token);
980 return (error);
982 break;
983 case TIOCGETA: { /* get termios struct */
984 struct termios *t = (struct termios *)data;
986 bcopy(&tp->t_termios, t, sizeof(struct termios));
987 break;
989 case TIOCGETD: /* get line discipline */
990 *(int *)data = tp->t_line;
991 break;
992 case TIOCGWINSZ: /* get window size */
993 *(struct winsize *)data = tp->t_winsize;
994 break;
995 case TIOCGPGRP: /* get pgrp of tty */
996 if (!isctty(p, tp)) {
997 lwkt_reltoken(&p->p_token);
998 lwkt_reltoken(&tty_token);
999 return (ENOTTY);
1001 *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
1002 break;
1003 case TIOCGSID: /* get sid of tty */
1004 if (!isctty(p, tp)) {
1005 lwkt_reltoken(&p->p_token);
1006 lwkt_reltoken(&tty_token);
1007 return (ENOTTY);
1009 *(int *)data = tp->t_session->s_sid;
1010 break;
1011 #ifdef TIOCHPCL
1012 case TIOCHPCL: /* hang up on last close */
1013 crit_enter();
1014 SET(tp->t_cflag, HUPCL);
1015 crit_exit();
1016 break;
1017 #endif
1018 case TIOCNXCL: /* reset exclusive use of tty */
1019 crit_enter();
1020 CLR(tp->t_state, TS_XCLUDE);
1021 crit_exit();
1022 break;
1023 case TIOCOUTQ: /* output queue size */
1024 *(int *)data = tp->t_outq.c_cc;
1025 break;
1026 case TIOCSETA: /* set termios struct */
1027 case TIOCSETAW: /* drain output, set */
1028 case TIOCSETAF: { /* drn out, fls in, set */
1029 struct termios *t = (struct termios *)data;
1031 if (t->c_ispeed == 0)
1032 t->c_ispeed = t->c_ospeed;
1033 if (t->c_ispeed == 0)
1034 t->c_ispeed = tp->t_ospeed;
1035 if (t->c_ispeed == 0) {
1036 lwkt_reltoken(&p->p_token);
1037 lwkt_reltoken(&tty_token);
1038 return (EINVAL);
1040 crit_enter();
1041 if (cmd == TIOCSETAW || cmd == TIOCSETAF) {
1042 error = ttywait(tp);
1043 if (error) {
1044 crit_exit();
1045 lwkt_reltoken(&p->p_token);
1046 lwkt_reltoken(&tty_token);
1047 return (error);
1049 if (cmd == TIOCSETAF)
1050 ttyflush(tp, FREAD);
1052 if (!ISSET(t->c_cflag, CIGNORE)) {
1054 * Set device hardware.
1056 if (tp->t_param && (error = (*tp->t_param)(tp, t))) {
1057 crit_exit();
1058 lwkt_reltoken(&p->p_token);
1059 lwkt_reltoken(&tty_token);
1060 return (error);
1062 if (ISSET(t->c_cflag, CLOCAL) &&
1063 !ISSET(tp->t_cflag, CLOCAL)) {
1065 * XXX disconnections would be too hard to
1066 * get rid of without this kludge. The only
1067 * way to get rid of controlling terminals
1068 * is to exit from the session leader.
1070 CLR(tp->t_state, TS_ZOMBIE);
1072 wakeup(TSA_CARR_ON(tp));
1073 ttwakeup(tp);
1074 ttwwakeup(tp);
1076 if ((ISSET(tp->t_state, TS_CARR_ON) ||
1077 ISSET(t->c_cflag, CLOCAL)) &&
1078 !ISSET(tp->t_state, TS_ZOMBIE))
1079 SET(tp->t_state, TS_CONNECTED);
1080 else
1081 CLR(tp->t_state, TS_CONNECTED);
1082 tp->t_cflag = t->c_cflag;
1083 tp->t_ispeed = t->c_ispeed;
1084 if (t->c_ospeed != 0)
1085 tp->t_ospeed = t->c_ospeed;
1086 ttsetwater(tp);
1088 if (ISSET(t->c_lflag, ICANON) != ISSET(tp->t_lflag, ICANON) &&
1089 cmd != TIOCSETAF) {
1090 if (ISSET(t->c_lflag, ICANON))
1091 SET(tp->t_lflag, PENDIN);
1092 else {
1094 * XXX we really shouldn't allow toggling
1095 * ICANON while we're in a non-termios line
1096 * discipline. Now we have to worry about
1097 * panicing for a null queue.
1099 if (tp->t_canq.c_cbreserved > 0 &&
1100 tp->t_rawq.c_cbreserved > 0) {
1101 catq(&tp->t_rawq, &tp->t_canq);
1103 * XXX the queue limits may be
1104 * different, so the old queue
1105 * swapping method no longer works.
1107 catq(&tp->t_canq, &tp->t_rawq);
1109 CLR(tp->t_lflag, PENDIN);
1111 ttwakeup(tp);
1113 tp->t_iflag = t->c_iflag;
1114 tp->t_oflag = t->c_oflag;
1116 * Make the EXTPROC bit read only.
1118 if (ISSET(tp->t_lflag, EXTPROC))
1119 SET(t->c_lflag, EXTPROC);
1120 else
1121 CLR(t->c_lflag, EXTPROC);
1122 tp->t_lflag = t->c_lflag | ISSET(tp->t_lflag, PENDIN);
1123 if (t->c_cc[VMIN] != tp->t_cc[VMIN] ||
1124 t->c_cc[VTIME] != tp->t_cc[VTIME])
1125 ttwakeup(tp);
1126 bcopy(t->c_cc, tp->t_cc, sizeof(t->c_cc));
1127 crit_exit();
1128 break;
1130 case TIOCSETD: { /* set line discipline */
1131 int t = *(int *)data;
1132 cdev_t device = tp->t_dev;
1134 if ((u_int)t >= nlinesw) {
1135 lwkt_reltoken(&p->p_token);
1136 lwkt_reltoken(&tty_token);
1137 return (ENXIO);
1139 if (t != tp->t_line) {
1140 crit_enter();
1141 (*linesw[tp->t_line].l_close)(tp, flag);
1142 error = (*linesw[t].l_open)(device, tp);
1143 if (error) {
1144 (void)(*linesw[tp->t_line].l_open)(device, tp);
1145 crit_exit();
1146 lwkt_reltoken(&p->p_token);
1147 lwkt_reltoken(&tty_token);
1148 return (error);
1150 tp->t_line = t;
1151 crit_exit();
1153 break;
1155 case TIOCSTART: /* start output, like ^Q */
1156 crit_enter();
1157 if (ISSET(tp->t_state, TS_TTSTOP) ||
1158 ISSET(tp->t_lflag, FLUSHO)) {
1159 CLR(tp->t_lflag, FLUSHO);
1160 CLR(tp->t_state, TS_TTSTOP);
1161 ttstart(tp);
1163 crit_exit();
1164 break;
1165 case TIOCSTI: /* simulate terminal input */
1166 if ((flag & FREAD) == 0 && priv_check(td, PRIV_ROOT)) {
1167 lwkt_reltoken(&p->p_token);
1168 lwkt_reltoken(&tty_token);
1169 return (EPERM);
1171 if (!isctty(p, tp) && priv_check(td, PRIV_ROOT)) {
1172 lwkt_reltoken(&p->p_token);
1173 lwkt_reltoken(&tty_token);
1174 return (EACCES);
1176 crit_enter();
1177 (*linesw[tp->t_line].l_rint)(*(u_char *)data, tp);
1178 crit_exit();
1179 break;
1180 case TIOCSTOP: /* stop output, like ^S */
1181 crit_enter();
1182 if (!ISSET(tp->t_state, TS_TTSTOP)) {
1183 SET(tp->t_state, TS_TTSTOP);
1184 (*tp->t_stop)(tp, 0);
1186 crit_exit();
1187 break;
1188 case TIOCSCTTY: /* become controlling tty */
1189 /* Session ctty vnode pointer set in vnode layer. */
1190 if (!SESS_LEADER(p) ||
1191 ((p->p_session->s_ttyvp || tp->t_session) &&
1192 (tp->t_session != p->p_session))) {
1193 lwkt_reltoken(&p->p_token);
1194 lwkt_reltoken(&tty_token);
1195 return (EPERM);
1197 ttyhold(tp);
1198 tp->t_session = p->p_session;
1199 opgrp = tp->t_pgrp;
1200 pgref(p->p_pgrp);
1201 tp->t_pgrp = p->p_pgrp;
1202 otp = p->p_session->s_ttyp;
1203 p->p_session->s_ttyp = tp;
1204 p->p_flags |= P_CONTROLT;
1205 if (otp)
1206 ttyunhold(otp);
1207 if (opgrp) {
1208 pgrel(opgrp);
1209 opgrp = NULL;
1211 break;
1212 case TIOCSPGRP: { /* set pgrp of tty */
1213 pid_t pgid = *(int *)data;
1215 if (!isctty(p, tp)) {
1216 lwkt_reltoken(&p->p_token);
1217 lwkt_reltoken(&tty_token);
1218 return (ENOTTY);
1220 else if (pgid < 1 || pgid > PID_MAX) {
1221 lwkt_reltoken(&p->p_token);
1222 lwkt_reltoken(&tty_token);
1223 return (EINVAL);
1224 } else {
1225 struct pgrp *pgrp = pgfind(pgid);
1226 if (pgrp == NULL || pgrp->pg_session != p->p_session) {
1227 if (pgrp)
1228 pgrel(pgrp);
1229 lwkt_reltoken(&p->p_token);
1230 lwkt_reltoken(&tty_token);
1231 return (EPERM);
1233 opgrp = tp->t_pgrp;
1234 tp->t_pgrp = pgrp;
1235 if (opgrp) {
1236 pgrel(opgrp);
1237 opgrp = NULL;
1240 break;
1242 case TIOCSTAT: /* simulate control-T */
1243 crit_enter();
1244 ttyinfo(tp);
1245 crit_exit();
1246 break;
1247 case TIOCSWINSZ: /* set window size */
1248 if (bcmp((caddr_t)&tp->t_winsize, data,
1249 sizeof (struct winsize))) {
1250 tp->t_winsize = *(struct winsize *)data;
1251 pgsignal(tp->t_pgrp, SIGWINCH, 1);
1253 break;
1254 case TIOCSDRAINWAIT:
1255 error = priv_check(td, PRIV_ROOT);
1256 if (error) {
1257 lwkt_reltoken(&p->p_token);
1258 lwkt_reltoken(&tty_token);
1259 return (error);
1261 tp->t_timeout = *(int *)data * hz;
1262 wakeup(TSA_OCOMPLETE(tp));
1263 wakeup(TSA_OLOWAT(tp));
1264 break;
1265 case TIOCGDRAINWAIT:
1266 *(int *)data = tp->t_timeout / hz;
1267 break;
1268 default:
1269 lwkt_reltoken(&p->p_token);
1270 lwkt_reltoken(&tty_token);
1271 return (ENOIOCTL);
1273 lwkt_reltoken(&p->p_token);
1274 lwkt_reltoken(&tty_token);
1275 return (0);
1278 static struct filterops ttyread_filtops =
1279 { FILTEROP_ISFD|FILTEROP_MPSAFE, NULL, filt_ttyrdetach, filt_ttyread };
1280 static struct filterops ttywrite_filtops =
1281 { FILTEROP_ISFD|FILTEROP_MPSAFE, NULL, filt_ttywdetach, filt_ttywrite };
1284 ttykqfilter(struct dev_kqfilter_args *ap)
1286 cdev_t dev = ap->a_head.a_dev;
1287 struct knote *kn = ap->a_kn;
1288 struct tty *tp = dev->si_tty;
1289 struct klist *klist;
1291 ap->a_result = 0;
1293 lwkt_gettoken(&tty_token);
1294 switch (kn->kn_filter) {
1295 case EVFILT_READ:
1296 klist = &tp->t_rkq.ki_note;
1297 kn->kn_fop = &ttyread_filtops;
1298 break;
1299 case EVFILT_WRITE:
1300 klist = &tp->t_wkq.ki_note;
1301 kn->kn_fop = &ttywrite_filtops;
1302 break;
1303 default:
1304 ap->a_result = EOPNOTSUPP;
1305 lwkt_reltoken(&tty_token);
1306 return (0);
1308 lwkt_reltoken(&tty_token);
1309 kn->kn_hook = (caddr_t)dev;
1310 knote_insert(klist, kn);
1312 return (0);
1315 static void
1316 filt_ttyrdetach(struct knote *kn)
1318 struct tty *tp = ((cdev_t)kn->kn_hook)->si_tty;
1320 lwkt_gettoken(&tty_token);
1321 knote_remove(&tp->t_rkq.ki_note, kn);
1322 lwkt_reltoken(&tty_token);
1325 static int
1326 filt_ttyread(struct knote *kn, long hint)
1328 struct tty *tp = ((cdev_t)kn->kn_hook)->si_tty;
1330 lwkt_gettoken(&tty_token);
1331 kn->kn_data = ttnread(tp);
1332 if (ISSET(tp->t_state, TS_ZOMBIE)) {
1333 kn->kn_flags |= (EV_EOF | EV_NODATA);
1334 lwkt_reltoken(&tty_token);
1335 return (1);
1337 lwkt_reltoken(&tty_token);
1338 return (kn->kn_data > 0);
1341 static void
1342 filt_ttywdetach(struct knote *kn)
1344 struct tty *tp = ((cdev_t)kn->kn_hook)->si_tty;
1346 lwkt_gettoken(&tty_token);
1347 knote_remove(&tp->t_wkq.ki_note, kn);
1348 lwkt_reltoken(&tty_token);
1351 static int
1352 filt_ttywrite(struct knote *kn, long hint)
1354 struct tty *tp = ((cdev_t)kn->kn_hook)->si_tty;
1355 int ret;
1357 lwkt_gettoken(&tty_token);
1358 kn->kn_data = tp->t_outq.c_cc;
1359 if (ISSET(tp->t_state, TS_ZOMBIE)) {
1360 lwkt_reltoken(&tty_token);
1361 return (1);
1363 ret = (kn->kn_data <= tp->t_olowat &&
1364 ISSET(tp->t_state, TS_CONNECTED));
1365 lwkt_reltoken(&tty_token);
1366 return ret;
1370 * Must be called while in a critical section.
1371 * NOTE: tty_token must be held.
1373 static int
1374 ttnread(struct tty *tp)
1376 int nread;
1378 ASSERT_LWKT_TOKEN_HELD(&tty_token);
1379 if (ISSET(tp->t_lflag, PENDIN))
1380 ttypend(tp);
1381 nread = tp->t_canq.c_cc;
1382 if (!ISSET(tp->t_lflag, ICANON)) {
1383 nread += tp->t_rawq.c_cc;
1384 if (nread < tp->t_cc[VMIN] && tp->t_cc[VTIME] == 0)
1385 nread = 0;
1387 return (nread);
1391 * Wait for output to drain.
1394 ttywait(struct tty *tp)
1396 int error;
1398 error = 0;
1399 crit_enter();
1400 lwkt_gettoken(&tty_token);
1401 while ((tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)) &&
1402 ISSET(tp->t_state, TS_CONNECTED) && tp->t_oproc) {
1403 (*tp->t_oproc)(tp);
1404 if ((tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)) &&
1405 ISSET(tp->t_state, TS_CONNECTED)) {
1406 SET(tp->t_state, TS_SO_OCOMPLETE);
1407 error = ttysleep(tp, TSA_OCOMPLETE(tp),
1408 PCATCH, "ttywai",
1409 tp->t_timeout);
1410 if (error) {
1411 if (error == EWOULDBLOCK)
1412 error = EIO;
1413 break;
1415 } else
1416 break;
1418 if (!error && (tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)))
1419 error = EIO;
1420 lwkt_reltoken(&tty_token);
1421 crit_exit();
1422 return (error);
1426 * Flush if successfully wait.
1428 static int
1429 ttywflush(struct tty *tp)
1431 int error;
1433 if ((error = ttywait(tp)) == 0)
1434 ttyflush(tp, FREAD);
1435 return (error);
1439 * Flush tty read and/or write queues, notifying anyone waiting.
1441 void
1442 ttyflush(struct tty *tp, int rw)
1444 crit_enter();
1445 lwkt_gettoken(&tty_token);
1446 #if 0
1447 again:
1448 #endif
1449 if (rw & FWRITE) {
1450 FLUSHQ(&tp->t_outq);
1451 CLR(tp->t_state, TS_TTSTOP);
1453 (*tp->t_stop)(tp, rw);
1454 if (rw & FREAD) {
1455 FLUSHQ(&tp->t_canq);
1456 FLUSHQ(&tp->t_rawq);
1457 CLR(tp->t_lflag, PENDIN);
1458 tp->t_rocount = 0;
1459 tp->t_rocol = 0;
1460 CLR(tp->t_state, TS_LOCAL);
1461 ttwakeup(tp);
1462 if (ISSET(tp->t_state, TS_TBLOCK)) {
1463 if (rw & FWRITE)
1464 FLUSHQ(&tp->t_outq);
1465 ttyunblock(tp);
1468 * Don't let leave any state that might clobber the
1469 * next line discipline (although we should do more
1470 * to send the START char). Not clearing the state
1471 * may have caused the "putc to a clist with no
1472 * reserved cblocks" panic/kprintf.
1474 CLR(tp->t_state, TS_TBLOCK);
1476 #if 0 /* forget it, sleeping isn't always safe and we don't know when it is */
1477 if (ISSET(tp->t_iflag, IXOFF)) {
1479 * XXX wait a bit in the hope that the stop
1480 * character (if any) will go out. Waiting
1481 * isn't good since it allows races. This
1482 * will be fixed when the stop character is
1483 * put in a special queue. Don't bother with
1484 * the checks in ttywait() since the timeout
1485 * will save us.
1487 SET(tp->t_state, TS_SO_OCOMPLETE);
1488 ttysleep(tp, TSA_OCOMPLETE(tp), 0,
1489 "ttyfls", hz / 10);
1491 * Don't try sending the stop character again.
1493 CLR(tp->t_state, TS_TBLOCK);
1494 goto again;
1496 #endif
1499 if (rw & FWRITE) {
1500 FLUSHQ(&tp->t_outq);
1501 ttwwakeup(tp);
1503 lwkt_reltoken(&tty_token);
1504 crit_exit();
1508 * Copy in the default termios characters.
1510 void
1511 termioschars(struct termios *t)
1513 lwkt_gettoken(&tty_token);
1514 bcopy(ttydefchars, t->c_cc, sizeof t->c_cc);
1515 lwkt_reltoken(&tty_token);
1519 * Old interface.
1521 void
1522 ttychars(struct tty *tp)
1524 lwkt_gettoken(&tty_token);
1525 termioschars(&tp->t_termios);
1526 lwkt_reltoken(&tty_token);
1530 * Handle input high water. Send stop character for the IXOFF case. Turn
1531 * on our input flow control bit and propagate the changes to the driver.
1532 * XXX the stop character should be put in a special high priority queue.
1534 void
1535 ttyblock(struct tty *tp)
1537 lwkt_gettoken(&tty_token);
1538 SET(tp->t_state, TS_TBLOCK);
1539 if (ISSET(tp->t_iflag, IXOFF) && tp->t_cc[VSTOP] != _POSIX_VDISABLE &&
1540 clist_putc(tp->t_cc[VSTOP], &tp->t_outq) != 0)
1541 CLR(tp->t_state, TS_TBLOCK); /* try again later */
1542 ttstart(tp);
1543 lwkt_reltoken(&tty_token);
1547 * Handle input low water. Send start character for the IXOFF case. Turn
1548 * off our input flow control bit and propagate the changes to the driver.
1549 * XXX the start character should be put in a special high priority queue.
1551 static void
1552 ttyunblock(struct tty *tp)
1554 lwkt_gettoken(&tty_token);
1555 CLR(tp->t_state, TS_TBLOCK);
1556 if (ISSET(tp->t_iflag, IXOFF) && tp->t_cc[VSTART] != _POSIX_VDISABLE &&
1557 clist_putc(tp->t_cc[VSTART], &tp->t_outq) != 0)
1558 SET(tp->t_state, TS_TBLOCK); /* try again later */
1559 ttstart(tp);
1560 lwkt_reltoken(&tty_token);
1563 #ifdef notyet
1564 /* Not used by any current (i386) drivers. */
1566 * Restart after an inter-char delay.
1568 void
1569 ttrstrt(void *tp_arg)
1571 struct tty *tp;
1573 KASSERT(tp_arg != NULL, ("ttrstrt"));
1575 tp = tp_arg;
1576 crit_enter();
1577 lwkt_gettoken(&tty_token);
1578 CLR(tp->t_state, TS_TIMEOUT);
1579 ttstart(tp);
1580 lwkt_reltoken(&tty_token);
1581 crit_exit();
1583 #endif
1586 ttstart(struct tty *tp)
1588 lwkt_gettoken(&tty_token);
1589 if (tp->t_oproc != NULL) /* XXX: Kludge for pty. */
1590 (*tp->t_oproc)(tp);
1591 lwkt_reltoken(&tty_token);
1592 return (0);
1596 * "close" a line discipline
1599 ttylclose(struct tty *tp, int flag)
1601 lwkt_gettoken(&tty_token);
1602 if (flag & FNONBLOCK || ttywflush(tp))
1603 ttyflush(tp, FREAD | FWRITE);
1604 lwkt_reltoken(&tty_token);
1605 return (0);
1608 void
1609 ttyhold(struct tty *tp)
1611 ++tp->t_refs;
1614 void
1615 ttyunhold(struct tty *tp)
1617 if (tp->t_unhold)
1618 tp->t_unhold(tp);
1619 else
1620 --tp->t_refs;
1624 * Handle modem control transition on a tty.
1625 * Flag indicates new state of carrier.
1626 * Returns 0 if the line should be turned off, otherwise 1.
1629 ttymodem(struct tty *tp, int flag)
1631 lwkt_gettoken(&tty_token);
1632 if (ISSET(tp->t_state, TS_CARR_ON) && ISSET(tp->t_cflag, MDMBUF)) {
1634 * MDMBUF: do flow control according to carrier flag
1635 * XXX TS_CAR_OFLOW doesn't do anything yet. TS_TTSTOP
1636 * works if IXON and IXANY are clear.
1638 if (flag) {
1639 CLR(tp->t_state, TS_CAR_OFLOW);
1640 CLR(tp->t_state, TS_TTSTOP);
1641 ttstart(tp);
1642 } else if (!ISSET(tp->t_state, TS_CAR_OFLOW)) {
1643 SET(tp->t_state, TS_CAR_OFLOW);
1644 SET(tp->t_state, TS_TTSTOP);
1645 (*tp->t_stop)(tp, 0);
1647 } else if (flag == 0) {
1649 * Lost carrier.
1651 CLR(tp->t_state, TS_CARR_ON);
1652 if (ISSET(tp->t_state, TS_ISOPEN) &&
1653 !ISSET(tp->t_cflag, CLOCAL)) {
1654 SET(tp->t_state, TS_ZOMBIE);
1655 CLR(tp->t_state, TS_CONNECTED);
1656 if (tp->t_session && tp->t_session->s_leader)
1657 ksignal(tp->t_session->s_leader, SIGHUP);
1658 ttyflush(tp, FREAD | FWRITE);
1659 lwkt_reltoken(&tty_token);
1660 return (0);
1662 } else {
1664 * Carrier now on.
1666 SET(tp->t_state, TS_CARR_ON);
1667 if (!ISSET(tp->t_state, TS_ZOMBIE))
1668 SET(tp->t_state, TS_CONNECTED);
1669 wakeup(TSA_CARR_ON(tp));
1670 ttwakeup(tp);
1671 ttwwakeup(tp);
1673 lwkt_reltoken(&tty_token);
1674 return (1);
1678 * Reinput pending characters after state switch
1679 * call from a critical section.
1681 static void
1682 ttypend(struct tty *tp)
1684 struct clist tq;
1685 int c;
1687 lwkt_gettoken(&tty_token);
1688 CLR(tp->t_lflag, PENDIN);
1689 SET(tp->t_state, TS_TYPEN);
1691 * XXX this assumes too much about clist internals. It may even
1692 * fail if the cblock slush pool is empty. We can't allocate more
1693 * cblocks here because we are called from an interrupt handler
1694 * and clist_alloc_cblocks() can wait.
1696 tq = tp->t_rawq;
1697 bzero(&tp->t_rawq, sizeof tp->t_rawq);
1698 tp->t_rawq.c_cbmax = tq.c_cbmax;
1699 tp->t_rawq.c_cbreserved = tq.c_cbreserved;
1700 while ((c = clist_getc(&tq)) >= 0)
1701 ttyinput(c, tp);
1702 CLR(tp->t_state, TS_TYPEN);
1703 lwkt_reltoken(&tty_token);
1707 * Process a read call on a tty device.
1710 ttread(struct tty *tp, struct uio *uio, int flag)
1712 struct clist *qp;
1713 int c;
1714 tcflag_t lflag;
1715 cc_t *cc = tp->t_cc;
1716 struct proc *pp;
1717 struct lwp *lp;
1718 int first, error = 0;
1719 int has_stime = 0, last_cc = 0;
1720 long slp = 0; /* XXX this should be renamed `timo'. */
1721 struct timeval stime;
1723 lp = curthread->td_lwp;
1724 stime.tv_sec = 0; /* fix compiler warnings */
1725 stime.tv_usec = 0;
1727 lwkt_gettoken(&tty_token);
1728 loop:
1729 crit_enter();
1730 lflag = tp->t_lflag;
1732 * take pending input first
1734 if (ISSET(lflag, PENDIN)) {
1735 ttypend(tp);
1736 splz(); /* reduce latency */
1737 lflag = tp->t_lflag; /* XXX ttypend() clobbers it */
1741 * Hang process if it's in the background.
1743 if ((pp = curproc) != NULL)
1744 lwkt_gettoken(&pp->p_token);
1745 if (pp && isbackground(pp, tp)) {
1746 crit_exit();
1747 if (SIGISMEMBER(pp->p_sigignore, SIGTTIN) ||
1748 SIGISMEMBER(lp->lwp_sigmask, SIGTTIN) ||
1749 (pp->p_flags & P_PPWAIT) || pp->p_pgrp->pg_jobc == 0) {
1750 lwkt_reltoken(&pp->p_token);
1751 lwkt_reltoken(&tty_token);
1752 return (EIO);
1754 pgsignal(pp->p_pgrp, SIGTTIN, 1);
1755 error = ttysleep(tp, &lbolt, PCATCH, "ttybg2", 0);
1756 if (error) {
1757 lwkt_reltoken(&pp->p_token);
1758 lwkt_reltoken(&tty_token);
1759 return (error);
1761 lwkt_reltoken(&pp->p_token);
1762 goto loop;
1764 if (pp)
1765 lwkt_reltoken(&pp->p_token);
1767 if (ISSET(tp->t_state, TS_ZOMBIE)) {
1768 crit_exit();
1769 lwkt_reltoken(&tty_token);
1770 return (0); /* EOF */
1774 * If canonical, use the canonical queue,
1775 * else use the raw queue.
1777 * (should get rid of clists...)
1779 qp = ISSET(lflag, ICANON) ? &tp->t_canq : &tp->t_rawq;
1781 if (flag & IO_NDELAY) {
1782 if (qp->c_cc > 0)
1783 goto read;
1784 if (!ISSET(lflag, ICANON) && cc[VMIN] == 0) {
1785 crit_exit();
1786 lwkt_reltoken(&tty_token);
1787 return (0);
1789 crit_exit();
1790 lwkt_reltoken(&tty_token);
1791 return (EWOULDBLOCK);
1793 if (!ISSET(lflag, ICANON)) {
1794 int m = cc[VMIN];
1795 long t = cc[VTIME];
1796 struct timeval timecopy;
1799 * Check each of the four combinations.
1800 * (m > 0 && t == 0) is the normal read case.
1801 * It should be fairly efficient, so we check that and its
1802 * companion case (m == 0 && t == 0) first.
1803 * For the other two cases, we compute the target sleep time
1804 * into slp.
1806 if (t == 0) {
1807 if (qp->c_cc < m)
1808 goto sleep;
1809 if (qp->c_cc > 0)
1810 goto read;
1812 /* m, t and qp->c_cc are all 0. 0 is enough input. */
1813 crit_exit();
1814 lwkt_reltoken(&tty_token);
1815 return (0);
1817 t *= 100000; /* time in us */
1818 #define diff(t1, t2) (((t1).tv_sec - (t2).tv_sec) * 1000000 + \
1819 ((t1).tv_usec - (t2).tv_usec))
1820 if (m > 0) {
1821 if (qp->c_cc <= 0)
1822 goto sleep;
1823 if (qp->c_cc >= m)
1824 goto read;
1825 getmicrotime(&timecopy);
1826 if (has_stime == 0) {
1827 /* first character, start timer */
1828 has_stime = 1;
1829 stime = timecopy;
1830 slp = t;
1831 } else if (qp->c_cc > last_cc) {
1832 /* got a character, restart timer */
1833 stime = timecopy;
1834 slp = t;
1835 } else {
1836 /* nothing, check expiration */
1837 slp = t - diff(timecopy, stime);
1838 if (slp <= 0)
1839 goto read;
1841 last_cc = qp->c_cc;
1842 } else { /* m == 0 */
1843 if (qp->c_cc > 0)
1844 goto read;
1845 getmicrotime(&timecopy);
1846 if (has_stime == 0) {
1847 has_stime = 1;
1848 stime = timecopy;
1849 slp = t;
1850 } else {
1851 slp = t - diff(timecopy, stime);
1852 if (slp <= 0) {
1853 /* Timed out, but 0 is enough input. */
1854 crit_exit();
1855 lwkt_reltoken(&tty_token);
1856 return (0);
1860 #undef diff
1862 * Rounding down may make us wake up just short
1863 * of the target, so we round up.
1864 * The formula is ceiling(slp * hz/1000000).
1865 * 32-bit arithmetic is enough for hz < 169.
1866 * XXX see tvtohz() for how to avoid overflow if hz
1867 * is large (divide by `tick' and/or arrange to
1868 * use tvtohz() if hz is large).
1870 slp = (long) (((u_long)slp * hz) + 999999) / 1000000;
1871 goto sleep;
1873 if (qp->c_cc <= 0) {
1874 sleep:
1876 * There is no input, or not enough input and we can block.
1878 error = ttysleep(tp, TSA_HUP_OR_INPUT(tp), PCATCH,
1879 ISSET(tp->t_state, TS_CONNECTED) ?
1880 "ttyin" : "ttyhup", (int)slp);
1881 crit_exit();
1882 if (error == EWOULDBLOCK)
1883 error = 0;
1884 else if (error) {
1885 lwkt_reltoken(&tty_token);
1886 return (error);
1889 * XXX what happens if another process eats some input
1890 * while we are asleep (not just here)? It would be
1891 * safest to detect changes and reset our state variables
1892 * (has_stime and last_cc).
1894 slp = 0;
1895 goto loop;
1897 read:
1898 crit_exit();
1900 * Input present, check for input mapping and processing.
1902 first = 1;
1903 if (ISSET(lflag, ICANON | ISIG))
1904 goto slowcase;
1905 for (;;) {
1906 char ibuf[IBUFSIZ];
1907 int icc;
1909 icc = (int)szmin(uio->uio_resid, IBUFSIZ);
1910 icc = q_to_b(qp, ibuf, icc);
1911 if (icc <= 0) {
1912 if (first)
1913 goto loop;
1914 break;
1916 error = uiomove(ibuf, (size_t)icc, uio);
1918 * XXX if there was an error then we should ungetc() the
1919 * unmoved chars and reduce icc here.
1921 if (error)
1922 break;
1923 if (uio->uio_resid == 0)
1924 break;
1925 first = 0;
1927 goto out;
1928 slowcase:
1929 for (;;) {
1930 c = clist_getc(qp);
1931 if (c < 0) {
1932 if (first)
1933 goto loop;
1934 break;
1937 * delayed suspend (^Y)
1939 if (CCEQ(cc[VDSUSP], c) &&
1940 ISSET(lflag, IEXTEN | ISIG) == (IEXTEN | ISIG)) {
1941 pgsignal(tp->t_pgrp, SIGTSTP, 1);
1942 if (first) {
1943 error = ttysleep(tp, &lbolt, PCATCH,
1944 "ttybg3", 0);
1945 if (error)
1946 break;
1947 goto loop;
1949 break;
1952 * Interpret EOF only in canonical mode.
1954 if (CCEQ(cc[VEOF], c) && ISSET(lflag, ICANON))
1955 break;
1957 * Give user character.
1959 error = ureadc(c, uio);
1960 if (error)
1961 /* XXX should ungetc(c, qp). */
1962 break;
1963 if (uio->uio_resid == 0)
1964 break;
1966 * In canonical mode check for a "break character"
1967 * marking the end of a "line of input".
1969 if (ISSET(lflag, ICANON) && TTBREAKC(c, lflag))
1970 break;
1971 first = 0;
1974 out:
1976 * Look to unblock input now that (presumably)
1977 * the input queue has gone down.
1979 crit_enter();
1980 if (ISSET(tp->t_state, TS_TBLOCK) &&
1981 tp->t_rawq.c_cc + tp->t_canq.c_cc <= tp->t_ilowat)
1982 ttyunblock(tp);
1983 crit_exit();
1985 lwkt_reltoken(&tty_token);
1986 return (error);
1990 * Check the output queue on tp for space for a kernel message (from uprintf
1991 * or tprintf). Allow some space over the normal hiwater mark so we don't
1992 * lose messages due to normal flow control, but don't let the tty run amok.
1993 * Sleeps here are not interruptible, but we return prematurely if new signals
1994 * arrive.
1997 ttycheckoutq(struct tty *tp, int wait)
1999 struct lwp *lp = curthread->td_lwp;
2000 int hiwat;
2001 sigset_t oldset, newset;
2003 lwkt_gettoken(&tty_token);
2004 hiwat = tp->t_ohiwat;
2005 SIGEMPTYSET(oldset);
2006 SIGEMPTYSET(newset);
2007 crit_enter();
2008 if (wait)
2009 oldset = lwp_sigpend(lp);
2010 if (tp->t_outq.c_cc > hiwat + OBUFSIZ + 100) {
2011 while (tp->t_outq.c_cc > hiwat) {
2012 ttstart(tp);
2013 if (tp->t_outq.c_cc <= hiwat)
2014 break;
2015 if (wait)
2016 newset = lwp_sigpend(lp);
2017 if (!wait || SIGSETNEQ(oldset, newset)) {
2018 crit_exit();
2019 lwkt_reltoken(&tty_token);
2020 return (0);
2022 SET(tp->t_state, TS_SO_OLOWAT);
2023 tsleep(TSA_OLOWAT(tp), 0, "ttoutq", hz);
2026 crit_exit();
2027 lwkt_reltoken(&tty_token);
2028 return (1);
2032 * Process a write call on a tty device.
2035 ttwrite(struct tty *tp, struct uio *uio, int flag)
2037 char *cp = NULL;
2038 int cc, ce;
2039 struct proc *pp;
2040 struct lwp *lp;
2041 int i, hiwat, error;
2042 size_t cnt;
2044 char obuf[OBUFSIZ];
2046 lwkt_gettoken(&tty_token);
2047 lp = curthread->td_lwp;
2048 hiwat = tp->t_ohiwat;
2049 cnt = uio->uio_resid;
2050 error = 0;
2051 cc = 0;
2052 loop:
2053 crit_enter();
2054 if (ISSET(tp->t_state, TS_ZOMBIE)) {
2055 crit_exit();
2056 if (uio->uio_resid == cnt)
2057 error = EIO;
2058 goto out;
2060 if (!ISSET(tp->t_state, TS_CONNECTED)) {
2061 if (flag & IO_NDELAY) {
2062 crit_exit();
2063 error = EWOULDBLOCK;
2064 goto out;
2066 error = ttysleep(tp, TSA_CARR_ON(tp), PCATCH, "ttydcd", 0);
2067 crit_exit();
2068 if (error)
2069 goto out;
2070 goto loop;
2072 crit_exit();
2075 * Hang the process if it's in the background.
2077 if ((pp = curproc) != NULL)
2078 lwkt_gettoken(&pp->p_token);
2079 if (pp && isbackground(pp, tp) &&
2080 ISSET(tp->t_lflag, TOSTOP) && !(pp->p_flags & P_PPWAIT) &&
2081 !SIGISMEMBER(pp->p_sigignore, SIGTTOU) &&
2082 !SIGISMEMBER(lp->lwp_sigmask, SIGTTOU)) {
2083 if (pp->p_pgrp->pg_jobc == 0) {
2084 error = EIO;
2085 lwkt_reltoken(&pp->p_token);
2086 goto out;
2088 pgsignal(pp->p_pgrp, SIGTTOU, 1);
2089 lwkt_reltoken(&pp->p_token);
2090 error = ttysleep(tp, &lbolt, PCATCH, "ttybg4", 0);
2091 if (error)
2092 goto out;
2093 goto loop;
2095 if (pp)
2096 lwkt_reltoken(&pp->p_token);
2098 * Process the user's data in at most OBUFSIZ chunks. Perform any
2099 * output translation. Keep track of high water mark, sleep on
2100 * overflow awaiting device aid in acquiring new space.
2102 while (uio->uio_resid > 0 || cc > 0) {
2103 if (ISSET(tp->t_lflag, FLUSHO)) {
2104 uio->uio_resid = 0;
2105 lwkt_reltoken(&tty_token);
2106 return (0);
2108 if (tp->t_outq.c_cc > hiwat)
2109 goto ovhiwat;
2111 * Grab a hunk of data from the user, unless we have some
2112 * leftover from last time.
2114 if (cc == 0) {
2115 cc = szmin(uio->uio_resid, OBUFSIZ);
2116 cp = obuf;
2117 error = uiomove(cp, (size_t)cc, uio);
2118 if (error) {
2119 cc = 0;
2120 break;
2124 * If nothing fancy need be done, grab those characters we
2125 * can handle without any of ttyoutput's processing and
2126 * just transfer them to the output q. For those chars
2127 * which require special processing (as indicated by the
2128 * bits in char_type), call ttyoutput. After processing
2129 * a hunk of data, look for FLUSHO so ^O's will take effect
2130 * immediately.
2132 while (cc > 0) {
2133 if (!ISSET(tp->t_oflag, OPOST))
2134 ce = cc;
2135 else {
2136 ce = cc - scanc((u_int)cc, (u_char *)cp,
2137 char_type, CCLASSMASK);
2139 * If ce is zero, then we're processing
2140 * a special character through ttyoutput.
2142 if (ce == 0) {
2143 tp->t_rocount = 0;
2144 if (ttyoutput(*cp, tp) >= 0) {
2145 /* No Clists, wait a bit. */
2146 ttstart(tp);
2147 if (flag & IO_NDELAY) {
2148 error = EWOULDBLOCK;
2149 goto out;
2151 error = ttysleep(tp, &lbolt,
2152 PCATCH,
2153 "ttybf1", 0);
2154 if (error)
2155 goto out;
2156 goto loop;
2158 cp++;
2159 cc--;
2160 if (ISSET(tp->t_lflag, FLUSHO) ||
2161 tp->t_outq.c_cc > hiwat)
2162 goto ovhiwat;
2163 continue;
2167 * A bunch of normal characters have been found.
2168 * Transfer them en masse to the output queue and
2169 * continue processing at the top of the loop.
2170 * If there are any further characters in this
2171 * <= OBUFSIZ chunk, the first should be a character
2172 * requiring special handling by ttyoutput.
2174 tp->t_rocount = 0;
2175 i = b_to_q(cp, ce, &tp->t_outq);
2176 ce -= i;
2177 tp->t_column += ce;
2178 cp += ce, cc -= ce, tk_nout += ce;
2179 tp->t_outcc += ce;
2180 if (i > 0) {
2181 /* No Clists, wait a bit. */
2182 ttstart(tp);
2183 if (flag & IO_NDELAY) {
2184 error = EWOULDBLOCK;
2185 goto out;
2187 error = ttysleep(tp, &lbolt, PCATCH,
2188 "ttybf2", 0);
2189 if (error)
2190 goto out;
2191 goto loop;
2193 if (ISSET(tp->t_lflag, FLUSHO) ||
2194 tp->t_outq.c_cc > hiwat)
2195 break;
2197 ttstart(tp);
2199 out:
2201 * If cc is nonzero, we leave the uio structure inconsistent, as the
2202 * offset and iov pointers have moved forward, but it doesn't matter
2203 * (the call will either return short or restart with a new uio).
2205 uio->uio_resid += cc;
2206 lwkt_reltoken(&tty_token);
2207 return (error);
2209 ovhiwat:
2210 ttstart(tp);
2211 crit_enter();
2213 * This can only occur if FLUSHO is set in t_lflag,
2214 * or if ttstart/oproc is synchronous (or very fast).
2216 if (tp->t_outq.c_cc <= hiwat) {
2217 crit_exit();
2218 goto loop;
2220 if (flag & IO_NDELAY) {
2221 crit_exit();
2222 uio->uio_resid += cc;
2223 lwkt_reltoken(&tty_token);
2224 return (uio->uio_resid == cnt ? EWOULDBLOCK : 0);
2226 SET(tp->t_state, TS_SO_OLOWAT);
2227 error = ttysleep(tp, TSA_OLOWAT(tp), PCATCH, "ttywri", tp->t_timeout);
2228 crit_exit();
2229 if (error == EWOULDBLOCK)
2230 error = EIO;
2231 if (error)
2232 goto out;
2233 goto loop;
2237 * Rubout one character from the rawq of tp
2238 * as cleanly as possible.
2239 * NOTE: Must be called with tty_token held
2241 static void
2242 ttyrub(int c, struct tty *tp)
2244 char *cp;
2245 int savecol;
2246 int tabc;
2248 ASSERT_LWKT_TOKEN_HELD(&tty_token);
2249 if (!ISSET(tp->t_lflag, ECHO) || ISSET(tp->t_lflag, EXTPROC))
2250 return;
2251 CLR(tp->t_lflag, FLUSHO);
2252 if (ISSET(tp->t_lflag, ECHOE)) {
2253 if (tp->t_rocount == 0) {
2255 * Screwed by ttwrite; retype
2257 ttyretype(tp);
2258 return;
2260 if (c == ('\t' | TTY_QUOTE) || c == ('\n' | TTY_QUOTE))
2261 ttyrubo(tp, 2);
2262 else {
2263 CLR(c, ~TTY_CHARMASK);
2264 switch (CCLASS(c)) {
2265 case ORDINARY:
2266 ttyrubo(tp, 1);
2267 break;
2268 case BACKSPACE:
2269 case CONTROL:
2270 case NEWLINE:
2271 case RETURN:
2272 case VTAB:
2273 if (ISSET(tp->t_lflag, ECHOCTL))
2274 ttyrubo(tp, 2);
2275 break;
2276 case TAB:
2277 if (tp->t_rocount < tp->t_rawq.c_cc) {
2278 ttyretype(tp);
2279 return;
2281 crit_enter();
2282 savecol = tp->t_column;
2283 SET(tp->t_state, TS_CNTTB);
2284 SET(tp->t_lflag, FLUSHO);
2285 tp->t_column = tp->t_rocol;
2286 cp = tp->t_rawq.c_cf;
2287 if (cp)
2288 tabc = *cp; /* XXX FIX NEXTC */
2289 for (; cp; cp = nextc(&tp->t_rawq, cp, &tabc))
2290 ttyecho(tabc, tp);
2291 CLR(tp->t_lflag, FLUSHO);
2292 CLR(tp->t_state, TS_CNTTB);
2293 crit_exit();
2295 /* savecol will now be length of the tab. */
2296 savecol -= tp->t_column;
2297 tp->t_column += savecol;
2298 if (savecol > 8)
2299 savecol = 8; /* overflow screw */
2300 while (--savecol >= 0)
2301 (void)ttyoutput('\b', tp);
2302 break;
2303 default: /* XXX */
2304 #define PANICSTR "ttyrub: would panic c = %d, val = %d\n"
2305 (void)kprintf(PANICSTR, c, CCLASS(c));
2306 #ifdef notdef
2307 panic(PANICSTR, c, CCLASS(c));
2308 #endif
2311 } else if (ISSET(tp->t_lflag, ECHOPRT)) {
2312 if (!ISSET(tp->t_state, TS_ERASE)) {
2313 SET(tp->t_state, TS_ERASE);
2314 (void)ttyoutput('\\', tp);
2316 ttyecho(c, tp);
2317 } else {
2318 ttyecho(tp->t_cc[VERASE], tp);
2320 * This code may be executed not only when an ERASE key
2321 * is pressed, but also when ^U (KILL) or ^W (WERASE) are.
2322 * So, I didn't think it was worthwhile to pass the extra
2323 * information (which would need an extra parameter,
2324 * changing every call) needed to distinguish the ERASE2
2325 * case from the ERASE.
2328 --tp->t_rocount;
2332 * Back over cnt characters, erasing them.
2333 * NOTE: Must be called with tty_token held
2335 static void
2336 ttyrubo(struct tty *tp, int cnt)
2338 ASSERT_LWKT_TOKEN_HELD(&tty_token);
2339 while (cnt-- > 0) {
2340 (void)ttyoutput('\b', tp);
2341 (void)ttyoutput(' ', tp);
2342 (void)ttyoutput('\b', tp);
2347 * ttyretype --
2348 * Reprint the rawq line. Note, it is assumed that c_cc has already
2349 * been checked.
2350 * NOTE: Must be called with tty_token held
2352 static void
2353 ttyretype(struct tty *tp)
2355 char *cp;
2356 int c;
2358 ASSERT_LWKT_TOKEN_HELD(&tty_token);
2359 /* Echo the reprint character. */
2360 if (tp->t_cc[VREPRINT] != _POSIX_VDISABLE)
2361 ttyecho(tp->t_cc[VREPRINT], tp);
2363 (void)ttyoutput('\n', tp);
2366 * XXX
2367 * FIX: NEXTC IS BROKEN - DOESN'T CHECK QUOTE
2368 * BIT OF FIRST CHAR.
2370 crit_enter();
2371 for (cp = tp->t_canq.c_cf, c = (cp != NULL ? *cp : 0);
2372 cp != NULL; cp = nextc(&tp->t_canq, cp, &c))
2373 ttyecho(c, tp);
2374 for (cp = tp->t_rawq.c_cf, c = (cp != NULL ? *cp : 0);
2375 cp != NULL; cp = nextc(&tp->t_rawq, cp, &c))
2376 ttyecho(c, tp);
2377 CLR(tp->t_state, TS_ERASE);
2378 crit_exit();
2380 tp->t_rocount = tp->t_rawq.c_cc;
2381 tp->t_rocol = 0;
2385 * Echo a typed character to the terminal.
2386 * NOTE: Must be called with tty_token held
2388 static void
2389 ttyecho(int c, struct tty *tp)
2391 ASSERT_LWKT_TOKEN_HELD(&tty_token);
2393 if (!ISSET(tp->t_state, TS_CNTTB))
2394 CLR(tp->t_lflag, FLUSHO);
2395 if ((!ISSET(tp->t_lflag, ECHO) &&
2396 (c != '\n' || !ISSET(tp->t_lflag, ECHONL))) ||
2397 ISSET(tp->t_lflag, EXTPROC))
2398 return;
2399 if (ISSET(tp->t_lflag, ECHOCTL) &&
2400 ((ISSET(c, TTY_CHARMASK) <= 037 && c != '\t' && c != '\n') ||
2401 ISSET(c, TTY_CHARMASK) == 0177)) {
2402 (void)ttyoutput('^', tp);
2403 CLR(c, ~TTY_CHARMASK);
2404 if (c == 0177)
2405 c = '?';
2406 else
2407 c += 'A' - 1;
2409 (void)ttyoutput(c, tp);
2413 * Wake up any readers on a tty.
2415 void
2416 ttwakeup(struct tty *tp)
2418 lwkt_gettoken(&tty_token);
2419 if (ISSET(tp->t_state, TS_ASYNC) && tp->t_sigio != NULL)
2420 pgsigio(tp->t_sigio, SIGIO, (tp->t_session != NULL));
2421 wakeup(TSA_HUP_OR_INPUT(tp));
2422 KNOTE(&tp->t_rkq.ki_note, 0);
2423 lwkt_reltoken(&tty_token);
2427 * Wake up any writers on a tty.
2429 void
2430 ttwwakeup(struct tty *tp)
2432 lwkt_gettoken(&tty_token);
2433 if (ISSET(tp->t_state, TS_ASYNC) && tp->t_sigio != NULL)
2434 pgsigio(tp->t_sigio, SIGIO, (tp->t_session != NULL));
2435 if (ISSET(tp->t_state, TS_BUSY | TS_SO_OCOMPLETE) ==
2436 TS_SO_OCOMPLETE && tp->t_outq.c_cc == 0) {
2437 CLR(tp->t_state, TS_SO_OCOMPLETE);
2438 wakeup(TSA_OCOMPLETE(tp));
2440 if (ISSET(tp->t_state, TS_SO_OLOWAT) &&
2441 tp->t_outq.c_cc <= tp->t_olowat) {
2442 CLR(tp->t_state, TS_SO_OLOWAT);
2443 wakeup(TSA_OLOWAT(tp));
2445 KNOTE(&tp->t_wkq.ki_note, 0);
2446 lwkt_reltoken(&tty_token);
2450 * Look up a code for a specified speed in a conversion table;
2451 * used by drivers to map software speed values to hardware parameters.
2452 * No requirements
2455 ttspeedtab(int speed, struct speedtab *table)
2458 for ( ; table->sp_speed != -1; table++)
2459 if (table->sp_speed == speed)
2460 return (table->sp_code);
2461 return (-1);
2465 * Set input and output watermarks and buffer sizes. For input, the
2466 * high watermark is about one second's worth of input above empty, the
2467 * low watermark is slightly below high water, and the buffer size is a
2468 * driver-dependent amount above high water. For output, the watermarks
2469 * are near the ends of the buffer, with about 1 second's worth of input
2470 * between them. All this only applies to the standard line discipline.
2472 void
2473 ttsetwater(struct tty *tp)
2475 int cps, ttmaxhiwat, x;
2477 lwkt_gettoken(&tty_token);
2478 /* Input. */
2479 clist_alloc_cblocks(&tp->t_canq, TTYHOG, 512);
2480 switch (tp->t_ispeedwat) {
2481 case (speed_t)-1:
2482 cps = tp->t_ispeed / 10;
2483 break;
2484 case 0:
2486 * This case is for old drivers that don't know about
2487 * t_ispeedwat. Arrange for them to get the old buffer
2488 * sizes and watermarks.
2490 cps = TTYHOG - 2 * 256;
2491 tp->t_ififosize = 2 * 2048;
2492 break;
2493 default:
2494 cps = tp->t_ispeedwat / 10;
2495 break;
2497 tp->t_ihiwat = cps;
2498 tp->t_ilowat = 7 * cps / 8;
2499 x = cps + tp->t_ififosize;
2500 clist_alloc_cblocks(&tp->t_rawq, x, x);
2502 /* Output. */
2503 switch (tp->t_ospeedwat) {
2504 case (speed_t)-1:
2505 cps = tp->t_ospeed / 10;
2506 ttmaxhiwat = 2 * TTMAXHIWAT;
2507 break;
2508 case 0:
2509 cps = tp->t_ospeed / 10;
2510 ttmaxhiwat = TTMAXHIWAT;
2511 break;
2512 default:
2513 cps = tp->t_ospeedwat / 10;
2514 ttmaxhiwat = 8 * TTMAXHIWAT;
2515 break;
2517 #define CLAMP(x, h, l) ((x) > h ? h : ((x) < l) ? l : (x))
2518 tp->t_olowat = x = CLAMP(cps / 2, TTMAXLOWAT, TTMINLOWAT);
2519 x += cps;
2520 x = CLAMP(x, ttmaxhiwat, TTMINHIWAT); /* XXX clamps are too magic */
2521 tp->t_ohiwat = roundup(x, CBSIZE); /* XXX for compat */
2522 x = imax(tp->t_ohiwat, TTMAXHIWAT); /* XXX for compat/safety */
2523 x += OBUFSIZ + 100;
2524 clist_alloc_cblocks(&tp->t_outq, x, x);
2525 #undef CLAMP
2526 lwkt_reltoken(&tty_token);
2530 * Report on state of foreground process group.
2532 void
2533 ttyinfo(struct tty *tp)
2535 struct pgrp *pgrp;
2536 struct proc *p, *pick;
2537 struct lwp *lp;
2538 struct rusage ru;
2539 char buf[64];
2540 const char *str;
2541 struct vmspace *vm;
2542 long vmsz;
2543 int pctcpu;
2544 int tmp;
2546 if (ttycheckoutq(tp,0) == 0)
2547 return;
2549 lwkt_gettoken(&tty_token);
2552 * We always print the load average, then figure out what else to
2553 * print based on the state of the current process group.
2555 tmp = (averunnable.ldavg[0] * 100 + FSCALE / 2) >> FSHIFT;
2556 ttyprintf(tp, "load: %d.%02d ", tmp / 100, tmp % 100);
2558 if (tp->t_session == NULL) {
2559 ttyprintf(tp, "not a controlling terminal\n");
2560 goto done2;
2562 if ((pgrp = tp->t_pgrp) == NULL) {
2563 ttyprintf(tp, "no foreground process group\n");
2564 goto done2;
2568 * Pick an interesting process. Note that certain elements,
2569 * in particular the wmesg, require a critical section for
2570 * safe access (YYY and we are still not MP safe).
2572 * NOTE: lwp_wmesg is lwp_thread->td_wmesg.
2574 pgref(pgrp);
2575 lwkt_gettoken(&pgrp->pg_token);
2577 pick = NULL;
2578 for (p = LIST_FIRST(&pgrp->pg_members);
2579 p != NULL;
2580 p = LIST_NEXT(p, p_pglist)) {
2581 PHOLD(p);
2582 if (proc_compare(pick, p)) {
2583 if (pick)
2584 PRELE(pick);
2585 pick = p;
2586 } else {
2587 PRELE(p);
2590 if (pick == NULL) {
2591 ttyprintf(tp, "empty foreground process group\n");
2592 goto done1;
2596 * Pick an interesting LWP (XXX)
2598 * pick is held.
2600 lp = FIRST_LWP_IN_PROC(pick);
2601 if (lp == NULL) {
2602 PRELE(pick);
2603 ttyprintf(tp, "foreground process without lwp\n");
2604 goto done1;
2608 * Figure out what wait/process-state message, and command
2609 * buffer to present
2612 * XXX lwp This is a horrible mixture. We need to rework this
2613 * as soon as lwps have their own runnable status.
2615 LWPHOLD(lp);
2616 if (pick->p_flags & P_WEXIT)
2617 str = "exiting";
2618 else if (lp->lwp_stat == LSRUN)
2619 str = "running";
2620 else if (pick->p_stat == SIDL)
2621 str = "spawning";
2622 else if (lp->lwp_wmesg) /* lwp_thread must not be NULL */
2623 str = lp->lwp_wmesg;
2624 else
2625 str = "iowait";
2627 ksnprintf(buf, sizeof(buf), "cmd: %s %d [%s]",
2628 pick->p_comm, pick->p_pid, str);
2631 * Calculate cpu usage, percent cpu, and cmsz. Note that
2632 * 'pick' becomes invalid the moment we exit the critical
2633 * section.
2635 if (lp->lwp_thread && (pick->p_flags & P_SWAPPEDOUT) == 0)
2636 calcru_proc(pick, &ru);
2638 pctcpu = (lp->lwp_pctcpu * 10000 + FSCALE / 2) >> FSHIFT;
2640 LWPRELE(lp);
2643 * NOTE: vmspace should be protected from destruction by the
2644 * combination of pg_token and the fact that we are not
2645 * flagged as a zombie.
2647 if (pick->p_stat == SIDL || pick->p_stat == SZOMB) {
2648 vmsz = 0;
2649 } else if ((vm = pick->p_vmspace) == NULL) {
2650 vmsz = 0;
2651 } else {
2652 vmspace_hold(vm);
2653 vmsz = pgtok(vmspace_resident_count(vm));
2654 vmspace_drop(vm);
2656 PRELE(pick);
2659 * Dump the output
2661 ttyprintf(tp, " %s ",
2662 buf);
2663 ttyprintf(tp, "%ld.%02ldu ",
2664 ru.ru_utime.tv_sec, ru.ru_utime.tv_usec / 10000);
2665 ttyprintf(tp, "%ld.%02lds ",
2666 ru.ru_stime.tv_sec, ru.ru_stime.tv_usec / 10000);
2667 ttyprintf(tp, "%d%% %ldk\n",
2668 pctcpu / 100, vmsz);
2670 done1:
2671 lwkt_reltoken(&pgrp->pg_token);
2672 pgrel(pgrp);
2673 done2:
2674 tp->t_rocount = 0; /* so pending input will be retyped if BS */
2675 lwkt_reltoken(&tty_token);
2679 * Returns 1 if p2 is "better" than p1
2681 * The algorithm for picking the "interesting" process is thus:
2683 * 1) Only foreground processes are eligible - implied.
2684 * 2) Runnable processes are favored over anything else. The runner
2685 * with the highest cpu utilization is picked (p_cpticks). Ties are
2686 * broken by picking the highest pid.
2687 * 3) The sleeper with the shortest sleep time is next. With ties,
2688 * we pick out just "short-term" sleepers (LWP_SINTR == 0).
2689 * 4) Further ties are broken by picking the highest pid.
2691 * NOTE: must be called with p1 and p2 held.
2693 #define ISRUN(lp) ((lp)->lwp_stat == LSRUN)
2694 #define TESTAB(a, b) ((a)<<1 | (b))
2695 #define ONLYA 2
2696 #define ONLYB 1
2697 #define BOTH 3
2699 static int
2700 proc_compare(struct proc *p1, struct proc *p2)
2702 struct lwp *lp1, *lp2;
2703 int res;
2705 if (p1 == NULL)
2706 return (1);
2707 if (lwkt_trytoken(&p1->p_token) == 0)
2708 return (1);
2709 if (lwkt_trytoken(&p2->p_token) == 0) {
2710 lwkt_reltoken(&p1->p_token);
2711 return (0);
2715 * weed out zombies
2717 switch (TESTAB(p1->p_stat == SZOMB, p2->p_stat == SZOMB)) {
2718 case ONLYA:
2719 res = 1;
2720 goto done;
2721 case ONLYB:
2722 res = 0;
2723 goto done;
2724 case BOTH:
2725 res = (p2->p_pid > p1->p_pid); /* tie - return highest pid */
2726 goto done;
2727 default:
2728 break;
2731 /* XXX choose the best lwp? */
2732 lp1 = FIRST_LWP_IN_PROC(p1);
2733 lp2 = FIRST_LWP_IN_PROC(p2);
2736 * Favor one with LWPs verses one that has none (is exiting).
2738 if (lp1 == NULL) {
2739 res = 1;
2740 goto done;
2742 if (lp2 == NULL) {
2743 res = 0;
2744 goto done;
2748 * see if at least one of them is runnable
2750 switch (TESTAB(ISRUN(lp1), ISRUN(lp2))) {
2751 case ONLYA:
2752 res = 0;
2753 goto done;
2754 case ONLYB:
2755 res = 1;
2756 goto done;
2757 case BOTH:
2759 * tie - favor one with highest recent cpu utilization
2761 if (lp2->lwp_cpticks > lp1->lwp_cpticks)
2762 res = 1;
2763 else if (lp1->lwp_cpticks > lp2->lwp_cpticks)
2764 res = 0;
2765 else
2766 res = (p2->p_pid > p1->p_pid); /* tie - ret highest */
2767 goto done;
2768 default:
2769 break;
2773 * Pick the one with the smallest sleep time
2775 if (lp2->lwp_slptime > lp1->lwp_slptime) {
2776 res = 0;
2777 goto done;
2779 if (lp1->lwp_slptime > lp2->lwp_slptime) {
2780 res = 1;
2781 goto done;
2785 * Favor one sleeping in a non-interruptible sleep
2787 if ((lp1->lwp_flags & LWP_SINTR) && (lp2->lwp_flags & LWP_SINTR) == 0)
2788 res = 1;
2789 else
2790 if ((lp2->lwp_flags & LWP_SINTR) && (lp1->lwp_flags & LWP_SINTR) == 0)
2791 res = 0;
2792 else
2793 res = (p2->p_pid > p1->p_pid); /* tie - return highest pid */
2794 /* fall through */
2796 done:
2797 lwkt_reltoken(&p2->p_token);
2798 lwkt_reltoken(&p1->p_token);
2799 return (res);
2803 * Output char to tty; console putchar style.
2806 tputchar(int c, struct tty *tp)
2808 crit_enter();
2809 lwkt_gettoken(&tty_token);
2810 if (!ISSET(tp->t_state, TS_CONNECTED)) {
2811 lwkt_reltoken(&tty_token);
2812 crit_exit();
2813 return (-1);
2815 if (c == '\n')
2816 (void)ttyoutput('\r', tp);
2817 (void)ttyoutput(c, tp);
2818 ttstart(tp);
2819 lwkt_reltoken(&tty_token);
2820 crit_exit();
2821 return (0);
2825 * Sleep on chan, returning ERESTART if tty changed while we napped and
2826 * returning any errors (e.g. EINTR/EWOULDBLOCK) reported by tsleep. If
2827 * the tty is revoked, restarting a pending call will redo validation done
2828 * at the start of the call.
2831 ttysleep(struct tty *tp, void *chan, int slpflags, char *wmesg, int timo)
2833 int error;
2834 int gen;
2836 gen = tp->t_gen;
2837 error = tsleep(chan, slpflags, wmesg, timo);
2838 if (error)
2839 return (error);
2840 return (tp->t_gen == gen ? 0 : ERESTART);
2844 * Revoke a tty.
2846 * We bump the gen to force any ttysleep()'s to return with ERESTART
2847 * and flush the tty. The related fp's should already have been
2848 * replaced so the tty will close when the last references on the
2849 * original fp's go away.
2852 ttyrevoke(struct dev_revoke_args *ap)
2854 struct tty *tp;
2856 lwkt_gettoken(&tty_token);
2857 tp = ap->a_head.a_dev->si_tty;
2858 tp->t_gen++;
2859 ttyflush(tp, FREAD | FWRITE);
2860 wakeup(TSA_CARR_ON(tp));
2861 ttwakeup(tp);
2862 ttwwakeup(tp);
2863 lwkt_reltoken(&tty_token);
2864 return (0);
2868 * Allocate a tty struct. Clists in the struct will be allocated by
2869 * ttyopen().
2871 struct tty *
2872 ttymalloc(struct tty *tp)
2875 if (tp) {
2876 return(tp);
2878 tp = kmalloc(sizeof *tp, M_TTYS, M_WAITOK|M_ZERO);
2879 ttyregister(tp);
2880 return (tp);
2883 void
2884 ttyunregister(struct tty *tp)
2886 lwkt_gettoken(&tty_token);
2887 KKASSERT(ISSET(tp->t_state, TS_REGISTERED));
2888 CLR(tp->t_state, TS_REGISTERED);
2889 TAILQ_REMOVE(&tty_list, tp, t_list);
2890 lwkt_reltoken(&tty_token);
2893 void
2894 ttyregister(struct tty *tp)
2896 lwkt_gettoken(&tty_token);
2897 KKASSERT(!ISSET(tp->t_state, TS_REGISTERED));
2898 SET(tp->t_state, TS_REGISTERED);
2899 TAILQ_INSERT_HEAD(&tty_list, tp, t_list);
2900 lwkt_reltoken(&tty_token);
2903 static int
2904 sysctl_kern_ttys(SYSCTL_HANDLER_ARGS)
2906 int error;
2907 struct tty *tp;
2908 struct tty t;
2909 struct tty marker;
2911 bzero(&marker, sizeof(marker));
2912 marker.t_state = TS_MARKER;
2913 error = 0;
2915 lwkt_gettoken(&tty_token);
2917 TAILQ_INSERT_HEAD(&tty_list, &marker, t_list);
2918 while ((tp = TAILQ_NEXT(&marker, t_list)) != NULL) {
2919 TAILQ_REMOVE(&tty_list, &marker, t_list);
2920 TAILQ_INSERT_AFTER(&tty_list, tp, &marker, t_list);
2921 if (tp->t_state & TS_MARKER)
2922 continue;
2923 t = *tp;
2924 if (t.t_dev)
2925 t.t_dev = (cdev_t)(uintptr_t)dev2udev(t.t_dev);
2926 error = SYSCTL_OUT(req, (caddr_t)&t, sizeof(t));
2927 if (error)
2928 break;
2930 TAILQ_REMOVE(&tty_list, &marker, t_list);
2931 lwkt_reltoken(&tty_token);
2932 return (error);
2935 SYSCTL_PROC(_kern, OID_AUTO, ttys, CTLTYPE_OPAQUE|CTLFLAG_RD,
2936 0, 0, sysctl_kern_ttys, "S,tty", "All struct ttys");
2938 void
2939 nottystop(struct tty *tp, int rw)
2941 return;
2945 ttyread(struct dev_read_args *ap)
2947 struct tty *tp;
2948 int ret;
2950 tp = ap->a_head.a_dev->si_tty;
2951 if (tp == NULL)
2952 return (ENODEV);
2953 lwkt_gettoken(&tty_token);
2954 ret = ((*linesw[tp->t_line].l_read)(tp, ap->a_uio, ap->a_ioflag));
2955 lwkt_reltoken(&tty_token);
2957 return ret;
2961 ttywrite(struct dev_write_args *ap)
2963 struct tty *tp;
2964 int ret;
2966 tp = ap->a_head.a_dev->si_tty;
2967 if (tp == NULL)
2968 return (ENODEV);
2969 lwkt_gettoken(&tty_token);
2970 ret = ((*linesw[tp->t_line].l_write)(tp, ap->a_uio, ap->a_ioflag));
2971 lwkt_reltoken(&tty_token);
2973 return ret;