kern: Remove debug print
[dragonfly.git] / sys / kern / tty.c
blobb4d096653e85553fd7fd0f25d095b1c6dc4821f6
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_compat.h"
75 #include "opt_uconsole.h"
77 #include <sys/param.h>
78 #include <sys/systm.h>
79 #include <sys/filio.h>
80 #if defined(COMPAT_43)
81 #include <sys/ioctl_compat.h>
82 #endif
83 #include <sys/proc.h>
84 #include <sys/priv.h>
85 #define TTYDEFCHARS
86 #include <sys/tty.h>
87 #include <sys/clist.h>
88 #undef TTYDEFCHARS
89 #include <sys/fcntl.h>
90 #include <sys/conf.h>
91 #include <sys/dkstat.h>
92 #include <sys/kernel.h>
93 #include <sys/vnode.h>
94 #include <sys/signalvar.h>
95 #include <sys/signal2.h>
96 #include <sys/resourcevar.h>
97 #include <sys/malloc.h>
98 #include <sys/filedesc.h>
99 #include <sys/sysctl.h>
100 #include <sys/thread2.h>
102 #include <vm/vm.h>
103 #include <sys/lock.h>
104 #include <vm/pmap.h>
105 #include <vm/vm_map.h>
106 #include <vm/vm_extern.h>
108 MALLOC_DEFINE(M_TTYS, "ttys", "tty data structures");
110 static int proc_compare (struct proc *p1, struct proc *p2);
111 static int ttnread (struct tty *tp);
112 static void ttyecho (int c, struct tty *tp);
113 static int ttyoutput (int c, struct tty *tp);
114 static void ttypend (struct tty *tp);
115 static void ttyretype (struct tty *tp);
116 static void ttyrub (int c, struct tty *tp);
117 static void ttyrubo (struct tty *tp, int cnt);
118 static void ttyunblock (struct tty *tp);
119 static int ttywflush (struct tty *tp);
120 static int filt_ttyread (struct knote *kn, long hint);
121 static void filt_ttyrdetach (struct knote *kn);
122 static int filt_ttywrite (struct knote *kn, long hint);
123 static void filt_ttywdetach (struct knote *kn);
126 * Table with character classes and parity. The 8th bit indicates parity,
127 * the 7th bit indicates the character is an alphameric or underscore (for
128 * ALTWERASE), and the low 6 bits indicate delay type. If the low 6 bits
129 * are 0 then the character needs no special processing on output; classes
130 * other than 0 might be translated or (not currently) require delays.
132 #define E 0x00 /* Even parity. */
133 #define O 0x80 /* Odd parity. */
134 #define PARITY(c) (char_type[c] & O)
136 #define ALPHA 0x40 /* Alpha or underscore. */
137 #define ISALPHA(c) (char_type[(c) & TTY_CHARMASK] & ALPHA)
139 #define CCLASSMASK 0x3f
140 #define CCLASS(c) (char_type[c] & CCLASSMASK)
142 #define BS BACKSPACE
143 #define CC CONTROL
144 #define CR RETURN
145 #define NA ORDINARY | ALPHA
146 #define NL NEWLINE
147 #define NO ORDINARY
148 #define TB TAB
149 #define VT VTAB
151 static u_char const char_type[] = {
152 E|CC, O|CC, O|CC, E|CC, O|CC, E|CC, E|CC, O|CC, /* nul - bel */
153 O|BS, E|TB, E|NL, O|CC, E|VT, O|CR, O|CC, E|CC, /* bs - si */
154 O|CC, E|CC, E|CC, O|CC, E|CC, O|CC, O|CC, E|CC, /* dle - etb */
155 E|CC, O|CC, O|CC, E|CC, O|CC, E|CC, E|CC, O|CC, /* can - us */
156 O|NO, E|NO, E|NO, O|NO, E|NO, O|NO, O|NO, E|NO, /* sp - ' */
157 E|NO, O|NO, O|NO, E|NO, O|NO, E|NO, E|NO, O|NO, /* ( - / */
158 E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* 0 - 7 */
159 O|NA, E|NA, E|NO, O|NO, E|NO, O|NO, O|NO, E|NO, /* 8 - ? */
160 O|NO, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA, /* @ - G */
161 E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* H - O */
162 E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* P - W */
163 O|NA, E|NA, E|NA, O|NO, E|NO, O|NO, O|NO, O|NA, /* X - _ */
164 E|NO, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* ` - g */
165 O|NA, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA, /* h - o */
166 O|NA, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA, /* p - w */
167 E|NA, O|NA, O|NA, E|NO, O|NO, E|NO, E|NO, O|CC, /* x - del */
169 * Meta chars; should be settable per character set;
170 * for now, treat them all as normal characters.
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,
184 NA, NA, NA, NA, NA, NA, NA, NA,
185 NA, NA, NA, NA, NA, NA, NA, NA,
186 NA, NA, NA, NA, NA, NA, NA, NA,
187 NA, NA, NA, NA, NA, NA, NA, NA,
189 #undef BS
190 #undef CC
191 #undef CR
192 #undef NA
193 #undef NL
194 #undef NO
195 #undef TB
196 #undef VT
198 /* Macros to clear/set/test flags. */
199 #define SET(t, f) (t) |= (f)
200 #define CLR(t, f) (t) &= ~(f)
201 #define ISSET(t, f) ((t) & (f))
203 #undef MAX_INPUT /* XXX wrong in <sys/syslimits.h> */
204 #define MAX_INPUT TTYHOG /* XXX limit is usually larger for !ICANON */
206 uint64_t tk_nin;
207 SYSCTL_OPAQUE(_kern, OID_AUTO, tk_nin, CTLFLAG_RD, &tk_nin, sizeof(tk_nin),
208 "LU", "TTY input statistic");
209 uint64_t tk_nout;
210 SYSCTL_OPAQUE(_kern, OID_AUTO, tk_nout, CTLFLAG_RD, &tk_nout, sizeof(tk_nout),
211 "LU", "TTY output statistic");
212 uint64_t tk_rawcc;
215 * list of struct tty where pstat(8) can pick it up with sysctl
217 static TAILQ_HEAD(, tty) tty_list = TAILQ_HEAD_INITIALIZER(tty_list);
220 * Initial open of tty, or (re)entry to standard tty line discipline.
223 ttyopen(cdev_t device, struct tty *tp)
225 crit_enter();
226 lwkt_gettoken(&tty_token);
227 tp->t_dev = device;
228 if (!ISSET(tp->t_state, TS_ISOPEN)) {
229 SET(tp->t_state, TS_ISOPEN);
230 if (ISSET(tp->t_cflag, CLOCAL)) {
231 SET(tp->t_state, TS_CONNECTED);
233 bzero(&tp->t_winsize, sizeof(tp->t_winsize));
235 ttsetwater(tp);
236 lwkt_reltoken(&tty_token);
237 crit_exit();
238 return (0);
242 * Handle close() on a tty line: flush and set to initial state,
243 * bumping generation number so that pending read/write calls
244 * can detect recycling of the tty.
246 * XXX our caller should have done `spltty(); l_close(); ttyclose();'
247 * and l_close() should have flushed, but we repeat the spltty() and
248 * the flush in case there are buggy callers.
251 ttyclose(struct tty *tp)
253 crit_enter();
254 lwkt_gettoken(&tty_token);
255 funsetown(&tp->t_sigio);
256 if (constty == tp)
257 constty = NULL;
259 ttyflush(tp, FREAD | FWRITE);
260 clist_free_cblocks(&tp->t_canq);
261 clist_free_cblocks(&tp->t_outq);
262 clist_free_cblocks(&tp->t_rawq);
264 tp->t_gen++;
265 tp->t_line = TTYDISC;
266 ttyclearsession(tp);
267 tp->t_state &= TS_REGISTERED; /* clear all bits except */
268 lwkt_reltoken(&tty_token);
269 crit_exit();
270 return (0);
274 * Disassociate the tty from its session. Traditionally this has only been
275 * a half-close, meaning that the session was still allowed to point at the
276 * tty (resulting in the tty in the ps command showing something like 'p0-'),
277 * even though the tty is no longer pointing at the session.
279 * The half close seems to be useful only for 'ps' output but there is as
280 * yet no reason to remove the feature. The full-close code is currently
281 * #if 0'd out. See also sess_rele() in kern/kern_proc.c.
283 void
284 ttyclearsession(struct tty *tp)
286 struct session *sp;
287 struct pgrp *opgrp;
289 lwkt_gettoken(&tty_token);
290 opgrp = tp->t_pgrp;
291 tp->t_pgrp = NULL;
292 if (opgrp) {
293 pgrel(opgrp);
294 opgrp = NULL;
297 if ((sp = tp->t_session) != NULL) {
298 tp->t_session = NULL;
299 #ifdef TTY_DO_FULL_CLOSE
300 /* FULL CLOSE (not yet) */
301 if (sp->s_ttyp == tp) {
302 sp->s_ttyp = NULL;
303 ttyunhold(tp);
304 } else {
305 kprintf("ttyclearsession: warning: sp->s_ttyp != tp "
306 "%p/%p\n", sp->s_ttyp, tp);
308 #endif
310 lwkt_reltoken(&tty_token);
314 * Release the tty vnode association for a session. This is the
315 * 'other half' of the close. Because multiple opens of /dev/tty
316 * only generate a single open to the actual tty, the file modes
317 * are locked to FREAD|FWRITE.
319 * If dorevoke is non-zero, the session is also revoked. We have to
320 * close the vnode if VCTTYISOPEN is set.
322 void
323 ttyclosesession(struct session *sp, int dorevoke)
325 struct vnode *vp;
327 lwkt_gettoken(&tty_token);
328 retry:
330 * There may not be a controlling terminal or it may have been closed
331 * out from under us.
333 if ((vp = sp->s_ttyvp) == NULL) {
334 lwkt_reltoken(&tty_token);
335 return;
339 * We need a lock if we have to close or revoke.
341 if ((vp->v_flag & VCTTYISOPEN) || dorevoke) {
342 vhold(vp);
343 if (vn_lock(vp, LK_EXCLUSIVE | LK_RETRY | LK_FAILRECLAIM)) {
344 vdrop(vp);
345 goto retry;
349 * Retry if the vnode was ripped out from under us
351 if (vp != sp->s_ttyvp) {
352 vn_unlock(vp);
353 vdrop(vp);
354 goto retry;
358 * Close and revoke as needed
360 sp->s_ttyvp = NULL;
361 if (vp->v_flag & VCTTYISOPEN) {
362 vclrflags(vp, VCTTYISOPEN);
363 VOP_CLOSE(vp, FREAD|FWRITE, NULL);
365 vn_unlock(vp);
366 if (dorevoke)
367 vrevoke(vp, proc0.p_ucred);
368 vdrop(vp);
369 } else {
370 sp->s_ttyvp = NULL;
372 vrele(vp);
373 lwkt_reltoken(&tty_token);
376 #define FLUSHQ(q) { \
377 if ((q)->c_cc) \
378 ndflush(q, (q)->c_cc); \
381 /* Is 'c' a line delimiter ("break" character)? */
382 #define TTBREAKC(c, lflag) \
383 ((c) == '\n' || (((c) == cc[VEOF] || \
384 (c) == cc[VEOL] || ((c) == cc[VEOL2] && lflag & IEXTEN)) && \
385 (c) != _POSIX_VDISABLE))
388 * Process input of a single character received on a tty.
391 ttyinput(int c, struct tty *tp)
393 tcflag_t iflag, lflag;
394 cc_t *cc;
395 int i, err;
397 lwkt_gettoken(&tty_token);
399 * If input is pending take it first.
401 lflag = tp->t_lflag;
402 if (ISSET(lflag, PENDIN))
403 ttypend(tp);
405 * Gather stats.
407 if (ISSET(lflag, ICANON))
408 ++tp->t_cancc;
409 else
410 ++tp->t_rawcc;
411 ++tk_nin;
414 * Block further input iff:
415 * current input > threshold AND input is available to user program
416 * AND input flow control is enabled and not yet invoked.
417 * The 3 is slop for PARMRK.
419 iflag = tp->t_iflag;
420 if (tp->t_rawq.c_cc + tp->t_canq.c_cc > tp->t_ihiwat - 3 &&
421 (!ISSET(lflag, ICANON) || tp->t_canq.c_cc != 0) &&
422 (ISSET(tp->t_cflag, CRTS_IFLOW) || ISSET(iflag, IXOFF)) &&
423 !ISSET(tp->t_state, TS_TBLOCK))
424 ttyblock(tp);
426 /* Handle exceptional conditions (break, parity, framing). */
427 cc = tp->t_cc;
428 err = (ISSET(c, TTY_ERRORMASK));
429 if (err) {
430 CLR(c, TTY_ERRORMASK);
431 if (ISSET(err, TTY_BI)) {
432 if (ISSET(iflag, IGNBRK)) {
433 lwkt_reltoken(&tty_token);
434 return (0);
436 if (ISSET(iflag, BRKINT)) {
437 ttyflush(tp, FREAD | FWRITE);
438 pgsignal(tp->t_pgrp, SIGINT, 1);
439 goto endcase;
441 if (ISSET(iflag, PARMRK))
442 goto parmrk;
443 } else if ((ISSET(err, TTY_PE) && ISSET(iflag, INPCK))
444 || ISSET(err, TTY_FE)) {
445 if (ISSET(iflag, IGNPAR)) {
446 lwkt_reltoken(&tty_token);
447 return (0);
449 else if (ISSET(iflag, PARMRK)) {
450 parmrk:
451 if (tp->t_rawq.c_cc + tp->t_canq.c_cc >
452 MAX_INPUT - 3)
453 goto input_overflow;
454 clist_putc(0377 | TTY_QUOTE, &tp->t_rawq);
455 clist_putc(0 | TTY_QUOTE, &tp->t_rawq);
456 clist_putc(c | TTY_QUOTE, &tp->t_rawq);
457 goto endcase;
458 } else
459 c = 0;
463 if (!ISSET(tp->t_state, TS_TYPEN) && ISSET(iflag, ISTRIP))
464 CLR(c, 0x80);
465 if (!ISSET(lflag, EXTPROC)) {
467 * Check for literal nexting very first
469 if (ISSET(tp->t_state, TS_LNCH)) {
470 SET(c, TTY_QUOTE);
471 CLR(tp->t_state, TS_LNCH);
474 * Scan for special characters. This code
475 * is really just a big case statement with
476 * non-constant cases. The bottom of the
477 * case statement is labeled ``endcase'', so goto
478 * it after a case match, or similar.
482 * Control chars which aren't controlled
483 * by ICANON, ISIG, or IXON.
485 if (ISSET(lflag, IEXTEN)) {
486 if (CCEQ(cc[VLNEXT], c)) {
487 if (ISSET(lflag, ECHO)) {
488 if (ISSET(lflag, ECHOE)) {
489 (void)ttyoutput('^', tp);
490 (void)ttyoutput('\b', tp);
491 } else
492 ttyecho(c, tp);
494 SET(tp->t_state, TS_LNCH);
495 goto endcase;
497 if (CCEQ(cc[VDISCARD], c)) {
498 if (ISSET(lflag, FLUSHO))
499 CLR(tp->t_lflag, FLUSHO);
500 else {
501 ttyflush(tp, FWRITE);
502 ttyecho(c, tp);
503 if (tp->t_rawq.c_cc + tp->t_canq.c_cc)
504 ttyretype(tp);
505 SET(tp->t_lflag, FLUSHO);
507 goto startoutput;
511 * Signals.
513 if (ISSET(lflag, ISIG)) {
514 if (CCEQ(cc[VINTR], c) || CCEQ(cc[VQUIT], c)) {
515 if (!ISSET(lflag, NOFLSH))
516 ttyflush(tp, FREAD | FWRITE);
517 ttyecho(c, tp);
518 pgsignal(tp->t_pgrp,
519 CCEQ(cc[VINTR], c) ? SIGINT : SIGQUIT, 1);
520 goto endcase;
522 if (CCEQ(cc[VSUSP], c)) {
523 if (!ISSET(lflag, NOFLSH))
524 ttyflush(tp, FREAD);
525 ttyecho(c, tp);
526 pgsignal(tp->t_pgrp, SIGTSTP, 1);
527 goto endcase;
531 * Handle start/stop characters.
533 if (ISSET(iflag, IXON)) {
534 if (CCEQ(cc[VSTOP], c)) {
535 if (!ISSET(tp->t_state, TS_TTSTOP)) {
536 SET(tp->t_state, TS_TTSTOP);
537 (*tp->t_stop)(tp, 0);
538 lwkt_reltoken(&tty_token);
539 return (0);
541 if (!CCEQ(cc[VSTART], c)) {
542 lwkt_reltoken(&tty_token);
543 return (0);
546 * if VSTART == VSTOP then toggle
548 goto endcase;
550 if (CCEQ(cc[VSTART], c))
551 goto restartoutput;
554 * IGNCR, ICRNL, & INLCR
556 if (c == '\r') {
557 if (ISSET(iflag, IGNCR)) {
558 lwkt_reltoken(&tty_token);
559 return (0);
561 else if (ISSET(iflag, ICRNL))
562 c = '\n';
563 } else if (c == '\n' && ISSET(iflag, INLCR))
564 c = '\r';
566 if (!ISSET(tp->t_lflag, EXTPROC) && ISSET(lflag, ICANON)) {
568 * From here on down canonical mode character
569 * processing takes place.
572 * erase or erase2 (^H / ^?)
574 if (CCEQ(cc[VERASE], c) || CCEQ(cc[VERASE2], c) ) {
575 if (tp->t_rawq.c_cc)
576 ttyrub(clist_unputc(&tp->t_rawq), tp);
577 goto endcase;
580 * kill (^U)
582 if (CCEQ(cc[VKILL], c)) {
583 if (ISSET(lflag, ECHOKE) &&
584 tp->t_rawq.c_cc == tp->t_rocount &&
585 !ISSET(lflag, ECHOPRT))
586 while (tp->t_rawq.c_cc)
587 ttyrub(clist_unputc(&tp->t_rawq), tp);
588 else {
589 ttyecho(c, tp);
590 if (ISSET(lflag, ECHOK) ||
591 ISSET(lflag, ECHOKE))
592 ttyecho('\n', tp);
593 FLUSHQ(&tp->t_rawq);
594 tp->t_rocount = 0;
596 CLR(tp->t_state, TS_LOCAL);
597 goto endcase;
600 * word erase (^W)
602 if (CCEQ(cc[VWERASE], c) && ISSET(lflag, IEXTEN)) {
603 int ctype;
606 * erase whitespace
608 while ((c = clist_unputc(&tp->t_rawq)) == ' ' || c == '\t')
609 ttyrub(c, tp);
610 if (c == -1)
611 goto endcase;
613 * erase last char of word and remember the
614 * next chars type (for ALTWERASE)
616 ttyrub(c, tp);
617 c = clist_unputc(&tp->t_rawq);
618 if (c == -1)
619 goto endcase;
620 if (c == ' ' || c == '\t') {
621 clist_putc(c, &tp->t_rawq);
622 goto endcase;
624 ctype = ISALPHA(c);
626 * erase rest of word
628 do {
629 ttyrub(c, tp);
630 c = clist_unputc(&tp->t_rawq);
631 if (c == -1)
632 goto endcase;
633 } while (c != ' ' && c != '\t' &&
634 (!ISSET(lflag, ALTWERASE) || ISALPHA(c) == ctype));
635 clist_putc(c, &tp->t_rawq);
636 goto endcase;
639 * reprint line (^R)
641 if (CCEQ(cc[VREPRINT], c) && ISSET(lflag, IEXTEN)) {
642 ttyretype(tp);
643 goto endcase;
646 * ^T - kernel info and generate SIGINFO
648 if (CCEQ(cc[VSTATUS], c) && ISSET(lflag, IEXTEN)) {
649 if (ISSET(lflag, ISIG))
650 pgsignal(tp->t_pgrp, SIGINFO, 1);
651 if (!ISSET(lflag, NOKERNINFO))
652 ttyinfo(tp);
653 goto endcase;
655 if (CCEQ(cc[VCHECKPT], c) && ISSET(lflag, IEXTEN)) {
656 if (ISSET(lflag, ISIG))
657 pgsignal(tp->t_pgrp, SIGCKPT, 1);
658 goto endcase;
662 * Check for input buffer overflow
664 if (tp->t_rawq.c_cc + tp->t_canq.c_cc >= MAX_INPUT) {
665 input_overflow:
666 if (ISSET(iflag, IMAXBEL)) {
667 if (tp->t_outq.c_cc < tp->t_ohiwat)
668 (void)ttyoutput(CTRL('g'), tp);
670 goto endcase;
673 if ( c == 0377 && ISSET(iflag, PARMRK) && !ISSET(iflag, ISTRIP)
674 && ISSET(iflag, IGNBRK|IGNPAR) != (IGNBRK|IGNPAR))
675 clist_putc(0377 | TTY_QUOTE, &tp->t_rawq);
678 * Put data char in q for user and
679 * wakeup on seeing a line delimiter.
681 if (clist_putc(c, &tp->t_rawq) >= 0) {
682 if (!ISSET(lflag, ICANON)) {
683 ttwakeup(tp);
684 ttyecho(c, tp);
685 goto endcase;
687 if (TTBREAKC(c, lflag)) {
688 tp->t_rocount = 0;
689 catq(&tp->t_rawq, &tp->t_canq);
690 ttwakeup(tp);
691 } else if (tp->t_rocount++ == 0)
692 tp->t_rocol = tp->t_column;
693 if (ISSET(tp->t_state, TS_ERASE)) {
695 * end of prterase \.../
697 CLR(tp->t_state, TS_ERASE);
698 (void)ttyoutput('/', tp);
700 i = tp->t_column;
701 ttyecho(c, tp);
702 if (CCEQ(cc[VEOF], c) && ISSET(lflag, ECHO)) {
704 * Place the cursor over the '^' of the ^D.
706 i = imin(2, tp->t_column - i);
707 while (i > 0) {
708 (void)ttyoutput('\b', tp);
709 i--;
713 endcase:
715 * IXANY means allow any character to restart output.
717 if (ISSET(tp->t_state, TS_TTSTOP) &&
718 !ISSET(iflag, IXANY) && cc[VSTART] != cc[VSTOP]) {
719 lwkt_reltoken(&tty_token);
720 return (0);
722 restartoutput:
723 CLR(tp->t_lflag, FLUSHO);
724 CLR(tp->t_state, TS_TTSTOP);
725 startoutput:
726 lwkt_reltoken(&tty_token);
727 return (ttstart(tp));
731 * Output a single character on a tty, doing output processing
732 * as needed (expanding tabs, newline processing, etc.).
733 * Returns < 0 if succeeds, otherwise returns char to resend.
734 * Must be recursive.
736 static int
737 ttyoutput(int c, struct tty *tp)
739 tcflag_t oflag;
740 int col;
742 lwkt_gettoken(&tty_token);
743 oflag = tp->t_oflag;
744 if (!ISSET(oflag, OPOST)) {
745 if (ISSET(tp->t_lflag, FLUSHO)) {
746 lwkt_reltoken(&tty_token);
747 return (-1);
749 if (clist_putc(c, &tp->t_outq)) {
750 lwkt_reltoken(&tty_token);
751 return (c);
753 tk_nout++;
754 tp->t_outcc++;
755 lwkt_reltoken(&tty_token);
756 return (-1);
759 * Do tab expansion if OXTABS is set. Special case if we external
760 * processing, we don't do the tab expansion because we'll probably
761 * get it wrong. If tab expansion needs to be done, let it happen
762 * externally.
764 CLR(c, ~TTY_CHARMASK);
765 if (c == '\t' &&
766 ISSET(oflag, OXTABS) && !ISSET(tp->t_lflag, EXTPROC)) {
767 c = 8 - (tp->t_column & 7);
768 if (!ISSET(tp->t_lflag, FLUSHO)) {
769 crit_enter(); /* Don't interrupt tabs. */
770 c -= b_to_q(" ", c, &tp->t_outq);
771 tk_nout += c;
772 tp->t_outcc += c;
773 crit_exit();
775 tp->t_column += c;
776 lwkt_reltoken(&tty_token);
777 return (c ? -1 : '\t');
779 if (c == CEOT && ISSET(oflag, ONOEOT)) {
780 lwkt_reltoken(&tty_token);
781 return (-1);
785 * Newline translation: if ONLCR is set,
786 * translate newline into "\r\n".
788 if (c == '\n' && ISSET(tp->t_oflag, ONLCR)) {
789 tk_nout++;
790 tp->t_outcc++;
791 if (!ISSET(tp->t_lflag, FLUSHO) && clist_putc('\r', &tp->t_outq)) {
792 lwkt_reltoken(&tty_token);
793 return (c);
796 /* If OCRNL is set, translate "\r" into "\n". */
797 else if (c == '\r' && ISSET(tp->t_oflag, OCRNL))
798 c = '\n';
799 /* If ONOCR is set, don't transmit CRs when on column 0. */
800 else if (c == '\r' && ISSET(tp->t_oflag, ONOCR) && tp->t_column == 0) {
801 lwkt_reltoken(&tty_token);
802 return (-1);
805 tk_nout++;
806 tp->t_outcc++;
807 if (!ISSET(tp->t_lflag, FLUSHO) && clist_putc(c, &tp->t_outq)) {
808 lwkt_reltoken(&tty_token);
809 return (c);
812 col = tp->t_column;
813 switch (CCLASS(c)) {
814 case BACKSPACE:
815 if (col > 0)
816 --col;
817 break;
818 case CONTROL:
819 break;
820 case NEWLINE:
821 if (ISSET(tp->t_oflag, ONLCR | ONLRET))
822 col = 0;
823 break;
824 case RETURN:
825 col = 0;
826 break;
827 case ORDINARY:
828 ++col;
829 break;
830 case TAB:
831 col = (col + 8) & ~7;
832 break;
834 tp->t_column = col;
835 lwkt_reltoken(&tty_token);
836 return (-1);
840 * Ioctls for all tty devices. Called after line-discipline specific ioctl
841 * has been called to do discipline-specific functions and/or reject any
842 * of these ioctl commands.
844 /* ARGSUSED */
846 ttioctl(struct tty *tp, u_long cmd, void *data, int flag)
848 struct thread *td = curthread;
849 struct lwp *lp = td->td_lwp;
850 struct proc *p = td->td_proc;
851 struct pgrp *opgrp;
852 struct tty *otp;
853 int error;
855 KKASSERT(p);
856 lwkt_gettoken(&tty_token);
857 lwkt_gettoken(&p->p_token);
859 /* If the ioctl involves modification, hang if in the background. */
860 switch (cmd) {
861 case TIOCCBRK:
862 case TIOCCONS:
863 case TIOCDRAIN:
864 case TIOCEXCL:
865 case TIOCFLUSH:
866 #ifdef TIOCHPCL
867 case TIOCHPCL:
868 #endif
869 case TIOCNXCL:
870 case TIOCSBRK:
871 case TIOCSCTTY:
872 case TIOCSDRAINWAIT:
873 case TIOCSETA:
874 case TIOCSETAF:
875 case TIOCSETAW:
876 case TIOCSETD:
877 case TIOCSPGRP:
878 case TIOCSTART:
879 case TIOCSTAT:
880 case TIOCSTI:
881 case TIOCSTOP:
882 case TIOCSWINSZ:
883 #if defined(COMPAT_43)
884 case TIOCLBIC:
885 case TIOCLBIS:
886 case TIOCLSET:
887 case TIOCSETC:
888 case OTIOCSETD:
889 case TIOCSETN:
890 case TIOCSETP:
891 case TIOCSLTC:
892 #endif
893 while (isbackground(p, tp) && !(p->p_flags & P_PPWAIT) &&
894 !SIGISMEMBER(p->p_sigignore, SIGTTOU) &&
895 !SIGISMEMBER(lp->lwp_sigmask, SIGTTOU)) {
896 if (p->p_pgrp->pg_jobc == 0) {
897 lwkt_reltoken(&p->p_token);
898 lwkt_reltoken(&tty_token);
899 return (EIO);
901 pgsignal(p->p_pgrp, SIGTTOU, 1);
902 error = ttysleep(tp, &lbolt, PCATCH, "ttybg1",
904 if (error) {
905 lwkt_reltoken(&p->p_token);
906 lwkt_reltoken(&tty_token);
907 return (error);
910 break;
913 switch (cmd) { /* Process the ioctl. */
914 case FIOASYNC: /* set/clear async i/o */
915 crit_enter();
916 if (*(int *)data)
917 SET(tp->t_state, TS_ASYNC);
918 else
919 CLR(tp->t_state, TS_ASYNC);
920 crit_exit();
921 break;
922 case FIONREAD: /* get # bytes to read */
923 crit_enter();
924 *(int *)data = ttnread(tp);
925 crit_exit();
926 break;
928 case FIOSETOWN:
930 * Policy -- Don't allow FIOSETOWN on someone else's
931 * controlling tty
933 if (tp->t_session != NULL && !isctty(p, tp)) {
934 lwkt_reltoken(&p->p_token);
935 lwkt_reltoken(&tty_token);
936 return (ENOTTY);
939 error = fsetown(*(int *)data, &tp->t_sigio);
940 if (error) {
941 lwkt_reltoken(&p->p_token);
942 lwkt_reltoken(&tty_token);
943 return (error);
945 break;
946 case FIOGETOWN:
947 if (tp->t_session != NULL && !isctty(p, tp)) {
948 lwkt_reltoken(&p->p_token);
949 lwkt_reltoken(&tty_token);
950 return (ENOTTY);
952 *(int *)data = fgetown(&tp->t_sigio);
953 break;
955 case TIOCEXCL: /* set exclusive use of tty */
956 crit_enter();
957 SET(tp->t_state, TS_XCLUDE);
958 crit_exit();
959 break;
960 case TIOCFLUSH: { /* flush buffers */
961 int flags = *(int *)data;
963 if (flags == 0)
964 flags = FREAD | FWRITE;
965 else
966 flags &= FREAD | FWRITE;
967 ttyflush(tp, flags);
968 break;
970 case TIOCCONS: /* become virtual console */
971 if (*(int *)data) {
972 if (constty && constty != tp &&
973 ISSET(constty->t_state, TS_CONNECTED)) {
974 lwkt_reltoken(&p->p_token);
975 lwkt_reltoken(&tty_token);
976 return (EBUSY);
978 #ifndef UCONSOLE
979 if ((error = priv_check(td, PRIV_ROOT)) != 0) {
980 lwkt_reltoken(&p->p_token);
981 lwkt_reltoken(&tty_token);
982 return (error);
984 #endif
985 constty = tp;
986 } else if (tp == constty)
987 constty = NULL;
988 break;
989 case TIOCDRAIN: /* wait till output drained */
990 error = ttywait(tp);
991 if (error) {
992 lwkt_reltoken(&p->p_token);
993 lwkt_reltoken(&tty_token);
994 return (error);
996 break;
997 case TIOCGETA: { /* get termios struct */
998 struct termios *t = (struct termios *)data;
1000 bcopy(&tp->t_termios, t, sizeof(struct termios));
1001 break;
1003 case TIOCGETD: /* get line discipline */
1004 *(int *)data = tp->t_line;
1005 break;
1006 case TIOCGWINSZ: /* get window size */
1007 *(struct winsize *)data = tp->t_winsize;
1008 break;
1009 case TIOCGPGRP: /* get pgrp of tty */
1010 if (!isctty(p, tp)) {
1011 lwkt_reltoken(&p->p_token);
1012 lwkt_reltoken(&tty_token);
1013 return (ENOTTY);
1015 *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
1016 break;
1017 case TIOCGSID: /* get sid of tty */
1018 if (!isctty(p, tp)) {
1019 lwkt_reltoken(&p->p_token);
1020 lwkt_reltoken(&tty_token);
1021 return (ENOTTY);
1023 *(int *)data = tp->t_session->s_sid;
1024 break;
1025 #ifdef TIOCHPCL
1026 case TIOCHPCL: /* hang up on last close */
1027 crit_enter();
1028 SET(tp->t_cflag, HUPCL);
1029 crit_exit();
1030 break;
1031 #endif
1032 case TIOCNXCL: /* reset exclusive use of tty */
1033 crit_enter();
1034 CLR(tp->t_state, TS_XCLUDE);
1035 crit_exit();
1036 break;
1037 case TIOCOUTQ: /* output queue size */
1038 *(int *)data = tp->t_outq.c_cc;
1039 break;
1040 case TIOCSETA: /* set termios struct */
1041 case TIOCSETAW: /* drain output, set */
1042 case TIOCSETAF: { /* drn out, fls in, set */
1043 struct termios *t = (struct termios *)data;
1045 if (t->c_ispeed == 0)
1046 t->c_ispeed = t->c_ospeed;
1047 if (t->c_ispeed == 0)
1048 t->c_ispeed = tp->t_ospeed;
1049 if (t->c_ispeed == 0) {
1050 lwkt_reltoken(&p->p_token);
1051 lwkt_reltoken(&tty_token);
1052 return (EINVAL);
1054 crit_enter();
1055 if (cmd == TIOCSETAW || cmd == TIOCSETAF) {
1056 error = ttywait(tp);
1057 if (error) {
1058 crit_exit();
1059 lwkt_reltoken(&p->p_token);
1060 lwkt_reltoken(&tty_token);
1061 return (error);
1063 if (cmd == TIOCSETAF)
1064 ttyflush(tp, FREAD);
1066 if (!ISSET(t->c_cflag, CIGNORE)) {
1068 * Set device hardware.
1070 if (tp->t_param && (error = (*tp->t_param)(tp, t))) {
1071 crit_exit();
1072 lwkt_reltoken(&p->p_token);
1073 lwkt_reltoken(&tty_token);
1074 return (error);
1076 if (ISSET(t->c_cflag, CLOCAL) &&
1077 !ISSET(tp->t_cflag, CLOCAL)) {
1079 * XXX disconnections would be too hard to
1080 * get rid of without this kludge. The only
1081 * way to get rid of controlling terminals
1082 * is to exit from the session leader.
1084 CLR(tp->t_state, TS_ZOMBIE);
1086 wakeup(TSA_CARR_ON(tp));
1087 ttwakeup(tp);
1088 ttwwakeup(tp);
1090 if ((ISSET(tp->t_state, TS_CARR_ON) ||
1091 ISSET(t->c_cflag, CLOCAL)) &&
1092 !ISSET(tp->t_state, TS_ZOMBIE))
1093 SET(tp->t_state, TS_CONNECTED);
1094 else
1095 CLR(tp->t_state, TS_CONNECTED);
1096 tp->t_cflag = t->c_cflag;
1097 tp->t_ispeed = t->c_ispeed;
1098 if (t->c_ospeed != 0)
1099 tp->t_ospeed = t->c_ospeed;
1100 ttsetwater(tp);
1102 if (ISSET(t->c_lflag, ICANON) != ISSET(tp->t_lflag, ICANON) &&
1103 cmd != TIOCSETAF) {
1104 if (ISSET(t->c_lflag, ICANON))
1105 SET(tp->t_lflag, PENDIN);
1106 else {
1108 * XXX we really shouldn't allow toggling
1109 * ICANON while we're in a non-termios line
1110 * discipline. Now we have to worry about
1111 * panicing for a null queue.
1113 if (tp->t_canq.c_cbreserved > 0 &&
1114 tp->t_rawq.c_cbreserved > 0) {
1115 catq(&tp->t_rawq, &tp->t_canq);
1117 * XXX the queue limits may be
1118 * different, so the old queue
1119 * swapping method no longer works.
1121 catq(&tp->t_canq, &tp->t_rawq);
1123 CLR(tp->t_lflag, PENDIN);
1125 ttwakeup(tp);
1127 tp->t_iflag = t->c_iflag;
1128 tp->t_oflag = t->c_oflag;
1130 * Make the EXTPROC bit read only.
1132 if (ISSET(tp->t_lflag, EXTPROC))
1133 SET(t->c_lflag, EXTPROC);
1134 else
1135 CLR(t->c_lflag, EXTPROC);
1136 tp->t_lflag = t->c_lflag | ISSET(tp->t_lflag, PENDIN);
1137 if (t->c_cc[VMIN] != tp->t_cc[VMIN] ||
1138 t->c_cc[VTIME] != tp->t_cc[VTIME])
1139 ttwakeup(tp);
1140 bcopy(t->c_cc, tp->t_cc, sizeof(t->c_cc));
1141 crit_exit();
1142 break;
1144 case TIOCSETD: { /* set line discipline */
1145 int t = *(int *)data;
1146 cdev_t device = tp->t_dev;
1148 if ((u_int)t >= nlinesw) {
1149 lwkt_reltoken(&p->p_token);
1150 lwkt_reltoken(&tty_token);
1151 return (ENXIO);
1153 if (t != tp->t_line) {
1154 crit_enter();
1155 (*linesw[tp->t_line].l_close)(tp, flag);
1156 error = (*linesw[t].l_open)(device, tp);
1157 if (error) {
1158 (void)(*linesw[tp->t_line].l_open)(device, tp);
1159 crit_exit();
1160 lwkt_reltoken(&p->p_token);
1161 lwkt_reltoken(&tty_token);
1162 return (error);
1164 tp->t_line = t;
1165 crit_exit();
1167 break;
1169 case TIOCSTART: /* start output, like ^Q */
1170 crit_enter();
1171 if (ISSET(tp->t_state, TS_TTSTOP) ||
1172 ISSET(tp->t_lflag, FLUSHO)) {
1173 CLR(tp->t_lflag, FLUSHO);
1174 CLR(tp->t_state, TS_TTSTOP);
1175 ttstart(tp);
1177 crit_exit();
1178 break;
1179 case TIOCSTI: /* simulate terminal input */
1180 if ((flag & FREAD) == 0 && priv_check(td, PRIV_ROOT)) {
1181 lwkt_reltoken(&p->p_token);
1182 lwkt_reltoken(&tty_token);
1183 return (EPERM);
1185 if (!isctty(p, tp) && priv_check(td, PRIV_ROOT)) {
1186 lwkt_reltoken(&p->p_token);
1187 lwkt_reltoken(&tty_token);
1188 return (EACCES);
1190 crit_enter();
1191 (*linesw[tp->t_line].l_rint)(*(u_char *)data, tp);
1192 crit_exit();
1193 break;
1194 case TIOCSTOP: /* stop output, like ^S */
1195 crit_enter();
1196 if (!ISSET(tp->t_state, TS_TTSTOP)) {
1197 SET(tp->t_state, TS_TTSTOP);
1198 (*tp->t_stop)(tp, 0);
1200 crit_exit();
1201 break;
1202 case TIOCSCTTY: /* become controlling tty */
1203 /* Session ctty vnode pointer set in vnode layer. */
1204 if (!SESS_LEADER(p) ||
1205 ((p->p_session->s_ttyvp || tp->t_session) &&
1206 (tp->t_session != p->p_session))) {
1207 lwkt_reltoken(&p->p_token);
1208 lwkt_reltoken(&tty_token);
1209 return (EPERM);
1211 ttyhold(tp);
1212 tp->t_session = p->p_session;
1213 opgrp = tp->t_pgrp;
1214 pgref(p->p_pgrp);
1215 tp->t_pgrp = p->p_pgrp;
1216 otp = p->p_session->s_ttyp;
1217 p->p_session->s_ttyp = tp;
1218 p->p_flags |= P_CONTROLT;
1219 if (otp)
1220 ttyunhold(otp);
1221 if (opgrp) {
1222 pgrel(opgrp);
1223 opgrp = NULL;
1225 break;
1226 case TIOCSPGRP: { /* set pgrp of tty */
1227 pid_t pgid = *(int *)data;
1229 if (!isctty(p, tp)) {
1230 lwkt_reltoken(&p->p_token);
1231 lwkt_reltoken(&tty_token);
1232 return (ENOTTY);
1234 else if (pgid < 1 || pgid > PID_MAX) {
1235 lwkt_reltoken(&p->p_token);
1236 lwkt_reltoken(&tty_token);
1237 return (EINVAL);
1238 } else {
1239 struct pgrp *pgrp = pgfind(pgid);
1240 if (pgrp == NULL || pgrp->pg_session != p->p_session) {
1241 if (pgrp)
1242 pgrel(pgrp);
1243 lwkt_reltoken(&p->p_token);
1244 lwkt_reltoken(&tty_token);
1245 return (EPERM);
1247 opgrp = tp->t_pgrp;
1248 tp->t_pgrp = pgrp;
1249 if (opgrp) {
1250 pgrel(opgrp);
1251 opgrp = NULL;
1254 break;
1256 case TIOCSTAT: /* simulate control-T */
1257 crit_enter();
1258 ttyinfo(tp);
1259 crit_exit();
1260 break;
1261 case TIOCSWINSZ: /* set window size */
1262 if (bcmp((caddr_t)&tp->t_winsize, data,
1263 sizeof (struct winsize))) {
1264 tp->t_winsize = *(struct winsize *)data;
1265 pgsignal(tp->t_pgrp, SIGWINCH, 1);
1267 break;
1268 case TIOCSDRAINWAIT:
1269 error = priv_check(td, PRIV_ROOT);
1270 if (error) {
1271 lwkt_reltoken(&p->p_token);
1272 lwkt_reltoken(&tty_token);
1273 return (error);
1275 tp->t_timeout = *(int *)data * hz;
1276 wakeup(TSA_OCOMPLETE(tp));
1277 wakeup(TSA_OLOWAT(tp));
1278 break;
1279 case TIOCGDRAINWAIT:
1280 *(int *)data = tp->t_timeout / hz;
1281 break;
1282 default:
1283 lwkt_reltoken(&p->p_token);
1284 lwkt_reltoken(&tty_token);
1285 #if defined(COMPAT_43)
1286 return (ttcompat(tp, cmd, data, flag));
1287 #else
1288 return (ENOIOCTL);
1289 #endif
1291 lwkt_reltoken(&p->p_token);
1292 lwkt_reltoken(&tty_token);
1293 return (0);
1296 static struct filterops ttyread_filtops =
1297 { FILTEROP_ISFD|FILTEROP_MPSAFE, NULL, filt_ttyrdetach, filt_ttyread };
1298 static struct filterops ttywrite_filtops =
1299 { FILTEROP_ISFD|FILTEROP_MPSAFE, NULL, filt_ttywdetach, filt_ttywrite };
1302 ttykqfilter(struct dev_kqfilter_args *ap)
1304 cdev_t dev = ap->a_head.a_dev;
1305 struct knote *kn = ap->a_kn;
1306 struct tty *tp = dev->si_tty;
1307 struct klist *klist;
1309 ap->a_result = 0;
1311 lwkt_gettoken(&tty_token);
1312 switch (kn->kn_filter) {
1313 case EVFILT_READ:
1314 klist = &tp->t_rkq.ki_note;
1315 kn->kn_fop = &ttyread_filtops;
1316 break;
1317 case EVFILT_WRITE:
1318 klist = &tp->t_wkq.ki_note;
1319 kn->kn_fop = &ttywrite_filtops;
1320 break;
1321 default:
1322 ap->a_result = EOPNOTSUPP;
1323 lwkt_reltoken(&tty_token);
1324 return (0);
1326 lwkt_reltoken(&tty_token);
1327 kn->kn_hook = (caddr_t)dev;
1328 knote_insert(klist, kn);
1330 return (0);
1333 static void
1334 filt_ttyrdetach(struct knote *kn)
1336 struct tty *tp = ((cdev_t)kn->kn_hook)->si_tty;
1338 lwkt_gettoken(&tty_token);
1339 knote_remove(&tp->t_rkq.ki_note, kn);
1340 lwkt_reltoken(&tty_token);
1343 static int
1344 filt_ttyread(struct knote *kn, long hint)
1346 struct tty *tp = ((cdev_t)kn->kn_hook)->si_tty;
1348 lwkt_gettoken(&tty_token);
1349 kn->kn_data = ttnread(tp);
1350 if (ISSET(tp->t_state, TS_ZOMBIE)) {
1351 kn->kn_flags |= (EV_EOF | EV_NODATA);
1352 lwkt_reltoken(&tty_token);
1353 return (1);
1355 lwkt_reltoken(&tty_token);
1356 return (kn->kn_data > 0);
1359 static void
1360 filt_ttywdetach(struct knote *kn)
1362 struct tty *tp = ((cdev_t)kn->kn_hook)->si_tty;
1364 lwkt_gettoken(&tty_token);
1365 knote_remove(&tp->t_wkq.ki_note, kn);
1366 lwkt_reltoken(&tty_token);
1369 static int
1370 filt_ttywrite(struct knote *kn, long hint)
1372 struct tty *tp = ((cdev_t)kn->kn_hook)->si_tty;
1373 int ret;
1375 lwkt_gettoken(&tty_token);
1376 kn->kn_data = tp->t_outq.c_cc;
1377 if (ISSET(tp->t_state, TS_ZOMBIE)) {
1378 lwkt_reltoken(&tty_token);
1379 return (1);
1381 ret = (kn->kn_data <= tp->t_olowat &&
1382 ISSET(tp->t_state, TS_CONNECTED));
1383 lwkt_reltoken(&tty_token);
1384 return ret;
1388 * Must be called while in a critical section.
1389 * NOTE: tty_token must be held.
1391 static int
1392 ttnread(struct tty *tp)
1394 int nread;
1396 ASSERT_LWKT_TOKEN_HELD(&tty_token);
1397 if (ISSET(tp->t_lflag, PENDIN))
1398 ttypend(tp);
1399 nread = tp->t_canq.c_cc;
1400 if (!ISSET(tp->t_lflag, ICANON)) {
1401 nread += tp->t_rawq.c_cc;
1402 if (nread < tp->t_cc[VMIN] && tp->t_cc[VTIME] == 0)
1403 nread = 0;
1405 return (nread);
1409 * Wait for output to drain.
1412 ttywait(struct tty *tp)
1414 int error;
1416 error = 0;
1417 crit_enter();
1418 lwkt_gettoken(&tty_token);
1419 while ((tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)) &&
1420 ISSET(tp->t_state, TS_CONNECTED) && tp->t_oproc) {
1421 (*tp->t_oproc)(tp);
1422 if ((tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)) &&
1423 ISSET(tp->t_state, TS_CONNECTED)) {
1424 SET(tp->t_state, TS_SO_OCOMPLETE);
1425 error = ttysleep(tp, TSA_OCOMPLETE(tp),
1426 PCATCH, "ttywai",
1427 tp->t_timeout);
1428 if (error) {
1429 if (error == EWOULDBLOCK)
1430 error = EIO;
1431 break;
1433 } else
1434 break;
1436 if (!error && (tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)))
1437 error = EIO;
1438 lwkt_reltoken(&tty_token);
1439 crit_exit();
1440 return (error);
1444 * Flush if successfully wait.
1446 static int
1447 ttywflush(struct tty *tp)
1449 int error;
1451 if ((error = ttywait(tp)) == 0)
1452 ttyflush(tp, FREAD);
1453 return (error);
1457 * Flush tty read and/or write queues, notifying anyone waiting.
1459 void
1460 ttyflush(struct tty *tp, int rw)
1462 crit_enter();
1463 lwkt_gettoken(&tty_token);
1464 #if 0
1465 again:
1466 #endif
1467 if (rw & FWRITE) {
1468 FLUSHQ(&tp->t_outq);
1469 CLR(tp->t_state, TS_TTSTOP);
1471 (*tp->t_stop)(tp, rw);
1472 if (rw & FREAD) {
1473 FLUSHQ(&tp->t_canq);
1474 FLUSHQ(&tp->t_rawq);
1475 CLR(tp->t_lflag, PENDIN);
1476 tp->t_rocount = 0;
1477 tp->t_rocol = 0;
1478 CLR(tp->t_state, TS_LOCAL);
1479 ttwakeup(tp);
1480 if (ISSET(tp->t_state, TS_TBLOCK)) {
1481 if (rw & FWRITE)
1482 FLUSHQ(&tp->t_outq);
1483 ttyunblock(tp);
1486 * Don't let leave any state that might clobber the
1487 * next line discipline (although we should do more
1488 * to send the START char). Not clearing the state
1489 * may have caused the "putc to a clist with no
1490 * reserved cblocks" panic/kprintf.
1492 CLR(tp->t_state, TS_TBLOCK);
1494 #if 0 /* forget it, sleeping isn't always safe and we don't know when it is */
1495 if (ISSET(tp->t_iflag, IXOFF)) {
1497 * XXX wait a bit in the hope that the stop
1498 * character (if any) will go out. Waiting
1499 * isn't good since it allows races. This
1500 * will be fixed when the stop character is
1501 * put in a special queue. Don't bother with
1502 * the checks in ttywait() since the timeout
1503 * will save us.
1505 SET(tp->t_state, TS_SO_OCOMPLETE);
1506 ttysleep(tp, TSA_OCOMPLETE(tp), 0,
1507 "ttyfls", hz / 10);
1509 * Don't try sending the stop character again.
1511 CLR(tp->t_state, TS_TBLOCK);
1512 goto again;
1514 #endif
1517 if (rw & FWRITE) {
1518 FLUSHQ(&tp->t_outq);
1519 ttwwakeup(tp);
1521 lwkt_reltoken(&tty_token);
1522 crit_exit();
1526 * Copy in the default termios characters.
1528 void
1529 termioschars(struct termios *t)
1531 lwkt_gettoken(&tty_token);
1532 bcopy(ttydefchars, t->c_cc, sizeof t->c_cc);
1533 lwkt_reltoken(&tty_token);
1537 * Old interface.
1539 void
1540 ttychars(struct tty *tp)
1542 lwkt_gettoken(&tty_token);
1543 termioschars(&tp->t_termios);
1544 lwkt_reltoken(&tty_token);
1548 * Handle input high water. Send stop character for the IXOFF case. Turn
1549 * on our input flow control bit and propagate the changes to the driver.
1550 * XXX the stop character should be put in a special high priority queue.
1552 void
1553 ttyblock(struct tty *tp)
1555 lwkt_gettoken(&tty_token);
1556 SET(tp->t_state, TS_TBLOCK);
1557 if (ISSET(tp->t_iflag, IXOFF) && tp->t_cc[VSTOP] != _POSIX_VDISABLE &&
1558 clist_putc(tp->t_cc[VSTOP], &tp->t_outq) != 0)
1559 CLR(tp->t_state, TS_TBLOCK); /* try again later */
1560 ttstart(tp);
1561 lwkt_reltoken(&tty_token);
1565 * Handle input low water. Send start character for the IXOFF case. Turn
1566 * off our input flow control bit and propagate the changes to the driver.
1567 * XXX the start character should be put in a special high priority queue.
1569 static void
1570 ttyunblock(struct tty *tp)
1572 lwkt_gettoken(&tty_token);
1573 CLR(tp->t_state, TS_TBLOCK);
1574 if (ISSET(tp->t_iflag, IXOFF) && tp->t_cc[VSTART] != _POSIX_VDISABLE &&
1575 clist_putc(tp->t_cc[VSTART], &tp->t_outq) != 0)
1576 SET(tp->t_state, TS_TBLOCK); /* try again later */
1577 ttstart(tp);
1578 lwkt_reltoken(&tty_token);
1581 #ifdef notyet
1582 /* Not used by any current (i386) drivers. */
1584 * Restart after an inter-char delay.
1586 void
1587 ttrstrt(void *tp_arg)
1589 struct tty *tp;
1591 KASSERT(tp_arg != NULL, ("ttrstrt"));
1593 tp = tp_arg;
1594 crit_enter();
1595 lwkt_gettoken(&tty_token);
1596 CLR(tp->t_state, TS_TIMEOUT);
1597 ttstart(tp);
1598 lwkt_reltoken(&tty_token);
1599 crit_exit();
1601 #endif
1604 ttstart(struct tty *tp)
1606 lwkt_gettoken(&tty_token);
1607 if (tp->t_oproc != NULL) /* XXX: Kludge for pty. */
1608 (*tp->t_oproc)(tp);
1609 lwkt_reltoken(&tty_token);
1610 return (0);
1614 * "close" a line discipline
1617 ttylclose(struct tty *tp, int flag)
1619 lwkt_gettoken(&tty_token);
1620 if (flag & FNONBLOCK || ttywflush(tp))
1621 ttyflush(tp, FREAD | FWRITE);
1622 lwkt_reltoken(&tty_token);
1623 return (0);
1626 void
1627 ttyhold(struct tty *tp)
1629 ++tp->t_refs;
1632 void
1633 ttyunhold(struct tty *tp)
1635 if (tp->t_unhold)
1636 tp->t_unhold(tp);
1637 else
1638 --tp->t_refs;
1642 * Handle modem control transition on a tty.
1643 * Flag indicates new state of carrier.
1644 * Returns 0 if the line should be turned off, otherwise 1.
1647 ttymodem(struct tty *tp, int flag)
1649 lwkt_gettoken(&tty_token);
1650 if (ISSET(tp->t_state, TS_CARR_ON) && ISSET(tp->t_cflag, MDMBUF)) {
1652 * MDMBUF: do flow control according to carrier flag
1653 * XXX TS_CAR_OFLOW doesn't do anything yet. TS_TTSTOP
1654 * works if IXON and IXANY are clear.
1656 if (flag) {
1657 CLR(tp->t_state, TS_CAR_OFLOW);
1658 CLR(tp->t_state, TS_TTSTOP);
1659 ttstart(tp);
1660 } else if (!ISSET(tp->t_state, TS_CAR_OFLOW)) {
1661 SET(tp->t_state, TS_CAR_OFLOW);
1662 SET(tp->t_state, TS_TTSTOP);
1663 (*tp->t_stop)(tp, 0);
1665 } else if (flag == 0) {
1667 * Lost carrier.
1669 CLR(tp->t_state, TS_CARR_ON);
1670 if (ISSET(tp->t_state, TS_ISOPEN) &&
1671 !ISSET(tp->t_cflag, CLOCAL)) {
1672 SET(tp->t_state, TS_ZOMBIE);
1673 CLR(tp->t_state, TS_CONNECTED);
1674 if (tp->t_session && tp->t_session->s_leader)
1675 ksignal(tp->t_session->s_leader, SIGHUP);
1676 ttyflush(tp, FREAD | FWRITE);
1677 lwkt_reltoken(&tty_token);
1678 return (0);
1680 } else {
1682 * Carrier now on.
1684 SET(tp->t_state, TS_CARR_ON);
1685 if (!ISSET(tp->t_state, TS_ZOMBIE))
1686 SET(tp->t_state, TS_CONNECTED);
1687 wakeup(TSA_CARR_ON(tp));
1688 ttwakeup(tp);
1689 ttwwakeup(tp);
1691 lwkt_reltoken(&tty_token);
1692 return (1);
1696 * Reinput pending characters after state switch
1697 * call from a critical section.
1699 static void
1700 ttypend(struct tty *tp)
1702 struct clist tq;
1703 int c;
1705 lwkt_gettoken(&tty_token);
1706 CLR(tp->t_lflag, PENDIN);
1707 SET(tp->t_state, TS_TYPEN);
1709 * XXX this assumes too much about clist internals. It may even
1710 * fail if the cblock slush pool is empty. We can't allocate more
1711 * cblocks here because we are called from an interrupt handler
1712 * and clist_alloc_cblocks() can wait.
1714 tq = tp->t_rawq;
1715 bzero(&tp->t_rawq, sizeof tp->t_rawq);
1716 tp->t_rawq.c_cbmax = tq.c_cbmax;
1717 tp->t_rawq.c_cbreserved = tq.c_cbreserved;
1718 while ((c = clist_getc(&tq)) >= 0)
1719 ttyinput(c, tp);
1720 CLR(tp->t_state, TS_TYPEN);
1721 lwkt_reltoken(&tty_token);
1725 * Process a read call on a tty device.
1728 ttread(struct tty *tp, struct uio *uio, int flag)
1730 struct clist *qp;
1731 int c;
1732 tcflag_t lflag;
1733 cc_t *cc = tp->t_cc;
1734 struct proc *pp;
1735 struct lwp *lp;
1736 int first, error = 0;
1737 int has_stime = 0, last_cc = 0;
1738 long slp = 0; /* XXX this should be renamed `timo'. */
1739 struct timeval stime;
1741 lp = curthread->td_lwp;
1742 stime.tv_sec = 0; /* fix compiler warnings */
1743 stime.tv_usec = 0;
1745 lwkt_gettoken(&tty_token);
1746 loop:
1747 crit_enter();
1748 lflag = tp->t_lflag;
1750 * take pending input first
1752 if (ISSET(lflag, PENDIN)) {
1753 ttypend(tp);
1754 splz(); /* reduce latency */
1755 lflag = tp->t_lflag; /* XXX ttypend() clobbers it */
1759 * Hang process if it's in the background.
1761 if ((pp = curproc) != NULL)
1762 lwkt_gettoken(&pp->p_token);
1763 if (pp && isbackground(pp, tp)) {
1764 crit_exit();
1765 if (SIGISMEMBER(pp->p_sigignore, SIGTTIN) ||
1766 SIGISMEMBER(lp->lwp_sigmask, SIGTTIN) ||
1767 (pp->p_flags & P_PPWAIT) || pp->p_pgrp->pg_jobc == 0) {
1768 lwkt_reltoken(&pp->p_token);
1769 lwkt_reltoken(&tty_token);
1770 return (EIO);
1772 pgsignal(pp->p_pgrp, SIGTTIN, 1);
1773 error = ttysleep(tp, &lbolt, PCATCH, "ttybg2", 0);
1774 if (error) {
1775 lwkt_reltoken(&pp->p_token);
1776 lwkt_reltoken(&tty_token);
1777 return (error);
1779 lwkt_reltoken(&pp->p_token);
1780 goto loop;
1782 if (pp)
1783 lwkt_reltoken(&pp->p_token);
1785 if (ISSET(tp->t_state, TS_ZOMBIE)) {
1786 crit_exit();
1787 lwkt_reltoken(&tty_token);
1788 return (0); /* EOF */
1792 * If canonical, use the canonical queue,
1793 * else use the raw queue.
1795 * (should get rid of clists...)
1797 qp = ISSET(lflag, ICANON) ? &tp->t_canq : &tp->t_rawq;
1799 if (flag & IO_NDELAY) {
1800 if (qp->c_cc > 0)
1801 goto read;
1802 if (!ISSET(lflag, ICANON) && cc[VMIN] == 0) {
1803 crit_exit();
1804 lwkt_reltoken(&tty_token);
1805 return (0);
1807 crit_exit();
1808 lwkt_reltoken(&tty_token);
1809 return (EWOULDBLOCK);
1811 if (!ISSET(lflag, ICANON)) {
1812 int m = cc[VMIN];
1813 long t = cc[VTIME];
1814 struct timeval timecopy;
1817 * Check each of the four combinations.
1818 * (m > 0 && t == 0) is the normal read case.
1819 * It should be fairly efficient, so we check that and its
1820 * companion case (m == 0 && t == 0) first.
1821 * For the other two cases, we compute the target sleep time
1822 * into slp.
1824 if (t == 0) {
1825 if (qp->c_cc < m)
1826 goto sleep;
1827 if (qp->c_cc > 0)
1828 goto read;
1830 /* m, t and qp->c_cc are all 0. 0 is enough input. */
1831 crit_exit();
1832 lwkt_reltoken(&tty_token);
1833 return (0);
1835 t *= 100000; /* time in us */
1836 #define diff(t1, t2) (((t1).tv_sec - (t2).tv_sec) * 1000000 + \
1837 ((t1).tv_usec - (t2).tv_usec))
1838 if (m > 0) {
1839 if (qp->c_cc <= 0)
1840 goto sleep;
1841 if (qp->c_cc >= m)
1842 goto read;
1843 getmicrotime(&timecopy);
1844 if (has_stime == 0) {
1845 /* first character, start timer */
1846 has_stime = 1;
1847 stime = timecopy;
1848 slp = t;
1849 } else if (qp->c_cc > last_cc) {
1850 /* got a character, restart timer */
1851 stime = timecopy;
1852 slp = t;
1853 } else {
1854 /* nothing, check expiration */
1855 slp = t - diff(timecopy, stime);
1856 if (slp <= 0)
1857 goto read;
1859 last_cc = qp->c_cc;
1860 } else { /* m == 0 */
1861 if (qp->c_cc > 0)
1862 goto read;
1863 getmicrotime(&timecopy);
1864 if (has_stime == 0) {
1865 has_stime = 1;
1866 stime = timecopy;
1867 slp = t;
1868 } else {
1869 slp = t - diff(timecopy, stime);
1870 if (slp <= 0) {
1871 /* Timed out, but 0 is enough input. */
1872 crit_exit();
1873 lwkt_reltoken(&tty_token);
1874 return (0);
1878 #undef diff
1880 * Rounding down may make us wake up just short
1881 * of the target, so we round up.
1882 * The formula is ceiling(slp * hz/1000000).
1883 * 32-bit arithmetic is enough for hz < 169.
1884 * XXX see tvtohz() for how to avoid overflow if hz
1885 * is large (divide by `tick' and/or arrange to
1886 * use tvtohz() if hz is large).
1888 slp = (long) (((u_long)slp * hz) + 999999) / 1000000;
1889 goto sleep;
1891 if (qp->c_cc <= 0) {
1892 sleep:
1894 * There is no input, or not enough input and we can block.
1896 error = ttysleep(tp, TSA_HUP_OR_INPUT(tp), PCATCH,
1897 ISSET(tp->t_state, TS_CONNECTED) ?
1898 "ttyin" : "ttyhup", (int)slp);
1899 crit_exit();
1900 if (error == EWOULDBLOCK)
1901 error = 0;
1902 else if (error) {
1903 lwkt_reltoken(&tty_token);
1904 return (error);
1907 * XXX what happens if another process eats some input
1908 * while we are asleep (not just here)? It would be
1909 * safest to detect changes and reset our state variables
1910 * (has_stime and last_cc).
1912 slp = 0;
1913 goto loop;
1915 read:
1916 crit_exit();
1918 * Input present, check for input mapping and processing.
1920 first = 1;
1921 if (ISSET(lflag, ICANON | ISIG))
1922 goto slowcase;
1923 for (;;) {
1924 char ibuf[IBUFSIZ];
1925 int icc;
1927 icc = (int)szmin(uio->uio_resid, IBUFSIZ);
1928 icc = q_to_b(qp, ibuf, icc);
1929 if (icc <= 0) {
1930 if (first)
1931 goto loop;
1932 break;
1934 error = uiomove(ibuf, (size_t)icc, uio);
1936 * XXX if there was an error then we should ungetc() the
1937 * unmoved chars and reduce icc here.
1939 if (error)
1940 break;
1941 if (uio->uio_resid == 0)
1942 break;
1943 first = 0;
1945 goto out;
1946 slowcase:
1947 for (;;) {
1948 c = clist_getc(qp);
1949 if (c < 0) {
1950 if (first)
1951 goto loop;
1952 break;
1955 * delayed suspend (^Y)
1957 if (CCEQ(cc[VDSUSP], c) &&
1958 ISSET(lflag, IEXTEN | ISIG) == (IEXTEN | ISIG)) {
1959 pgsignal(tp->t_pgrp, SIGTSTP, 1);
1960 if (first) {
1961 error = ttysleep(tp, &lbolt, PCATCH,
1962 "ttybg3", 0);
1963 if (error)
1964 break;
1965 goto loop;
1967 break;
1970 * Interpret EOF only in canonical mode.
1972 if (CCEQ(cc[VEOF], c) && ISSET(lflag, ICANON))
1973 break;
1975 * Give user character.
1977 error = ureadc(c, uio);
1978 if (error)
1979 /* XXX should ungetc(c, qp). */
1980 break;
1981 if (uio->uio_resid == 0)
1982 break;
1984 * In canonical mode check for a "break character"
1985 * marking the end of a "line of input".
1987 if (ISSET(lflag, ICANON) && TTBREAKC(c, lflag))
1988 break;
1989 first = 0;
1992 out:
1994 * Look to unblock input now that (presumably)
1995 * the input queue has gone down.
1997 crit_enter();
1998 if (ISSET(tp->t_state, TS_TBLOCK) &&
1999 tp->t_rawq.c_cc + tp->t_canq.c_cc <= tp->t_ilowat)
2000 ttyunblock(tp);
2001 crit_exit();
2003 lwkt_reltoken(&tty_token);
2004 return (error);
2008 * Check the output queue on tp for space for a kernel message (from uprintf
2009 * or tprintf). Allow some space over the normal hiwater mark so we don't
2010 * lose messages due to normal flow control, but don't let the tty run amok.
2011 * Sleeps here are not interruptible, but we return prematurely if new signals
2012 * arrive.
2015 ttycheckoutq(struct tty *tp, int wait)
2017 struct lwp *lp = curthread->td_lwp;
2018 int hiwat;
2019 sigset_t oldset, newset;
2021 lwkt_gettoken(&tty_token);
2022 hiwat = tp->t_ohiwat;
2023 SIGEMPTYSET(oldset);
2024 SIGEMPTYSET(newset);
2025 crit_enter();
2026 if (wait)
2027 oldset = lwp_sigpend(lp);
2028 if (tp->t_outq.c_cc > hiwat + OBUFSIZ + 100) {
2029 while (tp->t_outq.c_cc > hiwat) {
2030 ttstart(tp);
2031 if (tp->t_outq.c_cc <= hiwat)
2032 break;
2033 if (wait)
2034 newset = lwp_sigpend(lp);
2035 if (!wait || SIGSETNEQ(oldset, newset)) {
2036 crit_exit();
2037 lwkt_reltoken(&tty_token);
2038 return (0);
2040 SET(tp->t_state, TS_SO_OLOWAT);
2041 tsleep(TSA_OLOWAT(tp), 0, "ttoutq", hz);
2044 crit_exit();
2045 lwkt_reltoken(&tty_token);
2046 return (1);
2050 * Process a write call on a tty device.
2053 ttwrite(struct tty *tp, struct uio *uio, int flag)
2055 char *cp = NULL;
2056 int cc, ce;
2057 struct proc *pp;
2058 struct lwp *lp;
2059 int i, hiwat, error;
2060 size_t cnt;
2062 char obuf[OBUFSIZ];
2064 lwkt_gettoken(&tty_token);
2065 lp = curthread->td_lwp;
2066 hiwat = tp->t_ohiwat;
2067 cnt = uio->uio_resid;
2068 error = 0;
2069 cc = 0;
2070 loop:
2071 crit_enter();
2072 if (ISSET(tp->t_state, TS_ZOMBIE)) {
2073 crit_exit();
2074 if (uio->uio_resid == cnt)
2075 error = EIO;
2076 goto out;
2078 if (!ISSET(tp->t_state, TS_CONNECTED)) {
2079 if (flag & IO_NDELAY) {
2080 crit_exit();
2081 error = EWOULDBLOCK;
2082 goto out;
2084 error = ttysleep(tp, TSA_CARR_ON(tp), PCATCH, "ttydcd", 0);
2085 crit_exit();
2086 if (error)
2087 goto out;
2088 goto loop;
2090 crit_exit();
2093 * Hang the process if it's in the background.
2095 if ((pp = curproc) != NULL)
2096 lwkt_gettoken(&pp->p_token);
2097 if (pp && isbackground(pp, tp) &&
2098 ISSET(tp->t_lflag, TOSTOP) && !(pp->p_flags & P_PPWAIT) &&
2099 !SIGISMEMBER(pp->p_sigignore, SIGTTOU) &&
2100 !SIGISMEMBER(lp->lwp_sigmask, SIGTTOU)) {
2101 if (pp->p_pgrp->pg_jobc == 0) {
2102 error = EIO;
2103 lwkt_reltoken(&pp->p_token);
2104 goto out;
2106 pgsignal(pp->p_pgrp, SIGTTOU, 1);
2107 lwkt_reltoken(&pp->p_token);
2108 error = ttysleep(tp, &lbolt, PCATCH, "ttybg4", 0);
2109 if (error)
2110 goto out;
2111 goto loop;
2113 if (pp)
2114 lwkt_reltoken(&pp->p_token);
2116 * Process the user's data in at most OBUFSIZ chunks. Perform any
2117 * output translation. Keep track of high water mark, sleep on
2118 * overflow awaiting device aid in acquiring new space.
2120 while (uio->uio_resid > 0 || cc > 0) {
2121 if (ISSET(tp->t_lflag, FLUSHO)) {
2122 uio->uio_resid = 0;
2123 lwkt_reltoken(&tty_token);
2124 return (0);
2126 if (tp->t_outq.c_cc > hiwat)
2127 goto ovhiwat;
2129 * Grab a hunk of data from the user, unless we have some
2130 * leftover from last time.
2132 if (cc == 0) {
2133 cc = szmin(uio->uio_resid, OBUFSIZ);
2134 cp = obuf;
2135 error = uiomove(cp, (size_t)cc, uio);
2136 if (error) {
2137 cc = 0;
2138 break;
2142 * If nothing fancy need be done, grab those characters we
2143 * can handle without any of ttyoutput's processing and
2144 * just transfer them to the output q. For those chars
2145 * which require special processing (as indicated by the
2146 * bits in char_type), call ttyoutput. After processing
2147 * a hunk of data, look for FLUSHO so ^O's will take effect
2148 * immediately.
2150 while (cc > 0) {
2151 if (!ISSET(tp->t_oflag, OPOST))
2152 ce = cc;
2153 else {
2154 ce = cc - scanc((u_int)cc, (u_char *)cp,
2155 char_type, CCLASSMASK);
2157 * If ce is zero, then we're processing
2158 * a special character through ttyoutput.
2160 if (ce == 0) {
2161 tp->t_rocount = 0;
2162 if (ttyoutput(*cp, tp) >= 0) {
2163 /* No Clists, wait a bit. */
2164 ttstart(tp);
2165 if (flag & IO_NDELAY) {
2166 error = EWOULDBLOCK;
2167 goto out;
2169 error = ttysleep(tp, &lbolt,
2170 PCATCH,
2171 "ttybf1", 0);
2172 if (error)
2173 goto out;
2174 goto loop;
2176 cp++;
2177 cc--;
2178 if (ISSET(tp->t_lflag, FLUSHO) ||
2179 tp->t_outq.c_cc > hiwat)
2180 goto ovhiwat;
2181 continue;
2185 * A bunch of normal characters have been found.
2186 * Transfer them en masse to the output queue and
2187 * continue processing at the top of the loop.
2188 * If there are any further characters in this
2189 * <= OBUFSIZ chunk, the first should be a character
2190 * requiring special handling by ttyoutput.
2192 tp->t_rocount = 0;
2193 i = b_to_q(cp, ce, &tp->t_outq);
2194 ce -= i;
2195 tp->t_column += ce;
2196 cp += ce, cc -= ce, tk_nout += ce;
2197 tp->t_outcc += ce;
2198 if (i > 0) {
2199 /* No Clists, wait a bit. */
2200 ttstart(tp);
2201 if (flag & IO_NDELAY) {
2202 error = EWOULDBLOCK;
2203 goto out;
2205 error = ttysleep(tp, &lbolt, PCATCH,
2206 "ttybf2", 0);
2207 if (error)
2208 goto out;
2209 goto loop;
2211 if (ISSET(tp->t_lflag, FLUSHO) ||
2212 tp->t_outq.c_cc > hiwat)
2213 break;
2215 ttstart(tp);
2217 out:
2219 * If cc is nonzero, we leave the uio structure inconsistent, as the
2220 * offset and iov pointers have moved forward, but it doesn't matter
2221 * (the call will either return short or restart with a new uio).
2223 uio->uio_resid += cc;
2224 lwkt_reltoken(&tty_token);
2225 return (error);
2227 ovhiwat:
2228 ttstart(tp);
2229 crit_enter();
2231 * This can only occur if FLUSHO is set in t_lflag,
2232 * or if ttstart/oproc is synchronous (or very fast).
2234 if (tp->t_outq.c_cc <= hiwat) {
2235 crit_exit();
2236 goto loop;
2238 if (flag & IO_NDELAY) {
2239 crit_exit();
2240 uio->uio_resid += cc;
2241 lwkt_reltoken(&tty_token);
2242 return (uio->uio_resid == cnt ? EWOULDBLOCK : 0);
2244 SET(tp->t_state, TS_SO_OLOWAT);
2245 error = ttysleep(tp, TSA_OLOWAT(tp), PCATCH, "ttywri", tp->t_timeout);
2246 crit_exit();
2247 if (error == EWOULDBLOCK)
2248 error = EIO;
2249 if (error)
2250 goto out;
2251 goto loop;
2255 * Rubout one character from the rawq of tp
2256 * as cleanly as possible.
2257 * NOTE: Must be called with tty_token held
2259 static void
2260 ttyrub(int c, struct tty *tp)
2262 char *cp;
2263 int savecol;
2264 int tabc;
2266 ASSERT_LWKT_TOKEN_HELD(&tty_token);
2267 if (!ISSET(tp->t_lflag, ECHO) || ISSET(tp->t_lflag, EXTPROC))
2268 return;
2269 CLR(tp->t_lflag, FLUSHO);
2270 if (ISSET(tp->t_lflag, ECHOE)) {
2271 if (tp->t_rocount == 0) {
2273 * Screwed by ttwrite; retype
2275 ttyretype(tp);
2276 return;
2278 if (c == ('\t' | TTY_QUOTE) || c == ('\n' | TTY_QUOTE))
2279 ttyrubo(tp, 2);
2280 else {
2281 CLR(c, ~TTY_CHARMASK);
2282 switch (CCLASS(c)) {
2283 case ORDINARY:
2284 ttyrubo(tp, 1);
2285 break;
2286 case BACKSPACE:
2287 case CONTROL:
2288 case NEWLINE:
2289 case RETURN:
2290 case VTAB:
2291 if (ISSET(tp->t_lflag, ECHOCTL))
2292 ttyrubo(tp, 2);
2293 break;
2294 case TAB:
2295 if (tp->t_rocount < tp->t_rawq.c_cc) {
2296 ttyretype(tp);
2297 return;
2299 crit_enter();
2300 savecol = tp->t_column;
2301 SET(tp->t_state, TS_CNTTB);
2302 SET(tp->t_lflag, FLUSHO);
2303 tp->t_column = tp->t_rocol;
2304 cp = tp->t_rawq.c_cf;
2305 if (cp)
2306 tabc = *cp; /* XXX FIX NEXTC */
2307 for (; cp; cp = nextc(&tp->t_rawq, cp, &tabc))
2308 ttyecho(tabc, tp);
2309 CLR(tp->t_lflag, FLUSHO);
2310 CLR(tp->t_state, TS_CNTTB);
2311 crit_exit();
2313 /* savecol will now be length of the tab. */
2314 savecol -= tp->t_column;
2315 tp->t_column += savecol;
2316 if (savecol > 8)
2317 savecol = 8; /* overflow screw */
2318 while (--savecol >= 0)
2319 (void)ttyoutput('\b', tp);
2320 break;
2321 default: /* XXX */
2322 #define PANICSTR "ttyrub: would panic c = %d, val = %d\n"
2323 (void)kprintf(PANICSTR, c, CCLASS(c));
2324 #ifdef notdef
2325 panic(PANICSTR, c, CCLASS(c));
2326 #endif
2329 } else if (ISSET(tp->t_lflag, ECHOPRT)) {
2330 if (!ISSET(tp->t_state, TS_ERASE)) {
2331 SET(tp->t_state, TS_ERASE);
2332 (void)ttyoutput('\\', tp);
2334 ttyecho(c, tp);
2335 } else {
2336 ttyecho(tp->t_cc[VERASE], tp);
2338 * This code may be executed not only when an ERASE key
2339 * is pressed, but also when ^U (KILL) or ^W (WERASE) are.
2340 * So, I didn't think it was worthwhile to pass the extra
2341 * information (which would need an extra parameter,
2342 * changing every call) needed to distinguish the ERASE2
2343 * case from the ERASE.
2346 --tp->t_rocount;
2350 * Back over cnt characters, erasing them.
2351 * NOTE: Must be called with tty_token held
2353 static void
2354 ttyrubo(struct tty *tp, int cnt)
2356 ASSERT_LWKT_TOKEN_HELD(&tty_token);
2357 while (cnt-- > 0) {
2358 (void)ttyoutput('\b', tp);
2359 (void)ttyoutput(' ', tp);
2360 (void)ttyoutput('\b', tp);
2365 * ttyretype --
2366 * Reprint the rawq line. Note, it is assumed that c_cc has already
2367 * been checked.
2368 * NOTE: Must be called with tty_token held
2370 static void
2371 ttyretype(struct tty *tp)
2373 char *cp;
2374 int c;
2376 ASSERT_LWKT_TOKEN_HELD(&tty_token);
2377 /* Echo the reprint character. */
2378 if (tp->t_cc[VREPRINT] != _POSIX_VDISABLE)
2379 ttyecho(tp->t_cc[VREPRINT], tp);
2381 (void)ttyoutput('\n', tp);
2384 * XXX
2385 * FIX: NEXTC IS BROKEN - DOESN'T CHECK QUOTE
2386 * BIT OF FIRST CHAR.
2388 crit_enter();
2389 for (cp = tp->t_canq.c_cf, c = (cp != NULL ? *cp : 0);
2390 cp != NULL; cp = nextc(&tp->t_canq, cp, &c))
2391 ttyecho(c, tp);
2392 for (cp = tp->t_rawq.c_cf, c = (cp != NULL ? *cp : 0);
2393 cp != NULL; cp = nextc(&tp->t_rawq, cp, &c))
2394 ttyecho(c, tp);
2395 CLR(tp->t_state, TS_ERASE);
2396 crit_exit();
2398 tp->t_rocount = tp->t_rawq.c_cc;
2399 tp->t_rocol = 0;
2403 * Echo a typed character to the terminal.
2404 * NOTE: Must be called with tty_token held
2406 static void
2407 ttyecho(int c, struct tty *tp)
2409 ASSERT_LWKT_TOKEN_HELD(&tty_token);
2411 if (!ISSET(tp->t_state, TS_CNTTB))
2412 CLR(tp->t_lflag, FLUSHO);
2413 if ((!ISSET(tp->t_lflag, ECHO) &&
2414 (c != '\n' || !ISSET(tp->t_lflag, ECHONL))) ||
2415 ISSET(tp->t_lflag, EXTPROC))
2416 return;
2417 if (ISSET(tp->t_lflag, ECHOCTL) &&
2418 ((ISSET(c, TTY_CHARMASK) <= 037 && c != '\t' && c != '\n') ||
2419 ISSET(c, TTY_CHARMASK) == 0177)) {
2420 (void)ttyoutput('^', tp);
2421 CLR(c, ~TTY_CHARMASK);
2422 if (c == 0177)
2423 c = '?';
2424 else
2425 c += 'A' - 1;
2427 (void)ttyoutput(c, tp);
2431 * Wake up any readers on a tty.
2433 void
2434 ttwakeup(struct tty *tp)
2436 lwkt_gettoken(&tty_token);
2437 if (ISSET(tp->t_state, TS_ASYNC) && tp->t_sigio != NULL)
2438 pgsigio(tp->t_sigio, SIGIO, (tp->t_session != NULL));
2439 wakeup(TSA_HUP_OR_INPUT(tp));
2440 KNOTE(&tp->t_rkq.ki_note, 0);
2441 lwkt_reltoken(&tty_token);
2445 * Wake up any writers on a tty.
2447 void
2448 ttwwakeup(struct tty *tp)
2450 lwkt_gettoken(&tty_token);
2451 if (ISSET(tp->t_state, TS_ASYNC) && tp->t_sigio != NULL)
2452 pgsigio(tp->t_sigio, SIGIO, (tp->t_session != NULL));
2453 if (ISSET(tp->t_state, TS_BUSY | TS_SO_OCOMPLETE) ==
2454 TS_SO_OCOMPLETE && tp->t_outq.c_cc == 0) {
2455 CLR(tp->t_state, TS_SO_OCOMPLETE);
2456 wakeup(TSA_OCOMPLETE(tp));
2458 if (ISSET(tp->t_state, TS_SO_OLOWAT) &&
2459 tp->t_outq.c_cc <= tp->t_olowat) {
2460 CLR(tp->t_state, TS_SO_OLOWAT);
2461 wakeup(TSA_OLOWAT(tp));
2463 KNOTE(&tp->t_wkq.ki_note, 0);
2464 lwkt_reltoken(&tty_token);
2468 * Look up a code for a specified speed in a conversion table;
2469 * used by drivers to map software speed values to hardware parameters.
2470 * No requirements
2473 ttspeedtab(int speed, struct speedtab *table)
2476 for ( ; table->sp_speed != -1; table++)
2477 if (table->sp_speed == speed)
2478 return (table->sp_code);
2479 return (-1);
2483 * Set input and output watermarks and buffer sizes. For input, the
2484 * high watermark is about one second's worth of input above empty, the
2485 * low watermark is slightly below high water, and the buffer size is a
2486 * driver-dependent amount above high water. For output, the watermarks
2487 * are near the ends of the buffer, with about 1 second's worth of input
2488 * between them. All this only applies to the standard line discipline.
2490 void
2491 ttsetwater(struct tty *tp)
2493 int cps, ttmaxhiwat, x;
2495 lwkt_gettoken(&tty_token);
2496 /* Input. */
2497 clist_alloc_cblocks(&tp->t_canq, TTYHOG, 512);
2498 switch (tp->t_ispeedwat) {
2499 case (speed_t)-1:
2500 cps = tp->t_ispeed / 10;
2501 break;
2502 case 0:
2504 * This case is for old drivers that don't know about
2505 * t_ispeedwat. Arrange for them to get the old buffer
2506 * sizes and watermarks.
2508 cps = TTYHOG - 2 * 256;
2509 tp->t_ififosize = 2 * 2048;
2510 break;
2511 default:
2512 cps = tp->t_ispeedwat / 10;
2513 break;
2515 tp->t_ihiwat = cps;
2516 tp->t_ilowat = 7 * cps / 8;
2517 x = cps + tp->t_ififosize;
2518 clist_alloc_cblocks(&tp->t_rawq, x, x);
2520 /* Output. */
2521 switch (tp->t_ospeedwat) {
2522 case (speed_t)-1:
2523 cps = tp->t_ospeed / 10;
2524 ttmaxhiwat = 2 * TTMAXHIWAT;
2525 break;
2526 case 0:
2527 cps = tp->t_ospeed / 10;
2528 ttmaxhiwat = TTMAXHIWAT;
2529 break;
2530 default:
2531 cps = tp->t_ospeedwat / 10;
2532 ttmaxhiwat = 8 * TTMAXHIWAT;
2533 break;
2535 #define CLAMP(x, h, l) ((x) > h ? h : ((x) < l) ? l : (x))
2536 tp->t_olowat = x = CLAMP(cps / 2, TTMAXLOWAT, TTMINLOWAT);
2537 x += cps;
2538 x = CLAMP(x, ttmaxhiwat, TTMINHIWAT); /* XXX clamps are too magic */
2539 tp->t_ohiwat = roundup(x, CBSIZE); /* XXX for compat */
2540 x = imax(tp->t_ohiwat, TTMAXHIWAT); /* XXX for compat/safety */
2541 x += OBUFSIZ + 100;
2542 clist_alloc_cblocks(&tp->t_outq, x, x);
2543 #undef CLAMP
2544 lwkt_reltoken(&tty_token);
2548 * Report on state of foreground process group.
2550 void
2551 ttyinfo(struct tty *tp)
2553 struct pgrp *pgrp;
2554 struct proc *p, *pick;
2555 struct lwp *lp;
2556 struct rusage ru;
2557 char buf[64];
2558 const char *str;
2559 struct vmspace *vm;
2560 long vmsz;
2561 int pctcpu;
2562 int tmp;
2564 if (ttycheckoutq(tp,0) == 0)
2565 return;
2567 lwkt_gettoken(&tty_token);
2570 * We always print the load average, then figure out what else to
2571 * print based on the state of the current process group.
2573 tmp = (averunnable.ldavg[0] * 100 + FSCALE / 2) >> FSHIFT;
2574 ttyprintf(tp, "load: %d.%02d ", tmp / 100, tmp % 100);
2576 if (tp->t_session == NULL) {
2577 ttyprintf(tp, "not a controlling terminal\n");
2578 goto done2;
2580 if ((pgrp = tp->t_pgrp) == NULL) {
2581 ttyprintf(tp, "no foreground process group\n");
2582 goto done2;
2586 * Pick an interesting process. Note that certain elements,
2587 * in particular the wmesg, require a critical section for
2588 * safe access (YYY and we are still not MP safe).
2590 * NOTE: lwp_wmesg is lwp_thread->td_wmesg.
2592 pgref(pgrp);
2593 lwkt_gettoken(&pgrp->pg_token);
2595 pick = NULL;
2596 for (p = LIST_FIRST(&pgrp->pg_members);
2597 p != NULL;
2598 p = LIST_NEXT(p, p_pglist)) {
2599 PHOLD(p);
2600 if (proc_compare(pick, p)) {
2601 if (pick)
2602 PRELE(pick);
2603 pick = p;
2604 } else {
2605 PRELE(p);
2608 if (pick == NULL) {
2609 ttyprintf(tp, "empty foreground process group\n");
2610 goto done1;
2614 * Pick an interesting LWP (XXX)
2616 * pick is held.
2618 lp = FIRST_LWP_IN_PROC(pick);
2619 if (lp == NULL) {
2620 PRELE(pick);
2621 ttyprintf(tp, "foreground process without lwp\n");
2622 goto done1;
2626 * Figure out what wait/process-state message, and command
2627 * buffer to present
2630 * XXX lwp This is a horrible mixture. We need to rework this
2631 * as soon as lwps have their own runnable status.
2633 LWPHOLD(lp);
2634 if (pick->p_flags & P_WEXIT)
2635 str = "exiting";
2636 else if (lp->lwp_stat == LSRUN)
2637 str = "running";
2638 else if (pick->p_stat == SIDL)
2639 str = "spawning";
2640 else if (lp->lwp_wmesg) /* lwp_thread must not be NULL */
2641 str = lp->lwp_wmesg;
2642 else
2643 str = "iowait";
2645 ksnprintf(buf, sizeof(buf), "cmd: %s %d [%s]",
2646 pick->p_comm, pick->p_pid, str);
2649 * Calculate cpu usage, percent cpu, and cmsz. Note that
2650 * 'pick' becomes invalid the moment we exit the critical
2651 * section.
2653 if (lp->lwp_thread && (pick->p_flags & P_SWAPPEDOUT) == 0)
2654 calcru_proc(pick, &ru);
2656 pctcpu = (lp->lwp_pctcpu * 10000 + FSCALE / 2) >> FSHIFT;
2658 LWPRELE(lp);
2661 * NOTE: vmspace should be protected from destruction by the
2662 * combination of pg_token and the fact that we are not
2663 * flagged as a zombie.
2665 if (pick->p_stat == SIDL || pick->p_stat == SZOMB) {
2666 vmsz = 0;
2667 } else if ((vm = pick->p_vmspace) == NULL) {
2668 vmsz = 0;
2669 } else {
2670 vmspace_hold(vm);
2671 vmsz = pgtok(vmspace_resident_count(vm));
2672 vmspace_drop(vm);
2674 PRELE(pick);
2677 * Dump the output
2679 ttyprintf(tp, " %s ",
2680 buf);
2681 ttyprintf(tp, "%ld.%02ldu ",
2682 ru.ru_utime.tv_sec, ru.ru_utime.tv_usec / 10000);
2683 ttyprintf(tp, "%ld.%02lds ",
2684 ru.ru_stime.tv_sec, ru.ru_stime.tv_usec / 10000);
2685 ttyprintf(tp, "%d%% %ldk\n",
2686 pctcpu / 100, vmsz);
2688 done1:
2689 lwkt_reltoken(&pgrp->pg_token);
2690 pgrel(pgrp);
2691 done2:
2692 tp->t_rocount = 0; /* so pending input will be retyped if BS */
2693 lwkt_reltoken(&tty_token);
2697 * Returns 1 if p2 is "better" than p1
2699 * The algorithm for picking the "interesting" process is thus:
2701 * 1) Only foreground processes are eligible - implied.
2702 * 2) Runnable processes are favored over anything else. The runner
2703 * with the highest cpu utilization is picked (p_cpticks). Ties are
2704 * broken by picking the highest pid.
2705 * 3) The sleeper with the shortest sleep time is next. With ties,
2706 * we pick out just "short-term" sleepers (LWP_SINTR == 0).
2707 * 4) Further ties are broken by picking the highest pid.
2709 * NOTE: must be called with p1 and p2 held.
2711 #define ISRUN(lp) ((lp)->lwp_stat == LSRUN)
2712 #define TESTAB(a, b) ((a)<<1 | (b))
2713 #define ONLYA 2
2714 #define ONLYB 1
2715 #define BOTH 3
2717 static int
2718 proc_compare(struct proc *p1, struct proc *p2)
2720 struct lwp *lp1, *lp2;
2721 int res;
2723 if (p1 == NULL)
2724 return (1);
2725 if (lwkt_trytoken(&p1->p_token) == 0)
2726 return (1);
2727 if (lwkt_trytoken(&p2->p_token) == 0) {
2728 lwkt_reltoken(&p1->p_token);
2729 return (0);
2733 * weed out zombies
2735 switch (TESTAB(p1->p_stat == SZOMB, p2->p_stat == SZOMB)) {
2736 case ONLYA:
2737 res = 1;
2738 goto done;
2739 case ONLYB:
2740 res = 0;
2741 goto done;
2742 case BOTH:
2743 res = (p2->p_pid > p1->p_pid); /* tie - return highest pid */
2744 goto done;
2745 default:
2746 break;
2749 /* XXX choose the best lwp? */
2750 lp1 = FIRST_LWP_IN_PROC(p1);
2751 lp2 = FIRST_LWP_IN_PROC(p2);
2754 * Favor one with LWPs verses one that has none (is exiting).
2756 if (lp1 == NULL) {
2757 res = 1;
2758 goto done;
2760 if (lp2 == NULL) {
2761 res = 0;
2762 goto done;
2766 * see if at least one of them is runnable
2768 switch (TESTAB(ISRUN(lp1), ISRUN(lp2))) {
2769 case ONLYA:
2770 res = 0;
2771 goto done;
2772 case ONLYB:
2773 res = 1;
2774 goto done;
2775 case BOTH:
2777 * tie - favor one with highest recent cpu utilization
2779 if (lp2->lwp_cpticks > lp1->lwp_cpticks)
2780 res = 1;
2781 else if (lp1->lwp_cpticks > lp2->lwp_cpticks)
2782 res = 0;
2783 else
2784 res = (p2->p_pid > p1->p_pid); /* tie - ret highest */
2785 goto done;
2786 default:
2787 break;
2791 * Pick the one with the smallest sleep time
2793 if (lp2->lwp_slptime > lp1->lwp_slptime) {
2794 res = 0;
2795 goto done;
2797 if (lp1->lwp_slptime > lp2->lwp_slptime) {
2798 res = 1;
2799 goto done;
2803 * Favor one sleeping in a non-interruptible sleep
2805 if ((lp1->lwp_flags & LWP_SINTR) && (lp2->lwp_flags & LWP_SINTR) == 0)
2806 res = 1;
2807 else
2808 if ((lp2->lwp_flags & LWP_SINTR) && (lp1->lwp_flags & LWP_SINTR) == 0)
2809 res = 0;
2810 else
2811 res = (p2->p_pid > p1->p_pid); /* tie - return highest pid */
2812 /* fall through */
2814 done:
2815 lwkt_reltoken(&p2->p_token);
2816 lwkt_reltoken(&p1->p_token);
2817 return (res);
2821 * Output char to tty; console putchar style.
2824 tputchar(int c, struct tty *tp)
2826 crit_enter();
2827 lwkt_gettoken(&tty_token);
2828 if (!ISSET(tp->t_state, TS_CONNECTED)) {
2829 lwkt_reltoken(&tty_token);
2830 crit_exit();
2831 return (-1);
2833 if (c == '\n')
2834 (void)ttyoutput('\r', tp);
2835 (void)ttyoutput(c, tp);
2836 ttstart(tp);
2837 lwkt_reltoken(&tty_token);
2838 crit_exit();
2839 return (0);
2843 * Sleep on chan, returning ERESTART if tty changed while we napped and
2844 * returning any errors (e.g. EINTR/EWOULDBLOCK) reported by tsleep. If
2845 * the tty is revoked, restarting a pending call will redo validation done
2846 * at the start of the call.
2849 ttysleep(struct tty *tp, void *chan, int slpflags, char *wmesg, int timo)
2851 int error;
2852 int gen;
2854 gen = tp->t_gen;
2855 error = tsleep(chan, slpflags, wmesg, timo);
2856 if (error)
2857 return (error);
2858 return (tp->t_gen == gen ? 0 : ERESTART);
2862 * Revoke a tty.
2864 * We bump the gen to force any ttysleep()'s to return with ERESTART
2865 * and flush the tty. The related fp's should already have been
2866 * replaced so the tty will close when the last references on the
2867 * original fp's go away.
2870 ttyrevoke(struct dev_revoke_args *ap)
2872 struct tty *tp;
2874 lwkt_gettoken(&tty_token);
2875 tp = ap->a_head.a_dev->si_tty;
2876 tp->t_gen++;
2877 ttyflush(tp, FREAD | FWRITE);
2878 wakeup(TSA_CARR_ON(tp));
2879 ttwakeup(tp);
2880 ttwwakeup(tp);
2881 lwkt_reltoken(&tty_token);
2882 return (0);
2886 * Allocate a tty struct. Clists in the struct will be allocated by
2887 * ttyopen().
2889 struct tty *
2890 ttymalloc(struct tty *tp)
2893 if (tp) {
2894 return(tp);
2896 tp = kmalloc(sizeof *tp, M_TTYS, M_WAITOK|M_ZERO);
2897 ttyregister(tp);
2898 return (tp);
2901 void
2902 ttyunregister(struct tty *tp)
2904 lwkt_gettoken(&tty_token);
2905 KKASSERT(ISSET(tp->t_state, TS_REGISTERED));
2906 CLR(tp->t_state, TS_REGISTERED);
2907 TAILQ_REMOVE(&tty_list, tp, t_list);
2908 lwkt_reltoken(&tty_token);
2911 void
2912 ttyregister(struct tty *tp)
2914 lwkt_gettoken(&tty_token);
2915 KKASSERT(!ISSET(tp->t_state, TS_REGISTERED));
2916 SET(tp->t_state, TS_REGISTERED);
2917 TAILQ_INSERT_HEAD(&tty_list, tp, t_list);
2918 lwkt_reltoken(&tty_token);
2921 static int
2922 sysctl_kern_ttys(SYSCTL_HANDLER_ARGS)
2924 int error;
2925 struct tty *tp;
2926 struct tty t;
2927 struct tty marker;
2929 bzero(&marker, sizeof(marker));
2930 marker.t_state = TS_MARKER;
2931 error = 0;
2933 lwkt_gettoken(&tty_token);
2935 TAILQ_INSERT_HEAD(&tty_list, &marker, t_list);
2936 while ((tp = TAILQ_NEXT(&marker, t_list)) != NULL) {
2937 TAILQ_REMOVE(&tty_list, &marker, t_list);
2938 TAILQ_INSERT_AFTER(&tty_list, tp, &marker, t_list);
2939 if (tp->t_state & TS_MARKER)
2940 continue;
2941 t = *tp;
2942 if (t.t_dev)
2943 t.t_dev = (cdev_t)(uintptr_t)dev2udev(t.t_dev);
2944 error = SYSCTL_OUT(req, (caddr_t)&t, sizeof(t));
2945 if (error)
2946 break;
2948 TAILQ_REMOVE(&tty_list, &marker, t_list);
2949 lwkt_reltoken(&tty_token);
2950 return (error);
2953 SYSCTL_PROC(_kern, OID_AUTO, ttys, CTLTYPE_OPAQUE|CTLFLAG_RD,
2954 0, 0, sysctl_kern_ttys, "S,tty", "All struct ttys");
2956 void
2957 nottystop(struct tty *tp, int rw)
2959 return;
2963 ttyread(struct dev_read_args *ap)
2965 struct tty *tp;
2966 int ret;
2968 tp = ap->a_head.a_dev->si_tty;
2969 if (tp == NULL)
2970 return (ENODEV);
2971 lwkt_gettoken(&tty_token);
2972 ret = ((*linesw[tp->t_line].l_read)(tp, ap->a_uio, ap->a_ioflag));
2973 lwkt_reltoken(&tty_token);
2975 return ret;
2979 ttywrite(struct dev_write_args *ap)
2981 struct tty *tp;
2982 int ret;
2984 tp = ap->a_head.a_dev->si_tty;
2985 if (tp == NULL)
2986 return (ENODEV);
2987 lwkt_gettoken(&tty_token);
2988 ret = ((*linesw[tp->t_line].l_write)(tp, ap->a_uio, ap->a_ioflag));
2989 lwkt_reltoken(&tty_token);
2991 return ret;