nrelease - fix/improve livecd
[dragonfly.git] / sys / kern / tty.c
CommitLineData
984263bc 1/*-
22ff886e
AH
2 * (MPSAFE)
3 *
984263bc
MD
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.
11 *
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.
dc71b7ab 20 * 3. Neither the name of the University nor the names of its contributors
984263bc
MD
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
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.
35 *
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 $
38 */
39
22ff886e
AH
40/*
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.
44 */
45
984263bc
MD
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().
72 */
73
984263bc
MD
74#include "opt_uconsole.h"
75
76#include <sys/param.h>
77#include <sys/systm.h>
13dd34d8 78#include <sys/uio.h>
984263bc 79#include <sys/filio.h>
805c8e8e 80#include <sys/malloc.h>
984263bc 81#include <sys/proc.h>
2b3f93ea 82#include <sys/caps.h>
984263bc 83#include <sys/tty.h>
937ccd40
SW
84#define TTYDEFCHARS
85#include <sys/ttydefaults.h> /* for ttydefchars, CEOT */
984263bc
MD
86#undef TTYDEFCHARS
87#include <sys/fcntl.h>
88#include <sys/conf.h>
89#include <sys/dkstat.h>
984263bc
MD
90#include <sys/kernel.h>
91#include <sys/vnode.h>
92#include <sys/signalvar.h>
b1b4e5a6 93#include <sys/signal2.h>
984263bc 94#include <sys/resourcevar.h>
984263bc
MD
95#include <sys/filedesc.h>
96#include <sys/sysctl.h>
8dda877a 97#include <sys/thread2.h>
984263bc
MD
98
99#include <vm/vm.h>
100#include <sys/lock.h>
101#include <vm/pmap.h>
102#include <vm/vm_map.h>
197b441c 103#include <vm/vm_extern.h>
984263bc
MD
104
105MALLOC_DEFINE(M_TTYS, "ttys", "tty data structures");
106
402ed7e1
RG
107static int proc_compare (struct proc *p1, struct proc *p2);
108static int ttnread (struct tty *tp);
109static void ttyecho (int c, struct tty *tp);
110static int ttyoutput (int c, struct tty *tp);
111static void ttypend (struct tty *tp);
112static void ttyretype (struct tty *tp);
113static void ttyrub (int c, struct tty *tp);
114static void ttyrubo (struct tty *tp, int cnt);
115static void ttyunblock (struct tty *tp);
116static int ttywflush (struct tty *tp);
117static int filt_ttyread (struct knote *kn, long hint);
118static void filt_ttyrdetach (struct knote *kn);
119static int filt_ttywrite (struct knote *kn, long hint);
120static void filt_ttywdetach (struct knote *kn);
984263bc
MD
121
122/*
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.
128 */
129#define E 0x00 /* Even parity. */
130#define O 0x80 /* Odd parity. */
131#define PARITY(c) (char_type[c] & O)
132
133#define ALPHA 0x40 /* Alpha or underscore. */
134#define ISALPHA(c) (char_type[(c) & TTY_CHARMASK] & ALPHA)
135
136#define CCLASSMASK 0x3f
137#define CCLASS(c) (char_type[c] & CCLASSMASK)
138
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
147
148static 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 */
165 /*
166 * Meta chars; should be settable per character set;
167 * for now, treat them all as normal characters.
168 */
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,
185};
186#undef BS
187#undef CC
188#undef CR
189#undef NA
190#undef NL
191#undef NO
192#undef TB
193#undef VT
194
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))
199
200#undef MAX_INPUT /* XXX wrong in <sys/syslimits.h> */
201#define MAX_INPUT TTYHOG /* XXX limit is usually larger for !ICANON */
202
f5d21610
JS
203uint64_t tk_nin;
204SYSCTL_OPAQUE(_kern, OID_AUTO, tk_nin, CTLFLAG_RD, &tk_nin, sizeof(tk_nin),
205 "LU", "TTY input statistic");
206uint64_t tk_nout;
207SYSCTL_OPAQUE(_kern, OID_AUTO, tk_nout, CTLFLAG_RD, &tk_nout, sizeof(tk_nout),
208 "LU", "TTY output statistic");
209uint64_t tk_rawcc;
210
984263bc
MD
211/*
212 * list of struct tty where pstat(8) can pick it up with sysctl
213 */
ddac2002 214static TAILQ_HEAD(, tty) tty_list = TAILQ_HEAD_INITIALIZER(tty_list);
984263bc
MD
215
216/*
217 * Initial open of tty, or (re)entry to standard tty line discipline.
218 */
219int
c972a82f 220ttyopen(cdev_t device, struct tty *tp)
984263bc 221{
2efb75f3 222 lwkt_gettoken(&tp->t_token);
984263bc
MD
223 tp->t_dev = device;
224 if (!ISSET(tp->t_state, TS_ISOPEN)) {
225 SET(tp->t_state, TS_ISOPEN);
cd29885a 226 if (ISSET(tp->t_cflag, CLOCAL)) {
984263bc 227 SET(tp->t_state, TS_CONNECTED);
cd29885a 228 }
984263bc
MD
229 bzero(&tp->t_winsize, sizeof(tp->t_winsize));
230 }
231 ttsetwater(tp);
2efb75f3
MD
232 lwkt_reltoken(&tp->t_token);
233
984263bc
MD
234 return (0);
235}
236
237/*
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.
8b90699b 241 *
984263bc
MD
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.
245 */
246int
c972a82f 247ttyclose(struct tty *tp)
984263bc 248{
2efb75f3 249 lwkt_gettoken(&tp->t_token);
58c2553a 250 funsetown(&tp->t_sigio);
984263bc
MD
251 if (constty == tp)
252 constty = NULL;
253
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);
258
259 tp->t_gen++;
260 tp->t_line = TTYDISC;
8b90699b 261 ttyclearsession(tp);
ddac2002 262 tp->t_state &= TS_REGISTERED; /* clear all bits except */
2efb75f3
MD
263 lwkt_reltoken(&tp->t_token);
264
984263bc
MD
265 return (0);
266}
267
8b90699b
MD
268/*
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.
273 *
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.
277 */
278void
279ttyclearsession(struct tty *tp)
280{
281 struct session *sp;
2efb75f3 282 struct procglob *prg;
58c2553a 283 struct pgrp *opgrp;
8b90699b 284
2efb75f3 285 lwkt_gettoken(&tp->t_token);
58c2553a 286 opgrp = tp->t_pgrp;
8b90699b 287 tp->t_pgrp = NULL;
58c2553a
MD
288 if (opgrp) {
289 pgrel(opgrp);
290 opgrp = NULL;
291 }
292
2efb75f3 293again:
8b90699b 294 if ((sp = tp->t_session) != NULL) {
2efb75f3
MD
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;
300 }
8b90699b 301 tp->t_session = NULL;
2efb75f3 302
8b90699b
MD
303#ifdef TTY_DO_FULL_CLOSE
304 /* FULL CLOSE (not yet) */
305 if (sp->s_ttyp == tp) {
306 sp->s_ttyp = NULL;
94a6eea8 307 ttyunhold(tp);
8b90699b 308 } else {
6ea70f76 309 kprintf("ttyclearsession: warning: sp->s_ttyp != tp "
8b90699b
MD
310 "%p/%p\n", sp->s_ttyp, tp);
311 }
312#endif
2efb75f3 313 lwkt_reltoken(&prg->proc_token);
8b90699b 314 }
2efb75f3 315 lwkt_reltoken(&tp->t_token);
8b90699b
MD
316}
317
5fd012e0 318/*
f1aeb0c0 319 * Release the tty vnode association for a session. This is the
84cca6ec
MD
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.
f1aeb0c0
MD
323 *
324 * If dorevoke is non-zero, the session is also revoked. We have to
325 * close the vnode if VCTTYISOPEN is set.
5fd012e0
MD
326 */
327void
f1aeb0c0 328ttyclosesession(struct session *sp, int dorevoke)
5fd012e0
MD
329{
330 struct vnode *vp;
2efb75f3 331 struct procglob *prg;
5fd012e0 332
2efb75f3
MD
333 prg = sp->s_prg;
334 lwkt_gettoken(&prg->proc_token);
f1aeb0c0
MD
335retry:
336 /*
337 * There may not be a controlling terminal or it may have been closed
338 * out from under us.
339 */
22ff886e 340 if ((vp = sp->s_ttyvp) == NULL) {
2efb75f3 341 lwkt_reltoken(&prg->proc_token);
5fd012e0 342 return;
22ff886e 343 }
f1aeb0c0
MD
344
345 /*
346 * We need a lock if we have to close or revoke.
347 */
348 if ((vp->v_flag & VCTTYISOPEN) || dorevoke) {
349 vhold(vp);
b458d1ab 350 if (vn_lock(vp, LK_EXCLUSIVE | LK_RETRY | LK_FAILRECLAIM)) {
f1aeb0c0
MD
351 vdrop(vp);
352 goto retry;
353 }
354
355 /*
356 * Retry if the vnode was ripped out from under us
357 */
358 if (vp != sp->s_ttyvp) {
359 vn_unlock(vp);
360 vdrop(vp);
361 goto retry;
362 }
363
364 /*
365 * Close and revoke as needed
366 */
367 sp->s_ttyvp = NULL;
368 if (vp->v_flag & VCTTYISOPEN) {
5fd012e0 369 vclrflags(vp, VCTTYISOPEN);
3596743e 370 VOP_CLOSE(vp, FREAD|FWRITE, NULL);
5fd012e0 371 }
f1aeb0c0 372 vn_unlock(vp);
b8477cda
MD
373 if (dorevoke)
374 vrevoke(vp, proc0.p_ucred);
f1aeb0c0
MD
375 vdrop(vp);
376 } else {
377 sp->s_ttyvp = NULL;
5fd012e0 378 }
f1aeb0c0 379 vrele(vp);
2efb75f3 380 lwkt_reltoken(&prg->proc_token);
5fd012e0
MD
381}
382
984263bc
MD
383#define FLUSHQ(q) { \
384 if ((q)->c_cc) \
385 ndflush(q, (q)->c_cc); \
386}
387
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))
393
394/*
395 * Process input of a single character received on a tty.
396 */
397int
c972a82f 398ttyinput(int c, struct tty *tp)
984263bc 399{
1fd87d54
RG
400 tcflag_t iflag, lflag;
401 cc_t *cc;
984263bc
MD
402 int i, err;
403
2efb75f3 404 lwkt_gettoken(&tp->t_token);
984263bc
MD
405 /*
406 * If input is pending take it first.
407 */
408 lflag = tp->t_lflag;
409 if (ISSET(lflag, PENDIN))
410 ttypend(tp);
411 /*
412 * Gather stats.
413 */
f5d21610 414 if (ISSET(lflag, ICANON))
984263bc 415 ++tp->t_cancc;
f5d21610 416 else
984263bc 417 ++tp->t_rawcc;
984263bc
MD
418 ++tk_nin;
419
420 /*
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.
425 */
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);
432
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)) {
22ff886e 439 if (ISSET(iflag, IGNBRK)) {
2efb75f3 440 lwkt_reltoken(&tp->t_token);
984263bc 441 return (0);
22ff886e 442 }
984263bc
MD
443 if (ISSET(iflag, BRKINT)) {
444 ttyflush(tp, FREAD | FWRITE);
445 pgsignal(tp->t_pgrp, SIGINT, 1);
446 goto endcase;
447 }
448 if (ISSET(iflag, PARMRK))
449 goto parmrk;
450 } else if ((ISSET(err, TTY_PE) && ISSET(iflag, INPCK))
451 || ISSET(err, TTY_FE)) {
22ff886e 452 if (ISSET(iflag, IGNPAR)) {
2efb75f3 453 lwkt_reltoken(&tp->t_token);
984263bc 454 return (0);
22ff886e 455 }
984263bc
MD
456 else if (ISSET(iflag, PARMRK)) {
457parmrk:
458 if (tp->t_rawq.c_cc + tp->t_canq.c_cc >
459 MAX_INPUT - 3)
460 goto input_overflow;
0ced1954
MD
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);
984263bc
MD
464 goto endcase;
465 } else
466 c = 0;
467 }
468 }
469
470 if (!ISSET(tp->t_state, TS_TYPEN) && ISSET(iflag, ISTRIP))
471 CLR(c, 0x80);
472 if (!ISSET(lflag, EXTPROC)) {
473 /*
474 * Check for literal nexting very first
475 */
476 if (ISSET(tp->t_state, TS_LNCH)) {
477 SET(c, TTY_QUOTE);
478 CLR(tp->t_state, TS_LNCH);
479 }
480 /*
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.
486 */
487
488 /*
489 * Control chars which aren't controlled
490 * by ICANON, ISIG, or IXON.
491 */
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);
500 }
501 SET(tp->t_state, TS_LNCH);
502 goto endcase;
503 }
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);
513 }
514 goto startoutput;
515 }
516 }
517 /*
518 * Signals.
519 */
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;
528 }
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;
535 }
536 }
537 /*
538 * Handle start/stop characters.
539 */
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);
2efb75f3 545 lwkt_reltoken(&tp->t_token);
984263bc
MD
546 return (0);
547 }
22ff886e 548 if (!CCEQ(cc[VSTART], c)) {
2efb75f3 549 lwkt_reltoken(&tp->t_token);
984263bc 550 return (0);
22ff886e 551 }
984263bc
MD
552 /*
553 * if VSTART == VSTOP then toggle
554 */
555 goto endcase;
556 }
557 if (CCEQ(cc[VSTART], c))
558 goto restartoutput;
559 }
560 /*
561 * IGNCR, ICRNL, & INLCR
562 */
563 if (c == '\r') {
22ff886e 564 if (ISSET(iflag, IGNCR)) {
2efb75f3 565 lwkt_reltoken(&tp->t_token);
984263bc 566 return (0);
22ff886e 567 }
984263bc
MD
568 else if (ISSET(iflag, ICRNL))
569 c = '\n';
570 } else if (c == '\n' && ISSET(iflag, INLCR))
571 c = '\r';
572 }
573 if (!ISSET(tp->t_lflag, EXTPROC) && ISSET(lflag, ICANON)) {
574 /*
575 * From here on down canonical mode character
576 * processing takes place.
577 */
578 /*
579 * erase or erase2 (^H / ^?)
580 */
581 if (CCEQ(cc[VERASE], c) || CCEQ(cc[VERASE2], c) ) {
582 if (tp->t_rawq.c_cc)
0ced1954 583 ttyrub(clist_unputc(&tp->t_rawq), tp);
984263bc
MD
584 goto endcase;
585 }
586 /*
587 * kill (^U)
588 */
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)
0ced1954 594 ttyrub(clist_unputc(&tp->t_rawq), tp);
984263bc
MD
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;
602 }
603 CLR(tp->t_state, TS_LOCAL);
604 goto endcase;
605 }
606 /*
607 * word erase (^W)
608 */
609 if (CCEQ(cc[VWERASE], c) && ISSET(lflag, IEXTEN)) {
610 int ctype;
611
612 /*
613 * erase whitespace
614 */
0ced1954 615 while ((c = clist_unputc(&tp->t_rawq)) == ' ' || c == '\t')
984263bc
MD
616 ttyrub(c, tp);
617 if (c == -1)
618 goto endcase;
619 /*
620 * erase last char of word and remember the
621 * next chars type (for ALTWERASE)
622 */
623 ttyrub(c, tp);
0ced1954 624 c = clist_unputc(&tp->t_rawq);
984263bc
MD
625 if (c == -1)
626 goto endcase;
627 if (c == ' ' || c == '\t') {
0ced1954 628 clist_putc(c, &tp->t_rawq);
984263bc
MD
629 goto endcase;
630 }
631 ctype = ISALPHA(c);
632 /*
633 * erase rest of word
634 */
635 do {
636 ttyrub(c, tp);
0ced1954 637 c = clist_unputc(&tp->t_rawq);
984263bc
MD
638 if (c == -1)
639 goto endcase;
640 } while (c != ' ' && c != '\t' &&
641 (!ISSET(lflag, ALTWERASE) || ISALPHA(c) == ctype));
0ced1954 642 clist_putc(c, &tp->t_rawq);
984263bc
MD
643 goto endcase;
644 }
645 /*
646 * reprint line (^R)
647 */
648 if (CCEQ(cc[VREPRINT], c) && ISSET(lflag, IEXTEN)) {
649 ttyretype(tp);
650 goto endcase;
651 }
652 /*
653 * ^T - kernel info and generate SIGINFO
654 */
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;
661 }
dcf5aa01
MD
662 if (CCEQ(cc[VCHECKPT], c) && ISSET(lflag, IEXTEN)) {
663 if (ISSET(lflag, ISIG))
664 pgsignal(tp->t_pgrp, SIGCKPT, 1);
665 goto endcase;
666 }
984263bc
MD
667 }
668 /*
669 * Check for input buffer overflow
670 */
671 if (tp->t_rawq.c_cc + tp->t_canq.c_cc >= MAX_INPUT) {
672input_overflow:
673 if (ISSET(iflag, IMAXBEL)) {
674 if (tp->t_outq.c_cc < tp->t_ohiwat)
675 (void)ttyoutput(CTRL('g'), tp);
676 }
677 goto endcase;
678 }
679
e5117602
MD
680 if (c == 0377 && ISSET(iflag, PARMRK) && !ISSET(iflag, ISTRIP) &&
681 ISSET(iflag, IGNBRK|IGNPAR) != (IGNBRK|IGNPAR)) {
0ced1954 682 clist_putc(0377 | TTY_QUOTE, &tp->t_rawq);
e5117602 683 }
984263bc
MD
684
685 /*
686 * Put data char in q for user and
687 * wakeup on seeing a line delimiter.
688 */
0ced1954 689 if (clist_putc(c, &tp->t_rawq) >= 0) {
984263bc
MD
690 if (!ISSET(lflag, ICANON)) {
691 ttwakeup(tp);
692 ttyecho(c, tp);
693 goto endcase;
694 }
695 if (TTBREAKC(c, lflag)) {
696 tp->t_rocount = 0;
4725869b 697 clist_catq(&tp->t_rawq, &tp->t_canq);
984263bc
MD
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)) {
702 /*
703 * end of prterase \.../
704 */
705 CLR(tp->t_state, TS_ERASE);
706 (void)ttyoutput('/', tp);
707 }
708 i = tp->t_column;
709 ttyecho(c, tp);
710 if (CCEQ(cc[VEOF], c) && ISSET(lflag, ECHO)) {
711 /*
712 * Place the cursor over the '^' of the ^D.
713 */
714 i = imin(2, tp->t_column - i);
715 while (i > 0) {
716 (void)ttyoutput('\b', tp);
717 i--;
718 }
719 }
720 }
721endcase:
722 /*
723 * IXANY means allow any character to restart output.
724 */
725 if (ISSET(tp->t_state, TS_TTSTOP) &&
22ff886e 726 !ISSET(iflag, IXANY) && cc[VSTART] != cc[VSTOP]) {
2efb75f3 727 lwkt_reltoken(&tp->t_token);
984263bc 728 return (0);
22ff886e 729 }
984263bc
MD
730restartoutput:
731 CLR(tp->t_lflag, FLUSHO);
732 CLR(tp->t_state, TS_TTSTOP);
733startoutput:
2efb75f3 734 lwkt_reltoken(&tp->t_token);
984263bc
MD
735 return (ttstart(tp));
736}
737
738/*
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.
743 */
744static int
c972a82f 745ttyoutput(int c, struct tty *tp)
984263bc 746{
1fd87d54 747 tcflag_t oflag;
e43a034f 748 int col;
984263bc 749
2efb75f3 750 lwkt_gettoken(&tp->t_token);
984263bc
MD
751 oflag = tp->t_oflag;
752 if (!ISSET(oflag, OPOST)) {
22ff886e 753 if (ISSET(tp->t_lflag, FLUSHO)) {
2efb75f3 754 lwkt_reltoken(&tp->t_token);
984263bc 755 return (-1);
22ff886e
AH
756 }
757 if (clist_putc(c, &tp->t_outq)) {
2efb75f3 758 lwkt_reltoken(&tp->t_token);
984263bc 759 return (c);
22ff886e 760 }
984263bc
MD
761 tk_nout++;
762 tp->t_outcc++;
2efb75f3 763 lwkt_reltoken(&tp->t_token);
984263bc
MD
764 return (-1);
765 }
766 /*
8edc0aff
SW
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.
984263bc
MD
771 */
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)) {
4725869b 777 c -= clist_btoq(" ", c, &tp->t_outq);
984263bc
MD
778 tk_nout += c;
779 tp->t_outcc += c;
984263bc
MD
780 }
781 tp->t_column += c;
2efb75f3 782 lwkt_reltoken(&tp->t_token);
984263bc
MD
783 return (c ? -1 : '\t');
784 }
22ff886e 785 if (c == CEOT && ISSET(oflag, ONOEOT)) {
2efb75f3 786 lwkt_reltoken(&tp->t_token);
984263bc 787 return (-1);
22ff886e 788 }
984263bc
MD
789
790 /*
791 * Newline translation: if ONLCR is set,
792 * translate newline into "\r\n".
793 */
794 if (c == '\n' && ISSET(tp->t_oflag, ONLCR)) {
795 tk_nout++;
796 tp->t_outcc++;
22ff886e 797 if (!ISSET(tp->t_lflag, FLUSHO) && clist_putc('\r', &tp->t_outq)) {
2efb75f3 798 lwkt_reltoken(&tp->t_token);
984263bc 799 return (c);
22ff886e 800 }
984263bc
MD
801 }
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. */
22ff886e 806 else if (c == '\r' && ISSET(tp->t_oflag, ONOCR) && tp->t_column == 0) {
2efb75f3 807 lwkt_reltoken(&tp->t_token);
984263bc 808 return (-1);
22ff886e 809 }
984263bc
MD
810
811 tk_nout++;
812 tp->t_outcc++;
22ff886e 813 if (!ISSET(tp->t_lflag, FLUSHO) && clist_putc(c, &tp->t_outq)) {
2efb75f3 814 lwkt_reltoken(&tp->t_token);
984263bc 815 return (c);
22ff886e 816 }
984263bc
MD
817
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;
839 }
840 tp->t_column = col;
2efb75f3
MD
841 lwkt_reltoken(&tp->t_token);
842
984263bc
MD
843 return (-1);
844}
845
846/*
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.
850 */
851/* ARGSUSED */
852int
dadab5e9 853ttioctl(struct tty *tp, u_long cmd, void *data, int flag)
984263bc 854{
dadab5e9 855 struct thread *td = curthread;
08f2f1bb 856 struct lwp *lp = td->td_lwp;
dadab5e9 857 struct proc *p = td->td_proc;
58c2553a 858 struct pgrp *opgrp;
94a6eea8 859 struct tty *otp;
e43a034f 860 int error;
984263bc 861
dadab5e9 862 KKASSERT(p);
2efb75f3 863 lwkt_gettoken(&tp->t_token);
616516c8 864 lwkt_gettoken(&p->p_token);
dadab5e9 865
984263bc
MD
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:
4643740a 890 while (isbackground(p, tp) && !(p->p_flags & P_PPWAIT) &&
984263bc 891 !SIGISMEMBER(p->p_sigignore, SIGTTOU) &&
08f2f1bb 892 !SIGISMEMBER(lp->lwp_sigmask, SIGTTOU)) {
22ff886e 893 if (p->p_pgrp->pg_jobc == 0) {
616516c8 894 lwkt_reltoken(&p->p_token);
2efb75f3 895 lwkt_reltoken(&tp->t_token);
984263bc 896 return (EIO);
22ff886e 897 }
984263bc 898 pgsignal(p->p_pgrp, SIGTTOU, 1);
377d4740 899 error = ttysleep(tp, &lbolt, PCATCH, "ttybg1",
984263bc 900 0);
22ff886e 901 if (error) {
616516c8 902 lwkt_reltoken(&p->p_token);
2efb75f3 903 lwkt_reltoken(&tp->t_token);
984263bc 904 return (error);
22ff886e 905 }
984263bc
MD
906 }
907 break;
908 }
909
910 switch (cmd) { /* Process the ioctl. */
911 case FIOASYNC: /* set/clear async i/o */
984263bc
MD
912 if (*(int *)data)
913 SET(tp->t_state, TS_ASYNC);
914 else
915 CLR(tp->t_state, TS_ASYNC);
984263bc 916 break;
984263bc 917 case FIONREAD: /* get # bytes to read */
984263bc 918 *(int *)data = ttnread(tp);
984263bc
MD
919 break;
920
921 case FIOSETOWN:
922 /*
923 * Policy -- Don't allow FIOSETOWN on someone else's
924 * controlling tty
925 */
22ff886e 926 if (tp->t_session != NULL && !isctty(p, tp)) {
616516c8 927 lwkt_reltoken(&p->p_token);
2efb75f3 928 lwkt_reltoken(&tp->t_token);
984263bc 929 return (ENOTTY);
22ff886e 930 }
984263bc
MD
931
932 error = fsetown(*(int *)data, &tp->t_sigio);
22ff886e 933 if (error) {
616516c8 934 lwkt_reltoken(&p->p_token);
2efb75f3 935 lwkt_reltoken(&tp->t_token);
984263bc 936 return (error);
22ff886e 937 }
984263bc
MD
938 break;
939 case FIOGETOWN:
22ff886e 940 if (tp->t_session != NULL && !isctty(p, tp)) {
616516c8 941 lwkt_reltoken(&p->p_token);
2efb75f3 942 lwkt_reltoken(&tp->t_token);
984263bc 943 return (ENOTTY);
22ff886e 944 }
b5c4d81f 945 *(int *)data = fgetown(&tp->t_sigio);
984263bc
MD
946 break;
947
948 case TIOCEXCL: /* set exclusive use of tty */
984263bc 949 SET(tp->t_state, TS_XCLUDE);
984263bc
MD
950 break;
951 case TIOCFLUSH: { /* flush buffers */
1fd87d54 952 int flags = *(int *)data;
984263bc
MD
953
954 if (flags == 0)
955 flags = FREAD | FWRITE;
956 else
957 flags &= FREAD | FWRITE;
958 ttyflush(tp, flags);
959 break;
960 }
961 case TIOCCONS: /* become virtual console */
962 if (*(int *)data) {
963 if (constty && constty != tp &&
22ff886e 964 ISSET(constty->t_state, TS_CONNECTED)) {
616516c8 965 lwkt_reltoken(&p->p_token);
2efb75f3 966 lwkt_reltoken(&tp->t_token);
984263bc 967 return (EBUSY);
22ff886e 968 }
984263bc 969#ifndef UCONSOLE
2b3f93ea
MD
970 error = caps_priv_check_td(td, SYSCAP_RESTRICTEDROOT);
971 if (error) {
616516c8 972 lwkt_reltoken(&p->p_token);
2efb75f3 973 lwkt_reltoken(&tp->t_token);
984263bc 974 return (error);
22ff886e 975 }
984263bc
MD
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);
22ff886e 983 if (error) {
616516c8 984 lwkt_reltoken(&p->p_token);
2efb75f3 985 lwkt_reltoken(&tp->t_token);
984263bc 986 return (error);
22ff886e 987 }
984263bc
MD
988 break;
989 case TIOCGETA: { /* get termios struct */
990 struct termios *t = (struct termios *)data;
991
992 bcopy(&tp->t_termios, t, sizeof(struct termios));
993 break;
994 }
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 */
22ff886e 1002 if (!isctty(p, tp)) {
616516c8 1003 lwkt_reltoken(&p->p_token);
2efb75f3 1004 lwkt_reltoken(&tp->t_token);
984263bc 1005 return (ENOTTY);
22ff886e 1006 }
984263bc
MD
1007 *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
1008 break;
fa94d286 1009 case TIOCGSID: /* get sid of tty */
22ff886e 1010 if (!isctty(p, tp)) {
616516c8 1011 lwkt_reltoken(&p->p_token);
2efb75f3 1012 lwkt_reltoken(&tp->t_token);
fa94d286 1013 return (ENOTTY);
22ff886e 1014 }
fa94d286
PA
1015 *(int *)data = tp->t_session->s_sid;
1016 break;
984263bc
MD
1017#ifdef TIOCHPCL
1018 case TIOCHPCL: /* hang up on last close */
984263bc 1019 SET(tp->t_cflag, HUPCL);
984263bc
MD
1020 break;
1021#endif
1022 case TIOCNXCL: /* reset exclusive use of tty */
984263bc 1023 CLR(tp->t_state, TS_XCLUDE);
984263bc
MD
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 */
1fd87d54 1031 struct termios *t = (struct termios *)data;
984263bc
MD
1032
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;
22ff886e 1037 if (t->c_ispeed == 0) {
616516c8 1038 lwkt_reltoken(&p->p_token);
2efb75f3 1039 lwkt_reltoken(&tp->t_token);
984263bc 1040 return (EINVAL);
22ff886e 1041 }
984263bc
MD
1042 if (cmd == TIOCSETAW || cmd == TIOCSETAF) {
1043 error = ttywait(tp);
1044 if (error) {
616516c8 1045 lwkt_reltoken(&p->p_token);
2efb75f3 1046 lwkt_reltoken(&tp->t_token);
984263bc
MD
1047 return (error);
1048 }
1049 if (cmd == TIOCSETAF)
1050 ttyflush(tp, FREAD);
1051 }
1052 if (!ISSET(t->c_cflag, CIGNORE)) {
1053 /*
1054 * Set device hardware.
1055 */
1056 if (tp->t_param && (error = (*tp->t_param)(tp, t))) {
616516c8 1057 lwkt_reltoken(&p->p_token);
2efb75f3 1058 lwkt_reltoken(&tp->t_token);
984263bc
MD
1059 return (error);
1060 }
1061 if (ISSET(t->c_cflag, CLOCAL) &&
1062 !ISSET(tp->t_cflag, CLOCAL)) {
1063 /*
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.
1068 */
1069 CLR(tp->t_state, TS_ZOMBIE);
1070
1071 wakeup(TSA_CARR_ON(tp));
1072 ttwakeup(tp);
1073 ttwwakeup(tp);
1074 }
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);
1086 }
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 {
1092 /*
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.
1097 */
4725869b
MD
1098 if (tp->t_canq.c_ccmax > 0 &&
1099 tp->t_rawq.c_ccmax > 0) {
1100 clist_catq(&tp->t_rawq, &tp->t_canq);
984263bc
MD
1101 /*
1102 * XXX the queue limits may be
1103 * different, so the old queue
1104 * swapping method no longer works.
1105 */
4725869b 1106 clist_catq(&tp->t_canq, &tp->t_rawq);
984263bc
MD
1107 }
1108 CLR(tp->t_lflag, PENDIN);
1109 }
1110 ttwakeup(tp);
1111 }
1112 tp->t_iflag = t->c_iflag;
1113 tp->t_oflag = t->c_oflag;
1114 /*
1115 * Make the EXTPROC bit read only.
1116 */
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));
984263bc
MD
1126 break;
1127 }
1128 case TIOCSETD: { /* set line discipline */
1fd87d54 1129 int t = *(int *)data;
b13267a5 1130 cdev_t device = tp->t_dev;
984263bc 1131
22ff886e 1132 if ((u_int)t >= nlinesw) {
616516c8 1133 lwkt_reltoken(&p->p_token);
2efb75f3 1134 lwkt_reltoken(&tp->t_token);
984263bc 1135 return (ENXIO);
22ff886e 1136 }
984263bc 1137 if (t != tp->t_line) {
984263bc
MD
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);
616516c8 1142 lwkt_reltoken(&p->p_token);
2efb75f3 1143 lwkt_reltoken(&tp->t_token);
984263bc
MD
1144 return (error);
1145 }
1146 tp->t_line = t;
984263bc
MD
1147 }
1148 break;
1149 }
1150 case TIOCSTART: /* start output, like ^Q */
984263bc
MD
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);
1156 }
984263bc
MD
1157 break;
1158 case TIOCSTI: /* simulate terminal input */
2b3f93ea
MD
1159 if ((flag & FREAD) == 0 &&
1160 caps_priv_check_td(td, SYSCAP_RESTRICTEDROOT))
1161 {
616516c8 1162 lwkt_reltoken(&p->p_token);
2efb75f3 1163 lwkt_reltoken(&tp->t_token);
984263bc 1164 return (EPERM);
22ff886e 1165 }
2b3f93ea
MD
1166 if (!isctty(p, tp) &&
1167 caps_priv_check_td(td, SYSCAP_RESTRICTEDROOT))
1168 {
616516c8 1169 lwkt_reltoken(&p->p_token);
2efb75f3 1170 lwkt_reltoken(&tp->t_token);
984263bc 1171 return (EACCES);
22ff886e 1172 }
984263bc 1173 (*linesw[tp->t_line].l_rint)(*(u_char *)data, tp);
984263bc
MD
1174 break;
1175 case TIOCSTOP: /* stop output, like ^S */
984263bc
MD
1176 if (!ISSET(tp->t_state, TS_TTSTOP)) {
1177 SET(tp->t_state, TS_TTSTOP);
1178 (*tp->t_stop)(tp, 0);
1179 }
984263bc
MD
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) &&
94a6eea8 1185 (tp->t_session != p->p_session))) {
616516c8 1186 lwkt_reltoken(&p->p_token);
2efb75f3 1187 lwkt_reltoken(&tp->t_token);
984263bc 1188 return (EPERM);
94a6eea8
MD
1189 }
1190 ttyhold(tp);
984263bc 1191 tp->t_session = p->p_session;
58c2553a
MD
1192 opgrp = tp->t_pgrp;
1193 pgref(p->p_pgrp);
984263bc 1194 tp->t_pgrp = p->p_pgrp;
94a6eea8 1195 otp = p->p_session->s_ttyp;
984263bc 1196 p->p_session->s_ttyp = tp;
4643740a 1197 p->p_flags |= P_CONTROLT;
94a6eea8
MD
1198 if (otp)
1199 ttyunhold(otp);
58c2553a
MD
1200 if (opgrp) {
1201 pgrel(opgrp);
1202 opgrp = NULL;
1203 }
984263bc
MD
1204 break;
1205 case TIOCSPGRP: { /* set pgrp of tty */
3e28fb5c 1206 pid_t pgid = *(int *)data;
984263bc 1207
22ff886e 1208 if (!isctty(p, tp)) {
616516c8 1209 lwkt_reltoken(&p->p_token);
2efb75f3 1210 lwkt_reltoken(&tp->t_token);
984263bc 1211 return (ENOTTY);
22ff886e
AH
1212 }
1213 else if (pgid < 1 || pgid > PID_MAX) {
616516c8 1214 lwkt_reltoken(&p->p_token);
2efb75f3 1215 lwkt_reltoken(&tp->t_token);
3e28fb5c 1216 return (EINVAL);
22ff886e 1217 } else {
3e28fb5c 1218 struct pgrp *pgrp = pgfind(pgid);
22ff886e 1219 if (pgrp == NULL || pgrp->pg_session != p->p_session) {
58c2553a
MD
1220 if (pgrp)
1221 pgrel(pgrp);
616516c8 1222 lwkt_reltoken(&p->p_token);
2efb75f3 1223 lwkt_reltoken(&tp->t_token);
3e28fb5c 1224 return (EPERM);
22ff886e 1225 }
58c2553a 1226 opgrp = tp->t_pgrp;
3e28fb5c 1227 tp->t_pgrp = pgrp;
58c2553a
MD
1228 if (opgrp) {
1229 pgrel(opgrp);
1230 opgrp = NULL;
1231 }
3e28fb5c 1232 }
984263bc
MD
1233 break;
1234 }
1235 case TIOCSTAT: /* simulate control-T */
984263bc 1236 ttyinfo(tp);
984263bc
MD
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);
1243 }
1244 break;
1245 case TIOCSDRAINWAIT:
2b3f93ea 1246 error = caps_priv_check_td(td, SYSCAP_RESTRICTEDROOT);
22ff886e 1247 if (error) {
616516c8 1248 lwkt_reltoken(&p->p_token);
2efb75f3 1249 lwkt_reltoken(&tp->t_token);
984263bc 1250 return (error);
22ff886e 1251 }
984263bc
MD
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:
616516c8 1260 lwkt_reltoken(&p->p_token);
2efb75f3 1261 lwkt_reltoken(&tp->t_token);
984263bc 1262 return (ENOIOCTL);
984263bc 1263 }
616516c8 1264 lwkt_reltoken(&p->p_token);
2efb75f3 1265 lwkt_reltoken(&tp->t_token);
984263bc
MD
1266 return (0);
1267}
1268
984263bc 1269static struct filterops ttyread_filtops =
a081e067 1270 { FILTEROP_ISFD|FILTEROP_MPSAFE, NULL, filt_ttyrdetach, filt_ttyread };
984263bc 1271static struct filterops ttywrite_filtops =
a081e067 1272 { FILTEROP_ISFD|FILTEROP_MPSAFE, NULL, filt_ttywdetach, filt_ttywrite };
984263bc
MD
1273
1274int
fef8985e 1275ttykqfilter(struct dev_kqfilter_args *ap)
984263bc 1276{
b13267a5 1277 cdev_t dev = ap->a_head.a_dev;
fef8985e 1278 struct knote *kn = ap->a_kn;
984263bc
MD
1279 struct tty *tp = dev->si_tty;
1280 struct klist *klist;
984263bc 1281
fef8985e 1282 ap->a_result = 0;
22ff886e 1283
2efb75f3 1284 lwkt_gettoken(&tp->t_token);
984263bc
MD
1285 switch (kn->kn_filter) {
1286 case EVFILT_READ:
5b22f1a7 1287 klist = &tp->t_rkq.ki_note;
984263bc
MD
1288 kn->kn_fop = &ttyread_filtops;
1289 break;
1290 case EVFILT_WRITE:
5b22f1a7 1291 klist = &tp->t_wkq.ki_note;
984263bc
MD
1292 kn->kn_fop = &ttywrite_filtops;
1293 break;
1294 default:
b287d649 1295 ap->a_result = EOPNOTSUPP;
2efb75f3 1296 lwkt_reltoken(&tp->t_token);
fef8985e 1297 return (0);
984263bc 1298 }
2efb75f3 1299 lwkt_reltoken(&tp->t_token);
984263bc 1300 kn->kn_hook = (caddr_t)dev;
5b22f1a7 1301 knote_insert(klist, kn);
984263bc
MD
1302
1303 return (0);
1304}
1305
1306static void
1307filt_ttyrdetach(struct knote *kn)
1308{
b13267a5 1309 struct tty *tp = ((cdev_t)kn->kn_hook)->si_tty;
984263bc 1310
2efb75f3 1311 lwkt_gettoken(&tp->t_token);
5b22f1a7 1312 knote_remove(&tp->t_rkq.ki_note, kn);
2efb75f3 1313 lwkt_reltoken(&tp->t_token);
984263bc
MD
1314}
1315
1316static int
1317filt_ttyread(struct knote *kn, long hint)
1318{
b13267a5 1319 struct tty *tp = ((cdev_t)kn->kn_hook)->si_tty;
984263bc 1320
2efb75f3 1321 lwkt_gettoken(&tp->t_token);
984263bc
MD
1322 kn->kn_data = ttnread(tp);
1323 if (ISSET(tp->t_state, TS_ZOMBIE)) {
3bcb6e5e 1324 kn->kn_flags |= (EV_EOF | EV_NODATA);
2efb75f3 1325 lwkt_reltoken(&tp->t_token);
984263bc
MD
1326 return (1);
1327 }
2efb75f3 1328 lwkt_reltoken(&tp->t_token);
984263bc
MD
1329 return (kn->kn_data > 0);
1330}
1331
1332static void
1333filt_ttywdetach(struct knote *kn)
1334{
b13267a5 1335 struct tty *tp = ((cdev_t)kn->kn_hook)->si_tty;
984263bc 1336
2efb75f3 1337 lwkt_gettoken(&tp->t_token);
5b22f1a7 1338 knote_remove(&tp->t_wkq.ki_note, kn);
2efb75f3 1339 lwkt_reltoken(&tp->t_token);
984263bc
MD
1340}
1341
1342static int
c972a82f 1343filt_ttywrite(struct knote *kn, long hint)
984263bc 1344{
b13267a5 1345 struct tty *tp = ((cdev_t)kn->kn_hook)->si_tty;
22ff886e 1346 int ret;
984263bc 1347
2efb75f3 1348 lwkt_gettoken(&tp->t_token);
984263bc 1349 kn->kn_data = tp->t_outq.c_cc;
22ff886e 1350 if (ISSET(tp->t_state, TS_ZOMBIE)) {
2efb75f3 1351 lwkt_reltoken(&tp->t_token);
984263bc 1352 return (1);
22ff886e
AH
1353 }
1354 ret = (kn->kn_data <= tp->t_olowat &&
984263bc 1355 ISSET(tp->t_state, TS_CONNECTED));
2efb75f3 1356 lwkt_reltoken(&tp->t_token);
22ff886e 1357 return ret;
984263bc
MD
1358}
1359
1360/*
2efb75f3 1361 * NOTE: tp->t_token must be held.
984263bc
MD
1362 */
1363static int
c972a82f 1364ttnread(struct tty *tp)
984263bc
MD
1365{
1366 int nread;
1367
2efb75f3 1368 ASSERT_LWKT_TOKEN_HELD(&tp->t_token);
984263bc
MD
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;
1376 }
1377 return (nread);
1378}
1379
1380/*
1381 * Wait for output to drain.
1382 */
1383int
c972a82f 1384ttywait(struct tty *tp)
984263bc 1385{
e43a034f 1386 int error;
984263bc
MD
1387
1388 error = 0;
2efb75f3 1389 lwkt_gettoken(&tp->t_token);
984263bc
MD
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),
377d4740 1397 PCATCH, "ttywai",
984263bc
MD
1398 tp->t_timeout);
1399 if (error) {
1400 if (error == EWOULDBLOCK)
1401 error = EIO;
1402 break;
1403 }
1404 } else
1405 break;
1406 }
1407 if (!error && (tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)))
1408 error = EIO;
2efb75f3
MD
1409 lwkt_reltoken(&tp->t_token);
1410
984263bc
MD
1411 return (error);
1412}
1413
1414/*
1415 * Flush if successfully wait.
1416 */
1417static int
c972a82f 1418ttywflush(struct tty *tp)
984263bc
MD
1419{
1420 int error;
1421
1422 if ((error = ttywait(tp)) == 0)
1423 ttyflush(tp, FREAD);
1424 return (error);
1425}
1426
1427/*
1428 * Flush tty read and/or write queues, notifying anyone waiting.
1429 */
1430void
c972a82f 1431ttyflush(struct tty *tp, int rw)
984263bc 1432{
2efb75f3 1433 lwkt_gettoken(&tp->t_token);
984263bc
MD
1434#if 0
1435again:
1436#endif
1437 if (rw & FWRITE) {
1438 FLUSHQ(&tp->t_outq);
1439 CLR(tp->t_state, TS_TTSTOP);
1440 }
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);
1454
1455 /*
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
6ea70f76 1460 * reserved cblocks" panic/kprintf.
984263bc
MD
1461 */
1462 CLR(tp->t_state, TS_TBLOCK);
1463
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)) {
1466 /*
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.
1474 */
1475 SET(tp->t_state, TS_SO_OCOMPLETE);
377d4740 1476 ttysleep(tp, TSA_OCOMPLETE(tp), 0,
984263bc
MD
1477 "ttyfls", hz / 10);
1478 /*
1479 * Don't try sending the stop character again.
1480 */
1481 CLR(tp->t_state, TS_TBLOCK);
1482 goto again;
1483 }
1484#endif
1485 }
1486 }
1487 if (rw & FWRITE) {
1488 FLUSHQ(&tp->t_outq);
1489 ttwwakeup(tp);
1490 }
2efb75f3 1491 lwkt_reltoken(&tp->t_token);
984263bc
MD
1492}
1493
1494/*
1495 * Copy in the default termios characters.
1496 */
1497void
c972a82f 1498termioschars(struct termios *t)
984263bc 1499{
984263bc
MD
1500 bcopy(ttydefchars, t->c_cc, sizeof t->c_cc);
1501}
1502
1503/*
1504 * Old interface.
1505 */
1506void
c972a82f 1507ttychars(struct tty *tp)
984263bc 1508{
2efb75f3 1509 lwkt_gettoken(&tp->t_token);
984263bc 1510 termioschars(&tp->t_termios);
2efb75f3 1511 lwkt_reltoken(&tp->t_token);
984263bc
MD
1512}
1513
1514/*
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.
1518 */
1519void
c972a82f 1520ttyblock(struct tty *tp)
984263bc 1521{
2efb75f3 1522 lwkt_gettoken(&tp->t_token);
984263bc
MD
1523 SET(tp->t_state, TS_TBLOCK);
1524 if (ISSET(tp->t_iflag, IXOFF) && tp->t_cc[VSTOP] != _POSIX_VDISABLE &&
0ced1954 1525 clist_putc(tp->t_cc[VSTOP], &tp->t_outq) != 0)
984263bc
MD
1526 CLR(tp->t_state, TS_TBLOCK); /* try again later */
1527 ttstart(tp);
2efb75f3 1528 lwkt_reltoken(&tp->t_token);
984263bc
MD
1529}
1530
1531/*
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.
1535 */
1536static void
c972a82f 1537ttyunblock(struct tty *tp)
984263bc 1538{
2efb75f3 1539 lwkt_gettoken(&tp->t_token);
984263bc
MD
1540 CLR(tp->t_state, TS_TBLOCK);
1541 if (ISSET(tp->t_iflag, IXOFF) && tp->t_cc[VSTART] != _POSIX_VDISABLE &&
0ced1954 1542 clist_putc(tp->t_cc[VSTART], &tp->t_outq) != 0)
984263bc
MD
1543 SET(tp->t_state, TS_TBLOCK); /* try again later */
1544 ttstart(tp);
2efb75f3 1545 lwkt_reltoken(&tp->t_token);
984263bc
MD
1546}
1547
984263bc 1548int
c972a82f 1549ttstart(struct tty *tp)
984263bc 1550{
2efb75f3 1551 lwkt_gettoken(&tp->t_token);
984263bc
MD
1552 if (tp->t_oproc != NULL) /* XXX: Kludge for pty. */
1553 (*tp->t_oproc)(tp);
2efb75f3 1554 lwkt_reltoken(&tp->t_token);
984263bc
MD
1555 return (0);
1556}
1557
1558/*
1559 * "close" a line discipline
1560 */
1561int
c972a82f 1562ttylclose(struct tty *tp, int flag)
984263bc 1563{
2efb75f3 1564 lwkt_gettoken(&tp->t_token);
984263bc
MD
1565 if (flag & FNONBLOCK || ttywflush(tp))
1566 ttyflush(tp, FREAD | FWRITE);
2efb75f3 1567 lwkt_reltoken(&tp->t_token);
984263bc
MD
1568 return (0);
1569}
1570
94a6eea8
MD
1571void
1572ttyhold(struct tty *tp)
1573{
2efb75f3 1574 lwkt_gettoken(&tp->t_token);
94a6eea8 1575 ++tp->t_refs;
2efb75f3 1576 lwkt_reltoken(&tp->t_token);
94a6eea8
MD
1577}
1578
1579void
1580ttyunhold(struct tty *tp)
1581{
2efb75f3 1582 lwkt_gettoken(&tp->t_token);
f5f1bbd4
MD
1583 if (tp->t_unhold)
1584 tp->t_unhold(tp);
1585 else
1586 --tp->t_refs;
2efb75f3 1587 lwkt_reltoken(&tp->t_token);
94a6eea8
MD
1588}
1589
984263bc
MD
1590/*
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.
1594 */
1595int
c972a82f 1596ttymodem(struct tty *tp, int flag)
984263bc 1597{
2efb75f3 1598 lwkt_gettoken(&tp->t_token);
984263bc
MD
1599 if (ISSET(tp->t_state, TS_CARR_ON) && ISSET(tp->t_cflag, MDMBUF)) {
1600 /*
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.
1604 */
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);
1613 }
1614 } else if (flag == 0) {
1615 /*
1616 * Lost carrier.
1617 */
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)
84204577 1624 ksignal(tp->t_session->s_leader, SIGHUP);
984263bc 1625 ttyflush(tp, FREAD | FWRITE);
2efb75f3 1626 lwkt_reltoken(&tp->t_token);
984263bc
MD
1627 return (0);
1628 }
1629 } else {
1630 /*
1631 * Carrier now on.
1632 */
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);
1639 }
2efb75f3 1640 lwkt_reltoken(&tp->t_token);
984263bc
MD
1641 return (1);
1642}
1643
1644/*
1645 * Reinput pending characters after state switch
984263bc
MD
1646 */
1647static void
c972a82f 1648ttypend(struct tty *tp)
984263bc
MD
1649{
1650 struct clist tq;
1fd87d54 1651 int c;
984263bc 1652
2efb75f3 1653 lwkt_gettoken(&tp->t_token);
984263bc
MD
1654 CLR(tp->t_lflag, PENDIN);
1655 SET(tp->t_state, TS_TYPEN);
1656 /*
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.
1661 */
1662 tq = tp->t_rawq;
1663 bzero(&tp->t_rawq, sizeof tp->t_rawq);
4725869b 1664 clist_alloc_cblocks(&tp->t_rawq, tq.c_ccmax);
0ced1954 1665 while ((c = clist_getc(&tq)) >= 0)
984263bc
MD
1666 ttyinput(c, tp);
1667 CLR(tp->t_state, TS_TYPEN);
4725869b 1668 clist_free_cblocks(&tq);
2efb75f3 1669 lwkt_reltoken(&tp->t_token);
984263bc
MD
1670}
1671
1672/*
1673 * Process a read call on a tty device.
1674 */
1675int
c972a82f 1676ttread(struct tty *tp, struct uio *uio, int flag)
984263bc 1677{
1fd87d54
RG
1678 struct clist *qp;
1679 int c;
1680 tcflag_t lflag;
1681 cc_t *cc = tp->t_cc;
142dd704 1682 struct proc *pp;
08f2f1bb 1683 struct lwp *lp;
e43a034f 1684 int first, error = 0;
984263bc
MD
1685 int has_stime = 0, last_cc = 0;
1686 long slp = 0; /* XXX this should be renamed `timo'. */
1687 struct timeval stime;
1688
08f2f1bb 1689 lp = curthread->td_lwp;
d557216f
MD
1690 stime.tv_sec = 0; /* fix compiler warnings */
1691 stime.tv_usec = 0;
08f2f1bb 1692
2efb75f3 1693 lwkt_gettoken(&tp->t_token);
984263bc 1694loop:
984263bc
MD
1695 lflag = tp->t_lflag;
1696 /*
1697 * take pending input first
1698 */
1699 if (ISSET(lflag, PENDIN)) {
1700 ttypend(tp);
e43a034f 1701 splz(); /* reduce latency */
984263bc
MD
1702 lflag = tp->t_lflag; /* XXX ttypend() clobbers it */
1703 }
1704
1705 /*
1706 * Hang process if it's in the background.
1707 */
a8d3ab53
MD
1708 if ((pp = curproc) != NULL)
1709 lwkt_gettoken(&pp->p_token);
1710 if (pp && isbackground(pp, tp)) {
142dd704 1711 if (SIGISMEMBER(pp->p_sigignore, SIGTTIN) ||
08f2f1bb 1712 SIGISMEMBER(lp->lwp_sigmask, SIGTTIN) ||
4643740a 1713 (pp->p_flags & P_PPWAIT) || pp->p_pgrp->pg_jobc == 0) {
a8d3ab53 1714 lwkt_reltoken(&pp->p_token);
2efb75f3 1715 lwkt_reltoken(&tp->t_token);
984263bc 1716 return (EIO);
22ff886e 1717 }
142dd704 1718 pgsignal(pp->p_pgrp, SIGTTIN, 1);
377d4740 1719 error = ttysleep(tp, &lbolt, PCATCH, "ttybg2", 0);
22ff886e 1720 if (error) {
a8d3ab53 1721 lwkt_reltoken(&pp->p_token);
2efb75f3 1722 lwkt_reltoken(&tp->t_token);
984263bc 1723 return (error);
22ff886e 1724 }
a8d3ab53 1725 lwkt_reltoken(&pp->p_token);
984263bc
MD
1726 goto loop;
1727 }
a8d3ab53
MD
1728 if (pp)
1729 lwkt_reltoken(&pp->p_token);
984263bc
MD
1730
1731 if (ISSET(tp->t_state, TS_ZOMBIE)) {
2efb75f3 1732 lwkt_reltoken(&tp->t_token);
984263bc
MD
1733 return (0); /* EOF */
1734 }
1735
1736 /*
1737 * If canonical, use the canonical queue,
1738 * else use the raw queue.
1739 *
1740 * (should get rid of clists...)
1741 */
1742 qp = ISSET(lflag, ICANON) ? &tp->t_canq : &tp->t_rawq;
1743
1744 if (flag & IO_NDELAY) {
1745 if (qp->c_cc > 0)
1746 goto read;
1747 if (!ISSET(lflag, ICANON) && cc[VMIN] == 0) {
2efb75f3 1748 lwkt_reltoken(&tp->t_token);
984263bc
MD
1749 return (0);
1750 }
2efb75f3 1751 lwkt_reltoken(&tp->t_token);
984263bc
MD
1752 return (EWOULDBLOCK);
1753 }
1754 if (!ISSET(lflag, ICANON)) {
1755 int m = cc[VMIN];
1756 long t = cc[VTIME];
1757 struct timeval timecopy;
1758
1759 /*
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.
1766 */
1767 if (t == 0) {
1768 if (qp->c_cc < m)
1769 goto sleep;
1770 if (qp->c_cc > 0)
1771 goto read;
1772
1773 /* m, t and qp->c_cc are all 0. 0 is enough input. */
2efb75f3 1774 lwkt_reltoken(&tp->t_token);
984263bc
MD
1775 return (0);
1776 }
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);
d557216f 1786 if (has_stime == 0) {
984263bc
MD
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;
1800 }
1801 last_cc = qp->c_cc;
1802 } else { /* m == 0 */
1803 if (qp->c_cc > 0)
1804 goto read;
1805 getmicrotime(&timecopy);
d557216f 1806 if (has_stime == 0) {
984263bc
MD
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. */
2efb75f3 1814 lwkt_reltoken(&tp->t_token);
984263bc
MD
1815 return (0);
1816 }
1817 }
1818 }
1819#undef diff
1820 /*
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).
1828 */
1829 slp = (long) (((u_long)slp * hz) + 999999) / 1000000;
1830 goto sleep;
1831 }
1832 if (qp->c_cc <= 0) {
1833sleep:
1834 /*
1835 * There is no input, or not enough input and we can block.
1836 */
377d4740 1837 error = ttysleep(tp, TSA_HUP_OR_INPUT(tp), PCATCH,
984263bc
MD
1838 ISSET(tp->t_state, TS_CONNECTED) ?
1839 "ttyin" : "ttyhup", (int)slp);
984263bc
MD
1840 if (error == EWOULDBLOCK)
1841 error = 0;
22ff886e 1842 else if (error) {
2efb75f3 1843 lwkt_reltoken(&tp->t_token);
984263bc 1844 return (error);
22ff886e 1845 }
984263bc
MD
1846 /*
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).
1851 */
1852 slp = 0;
1853 goto loop;
1854 }
1855read:
984263bc
MD
1856 /*
1857 * Input present, check for input mapping and processing.
1858 */
1859 first = 1;
1860 if (ISSET(lflag, ICANON | ISIG))
1861 goto slowcase;
1862 for (;;) {
1863 char ibuf[IBUFSIZ];
1864 int icc;
1865
e54488bb 1866 icc = (int)szmin(uio->uio_resid, IBUFSIZ);
4725869b 1867 icc = clist_qtob(qp, ibuf, icc);
984263bc
MD
1868 if (icc <= 0) {
1869 if (first)
1870 goto loop;
1871 break;
1872 }
e54488bb 1873 error = uiomove(ibuf, (size_t)icc, uio);
984263bc
MD
1874 /*
1875 * XXX if there was an error then we should ungetc() the
1876 * unmoved chars and reduce icc here.
1877 */
1878 if (error)
1879 break;
8f706258 1880 if (uio->uio_resid == 0)
984263bc
MD
1881 break;
1882 first = 0;
1883 }
1884 goto out;
1885slowcase:
1886 for (;;) {
0ced1954 1887 c = clist_getc(qp);
984263bc
MD
1888 if (c < 0) {
1889 if (first)
1890 goto loop;
1891 break;
1892 }
1893 /*
1894 * delayed suspend (^Y)
1895 */
1896 if (CCEQ(cc[VDSUSP], c) &&
1897 ISSET(lflag, IEXTEN | ISIG) == (IEXTEN | ISIG)) {
1898 pgsignal(tp->t_pgrp, SIGTSTP, 1);
1899 if (first) {
377d4740 1900 error = ttysleep(tp, &lbolt, PCATCH,
984263bc
MD
1901 "ttybg3", 0);
1902 if (error)
1903 break;
1904 goto loop;
1905 }
1906 break;
1907 }
1908 /*
1909 * Interpret EOF only in canonical mode.
1910 */
1911 if (CCEQ(cc[VEOF], c) && ISSET(lflag, ICANON))
1912 break;
1913 /*
1914 * Give user character.
1915 */
8f706258 1916 error = ureadc(c, uio);
984263bc
MD
1917 if (error)
1918 /* XXX should ungetc(c, qp). */
1919 break;
8f706258 1920 if (uio->uio_resid == 0)
984263bc
MD
1921 break;
1922 /*
1923 * In canonical mode check for a "break character"
1924 * marking the end of a "line of input".
1925 */
1926 if (ISSET(lflag, ICANON) && TTBREAKC(c, lflag))
1927 break;
1928 first = 0;
1929 }
1930
1931out:
1932 /*
1933 * Look to unblock input now that (presumably)
1934 * the input queue has gone down.
1935 */
984263bc 1936 if (ISSET(tp->t_state, TS_TBLOCK) &&
2efb75f3 1937 tp->t_rawq.c_cc + tp->t_canq.c_cc <= tp->t_ilowat) {
984263bc 1938 ttyunblock(tp);
2efb75f3 1939 }
984263bc 1940
2efb75f3 1941 lwkt_reltoken(&tp->t_token);
984263bc
MD
1942 return (error);
1943}
1944
1945/*
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.
1951 */
1952int
c972a82f 1953ttycheckoutq(struct tty *tp, int wait)
984263bc 1954{
aa6c3de6 1955 struct lwp *lp = curthread->td_lwp;
e43a034f 1956 int hiwat;
aa6c3de6 1957 sigset_t oldset, newset;
984263bc 1958
2efb75f3 1959 lwkt_gettoken(&tp->t_token);
984263bc 1960 hiwat = tp->t_ohiwat;
aa6c3de6
SS
1961 SIGEMPTYSET(oldset);
1962 SIGEMPTYSET(newset);
984263bc 1963 if (wait)
aa6c3de6 1964 oldset = lwp_sigpend(lp);
e43a034f 1965 if (tp->t_outq.c_cc > hiwat + OBUFSIZ + 100) {
984263bc
MD
1966 while (tp->t_outq.c_cc > hiwat) {
1967 ttstart(tp);
1968 if (tp->t_outq.c_cc <= hiwat)
1969 break;
aa6c3de6
SS
1970 if (wait)
1971 newset = lwp_sigpend(lp);
1972 if (!wait || SIGSETNEQ(oldset, newset)) {
2efb75f3 1973 lwkt_reltoken(&tp->t_token);
984263bc
MD
1974 return (0);
1975 }
1976 SET(tp->t_state, TS_SO_OLOWAT);
377d4740 1977 tsleep(TSA_OLOWAT(tp), 0, "ttoutq", hz);
984263bc 1978 }
e43a034f 1979 }
2efb75f3 1980 lwkt_reltoken(&tp->t_token);
984263bc
MD
1981 return (1);
1982}
1983
1984/*
1985 * Process a write call on a tty device.
1986 */
1987int
c972a82f 1988ttwrite(struct tty *tp, struct uio *uio, int flag)
984263bc 1989{
1fd87d54
RG
1990 char *cp = NULL;
1991 int cc, ce;
142dd704 1992 struct proc *pp;
08f2f1bb 1993 struct lwp *lp;
e54488bb
MD
1994 int i, hiwat, error;
1995 size_t cnt;
1996
984263bc
MD
1997 char obuf[OBUFSIZ];
1998
2efb75f3 1999 lwkt_gettoken(&tp->t_token);
08f2f1bb 2000 lp = curthread->td_lwp;
984263bc
MD
2001 hiwat = tp->t_ohiwat;
2002 cnt = uio->uio_resid;
2003 error = 0;
2004 cc = 0;
2005loop:
984263bc 2006 if (ISSET(tp->t_state, TS_ZOMBIE)) {
984263bc
MD
2007 if (uio->uio_resid == cnt)
2008 error = EIO;
2009 goto out;
2010 }
2011 if (!ISSET(tp->t_state, TS_CONNECTED)) {
2012 if (flag & IO_NDELAY) {
984263bc
MD
2013 error = EWOULDBLOCK;
2014 goto out;
2015 }
377d4740 2016 error = ttysleep(tp, TSA_CARR_ON(tp), PCATCH, "ttydcd", 0);
984263bc
MD
2017 if (error)
2018 goto out;
2019 goto loop;
2020 }
142dd704 2021
984263bc
MD
2022 /*
2023 * Hang the process if it's in the background.
2024 */
a8d3ab53
MD
2025 if ((pp = curproc) != NULL)
2026 lwkt_gettoken(&pp->p_token);
2027 if (pp && isbackground(pp, tp) &&
4643740a 2028 ISSET(tp->t_lflag, TOSTOP) && !(pp->p_flags & P_PPWAIT) &&
142dd704 2029 !SIGISMEMBER(pp->p_sigignore, SIGTTOU) &&
08f2f1bb 2030 !SIGISMEMBER(lp->lwp_sigmask, SIGTTOU)) {
142dd704 2031 if (pp->p_pgrp->pg_jobc == 0) {
984263bc 2032 error = EIO;
a8d3ab53 2033 lwkt_reltoken(&pp->p_token);
984263bc
MD
2034 goto out;
2035 }
142dd704 2036 pgsignal(pp->p_pgrp, SIGTTOU, 1);
a8d3ab53 2037 lwkt_reltoken(&pp->p_token);
377d4740 2038 error = ttysleep(tp, &lbolt, PCATCH, "ttybg4", 0);
984263bc
MD
2039 if (error)
2040 goto out;
2041 goto loop;
2042 }
a8d3ab53
MD
2043 if (pp)
2044 lwkt_reltoken(&pp->p_token);
984263bc
MD
2045 /*
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.
2049 */
2050 while (uio->uio_resid > 0 || cc > 0) {
2051 if (ISSET(tp->t_lflag, FLUSHO)) {
2052 uio->uio_resid = 0;
2efb75f3 2053 lwkt_reltoken(&tp->t_token);
984263bc
MD
2054 return (0);
2055 }
2056 if (tp->t_outq.c_cc > hiwat)
2057 goto ovhiwat;
2058 /*
2059 * Grab a hunk of data from the user, unless we have some
2060 * leftover from last time.
2061 */
2062 if (cc == 0) {
e54488bb 2063 cc = szmin(uio->uio_resid, OBUFSIZ);
984263bc 2064 cp = obuf;
e54488bb 2065 error = uiomove(cp, (size_t)cc, uio);
984263bc
MD
2066 if (error) {
2067 cc = 0;
2068 break;
2069 }
2070 }
2071 /*
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.
2079 */
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);
2086 /*
2087 * If ce is zero, then we're processing
2088 * a special character through ttyoutput.
2089 */
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;
2098 }
2099 error = ttysleep(tp, &lbolt,
377d4740 2100 PCATCH,
984263bc
MD
2101 "ttybf1", 0);
2102 if (error)
2103 goto out;
2104 goto loop;
2105 }
2106 cp++;
2107 cc--;
2108 if (ISSET(tp->t_lflag, FLUSHO) ||
2109 tp->t_outq.c_cc > hiwat)
2110 goto ovhiwat;
2111 continue;
2112 }
2113 }
2114 /*
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.
2121 */
2122 tp->t_rocount = 0;
4725869b 2123 i = clist_btoq(cp, ce, &tp->t_outq);
984263bc
MD
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;
2134 }
377d4740 2135 error = ttysleep(tp, &lbolt, PCATCH,
984263bc
MD
2136 "ttybf2", 0);
2137 if (error)
2138 goto out;
2139 goto loop;
2140 }
2141 if (ISSET(tp->t_lflag, FLUSHO) ||
2142 tp->t_outq.c_cc > hiwat)
2143 break;
2144 }
2145 ttstart(tp);
2146 }
2147out:
2148 /*
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).
2152 */
2153 uio->uio_resid += cc;
2efb75f3 2154 lwkt_reltoken(&tp->t_token);
984263bc
MD
2155 return (error);
2156
2157ovhiwat:
2158 ttstart(tp);
984263bc
MD
2159 /*
2160 * This can only occur if FLUSHO is set in t_lflag,
2161 * or if ttstart/oproc is synchronous (or very fast).
2162 */
2163 if (tp->t_outq.c_cc <= hiwat) {
984263bc
MD
2164 goto loop;
2165 }
2166 if (flag & IO_NDELAY) {
984263bc 2167 uio->uio_resid += cc;
2efb75f3 2168 lwkt_reltoken(&tp->t_token);
984263bc
MD
2169 return (uio->uio_resid == cnt ? EWOULDBLOCK : 0);
2170 }
2171 SET(tp->t_state, TS_SO_OLOWAT);
377d4740 2172 error = ttysleep(tp, TSA_OLOWAT(tp), PCATCH, "ttywri", tp->t_timeout);
984263bc
MD
2173 if (error == EWOULDBLOCK)
2174 error = EIO;
2175 if (error)
2176 goto out;
2177 goto loop;
2178}
2179
2180/*
2181 * Rubout one character from the rawq of tp
2182 * as cleanly as possible.
2efb75f3 2183 * NOTE: Must be called with tp->t_token held
984263bc
MD
2184 */
2185static void
c972a82f 2186ttyrub(int c, struct tty *tp)
984263bc 2187{
4725869b 2188 void *cp;
1fd87d54 2189 int savecol;
e43a034f 2190 int tabc;
984263bc 2191
2efb75f3 2192 ASSERT_LWKT_TOKEN_HELD(&tp->t_token);
984263bc
MD
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) {
2198 /*
2199 * Screwed by ttwrite; retype
2200 */
2201 ttyretype(tp);
2202 return;
2203 }
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;
2224 }
984263bc
MD
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;
4725869b
MD
2229
2230 cp = clist_nextc(&tp->t_rawq, NULL, &tabc);
2231 while (cp) {
984263bc 2232 ttyecho(tabc, tp);
4725869b
MD
2233 cp = clist_nextc(&tp->t_rawq,
2234 cp, &tabc);
2235 }
984263bc
MD
2236 CLR(tp->t_lflag, FLUSHO);
2237 CLR(tp->t_state, TS_CNTTB);
984263bc
MD
2238
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"
6ea70f76 2249 (void)kprintf(PANICSTR, c, CCLASS(c));
984263bc
MD
2250#ifdef notdef
2251 panic(PANICSTR, c, CCLASS(c));
2252#endif
2253 }
2254 }
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);
2259 }
2260 ttyecho(c, tp);
2261 } else {
2262 ttyecho(tp->t_cc[VERASE], tp);
2263 /*
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.
2270 */
2271 }
2272 --tp->t_rocount;
2273}
2274
2275/*
2276 * Back over cnt characters, erasing them.
2efb75f3 2277 * NOTE: Must be called with tp->t_token held
984263bc
MD
2278 */
2279static void
c972a82f 2280ttyrubo(struct tty *tp, int cnt)
984263bc 2281{
2efb75f3 2282 ASSERT_LWKT_TOKEN_HELD(&tp->t_token);
984263bc
MD
2283 while (cnt-- > 0) {
2284 (void)ttyoutput('\b', tp);
2285 (void)ttyoutput(' ', tp);
2286 (void)ttyoutput('\b', tp);
2287 }
2288}
2289
2290/*
2291 * ttyretype --
2292 * Reprint the rawq line. Note, it is assumed that c_cc has already
2293 * been checked.
2efb75f3 2294 * NOTE: Must be called with tp->t_token held
984263bc
MD
2295 */
2296static void
c972a82f 2297ttyretype(struct tty *tp)
984263bc 2298{
4725869b 2299 void *cp;
e43a034f 2300 int c;
984263bc 2301
2efb75f3 2302 ASSERT_LWKT_TOKEN_HELD(&tp->t_token);
984263bc
MD
2303 /* Echo the reprint character. */
2304 if (tp->t_cc[VREPRINT] != _POSIX_VDISABLE)
2305 ttyecho(tp->t_cc[VREPRINT], tp);
2306
2307 (void)ttyoutput('\n', tp);
2308
2309 /*
2310 * XXX
2311 * FIX: NEXTC IS BROKEN - DOESN'T CHECK QUOTE
2312 * BIT OF FIRST CHAR.
2313 */
4725869b
MD
2314 cp = clist_nextc(&tp->t_canq, NULL, &c);
2315 while (cp) {
984263bc 2316 ttyecho(c, tp);
4725869b
MD
2317 cp = clist_nextc(&tp->t_canq, cp, &c);
2318 }
2319 cp = clist_nextc(&tp->t_rawq, NULL, &c);
2320 while (cp) {
984263bc 2321 ttyecho(c, tp);
4725869b
MD
2322 cp = clist_nextc(&tp->t_rawq, cp, &c);
2323 }
984263bc 2324 CLR(tp->t_state, TS_ERASE);
984263bc
MD
2325
2326 tp->t_rocount = tp->t_rawq.c_cc;
2327 tp->t_rocol = 0;
2328}
2329
2330/*
2331 * Echo a typed character to the terminal.
2efb75f3 2332 * NOTE: Must be called with tp->t_token held
984263bc
MD
2333 */
2334static void
c972a82f 2335ttyecho(int c, struct tty *tp)
984263bc 2336{
2efb75f3 2337 ASSERT_LWKT_TOKEN_HELD(&tp->t_token);
984263bc
MD
2338
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;
2354 }
2355 (void)ttyoutput(c, tp);
2356}
2357
2358/*
2359 * Wake up any readers on a tty.
2360 */
2361void
c972a82f 2362ttwakeup(struct tty *tp)
984263bc 2363{
2efb75f3 2364 lwkt_gettoken(&tp->t_token);
984263bc
MD
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));
5b22f1a7 2368 KNOTE(&tp->t_rkq.ki_note, 0);
2efb75f3 2369 lwkt_reltoken(&tp->t_token);
984263bc
MD
2370}
2371
2372/*
2373 * Wake up any writers on a tty.
2374 */
2375void
c972a82f 2376ttwwakeup(struct tty *tp)
984263bc 2377{
2efb75f3 2378 lwkt_gettoken(&tp->t_token);
984263bc
MD
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));
2385 }
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));
2390 }
5b22f1a7 2391 KNOTE(&tp->t_wkq.ki_note, 0);
2efb75f3 2392 lwkt_reltoken(&tp->t_token);
984263bc
MD
2393}
2394
2395/*
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.
22ff886e 2398 * No requirements
984263bc
MD
2399 */
2400int
c972a82f 2401ttspeedtab(int speed, struct speedtab *table)
984263bc
MD
2402{
2403
2404 for ( ; table->sp_speed != -1; table++)
2405 if (table->sp_speed == speed)
2406 return (table->sp_code);
2407 return (-1);
2408}
2409
2410/*
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.
2417 */
e5117602
MD
2418#define CLAMP(x, h, l) ((x) > h ? h : ((x) < l) ? l : (x))
2419
984263bc 2420void
c972a82f 2421ttsetwater(struct tty *tp)
984263bc 2422{
e5117602
MD
2423 int ttmaxhiwat; /* maximum high water mark */
2424 int cps; /* characters per second */
2425 int x;
984263bc 2426
2efb75f3 2427 lwkt_gettoken(&tp->t_token);
e5117602
MD
2428
2429 /*
2430 * Input side.
2431 *
2432 * Calculate nominal low and high water marks, leave a little
2433 * room to absorb flow control latencies.
2434 */
4725869b 2435 clist_alloc_cblocks(&tp->t_canq, TTYHOG);
e5117602 2436
984263bc
MD
2437 switch (tp->t_ispeedwat) {
2438 case (speed_t)-1:
2439 cps = tp->t_ispeed / 10;
2440 break;
2441 case 0:
2442 /*
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.
2446 */
2447 cps = TTYHOG - 2 * 256;
2849f1e5 2448 tp->t_ififosize = 2 * 2048;
984263bc
MD
2449 break;
2450 default:
2451 cps = tp->t_ispeedwat / 10;
2452 break;
2453 }
2454 tp->t_ihiwat = cps;
2455 tp->t_ilowat = 7 * cps / 8;
2456 x = cps + tp->t_ififosize;
4725869b 2457 clist_alloc_cblocks(&tp->t_rawq, x);
984263bc 2458
e5117602
MD
2459 /*
2460 * Output side.
2461 *
2462 * Calculate nominal low and high water marks, and make the
2463 * actual buffer just a tad larger to absorb flow control latencies.
2464 */
984263bc
MD
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;
2478 }
e5117602
MD
2479
2480 x = CLAMP(cps / 2, TTMAXLOWAT, TTMINLOWAT);
2481 tp->t_olowat = x;
2482
984263bc 2483 x += cps;
e5117602
MD
2484 x = CLAMP(x, ttmaxhiwat, TTMINHIWAT);
2485 tp->t_ohiwat = x;
2486
2487 x = imax(tp->t_ohiwat, TTMAXHIWAT);
984263bc 2488 x += OBUFSIZ + 100;
4725869b 2489 clist_alloc_cblocks(&tp->t_outq, x);
e5117602 2490
2efb75f3 2491 lwkt_reltoken(&tp->t_token);
984263bc
MD
2492}
2493
e5117602
MD
2494#undef CLAMP
2495
984263bc
MD
2496/*
2497 * Report on state of foreground process group.
2498 */
2499void
c972a82f 2500ttyinfo(struct tty *tp)
984263bc 2501{
197b441c 2502 struct pgrp *pgrp;
1fd87d54 2503 struct proc *p, *pick;
08f2f1bb 2504 struct lwp *lp;
fde7ac71 2505 struct rusage ru;
197b441c
MD
2506 char buf[64];
2507 const char *str;
2508 struct vmspace *vm;
2509 long vmsz;
2510 int pctcpu;
984263bc
MD
2511 int tmp;
2512
2513 if (ttycheckoutq(tp,0) == 0)
2514 return;
2515
2efb75f3 2516 lwkt_gettoken(&tp->t_token);
a8d3ab53 2517
5daa25b0
MD
2518 /*
2519 * We always print the load average, then figure out what else to
2520 * print based on the state of the current process group.
2521 */
984263bc
MD
2522 tmp = (averunnable.ldavg[0] * 100 + FSCALE / 2) >> FSHIFT;
2523 ttyprintf(tp, "load: %d.%02d ", tmp / 100, tmp % 100);
2524
5daa25b0 2525 if (tp->t_session == NULL) {
984263bc 2526 ttyprintf(tp, "not a controlling terminal\n");
197b441c
MD
2527 goto done2;
2528 }
2529 if ((pgrp = tp->t_pgrp) == NULL) {
984263bc 2530 ttyprintf(tp, "no foreground process group\n");
197b441c
MD
2531 goto done2;
2532 }
5daa25b0 2533
197b441c
MD
2534 /*
2535 * Pick an interesting process. Note that certain elements,
2efb75f3 2536 * in particular the wmesg.
197b441c
MD
2537 *
2538 * NOTE: lwp_wmesg is lwp_thread->td_wmesg.
2539 */
2540 pgref(pgrp);
2541 lwkt_gettoken(&pgrp->pg_token);
2542
2543 pick = NULL;
2544 for (p = LIST_FIRST(&pgrp->pg_members);
2545 p != NULL;
2546 p = LIST_NEXT(p, p_pglist)) {
a8d3ab53
MD
2547 PHOLD(p);
2548 if (proc_compare(pick, p)) {
2549 if (pick)
2550 PRELE(pick);
197b441c 2551 pick = p;
a8d3ab53
MD
2552 } else {
2553 PRELE(p);
2554 }
197b441c
MD
2555 }
2556 if (pick == NULL) {
2557 ttyprintf(tp, "empty foreground process group\n");
2558 goto done1;
2559 }
08f2f1bb 2560
197b441c
MD
2561 /*
2562 * Pick an interesting LWP (XXX)
a8d3ab53
MD
2563 *
2564 * pick is held.
197b441c 2565 */
197b441c
MD
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;
2571 }
984263bc 2572
197b441c
MD
2573 /*
2574 * Figure out what wait/process-state message, and command
2575 * buffer to present
2576 */
2577 /*
2578 * XXX lwp This is a horrible mixture. We need to rework this
2579 * as soon as lwps have their own runnable status.
2580 */
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 */
213c68be 2589 str = lp->lwp_wmesg;
197b441c
MD
2590 else
2591 str = "iowait";
984263bc 2592
197b441c
MD
2593 ksnprintf(buf, sizeof(buf), "cmd: %s %d [%s]",
2594 pick->p_comm, pick->p_pid, str);
984263bc 2595
197b441c
MD
2596 /*
2597 * Calculate cpu usage, percent cpu, and cmsz. Note that
2efb75f3 2598 * 'pick' becomes invalid the moment we release the token.
197b441c 2599 */
ef866ef7 2600 if (lp->lwp_thread)
197b441c 2601 calcru_proc(pick, &ru);
5daa25b0 2602
197b441c 2603 pctcpu = (lp->lwp_pctcpu * 10000 + FSCALE / 2) >> FSHIFT;
5daa25b0 2604
197b441c 2605 LWPRELE(lp);
984263bc 2606
93f86408
MD
2607 /*
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.
2611 */
197b441c
MD
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);
984263bc 2620 }
197b441c
MD
2621 PRELE(pick);
2622
2623 /*
2624 * Dump the output
2625 */
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);
2634
2635done1:
2636 lwkt_reltoken(&pgrp->pg_token);
2637 pgrel(pgrp);
2638done2:
984263bc 2639 tp->t_rocount = 0; /* so pending input will be retyped if BS */
2efb75f3 2640 lwkt_reltoken(&tp->t_token);
984263bc
MD
2641}
2642
2643/*
2644 * Returns 1 if p2 is "better" than p1
2645 *
2646 * The algorithm for picking the "interesting" process is thus:
2647 *
2648 * 1) Only foreground processes are eligible - implied.
2649 * 2) Runnable processes are favored over anything else. The runner
dcc99b62 2650 * with the highest cpu utilization is picked (p_cpticks). Ties are
984263bc
MD
2651 * broken by picking the highest pid.
2652 * 3) The sleeper with the shortest sleep time is next. With ties,
9a379a4a 2653 * we pick out just "short-term" sleepers (LWP_SINTR == 0).
984263bc 2654 * 4) Further ties are broken by picking the highest pid.
22ff886e 2655 *
a8d3ab53 2656 * NOTE: must be called with p1 and p2 held.
984263bc 2657 */
164b8401 2658#define ISRUN(lp) ((lp)->lwp_stat == LSRUN)
984263bc
MD
2659#define TESTAB(a, b) ((a)<<1 | (b))
2660#define ONLYA 2
2661#define ONLYB 1
2662#define BOTH 3
2663
2664static int
c972a82f 2665proc_compare(struct proc *p1, struct proc *p2)
984263bc 2666{
08f2f1bb 2667 struct lwp *lp1, *lp2;
91148fea 2668 int res;
22ff886e 2669
984263bc
MD
2670 if (p1 == NULL)
2671 return (1);
91148fea
MD
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);
2677 }
08f2f1bb 2678
93e5e2ea
MD
2679 /*
2680 * weed out zombies
2681 */
2682 switch (TESTAB(p1->p_stat == SZOMB, p2->p_stat == SZOMB)) {
2683 case ONLYA:
91148fea
MD
2684 res = 1;
2685 goto done;
93e5e2ea 2686 case ONLYB:
91148fea
MD
2687 res = 0;
2688 goto done;
93e5e2ea 2689 case BOTH:
91148fea
MD
2690 res = (p2->p_pid > p1->p_pid); /* tie - return highest pid */
2691 goto done;
2692 default:
2693 break;
93e5e2ea
MD
2694 }
2695
91148fea 2696 /* XXX choose the best lwp? */
08f2f1bb
SS
2697 lp1 = FIRST_LWP_IN_PROC(p1);
2698 lp2 = FIRST_LWP_IN_PROC(p2);
2699
91148fea
MD
2700 /*
2701 * Favor one with LWPs verses one that has none (is exiting).
2702 */
2703 if (lp1 == NULL) {
2704 res = 1;
2705 goto done;
2706 }
2707 if (lp2 == NULL) {
2708 res = 0;
2709 goto done;
2710 }
2711
984263bc
MD
2712 /*
2713 * see if at least one of them is runnable
2714 */
164b8401 2715 switch (TESTAB(ISRUN(lp1), ISRUN(lp2))) {
984263bc 2716 case ONLYA:
91148fea
MD
2717 res = 0;
2718 goto done;
984263bc 2719 case ONLYB:
91148fea
MD
2720 res = 1;
2721 goto done;
984263bc
MD
2722 case BOTH:
2723 /*
2724 * tie - favor one with highest recent cpu utilization
2725 */
08f2f1bb 2726 if (lp2->lwp_cpticks > lp1->lwp_cpticks)
91148fea
MD
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;
984263bc 2735 }
91148fea 2736
984263bc 2737 /*
91148fea 2738 * Pick the one with the smallest sleep time
984263bc 2739 */
91148fea
MD
2740 if (lp2->lwp_slptime > lp1->lwp_slptime) {
2741 res = 0;
2742 goto done;
2743 }
2744 if (lp1->lwp_slptime > lp2->lwp_slptime) {
2745 res = 1;
2746 goto done;
2747 }
2748
984263bc 2749 /*
91148fea 2750 * Favor one sleeping in a non-interruptible sleep
984263bc 2751 */
91148fea
MD
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 */
2760
2761done:
2762 lwkt_reltoken(&p2->p_token);
2763 lwkt_reltoken(&p1->p_token);
2764 return (res);
984263bc
MD
2765}
2766
2767/*
2768 * Output char to tty; console putchar style.
2769 */
2770int
c972a82f 2771tputchar(int c, struct tty *tp)
984263bc 2772{
2efb75f3 2773 lwkt_gettoken(&tp->t_token);
984263bc 2774 if (!ISSET(tp->t_state, TS_CONNECTED)) {
2efb75f3 2775 lwkt_reltoken(&tp->t_token);
984263bc
MD
2776 return (-1);
2777 }
2778 if (c == '\n')
2779 (void)ttyoutput('\r', tp);
2780 (void)ttyoutput(c, tp);
2781 ttstart(tp);
2efb75f3
MD
2782 lwkt_reltoken(&tp->t_token);
2783
984263bc
MD
2784 return (0);
2785}
2786
2787/*
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.
2792 */
2793int
c972a82f 2794ttysleep(struct tty *tp, void *chan, int slpflags, char *wmesg, int timo)
984263bc
MD
2795{
2796 int error;
2797 int gen;
2798
2799 gen = tp->t_gen;
377d4740 2800 error = tsleep(chan, slpflags, wmesg, timo);
984263bc
MD
2801 if (error)
2802 return (error);
2803 return (tp->t_gen == gen ? 0 : ERESTART);
2804}
2805
a32446b7
MD
2806/*
2807 * Revoke a tty.
2808 *
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.
2813 */
2814int
2815ttyrevoke(struct dev_revoke_args *ap)
2816{
2817 struct tty *tp;
2818
2819 tp = ap->a_head.a_dev->si_tty;
2efb75f3 2820 lwkt_gettoken(&tp->t_token);
a32446b7
MD
2821 tp->t_gen++;
2822 ttyflush(tp, FREAD | FWRITE);
2823 wakeup(TSA_CARR_ON(tp));
2824 ttwakeup(tp);
2825 ttwwakeup(tp);
2efb75f3
MD
2826 lwkt_reltoken(&tp->t_token);
2827
a32446b7
MD
2828 return (0);
2829}
2830
984263bc
MD
2831/*
2832 * Allocate a tty struct. Clists in the struct will be allocated by
2efb75f3
MD
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.
2835 *
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.
984263bc
MD
2839 */
2840struct tty *
2efb75f3 2841ttymalloc(struct tty **tpp)
984263bc 2842{
2efb75f3 2843 struct tty *tp;
984263bc 2844
2efb75f3
MD
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);
2854 }
2855 lwkt_reltoken(&tty_token);
cd29885a 2856 }
984263bc
MD
2857 return (tp);
2858}
2859
2efb75f3
MD
2860/*
2861 * Caller must hold tp->t_token
2862 */
984263bc 2863void
ddac2002 2864ttyunregister(struct tty *tp)
984263bc 2865{
22ff886e 2866 lwkt_gettoken(&tty_token);
2efb75f3
MD
2867 if (ISSET(tp->t_state, TS_REGISTERED)) {
2868 CLR(tp->t_state, TS_REGISTERED);
2869 TAILQ_REMOVE(&tty_list, tp, t_list);
2870 }
22ff886e 2871 lwkt_reltoken(&tty_token);
984263bc 2872}
984263bc 2873
2efb75f3
MD
2874void
2875ttyinit(struct tty *tp)
2876{
2877 lwkt_token_init(&tp->t_token, "tp");
2878}
2879
984263bc 2880void
c972a82f 2881ttyregister(struct tty *tp)
984263bc 2882{
22ff886e 2883 lwkt_gettoken(&tty_token);
2efb75f3
MD
2884 if (!ISSET(tp->t_state, TS_REGISTERED)) {
2885 SET(tp->t_state, TS_REGISTERED);
2886 TAILQ_INSERT_HEAD(&tty_list, tp, t_list);
2887 }
22ff886e 2888 lwkt_reltoken(&tty_token);
984263bc
MD
2889}
2890
2891static int
2892sysctl_kern_ttys(SYSCTL_HANDLER_ARGS)
2893{
2894 int error;
ddac2002
MD
2895 struct tty *tp;
2896 struct tty t;
2897 struct tty marker;
2898
2899 bzero(&marker, sizeof(marker));
2900 marker.t_state = TS_MARKER;
2901 error = 0;
2902
22ff886e
AH
2903 lwkt_gettoken(&tty_token);
2904
ddac2002
MD
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;
984263bc
MD
2911 t = *tp;
2912 if (t.t_dev)
2ac7d105 2913 t.t_dev = (cdev_t)(uintptr_t)devid_from_dev(t.t_dev);
984263bc
MD
2914 error = SYSCTL_OUT(req, (caddr_t)&t, sizeof(t));
2915 if (error)
ddac2002 2916 break;
984263bc 2917 }
ddac2002 2918 TAILQ_REMOVE(&tty_list, &marker, t_list);
22ff886e 2919 lwkt_reltoken(&tty_token);
ddac2002 2920 return (error);
984263bc
MD
2921}
2922
2923SYSCTL_PROC(_kern, OID_AUTO, ttys, CTLTYPE_OPAQUE|CTLFLAG_RD,
2924 0, 0, sysctl_kern_ttys, "S,tty", "All struct ttys");
2925
2926void
c972a82f 2927nottystop(struct tty *tp, int rw)
984263bc 2928{
984263bc
MD
2929 return;
2930}
2931
2932int
fef8985e 2933ttyread(struct dev_read_args *ap)
984263bc
MD
2934{
2935 struct tty *tp;
22ff886e 2936 int ret;
984263bc 2937
fef8985e 2938 tp = ap->a_head.a_dev->si_tty;
984263bc
MD
2939 if (tp == NULL)
2940 return (ENODEV);
2efb75f3 2941 lwkt_gettoken(&tp->t_token);
22ff886e 2942 ret = ((*linesw[tp->t_line].l_read)(tp, ap->a_uio, ap->a_ioflag));
2efb75f3 2943 lwkt_reltoken(&tp->t_token);
22ff886e
AH
2944
2945 return ret;
984263bc
MD
2946}
2947
2948int
fef8985e 2949ttywrite(struct dev_write_args *ap)
984263bc
MD
2950{
2951 struct tty *tp;
22ff886e 2952 int ret;
984263bc 2953
fef8985e 2954 tp = ap->a_head.a_dev->si_tty;
984263bc
MD
2955 if (tp == NULL)
2956 return (ENODEV);
2efb75f3 2957 lwkt_gettoken(&tp->t_token);
22ff886e 2958 ret = ((*linesw[tp->t_line].l_write)(tp, ap->a_uio, ap->a_ioflag));
2efb75f3 2959 lwkt_reltoken(&tp->t_token);
22ff886e
AH
2960
2961 return ret;
984263bc 2962}