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