kernel: Remove the FFS_ROOT option. It was a no-op since 4.9.
[dragonfly.git] / sys / kern / tty.c
blob6641b3ae4478263bac60344b831c57e69f934aad
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 #include <sys/tty.h>
82 #define TTYDEFCHARS
83 #include <sys/ttydefaults.h> /* for ttydefchars, CEOT */
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 lwkt_gettoken(&tp->t_token);
222 tp->t_dev = device;
223 if (!ISSET(tp->t_state, TS_ISOPEN)) {
224 SET(tp->t_state, TS_ISOPEN);
225 if (ISSET(tp->t_cflag, CLOCAL)) {
226 SET(tp->t_state, TS_CONNECTED);
228 bzero(&tp->t_winsize, sizeof(tp->t_winsize));
230 ttsetwater(tp);
231 lwkt_reltoken(&tp->t_token);
233 return (0);
237 * Handle close() on a tty line: flush and set to initial state,
238 * bumping generation number so that pending read/write calls
239 * can detect recycling of the tty.
241 * XXX our caller should have done `spltty(); l_close(); ttyclose();'
242 * and l_close() should have flushed, but we repeat the spltty() and
243 * the flush in case there are buggy callers.
246 ttyclose(struct tty *tp)
248 lwkt_gettoken(&tp->t_token);
249 funsetown(&tp->t_sigio);
250 if (constty == tp)
251 constty = NULL;
253 ttyflush(tp, FREAD | FWRITE);
254 clist_free_cblocks(&tp->t_canq);
255 clist_free_cblocks(&tp->t_outq);
256 clist_free_cblocks(&tp->t_rawq);
258 tp->t_gen++;
259 tp->t_line = TTYDISC;
260 ttyclearsession(tp);
261 tp->t_state &= TS_REGISTERED; /* clear all bits except */
262 lwkt_reltoken(&tp->t_token);
264 return (0);
268 * Disassociate the tty from its session. Traditionally this has only been
269 * a half-close, meaning that the session was still allowed to point at the
270 * tty (resulting in the tty in the ps command showing something like 'p0-'),
271 * even though the tty is no longer pointing at the session.
273 * The half close seems to be useful only for 'ps' output but there is as
274 * yet no reason to remove the feature. The full-close code is currently
275 * #if 0'd out. See also sess_rele() in kern/kern_proc.c.
277 void
278 ttyclearsession(struct tty *tp)
280 struct session *sp;
281 struct procglob *prg;
282 struct pgrp *opgrp;
284 lwkt_gettoken(&tp->t_token);
285 opgrp = tp->t_pgrp;
286 tp->t_pgrp = NULL;
287 if (opgrp) {
288 pgrel(opgrp);
289 opgrp = NULL;
292 again:
293 if ((sp = tp->t_session) != NULL) {
294 prg = sp->s_prg;
295 lwkt_gettoken(&prg->proc_token);
296 if (sp != tp->t_session) {
297 lwkt_reltoken(&prg->proc_token);
298 goto again;
300 tp->t_session = NULL;
302 #ifdef TTY_DO_FULL_CLOSE
303 /* FULL CLOSE (not yet) */
304 if (sp->s_ttyp == tp) {
305 sp->s_ttyp = NULL;
306 ttyunhold(tp);
307 } else {
308 kprintf("ttyclearsession: warning: sp->s_ttyp != tp "
309 "%p/%p\n", sp->s_ttyp, tp);
311 #endif
312 lwkt_reltoken(&prg->proc_token);
314 lwkt_reltoken(&tp->t_token);
318 * Release the tty vnode association for a session. This is the
319 * 'other half' of the close. Because multiple opens of /dev/tty
320 * only generate a single open to the actual tty, the file modes
321 * are locked to FREAD|FWRITE.
323 * If dorevoke is non-zero, the session is also revoked. We have to
324 * close the vnode if VCTTYISOPEN is set.
326 void
327 ttyclosesession(struct session *sp, int dorevoke)
329 struct vnode *vp;
330 struct procglob *prg;
332 prg = sp->s_prg;
333 lwkt_gettoken(&prg->proc_token);
334 retry:
336 * There may not be a controlling terminal or it may have been closed
337 * out from under us.
339 if ((vp = sp->s_ttyvp) == NULL) {
340 lwkt_reltoken(&prg->proc_token);
341 return;
345 * We need a lock if we have to close or revoke.
347 if ((vp->v_flag & VCTTYISOPEN) || dorevoke) {
348 vhold(vp);
349 if (vn_lock(vp, LK_EXCLUSIVE | LK_RETRY | LK_FAILRECLAIM)) {
350 vdrop(vp);
351 goto retry;
355 * Retry if the vnode was ripped out from under us
357 if (vp != sp->s_ttyvp) {
358 vn_unlock(vp);
359 vdrop(vp);
360 goto retry;
364 * Close and revoke as needed
366 sp->s_ttyvp = NULL;
367 if (vp->v_flag & VCTTYISOPEN) {
368 vclrflags(vp, VCTTYISOPEN);
369 VOP_CLOSE(vp, FREAD|FWRITE, NULL);
371 vn_unlock(vp);
372 if (dorevoke)
373 vrevoke(vp, proc0.p_ucred);
374 vdrop(vp);
375 } else {
376 sp->s_ttyvp = NULL;
378 vrele(vp);
379 lwkt_reltoken(&prg->proc_token);
382 #define FLUSHQ(q) { \
383 if ((q)->c_cc) \
384 ndflush(q, (q)->c_cc); \
387 /* Is 'c' a line delimiter ("break" character)? */
388 #define TTBREAKC(c, lflag) \
389 ((c) == '\n' || (((c) == cc[VEOF] || \
390 (c) == cc[VEOL] || ((c) == cc[VEOL2] && lflag & IEXTEN)) && \
391 (c) != _POSIX_VDISABLE))
394 * Process input of a single character received on a tty.
397 ttyinput(int c, struct tty *tp)
399 tcflag_t iflag, lflag;
400 cc_t *cc;
401 int i, err;
403 lwkt_gettoken(&tp->t_token);
405 * If input is pending take it first.
407 lflag = tp->t_lflag;
408 if (ISSET(lflag, PENDIN))
409 ttypend(tp);
411 * Gather stats.
413 if (ISSET(lflag, ICANON))
414 ++tp->t_cancc;
415 else
416 ++tp->t_rawcc;
417 ++tk_nin;
420 * Block further input iff:
421 * current input > threshold AND input is available to user program
422 * AND input flow control is enabled and not yet invoked.
423 * The 3 is slop for PARMRK.
425 iflag = tp->t_iflag;
426 if (tp->t_rawq.c_cc + tp->t_canq.c_cc > tp->t_ihiwat - 3 &&
427 (!ISSET(lflag, ICANON) || tp->t_canq.c_cc != 0) &&
428 (ISSET(tp->t_cflag, CRTS_IFLOW) || ISSET(iflag, IXOFF)) &&
429 !ISSET(tp->t_state, TS_TBLOCK))
430 ttyblock(tp);
432 /* Handle exceptional conditions (break, parity, framing). */
433 cc = tp->t_cc;
434 err = (ISSET(c, TTY_ERRORMASK));
435 if (err) {
436 CLR(c, TTY_ERRORMASK);
437 if (ISSET(err, TTY_BI)) {
438 if (ISSET(iflag, IGNBRK)) {
439 lwkt_reltoken(&tp->t_token);
440 return (0);
442 if (ISSET(iflag, BRKINT)) {
443 ttyflush(tp, FREAD | FWRITE);
444 pgsignal(tp->t_pgrp, SIGINT, 1);
445 goto endcase;
447 if (ISSET(iflag, PARMRK))
448 goto parmrk;
449 } else if ((ISSET(err, TTY_PE) && ISSET(iflag, INPCK))
450 || ISSET(err, TTY_FE)) {
451 if (ISSET(iflag, IGNPAR)) {
452 lwkt_reltoken(&tp->t_token);
453 return (0);
455 else if (ISSET(iflag, PARMRK)) {
456 parmrk:
457 if (tp->t_rawq.c_cc + tp->t_canq.c_cc >
458 MAX_INPUT - 3)
459 goto input_overflow;
460 clist_putc(0377 | TTY_QUOTE, &tp->t_rawq);
461 clist_putc(0 | TTY_QUOTE, &tp->t_rawq);
462 clist_putc(c | TTY_QUOTE, &tp->t_rawq);
463 goto endcase;
464 } else
465 c = 0;
469 if (!ISSET(tp->t_state, TS_TYPEN) && ISSET(iflag, ISTRIP))
470 CLR(c, 0x80);
471 if (!ISSET(lflag, EXTPROC)) {
473 * Check for literal nexting very first
475 if (ISSET(tp->t_state, TS_LNCH)) {
476 SET(c, TTY_QUOTE);
477 CLR(tp->t_state, TS_LNCH);
480 * Scan for special characters. This code
481 * is really just a big case statement with
482 * non-constant cases. The bottom of the
483 * case statement is labeled ``endcase'', so goto
484 * it after a case match, or similar.
488 * Control chars which aren't controlled
489 * by ICANON, ISIG, or IXON.
491 if (ISSET(lflag, IEXTEN)) {
492 if (CCEQ(cc[VLNEXT], c)) {
493 if (ISSET(lflag, ECHO)) {
494 if (ISSET(lflag, ECHOE)) {
495 (void)ttyoutput('^', tp);
496 (void)ttyoutput('\b', tp);
497 } else
498 ttyecho(c, tp);
500 SET(tp->t_state, TS_LNCH);
501 goto endcase;
503 if (CCEQ(cc[VDISCARD], c)) {
504 if (ISSET(lflag, FLUSHO))
505 CLR(tp->t_lflag, FLUSHO);
506 else {
507 ttyflush(tp, FWRITE);
508 ttyecho(c, tp);
509 if (tp->t_rawq.c_cc + tp->t_canq.c_cc)
510 ttyretype(tp);
511 SET(tp->t_lflag, FLUSHO);
513 goto startoutput;
517 * Signals.
519 if (ISSET(lflag, ISIG)) {
520 if (CCEQ(cc[VINTR], c) || CCEQ(cc[VQUIT], c)) {
521 if (!ISSET(lflag, NOFLSH))
522 ttyflush(tp, FREAD | FWRITE);
523 ttyecho(c, tp);
524 pgsignal(tp->t_pgrp,
525 CCEQ(cc[VINTR], c) ? SIGINT : SIGQUIT, 1);
526 goto endcase;
528 if (CCEQ(cc[VSUSP], c)) {
529 if (!ISSET(lflag, NOFLSH))
530 ttyflush(tp, FREAD);
531 ttyecho(c, tp);
532 pgsignal(tp->t_pgrp, SIGTSTP, 1);
533 goto endcase;
537 * Handle start/stop characters.
539 if (ISSET(iflag, IXON)) {
540 if (CCEQ(cc[VSTOP], c)) {
541 if (!ISSET(tp->t_state, TS_TTSTOP)) {
542 SET(tp->t_state, TS_TTSTOP);
543 (*tp->t_stop)(tp, 0);
544 lwkt_reltoken(&tp->t_token);
545 return (0);
547 if (!CCEQ(cc[VSTART], c)) {
548 lwkt_reltoken(&tp->t_token);
549 return (0);
552 * if VSTART == VSTOP then toggle
554 goto endcase;
556 if (CCEQ(cc[VSTART], c))
557 goto restartoutput;
560 * IGNCR, ICRNL, & INLCR
562 if (c == '\r') {
563 if (ISSET(iflag, IGNCR)) {
564 lwkt_reltoken(&tp->t_token);
565 return (0);
567 else if (ISSET(iflag, ICRNL))
568 c = '\n';
569 } else if (c == '\n' && ISSET(iflag, INLCR))
570 c = '\r';
572 if (!ISSET(tp->t_lflag, EXTPROC) && ISSET(lflag, ICANON)) {
574 * From here on down canonical mode character
575 * processing takes place.
578 * erase or erase2 (^H / ^?)
580 if (CCEQ(cc[VERASE], c) || CCEQ(cc[VERASE2], c) ) {
581 if (tp->t_rawq.c_cc)
582 ttyrub(clist_unputc(&tp->t_rawq), tp);
583 goto endcase;
586 * kill (^U)
588 if (CCEQ(cc[VKILL], c)) {
589 if (ISSET(lflag, ECHOKE) &&
590 tp->t_rawq.c_cc == tp->t_rocount &&
591 !ISSET(lflag, ECHOPRT))
592 while (tp->t_rawq.c_cc)
593 ttyrub(clist_unputc(&tp->t_rawq), tp);
594 else {
595 ttyecho(c, tp);
596 if (ISSET(lflag, ECHOK) ||
597 ISSET(lflag, ECHOKE))
598 ttyecho('\n', tp);
599 FLUSHQ(&tp->t_rawq);
600 tp->t_rocount = 0;
602 CLR(tp->t_state, TS_LOCAL);
603 goto endcase;
606 * word erase (^W)
608 if (CCEQ(cc[VWERASE], c) && ISSET(lflag, IEXTEN)) {
609 int ctype;
612 * erase whitespace
614 while ((c = clist_unputc(&tp->t_rawq)) == ' ' || c == '\t')
615 ttyrub(c, tp);
616 if (c == -1)
617 goto endcase;
619 * erase last char of word and remember the
620 * next chars type (for ALTWERASE)
622 ttyrub(c, tp);
623 c = clist_unputc(&tp->t_rawq);
624 if (c == -1)
625 goto endcase;
626 if (c == ' ' || c == '\t') {
627 clist_putc(c, &tp->t_rawq);
628 goto endcase;
630 ctype = ISALPHA(c);
632 * erase rest of word
634 do {
635 ttyrub(c, tp);
636 c = clist_unputc(&tp->t_rawq);
637 if (c == -1)
638 goto endcase;
639 } while (c != ' ' && c != '\t' &&
640 (!ISSET(lflag, ALTWERASE) || ISALPHA(c) == ctype));
641 clist_putc(c, &tp->t_rawq);
642 goto endcase;
645 * reprint line (^R)
647 if (CCEQ(cc[VREPRINT], c) && ISSET(lflag, IEXTEN)) {
648 ttyretype(tp);
649 goto endcase;
652 * ^T - kernel info and generate SIGINFO
654 if (CCEQ(cc[VSTATUS], c) && ISSET(lflag, IEXTEN)) {
655 if (ISSET(lflag, ISIG))
656 pgsignal(tp->t_pgrp, SIGINFO, 1);
657 if (!ISSET(lflag, NOKERNINFO))
658 ttyinfo(tp);
659 goto endcase;
661 if (CCEQ(cc[VCHECKPT], c) && ISSET(lflag, IEXTEN)) {
662 if (ISSET(lflag, ISIG))
663 pgsignal(tp->t_pgrp, SIGCKPT, 1);
664 goto endcase;
668 * Check for input buffer overflow
670 if (tp->t_rawq.c_cc + tp->t_canq.c_cc >= MAX_INPUT) {
671 input_overflow:
672 if (ISSET(iflag, IMAXBEL)) {
673 if (tp->t_outq.c_cc < tp->t_ohiwat)
674 (void)ttyoutput(CTRL('g'), tp);
676 goto endcase;
679 if (c == 0377 && ISSET(iflag, PARMRK) && !ISSET(iflag, ISTRIP) &&
680 ISSET(iflag, IGNBRK|IGNPAR) != (IGNBRK|IGNPAR)) {
681 clist_putc(0377 | TTY_QUOTE, &tp->t_rawq);
685 * Put data char in q for user and
686 * wakeup on seeing a line delimiter.
688 if (clist_putc(c, &tp->t_rawq) >= 0) {
689 if (!ISSET(lflag, ICANON)) {
690 ttwakeup(tp);
691 ttyecho(c, tp);
692 goto endcase;
694 if (TTBREAKC(c, lflag)) {
695 tp->t_rocount = 0;
696 clist_catq(&tp->t_rawq, &tp->t_canq);
697 ttwakeup(tp);
698 } else if (tp->t_rocount++ == 0)
699 tp->t_rocol = tp->t_column;
700 if (ISSET(tp->t_state, TS_ERASE)) {
702 * end of prterase \.../
704 CLR(tp->t_state, TS_ERASE);
705 (void)ttyoutput('/', tp);
707 i = tp->t_column;
708 ttyecho(c, tp);
709 if (CCEQ(cc[VEOF], c) && ISSET(lflag, ECHO)) {
711 * Place the cursor over the '^' of the ^D.
713 i = imin(2, tp->t_column - i);
714 while (i > 0) {
715 (void)ttyoutput('\b', tp);
716 i--;
720 endcase:
722 * IXANY means allow any character to restart output.
724 if (ISSET(tp->t_state, TS_TTSTOP) &&
725 !ISSET(iflag, IXANY) && cc[VSTART] != cc[VSTOP]) {
726 lwkt_reltoken(&tp->t_token);
727 return (0);
729 restartoutput:
730 CLR(tp->t_lflag, FLUSHO);
731 CLR(tp->t_state, TS_TTSTOP);
732 startoutput:
733 lwkt_reltoken(&tp->t_token);
734 return (ttstart(tp));
738 * Output a single character on a tty, doing output processing
739 * as needed (expanding tabs, newline processing, etc.).
740 * Returns < 0 if succeeds, otherwise returns char to resend.
741 * Must be recursive.
743 static int
744 ttyoutput(int c, struct tty *tp)
746 tcflag_t oflag;
747 int col;
749 lwkt_gettoken(&tp->t_token);
750 oflag = tp->t_oflag;
751 if (!ISSET(oflag, OPOST)) {
752 if (ISSET(tp->t_lflag, FLUSHO)) {
753 lwkt_reltoken(&tp->t_token);
754 return (-1);
756 if (clist_putc(c, &tp->t_outq)) {
757 lwkt_reltoken(&tp->t_token);
758 return (c);
760 tk_nout++;
761 tp->t_outcc++;
762 lwkt_reltoken(&tp->t_token);
763 return (-1);
766 * Do tab expansion if OXTABS is set. Special case if we external
767 * processing, we don't do the tab expansion because we'll probably
768 * get it wrong. If tab expansion needs to be done, let it happen
769 * externally.
771 CLR(c, ~TTY_CHARMASK);
772 if (c == '\t' &&
773 ISSET(oflag, OXTABS) && !ISSET(tp->t_lflag, EXTPROC)) {
774 c = 8 - (tp->t_column & 7);
775 if (!ISSET(tp->t_lflag, FLUSHO)) {
776 c -= clist_btoq(" ", c, &tp->t_outq);
777 tk_nout += c;
778 tp->t_outcc += c;
780 tp->t_column += c;
781 lwkt_reltoken(&tp->t_token);
782 return (c ? -1 : '\t');
784 if (c == CEOT && ISSET(oflag, ONOEOT)) {
785 lwkt_reltoken(&tp->t_token);
786 return (-1);
790 * Newline translation: if ONLCR is set,
791 * translate newline into "\r\n".
793 if (c == '\n' && ISSET(tp->t_oflag, ONLCR)) {
794 tk_nout++;
795 tp->t_outcc++;
796 if (!ISSET(tp->t_lflag, FLUSHO) && clist_putc('\r', &tp->t_outq)) {
797 lwkt_reltoken(&tp->t_token);
798 return (c);
801 /* If OCRNL is set, translate "\r" into "\n". */
802 else if (c == '\r' && ISSET(tp->t_oflag, OCRNL))
803 c = '\n';
804 /* If ONOCR is set, don't transmit CRs when on column 0. */
805 else if (c == '\r' && ISSET(tp->t_oflag, ONOCR) && tp->t_column == 0) {
806 lwkt_reltoken(&tp->t_token);
807 return (-1);
810 tk_nout++;
811 tp->t_outcc++;
812 if (!ISSET(tp->t_lflag, FLUSHO) && clist_putc(c, &tp->t_outq)) {
813 lwkt_reltoken(&tp->t_token);
814 return (c);
817 col = tp->t_column;
818 switch (CCLASS(c)) {
819 case BACKSPACE:
820 if (col > 0)
821 --col;
822 break;
823 case CONTROL:
824 break;
825 case NEWLINE:
826 if (ISSET(tp->t_oflag, ONLCR | ONLRET))
827 col = 0;
828 break;
829 case RETURN:
830 col = 0;
831 break;
832 case ORDINARY:
833 ++col;
834 break;
835 case TAB:
836 col = (col + 8) & ~7;
837 break;
839 tp->t_column = col;
840 lwkt_reltoken(&tp->t_token);
842 return (-1);
846 * Ioctls for all tty devices. Called after line-discipline specific ioctl
847 * has been called to do discipline-specific functions and/or reject any
848 * of these ioctl commands.
850 /* ARGSUSED */
852 ttioctl(struct tty *tp, u_long cmd, void *data, int flag)
854 struct thread *td = curthread;
855 struct lwp *lp = td->td_lwp;
856 struct proc *p = td->td_proc;
857 struct pgrp *opgrp;
858 struct tty *otp;
859 int error;
861 KKASSERT(p);
862 lwkt_gettoken(&tp->t_token);
863 lwkt_gettoken(&p->p_token);
865 /* If the ioctl involves modification, hang if in the background. */
866 switch (cmd) {
867 case TIOCCBRK:
868 case TIOCCONS:
869 case TIOCDRAIN:
870 case TIOCEXCL:
871 case TIOCFLUSH:
872 #ifdef TIOCHPCL
873 case TIOCHPCL:
874 #endif
875 case TIOCNXCL:
876 case TIOCSBRK:
877 case TIOCSCTTY:
878 case TIOCSDRAINWAIT:
879 case TIOCSETA:
880 case TIOCSETAF:
881 case TIOCSETAW:
882 case TIOCSETD:
883 case TIOCSPGRP:
884 case TIOCSTART:
885 case TIOCSTAT:
886 case TIOCSTI:
887 case TIOCSTOP:
888 case TIOCSWINSZ:
889 while (isbackground(p, tp) && !(p->p_flags & P_PPWAIT) &&
890 !SIGISMEMBER(p->p_sigignore, SIGTTOU) &&
891 !SIGISMEMBER(lp->lwp_sigmask, SIGTTOU)) {
892 if (p->p_pgrp->pg_jobc == 0) {
893 lwkt_reltoken(&p->p_token);
894 lwkt_reltoken(&tp->t_token);
895 return (EIO);
897 pgsignal(p->p_pgrp, SIGTTOU, 1);
898 error = ttysleep(tp, &lbolt, PCATCH, "ttybg1",
900 if (error) {
901 lwkt_reltoken(&p->p_token);
902 lwkt_reltoken(&tp->t_token);
903 return (error);
906 break;
909 switch (cmd) { /* Process the ioctl. */
910 case FIOASYNC: /* set/clear async i/o */
911 if (*(int *)data)
912 SET(tp->t_state, TS_ASYNC);
913 else
914 CLR(tp->t_state, TS_ASYNC);
915 break;
916 case FIONREAD: /* get # bytes to read */
917 *(int *)data = ttnread(tp);
918 break;
920 case FIOSETOWN:
922 * Policy -- Don't allow FIOSETOWN on someone else's
923 * controlling tty
925 if (tp->t_session != NULL && !isctty(p, tp)) {
926 lwkt_reltoken(&p->p_token);
927 lwkt_reltoken(&tp->t_token);
928 return (ENOTTY);
931 error = fsetown(*(int *)data, &tp->t_sigio);
932 if (error) {
933 lwkt_reltoken(&p->p_token);
934 lwkt_reltoken(&tp->t_token);
935 return (error);
937 break;
938 case FIOGETOWN:
939 if (tp->t_session != NULL && !isctty(p, tp)) {
940 lwkt_reltoken(&p->p_token);
941 lwkt_reltoken(&tp->t_token);
942 return (ENOTTY);
944 *(int *)data = fgetown(&tp->t_sigio);
945 break;
947 case TIOCEXCL: /* set exclusive use of tty */
948 SET(tp->t_state, TS_XCLUDE);
949 break;
950 case TIOCFLUSH: { /* flush buffers */
951 int flags = *(int *)data;
953 if (flags == 0)
954 flags = FREAD | FWRITE;
955 else
956 flags &= FREAD | FWRITE;
957 ttyflush(tp, flags);
958 break;
960 case TIOCCONS: /* become virtual console */
961 if (*(int *)data) {
962 if (constty && constty != tp &&
963 ISSET(constty->t_state, TS_CONNECTED)) {
964 lwkt_reltoken(&p->p_token);
965 lwkt_reltoken(&tp->t_token);
966 return (EBUSY);
968 #ifndef UCONSOLE
969 if ((error = priv_check(td, PRIV_ROOT)) != 0) {
970 lwkt_reltoken(&p->p_token);
971 lwkt_reltoken(&tp->t_token);
972 return (error);
974 #endif
975 constty = tp;
976 } else if (tp == constty)
977 constty = NULL;
978 break;
979 case TIOCDRAIN: /* wait till output drained */
980 error = ttywait(tp);
981 if (error) {
982 lwkt_reltoken(&p->p_token);
983 lwkt_reltoken(&tp->t_token);
984 return (error);
986 break;
987 case TIOCGETA: { /* get termios struct */
988 struct termios *t = (struct termios *)data;
990 bcopy(&tp->t_termios, t, sizeof(struct termios));
991 break;
993 case TIOCGETD: /* get line discipline */
994 *(int *)data = tp->t_line;
995 break;
996 case TIOCGWINSZ: /* get window size */
997 *(struct winsize *)data = tp->t_winsize;
998 break;
999 case TIOCGPGRP: /* get pgrp of tty */
1000 if (!isctty(p, tp)) {
1001 lwkt_reltoken(&p->p_token);
1002 lwkt_reltoken(&tp->t_token);
1003 return (ENOTTY);
1005 *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
1006 break;
1007 case TIOCGSID: /* get sid of tty */
1008 if (!isctty(p, tp)) {
1009 lwkt_reltoken(&p->p_token);
1010 lwkt_reltoken(&tp->t_token);
1011 return (ENOTTY);
1013 *(int *)data = tp->t_session->s_sid;
1014 break;
1015 #ifdef TIOCHPCL
1016 case TIOCHPCL: /* hang up on last close */
1017 SET(tp->t_cflag, HUPCL);
1018 break;
1019 #endif
1020 case TIOCNXCL: /* reset exclusive use of tty */
1021 CLR(tp->t_state, TS_XCLUDE);
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(&tp->t_token);
1038 return (EINVAL);
1040 if (cmd == TIOCSETAW || cmd == TIOCSETAF) {
1041 error = ttywait(tp);
1042 if (error) {
1043 lwkt_reltoken(&p->p_token);
1044 lwkt_reltoken(&tp->t_token);
1045 return (error);
1047 if (cmd == TIOCSETAF)
1048 ttyflush(tp, FREAD);
1050 if (!ISSET(t->c_cflag, CIGNORE)) {
1052 * Set device hardware.
1054 if (tp->t_param && (error = (*tp->t_param)(tp, t))) {
1055 lwkt_reltoken(&p->p_token);
1056 lwkt_reltoken(&tp->t_token);
1057 return (error);
1059 if (ISSET(t->c_cflag, CLOCAL) &&
1060 !ISSET(tp->t_cflag, CLOCAL)) {
1062 * XXX disconnections would be too hard to
1063 * get rid of without this kludge. The only
1064 * way to get rid of controlling terminals
1065 * is to exit from the session leader.
1067 CLR(tp->t_state, TS_ZOMBIE);
1069 wakeup(TSA_CARR_ON(tp));
1070 ttwakeup(tp);
1071 ttwwakeup(tp);
1073 if ((ISSET(tp->t_state, TS_CARR_ON) ||
1074 ISSET(t->c_cflag, CLOCAL)) &&
1075 !ISSET(tp->t_state, TS_ZOMBIE))
1076 SET(tp->t_state, TS_CONNECTED);
1077 else
1078 CLR(tp->t_state, TS_CONNECTED);
1079 tp->t_cflag = t->c_cflag;
1080 tp->t_ispeed = t->c_ispeed;
1081 if (t->c_ospeed != 0)
1082 tp->t_ospeed = t->c_ospeed;
1083 ttsetwater(tp);
1085 if (ISSET(t->c_lflag, ICANON) != ISSET(tp->t_lflag, ICANON) &&
1086 cmd != TIOCSETAF) {
1087 if (ISSET(t->c_lflag, ICANON))
1088 SET(tp->t_lflag, PENDIN);
1089 else {
1091 * XXX we really shouldn't allow toggling
1092 * ICANON while we're in a non-termios line
1093 * discipline. Now we have to worry about
1094 * panicing for a null queue.
1096 if (tp->t_canq.c_ccmax > 0 &&
1097 tp->t_rawq.c_ccmax > 0) {
1098 clist_catq(&tp->t_rawq, &tp->t_canq);
1100 * XXX the queue limits may be
1101 * different, so the old queue
1102 * swapping method no longer works.
1104 clist_catq(&tp->t_canq, &tp->t_rawq);
1106 CLR(tp->t_lflag, PENDIN);
1108 ttwakeup(tp);
1110 tp->t_iflag = t->c_iflag;
1111 tp->t_oflag = t->c_oflag;
1113 * Make the EXTPROC bit read only.
1115 if (ISSET(tp->t_lflag, EXTPROC))
1116 SET(t->c_lflag, EXTPROC);
1117 else
1118 CLR(t->c_lflag, EXTPROC);
1119 tp->t_lflag = t->c_lflag | ISSET(tp->t_lflag, PENDIN);
1120 if (t->c_cc[VMIN] != tp->t_cc[VMIN] ||
1121 t->c_cc[VTIME] != tp->t_cc[VTIME])
1122 ttwakeup(tp);
1123 bcopy(t->c_cc, tp->t_cc, sizeof(t->c_cc));
1124 break;
1126 case TIOCSETD: { /* set line discipline */
1127 int t = *(int *)data;
1128 cdev_t device = tp->t_dev;
1130 if ((u_int)t >= nlinesw) {
1131 lwkt_reltoken(&p->p_token);
1132 lwkt_reltoken(&tp->t_token);
1133 return (ENXIO);
1135 if (t != tp->t_line) {
1136 (*linesw[tp->t_line].l_close)(tp, flag);
1137 error = (*linesw[t].l_open)(device, tp);
1138 if (error) {
1139 (void)(*linesw[tp->t_line].l_open)(device, tp);
1140 lwkt_reltoken(&p->p_token);
1141 lwkt_reltoken(&tp->t_token);
1142 return (error);
1144 tp->t_line = t;
1146 break;
1148 case TIOCSTART: /* start output, like ^Q */
1149 if (ISSET(tp->t_state, TS_TTSTOP) ||
1150 ISSET(tp->t_lflag, FLUSHO)) {
1151 CLR(tp->t_lflag, FLUSHO);
1152 CLR(tp->t_state, TS_TTSTOP);
1153 ttstart(tp);
1155 break;
1156 case TIOCSTI: /* simulate terminal input */
1157 if ((flag & FREAD) == 0 && priv_check(td, PRIV_ROOT)) {
1158 lwkt_reltoken(&p->p_token);
1159 lwkt_reltoken(&tp->t_token);
1160 return (EPERM);
1162 if (!isctty(p, tp) && priv_check(td, PRIV_ROOT)) {
1163 lwkt_reltoken(&p->p_token);
1164 lwkt_reltoken(&tp->t_token);
1165 return (EACCES);
1167 (*linesw[tp->t_line].l_rint)(*(u_char *)data, tp);
1168 break;
1169 case TIOCSTOP: /* stop output, like ^S */
1170 if (!ISSET(tp->t_state, TS_TTSTOP)) {
1171 SET(tp->t_state, TS_TTSTOP);
1172 (*tp->t_stop)(tp, 0);
1174 break;
1175 case TIOCSCTTY: /* become controlling tty */
1176 /* Session ctty vnode pointer set in vnode layer. */
1177 if (!SESS_LEADER(p) ||
1178 ((p->p_session->s_ttyvp || tp->t_session) &&
1179 (tp->t_session != p->p_session))) {
1180 lwkt_reltoken(&p->p_token);
1181 lwkt_reltoken(&tp->t_token);
1182 return (EPERM);
1184 ttyhold(tp);
1185 tp->t_session = p->p_session;
1186 opgrp = tp->t_pgrp;
1187 pgref(p->p_pgrp);
1188 tp->t_pgrp = p->p_pgrp;
1189 otp = p->p_session->s_ttyp;
1190 p->p_session->s_ttyp = tp;
1191 p->p_flags |= P_CONTROLT;
1192 if (otp)
1193 ttyunhold(otp);
1194 if (opgrp) {
1195 pgrel(opgrp);
1196 opgrp = NULL;
1198 break;
1199 case TIOCSPGRP: { /* set pgrp of tty */
1200 pid_t pgid = *(int *)data;
1202 if (!isctty(p, tp)) {
1203 lwkt_reltoken(&p->p_token);
1204 lwkt_reltoken(&tp->t_token);
1205 return (ENOTTY);
1207 else if (pgid < 1 || pgid > PID_MAX) {
1208 lwkt_reltoken(&p->p_token);
1209 lwkt_reltoken(&tp->t_token);
1210 return (EINVAL);
1211 } else {
1212 struct pgrp *pgrp = pgfind(pgid);
1213 if (pgrp == NULL || pgrp->pg_session != p->p_session) {
1214 if (pgrp)
1215 pgrel(pgrp);
1216 lwkt_reltoken(&p->p_token);
1217 lwkt_reltoken(&tp->t_token);
1218 return (EPERM);
1220 opgrp = tp->t_pgrp;
1221 tp->t_pgrp = pgrp;
1222 if (opgrp) {
1223 pgrel(opgrp);
1224 opgrp = NULL;
1227 break;
1229 case TIOCSTAT: /* simulate control-T */
1230 ttyinfo(tp);
1231 break;
1232 case TIOCSWINSZ: /* set window size */
1233 if (bcmp((caddr_t)&tp->t_winsize, data,
1234 sizeof (struct winsize))) {
1235 tp->t_winsize = *(struct winsize *)data;
1236 pgsignal(tp->t_pgrp, SIGWINCH, 1);
1238 break;
1239 case TIOCSDRAINWAIT:
1240 error = priv_check(td, PRIV_ROOT);
1241 if (error) {
1242 lwkt_reltoken(&p->p_token);
1243 lwkt_reltoken(&tp->t_token);
1244 return (error);
1246 tp->t_timeout = *(int *)data * hz;
1247 wakeup(TSA_OCOMPLETE(tp));
1248 wakeup(TSA_OLOWAT(tp));
1249 break;
1250 case TIOCGDRAINWAIT:
1251 *(int *)data = tp->t_timeout / hz;
1252 break;
1253 default:
1254 lwkt_reltoken(&p->p_token);
1255 lwkt_reltoken(&tp->t_token);
1256 return (ENOIOCTL);
1258 lwkt_reltoken(&p->p_token);
1259 lwkt_reltoken(&tp->t_token);
1260 return (0);
1263 static struct filterops ttyread_filtops =
1264 { FILTEROP_ISFD|FILTEROP_MPSAFE, NULL, filt_ttyrdetach, filt_ttyread };
1265 static struct filterops ttywrite_filtops =
1266 { FILTEROP_ISFD|FILTEROP_MPSAFE, NULL, filt_ttywdetach, filt_ttywrite };
1269 ttykqfilter(struct dev_kqfilter_args *ap)
1271 cdev_t dev = ap->a_head.a_dev;
1272 struct knote *kn = ap->a_kn;
1273 struct tty *tp = dev->si_tty;
1274 struct klist *klist;
1276 ap->a_result = 0;
1278 lwkt_gettoken(&tp->t_token);
1279 switch (kn->kn_filter) {
1280 case EVFILT_READ:
1281 klist = &tp->t_rkq.ki_note;
1282 kn->kn_fop = &ttyread_filtops;
1283 break;
1284 case EVFILT_WRITE:
1285 klist = &tp->t_wkq.ki_note;
1286 kn->kn_fop = &ttywrite_filtops;
1287 break;
1288 default:
1289 ap->a_result = EOPNOTSUPP;
1290 lwkt_reltoken(&tp->t_token);
1291 return (0);
1293 lwkt_reltoken(&tp->t_token);
1294 kn->kn_hook = (caddr_t)dev;
1295 knote_insert(klist, kn);
1297 return (0);
1300 static void
1301 filt_ttyrdetach(struct knote *kn)
1303 struct tty *tp = ((cdev_t)kn->kn_hook)->si_tty;
1305 lwkt_gettoken(&tp->t_token);
1306 knote_remove(&tp->t_rkq.ki_note, kn);
1307 lwkt_reltoken(&tp->t_token);
1310 static int
1311 filt_ttyread(struct knote *kn, long hint)
1313 struct tty *tp = ((cdev_t)kn->kn_hook)->si_tty;
1315 lwkt_gettoken(&tp->t_token);
1316 kn->kn_data = ttnread(tp);
1317 if (ISSET(tp->t_state, TS_ZOMBIE)) {
1318 kn->kn_flags |= (EV_EOF | EV_NODATA);
1319 lwkt_reltoken(&tp->t_token);
1320 return (1);
1322 lwkt_reltoken(&tp->t_token);
1323 return (kn->kn_data > 0);
1326 static void
1327 filt_ttywdetach(struct knote *kn)
1329 struct tty *tp = ((cdev_t)kn->kn_hook)->si_tty;
1331 lwkt_gettoken(&tp->t_token);
1332 knote_remove(&tp->t_wkq.ki_note, kn);
1333 lwkt_reltoken(&tp->t_token);
1336 static int
1337 filt_ttywrite(struct knote *kn, long hint)
1339 struct tty *tp = ((cdev_t)kn->kn_hook)->si_tty;
1340 int ret;
1342 lwkt_gettoken(&tp->t_token);
1343 kn->kn_data = tp->t_outq.c_cc;
1344 if (ISSET(tp->t_state, TS_ZOMBIE)) {
1345 lwkt_reltoken(&tp->t_token);
1346 return (1);
1348 ret = (kn->kn_data <= tp->t_olowat &&
1349 ISSET(tp->t_state, TS_CONNECTED));
1350 lwkt_reltoken(&tp->t_token);
1351 return ret;
1355 * NOTE: tp->t_token must be held.
1357 static int
1358 ttnread(struct tty *tp)
1360 int nread;
1362 ASSERT_LWKT_TOKEN_HELD(&tp->t_token);
1363 if (ISSET(tp->t_lflag, PENDIN))
1364 ttypend(tp);
1365 nread = tp->t_canq.c_cc;
1366 if (!ISSET(tp->t_lflag, ICANON)) {
1367 nread += tp->t_rawq.c_cc;
1368 if (nread < tp->t_cc[VMIN] && tp->t_cc[VTIME] == 0)
1369 nread = 0;
1371 return (nread);
1375 * Wait for output to drain.
1378 ttywait(struct tty *tp)
1380 int error;
1382 error = 0;
1383 lwkt_gettoken(&tp->t_token);
1384 while ((tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)) &&
1385 ISSET(tp->t_state, TS_CONNECTED) && tp->t_oproc) {
1386 (*tp->t_oproc)(tp);
1387 if ((tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)) &&
1388 ISSET(tp->t_state, TS_CONNECTED)) {
1389 SET(tp->t_state, TS_SO_OCOMPLETE);
1390 error = ttysleep(tp, TSA_OCOMPLETE(tp),
1391 PCATCH, "ttywai",
1392 tp->t_timeout);
1393 if (error) {
1394 if (error == EWOULDBLOCK)
1395 error = EIO;
1396 break;
1398 } else
1399 break;
1401 if (!error && (tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)))
1402 error = EIO;
1403 lwkt_reltoken(&tp->t_token);
1405 return (error);
1409 * Flush if successfully wait.
1411 static int
1412 ttywflush(struct tty *tp)
1414 int error;
1416 if ((error = ttywait(tp)) == 0)
1417 ttyflush(tp, FREAD);
1418 return (error);
1422 * Flush tty read and/or write queues, notifying anyone waiting.
1424 void
1425 ttyflush(struct tty *tp, int rw)
1427 lwkt_gettoken(&tp->t_token);
1428 #if 0
1429 again:
1430 #endif
1431 if (rw & FWRITE) {
1432 FLUSHQ(&tp->t_outq);
1433 CLR(tp->t_state, TS_TTSTOP);
1435 (*tp->t_stop)(tp, rw);
1436 if (rw & FREAD) {
1437 FLUSHQ(&tp->t_canq);
1438 FLUSHQ(&tp->t_rawq);
1439 CLR(tp->t_lflag, PENDIN);
1440 tp->t_rocount = 0;
1441 tp->t_rocol = 0;
1442 CLR(tp->t_state, TS_LOCAL);
1443 ttwakeup(tp);
1444 if (ISSET(tp->t_state, TS_TBLOCK)) {
1445 if (rw & FWRITE)
1446 FLUSHQ(&tp->t_outq);
1447 ttyunblock(tp);
1450 * Don't let leave any state that might clobber the
1451 * next line discipline (although we should do more
1452 * to send the START char). Not clearing the state
1453 * may have caused the "putc to a clist with no
1454 * reserved cblocks" panic/kprintf.
1456 CLR(tp->t_state, TS_TBLOCK);
1458 #if 0 /* forget it, sleeping isn't always safe and we don't know when it is */
1459 if (ISSET(tp->t_iflag, IXOFF)) {
1461 * XXX wait a bit in the hope that the stop
1462 * character (if any) will go out. Waiting
1463 * isn't good since it allows races. This
1464 * will be fixed when the stop character is
1465 * put in a special queue. Don't bother with
1466 * the checks in ttywait() since the timeout
1467 * will save us.
1469 SET(tp->t_state, TS_SO_OCOMPLETE);
1470 ttysleep(tp, TSA_OCOMPLETE(tp), 0,
1471 "ttyfls", hz / 10);
1473 * Don't try sending the stop character again.
1475 CLR(tp->t_state, TS_TBLOCK);
1476 goto again;
1478 #endif
1481 if (rw & FWRITE) {
1482 FLUSHQ(&tp->t_outq);
1483 ttwwakeup(tp);
1485 lwkt_reltoken(&tp->t_token);
1489 * Copy in the default termios characters.
1491 void
1492 termioschars(struct termios *t)
1494 bcopy(ttydefchars, t->c_cc, sizeof t->c_cc);
1498 * Old interface.
1500 void
1501 ttychars(struct tty *tp)
1503 lwkt_gettoken(&tp->t_token);
1504 termioschars(&tp->t_termios);
1505 lwkt_reltoken(&tp->t_token);
1509 * Handle input high water. Send stop character for the IXOFF case. Turn
1510 * on our input flow control bit and propagate the changes to the driver.
1511 * XXX the stop character should be put in a special high priority queue.
1513 void
1514 ttyblock(struct tty *tp)
1516 lwkt_gettoken(&tp->t_token);
1517 SET(tp->t_state, TS_TBLOCK);
1518 if (ISSET(tp->t_iflag, IXOFF) && tp->t_cc[VSTOP] != _POSIX_VDISABLE &&
1519 clist_putc(tp->t_cc[VSTOP], &tp->t_outq) != 0)
1520 CLR(tp->t_state, TS_TBLOCK); /* try again later */
1521 ttstart(tp);
1522 lwkt_reltoken(&tp->t_token);
1526 * Handle input low water. Send start character for the IXOFF case. Turn
1527 * off our input flow control bit and propagate the changes to the driver.
1528 * XXX the start character should be put in a special high priority queue.
1530 static void
1531 ttyunblock(struct tty *tp)
1533 lwkt_gettoken(&tp->t_token);
1534 CLR(tp->t_state, TS_TBLOCK);
1535 if (ISSET(tp->t_iflag, IXOFF) && tp->t_cc[VSTART] != _POSIX_VDISABLE &&
1536 clist_putc(tp->t_cc[VSTART], &tp->t_outq) != 0)
1537 SET(tp->t_state, TS_TBLOCK); /* try again later */
1538 ttstart(tp);
1539 lwkt_reltoken(&tp->t_token);
1543 ttstart(struct tty *tp)
1545 lwkt_gettoken(&tp->t_token);
1546 if (tp->t_oproc != NULL) /* XXX: Kludge for pty. */
1547 (*tp->t_oproc)(tp);
1548 lwkt_reltoken(&tp->t_token);
1549 return (0);
1553 * "close" a line discipline
1556 ttylclose(struct tty *tp, int flag)
1558 lwkt_gettoken(&tp->t_token);
1559 if (flag & FNONBLOCK || ttywflush(tp))
1560 ttyflush(tp, FREAD | FWRITE);
1561 lwkt_reltoken(&tp->t_token);
1562 return (0);
1565 void
1566 ttyhold(struct tty *tp)
1568 lwkt_gettoken(&tp->t_token);
1569 ++tp->t_refs;
1570 lwkt_reltoken(&tp->t_token);
1573 void
1574 ttyunhold(struct tty *tp)
1576 lwkt_gettoken(&tp->t_token);
1577 if (tp->t_unhold)
1578 tp->t_unhold(tp);
1579 else
1580 --tp->t_refs;
1581 lwkt_reltoken(&tp->t_token);
1585 * Handle modem control transition on a tty.
1586 * Flag indicates new state of carrier.
1587 * Returns 0 if the line should be turned off, otherwise 1.
1590 ttymodem(struct tty *tp, int flag)
1592 lwkt_gettoken(&tp->t_token);
1593 if (ISSET(tp->t_state, TS_CARR_ON) && ISSET(tp->t_cflag, MDMBUF)) {
1595 * MDMBUF: do flow control according to carrier flag
1596 * XXX TS_CAR_OFLOW doesn't do anything yet. TS_TTSTOP
1597 * works if IXON and IXANY are clear.
1599 if (flag) {
1600 CLR(tp->t_state, TS_CAR_OFLOW);
1601 CLR(tp->t_state, TS_TTSTOP);
1602 ttstart(tp);
1603 } else if (!ISSET(tp->t_state, TS_CAR_OFLOW)) {
1604 SET(tp->t_state, TS_CAR_OFLOW);
1605 SET(tp->t_state, TS_TTSTOP);
1606 (*tp->t_stop)(tp, 0);
1608 } else if (flag == 0) {
1610 * Lost carrier.
1612 CLR(tp->t_state, TS_CARR_ON);
1613 if (ISSET(tp->t_state, TS_ISOPEN) &&
1614 !ISSET(tp->t_cflag, CLOCAL)) {
1615 SET(tp->t_state, TS_ZOMBIE);
1616 CLR(tp->t_state, TS_CONNECTED);
1617 if (tp->t_session && tp->t_session->s_leader)
1618 ksignal(tp->t_session->s_leader, SIGHUP);
1619 ttyflush(tp, FREAD | FWRITE);
1620 lwkt_reltoken(&tp->t_token);
1621 return (0);
1623 } else {
1625 * Carrier now on.
1627 SET(tp->t_state, TS_CARR_ON);
1628 if (!ISSET(tp->t_state, TS_ZOMBIE))
1629 SET(tp->t_state, TS_CONNECTED);
1630 wakeup(TSA_CARR_ON(tp));
1631 ttwakeup(tp);
1632 ttwwakeup(tp);
1634 lwkt_reltoken(&tp->t_token);
1635 return (1);
1639 * Reinput pending characters after state switch
1641 static void
1642 ttypend(struct tty *tp)
1644 struct clist tq;
1645 int c;
1647 lwkt_gettoken(&tp->t_token);
1648 CLR(tp->t_lflag, PENDIN);
1649 SET(tp->t_state, TS_TYPEN);
1651 * XXX this assumes too much about clist internals. It may even
1652 * fail if the cblock slush pool is empty. We can't allocate more
1653 * cblocks here because we are called from an interrupt handler
1654 * and clist_alloc_cblocks() can wait.
1656 tq = tp->t_rawq;
1657 bzero(&tp->t_rawq, sizeof tp->t_rawq);
1658 clist_alloc_cblocks(&tp->t_rawq, tq.c_ccmax);
1659 while ((c = clist_getc(&tq)) >= 0)
1660 ttyinput(c, tp);
1661 CLR(tp->t_state, TS_TYPEN);
1662 clist_free_cblocks(&tq);
1663 lwkt_reltoken(&tp->t_token);
1667 * Process a read call on a tty device.
1670 ttread(struct tty *tp, struct uio *uio, int flag)
1672 struct clist *qp;
1673 int c;
1674 tcflag_t lflag;
1675 cc_t *cc = tp->t_cc;
1676 struct proc *pp;
1677 struct lwp *lp;
1678 int first, error = 0;
1679 int has_stime = 0, last_cc = 0;
1680 long slp = 0; /* XXX this should be renamed `timo'. */
1681 struct timeval stime;
1683 lp = curthread->td_lwp;
1684 stime.tv_sec = 0; /* fix compiler warnings */
1685 stime.tv_usec = 0;
1687 lwkt_gettoken(&tp->t_token);
1688 loop:
1689 lflag = tp->t_lflag;
1691 * take pending input first
1693 if (ISSET(lflag, PENDIN)) {
1694 ttypend(tp);
1695 splz(); /* reduce latency */
1696 lflag = tp->t_lflag; /* XXX ttypend() clobbers it */
1700 * Hang process if it's in the background.
1702 if ((pp = curproc) != NULL)
1703 lwkt_gettoken(&pp->p_token);
1704 if (pp && isbackground(pp, tp)) {
1705 if (SIGISMEMBER(pp->p_sigignore, SIGTTIN) ||
1706 SIGISMEMBER(lp->lwp_sigmask, SIGTTIN) ||
1707 (pp->p_flags & P_PPWAIT) || pp->p_pgrp->pg_jobc == 0) {
1708 lwkt_reltoken(&pp->p_token);
1709 lwkt_reltoken(&tp->t_token);
1710 return (EIO);
1712 pgsignal(pp->p_pgrp, SIGTTIN, 1);
1713 error = ttysleep(tp, &lbolt, PCATCH, "ttybg2", 0);
1714 if (error) {
1715 lwkt_reltoken(&pp->p_token);
1716 lwkt_reltoken(&tp->t_token);
1717 return (error);
1719 lwkt_reltoken(&pp->p_token);
1720 goto loop;
1722 if (pp)
1723 lwkt_reltoken(&pp->p_token);
1725 if (ISSET(tp->t_state, TS_ZOMBIE)) {
1726 lwkt_reltoken(&tp->t_token);
1727 return (0); /* EOF */
1731 * If canonical, use the canonical queue,
1732 * else use the raw queue.
1734 * (should get rid of clists...)
1736 qp = ISSET(lflag, ICANON) ? &tp->t_canq : &tp->t_rawq;
1738 if (flag & IO_NDELAY) {
1739 if (qp->c_cc > 0)
1740 goto read;
1741 if (!ISSET(lflag, ICANON) && cc[VMIN] == 0) {
1742 lwkt_reltoken(&tp->t_token);
1743 return (0);
1745 lwkt_reltoken(&tp->t_token);
1746 return (EWOULDBLOCK);
1748 if (!ISSET(lflag, ICANON)) {
1749 int m = cc[VMIN];
1750 long t = cc[VTIME];
1751 struct timeval timecopy;
1754 * Check each of the four combinations.
1755 * (m > 0 && t == 0) is the normal read case.
1756 * It should be fairly efficient, so we check that and its
1757 * companion case (m == 0 && t == 0) first.
1758 * For the other two cases, we compute the target sleep time
1759 * into slp.
1761 if (t == 0) {
1762 if (qp->c_cc < m)
1763 goto sleep;
1764 if (qp->c_cc > 0)
1765 goto read;
1767 /* m, t and qp->c_cc are all 0. 0 is enough input. */
1768 lwkt_reltoken(&tp->t_token);
1769 return (0);
1771 t *= 100000; /* time in us */
1772 #define diff(t1, t2) (((t1).tv_sec - (t2).tv_sec) * 1000000 + \
1773 ((t1).tv_usec - (t2).tv_usec))
1774 if (m > 0) {
1775 if (qp->c_cc <= 0)
1776 goto sleep;
1777 if (qp->c_cc >= m)
1778 goto read;
1779 getmicrotime(&timecopy);
1780 if (has_stime == 0) {
1781 /* first character, start timer */
1782 has_stime = 1;
1783 stime = timecopy;
1784 slp = t;
1785 } else if (qp->c_cc > last_cc) {
1786 /* got a character, restart timer */
1787 stime = timecopy;
1788 slp = t;
1789 } else {
1790 /* nothing, check expiration */
1791 slp = t - diff(timecopy, stime);
1792 if (slp <= 0)
1793 goto read;
1795 last_cc = qp->c_cc;
1796 } else { /* m == 0 */
1797 if (qp->c_cc > 0)
1798 goto read;
1799 getmicrotime(&timecopy);
1800 if (has_stime == 0) {
1801 has_stime = 1;
1802 stime = timecopy;
1803 slp = t;
1804 } else {
1805 slp = t - diff(timecopy, stime);
1806 if (slp <= 0) {
1807 /* Timed out, but 0 is enough input. */
1808 lwkt_reltoken(&tp->t_token);
1809 return (0);
1813 #undef diff
1815 * Rounding down may make us wake up just short
1816 * of the target, so we round up.
1817 * The formula is ceiling(slp * hz/1000000).
1818 * 32-bit arithmetic is enough for hz < 169.
1819 * XXX see tvtohz() for how to avoid overflow if hz
1820 * is large (divide by `tick' and/or arrange to
1821 * use tvtohz() if hz is large).
1823 slp = (long) (((u_long)slp * hz) + 999999) / 1000000;
1824 goto sleep;
1826 if (qp->c_cc <= 0) {
1827 sleep:
1829 * There is no input, or not enough input and we can block.
1831 error = ttysleep(tp, TSA_HUP_OR_INPUT(tp), PCATCH,
1832 ISSET(tp->t_state, TS_CONNECTED) ?
1833 "ttyin" : "ttyhup", (int)slp);
1834 if (error == EWOULDBLOCK)
1835 error = 0;
1836 else if (error) {
1837 lwkt_reltoken(&tp->t_token);
1838 return (error);
1841 * XXX what happens if another process eats some input
1842 * while we are asleep (not just here)? It would be
1843 * safest to detect changes and reset our state variables
1844 * (has_stime and last_cc).
1846 slp = 0;
1847 goto loop;
1849 read:
1851 * Input present, check for input mapping and processing.
1853 first = 1;
1854 if (ISSET(lflag, ICANON | ISIG))
1855 goto slowcase;
1856 for (;;) {
1857 char ibuf[IBUFSIZ];
1858 int icc;
1860 icc = (int)szmin(uio->uio_resid, IBUFSIZ);
1861 icc = clist_qtob(qp, ibuf, icc);
1862 if (icc <= 0) {
1863 if (first)
1864 goto loop;
1865 break;
1867 error = uiomove(ibuf, (size_t)icc, uio);
1869 * XXX if there was an error then we should ungetc() the
1870 * unmoved chars and reduce icc here.
1872 if (error)
1873 break;
1874 if (uio->uio_resid == 0)
1875 break;
1876 first = 0;
1878 goto out;
1879 slowcase:
1880 for (;;) {
1881 c = clist_getc(qp);
1882 if (c < 0) {
1883 if (first)
1884 goto loop;
1885 break;
1888 * delayed suspend (^Y)
1890 if (CCEQ(cc[VDSUSP], c) &&
1891 ISSET(lflag, IEXTEN | ISIG) == (IEXTEN | ISIG)) {
1892 pgsignal(tp->t_pgrp, SIGTSTP, 1);
1893 if (first) {
1894 error = ttysleep(tp, &lbolt, PCATCH,
1895 "ttybg3", 0);
1896 if (error)
1897 break;
1898 goto loop;
1900 break;
1903 * Interpret EOF only in canonical mode.
1905 if (CCEQ(cc[VEOF], c) && ISSET(lflag, ICANON))
1906 break;
1908 * Give user character.
1910 error = ureadc(c, uio);
1911 if (error)
1912 /* XXX should ungetc(c, qp). */
1913 break;
1914 if (uio->uio_resid == 0)
1915 break;
1917 * In canonical mode check for a "break character"
1918 * marking the end of a "line of input".
1920 if (ISSET(lflag, ICANON) && TTBREAKC(c, lflag))
1921 break;
1922 first = 0;
1925 out:
1927 * Look to unblock input now that (presumably)
1928 * the input queue has gone down.
1930 if (ISSET(tp->t_state, TS_TBLOCK) &&
1931 tp->t_rawq.c_cc + tp->t_canq.c_cc <= tp->t_ilowat) {
1932 ttyunblock(tp);
1935 lwkt_reltoken(&tp->t_token);
1936 return (error);
1940 * Check the output queue on tp for space for a kernel message (from uprintf
1941 * or tprintf). Allow some space over the normal hiwater mark so we don't
1942 * lose messages due to normal flow control, but don't let the tty run amok.
1943 * Sleeps here are not interruptible, but we return prematurely if new signals
1944 * arrive.
1947 ttycheckoutq(struct tty *tp, int wait)
1949 struct lwp *lp = curthread->td_lwp;
1950 int hiwat;
1951 sigset_t oldset, newset;
1953 lwkt_gettoken(&tp->t_token);
1954 hiwat = tp->t_ohiwat;
1955 SIGEMPTYSET(oldset);
1956 SIGEMPTYSET(newset);
1957 if (wait)
1958 oldset = lwp_sigpend(lp);
1959 if (tp->t_outq.c_cc > hiwat + OBUFSIZ + 100) {
1960 while (tp->t_outq.c_cc > hiwat) {
1961 ttstart(tp);
1962 if (tp->t_outq.c_cc <= hiwat)
1963 break;
1964 if (wait)
1965 newset = lwp_sigpend(lp);
1966 if (!wait || SIGSETNEQ(oldset, newset)) {
1967 lwkt_reltoken(&tp->t_token);
1968 return (0);
1970 SET(tp->t_state, TS_SO_OLOWAT);
1971 tsleep(TSA_OLOWAT(tp), 0, "ttoutq", hz);
1974 lwkt_reltoken(&tp->t_token);
1975 return (1);
1979 * Process a write call on a tty device.
1982 ttwrite(struct tty *tp, struct uio *uio, int flag)
1984 char *cp = NULL;
1985 int cc, ce;
1986 struct proc *pp;
1987 struct lwp *lp;
1988 int i, hiwat, error;
1989 size_t cnt;
1991 char obuf[OBUFSIZ];
1993 lwkt_gettoken(&tp->t_token);
1994 lp = curthread->td_lwp;
1995 hiwat = tp->t_ohiwat;
1996 cnt = uio->uio_resid;
1997 error = 0;
1998 cc = 0;
1999 loop:
2000 if (ISSET(tp->t_state, TS_ZOMBIE)) {
2001 if (uio->uio_resid == cnt)
2002 error = EIO;
2003 goto out;
2005 if (!ISSET(tp->t_state, TS_CONNECTED)) {
2006 if (flag & IO_NDELAY) {
2007 error = EWOULDBLOCK;
2008 goto out;
2010 error = ttysleep(tp, TSA_CARR_ON(tp), PCATCH, "ttydcd", 0);
2011 if (error)
2012 goto out;
2013 goto loop;
2017 * Hang the process if it's in the background.
2019 if ((pp = curproc) != NULL)
2020 lwkt_gettoken(&pp->p_token);
2021 if (pp && isbackground(pp, tp) &&
2022 ISSET(tp->t_lflag, TOSTOP) && !(pp->p_flags & P_PPWAIT) &&
2023 !SIGISMEMBER(pp->p_sigignore, SIGTTOU) &&
2024 !SIGISMEMBER(lp->lwp_sigmask, SIGTTOU)) {
2025 if (pp->p_pgrp->pg_jobc == 0) {
2026 error = EIO;
2027 lwkt_reltoken(&pp->p_token);
2028 goto out;
2030 pgsignal(pp->p_pgrp, SIGTTOU, 1);
2031 lwkt_reltoken(&pp->p_token);
2032 error = ttysleep(tp, &lbolt, PCATCH, "ttybg4", 0);
2033 if (error)
2034 goto out;
2035 goto loop;
2037 if (pp)
2038 lwkt_reltoken(&pp->p_token);
2040 * Process the user's data in at most OBUFSIZ chunks. Perform any
2041 * output translation. Keep track of high water mark, sleep on
2042 * overflow awaiting device aid in acquiring new space.
2044 while (uio->uio_resid > 0 || cc > 0) {
2045 if (ISSET(tp->t_lflag, FLUSHO)) {
2046 uio->uio_resid = 0;
2047 lwkt_reltoken(&tp->t_token);
2048 return (0);
2050 if (tp->t_outq.c_cc > hiwat)
2051 goto ovhiwat;
2053 * Grab a hunk of data from the user, unless we have some
2054 * leftover from last time.
2056 if (cc == 0) {
2057 cc = szmin(uio->uio_resid, OBUFSIZ);
2058 cp = obuf;
2059 error = uiomove(cp, (size_t)cc, uio);
2060 if (error) {
2061 cc = 0;
2062 break;
2066 * If nothing fancy need be done, grab those characters we
2067 * can handle without any of ttyoutput's processing and
2068 * just transfer them to the output q. For those chars
2069 * which require special processing (as indicated by the
2070 * bits in char_type), call ttyoutput. After processing
2071 * a hunk of data, look for FLUSHO so ^O's will take effect
2072 * immediately.
2074 while (cc > 0) {
2075 if (!ISSET(tp->t_oflag, OPOST))
2076 ce = cc;
2077 else {
2078 ce = cc - scanc((u_int)cc, (u_char *)cp,
2079 char_type, CCLASSMASK);
2081 * If ce is zero, then we're processing
2082 * a special character through ttyoutput.
2084 if (ce == 0) {
2085 tp->t_rocount = 0;
2086 if (ttyoutput(*cp, tp) >= 0) {
2087 /* No Clists, wait a bit. */
2088 ttstart(tp);
2089 if (flag & IO_NDELAY) {
2090 error = EWOULDBLOCK;
2091 goto out;
2093 error = ttysleep(tp, &lbolt,
2094 PCATCH,
2095 "ttybf1", 0);
2096 if (error)
2097 goto out;
2098 goto loop;
2100 cp++;
2101 cc--;
2102 if (ISSET(tp->t_lflag, FLUSHO) ||
2103 tp->t_outq.c_cc > hiwat)
2104 goto ovhiwat;
2105 continue;
2109 * A bunch of normal characters have been found.
2110 * Transfer them en masse to the output queue and
2111 * continue processing at the top of the loop.
2112 * If there are any further characters in this
2113 * <= OBUFSIZ chunk, the first should be a character
2114 * requiring special handling by ttyoutput.
2116 tp->t_rocount = 0;
2117 i = clist_btoq(cp, ce, &tp->t_outq);
2118 ce -= i;
2119 tp->t_column += ce;
2120 cp += ce, cc -= ce, tk_nout += ce;
2121 tp->t_outcc += ce;
2122 if (i > 0) {
2123 /* No Clists, wait a bit. */
2124 ttstart(tp);
2125 if (flag & IO_NDELAY) {
2126 error = EWOULDBLOCK;
2127 goto out;
2129 error = ttysleep(tp, &lbolt, PCATCH,
2130 "ttybf2", 0);
2131 if (error)
2132 goto out;
2133 goto loop;
2135 if (ISSET(tp->t_lflag, FLUSHO) ||
2136 tp->t_outq.c_cc > hiwat)
2137 break;
2139 ttstart(tp);
2141 out:
2143 * If cc is nonzero, we leave the uio structure inconsistent, as the
2144 * offset and iov pointers have moved forward, but it doesn't matter
2145 * (the call will either return short or restart with a new uio).
2147 uio->uio_resid += cc;
2148 lwkt_reltoken(&tp->t_token);
2149 return (error);
2151 ovhiwat:
2152 ttstart(tp);
2154 * This can only occur if FLUSHO is set in t_lflag,
2155 * or if ttstart/oproc is synchronous (or very fast).
2157 if (tp->t_outq.c_cc <= hiwat) {
2158 goto loop;
2160 if (flag & IO_NDELAY) {
2161 uio->uio_resid += cc;
2162 lwkt_reltoken(&tp->t_token);
2163 return (uio->uio_resid == cnt ? EWOULDBLOCK : 0);
2165 SET(tp->t_state, TS_SO_OLOWAT);
2166 error = ttysleep(tp, TSA_OLOWAT(tp), PCATCH, "ttywri", tp->t_timeout);
2167 if (error == EWOULDBLOCK)
2168 error = EIO;
2169 if (error)
2170 goto out;
2171 goto loop;
2175 * Rubout one character from the rawq of tp
2176 * as cleanly as possible.
2177 * NOTE: Must be called with tp->t_token held
2179 static void
2180 ttyrub(int c, struct tty *tp)
2182 void *cp;
2183 int savecol;
2184 int tabc;
2186 ASSERT_LWKT_TOKEN_HELD(&tp->t_token);
2187 if (!ISSET(tp->t_lflag, ECHO) || ISSET(tp->t_lflag, EXTPROC))
2188 return;
2189 CLR(tp->t_lflag, FLUSHO);
2190 if (ISSET(tp->t_lflag, ECHOE)) {
2191 if (tp->t_rocount == 0) {
2193 * Screwed by ttwrite; retype
2195 ttyretype(tp);
2196 return;
2198 if (c == ('\t' | TTY_QUOTE) || c == ('\n' | TTY_QUOTE))
2199 ttyrubo(tp, 2);
2200 else {
2201 CLR(c, ~TTY_CHARMASK);
2202 switch (CCLASS(c)) {
2203 case ORDINARY:
2204 ttyrubo(tp, 1);
2205 break;
2206 case BACKSPACE:
2207 case CONTROL:
2208 case NEWLINE:
2209 case RETURN:
2210 case VTAB:
2211 if (ISSET(tp->t_lflag, ECHOCTL))
2212 ttyrubo(tp, 2);
2213 break;
2214 case TAB:
2215 if (tp->t_rocount < tp->t_rawq.c_cc) {
2216 ttyretype(tp);
2217 return;
2219 savecol = tp->t_column;
2220 SET(tp->t_state, TS_CNTTB);
2221 SET(tp->t_lflag, FLUSHO);
2222 tp->t_column = tp->t_rocol;
2224 cp = clist_nextc(&tp->t_rawq, NULL, &tabc);
2225 while (cp) {
2226 ttyecho(tabc, tp);
2227 cp = clist_nextc(&tp->t_rawq,
2228 cp, &tabc);
2230 CLR(tp->t_lflag, FLUSHO);
2231 CLR(tp->t_state, TS_CNTTB);
2233 /* savecol will now be length of the tab. */
2234 savecol -= tp->t_column;
2235 tp->t_column += savecol;
2236 if (savecol > 8)
2237 savecol = 8; /* overflow screw */
2238 while (--savecol >= 0)
2239 (void)ttyoutput('\b', tp);
2240 break;
2241 default: /* XXX */
2242 #define PANICSTR "ttyrub: would panic c = %d, val = %d\n"
2243 (void)kprintf(PANICSTR, c, CCLASS(c));
2244 #ifdef notdef
2245 panic(PANICSTR, c, CCLASS(c));
2246 #endif
2249 } else if (ISSET(tp->t_lflag, ECHOPRT)) {
2250 if (!ISSET(tp->t_state, TS_ERASE)) {
2251 SET(tp->t_state, TS_ERASE);
2252 (void)ttyoutput('\\', tp);
2254 ttyecho(c, tp);
2255 } else {
2256 ttyecho(tp->t_cc[VERASE], tp);
2258 * This code may be executed not only when an ERASE key
2259 * is pressed, but also when ^U (KILL) or ^W (WERASE) are.
2260 * So, I didn't think it was worthwhile to pass the extra
2261 * information (which would need an extra parameter,
2262 * changing every call) needed to distinguish the ERASE2
2263 * case from the ERASE.
2266 --tp->t_rocount;
2270 * Back over cnt characters, erasing them.
2271 * NOTE: Must be called with tp->t_token held
2273 static void
2274 ttyrubo(struct tty *tp, int cnt)
2276 ASSERT_LWKT_TOKEN_HELD(&tp->t_token);
2277 while (cnt-- > 0) {
2278 (void)ttyoutput('\b', tp);
2279 (void)ttyoutput(' ', tp);
2280 (void)ttyoutput('\b', tp);
2285 * ttyretype --
2286 * Reprint the rawq line. Note, it is assumed that c_cc has already
2287 * been checked.
2288 * NOTE: Must be called with tp->t_token held
2290 static void
2291 ttyretype(struct tty *tp)
2293 void *cp;
2294 int c;
2296 ASSERT_LWKT_TOKEN_HELD(&tp->t_token);
2297 /* Echo the reprint character. */
2298 if (tp->t_cc[VREPRINT] != _POSIX_VDISABLE)
2299 ttyecho(tp->t_cc[VREPRINT], tp);
2301 (void)ttyoutput('\n', tp);
2304 * XXX
2305 * FIX: NEXTC IS BROKEN - DOESN'T CHECK QUOTE
2306 * BIT OF FIRST CHAR.
2308 cp = clist_nextc(&tp->t_canq, NULL, &c);
2309 while (cp) {
2310 ttyecho(c, tp);
2311 cp = clist_nextc(&tp->t_canq, cp, &c);
2313 cp = clist_nextc(&tp->t_rawq, NULL, &c);
2314 while (cp) {
2315 ttyecho(c, tp);
2316 cp = clist_nextc(&tp->t_rawq, cp, &c);
2318 CLR(tp->t_state, TS_ERASE);
2320 tp->t_rocount = tp->t_rawq.c_cc;
2321 tp->t_rocol = 0;
2325 * Echo a typed character to the terminal.
2326 * NOTE: Must be called with tp->t_token held
2328 static void
2329 ttyecho(int c, struct tty *tp)
2331 ASSERT_LWKT_TOKEN_HELD(&tp->t_token);
2333 if (!ISSET(tp->t_state, TS_CNTTB))
2334 CLR(tp->t_lflag, FLUSHO);
2335 if ((!ISSET(tp->t_lflag, ECHO) &&
2336 (c != '\n' || !ISSET(tp->t_lflag, ECHONL))) ||
2337 ISSET(tp->t_lflag, EXTPROC))
2338 return;
2339 if (ISSET(tp->t_lflag, ECHOCTL) &&
2340 ((ISSET(c, TTY_CHARMASK) <= 037 && c != '\t' && c != '\n') ||
2341 ISSET(c, TTY_CHARMASK) == 0177)) {
2342 (void)ttyoutput('^', tp);
2343 CLR(c, ~TTY_CHARMASK);
2344 if (c == 0177)
2345 c = '?';
2346 else
2347 c += 'A' - 1;
2349 (void)ttyoutput(c, tp);
2353 * Wake up any readers on a tty.
2355 void
2356 ttwakeup(struct tty *tp)
2358 lwkt_gettoken(&tp->t_token);
2359 if (ISSET(tp->t_state, TS_ASYNC) && tp->t_sigio != NULL)
2360 pgsigio(tp->t_sigio, SIGIO, (tp->t_session != NULL));
2361 wakeup(TSA_HUP_OR_INPUT(tp));
2362 KNOTE(&tp->t_rkq.ki_note, 0);
2363 lwkt_reltoken(&tp->t_token);
2367 * Wake up any writers on a tty.
2369 void
2370 ttwwakeup(struct tty *tp)
2372 lwkt_gettoken(&tp->t_token);
2373 if (ISSET(tp->t_state, TS_ASYNC) && tp->t_sigio != NULL)
2374 pgsigio(tp->t_sigio, SIGIO, (tp->t_session != NULL));
2375 if (ISSET(tp->t_state, TS_BUSY | TS_SO_OCOMPLETE) ==
2376 TS_SO_OCOMPLETE && tp->t_outq.c_cc == 0) {
2377 CLR(tp->t_state, TS_SO_OCOMPLETE);
2378 wakeup(TSA_OCOMPLETE(tp));
2380 if (ISSET(tp->t_state, TS_SO_OLOWAT) &&
2381 tp->t_outq.c_cc <= tp->t_olowat) {
2382 CLR(tp->t_state, TS_SO_OLOWAT);
2383 wakeup(TSA_OLOWAT(tp));
2385 KNOTE(&tp->t_wkq.ki_note, 0);
2386 lwkt_reltoken(&tp->t_token);
2390 * Look up a code for a specified speed in a conversion table;
2391 * used by drivers to map software speed values to hardware parameters.
2392 * No requirements
2395 ttspeedtab(int speed, struct speedtab *table)
2398 for ( ; table->sp_speed != -1; table++)
2399 if (table->sp_speed == speed)
2400 return (table->sp_code);
2401 return (-1);
2405 * Set input and output watermarks and buffer sizes. For input, the
2406 * high watermark is about one second's worth of input above empty, the
2407 * low watermark is slightly below high water, and the buffer size is a
2408 * driver-dependent amount above high water. For output, the watermarks
2409 * are near the ends of the buffer, with about 1 second's worth of input
2410 * between them. All this only applies to the standard line discipline.
2412 #define CLAMP(x, h, l) ((x) > h ? h : ((x) < l) ? l : (x))
2414 void
2415 ttsetwater(struct tty *tp)
2417 int ttmaxhiwat; /* maximum high water mark */
2418 int cps; /* characters per second */
2419 int x;
2421 lwkt_gettoken(&tp->t_token);
2424 * Input side.
2426 * Calculate nominal low and high water marks, leave a little
2427 * room to absorb flow control latencies.
2429 clist_alloc_cblocks(&tp->t_canq, TTYHOG);
2431 switch (tp->t_ispeedwat) {
2432 case (speed_t)-1:
2433 cps = tp->t_ispeed / 10;
2434 break;
2435 case 0:
2437 * This case is for old drivers that don't know about
2438 * t_ispeedwat. Arrange for them to get the old buffer
2439 * sizes and watermarks.
2441 cps = TTYHOG - 2 * 256;
2442 tp->t_ififosize = 2 * 2048;
2443 break;
2444 default:
2445 cps = tp->t_ispeedwat / 10;
2446 break;
2448 tp->t_ihiwat = cps;
2449 tp->t_ilowat = 7 * cps / 8;
2450 x = cps + tp->t_ififosize;
2451 clist_alloc_cblocks(&tp->t_rawq, x);
2454 * Output side.
2456 * Calculate nominal low and high water marks, and make the
2457 * actual buffer just a tad larger to absorb flow control latencies.
2459 switch (tp->t_ospeedwat) {
2460 case (speed_t)-1:
2461 cps = tp->t_ospeed / 10;
2462 ttmaxhiwat = 2 * TTMAXHIWAT;
2463 break;
2464 case 0:
2465 cps = tp->t_ospeed / 10;
2466 ttmaxhiwat = TTMAXHIWAT;
2467 break;
2468 default:
2469 cps = tp->t_ospeedwat / 10;
2470 ttmaxhiwat = 8 * TTMAXHIWAT;
2471 break;
2474 x = CLAMP(cps / 2, TTMAXLOWAT, TTMINLOWAT);
2475 tp->t_olowat = x;
2477 x += cps;
2478 x = CLAMP(x, ttmaxhiwat, TTMINHIWAT);
2479 tp->t_ohiwat = x;
2481 x = imax(tp->t_ohiwat, TTMAXHIWAT);
2482 x += OBUFSIZ + 100;
2483 clist_alloc_cblocks(&tp->t_outq, x);
2485 lwkt_reltoken(&tp->t_token);
2488 #undef CLAMP
2491 * Report on state of foreground process group.
2493 void
2494 ttyinfo(struct tty *tp)
2496 struct pgrp *pgrp;
2497 struct proc *p, *pick;
2498 struct lwp *lp;
2499 struct rusage ru;
2500 char buf[64];
2501 const char *str;
2502 struct vmspace *vm;
2503 long vmsz;
2504 int pctcpu;
2505 int tmp;
2507 if (ttycheckoutq(tp,0) == 0)
2508 return;
2510 lwkt_gettoken(&tp->t_token);
2513 * We always print the load average, then figure out what else to
2514 * print based on the state of the current process group.
2516 tmp = (averunnable.ldavg[0] * 100 + FSCALE / 2) >> FSHIFT;
2517 ttyprintf(tp, "load: %d.%02d ", tmp / 100, tmp % 100);
2519 if (tp->t_session == NULL) {
2520 ttyprintf(tp, "not a controlling terminal\n");
2521 goto done2;
2523 if ((pgrp = tp->t_pgrp) == NULL) {
2524 ttyprintf(tp, "no foreground process group\n");
2525 goto done2;
2529 * Pick an interesting process. Note that certain elements,
2530 * in particular the wmesg.
2532 * NOTE: lwp_wmesg is lwp_thread->td_wmesg.
2534 pgref(pgrp);
2535 lwkt_gettoken(&pgrp->pg_token);
2537 pick = NULL;
2538 for (p = LIST_FIRST(&pgrp->pg_members);
2539 p != NULL;
2540 p = LIST_NEXT(p, p_pglist)) {
2541 PHOLD(p);
2542 if (proc_compare(pick, p)) {
2543 if (pick)
2544 PRELE(pick);
2545 pick = p;
2546 } else {
2547 PRELE(p);
2550 if (pick == NULL) {
2551 ttyprintf(tp, "empty foreground process group\n");
2552 goto done1;
2556 * Pick an interesting LWP (XXX)
2558 * pick is held.
2560 lp = FIRST_LWP_IN_PROC(pick);
2561 if (lp == NULL) {
2562 PRELE(pick);
2563 ttyprintf(tp, "foreground process without lwp\n");
2564 goto done1;
2568 * Figure out what wait/process-state message, and command
2569 * buffer to present
2572 * XXX lwp This is a horrible mixture. We need to rework this
2573 * as soon as lwps have their own runnable status.
2575 LWPHOLD(lp);
2576 if (pick->p_flags & P_WEXIT)
2577 str = "exiting";
2578 else if (lp->lwp_stat == LSRUN)
2579 str = "running";
2580 else if (pick->p_stat == SIDL)
2581 str = "spawning";
2582 else if (lp->lwp_wmesg) /* lwp_thread must not be NULL */
2583 str = lp->lwp_wmesg;
2584 else
2585 str = "iowait";
2587 ksnprintf(buf, sizeof(buf), "cmd: %s %d [%s]",
2588 pick->p_comm, pick->p_pid, str);
2591 * Calculate cpu usage, percent cpu, and cmsz. Note that
2592 * 'pick' becomes invalid the moment we release the token.
2594 if (lp->lwp_thread && (pick->p_flags & P_SWAPPEDOUT) == 0)
2595 calcru_proc(pick, &ru);
2597 pctcpu = (lp->lwp_pctcpu * 10000 + FSCALE / 2) >> FSHIFT;
2599 LWPRELE(lp);
2602 * NOTE: vmspace should be protected from destruction by the
2603 * combination of pg_token and the fact that we are not
2604 * flagged as a zombie.
2606 if (pick->p_stat == SIDL || pick->p_stat == SZOMB) {
2607 vmsz = 0;
2608 } else if ((vm = pick->p_vmspace) == NULL) {
2609 vmsz = 0;
2610 } else {
2611 vmspace_hold(vm);
2612 vmsz = pgtok(vmspace_resident_count(vm));
2613 vmspace_drop(vm);
2615 PRELE(pick);
2618 * Dump the output
2620 ttyprintf(tp, " %s ",
2621 buf);
2622 ttyprintf(tp, "%ld.%02ldu ",
2623 ru.ru_utime.tv_sec, ru.ru_utime.tv_usec / 10000);
2624 ttyprintf(tp, "%ld.%02lds ",
2625 ru.ru_stime.tv_sec, ru.ru_stime.tv_usec / 10000);
2626 ttyprintf(tp, "%d%% %ldk\n",
2627 pctcpu / 100, vmsz);
2629 done1:
2630 lwkt_reltoken(&pgrp->pg_token);
2631 pgrel(pgrp);
2632 done2:
2633 tp->t_rocount = 0; /* so pending input will be retyped if BS */
2634 lwkt_reltoken(&tp->t_token);
2638 * Returns 1 if p2 is "better" than p1
2640 * The algorithm for picking the "interesting" process is thus:
2642 * 1) Only foreground processes are eligible - implied.
2643 * 2) Runnable processes are favored over anything else. The runner
2644 * with the highest cpu utilization is picked (p_cpticks). Ties are
2645 * broken by picking the highest pid.
2646 * 3) The sleeper with the shortest sleep time is next. With ties,
2647 * we pick out just "short-term" sleepers (LWP_SINTR == 0).
2648 * 4) Further ties are broken by picking the highest pid.
2650 * NOTE: must be called with p1 and p2 held.
2652 #define ISRUN(lp) ((lp)->lwp_stat == LSRUN)
2653 #define TESTAB(a, b) ((a)<<1 | (b))
2654 #define ONLYA 2
2655 #define ONLYB 1
2656 #define BOTH 3
2658 static int
2659 proc_compare(struct proc *p1, struct proc *p2)
2661 struct lwp *lp1, *lp2;
2662 int res;
2664 if (p1 == NULL)
2665 return (1);
2666 if (lwkt_trytoken(&p1->p_token) == 0)
2667 return (1);
2668 if (lwkt_trytoken(&p2->p_token) == 0) {
2669 lwkt_reltoken(&p1->p_token);
2670 return (0);
2674 * weed out zombies
2676 switch (TESTAB(p1->p_stat == SZOMB, p2->p_stat == SZOMB)) {
2677 case ONLYA:
2678 res = 1;
2679 goto done;
2680 case ONLYB:
2681 res = 0;
2682 goto done;
2683 case BOTH:
2684 res = (p2->p_pid > p1->p_pid); /* tie - return highest pid */
2685 goto done;
2686 default:
2687 break;
2690 /* XXX choose the best lwp? */
2691 lp1 = FIRST_LWP_IN_PROC(p1);
2692 lp2 = FIRST_LWP_IN_PROC(p2);
2695 * Favor one with LWPs verses one that has none (is exiting).
2697 if (lp1 == NULL) {
2698 res = 1;
2699 goto done;
2701 if (lp2 == NULL) {
2702 res = 0;
2703 goto done;
2707 * see if at least one of them is runnable
2709 switch (TESTAB(ISRUN(lp1), ISRUN(lp2))) {
2710 case ONLYA:
2711 res = 0;
2712 goto done;
2713 case ONLYB:
2714 res = 1;
2715 goto done;
2716 case BOTH:
2718 * tie - favor one with highest recent cpu utilization
2720 if (lp2->lwp_cpticks > lp1->lwp_cpticks)
2721 res = 1;
2722 else if (lp1->lwp_cpticks > lp2->lwp_cpticks)
2723 res = 0;
2724 else
2725 res = (p2->p_pid > p1->p_pid); /* tie - ret highest */
2726 goto done;
2727 default:
2728 break;
2732 * Pick the one with the smallest sleep time
2734 if (lp2->lwp_slptime > lp1->lwp_slptime) {
2735 res = 0;
2736 goto done;
2738 if (lp1->lwp_slptime > lp2->lwp_slptime) {
2739 res = 1;
2740 goto done;
2744 * Favor one sleeping in a non-interruptible sleep
2746 if ((lp1->lwp_flags & LWP_SINTR) && (lp2->lwp_flags & LWP_SINTR) == 0)
2747 res = 1;
2748 else
2749 if ((lp2->lwp_flags & LWP_SINTR) && (lp1->lwp_flags & LWP_SINTR) == 0)
2750 res = 0;
2751 else
2752 res = (p2->p_pid > p1->p_pid); /* tie - return highest pid */
2753 /* fall through */
2755 done:
2756 lwkt_reltoken(&p2->p_token);
2757 lwkt_reltoken(&p1->p_token);
2758 return (res);
2762 * Output char to tty; console putchar style.
2765 tputchar(int c, struct tty *tp)
2767 lwkt_gettoken(&tp->t_token);
2768 if (!ISSET(tp->t_state, TS_CONNECTED)) {
2769 lwkt_reltoken(&tp->t_token);
2770 return (-1);
2772 if (c == '\n')
2773 (void)ttyoutput('\r', tp);
2774 (void)ttyoutput(c, tp);
2775 ttstart(tp);
2776 lwkt_reltoken(&tp->t_token);
2778 return (0);
2782 * Sleep on chan, returning ERESTART if tty changed while we napped and
2783 * returning any errors (e.g. EINTR/EWOULDBLOCK) reported by tsleep. If
2784 * the tty is revoked, restarting a pending call will redo validation done
2785 * at the start of the call.
2788 ttysleep(struct tty *tp, void *chan, int slpflags, char *wmesg, int timo)
2790 int error;
2791 int gen;
2793 gen = tp->t_gen;
2794 error = tsleep(chan, slpflags, wmesg, timo);
2795 if (error)
2796 return (error);
2797 return (tp->t_gen == gen ? 0 : ERESTART);
2801 * Revoke a tty.
2803 * We bump the gen to force any ttysleep()'s to return with ERESTART
2804 * and flush the tty. The related fp's should already have been
2805 * replaced so the tty will close when the last references on the
2806 * original fp's go away.
2809 ttyrevoke(struct dev_revoke_args *ap)
2811 struct tty *tp;
2813 tp = ap->a_head.a_dev->si_tty;
2814 lwkt_gettoken(&tp->t_token);
2815 tp->t_gen++;
2816 ttyflush(tp, FREAD | FWRITE);
2817 wakeup(TSA_CARR_ON(tp));
2818 ttwakeup(tp);
2819 ttwwakeup(tp);
2820 lwkt_reltoken(&tp->t_token);
2822 return (0);
2826 * Allocate a tty struct. Clists in the struct will be allocated by
2827 * ttyopen(). The tty itself is protected by tp->t_token. tty_token
2828 * is primarily used to interlock the NULL test and for registration.
2830 * by convention, once allocated, tty structures are never freed. This
2831 * saves us from numerous release race scenarios that can occur due to the
2832 * token being embedded in the tty structure.
2834 struct tty *
2835 ttymalloc(struct tty **tpp)
2837 struct tty *tp;
2839 if ((tp = *tpp) == NULL) {
2840 tp = kmalloc(sizeof *tp, M_TTYS, M_WAITOK|M_ZERO);
2841 lwkt_gettoken(&tty_token);
2842 if (*tpp == NULL) { /* recheck after blocking kmalloc */
2843 *tpp = tp;
2844 ttyinit(tp);
2845 ttyregister(tp);
2846 } else {
2847 kfree(tp, M_TTYS);
2849 lwkt_reltoken(&tty_token);
2851 return (tp);
2855 * Caller must hold tp->t_token
2857 void
2858 ttyunregister(struct tty *tp)
2860 lwkt_gettoken(&tty_token);
2861 if (ISSET(tp->t_state, TS_REGISTERED)) {
2862 CLR(tp->t_state, TS_REGISTERED);
2863 TAILQ_REMOVE(&tty_list, tp, t_list);
2865 lwkt_reltoken(&tty_token);
2868 void
2869 ttyinit(struct tty *tp)
2871 lwkt_token_init(&tp->t_token, "tp");
2874 void
2875 ttyregister(struct tty *tp)
2877 lwkt_gettoken(&tty_token);
2878 if (!ISSET(tp->t_state, TS_REGISTERED)) {
2879 SET(tp->t_state, TS_REGISTERED);
2880 TAILQ_INSERT_HEAD(&tty_list, tp, t_list);
2882 lwkt_reltoken(&tty_token);
2885 static int
2886 sysctl_kern_ttys(SYSCTL_HANDLER_ARGS)
2888 int error;
2889 struct tty *tp;
2890 struct tty t;
2891 struct tty marker;
2893 bzero(&marker, sizeof(marker));
2894 marker.t_state = TS_MARKER;
2895 error = 0;
2897 lwkt_gettoken(&tty_token);
2899 TAILQ_INSERT_HEAD(&tty_list, &marker, t_list);
2900 while ((tp = TAILQ_NEXT(&marker, t_list)) != NULL) {
2901 TAILQ_REMOVE(&tty_list, &marker, t_list);
2902 TAILQ_INSERT_AFTER(&tty_list, tp, &marker, t_list);
2903 if (tp->t_state & TS_MARKER)
2904 continue;
2905 t = *tp;
2906 if (t.t_dev)
2907 t.t_dev = (cdev_t)(uintptr_t)dev2udev(t.t_dev);
2908 error = SYSCTL_OUT(req, (caddr_t)&t, sizeof(t));
2909 if (error)
2910 break;
2912 TAILQ_REMOVE(&tty_list, &marker, t_list);
2913 lwkt_reltoken(&tty_token);
2914 return (error);
2917 SYSCTL_PROC(_kern, OID_AUTO, ttys, CTLTYPE_OPAQUE|CTLFLAG_RD,
2918 0, 0, sysctl_kern_ttys, "S,tty", "All struct ttys");
2920 void
2921 nottystop(struct tty *tp, int rw)
2923 return;
2927 ttyread(struct dev_read_args *ap)
2929 struct tty *tp;
2930 int ret;
2932 tp = ap->a_head.a_dev->si_tty;
2933 if (tp == NULL)
2934 return (ENODEV);
2935 lwkt_gettoken(&tp->t_token);
2936 ret = ((*linesw[tp->t_line].l_read)(tp, ap->a_uio, ap->a_ioflag));
2937 lwkt_reltoken(&tp->t_token);
2939 return ret;
2943 ttywrite(struct dev_write_args *ap)
2945 struct tty *tp;
2946 int ret;
2948 tp = ap->a_head.a_dev->si_tty;
2949 if (tp == NULL)
2950 return (ENODEV);
2951 lwkt_gettoken(&tp->t_token);
2952 ret = ((*linesw[tp->t_line].l_write)(tp, ap->a_uio, ap->a_ioflag));
2953 lwkt_reltoken(&tp->t_token);
2955 return ret;