wg.conf.5: Fix a typo (in-inline comments are *not* allowed)
[dragonfly.git] / sys / kern / tty.c
blobbc4aefb2de47fd47dbb02348e8c1fce6758c1390
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/uio.h>
79 #include <sys/filio.h>
80 #include <sys/malloc.h>
81 #include <sys/proc.h>
82 #include <sys/caps.h>
83 #include <sys/tty.h>
84 #define TTYDEFCHARS
85 #include <sys/ttydefaults.h> /* for ttydefchars, CEOT */
86 #undef TTYDEFCHARS
87 #include <sys/fcntl.h>
88 #include <sys/conf.h>
89 #include <sys/dkstat.h>
90 #include <sys/kernel.h>
91 #include <sys/vnode.h>
92 #include <sys/signalvar.h>
93 #include <sys/signal2.h>
94 #include <sys/resourcevar.h>
95 #include <sys/filedesc.h>
96 #include <sys/sysctl.h>
97 #include <sys/thread2.h>
99 #include <vm/vm.h>
100 #include <sys/lock.h>
101 #include <vm/pmap.h>
102 #include <vm/vm_map.h>
103 #include <vm/vm_extern.h>
105 MALLOC_DEFINE(M_TTYS, "ttys", "tty data structures");
107 static int proc_compare (struct proc *p1, struct proc *p2);
108 static int ttnread (struct tty *tp);
109 static void ttyecho (int c, struct tty *tp);
110 static int ttyoutput (int c, struct tty *tp);
111 static void ttypend (struct tty *tp);
112 static void ttyretype (struct tty *tp);
113 static void ttyrub (int c, struct tty *tp);
114 static void ttyrubo (struct tty *tp, int cnt);
115 static void ttyunblock (struct tty *tp);
116 static int ttywflush (struct tty *tp);
117 static int filt_ttyread (struct knote *kn, long hint);
118 static void filt_ttyrdetach (struct knote *kn);
119 static int filt_ttywrite (struct knote *kn, long hint);
120 static void filt_ttywdetach (struct knote *kn);
123 * Table with character classes and parity. The 8th bit indicates parity,
124 * the 7th bit indicates the character is an alphameric or underscore (for
125 * ALTWERASE), and the low 6 bits indicate delay type. If the low 6 bits
126 * are 0 then the character needs no special processing on output; classes
127 * other than 0 might be translated or (not currently) require delays.
129 #define E 0x00 /* Even parity. */
130 #define O 0x80 /* Odd parity. */
131 #define PARITY(c) (char_type[c] & O)
133 #define ALPHA 0x40 /* Alpha or underscore. */
134 #define ISALPHA(c) (char_type[(c) & TTY_CHARMASK] & ALPHA)
136 #define CCLASSMASK 0x3f
137 #define CCLASS(c) (char_type[c] & CCLASSMASK)
139 #define BS BACKSPACE
140 #define CC CONTROL
141 #define CR RETURN
142 #define NA ORDINARY | ALPHA
143 #define NL NEWLINE
144 #define NO ORDINARY
145 #define TB TAB
146 #define VT VTAB
148 static u_char const char_type[] = {
149 E|CC, O|CC, O|CC, E|CC, O|CC, E|CC, E|CC, O|CC, /* nul - bel */
150 O|BS, E|TB, E|NL, O|CC, E|VT, O|CR, O|CC, E|CC, /* bs - si */
151 O|CC, E|CC, E|CC, O|CC, E|CC, O|CC, O|CC, E|CC, /* dle - etb */
152 E|CC, O|CC, O|CC, E|CC, O|CC, E|CC, E|CC, O|CC, /* can - us */
153 O|NO, E|NO, E|NO, O|NO, E|NO, O|NO, O|NO, E|NO, /* sp - ' */
154 E|NO, O|NO, O|NO, E|NO, O|NO, E|NO, E|NO, O|NO, /* ( - / */
155 E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* 0 - 7 */
156 O|NA, E|NA, E|NO, O|NO, E|NO, O|NO, O|NO, E|NO, /* 8 - ? */
157 O|NO, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA, /* @ - G */
158 E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* H - O */
159 E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* P - W */
160 O|NA, E|NA, E|NA, O|NO, E|NO, O|NO, O|NO, O|NA, /* X - _ */
161 E|NO, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* ` - g */
162 O|NA, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA, /* h - o */
163 O|NA, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA, /* p - w */
164 E|NA, O|NA, O|NA, E|NO, O|NO, E|NO, E|NO, O|CC, /* x - del */
166 * Meta chars; should be settable per character set;
167 * for now, treat them all as normal characters.
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,
184 NA, NA, NA, NA, NA, NA, NA, NA,
186 #undef BS
187 #undef CC
188 #undef CR
189 #undef NA
190 #undef NL
191 #undef NO
192 #undef TB
193 #undef VT
195 /* Macros to clear/set/test flags. */
196 #define SET(t, f) (t) |= (f)
197 #define CLR(t, f) (t) &= ~(f)
198 #define ISSET(t, f) ((t) & (f))
200 #undef MAX_INPUT /* XXX wrong in <sys/syslimits.h> */
201 #define MAX_INPUT TTYHOG /* XXX limit is usually larger for !ICANON */
203 uint64_t tk_nin;
204 SYSCTL_OPAQUE(_kern, OID_AUTO, tk_nin, CTLFLAG_RD, &tk_nin, sizeof(tk_nin),
205 "LU", "TTY input statistic");
206 uint64_t tk_nout;
207 SYSCTL_OPAQUE(_kern, OID_AUTO, tk_nout, CTLFLAG_RD, &tk_nout, sizeof(tk_nout),
208 "LU", "TTY output statistic");
209 uint64_t tk_rawcc;
212 * list of struct tty where pstat(8) can pick it up with sysctl
214 static TAILQ_HEAD(, tty) tty_list = TAILQ_HEAD_INITIALIZER(tty_list);
217 * Initial open of tty, or (re)entry to standard tty line discipline.
220 ttyopen(cdev_t device, struct tty *tp)
222 lwkt_gettoken(&tp->t_token);
223 tp->t_dev = device;
224 if (!ISSET(tp->t_state, TS_ISOPEN)) {
225 SET(tp->t_state, TS_ISOPEN);
226 if (ISSET(tp->t_cflag, CLOCAL)) {
227 SET(tp->t_state, TS_CONNECTED);
229 bzero(&tp->t_winsize, sizeof(tp->t_winsize));
231 ttsetwater(tp);
232 lwkt_reltoken(&tp->t_token);
234 return (0);
238 * Handle close() on a tty line: flush and set to initial state,
239 * bumping generation number so that pending read/write calls
240 * can detect recycling of the tty.
242 * XXX our caller should have done `spltty(); l_close(); ttyclose();'
243 * and l_close() should have flushed, but we repeat the spltty() and
244 * the flush in case there are buggy callers.
247 ttyclose(struct tty *tp)
249 lwkt_gettoken(&tp->t_token);
250 funsetown(&tp->t_sigio);
251 if (constty == tp)
252 constty = NULL;
254 ttyflush(tp, FREAD | FWRITE);
255 clist_free_cblocks(&tp->t_canq);
256 clist_free_cblocks(&tp->t_outq);
257 clist_free_cblocks(&tp->t_rawq);
259 tp->t_gen++;
260 tp->t_line = TTYDISC;
261 ttyclearsession(tp);
262 tp->t_state &= TS_REGISTERED; /* clear all bits except */
263 lwkt_reltoken(&tp->t_token);
265 return (0);
269 * Disassociate the tty from its session. Traditionally this has only been
270 * a half-close, meaning that the session was still allowed to point at the
271 * tty (resulting in the tty in the ps command showing something like 'p0-'),
272 * even though the tty is no longer pointing at the session.
274 * The half close seems to be useful only for 'ps' output but there is as
275 * yet no reason to remove the feature. The full-close code is currently
276 * #if 0'd out. See also sess_rele() in kern/kern_proc.c.
278 void
279 ttyclearsession(struct tty *tp)
281 struct session *sp;
282 struct procglob *prg;
283 struct pgrp *opgrp;
285 lwkt_gettoken(&tp->t_token);
286 opgrp = tp->t_pgrp;
287 tp->t_pgrp = NULL;
288 if (opgrp) {
289 pgrel(opgrp);
290 opgrp = NULL;
293 again:
294 if ((sp = tp->t_session) != NULL) {
295 prg = sp->s_prg;
296 lwkt_gettoken(&prg->proc_token);
297 if (sp != tp->t_session) {
298 lwkt_reltoken(&prg->proc_token);
299 goto again;
301 tp->t_session = NULL;
303 #ifdef TTY_DO_FULL_CLOSE
304 /* FULL CLOSE (not yet) */
305 if (sp->s_ttyp == tp) {
306 sp->s_ttyp = NULL;
307 ttyunhold(tp);
308 } else {
309 kprintf("ttyclearsession: warning: sp->s_ttyp != tp "
310 "%p/%p\n", sp->s_ttyp, tp);
312 #endif
313 lwkt_reltoken(&prg->proc_token);
315 lwkt_reltoken(&tp->t_token);
319 * Release the tty vnode association for a session. This is the
320 * 'other half' of the close. Because multiple opens of /dev/tty
321 * only generate a single open to the actual tty, the file modes
322 * are locked to FREAD|FWRITE.
324 * If dorevoke is non-zero, the session is also revoked. We have to
325 * close the vnode if VCTTYISOPEN is set.
327 void
328 ttyclosesession(struct session *sp, int dorevoke)
330 struct vnode *vp;
331 struct procglob *prg;
333 prg = sp->s_prg;
334 lwkt_gettoken(&prg->proc_token);
335 retry:
337 * There may not be a controlling terminal or it may have been closed
338 * out from under us.
340 if ((vp = sp->s_ttyvp) == NULL) {
341 lwkt_reltoken(&prg->proc_token);
342 return;
346 * We need a lock if we have to close or revoke.
348 if ((vp->v_flag & VCTTYISOPEN) || dorevoke) {
349 vhold(vp);
350 if (vn_lock(vp, LK_EXCLUSIVE | LK_RETRY | LK_FAILRECLAIM)) {
351 vdrop(vp);
352 goto retry;
356 * Retry if the vnode was ripped out from under us
358 if (vp != sp->s_ttyvp) {
359 vn_unlock(vp);
360 vdrop(vp);
361 goto retry;
365 * Close and revoke as needed
367 sp->s_ttyvp = NULL;
368 if (vp->v_flag & VCTTYISOPEN) {
369 vclrflags(vp, VCTTYISOPEN);
370 VOP_CLOSE(vp, FREAD|FWRITE, NULL);
372 vn_unlock(vp);
373 if (dorevoke)
374 vrevoke(vp, proc0.p_ucred);
375 vdrop(vp);
376 } else {
377 sp->s_ttyvp = NULL;
379 vrele(vp);
380 lwkt_reltoken(&prg->proc_token);
383 #define FLUSHQ(q) { \
384 if ((q)->c_cc) \
385 ndflush(q, (q)->c_cc); \
388 /* Is 'c' a line delimiter ("break" character)? */
389 #define TTBREAKC(c, lflag) \
390 ((c) == '\n' || (((c) == cc[VEOF] || \
391 (c) == cc[VEOL] || ((c) == cc[VEOL2] && lflag & IEXTEN)) && \
392 (c) != _POSIX_VDISABLE))
395 * Process input of a single character received on a tty.
398 ttyinput(int c, struct tty *tp)
400 tcflag_t iflag, lflag;
401 cc_t *cc;
402 int i, err;
404 lwkt_gettoken(&tp->t_token);
406 * If input is pending take it first.
408 lflag = tp->t_lflag;
409 if (ISSET(lflag, PENDIN))
410 ttypend(tp);
412 * Gather stats.
414 if (ISSET(lflag, ICANON))
415 ++tp->t_cancc;
416 else
417 ++tp->t_rawcc;
418 ++tk_nin;
421 * Block further input iff:
422 * current input > threshold AND input is available to user program
423 * AND input flow control is enabled and not yet invoked.
424 * The 3 is slop for PARMRK.
426 iflag = tp->t_iflag;
427 if (tp->t_rawq.c_cc + tp->t_canq.c_cc > tp->t_ihiwat - 3 &&
428 (!ISSET(lflag, ICANON) || tp->t_canq.c_cc != 0) &&
429 (ISSET(tp->t_cflag, CRTS_IFLOW) || ISSET(iflag, IXOFF)) &&
430 !ISSET(tp->t_state, TS_TBLOCK))
431 ttyblock(tp);
433 /* Handle exceptional conditions (break, parity, framing). */
434 cc = tp->t_cc;
435 err = (ISSET(c, TTY_ERRORMASK));
436 if (err) {
437 CLR(c, TTY_ERRORMASK);
438 if (ISSET(err, TTY_BI)) {
439 if (ISSET(iflag, IGNBRK)) {
440 lwkt_reltoken(&tp->t_token);
441 return (0);
443 if (ISSET(iflag, BRKINT)) {
444 ttyflush(tp, FREAD | FWRITE);
445 pgsignal(tp->t_pgrp, SIGINT, 1);
446 goto endcase;
448 if (ISSET(iflag, PARMRK))
449 goto parmrk;
450 } else if ((ISSET(err, TTY_PE) && ISSET(iflag, INPCK))
451 || ISSET(err, TTY_FE)) {
452 if (ISSET(iflag, IGNPAR)) {
453 lwkt_reltoken(&tp->t_token);
454 return (0);
456 else if (ISSET(iflag, PARMRK)) {
457 parmrk:
458 if (tp->t_rawq.c_cc + tp->t_canq.c_cc >
459 MAX_INPUT - 3)
460 goto input_overflow;
461 clist_putc(0377 | TTY_QUOTE, &tp->t_rawq);
462 clist_putc(0 | TTY_QUOTE, &tp->t_rawq);
463 clist_putc(c | TTY_QUOTE, &tp->t_rawq);
464 goto endcase;
465 } else
466 c = 0;
470 if (!ISSET(tp->t_state, TS_TYPEN) && ISSET(iflag, ISTRIP))
471 CLR(c, 0x80);
472 if (!ISSET(lflag, EXTPROC)) {
474 * Check for literal nexting very first
476 if (ISSET(tp->t_state, TS_LNCH)) {
477 SET(c, TTY_QUOTE);
478 CLR(tp->t_state, TS_LNCH);
481 * Scan for special characters. This code
482 * is really just a big case statement with
483 * non-constant cases. The bottom of the
484 * case statement is labeled ``endcase'', so goto
485 * it after a case match, or similar.
489 * Control chars which aren't controlled
490 * by ICANON, ISIG, or IXON.
492 if (ISSET(lflag, IEXTEN)) {
493 if (CCEQ(cc[VLNEXT], c)) {
494 if (ISSET(lflag, ECHO)) {
495 if (ISSET(lflag, ECHOE)) {
496 (void)ttyoutput('^', tp);
497 (void)ttyoutput('\b', tp);
498 } else
499 ttyecho(c, tp);
501 SET(tp->t_state, TS_LNCH);
502 goto endcase;
504 if (CCEQ(cc[VDISCARD], c)) {
505 if (ISSET(lflag, FLUSHO))
506 CLR(tp->t_lflag, FLUSHO);
507 else {
508 ttyflush(tp, FWRITE);
509 ttyecho(c, tp);
510 if (tp->t_rawq.c_cc + tp->t_canq.c_cc)
511 ttyretype(tp);
512 SET(tp->t_lflag, FLUSHO);
514 goto startoutput;
518 * Signals.
520 if (ISSET(lflag, ISIG)) {
521 if (CCEQ(cc[VINTR], c) || CCEQ(cc[VQUIT], c)) {
522 if (!ISSET(lflag, NOFLSH))
523 ttyflush(tp, FREAD | FWRITE);
524 ttyecho(c, tp);
525 pgsignal(tp->t_pgrp,
526 CCEQ(cc[VINTR], c) ? SIGINT : SIGQUIT, 1);
527 goto endcase;
529 if (CCEQ(cc[VSUSP], c)) {
530 if (!ISSET(lflag, NOFLSH))
531 ttyflush(tp, FREAD);
532 ttyecho(c, tp);
533 pgsignal(tp->t_pgrp, SIGTSTP, 1);
534 goto endcase;
538 * Handle start/stop characters.
540 if (ISSET(iflag, IXON)) {
541 if (CCEQ(cc[VSTOP], c)) {
542 if (!ISSET(tp->t_state, TS_TTSTOP)) {
543 SET(tp->t_state, TS_TTSTOP);
544 (*tp->t_stop)(tp, 0);
545 lwkt_reltoken(&tp->t_token);
546 return (0);
548 if (!CCEQ(cc[VSTART], c)) {
549 lwkt_reltoken(&tp->t_token);
550 return (0);
553 * if VSTART == VSTOP then toggle
555 goto endcase;
557 if (CCEQ(cc[VSTART], c))
558 goto restartoutput;
561 * IGNCR, ICRNL, & INLCR
563 if (c == '\r') {
564 if (ISSET(iflag, IGNCR)) {
565 lwkt_reltoken(&tp->t_token);
566 return (0);
568 else if (ISSET(iflag, ICRNL))
569 c = '\n';
570 } else if (c == '\n' && ISSET(iflag, INLCR))
571 c = '\r';
573 if (!ISSET(tp->t_lflag, EXTPROC) && ISSET(lflag, ICANON)) {
575 * From here on down canonical mode character
576 * processing takes place.
579 * erase or erase2 (^H / ^?)
581 if (CCEQ(cc[VERASE], c) || CCEQ(cc[VERASE2], c) ) {
582 if (tp->t_rawq.c_cc)
583 ttyrub(clist_unputc(&tp->t_rawq), tp);
584 goto endcase;
587 * kill (^U)
589 if (CCEQ(cc[VKILL], c)) {
590 if (ISSET(lflag, ECHOKE) &&
591 tp->t_rawq.c_cc == tp->t_rocount &&
592 !ISSET(lflag, ECHOPRT))
593 while (tp->t_rawq.c_cc)
594 ttyrub(clist_unputc(&tp->t_rawq), tp);
595 else {
596 ttyecho(c, tp);
597 if (ISSET(lflag, ECHOK) ||
598 ISSET(lflag, ECHOKE))
599 ttyecho('\n', tp);
600 FLUSHQ(&tp->t_rawq);
601 tp->t_rocount = 0;
603 CLR(tp->t_state, TS_LOCAL);
604 goto endcase;
607 * word erase (^W)
609 if (CCEQ(cc[VWERASE], c) && ISSET(lflag, IEXTEN)) {
610 int ctype;
613 * erase whitespace
615 while ((c = clist_unputc(&tp->t_rawq)) == ' ' || c == '\t')
616 ttyrub(c, tp);
617 if (c == -1)
618 goto endcase;
620 * erase last char of word and remember the
621 * next chars type (for ALTWERASE)
623 ttyrub(c, tp);
624 c = clist_unputc(&tp->t_rawq);
625 if (c == -1)
626 goto endcase;
627 if (c == ' ' || c == '\t') {
628 clist_putc(c, &tp->t_rawq);
629 goto endcase;
631 ctype = ISALPHA(c);
633 * erase rest of word
635 do {
636 ttyrub(c, tp);
637 c = clist_unputc(&tp->t_rawq);
638 if (c == -1)
639 goto endcase;
640 } while (c != ' ' && c != '\t' &&
641 (!ISSET(lflag, ALTWERASE) || ISALPHA(c) == ctype));
642 clist_putc(c, &tp->t_rawq);
643 goto endcase;
646 * reprint line (^R)
648 if (CCEQ(cc[VREPRINT], c) && ISSET(lflag, IEXTEN)) {
649 ttyretype(tp);
650 goto endcase;
653 * ^T - kernel info and generate SIGINFO
655 if (CCEQ(cc[VSTATUS], c) && ISSET(lflag, IEXTEN)) {
656 if (ISSET(lflag, ISIG))
657 pgsignal(tp->t_pgrp, SIGINFO, 1);
658 if (!ISSET(lflag, NOKERNINFO))
659 ttyinfo(tp);
660 goto endcase;
662 if (CCEQ(cc[VCHECKPT], c) && ISSET(lflag, IEXTEN)) {
663 if (ISSET(lflag, ISIG))
664 pgsignal(tp->t_pgrp, SIGCKPT, 1);
665 goto endcase;
669 * Check for input buffer overflow
671 if (tp->t_rawq.c_cc + tp->t_canq.c_cc >= MAX_INPUT) {
672 input_overflow:
673 if (ISSET(iflag, IMAXBEL)) {
674 if (tp->t_outq.c_cc < tp->t_ohiwat)
675 (void)ttyoutput(CTRL('g'), tp);
677 goto endcase;
680 if (c == 0377 && ISSET(iflag, PARMRK) && !ISSET(iflag, ISTRIP) &&
681 ISSET(iflag, IGNBRK|IGNPAR) != (IGNBRK|IGNPAR)) {
682 clist_putc(0377 | TTY_QUOTE, &tp->t_rawq);
686 * Put data char in q for user and
687 * wakeup on seeing a line delimiter.
689 if (clist_putc(c, &tp->t_rawq) >= 0) {
690 if (!ISSET(lflag, ICANON)) {
691 ttwakeup(tp);
692 ttyecho(c, tp);
693 goto endcase;
695 if (TTBREAKC(c, lflag)) {
696 tp->t_rocount = 0;
697 clist_catq(&tp->t_rawq, &tp->t_canq);
698 ttwakeup(tp);
699 } else if (tp->t_rocount++ == 0)
700 tp->t_rocol = tp->t_column;
701 if (ISSET(tp->t_state, TS_ERASE)) {
703 * end of prterase \.../
705 CLR(tp->t_state, TS_ERASE);
706 (void)ttyoutput('/', tp);
708 i = tp->t_column;
709 ttyecho(c, tp);
710 if (CCEQ(cc[VEOF], c) && ISSET(lflag, ECHO)) {
712 * Place the cursor over the '^' of the ^D.
714 i = imin(2, tp->t_column - i);
715 while (i > 0) {
716 (void)ttyoutput('\b', tp);
717 i--;
721 endcase:
723 * IXANY means allow any character to restart output.
725 if (ISSET(tp->t_state, TS_TTSTOP) &&
726 !ISSET(iflag, IXANY) && cc[VSTART] != cc[VSTOP]) {
727 lwkt_reltoken(&tp->t_token);
728 return (0);
730 restartoutput:
731 CLR(tp->t_lflag, FLUSHO);
732 CLR(tp->t_state, TS_TTSTOP);
733 startoutput:
734 lwkt_reltoken(&tp->t_token);
735 return (ttstart(tp));
739 * Output a single character on a tty, doing output processing
740 * as needed (expanding tabs, newline processing, etc.).
741 * Returns < 0 if succeeds, otherwise returns char to resend.
742 * Must be recursive.
744 static int
745 ttyoutput(int c, struct tty *tp)
747 tcflag_t oflag;
748 int col;
750 lwkt_gettoken(&tp->t_token);
751 oflag = tp->t_oflag;
752 if (!ISSET(oflag, OPOST)) {
753 if (ISSET(tp->t_lflag, FLUSHO)) {
754 lwkt_reltoken(&tp->t_token);
755 return (-1);
757 if (clist_putc(c, &tp->t_outq)) {
758 lwkt_reltoken(&tp->t_token);
759 return (c);
761 tk_nout++;
762 tp->t_outcc++;
763 lwkt_reltoken(&tp->t_token);
764 return (-1);
767 * Do tab expansion if OXTABS aka TAB3 is set. Special case if we
768 * external processing, we don't do the tab expansion because we'll
769 * probably get it wrong. If tab expansion needs to be done, let
770 * it happen externally.
772 CLR(c, ~TTY_CHARMASK);
773 if (c == '\t' &&
774 ISSET(oflag, OXTABS) && !ISSET(tp->t_lflag, EXTPROC)) {
775 c = 8 - (tp->t_column & 7);
776 if (!ISSET(tp->t_lflag, FLUSHO)) {
777 c -= clist_btoq(" ", c, &tp->t_outq);
778 tk_nout += c;
779 tp->t_outcc += c;
781 tp->t_column += c;
782 lwkt_reltoken(&tp->t_token);
783 return (c ? -1 : '\t');
785 if (c == CEOT && ISSET(oflag, ONOEOT)) {
786 lwkt_reltoken(&tp->t_token);
787 return (-1);
791 * Newline translation: if ONLCR is set,
792 * translate newline into "\r\n".
794 if (c == '\n' && ISSET(tp->t_oflag, ONLCR)) {
795 tk_nout++;
796 tp->t_outcc++;
797 if (!ISSET(tp->t_lflag, FLUSHO) && clist_putc('\r', &tp->t_outq)) {
798 lwkt_reltoken(&tp->t_token);
799 return (c);
802 /* If OCRNL is set, translate "\r" into "\n". */
803 else if (c == '\r' && ISSET(tp->t_oflag, OCRNL))
804 c = '\n';
805 /* If ONOCR is set, don't transmit CRs when on column 0. */
806 else if (c == '\r' && ISSET(tp->t_oflag, ONOCR) && tp->t_column == 0) {
807 lwkt_reltoken(&tp->t_token);
808 return (-1);
811 tk_nout++;
812 tp->t_outcc++;
813 if (!ISSET(tp->t_lflag, FLUSHO) && clist_putc(c, &tp->t_outq)) {
814 lwkt_reltoken(&tp->t_token);
815 return (c);
818 col = tp->t_column;
819 switch (CCLASS(c)) {
820 case BACKSPACE:
821 if (col > 0)
822 --col;
823 break;
824 case CONTROL:
825 break;
826 case NEWLINE:
827 if (ISSET(tp->t_oflag, ONLCR | ONLRET))
828 col = 0;
829 break;
830 case RETURN:
831 col = 0;
832 break;
833 case ORDINARY:
834 ++col;
835 break;
836 case TAB:
837 col = (col + 8) & ~7;
838 break;
840 tp->t_column = col;
841 lwkt_reltoken(&tp->t_token);
843 return (-1);
847 * Ioctls for all tty devices. Called after line-discipline specific ioctl
848 * has been called to do discipline-specific functions and/or reject any
849 * of these ioctl commands.
851 /* ARGSUSED */
853 ttioctl(struct tty *tp, u_long cmd, void *data, int flag)
855 struct thread *td = curthread;
856 struct lwp *lp = td->td_lwp;
857 struct proc *p = td->td_proc;
858 struct pgrp *opgrp;
859 struct tty *otp;
860 int error;
862 KKASSERT(p);
863 lwkt_gettoken(&tp->t_token);
864 lwkt_gettoken(&p->p_token);
866 /* If the ioctl involves modification, hang if in the background. */
867 switch (cmd) {
868 case TIOCCBRK:
869 case TIOCCONS:
870 case TIOCDRAIN:
871 case TIOCEXCL:
872 case TIOCFLUSH:
873 #ifdef TIOCHPCL
874 case TIOCHPCL:
875 #endif
876 case TIOCNXCL:
877 case TIOCSBRK:
878 case TIOCSCTTY:
879 case TIOCSDRAINWAIT:
880 case TIOCSETA:
881 case TIOCSETAF:
882 case TIOCSETAW:
883 case TIOCSETD:
884 case TIOCSPGRP:
885 case TIOCSTART:
886 case TIOCSTAT:
887 case TIOCSTI:
888 case TIOCSTOP:
889 case TIOCSWINSZ:
890 while (isbackground(p, tp) && !(p->p_flags & P_PPWAIT) &&
891 !SIGISMEMBER(p->p_sigignore, SIGTTOU) &&
892 !SIGISMEMBER(lp->lwp_sigmask, SIGTTOU)) {
893 if (p->p_pgrp->pg_jobc == 0) {
894 lwkt_reltoken(&p->p_token);
895 lwkt_reltoken(&tp->t_token);
896 return (EIO);
898 pgsignal(p->p_pgrp, SIGTTOU, 1);
899 error = ttysleep(tp, &lbolt, PCATCH, "ttybg1",
901 if (error) {
902 lwkt_reltoken(&p->p_token);
903 lwkt_reltoken(&tp->t_token);
904 return (error);
907 break;
910 switch (cmd) { /* Process the ioctl. */
911 case FIOASYNC: /* set/clear async i/o */
912 if (*(int *)data)
913 SET(tp->t_state, TS_ASYNC);
914 else
915 CLR(tp->t_state, TS_ASYNC);
916 break;
917 case FIONREAD: /* get # bytes to read */
918 *(int *)data = ttnread(tp);
919 break;
921 case FIOSETOWN:
923 * Policy -- Don't allow FIOSETOWN on someone else's
924 * controlling tty
926 if (tp->t_session != NULL && !isctty(p, tp)) {
927 lwkt_reltoken(&p->p_token);
928 lwkt_reltoken(&tp->t_token);
929 return (ENOTTY);
932 error = fsetown(*(int *)data, &tp->t_sigio);
933 if (error) {
934 lwkt_reltoken(&p->p_token);
935 lwkt_reltoken(&tp->t_token);
936 return (error);
938 break;
939 case FIOGETOWN:
940 if (tp->t_session != NULL && !isctty(p, tp)) {
941 lwkt_reltoken(&p->p_token);
942 lwkt_reltoken(&tp->t_token);
943 return (ENOTTY);
945 *(int *)data = fgetown(&tp->t_sigio);
946 break;
948 case TIOCEXCL: /* set exclusive use of tty */
949 SET(tp->t_state, TS_XCLUDE);
950 break;
951 case TIOCFLUSH: { /* flush buffers */
952 int flags = *(int *)data;
954 if (flags == 0)
955 flags = FREAD | FWRITE;
956 else
957 flags &= FREAD | FWRITE;
958 ttyflush(tp, flags);
959 break;
961 case TIOCCONS: /* become virtual console */
962 if (*(int *)data) {
963 if (constty && constty != tp &&
964 ISSET(constty->t_state, TS_CONNECTED)) {
965 lwkt_reltoken(&p->p_token);
966 lwkt_reltoken(&tp->t_token);
967 return (EBUSY);
969 #ifndef UCONSOLE
970 error = caps_priv_check_td(td, SYSCAP_RESTRICTEDROOT);
971 if (error) {
972 lwkt_reltoken(&p->p_token);
973 lwkt_reltoken(&tp->t_token);
974 return (error);
976 #endif
977 constty = tp;
978 } else if (tp == constty)
979 constty = NULL;
980 break;
981 case TIOCDRAIN: /* wait till output drained */
982 error = ttywait(tp);
983 if (error) {
984 lwkt_reltoken(&p->p_token);
985 lwkt_reltoken(&tp->t_token);
986 return (error);
988 break;
989 case TIOCGETA: { /* get termios struct */
990 struct termios *t = (struct termios *)data;
992 bcopy(&tp->t_termios, t, sizeof(struct termios));
993 break;
995 case TIOCGETD: /* get line discipline */
996 *(int *)data = tp->t_line;
997 break;
998 case TIOCGWINSZ: /* get window size */
999 *(struct winsize *)data = tp->t_winsize;
1000 break;
1001 case TIOCGPGRP: /* get pgrp of tty */
1002 if (!isctty(p, tp)) {
1003 lwkt_reltoken(&p->p_token);
1004 lwkt_reltoken(&tp->t_token);
1005 return (ENOTTY);
1007 *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
1008 break;
1009 case TIOCGSID: /* get sid of tty */
1010 if (!isctty(p, tp)) {
1011 lwkt_reltoken(&p->p_token);
1012 lwkt_reltoken(&tp->t_token);
1013 return (ENOTTY);
1015 *(int *)data = tp->t_session->s_sid;
1016 break;
1017 #ifdef TIOCHPCL
1018 case TIOCHPCL: /* hang up on last close */
1019 SET(tp->t_cflag, HUPCL);
1020 break;
1021 #endif
1022 case TIOCNXCL: /* reset exclusive use of tty */
1023 CLR(tp->t_state, TS_XCLUDE);
1024 break;
1025 case TIOCOUTQ: /* output queue size */
1026 *(int *)data = tp->t_outq.c_cc;
1027 break;
1028 case TIOCSETA: /* set termios struct */
1029 case TIOCSETAW: /* drain output, set */
1030 case TIOCSETAF: { /* drn out, fls in, set */
1031 struct termios *t = (struct termios *)data;
1033 if (t->c_ispeed == 0)
1034 t->c_ispeed = t->c_ospeed;
1035 if (t->c_ispeed == 0)
1036 t->c_ispeed = tp->t_ospeed;
1037 if (t->c_ispeed == 0) {
1038 lwkt_reltoken(&p->p_token);
1039 lwkt_reltoken(&tp->t_token);
1040 return (EINVAL);
1042 if (cmd == TIOCSETAW || cmd == TIOCSETAF) {
1043 error = ttywait(tp);
1044 if (error) {
1045 lwkt_reltoken(&p->p_token);
1046 lwkt_reltoken(&tp->t_token);
1047 return (error);
1049 if (cmd == TIOCSETAF)
1050 ttyflush(tp, FREAD);
1052 if (!ISSET(t->c_cflag, CIGNORE)) {
1054 * Set device hardware.
1056 if (tp->t_param && (error = (*tp->t_param)(tp, t))) {
1057 lwkt_reltoken(&p->p_token);
1058 lwkt_reltoken(&tp->t_token);
1059 return (error);
1061 if (ISSET(t->c_cflag, CLOCAL) &&
1062 !ISSET(tp->t_cflag, CLOCAL)) {
1064 * XXX disconnections would be too hard to
1065 * get rid of without this kludge. The only
1066 * way to get rid of controlling terminals
1067 * is to exit from the session leader.
1069 CLR(tp->t_state, TS_ZOMBIE);
1071 wakeup(TSA_CARR_ON(tp));
1072 ttwakeup(tp);
1073 ttwwakeup(tp);
1075 if ((ISSET(tp->t_state, TS_CARR_ON) ||
1076 ISSET(t->c_cflag, CLOCAL)) &&
1077 !ISSET(tp->t_state, TS_ZOMBIE))
1078 SET(tp->t_state, TS_CONNECTED);
1079 else
1080 CLR(tp->t_state, TS_CONNECTED);
1081 tp->t_cflag = t->c_cflag;
1082 tp->t_ispeed = t->c_ispeed;
1083 if (t->c_ospeed != 0)
1084 tp->t_ospeed = t->c_ospeed;
1085 ttsetwater(tp);
1087 if (ISSET(t->c_lflag, ICANON) != ISSET(tp->t_lflag, ICANON) &&
1088 cmd != TIOCSETAF) {
1089 if (ISSET(t->c_lflag, ICANON))
1090 SET(tp->t_lflag, PENDIN);
1091 else {
1093 * XXX we really shouldn't allow toggling
1094 * ICANON while we're in a non-termios line
1095 * discipline. Now we have to worry about
1096 * panicing for a null queue.
1098 if (tp->t_canq.c_ccmax > 0 &&
1099 tp->t_rawq.c_ccmax > 0) {
1100 clist_catq(&tp->t_rawq, &tp->t_canq);
1102 * XXX the queue limits may be
1103 * different, so the old queue
1104 * swapping method no longer works.
1106 clist_catq(&tp->t_canq, &tp->t_rawq);
1108 CLR(tp->t_lflag, PENDIN);
1110 ttwakeup(tp);
1112 tp->t_iflag = t->c_iflag;
1113 tp->t_oflag = t->c_oflag;
1115 * Make the EXTPROC bit read only.
1117 if (ISSET(tp->t_lflag, EXTPROC))
1118 SET(t->c_lflag, EXTPROC);
1119 else
1120 CLR(t->c_lflag, EXTPROC);
1121 tp->t_lflag = t->c_lflag | ISSET(tp->t_lflag, PENDIN);
1122 if (t->c_cc[VMIN] != tp->t_cc[VMIN] ||
1123 t->c_cc[VTIME] != tp->t_cc[VTIME])
1124 ttwakeup(tp);
1125 bcopy(t->c_cc, tp->t_cc, sizeof(t->c_cc));
1126 break;
1128 case TIOCSETD: { /* set line discipline */
1129 int t = *(int *)data;
1130 cdev_t device = tp->t_dev;
1132 if ((u_int)t >= nlinesw) {
1133 lwkt_reltoken(&p->p_token);
1134 lwkt_reltoken(&tp->t_token);
1135 return (ENXIO);
1137 if (t != tp->t_line) {
1138 (*linesw[tp->t_line].l_close)(tp, flag);
1139 error = (*linesw[t].l_open)(device, tp);
1140 if (error) {
1141 (void)(*linesw[tp->t_line].l_open)(device, tp);
1142 lwkt_reltoken(&p->p_token);
1143 lwkt_reltoken(&tp->t_token);
1144 return (error);
1146 tp->t_line = t;
1148 break;
1150 case TIOCSTART: /* start output, like ^Q */
1151 if (ISSET(tp->t_state, TS_TTSTOP) ||
1152 ISSET(tp->t_lflag, FLUSHO)) {
1153 CLR(tp->t_lflag, FLUSHO);
1154 CLR(tp->t_state, TS_TTSTOP);
1155 ttstart(tp);
1157 break;
1158 case TIOCSTI: /* simulate terminal input */
1159 if ((flag & FREAD) == 0 &&
1160 caps_priv_check_td(td, SYSCAP_RESTRICTEDROOT))
1162 lwkt_reltoken(&p->p_token);
1163 lwkt_reltoken(&tp->t_token);
1164 return (EPERM);
1166 if (!isctty(p, tp) &&
1167 caps_priv_check_td(td, SYSCAP_RESTRICTEDROOT))
1169 lwkt_reltoken(&p->p_token);
1170 lwkt_reltoken(&tp->t_token);
1171 return (EACCES);
1173 (*linesw[tp->t_line].l_rint)(*(u_char *)data, tp);
1174 break;
1175 case TIOCSTOP: /* stop output, like ^S */
1176 if (!ISSET(tp->t_state, TS_TTSTOP)) {
1177 SET(tp->t_state, TS_TTSTOP);
1178 (*tp->t_stop)(tp, 0);
1180 break;
1181 case TIOCSCTTY: /* become controlling tty */
1182 /* Session ctty vnode pointer set in vnode layer. */
1183 if (!SESS_LEADER(p) ||
1184 ((p->p_session->s_ttyvp || tp->t_session) &&
1185 (tp->t_session != p->p_session))) {
1186 lwkt_reltoken(&p->p_token);
1187 lwkt_reltoken(&tp->t_token);
1188 return (EPERM);
1190 ttyhold(tp);
1191 tp->t_session = p->p_session;
1192 opgrp = tp->t_pgrp;
1193 pgref(p->p_pgrp);
1194 tp->t_pgrp = p->p_pgrp;
1195 otp = p->p_session->s_ttyp;
1196 p->p_session->s_ttyp = tp;
1197 p->p_flags |= P_CONTROLT;
1198 if (otp)
1199 ttyunhold(otp);
1200 if (opgrp) {
1201 pgrel(opgrp);
1202 opgrp = NULL;
1204 break;
1205 case TIOCSPGRP: { /* set pgrp of tty */
1206 pid_t pgid = *(int *)data;
1208 if (!isctty(p, tp)) {
1209 lwkt_reltoken(&p->p_token);
1210 lwkt_reltoken(&tp->t_token);
1211 return (ENOTTY);
1213 else if (pgid < 1 || pgid > PID_MAX) {
1214 lwkt_reltoken(&p->p_token);
1215 lwkt_reltoken(&tp->t_token);
1216 return (EINVAL);
1217 } else {
1218 struct pgrp *pgrp = pgfind(pgid);
1219 if (pgrp == NULL || pgrp->pg_session != p->p_session) {
1220 if (pgrp)
1221 pgrel(pgrp);
1222 lwkt_reltoken(&p->p_token);
1223 lwkt_reltoken(&tp->t_token);
1224 return (EPERM);
1226 opgrp = tp->t_pgrp;
1227 tp->t_pgrp = pgrp;
1228 if (opgrp) {
1229 pgrel(opgrp);
1230 opgrp = NULL;
1233 break;
1235 case TIOCSTAT: /* simulate control-T */
1236 ttyinfo(tp);
1237 break;
1238 case TIOCSWINSZ: /* set window size */
1239 if (bcmp((caddr_t)&tp->t_winsize, data,
1240 sizeof (struct winsize))) {
1241 tp->t_winsize = *(struct winsize *)data;
1242 pgsignal(tp->t_pgrp, SIGWINCH, 1);
1244 break;
1245 case TIOCSDRAINWAIT:
1246 error = caps_priv_check_td(td, SYSCAP_RESTRICTEDROOT);
1247 if (error) {
1248 lwkt_reltoken(&p->p_token);
1249 lwkt_reltoken(&tp->t_token);
1250 return (error);
1252 tp->t_timeout = *(int *)data * hz;
1253 wakeup(TSA_OCOMPLETE(tp));
1254 wakeup(TSA_OLOWAT(tp));
1255 break;
1256 case TIOCGDRAINWAIT:
1257 *(int *)data = tp->t_timeout / hz;
1258 break;
1259 default:
1260 lwkt_reltoken(&p->p_token);
1261 lwkt_reltoken(&tp->t_token);
1262 return (ENOIOCTL);
1264 lwkt_reltoken(&p->p_token);
1265 lwkt_reltoken(&tp->t_token);
1266 return (0);
1269 static struct filterops ttyread_filtops =
1270 { FILTEROP_ISFD|FILTEROP_MPSAFE, NULL, filt_ttyrdetach, filt_ttyread };
1271 static struct filterops ttywrite_filtops =
1272 { FILTEROP_ISFD|FILTEROP_MPSAFE, NULL, filt_ttywdetach, filt_ttywrite };
1275 ttykqfilter(struct dev_kqfilter_args *ap)
1277 cdev_t dev = ap->a_head.a_dev;
1278 struct knote *kn = ap->a_kn;
1279 struct tty *tp = dev->si_tty;
1280 struct klist *klist;
1282 ap->a_result = 0;
1284 lwkt_gettoken(&tp->t_token);
1285 switch (kn->kn_filter) {
1286 case EVFILT_READ:
1287 klist = &tp->t_rkq.ki_note;
1288 kn->kn_fop = &ttyread_filtops;
1289 break;
1290 case EVFILT_WRITE:
1291 klist = &tp->t_wkq.ki_note;
1292 kn->kn_fop = &ttywrite_filtops;
1293 break;
1294 default:
1295 ap->a_result = EOPNOTSUPP;
1296 lwkt_reltoken(&tp->t_token);
1297 return (0);
1299 lwkt_reltoken(&tp->t_token);
1300 kn->kn_hook = (caddr_t)dev;
1301 knote_insert(klist, kn);
1303 return (0);
1306 static void
1307 filt_ttyrdetach(struct knote *kn)
1309 struct tty *tp = ((cdev_t)kn->kn_hook)->si_tty;
1311 lwkt_gettoken(&tp->t_token);
1312 knote_remove(&tp->t_rkq.ki_note, kn);
1313 lwkt_reltoken(&tp->t_token);
1316 static int
1317 filt_ttyread(struct knote *kn, long hint)
1319 struct tty *tp = ((cdev_t)kn->kn_hook)->si_tty;
1321 lwkt_gettoken(&tp->t_token);
1322 kn->kn_data = ttnread(tp);
1323 if (ISSET(tp->t_state, TS_ZOMBIE)) {
1324 kn->kn_flags |= (EV_EOF | EV_NODATA);
1325 lwkt_reltoken(&tp->t_token);
1326 return (1);
1328 lwkt_reltoken(&tp->t_token);
1329 return (kn->kn_data > 0);
1332 static void
1333 filt_ttywdetach(struct knote *kn)
1335 struct tty *tp = ((cdev_t)kn->kn_hook)->si_tty;
1337 lwkt_gettoken(&tp->t_token);
1338 knote_remove(&tp->t_wkq.ki_note, kn);
1339 lwkt_reltoken(&tp->t_token);
1342 static int
1343 filt_ttywrite(struct knote *kn, long hint)
1345 struct tty *tp = ((cdev_t)kn->kn_hook)->si_tty;
1346 int ret;
1348 lwkt_gettoken(&tp->t_token);
1349 kn->kn_data = tp->t_outq.c_cc;
1350 if (ISSET(tp->t_state, TS_ZOMBIE)) {
1351 lwkt_reltoken(&tp->t_token);
1352 return (1);
1354 ret = (kn->kn_data <= tp->t_olowat &&
1355 ISSET(tp->t_state, TS_CONNECTED));
1356 lwkt_reltoken(&tp->t_token);
1357 return ret;
1361 * NOTE: tp->t_token must be held.
1363 static int
1364 ttnread(struct tty *tp)
1366 int nread;
1368 ASSERT_LWKT_TOKEN_HELD(&tp->t_token);
1369 if (ISSET(tp->t_lflag, PENDIN))
1370 ttypend(tp);
1371 nread = tp->t_canq.c_cc;
1372 if (!ISSET(tp->t_lflag, ICANON)) {
1373 nread += tp->t_rawq.c_cc;
1374 if (nread < tp->t_cc[VMIN] && tp->t_cc[VTIME] == 0)
1375 nread = 0;
1377 return (nread);
1381 * Wait for output to drain.
1384 ttywait(struct tty *tp)
1386 int error;
1388 error = 0;
1389 lwkt_gettoken(&tp->t_token);
1390 while ((tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)) &&
1391 ISSET(tp->t_state, TS_CONNECTED) && tp->t_oproc) {
1392 (*tp->t_oproc)(tp);
1393 if ((tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)) &&
1394 ISSET(tp->t_state, TS_CONNECTED)) {
1395 SET(tp->t_state, TS_SO_OCOMPLETE);
1396 error = ttysleep(tp, TSA_OCOMPLETE(tp),
1397 PCATCH, "ttywai",
1398 tp->t_timeout);
1399 if (error) {
1400 if (error == EWOULDBLOCK)
1401 error = EIO;
1402 break;
1404 } else
1405 break;
1407 if (!error && (tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)))
1408 error = EIO;
1409 lwkt_reltoken(&tp->t_token);
1411 return (error);
1415 * Flush if successfully wait.
1417 static int
1418 ttywflush(struct tty *tp)
1420 int error;
1422 if ((error = ttywait(tp)) == 0)
1423 ttyflush(tp, FREAD);
1424 return (error);
1428 * Flush tty read and/or write queues, notifying anyone waiting.
1430 void
1431 ttyflush(struct tty *tp, int rw)
1433 lwkt_gettoken(&tp->t_token);
1434 #if 0
1435 again:
1436 #endif
1437 if (rw & FWRITE) {
1438 FLUSHQ(&tp->t_outq);
1439 CLR(tp->t_state, TS_TTSTOP);
1441 (*tp->t_stop)(tp, rw);
1442 if (rw & FREAD) {
1443 FLUSHQ(&tp->t_canq);
1444 FLUSHQ(&tp->t_rawq);
1445 CLR(tp->t_lflag, PENDIN);
1446 tp->t_rocount = 0;
1447 tp->t_rocol = 0;
1448 CLR(tp->t_state, TS_LOCAL);
1449 ttwakeup(tp);
1450 if (ISSET(tp->t_state, TS_TBLOCK)) {
1451 if (rw & FWRITE)
1452 FLUSHQ(&tp->t_outq);
1453 ttyunblock(tp);
1456 * Don't let leave any state that might clobber the
1457 * next line discipline (although we should do more
1458 * to send the START char). Not clearing the state
1459 * may have caused the "putc to a clist with no
1460 * reserved cblocks" panic/kprintf.
1462 CLR(tp->t_state, TS_TBLOCK);
1464 #if 0 /* forget it, sleeping isn't always safe and we don't know when it is */
1465 if (ISSET(tp->t_iflag, IXOFF)) {
1467 * XXX wait a bit in the hope that the stop
1468 * character (if any) will go out. Waiting
1469 * isn't good since it allows races. This
1470 * will be fixed when the stop character is
1471 * put in a special queue. Don't bother with
1472 * the checks in ttywait() since the timeout
1473 * will save us.
1475 SET(tp->t_state, TS_SO_OCOMPLETE);
1476 ttysleep(tp, TSA_OCOMPLETE(tp), 0,
1477 "ttyfls", hz / 10);
1479 * Don't try sending the stop character again.
1481 CLR(tp->t_state, TS_TBLOCK);
1482 goto again;
1484 #endif
1487 if (rw & FWRITE) {
1488 FLUSHQ(&tp->t_outq);
1489 ttwwakeup(tp);
1491 lwkt_reltoken(&tp->t_token);
1495 * Copy in the default termios characters.
1497 void
1498 termioschars(struct termios *t)
1500 bcopy(ttydefchars, t->c_cc, sizeof t->c_cc);
1504 * Old interface.
1506 void
1507 ttychars(struct tty *tp)
1509 lwkt_gettoken(&tp->t_token);
1510 termioschars(&tp->t_termios);
1511 lwkt_reltoken(&tp->t_token);
1515 * Handle input high water. Send stop character for the IXOFF case. Turn
1516 * on our input flow control bit and propagate the changes to the driver.
1517 * XXX the stop character should be put in a special high priority queue.
1519 void
1520 ttyblock(struct tty *tp)
1522 lwkt_gettoken(&tp->t_token);
1523 SET(tp->t_state, TS_TBLOCK);
1524 if (ISSET(tp->t_iflag, IXOFF) && tp->t_cc[VSTOP] != _POSIX_VDISABLE &&
1525 clist_putc(tp->t_cc[VSTOP], &tp->t_outq) != 0)
1526 CLR(tp->t_state, TS_TBLOCK); /* try again later */
1527 ttstart(tp);
1528 lwkt_reltoken(&tp->t_token);
1532 * Handle input low water. Send start character for the IXOFF case. Turn
1533 * off our input flow control bit and propagate the changes to the driver.
1534 * XXX the start character should be put in a special high priority queue.
1536 static void
1537 ttyunblock(struct tty *tp)
1539 lwkt_gettoken(&tp->t_token);
1540 CLR(tp->t_state, TS_TBLOCK);
1541 if (ISSET(tp->t_iflag, IXOFF) && tp->t_cc[VSTART] != _POSIX_VDISABLE &&
1542 clist_putc(tp->t_cc[VSTART], &tp->t_outq) != 0)
1543 SET(tp->t_state, TS_TBLOCK); /* try again later */
1544 ttstart(tp);
1545 lwkt_reltoken(&tp->t_token);
1549 ttstart(struct tty *tp)
1551 lwkt_gettoken(&tp->t_token);
1552 if (tp->t_oproc != NULL) /* XXX: Kludge for pty. */
1553 (*tp->t_oproc)(tp);
1554 lwkt_reltoken(&tp->t_token);
1555 return (0);
1559 * "close" a line discipline
1562 ttylclose(struct tty *tp, int flag)
1564 lwkt_gettoken(&tp->t_token);
1565 if (flag & FNONBLOCK || ttywflush(tp))
1566 ttyflush(tp, FREAD | FWRITE);
1567 lwkt_reltoken(&tp->t_token);
1568 return (0);
1571 void
1572 ttyhold(struct tty *tp)
1574 lwkt_gettoken(&tp->t_token);
1575 ++tp->t_refs;
1576 lwkt_reltoken(&tp->t_token);
1579 void
1580 ttyunhold(struct tty *tp)
1582 lwkt_gettoken(&tp->t_token);
1583 if (tp->t_unhold)
1584 tp->t_unhold(tp);
1585 else
1586 --tp->t_refs;
1587 lwkt_reltoken(&tp->t_token);
1591 * Handle modem control transition on a tty.
1592 * Flag indicates new state of carrier.
1593 * Returns 0 if the line should be turned off, otherwise 1.
1596 ttymodem(struct tty *tp, int flag)
1598 lwkt_gettoken(&tp->t_token);
1599 if (ISSET(tp->t_state, TS_CARR_ON) && ISSET(tp->t_cflag, MDMBUF)) {
1601 * MDMBUF: do flow control according to carrier flag
1602 * XXX TS_CAR_OFLOW doesn't do anything yet. TS_TTSTOP
1603 * works if IXON and IXANY are clear.
1605 if (flag) {
1606 CLR(tp->t_state, TS_CAR_OFLOW);
1607 CLR(tp->t_state, TS_TTSTOP);
1608 ttstart(tp);
1609 } else if (!ISSET(tp->t_state, TS_CAR_OFLOW)) {
1610 SET(tp->t_state, TS_CAR_OFLOW);
1611 SET(tp->t_state, TS_TTSTOP);
1612 (*tp->t_stop)(tp, 0);
1614 } else if (flag == 0) {
1616 * Lost carrier.
1618 CLR(tp->t_state, TS_CARR_ON);
1619 if (ISSET(tp->t_state, TS_ISOPEN) &&
1620 !ISSET(tp->t_cflag, CLOCAL)) {
1621 SET(tp->t_state, TS_ZOMBIE);
1622 CLR(tp->t_state, TS_CONNECTED);
1623 if (tp->t_session && tp->t_session->s_leader)
1624 ksignal(tp->t_session->s_leader, SIGHUP);
1625 ttyflush(tp, FREAD | FWRITE);
1626 lwkt_reltoken(&tp->t_token);
1627 return (0);
1629 } else {
1631 * Carrier now on.
1633 SET(tp->t_state, TS_CARR_ON);
1634 if (!ISSET(tp->t_state, TS_ZOMBIE))
1635 SET(tp->t_state, TS_CONNECTED);
1636 wakeup(TSA_CARR_ON(tp));
1637 ttwakeup(tp);
1638 ttwwakeup(tp);
1640 lwkt_reltoken(&tp->t_token);
1641 return (1);
1645 * Reinput pending characters after state switch
1647 static void
1648 ttypend(struct tty *tp)
1650 struct clist tq;
1651 int c;
1653 lwkt_gettoken(&tp->t_token);
1654 CLR(tp->t_lflag, PENDIN);
1655 SET(tp->t_state, TS_TYPEN);
1657 * XXX this assumes too much about clist internals. It may even
1658 * fail if the cblock slush pool is empty. We can't allocate more
1659 * cblocks here because we are called from an interrupt handler
1660 * and clist_alloc_cblocks() can wait.
1662 tq = tp->t_rawq;
1663 bzero(&tp->t_rawq, sizeof tp->t_rawq);
1664 clist_alloc_cblocks(&tp->t_rawq, tq.c_ccmax);
1665 while ((c = clist_getc(&tq)) >= 0)
1666 ttyinput(c, tp);
1667 CLR(tp->t_state, TS_TYPEN);
1668 clist_free_cblocks(&tq);
1669 lwkt_reltoken(&tp->t_token);
1673 * Process a read call on a tty device.
1676 ttread(struct tty *tp, struct uio *uio, int flag)
1678 struct clist *qp;
1679 int c;
1680 tcflag_t lflag;
1681 cc_t *cc = tp->t_cc;
1682 struct proc *pp;
1683 struct lwp *lp;
1684 int first, error = 0;
1685 int has_stime = 0, last_cc = 0;
1686 long slp = 0; /* XXX this should be renamed `timo'. */
1687 struct timeval stime;
1689 lp = curthread->td_lwp;
1690 stime.tv_sec = 0; /* fix compiler warnings */
1691 stime.tv_usec = 0;
1693 lwkt_gettoken(&tp->t_token);
1694 loop:
1695 lflag = tp->t_lflag;
1697 * take pending input first
1699 if (ISSET(lflag, PENDIN)) {
1700 ttypend(tp);
1701 splz(); /* reduce latency */
1702 lflag = tp->t_lflag; /* XXX ttypend() clobbers it */
1706 * Hang process if it's in the background.
1708 if ((pp = curproc) != NULL)
1709 lwkt_gettoken(&pp->p_token);
1710 if (pp && isbackground(pp, tp)) {
1711 if (SIGISMEMBER(pp->p_sigignore, SIGTTIN) ||
1712 SIGISMEMBER(lp->lwp_sigmask, SIGTTIN) ||
1713 (pp->p_flags & P_PPWAIT) || pp->p_pgrp->pg_jobc == 0) {
1714 lwkt_reltoken(&pp->p_token);
1715 lwkt_reltoken(&tp->t_token);
1716 return (EIO);
1718 pgsignal(pp->p_pgrp, SIGTTIN, 1);
1719 error = ttysleep(tp, &lbolt, PCATCH, "ttybg2", 0);
1720 if (error) {
1721 lwkt_reltoken(&pp->p_token);
1722 lwkt_reltoken(&tp->t_token);
1723 return (error);
1725 lwkt_reltoken(&pp->p_token);
1726 goto loop;
1728 if (pp)
1729 lwkt_reltoken(&pp->p_token);
1731 if (ISSET(tp->t_state, TS_ZOMBIE)) {
1732 lwkt_reltoken(&tp->t_token);
1733 return (0); /* EOF */
1737 * If canonical, use the canonical queue,
1738 * else use the raw queue.
1740 * (should get rid of clists...)
1742 qp = ISSET(lflag, ICANON) ? &tp->t_canq : &tp->t_rawq;
1744 if (flag & IO_NDELAY) {
1745 if (qp->c_cc > 0)
1746 goto read;
1747 if (!ISSET(lflag, ICANON) && cc[VMIN] == 0) {
1748 lwkt_reltoken(&tp->t_token);
1749 return (0);
1751 lwkt_reltoken(&tp->t_token);
1752 return (EWOULDBLOCK);
1754 if (!ISSET(lflag, ICANON)) {
1755 int m = cc[VMIN];
1756 long t = cc[VTIME];
1757 struct timeval timecopy;
1760 * Check each of the four combinations.
1761 * (m > 0 && t == 0) is the normal read case.
1762 * It should be fairly efficient, so we check that and its
1763 * companion case (m == 0 && t == 0) first.
1764 * For the other two cases, we compute the target sleep time
1765 * into slp.
1767 if (t == 0) {
1768 if (qp->c_cc < m)
1769 goto sleep;
1770 if (qp->c_cc > 0)
1771 goto read;
1773 /* m, t and qp->c_cc are all 0. 0 is enough input. */
1774 lwkt_reltoken(&tp->t_token);
1775 return (0);
1777 t *= 100000; /* time in us */
1778 #define diff(t1, t2) (((t1).tv_sec - (t2).tv_sec) * 1000000 + \
1779 ((t1).tv_usec - (t2).tv_usec))
1780 if (m > 0) {
1781 if (qp->c_cc <= 0)
1782 goto sleep;
1783 if (qp->c_cc >= m)
1784 goto read;
1785 getmicrotime(&timecopy);
1786 if (has_stime == 0) {
1787 /* first character, start timer */
1788 has_stime = 1;
1789 stime = timecopy;
1790 slp = t;
1791 } else if (qp->c_cc > last_cc) {
1792 /* got a character, restart timer */
1793 stime = timecopy;
1794 slp = t;
1795 } else {
1796 /* nothing, check expiration */
1797 slp = t - diff(timecopy, stime);
1798 if (slp <= 0)
1799 goto read;
1801 last_cc = qp->c_cc;
1802 } else { /* m == 0 */
1803 if (qp->c_cc > 0)
1804 goto read;
1805 getmicrotime(&timecopy);
1806 if (has_stime == 0) {
1807 has_stime = 1;
1808 stime = timecopy;
1809 slp = t;
1810 } else {
1811 slp = t - diff(timecopy, stime);
1812 if (slp <= 0) {
1813 /* Timed out, but 0 is enough input. */
1814 lwkt_reltoken(&tp->t_token);
1815 return (0);
1819 #undef diff
1821 * Rounding down may make us wake up just short
1822 * of the target, so we round up.
1823 * The formula is ceiling(slp * hz/1000000).
1824 * 32-bit arithmetic is enough for hz < 169.
1825 * XXX see tvtohz() for how to avoid overflow if hz
1826 * is large (divide by `tick' and/or arrange to
1827 * use tvtohz() if hz is large).
1829 slp = (long) (((u_long)slp * hz) + 999999) / 1000000;
1830 goto sleep;
1832 if (qp->c_cc <= 0) {
1833 sleep:
1835 * There is no input, or not enough input and we can block.
1837 error = ttysleep(tp, TSA_HUP_OR_INPUT(tp), PCATCH,
1838 ISSET(tp->t_state, TS_CONNECTED) ?
1839 "ttyin" : "ttyhup", (int)slp);
1840 if (error == EWOULDBLOCK)
1841 error = 0;
1842 else if (error) {
1843 lwkt_reltoken(&tp->t_token);
1844 return (error);
1847 * XXX what happens if another process eats some input
1848 * while we are asleep (not just here)? It would be
1849 * safest to detect changes and reset our state variables
1850 * (has_stime and last_cc).
1852 slp = 0;
1853 goto loop;
1855 read:
1857 * Input present, check for input mapping and processing.
1859 first = 1;
1860 if (ISSET(lflag, ICANON | ISIG))
1861 goto slowcase;
1862 for (;;) {
1863 char ibuf[IBUFSIZ];
1864 int icc;
1866 icc = (int)szmin(uio->uio_resid, IBUFSIZ);
1867 icc = clist_qtob(qp, ibuf, icc);
1868 if (icc <= 0) {
1869 if (first)
1870 goto loop;
1871 break;
1873 error = uiomove(ibuf, (size_t)icc, uio);
1875 * XXX if there was an error then we should ungetc() the
1876 * unmoved chars and reduce icc here.
1878 if (error)
1879 break;
1880 if (uio->uio_resid == 0)
1881 break;
1882 first = 0;
1884 goto out;
1885 slowcase:
1886 for (;;) {
1887 c = clist_getc(qp);
1888 if (c < 0) {
1889 if (first)
1890 goto loop;
1891 break;
1894 * delayed suspend (^Y)
1896 if (CCEQ(cc[VDSUSP], c) &&
1897 ISSET(lflag, IEXTEN | ISIG) == (IEXTEN | ISIG)) {
1898 pgsignal(tp->t_pgrp, SIGTSTP, 1);
1899 if (first) {
1900 error = ttysleep(tp, &lbolt, PCATCH,
1901 "ttybg3", 0);
1902 if (error)
1903 break;
1904 goto loop;
1906 break;
1909 * Interpret EOF only in canonical mode.
1911 if (CCEQ(cc[VEOF], c) && ISSET(lflag, ICANON))
1912 break;
1914 * Give user character.
1916 error = ureadc(c, uio);
1917 if (error)
1918 /* XXX should ungetc(c, qp). */
1919 break;
1920 if (uio->uio_resid == 0)
1921 break;
1923 * In canonical mode check for a "break character"
1924 * marking the end of a "line of input".
1926 if (ISSET(lflag, ICANON) && TTBREAKC(c, lflag))
1927 break;
1928 first = 0;
1931 out:
1933 * Look to unblock input now that (presumably)
1934 * the input queue has gone down.
1936 if (ISSET(tp->t_state, TS_TBLOCK) &&
1937 tp->t_rawq.c_cc + tp->t_canq.c_cc <= tp->t_ilowat) {
1938 ttyunblock(tp);
1941 lwkt_reltoken(&tp->t_token);
1942 return (error);
1946 * Check the output queue on tp for space for a kernel message (from uprintf
1947 * or tprintf). Allow some space over the normal hiwater mark so we don't
1948 * lose messages due to normal flow control, but don't let the tty run amok.
1949 * Sleeps here are not interruptible, but we return prematurely if new signals
1950 * arrive.
1953 ttycheckoutq(struct tty *tp, int wait)
1955 struct lwp *lp = curthread->td_lwp;
1956 int hiwat;
1957 sigset_t oldset, newset;
1959 lwkt_gettoken(&tp->t_token);
1960 hiwat = tp->t_ohiwat;
1961 SIGEMPTYSET(oldset);
1962 SIGEMPTYSET(newset);
1963 if (wait)
1964 oldset = lwp_sigpend(lp);
1965 if (tp->t_outq.c_cc > hiwat + OBUFSIZ + 100) {
1966 while (tp->t_outq.c_cc > hiwat) {
1967 ttstart(tp);
1968 if (tp->t_outq.c_cc <= hiwat)
1969 break;
1970 if (wait)
1971 newset = lwp_sigpend(lp);
1972 if (!wait || SIGSETNEQ(oldset, newset)) {
1973 lwkt_reltoken(&tp->t_token);
1974 return (0);
1976 SET(tp->t_state, TS_SO_OLOWAT);
1977 tsleep(TSA_OLOWAT(tp), 0, "ttoutq", hz);
1980 lwkt_reltoken(&tp->t_token);
1981 return (1);
1985 * Process a write call on a tty device.
1988 ttwrite(struct tty *tp, struct uio *uio, int flag)
1990 char *cp = NULL;
1991 int cc, ce;
1992 struct proc *pp;
1993 struct lwp *lp;
1994 int i, hiwat, error;
1995 size_t cnt;
1997 char obuf[OBUFSIZ];
1999 lwkt_gettoken(&tp->t_token);
2000 lp = curthread->td_lwp;
2001 hiwat = tp->t_ohiwat;
2002 cnt = uio->uio_resid;
2003 error = 0;
2004 cc = 0;
2005 loop:
2006 if (ISSET(tp->t_state, TS_ZOMBIE)) {
2007 if (uio->uio_resid == cnt)
2008 error = EIO;
2009 goto out;
2011 if (!ISSET(tp->t_state, TS_CONNECTED)) {
2012 if (flag & IO_NDELAY) {
2013 error = EWOULDBLOCK;
2014 goto out;
2016 error = ttysleep(tp, TSA_CARR_ON(tp), PCATCH, "ttydcd", 0);
2017 if (error)
2018 goto out;
2019 goto loop;
2023 * Hang the process if it's in the background.
2025 if ((pp = curproc) != NULL)
2026 lwkt_gettoken(&pp->p_token);
2027 if (pp && isbackground(pp, tp) &&
2028 ISSET(tp->t_lflag, TOSTOP) && !(pp->p_flags & P_PPWAIT) &&
2029 !SIGISMEMBER(pp->p_sigignore, SIGTTOU) &&
2030 !SIGISMEMBER(lp->lwp_sigmask, SIGTTOU)) {
2031 if (pp->p_pgrp->pg_jobc == 0) {
2032 error = EIO;
2033 lwkt_reltoken(&pp->p_token);
2034 goto out;
2036 pgsignal(pp->p_pgrp, SIGTTOU, 1);
2037 lwkt_reltoken(&pp->p_token);
2038 error = ttysleep(tp, &lbolt, PCATCH, "ttybg4", 0);
2039 if (error)
2040 goto out;
2041 goto loop;
2043 if (pp)
2044 lwkt_reltoken(&pp->p_token);
2046 * Process the user's data in at most OBUFSIZ chunks. Perform any
2047 * output translation. Keep track of high water mark, sleep on
2048 * overflow awaiting device aid in acquiring new space.
2050 while (uio->uio_resid > 0 || cc > 0) {
2051 if (ISSET(tp->t_lflag, FLUSHO)) {
2052 uio->uio_resid = 0;
2053 lwkt_reltoken(&tp->t_token);
2054 return (0);
2056 if (tp->t_outq.c_cc > hiwat)
2057 goto ovhiwat;
2059 * Grab a hunk of data from the user, unless we have some
2060 * leftover from last time.
2062 if (cc == 0) {
2063 cc = szmin(uio->uio_resid, OBUFSIZ);
2064 cp = obuf;
2065 error = uiomove(cp, (size_t)cc, uio);
2066 if (error) {
2067 cc = 0;
2068 break;
2072 * If nothing fancy need be done, grab those characters we
2073 * can handle without any of ttyoutput's processing and
2074 * just transfer them to the output q. For those chars
2075 * which require special processing (as indicated by the
2076 * bits in char_type), call ttyoutput. After processing
2077 * a hunk of data, look for FLUSHO so ^O's will take effect
2078 * immediately.
2080 while (cc > 0) {
2081 if (!ISSET(tp->t_oflag, OPOST))
2082 ce = cc;
2083 else {
2084 ce = cc - scanc((u_int)cc, (u_char *)cp,
2085 char_type, CCLASSMASK);
2087 * If ce is zero, then we're processing
2088 * a special character through ttyoutput.
2090 if (ce == 0) {
2091 tp->t_rocount = 0;
2092 if (ttyoutput(*cp, tp) >= 0) {
2093 /* No Clists, wait a bit. */
2094 ttstart(tp);
2095 if (flag & IO_NDELAY) {
2096 error = EWOULDBLOCK;
2097 goto out;
2099 error = ttysleep(tp, &lbolt,
2100 PCATCH,
2101 "ttybf1", 0);
2102 if (error)
2103 goto out;
2104 goto loop;
2106 cp++;
2107 cc--;
2108 if (ISSET(tp->t_lflag, FLUSHO) ||
2109 tp->t_outq.c_cc > hiwat)
2110 goto ovhiwat;
2111 continue;
2115 * A bunch of normal characters have been found.
2116 * Transfer them en masse to the output queue and
2117 * continue processing at the top of the loop.
2118 * If there are any further characters in this
2119 * <= OBUFSIZ chunk, the first should be a character
2120 * requiring special handling by ttyoutput.
2122 tp->t_rocount = 0;
2123 i = clist_btoq(cp, ce, &tp->t_outq);
2124 ce -= i;
2125 tp->t_column += ce;
2126 cp += ce, cc -= ce, tk_nout += ce;
2127 tp->t_outcc += ce;
2128 if (i > 0) {
2129 /* No Clists, wait a bit. */
2130 ttstart(tp);
2131 if (flag & IO_NDELAY) {
2132 error = EWOULDBLOCK;
2133 goto out;
2135 error = ttysleep(tp, &lbolt, PCATCH,
2136 "ttybf2", 0);
2137 if (error)
2138 goto out;
2139 goto loop;
2141 if (ISSET(tp->t_lflag, FLUSHO) ||
2142 tp->t_outq.c_cc > hiwat)
2143 break;
2145 ttstart(tp);
2147 out:
2149 * If cc is nonzero, we leave the uio structure inconsistent, as the
2150 * offset and iov pointers have moved forward, but it doesn't matter
2151 * (the call will either return short or restart with a new uio).
2153 uio->uio_resid += cc;
2154 lwkt_reltoken(&tp->t_token);
2155 return (error);
2157 ovhiwat:
2158 ttstart(tp);
2160 * This can only occur if FLUSHO is set in t_lflag,
2161 * or if ttstart/oproc is synchronous (or very fast).
2163 if (tp->t_outq.c_cc <= hiwat) {
2164 goto loop;
2166 if (flag & IO_NDELAY) {
2167 uio->uio_resid += cc;
2168 lwkt_reltoken(&tp->t_token);
2169 return (uio->uio_resid == cnt ? EWOULDBLOCK : 0);
2171 SET(tp->t_state, TS_SO_OLOWAT);
2172 error = ttysleep(tp, TSA_OLOWAT(tp), PCATCH, "ttywri", tp->t_timeout);
2173 if (error == EWOULDBLOCK)
2174 error = EIO;
2175 if (error)
2176 goto out;
2177 goto loop;
2181 * Rubout one character from the rawq of tp
2182 * as cleanly as possible.
2183 * NOTE: Must be called with tp->t_token held
2185 static void
2186 ttyrub(int c, struct tty *tp)
2188 void *cp;
2189 int savecol;
2190 int tabc;
2192 ASSERT_LWKT_TOKEN_HELD(&tp->t_token);
2193 if (!ISSET(tp->t_lflag, ECHO) || ISSET(tp->t_lflag, EXTPROC))
2194 return;
2195 CLR(tp->t_lflag, FLUSHO);
2196 if (ISSET(tp->t_lflag, ECHOE)) {
2197 if (tp->t_rocount == 0) {
2199 * Screwed by ttwrite; retype
2201 ttyretype(tp);
2202 return;
2204 if (c == ('\t' | TTY_QUOTE) || c == ('\n' | TTY_QUOTE))
2205 ttyrubo(tp, 2);
2206 else {
2207 CLR(c, ~TTY_CHARMASK);
2208 switch (CCLASS(c)) {
2209 case ORDINARY:
2210 ttyrubo(tp, 1);
2211 break;
2212 case BACKSPACE:
2213 case CONTROL:
2214 case NEWLINE:
2215 case RETURN:
2216 case VTAB:
2217 if (ISSET(tp->t_lflag, ECHOCTL))
2218 ttyrubo(tp, 2);
2219 break;
2220 case TAB:
2221 if (tp->t_rocount < tp->t_rawq.c_cc) {
2222 ttyretype(tp);
2223 return;
2225 savecol = tp->t_column;
2226 SET(tp->t_state, TS_CNTTB);
2227 SET(tp->t_lflag, FLUSHO);
2228 tp->t_column = tp->t_rocol;
2230 cp = clist_nextc(&tp->t_rawq, NULL, &tabc);
2231 while (cp) {
2232 ttyecho(tabc, tp);
2233 cp = clist_nextc(&tp->t_rawq,
2234 cp, &tabc);
2236 CLR(tp->t_lflag, FLUSHO);
2237 CLR(tp->t_state, TS_CNTTB);
2239 /* savecol will now be length of the tab. */
2240 savecol -= tp->t_column;
2241 tp->t_column += savecol;
2242 if (savecol > 8)
2243 savecol = 8; /* overflow screw */
2244 while (--savecol >= 0)
2245 (void)ttyoutput('\b', tp);
2246 break;
2247 default: /* XXX */
2248 #define PANICSTR "ttyrub: would panic c = %d, val = %d\n"
2249 (void)kprintf(PANICSTR, c, CCLASS(c));
2250 #ifdef notdef
2251 panic(PANICSTR, c, CCLASS(c));
2252 #endif
2255 } else if (ISSET(tp->t_lflag, ECHOPRT)) {
2256 if (!ISSET(tp->t_state, TS_ERASE)) {
2257 SET(tp->t_state, TS_ERASE);
2258 (void)ttyoutput('\\', tp);
2260 ttyecho(c, tp);
2261 } else {
2262 ttyecho(tp->t_cc[VERASE], tp);
2264 * This code may be executed not only when an ERASE key
2265 * is pressed, but also when ^U (KILL) or ^W (WERASE) are.
2266 * So, I didn't think it was worthwhile to pass the extra
2267 * information (which would need an extra parameter,
2268 * changing every call) needed to distinguish the ERASE2
2269 * case from the ERASE.
2272 --tp->t_rocount;
2276 * Back over cnt characters, erasing them.
2277 * NOTE: Must be called with tp->t_token held
2279 static void
2280 ttyrubo(struct tty *tp, int cnt)
2282 ASSERT_LWKT_TOKEN_HELD(&tp->t_token);
2283 while (cnt-- > 0) {
2284 (void)ttyoutput('\b', tp);
2285 (void)ttyoutput(' ', tp);
2286 (void)ttyoutput('\b', tp);
2291 * ttyretype --
2292 * Reprint the rawq line. Note, it is assumed that c_cc has already
2293 * been checked.
2294 * NOTE: Must be called with tp->t_token held
2296 static void
2297 ttyretype(struct tty *tp)
2299 void *cp;
2300 int c;
2302 ASSERT_LWKT_TOKEN_HELD(&tp->t_token);
2303 /* Echo the reprint character. */
2304 if (tp->t_cc[VREPRINT] != _POSIX_VDISABLE)
2305 ttyecho(tp->t_cc[VREPRINT], tp);
2307 (void)ttyoutput('\n', tp);
2310 * XXX
2311 * FIX: NEXTC IS BROKEN - DOESN'T CHECK QUOTE
2312 * BIT OF FIRST CHAR.
2314 cp = clist_nextc(&tp->t_canq, NULL, &c);
2315 while (cp) {
2316 ttyecho(c, tp);
2317 cp = clist_nextc(&tp->t_canq, cp, &c);
2319 cp = clist_nextc(&tp->t_rawq, NULL, &c);
2320 while (cp) {
2321 ttyecho(c, tp);
2322 cp = clist_nextc(&tp->t_rawq, cp, &c);
2324 CLR(tp->t_state, TS_ERASE);
2326 tp->t_rocount = tp->t_rawq.c_cc;
2327 tp->t_rocol = 0;
2331 * Echo a typed character to the terminal.
2332 * NOTE: Must be called with tp->t_token held
2334 static void
2335 ttyecho(int c, struct tty *tp)
2337 ASSERT_LWKT_TOKEN_HELD(&tp->t_token);
2339 if (!ISSET(tp->t_state, TS_CNTTB))
2340 CLR(tp->t_lflag, FLUSHO);
2341 if ((!ISSET(tp->t_lflag, ECHO) &&
2342 (c != '\n' || !ISSET(tp->t_lflag, ECHONL))) ||
2343 ISSET(tp->t_lflag, EXTPROC))
2344 return;
2345 if (ISSET(tp->t_lflag, ECHOCTL) &&
2346 ((ISSET(c, TTY_CHARMASK) <= 037 && c != '\t' && c != '\n') ||
2347 ISSET(c, TTY_CHARMASK) == 0177)) {
2348 (void)ttyoutput('^', tp);
2349 CLR(c, ~TTY_CHARMASK);
2350 if (c == 0177)
2351 c = '?';
2352 else
2353 c += 'A' - 1;
2355 (void)ttyoutput(c, tp);
2359 * Wake up any readers on a tty.
2361 void
2362 ttwakeup(struct tty *tp)
2364 lwkt_gettoken(&tp->t_token);
2365 if (ISSET(tp->t_state, TS_ASYNC) && tp->t_sigio != NULL)
2366 pgsigio(tp->t_sigio, SIGIO, (tp->t_session != NULL));
2367 wakeup(TSA_HUP_OR_INPUT(tp));
2368 KNOTE(&tp->t_rkq.ki_note, 0);
2369 lwkt_reltoken(&tp->t_token);
2373 * Wake up any writers on a tty.
2375 void
2376 ttwwakeup(struct tty *tp)
2378 lwkt_gettoken(&tp->t_token);
2379 if (ISSET(tp->t_state, TS_ASYNC) && tp->t_sigio != NULL)
2380 pgsigio(tp->t_sigio, SIGIO, (tp->t_session != NULL));
2381 if (ISSET(tp->t_state, TS_BUSY | TS_SO_OCOMPLETE) ==
2382 TS_SO_OCOMPLETE && tp->t_outq.c_cc == 0) {
2383 CLR(tp->t_state, TS_SO_OCOMPLETE);
2384 wakeup(TSA_OCOMPLETE(tp));
2386 if (ISSET(tp->t_state, TS_SO_OLOWAT) &&
2387 tp->t_outq.c_cc <= tp->t_olowat) {
2388 CLR(tp->t_state, TS_SO_OLOWAT);
2389 wakeup(TSA_OLOWAT(tp));
2391 KNOTE(&tp->t_wkq.ki_note, 0);
2392 lwkt_reltoken(&tp->t_token);
2396 * Look up a code for a specified speed in a conversion table;
2397 * used by drivers to map software speed values to hardware parameters.
2398 * No requirements
2401 ttspeedtab(int speed, struct speedtab *table)
2404 for ( ; table->sp_speed != -1; table++)
2405 if (table->sp_speed == speed)
2406 return (table->sp_code);
2407 return (-1);
2411 * Set input and output watermarks and buffer sizes. For input, the
2412 * high watermark is about one second's worth of input above empty, the
2413 * low watermark is slightly below high water, and the buffer size is a
2414 * driver-dependent amount above high water. For output, the watermarks
2415 * are near the ends of the buffer, with about 1 second's worth of input
2416 * between them. All this only applies to the standard line discipline.
2418 #define CLAMP(x, h, l) ((x) > h ? h : ((x) < l) ? l : (x))
2420 void
2421 ttsetwater(struct tty *tp)
2423 int ttmaxhiwat; /* maximum high water mark */
2424 int cps; /* characters per second */
2425 int x;
2427 lwkt_gettoken(&tp->t_token);
2430 * Input side.
2432 * Calculate nominal low and high water marks, leave a little
2433 * room to absorb flow control latencies.
2435 clist_alloc_cblocks(&tp->t_canq, TTYHOG);
2437 switch (tp->t_ispeedwat) {
2438 case (speed_t)-1:
2439 cps = tp->t_ispeed / 10;
2440 break;
2441 case 0:
2443 * This case is for old drivers that don't know about
2444 * t_ispeedwat. Arrange for them to get the old buffer
2445 * sizes and watermarks.
2447 cps = TTYHOG - 2 * 256;
2448 tp->t_ififosize = 2 * 2048;
2449 break;
2450 default:
2451 cps = tp->t_ispeedwat / 10;
2452 break;
2454 tp->t_ihiwat = cps;
2455 tp->t_ilowat = 7 * cps / 8;
2456 x = cps + tp->t_ififosize;
2457 clist_alloc_cblocks(&tp->t_rawq, x);
2460 * Output side.
2462 * Calculate nominal low and high water marks, and make the
2463 * actual buffer just a tad larger to absorb flow control latencies.
2465 switch (tp->t_ospeedwat) {
2466 case (speed_t)-1:
2467 cps = tp->t_ospeed / 10;
2468 ttmaxhiwat = 2 * TTMAXHIWAT;
2469 break;
2470 case 0:
2471 cps = tp->t_ospeed / 10;
2472 ttmaxhiwat = TTMAXHIWAT;
2473 break;
2474 default:
2475 cps = tp->t_ospeedwat / 10;
2476 ttmaxhiwat = 8 * TTMAXHIWAT;
2477 break;
2480 x = CLAMP(cps / 2, TTMAXLOWAT, TTMINLOWAT);
2481 tp->t_olowat = x;
2483 x += cps;
2484 x = CLAMP(x, ttmaxhiwat, TTMINHIWAT);
2485 tp->t_ohiwat = x;
2487 x = imax(tp->t_ohiwat, TTMAXHIWAT);
2488 x += OBUFSIZ + 100;
2489 clist_alloc_cblocks(&tp->t_outq, x);
2491 lwkt_reltoken(&tp->t_token);
2494 #undef CLAMP
2497 * Report on state of foreground process group.
2499 void
2500 ttyinfo(struct tty *tp)
2502 struct pgrp *pgrp;
2503 struct proc *p, *pick;
2504 struct lwp *lp;
2505 struct rusage ru;
2506 char buf[64];
2507 const char *str;
2508 struct vmspace *vm;
2509 long vmsz;
2510 int pctcpu;
2511 int tmp;
2513 if (ttycheckoutq(tp,0) == 0)
2514 return;
2516 lwkt_gettoken(&tp->t_token);
2519 * We always print the load average, then figure out what else to
2520 * print based on the state of the current process group.
2522 tmp = (averunnable.ldavg[0] * 100 + FSCALE / 2) >> FSHIFT;
2523 ttyprintf(tp, "load: %d.%02d ", tmp / 100, tmp % 100);
2525 if (tp->t_session == NULL) {
2526 ttyprintf(tp, "not a controlling terminal\n");
2527 goto done2;
2529 if ((pgrp = tp->t_pgrp) == NULL) {
2530 ttyprintf(tp, "no foreground process group\n");
2531 goto done2;
2535 * Pick an interesting process. Note that certain elements,
2536 * in particular the wmesg.
2538 * NOTE: lwp_wmesg is lwp_thread->td_wmesg.
2540 pgref(pgrp);
2541 lwkt_gettoken(&pgrp->pg_token);
2543 pick = NULL;
2544 for (p = LIST_FIRST(&pgrp->pg_members);
2545 p != NULL;
2546 p = LIST_NEXT(p, p_pglist)) {
2547 PHOLD(p);
2548 if (proc_compare(pick, p)) {
2549 if (pick)
2550 PRELE(pick);
2551 pick = p;
2552 } else {
2553 PRELE(p);
2556 if (pick == NULL) {
2557 ttyprintf(tp, "empty foreground process group\n");
2558 goto done1;
2562 * Pick an interesting LWP (XXX)
2564 * pick is held.
2566 lp = FIRST_LWP_IN_PROC(pick);
2567 if (lp == NULL) {
2568 PRELE(pick);
2569 ttyprintf(tp, "foreground process without lwp\n");
2570 goto done1;
2574 * Figure out what wait/process-state message, and command
2575 * buffer to present
2578 * XXX lwp This is a horrible mixture. We need to rework this
2579 * as soon as lwps have their own runnable status.
2581 LWPHOLD(lp);
2582 if (pick->p_flags & P_WEXIT)
2583 str = "exiting";
2584 else if (lp->lwp_stat == LSRUN)
2585 str = "running";
2586 else if (pick->p_stat == SIDL)
2587 str = "spawning";
2588 else if (lp->lwp_wmesg) /* lwp_thread must not be NULL */
2589 str = lp->lwp_wmesg;
2590 else
2591 str = "iowait";
2593 ksnprintf(buf, sizeof(buf), "cmd: %s %d [%s]",
2594 pick->p_comm, pick->p_pid, str);
2597 * Calculate cpu usage, percent cpu, and cmsz. Note that
2598 * 'pick' becomes invalid the moment we release the token.
2600 if (lp->lwp_thread)
2601 calcru_proc(pick, &ru);
2603 pctcpu = (lp->lwp_pctcpu * 10000 + FSCALE / 2) >> FSHIFT;
2605 LWPRELE(lp);
2608 * NOTE: vmspace should be protected from destruction by the
2609 * combination of pg_token and the fact that we are not
2610 * flagged as a zombie.
2612 if (pick->p_stat == SIDL || pick->p_stat == SZOMB) {
2613 vmsz = 0;
2614 } else if ((vm = pick->p_vmspace) == NULL) {
2615 vmsz = 0;
2616 } else {
2617 vmspace_hold(vm);
2618 vmsz = pgtok(vmspace_resident_count(vm));
2619 vmspace_drop(vm);
2621 PRELE(pick);
2624 * Dump the output
2626 ttyprintf(tp, " %s ",
2627 buf);
2628 ttyprintf(tp, "%ld.%02ldu ",
2629 ru.ru_utime.tv_sec, ru.ru_utime.tv_usec / 10000);
2630 ttyprintf(tp, "%ld.%02lds ",
2631 ru.ru_stime.tv_sec, ru.ru_stime.tv_usec / 10000);
2632 ttyprintf(tp, "%d%% %ldk\n",
2633 pctcpu / 100, vmsz);
2635 done1:
2636 lwkt_reltoken(&pgrp->pg_token);
2637 pgrel(pgrp);
2638 done2:
2639 tp->t_rocount = 0; /* so pending input will be retyped if BS */
2640 lwkt_reltoken(&tp->t_token);
2644 * Returns 1 if p2 is "better" than p1
2646 * The algorithm for picking the "interesting" process is thus:
2648 * 1) Only foreground processes are eligible - implied.
2649 * 2) Runnable processes are favored over anything else. The runner
2650 * with the highest cpu utilization is picked (p_cpticks). Ties are
2651 * broken by picking the highest pid.
2652 * 3) The sleeper with the shortest sleep time is next. With ties,
2653 * we pick out just "short-term" sleepers (LWP_SINTR == 0).
2654 * 4) Further ties are broken by picking the highest pid.
2656 * NOTE: must be called with p1 and p2 held.
2658 #define ISRUN(lp) ((lp)->lwp_stat == LSRUN)
2659 #define TESTAB(a, b) ((a)<<1 | (b))
2660 #define ONLYA 2
2661 #define ONLYB 1
2662 #define BOTH 3
2664 static int
2665 proc_compare(struct proc *p1, struct proc *p2)
2667 struct lwp *lp1, *lp2;
2668 int res;
2670 if (p1 == NULL)
2671 return (1);
2672 if (lwkt_trytoken(&p1->p_token) == 0)
2673 return (1);
2674 if (lwkt_trytoken(&p2->p_token) == 0) {
2675 lwkt_reltoken(&p1->p_token);
2676 return (0);
2680 * weed out zombies
2682 switch (TESTAB(p1->p_stat == SZOMB, p2->p_stat == SZOMB)) {
2683 case ONLYA:
2684 res = 1;
2685 goto done;
2686 case ONLYB:
2687 res = 0;
2688 goto done;
2689 case BOTH:
2690 res = (p2->p_pid > p1->p_pid); /* tie - return highest pid */
2691 goto done;
2692 default:
2693 break;
2696 /* XXX choose the best lwp? */
2697 lp1 = FIRST_LWP_IN_PROC(p1);
2698 lp2 = FIRST_LWP_IN_PROC(p2);
2701 * Favor one with LWPs verses one that has none (is exiting).
2703 if (lp1 == NULL) {
2704 res = 1;
2705 goto done;
2707 if (lp2 == NULL) {
2708 res = 0;
2709 goto done;
2713 * see if at least one of them is runnable
2715 switch (TESTAB(ISRUN(lp1), ISRUN(lp2))) {
2716 case ONLYA:
2717 res = 0;
2718 goto done;
2719 case ONLYB:
2720 res = 1;
2721 goto done;
2722 case BOTH:
2724 * tie - favor one with highest recent cpu utilization
2726 if (lp2->lwp_cpticks > lp1->lwp_cpticks)
2727 res = 1;
2728 else if (lp1->lwp_cpticks > lp2->lwp_cpticks)
2729 res = 0;
2730 else
2731 res = (p2->p_pid > p1->p_pid); /* tie - ret highest */
2732 goto done;
2733 default:
2734 break;
2738 * Pick the one with the smallest sleep time
2740 if (lp2->lwp_slptime > lp1->lwp_slptime) {
2741 res = 0;
2742 goto done;
2744 if (lp1->lwp_slptime > lp2->lwp_slptime) {
2745 res = 1;
2746 goto done;
2750 * Favor one sleeping in a non-interruptible sleep
2752 if ((lp1->lwp_flags & LWP_SINTR) && (lp2->lwp_flags & LWP_SINTR) == 0)
2753 res = 1;
2754 else
2755 if ((lp2->lwp_flags & LWP_SINTR) && (lp1->lwp_flags & LWP_SINTR) == 0)
2756 res = 0;
2757 else
2758 res = (p2->p_pid > p1->p_pid); /* tie - return highest pid */
2759 /* fall through */
2761 done:
2762 lwkt_reltoken(&p2->p_token);
2763 lwkt_reltoken(&p1->p_token);
2764 return (res);
2768 * Output char to tty; console putchar style.
2771 tputchar(int c, struct tty *tp)
2773 lwkt_gettoken(&tp->t_token);
2774 if (!ISSET(tp->t_state, TS_CONNECTED)) {
2775 lwkt_reltoken(&tp->t_token);
2776 return (-1);
2778 if (c == '\n')
2779 (void)ttyoutput('\r', tp);
2780 (void)ttyoutput(c, tp);
2781 ttstart(tp);
2782 lwkt_reltoken(&tp->t_token);
2784 return (0);
2788 * Sleep on chan, returning ERESTART if tty changed while we napped and
2789 * returning any errors (e.g. EINTR/EWOULDBLOCK) reported by tsleep. If
2790 * the tty is revoked, restarting a pending call will redo validation done
2791 * at the start of the call.
2794 ttysleep(struct tty *tp, void *chan, int slpflags, char *wmesg, int timo)
2796 int error;
2797 int gen;
2799 gen = tp->t_gen;
2800 error = tsleep(chan, slpflags, wmesg, timo);
2801 if (error)
2802 return (error);
2803 return (tp->t_gen == gen ? 0 : ERESTART);
2807 * Revoke a tty.
2809 * We bump the gen to force any ttysleep()'s to return with ERESTART
2810 * and flush the tty. The related fp's should already have been
2811 * replaced so the tty will close when the last references on the
2812 * original fp's go away.
2815 ttyrevoke(struct dev_revoke_args *ap)
2817 struct tty *tp;
2819 tp = ap->a_head.a_dev->si_tty;
2820 lwkt_gettoken(&tp->t_token);
2821 tp->t_gen++;
2822 ttyflush(tp, FREAD | FWRITE);
2823 wakeup(TSA_CARR_ON(tp));
2824 ttwakeup(tp);
2825 ttwwakeup(tp);
2826 lwkt_reltoken(&tp->t_token);
2828 return (0);
2832 * Allocate a tty struct. Clists in the struct will be allocated by
2833 * ttyopen(). The tty itself is protected by tp->t_token. tty_token
2834 * is primarily used to interlock the NULL test and for registration.
2836 * by convention, once allocated, tty structures are never freed. This
2837 * saves us from numerous release race scenarios that can occur due to the
2838 * token being embedded in the tty structure.
2840 struct tty *
2841 ttymalloc(struct tty **tpp)
2843 struct tty *tp;
2845 if ((tp = *tpp) == NULL) {
2846 tp = kmalloc(sizeof *tp, M_TTYS, M_WAITOK|M_ZERO);
2847 lwkt_gettoken(&tty_token);
2848 if (*tpp == NULL) { /* recheck after blocking kmalloc */
2849 *tpp = tp;
2850 ttyinit(tp);
2851 ttyregister(tp);
2852 } else {
2853 kfree(tp, M_TTYS);
2855 lwkt_reltoken(&tty_token);
2857 return (tp);
2861 * Caller must hold tp->t_token
2863 void
2864 ttyunregister(struct tty *tp)
2866 lwkt_gettoken(&tty_token);
2867 if (ISSET(tp->t_state, TS_REGISTERED)) {
2868 CLR(tp->t_state, TS_REGISTERED);
2869 TAILQ_REMOVE(&tty_list, tp, t_list);
2871 lwkt_reltoken(&tty_token);
2874 void
2875 ttyinit(struct tty *tp)
2877 lwkt_token_init(&tp->t_token, "tp");
2880 void
2881 ttyregister(struct tty *tp)
2883 lwkt_gettoken(&tty_token);
2884 if (!ISSET(tp->t_state, TS_REGISTERED)) {
2885 SET(tp->t_state, TS_REGISTERED);
2886 TAILQ_INSERT_HEAD(&tty_list, tp, t_list);
2888 lwkt_reltoken(&tty_token);
2891 static int
2892 sysctl_kern_ttys(SYSCTL_HANDLER_ARGS)
2894 int error;
2895 struct tty *tp;
2896 struct tty t;
2897 struct tty marker;
2899 bzero(&marker, sizeof(marker));
2900 marker.t_state = TS_MARKER;
2901 error = 0;
2903 lwkt_gettoken(&tty_token);
2905 TAILQ_INSERT_HEAD(&tty_list, &marker, t_list);
2906 while ((tp = TAILQ_NEXT(&marker, t_list)) != NULL) {
2907 TAILQ_REMOVE(&tty_list, &marker, t_list);
2908 TAILQ_INSERT_AFTER(&tty_list, tp, &marker, t_list);
2909 if (tp->t_state & TS_MARKER)
2910 continue;
2911 t = *tp;
2912 if (t.t_dev)
2913 t.t_dev = (cdev_t)(uintptr_t)devid_from_dev(t.t_dev);
2914 error = SYSCTL_OUT(req, (caddr_t)&t, sizeof(t));
2915 if (error)
2916 break;
2918 TAILQ_REMOVE(&tty_list, &marker, t_list);
2919 lwkt_reltoken(&tty_token);
2920 return (error);
2923 SYSCTL_PROC(_kern, OID_AUTO, ttys, CTLTYPE_OPAQUE|CTLFLAG_RD,
2924 0, 0, sysctl_kern_ttys, "S,tty", "All struct ttys");
2926 void
2927 nottystop(struct tty *tp, int rw)
2929 return;
2933 ttyread(struct dev_read_args *ap)
2935 struct tty *tp;
2936 int ret;
2938 tp = ap->a_head.a_dev->si_tty;
2939 if (tp == NULL)
2940 return (ENODEV);
2941 lwkt_gettoken(&tp->t_token);
2942 ret = ((*linesw[tp->t_line].l_read)(tp, ap->a_uio, ap->a_ioflag));
2943 lwkt_reltoken(&tp->t_token);
2945 return ret;
2949 ttywrite(struct dev_write_args *ap)
2951 struct tty *tp;
2952 int ret;
2954 tp = ap->a_head.a_dev->si_tty;
2955 if (tp == NULL)
2956 return (ENODEV);
2957 lwkt_gettoken(&tp->t_token);
2958 ret = ((*linesw[tp->t_line].l_write)(tp, ap->a_uio, ap->a_ioflag));
2959 lwkt_reltoken(&tp->t_token);
2961 return ret;