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