1 /*        $NetBSD: tty.c,v 1.313 2024/07/14 05:10:40 kre Exp $        */
2 
3 /*-
4  * Copyright (c) 2008, 2020 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /*-
30  * Copyright (c) 1982, 1986, 1990, 1991, 1993
31  *        The Regents of the University of California.  All rights reserved.
32  * (c) UNIX System Laboratories, Inc.
33  * All or some portions of this file are derived from material licensed
34  * to the University of California by American Telephone and Telegraph
35  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
36  * the permission of UNIX System Laboratories, Inc.
37  *
38  * Redistribution and use in source and binary forms, with or without
39  * modification, are permitted provided that the following conditions
40  * are met:
41  * 1. Redistributions of source code must retain the above copyright
42  *    notice, this list of conditions and the following disclaimer.
43  * 2. Redistributions in binary form must reproduce the above copyright
44  *    notice, this list of conditions and the following disclaimer in the
45  *    documentation and/or other materials provided with the distribution.
46  * 3. Neither the name of the University nor the names of its contributors
47  *    may be used to endorse or promote products derived from this software
48  *    without specific prior written permission.
49  *
50  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
51  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
53  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
54  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
55  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
56  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
57  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
58  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
59  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
60  * SUCH DAMAGE.
61  *
62  *        @(#)tty.c 8.13 (Berkeley) 1/9/95
63  */
64 
65 #include <sys/cdefs.h>
66 __KERNEL_RCSID(0, "$NetBSD: tty.c,v 1.313 2024/07/14 05:10:40 kre Exp $");
67 
68 #ifdef _KERNEL_OPT
69 #include "opt_compat_netbsd.h"
70 #endif
71 
72 #define TTY_ALLOW_PRIVATE
73 
74 #include <sys/param.h>
75 #include <sys/systm.h>
76 #include <sys/ioctl.h>
77 #include <sys/proc.h>
78 #define   TTYDEFCHARS
79 #include <sys/tty.h>
80 #undef    TTYDEFCHARS
81 #include <sys/file.h>
82 #include <sys/conf.h>
83 #include <sys/cpu.h>
84 #include <sys/dkstat.h>
85 #include <sys/uio.h>
86 #include <sys/kernel.h>
87 #include <sys/vnode.h>
88 #include <sys/syslog.h>
89 #include <sys/kmem.h>
90 #include <sys/signalvar.h>
91 #include <sys/resourcevar.h>
92 #include <sys/poll.h>
93 #include <sys/kprintf.h>
94 #include <sys/namei.h>
95 #include <sys/sysctl.h>
96 #include <sys/kauth.h>
97 #include <sys/intr.h>
98 #include <sys/ioctl_compat.h>
99 #include <sys/module.h>
100 #include <sys/bitops.h>
101 #include <sys/compat_stub.h>
102 #include <sys/atomic.h>
103 #include <sys/condvar.h>
104 #include <sys/pserialize.h>
105 
106 static int          ttnread(struct tty *);
107 static void         ttyblock(struct tty *);
108 static void         ttyecho(int, struct tty *);
109 static void         ttyrubo(struct tty *, int);
110 static void         ttyprintf_nolock(struct tty *, const char *fmt, ...)
111     __printflike(2, 3);
112 static int          proc_compare_wrapper(struct proc *, struct proc *);
113 static void         ttysigintr(void *);
114 
115 /* Symbolic sleep message strings. */
116 const char          ttclos[] = "ttycls";
117 const char          ttopen[] = "ttyopn";
118 const char          ttybg[] = "ttybg";
119 const char          ttyin[] = "ttyin";
120 const char          ttyout[] = "ttyout";
121 
122 /*
123  * Used to determine whether we still have a connection.  This is true in
124  * one of 3 cases:
125  * 1) We have carrier.
126  * 2) It's a locally attached terminal, and we are therefore ignoring carrier.
127  * 3) We're using a flow control mechanism that overloads the carrier signal.
128  */
129 #define   CONNECTED(tp)       (ISSET(tp->t_state, TS_CARR_ON) ||      \
130                                ISSET(tp->t_cflag, CLOCAL | MDMBUF))
131 
132 /*
133  * Table with character classes and parity. The 8th bit indicates parity,
134  * the 7th bit indicates the character is an alphameric or underscore (for
135  * ALTWERASE), and the low 6 bits indicate delay type.  If the low 6 bits
136  * are 0 then the character needs no special processing on output; classes
137  * other than 0 might be translated or (not currently) require delays.
138  */
139 #define   E         0x00      /* Even parity. */
140 #define   O         0x80      /* Odd parity. */
141 #define   PARITY(c) (char_type[c] & O)
142 
143 #define   ALPHA     0x40      /* Alpha or underscore. */
144 #define   ISALPHA(c)          (char_type[(c) & TTY_CHARMASK] & ALPHA)
145 
146 #define   CCLASSMASK          0x3f
147 #define   CCLASS(c) (char_type[c] & CCLASSMASK)
148 
149 #define   BS        BACKSPACE
150 #define   CC        CONTROL
151 #define   CR        RETURN
152 #define   NA        ORDINARY | ALPHA
153 #define   NL        NEWLINE
154 #define   NO        ORDINARY
155 #define   TB        TAB
156 #define   VT        VTAB
157 
158 unsigned char const char_type[] = {
159           E|CC, O|CC, O|CC, E|CC, O|CC, E|CC, E|CC, O|CC,   /* nul - bel */
160           O|BS, E|TB, E|NL, O|CC, E|VT, O|CR, O|CC, E|CC,   /* bs - si */
161           O|CC, E|CC, E|CC, O|CC, E|CC, O|CC, O|CC, E|CC,   /* dle - etb */
162           E|CC, O|CC, O|CC, E|CC, O|CC, E|CC, E|CC, O|CC,   /* can - us */
163           O|NO, E|NO, E|NO, O|NO, E|NO, O|NO, O|NO, E|NO,   /* sp - ' */
164           E|NO, O|NO, O|NO, E|NO, O|NO, E|NO, E|NO, O|NO,   /* ( - / */
165           E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA,   /* 0 - 7 */
166           O|NA, E|NA, E|NO, O|NO, E|NO, O|NO, O|NO, E|NO,   /* 8 - ? */
167           O|NO, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA,   /* @ - G */
168           E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA,   /* H - O */
169           E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA,   /* P - W */
170           O|NA, E|NA, E|NA, O|NO, E|NO, O|NO, O|NO, O|NA,   /* X - _ */
171           E|NO, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA,   /* ` - g */
172           O|NA, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA,   /* h - o */
173           O|NA, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA,   /* p - w */
174           E|NA, O|NA, O|NA, E|NO, O|NO, E|NO, E|NO, O|CC,   /* x - del */
175           /*
176            * Meta chars; should be settable per character set;
177            * for now, treat them all as normal characters.
178            */
179           NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
180           NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
181           NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
182           NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
183           NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
184           NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
185           NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
186           NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
187           NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
188           NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
189           NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
190           NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
191           NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
192           NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
193           NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
194           NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
195 };
196 #undef    BS
197 #undef    CC
198 #undef    CR
199 #undef    NA
200 #undef    NL
201 #undef    NO
202 #undef    TB
203 #undef    VT
204 
205 static struct ttylist_head tty_sigqueue = TAILQ_HEAD_INITIALIZER(tty_sigqueue);
206 static void *tty_sigsih;
207 
208 struct ttylist_head ttylist = TAILQ_HEAD_INITIALIZER(ttylist);
209 int tty_count;
210 kmutex_t tty_lock;
211 kmutex_t constty_lock;
212 static struct pserialize *constty_psz;
213 static kcondvar_t ttyref_cv;
214 
215 struct ptm_pty *ptm = NULL;
216 
217 uint64_t tk_cancc;
218 uint64_t tk_nin;
219 uint64_t tk_nout;
220 uint64_t tk_rawcc;
221 
222 static kauth_listener_t tty_listener;
223 
224 #define   TTY_MINQSIZE        0x00400
225 #define   TTY_MAXQSIZE        0x10000
226 int tty_qsize = TTY_MINQSIZE;
227 
228 static int
tty_get_qsize(int * qsize,int newsize)229 tty_get_qsize(int *qsize, int newsize)
230 {
231           if (newsize <= 0)
232                     return EINVAL;
233 
234           newsize = 1 << ilog2(newsize);          /* Make it a power of two */
235 
236           if (newsize < TTY_MINQSIZE || newsize > TTY_MAXQSIZE)
237                     return EINVAL;
238 
239           *qsize = newsize;
240           return 0;
241 }
242 
243 static int
tty_set_qsize(struct tty * tp,int newsize)244 tty_set_qsize(struct tty *tp, int newsize)
245 {
246           struct clist rawq, canq, outq;
247           struct clist orawq, ocanq, ooutq;
248 
249           clalloc(&rawq, newsize, 1);
250           clalloc(&canq, newsize, 1);
251           clalloc(&outq, newsize, 0);
252 
253           mutex_spin_enter(&tty_lock);
254 
255           if (tp->t_outq.c_cc != 0) {
256                     mutex_spin_exit(&tty_lock);
257                     clfree(&rawq);
258                     clfree(&canq);
259                     clfree(&outq);
260                     return EBUSY;
261           }
262 
263           orawq = tp->t_rawq;
264           ocanq = tp->t_canq;
265           ooutq = tp->t_outq;
266 
267           tp->t_qsize = newsize;
268           tp->t_rawq = rawq;
269           tp->t_canq = canq;
270           tp->t_outq = outq;
271 
272           ttsetwater(tp);
273 
274           mutex_spin_exit(&tty_lock);
275 
276           clfree(&orawq);
277           clfree(&ocanq);
278           clfree(&ooutq);
279 
280           return 0;
281 }
282 
283 static int
sysctl_kern_tty_qsize(SYSCTLFN_ARGS)284 sysctl_kern_tty_qsize(SYSCTLFN_ARGS)
285 {
286           int newsize;
287           int error;
288           struct sysctlnode node;
289           node = *rnode;
290           node.sysctl_data = &newsize;
291 
292           newsize = tty_qsize;
293           error = sysctl_lookup(SYSCTLFN_CALL(&node));
294           if (error || newp == NULL)
295                     return error;
296 
297 
298           return tty_get_qsize(&tty_qsize, newsize);
299 }
300 
301 static void
sysctl_kern_tty_setup(void)302 sysctl_kern_tty_setup(void)
303 {
304           const struct sysctlnode *rnode, *cnode;
305 
306           sysctl_createv(NULL, 0, NULL, NULL,
307                            CTLFLAG_PERMANENT,
308                            CTLTYPE_NODE, "tkstat",
309                            SYSCTL_DESCR("Number of characters sent and received "
310                                             "on ttys"),
311                            NULL, 0, NULL, 0,
312                            CTL_KERN, KERN_TKSTAT, CTL_EOL);
313 
314           sysctl_createv(NULL, 0, NULL, NULL,
315                            CTLFLAG_PERMANENT,
316                            CTLTYPE_QUAD, "nin",
317                            SYSCTL_DESCR("Total number of tty input characters"),
318                            NULL, 0, &tk_nin, 0,
319                            CTL_KERN, KERN_TKSTAT, KERN_TKSTAT_NIN, CTL_EOL);
320           sysctl_createv(NULL, 0, NULL, NULL,
321                            CTLFLAG_PERMANENT,
322                            CTLTYPE_QUAD, "nout",
323                            SYSCTL_DESCR("Total number of tty output characters"),
324                            NULL, 0, &tk_nout, 0,
325                            CTL_KERN, KERN_TKSTAT, KERN_TKSTAT_NOUT, CTL_EOL);
326           sysctl_createv(NULL, 0, NULL, NULL,
327                            CTLFLAG_PERMANENT,
328                            CTLTYPE_QUAD, "cancc",
329                            SYSCTL_DESCR("Number of canonical tty input characters"),
330                            NULL, 0, &tk_cancc, 0,
331                            CTL_KERN, KERN_TKSTAT, KERN_TKSTAT_CANCC, CTL_EOL);
332           sysctl_createv(NULL, 0, NULL, NULL,
333                            CTLFLAG_PERMANENT,
334                            CTLTYPE_QUAD, "rawcc",
335                            SYSCTL_DESCR("Number of raw tty input characters"),
336                            NULL, 0, &tk_rawcc, 0,
337                            CTL_KERN, KERN_TKSTAT, KERN_TKSTAT_RAWCC, CTL_EOL);
338 
339           sysctl_createv(NULL, 0, NULL, &rnode,
340                            CTLFLAG_PERMANENT,
341                            CTLTYPE_NODE, "tty", NULL,
342                            NULL, 0, NULL, 0,
343                            CTL_KERN, CTL_CREATE, CTL_EOL);
344           sysctl_createv(NULL, 0, &rnode, &cnode,
345                            CTLFLAG_PERMANENT | CTLFLAG_READWRITE,
346                            CTLTYPE_INT, "qsize",
347                            SYSCTL_DESCR("TTY input and output queue size"),
348                            sysctl_kern_tty_qsize, 0, &tty_qsize, 0,
349                            CTL_CREATE, CTL_EOL);
350 }
351 
352 /*
353  * ttylock(tp), ttyunlock(tp), ttylocked(tp)
354  *
355  *        Exclusive lock on tty.  Currently a single global lock.
356  *
357  *        ttylocked is for positive DIAGNOSTIC assertions only.
358  */
359 void
ttylock(struct tty * tp)360 ttylock(struct tty *tp)
361 {
362 
363           mutex_spin_enter(&tty_lock);
364 }
365 
366 void
ttyunlock(struct tty * tp)367 ttyunlock(struct tty *tp)
368 {
369 
370           mutex_spin_exit(&tty_lock);
371 }
372 
373 bool
ttylocked(struct tty * tp)374 ttylocked(struct tty *tp)
375 {
376 
377           return mutex_owned(&tty_lock);
378 }
379 
380 int
ttyopen(struct tty * tp,int dialout,int nonblock)381 ttyopen(struct tty *tp, int dialout, int nonblock)
382 {
383           int       error;
384 
385           error = 0;
386 
387           mutex_spin_enter(&tty_lock);
388 
389           if (dialout) {
390                     /*
391                      * If the device is already open for non-dialout, fail.
392                      * Otherwise, set TS_DIALOUT to block any pending non-dialout
393                      * opens.
394                      */
395                     if (ISSET(tp->t_state, TS_ISOPEN) &&
396                         !ISSET(tp->t_state, TS_DIALOUT)) {
397                               error = EBUSY;
398                               goto out;
399                     }
400                     SET(tp->t_state, TS_DIALOUT);
401           } else {
402                     if (!nonblock) {
403                               /*
404                                * Wait for carrier.  Also wait for any dialout
405                                * processes to close the tty first.
406                                */
407                               while (ISSET(tp->t_state, TS_DIALOUT) ||
408                                      !CONNECTED(tp)) {
409                                         tp->t_wopen++;
410                                         error = ttysleep(tp, &tp->t_rawcv, true, 0);
411                                         tp->t_wopen--;
412                                         if (error)
413                                                   goto out;
414                               }
415                     } else {
416                               /*
417                                * Don't allow a non-blocking non-dialout open if the
418                                * device is already open for dialout.
419                                */
420                               if (ISSET(tp->t_state, TS_DIALOUT)) {
421                                         error = EBUSY;
422                                         goto out;
423                               }
424                     }
425           }
426 
427 out:
428           mutex_spin_exit(&tty_lock);
429           return (error);
430 }
431 
432 /*
433  * Initial open of tty, or (re)entry to standard tty line discipline.
434  */
435 int
ttylopen(dev_t device,struct tty * tp)436 ttylopen(dev_t device, struct tty *tp)
437 {
438 
439           mutex_spin_enter(&tty_lock);
440           tp->t_dev = device;
441           if (!ISSET(tp->t_state, TS_ISOPEN)) {
442                     SET(tp->t_state, TS_ISOPEN);
443                     memset(&tp->t_winsize, 0, sizeof(tp->t_winsize));
444                     tp->t_flags = 0;
445           }
446           mutex_spin_exit(&tty_lock);
447           if (tp->t_qsize != tty_qsize)
448                     tty_set_qsize(tp, tty_qsize);
449           return (0);
450 }
451 
452 /*
453  * Interrupt any pending I/O and make it fail.  Used before close to
454  * interrupt pending open/read/write/&c. and make it fail promptly.
455  */
456 void
ttycancel(struct tty * tp)457 ttycancel(struct tty *tp)
458 {
459 
460           mutex_spin_enter(&tty_lock);
461           tp->t_state |= TS_CANCEL;
462           cv_broadcast(&tp->t_outcv);
463           cv_broadcast(&tp->t_rawcv);
464           mutex_spin_exit(&tty_lock);
465 }
466 
467 /*
468  * Handle close() on a tty line: flush and set to initial state,
469  * bumping generation number so that pending read/write calls
470  * can detect recycling of the tty.
471  */
472 int
ttyclose(struct tty * tp)473 ttyclose(struct tty *tp)
474 {
475           struct session *sess;
476 
477           /*
478            * Make sure this is not the constty.  Without constty_lock it
479            * is always allowed to transition from nonnull to null.
480            */
481           (void)atomic_cas_ptr(&constty, tp, NULL);
482 
483           /*
484            * We don't know if this has _ever_ been the constty: another
485            * thread may have kicked it out as constty before we started
486            * to close.
487            *
488            * So we wait for all users that might be acquiring references
489            * to finish doing so -- after that, no more references can be
490            * made, at which point we can safely flush the tty, wait for
491            * the existing references to drain, and finally free or reuse
492            * the tty.
493            */
494           pserialize_perform(constty_psz);
495 
496           mutex_spin_enter(&tty_lock);
497 
498           ttyflush(tp, FREAD | FWRITE);
499 
500           tp->t_gen++;
501           tp->t_pgrp = NULL;
502           tp->t_state = 0;
503           sess = tp->t_session;
504           tp->t_session = NULL;
505 
506           while (tp->t_refcnt)
507                     cv_wait(&ttyref_cv, &tty_lock);
508 
509           mutex_spin_exit(&tty_lock);
510 
511           if (sess != NULL) {
512                     mutex_enter(&proc_lock);
513                     /* Releases proc_lock. */
514                     proc_sessrele(sess);
515           }
516           return (0);
517 }
518 
519 #define   FLUSHQ(q) {                                                                     \
520           if ((q)->c_cc)                                                                  \
521                     ndflush(q, (q)->c_cc);                                                \
522 }
523 
524 /*
525  * tty_acquire(tp), tty_release(tp)
526  *
527  *        Acquire a reference to tp that prevents it from being closed
528  *        until released.  Caller must guarantee tp has not yet been
529  *        closed, e.g. by obtaining tp from constty during a pserialize
530  *        read section.  Caller must not hold tty_lock.
531  */
532 void
tty_acquire(struct tty * tp)533 tty_acquire(struct tty *tp)
534 {
535           unsigned refcnt __diagused;
536 
537           refcnt = atomic_inc_uint_nv(&tp->t_refcnt);
538           KASSERT(refcnt < UINT_MAX);
539 }
540 
541 void
tty_release(struct tty * tp)542 tty_release(struct tty *tp)
543 {
544           unsigned old, new;
545 
546           KDASSERT(mutex_ownable(&tty_lock));
547 
548           do {
549                     old = atomic_load_relaxed(&tp->t_refcnt);
550                     if (old == 1) {
551                               mutex_spin_enter(&tty_lock);
552                               if (atomic_dec_uint_nv(&tp->t_refcnt) == 0)
553                                         cv_broadcast(&ttyref_cv);
554                               mutex_spin_exit(&tty_lock);
555                               return;
556                     }
557                     KASSERT(old != 0);
558                     new = old - 1;
559           } while (atomic_cas_uint(&tp->t_refcnt, old, new) != old);
560 }
561 
562 /*
563  * This macro is used in canonical mode input processing, where a read
564  * request shall not return unless a 'line delimiter' ('\n') or 'break'
565  * (EOF, EOL, EOL2) character (or a signal) has been received. As EOL2
566  * is an extension to the POSIX.1 defined set of special characters,
567  * recognize it only if IEXTEN is set in the set of local flags.
568  */
569 #define   TTBREAKC(c, lflg)                                                     \
570           ((c) == '\n' || (((c) == cc[VEOF] || (c) == cc[VEOL] ||               \
571           ((c) == cc[VEOL2] && ISSET(lflg, IEXTEN))) && (c) != _POSIX_VDISABLE))
572 
573 
574 
575 /*
576  * ttyinput() helper.
577  * Call with the tty lock held.
578  */
579 /* XXX static */ int
ttyinput_wlock(int c,struct tty * tp)580 ttyinput_wlock(int c, struct tty *tp)
581 {
582           int       iflag, lflag, i, error;
583           u_char    *cc;
584 
585           KASSERT(mutex_owned(&tty_lock));
586 
587           /*
588            * If input is pending take it first.
589            */
590           lflag = tp->t_lflag;
591           if (ISSET(lflag, PENDIN))
592                     ttypend(tp);
593           /*
594            * Gather stats.
595            */
596           if (ISSET(lflag, ICANON)) {
597                     ++tk_cancc;
598                     ++tp->t_cancc;
599           } else {
600                     ++tk_rawcc;
601                     ++tp->t_rawcc;
602           }
603           ++tk_nin;
604 
605           cc = tp->t_cc;
606 
607           /*
608            * Handle exceptional conditions (break, parity, framing).
609            */
610           iflag = tp->t_iflag;
611           if ((error = (ISSET(c, TTY_ERRORMASK))) != 0) {
612                     CLR(c, TTY_ERRORMASK);
613                     if (ISSET(error, TTY_FE) && c == 0) {             /* Break. */
614                               if (ISSET(iflag, IGNBRK))
615                                         return (0);
616                               else if (ISSET(iflag, BRKINT)) {
617                                         ttyflush(tp, FREAD | FWRITE);
618                                         ttysig(tp, TTYSIG_PG1, SIGINT);
619                                         return (0);
620                               } else if (ISSET(iflag, PARMRK))
621                                         goto parmrk;
622                     } else if ((ISSET(error, TTY_PE) && ISSET(iflag, INPCK)) ||
623                         ISSET(error, TTY_FE)) {
624                               if (ISSET(iflag, IGNPAR))
625                                         return (0);
626                               else if (ISSET(iflag, PARMRK)) {
627  parmrk:                      (void)putc(0377 | TTY_QUOTE, &tp->t_rawq);
628                                         (void)putc(0    | TTY_QUOTE, &tp->t_rawq);
629                                         (void)putc(c    | TTY_QUOTE, &tp->t_rawq);
630                                         return (0);
631                               } else
632                                         c = 0;
633                     }
634           } else if (c == 0377 &&
635               ISSET(iflag, ISTRIP|IGNPAR|INPCK|PARMRK) == (INPCK|PARMRK)) {
636                     /* "Escape" a valid character of '\377'. */
637                     (void)putc(0377 | TTY_QUOTE, &tp->t_rawq);
638                     (void)putc(0377 | TTY_QUOTE, &tp->t_rawq);
639                     goto endcase;
640           }
641 
642           /*
643            * In tandem mode, check high water mark.
644            */
645           if (ISSET(iflag, IXOFF) || ISSET(tp->t_cflag, CHWFLOW))
646                     ttyblock(tp);
647           if (!ISSET(tp->t_state, TS_TYPEN) && ISSET(iflag, ISTRIP))
648                     CLR(c, 0x80);
649           if (!ISSET(lflag, EXTPROC)) {
650                     /*
651                      * Check for literal nexting very first
652                      */
653                     if (ISSET(tp->t_state, TS_LNCH)) {
654                               SET(c, TTY_QUOTE);
655                               CLR(tp->t_state, TS_LNCH);
656                     }
657                     /*
658                      * Scan for special characters.  This code
659                      * is really just a big case statement with
660                      * non-constant cases.  The bottom of the
661                      * case statement is labeled ``endcase'', so goto
662                      * it after a case match, or similar.
663                      */
664 
665                     /*
666                      * Control chars which aren't controlled
667                      * by ICANON, ISIG, or IXON.
668                      */
669                     if (ISSET(lflag, IEXTEN)) {
670                               if (CCEQ(cc[VLNEXT], c)) {
671                                         if (ISSET(lflag, ECHO)) {
672                                                   if (ISSET(lflag, ECHOE)) {
673                                                             (void)ttyoutput('^', tp);
674                                                             (void)ttyoutput('\b', tp);
675                                                   } else
676                                                             ttyecho(c, tp);
677                                         }
678                                         SET(tp->t_state, TS_LNCH);
679                                         goto endcase;
680                               }
681                               if (CCEQ(cc[VDISCARD], c)) {
682                                         if (ISSET(lflag, FLUSHO))
683                                                   CLR(tp->t_lflag, FLUSHO);
684                                         else {
685                                                   ttyflush(tp, FWRITE);
686                                                   ttyecho(c, tp);
687                                                   if (tp->t_rawq.c_cc + tp->t_canq.c_cc)
688                                                             ttyretype(tp);
689                                                   SET(tp->t_lflag, FLUSHO);
690                                         }
691                                         goto startoutput;
692                               }
693                     }
694                     /*
695                      * Signals.
696                      */
697                     if (ISSET(lflag, ISIG)) {
698                               if (CCEQ(cc[VINTR], c) || CCEQ(cc[VQUIT], c)) {
699                                         if (!ISSET(lflag, NOFLSH))
700                                                   ttyflush(tp, FREAD | FWRITE);
701                                         ttyecho(c, tp);
702                                         ttysig(tp, TTYSIG_PG1, CCEQ(cc[VINTR], c) ?
703                                             SIGINT : SIGQUIT);
704                                         goto endcase;
705                               }
706                               if (CCEQ(cc[VSUSP], c)) {
707                                         if (!ISSET(lflag, NOFLSH))
708                                                   ttyflush(tp, FREAD);
709                                         ttyecho(c, tp);
710                                         ttysig(tp, TTYSIG_PG1, SIGTSTP);
711                                         goto endcase;
712                               }
713                     }
714                     /*
715                      * Handle start/stop characters.
716                      */
717                     if (ISSET(iflag, IXON)) {
718                               if (CCEQ(cc[VSTOP], c)) {
719                                         if (!ISSET(tp->t_state, TS_TTSTOP)) {
720                                                   SET(tp->t_state, TS_TTSTOP);
721                                                   cdev_stop(tp, 0);
722                                                   return (0);
723                                         }
724                                         if (!CCEQ(cc[VSTART], c))
725                                                   return (0);
726                                         /*
727                                          * if VSTART == VSTOP then toggle
728                                          */
729                                         goto endcase;
730                               }
731                               if (CCEQ(cc[VSTART], c))
732                                         goto restartoutput;
733                     }
734                     /*
735                      * IGNCR, ICRNL, & INLCR
736                      */
737                     if (c == '\r') {
738                               if (ISSET(iflag, IGNCR))
739                                         goto endcase;
740                               else if (ISSET(iflag, ICRNL))
741                                         c = '\n';
742                     } else if (c == '\n' && ISSET(iflag, INLCR))
743                               c = '\r';
744           }
745           if (!ISSET(lflag, EXTPROC) && ISSET(lflag, ICANON)) {
746                     /*
747                      * From here on down canonical mode character
748                      * processing takes place.
749                      */
750                     /*
751                      * erase (^H / ^?)
752                      */
753                     if (CCEQ(cc[VERASE], c)) {
754                               if (tp->t_rawq.c_cc)
755                                         ttyrub(unputc(&tp->t_rawq), tp);
756                               goto endcase;
757                     }
758                     /*
759                      * kill (^U)
760                      */
761                     if (CCEQ(cc[VKILL], c)) {
762                               if (ISSET(lflag, ECHOKE) &&
763                                   tp->t_rawq.c_cc == tp->t_rocount &&
764                                   !ISSET(lflag, ECHOPRT))
765                                         while (tp->t_rawq.c_cc)
766                                                   ttyrub(unputc(&tp->t_rawq), tp);
767                               else {
768                                         ttyecho(c, tp);
769                                         if (ISSET(lflag, ECHOK) ||
770                                             ISSET(lflag, ECHOKE))
771                                                   ttyecho('\n', tp);
772                                         FLUSHQ(&tp->t_rawq);
773                                         tp->t_rocount = 0;
774                               }
775                               CLR(tp->t_state, TS_LOCAL);
776                               goto endcase;
777                     }
778                     /*
779                      * Extensions to the POSIX.1 GTI set of functions.
780                      */
781                     if (ISSET(lflag, IEXTEN)) {
782                               /*
783                                * word erase (^W)
784                                */
785                               if (CCEQ(cc[VWERASE], c)) {
786                                         int alt = ISSET(lflag, ALTWERASE);
787                                         int ctype;
788 
789                                         /*
790                                          * erase whitespace
791                                          */
792                                         while ((c = unputc(&tp->t_rawq)) == ' ' ||
793                                             c == '\t')
794                                                   ttyrub(c, tp);
795                                         if (c == -1)
796                                                   goto endcase;
797                                         /*
798                                          * erase last char of word and remember the
799                                          * next chars type (for ALTWERASE)
800                                          */
801                                         ttyrub(c, tp);
802                                         c = unputc(&tp->t_rawq);
803                                         if (c == -1)
804                                                   goto endcase;
805                                         if (c == ' ' || c == '\t') {
806                                                   (void)putc(c, &tp->t_rawq);
807                                                   goto endcase;
808                                         }
809                                         ctype = ISALPHA(c);
810                                         /*
811                                          * erase rest of word
812                                          */
813                                         do {
814                                                   ttyrub(c, tp);
815                                                   c = unputc(&tp->t_rawq);
816                                                   if (c == -1)
817                                                             goto endcase;
818                                         } while (c != ' ' && c != '\t' &&
819                                             (alt == 0 || ISALPHA(c) == ctype));
820                                         (void)putc(c, &tp->t_rawq);
821                                         goto endcase;
822                               }
823                               /*
824                                * reprint line (^R)
825                                */
826                               if (CCEQ(cc[VREPRINT], c)) {
827                                         ttyretype(tp);
828                                         goto endcase;
829                               }
830                               /*
831                                * ^T - kernel info and generate SIGINFO
832                                */
833                               if (CCEQ(cc[VSTATUS], c)) {
834                                         ttysig(tp, TTYSIG_PG1, SIGINFO);
835                                         goto endcase;
836                               }
837                     }
838           }
839           /*
840            * Check for input buffer overflow
841            */
842           if (tp->t_rawq.c_cc + tp->t_canq.c_cc >= TTYHOG) {
843                     if (ISSET(iflag, IMAXBEL)) {
844                               if (tp->t_outq.c_cc < tp->t_hiwat)
845                                         (void)ttyoutput(CTRL('g'), tp);
846                     } else
847                               ttyflush(tp, FREAD | FWRITE);
848                     goto endcase;
849           }
850           /*
851            * Put data char in q for user and
852            * wakeup on seeing a line delimiter.
853            */
854           if (putc(c, &tp->t_rawq) >= 0) {
855                     if (!ISSET(lflag, ICANON)) {
856                               ttwakeup(tp);
857                               ttyecho(c, tp);
858                               goto endcase;
859                     }
860                     if (TTBREAKC(c, lflag)) {
861                               tp->t_rocount = 0;
862                               catq(&tp->t_rawq, &tp->t_canq);
863                               ttwakeup(tp);
864                     } else if (tp->t_rocount++ == 0)
865                               tp->t_rocol = tp->t_column;
866                     if (ISSET(tp->t_state, TS_ERASE)) {
867                               /*
868                                * end of prterase \.../
869                                */
870                               CLR(tp->t_state, TS_ERASE);
871                               (void)ttyoutput('/', tp);
872                     }
873                     i = tp->t_column;
874                     ttyecho(c, tp);
875                     if (CCEQ(cc[VEOF], c) && ISSET(lflag, ECHO)) {
876                               /*
877                                * Place the cursor over the '^' of the ^D.
878                                */
879                               i = uimin(2, tp->t_column - i);
880                               while (i > 0) {
881                                         (void)ttyoutput('\b', tp);
882                                         i--;
883                               }
884                     }
885           }
886  endcase:
887           /*
888            * IXANY means allow any character to restart output.
889            */
890           if (ISSET(tp->t_state, TS_TTSTOP) &&
891               !ISSET(iflag, IXANY) && cc[VSTART] != cc[VSTOP]) {
892                     return (0);
893           }
894  restartoutput:
895           CLR(tp->t_lflag, FLUSHO);
896           CLR(tp->t_state, TS_TTSTOP);
897  startoutput:
898           return (ttstart(tp));
899 }
900 
901 /*
902  * Process input of a single character received on a tty.
903  *
904  * XXX - this is a hack, all drivers must changed to acquire the
905  *         lock before calling linesw->l_rint()
906  */
907 int
ttyinput(int c,struct tty * tp)908 ttyinput(int c, struct tty *tp)
909 {
910           int error;
911 
912           /*
913            * Unless the receiver is enabled, drop incoming data.
914            */
915           if (!ISSET(tp->t_cflag, CREAD))
916                     return (0);
917 
918           mutex_spin_enter(&tty_lock);
919           error = ttyinput_wlock(c, tp);
920           mutex_spin_exit(&tty_lock);
921 
922           return (error);
923 }
924 
925 /*
926  * Output a single character on a tty, doing output processing
927  * as needed (expanding tabs, newline processing, etc.).
928  * Returns < 0 if succeeds, otherwise returns char to resend.
929  * Must be recursive.
930  *
931  * Call with tty lock held.
932  */
933 int
ttyoutput(int c,struct tty * tp)934 ttyoutput(int c, struct tty *tp)
935 {
936           long      oflag;
937           int       col, notout;
938 
939           KASSERT(mutex_owned(&tty_lock));
940 
941           oflag = tp->t_oflag;
942           if (!ISSET(oflag, OPOST)) {
943                     tk_nout++;
944                     tp->t_outcc++;
945                     if (!ISSET(tp->t_lflag, FLUSHO) && putc(c, &tp->t_outq))
946                               return (c);
947                     return (-1);
948           }
949           /*
950            * Do tab expansion if OXTABS is set.  Special case if we do external
951            * processing, we don't do the tab expansion because we'll probably
952            * get it wrong.  If tab expansion needs to be done, let it happen
953            * externally.
954            */
955           CLR(c, ~TTY_CHARMASK);
956           if (c == '\t' &&
957               ISSET(oflag, OXTABS) && !ISSET(tp->t_lflag, EXTPROC)) {
958                     c = 8 - (tp->t_column & 7);
959                     if (ISSET(tp->t_lflag, FLUSHO)) {
960                               notout = 0;
961                     } else {
962                               notout = b_to_q("        ", c, &tp->t_outq);
963                               c -= notout;
964                               tk_nout += c;
965                               tp->t_outcc += c;
966                     }
967                     tp->t_column += c;
968                     return (notout ? '\t' : -1);
969           }
970           if (c == CEOT && ISSET(oflag, ONOEOT))
971                     return (-1);
972 
973           /*
974            * Newline translation: if ONLCR is set,
975            * translate newline into "\r\n".
976            */
977           if (c == '\n' && ISSET(tp->t_oflag, ONLCR)) {
978                     tk_nout++;
979                     tp->t_outcc++;
980                     if (!ISSET(tp->t_lflag, FLUSHO) && putc('\r', &tp->t_outq))
981                               return (c);
982           }
983           /* If OCRNL is set, translate "\r" into "\n". */
984           else if (c == '\r' && ISSET(tp->t_oflag, OCRNL))
985                     c = '\n';
986           /* If ONOCR is set, don't transmit CRs when on column 0. */
987           else if (c == '\r' && ISSET(tp->t_oflag, ONOCR) && tp->t_column == 0)
988                     return (-1);
989 
990           tk_nout++;
991           tp->t_outcc++;
992           if (!ISSET(tp->t_lflag, FLUSHO) && putc(c, &tp->t_outq))
993                     return (c);
994 
995           col = tp->t_column;
996           switch (CCLASS(c)) {
997           case BACKSPACE:
998                     if (col > 0)
999                               --col;
1000                     break;
1001           case CONTROL:
1002                     break;
1003           case NEWLINE:
1004                     if (ISSET(tp->t_oflag, ONLCR | ONLRET))
1005                               col = 0;
1006                     break;
1007           case RETURN:
1008                     col = 0;
1009                     break;
1010           case ORDINARY:
1011                     ++col;
1012                     break;
1013           case TAB:
1014                     col = (col + 8) & ~7;
1015                     break;
1016           }
1017           tp->t_column = col;
1018           return (-1);
1019 }
1020 
1021 /*
1022  * Ioctls for all tty devices.  Called after line-discipline specific ioctl
1023  * has been called to do discipline-specific functions and/or reject any
1024  * of these ioctl commands.
1025  */
1026 /* ARGSUSED */
1027 int
ttioctl(struct tty * tp,u_long cmd,void * data,int flag,struct lwp * l)1028 ttioctl(struct tty *tp, u_long cmd, void *data, int flag, struct lwp *l)
1029 {
1030           struct proc *p;
1031           struct linesw       *lp;
1032           int                 s, error;
1033           struct pathbuf *pb;
1034           struct nameidata nd;
1035           char                infobuf[200];
1036 
1037           KASSERT(l != NULL);
1038           p = l->l_proc;
1039 
1040           /* If the ioctl involves modification, hang if in the background. */
1041           switch (cmd) {
1042           case  TIOCFLUSH:
1043           case  TIOCDRAIN:
1044           case  TIOCSBRK:
1045           case  TIOCCBRK:
1046           case  TIOCSTART:
1047           case  TIOCSETA:
1048           case  TIOCSETD:
1049           case  TIOCSLINED:
1050           case  TIOCSETAF:
1051           case  TIOCSETAW:
1052 #ifdef notdef
1053           case  TIOCSPGRP:
1054           case  FIOSETOWN:
1055 #endif
1056           case  TIOCSTAT:
1057           case  TIOCSTI:
1058           case  TIOCSWINSZ:
1059           case  TIOCSQSIZE:
1060           case  TIOCLBIC:
1061           case  TIOCLBIS:
1062           case  TIOCLSET:
1063           case  TIOCSETC:
1064           case OTIOCSETD:
1065           case  TIOCSETN:
1066           case  TIOCSETP:
1067           case  TIOCSLTC:
1068                     mutex_spin_enter(&tty_lock);
1069                     while (isbackground(curproc, tp) &&
1070                         p->p_pgrp->pg_jobc && (p->p_lflag & PL_PPWAIT) == 0 &&
1071                         !sigismasked(l, SIGTTOU)) {
1072                               mutex_spin_exit(&tty_lock);
1073 
1074                               mutex_enter(&proc_lock);
1075                               pgsignal(p->p_pgrp, SIGTTOU, 1);
1076                               mutex_exit(&proc_lock);
1077 
1078                               mutex_spin_enter(&tty_lock);
1079                               error = ttypause(tp, hz);
1080                               if (error) {
1081                                         mutex_spin_exit(&tty_lock);
1082                                         return (error);
1083                               }
1084                     }
1085                     mutex_spin_exit(&tty_lock);
1086                     break;
1087           }
1088 
1089           switch (cmd) {                          /* Process the ioctl. */
1090           case FIOASYNC:                          /* set/clear async i/o */
1091                     mutex_spin_enter(&tty_lock);
1092                     if (*(int *)data)
1093                               SET(tp->t_state, TS_ASYNC);
1094                     else
1095                               CLR(tp->t_state, TS_ASYNC);
1096                     mutex_spin_exit(&tty_lock);
1097                     break;
1098           case FIONBIO:                           /* set/clear non-blocking i/o */
1099                     break;                        /* XXX: delete. */
1100           case FIONREAD:                          /* get # bytes to read */
1101                     mutex_spin_enter(&tty_lock);
1102                     *(int *)data = ttnread(tp);
1103                     mutex_spin_exit(&tty_lock);
1104                     break;
1105           case FIONWRITE:                         /* get # bytes to written & unsent */
1106                     mutex_spin_enter(&tty_lock);
1107                     *(int *)data = tp->t_outq.c_cc;
1108                     mutex_spin_exit(&tty_lock);
1109                     break;
1110           case FIONSPACE:                         /* get # bytes to written & unsent */
1111                     mutex_spin_enter(&tty_lock);
1112                     *(int *)data = tp->t_outq.c_cn - tp->t_outq.c_cc;
1113                     mutex_spin_exit(&tty_lock);
1114                     break;
1115           case TIOCEXCL:                          /* set exclusive use of tty */
1116                     mutex_spin_enter(&tty_lock);
1117                     SET(tp->t_state, TS_XCLUDE);
1118                     mutex_spin_exit(&tty_lock);
1119                     break;
1120           case TIOCFLUSH: {             /* flush buffers */
1121                     int flags = *(int *)data;
1122 
1123                     if (flags == 0)
1124                               flags = FREAD | FWRITE;
1125                     else
1126                               flags &= FREAD | FWRITE;
1127                     mutex_spin_enter(&tty_lock);
1128                     ttyflush(tp, flags);
1129                     mutex_spin_exit(&tty_lock);
1130                     break;
1131           }
1132           case TIOCCONS: {              /* become virtual console */
1133                     struct tty *ctp;
1134 
1135                     mutex_enter(&constty_lock);
1136                     error = 0;
1137                     ctp = atomic_load_relaxed(&constty);
1138                     if (*(int *)data) {
1139                               if (ctp != NULL && ctp != tp &&
1140                                   ISSET(ctp->t_state, TS_CARR_ON | TS_ISOPEN) ==
1141                                   (TS_CARR_ON | TS_ISOPEN)) {
1142                                         error = EBUSY;
1143                                         goto unlock_constty;
1144                               }
1145 
1146                               pb = pathbuf_create("/dev/console");
1147                               if (pb == NULL) {
1148                                         error = ENOMEM;
1149                                         goto unlock_constty;
1150                               }
1151                               NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, pb);
1152                               if ((error = namei(&nd)) != 0) {
1153                                         pathbuf_destroy(pb);
1154                                         goto unlock_constty;
1155                               }
1156                               error = VOP_ACCESS(nd.ni_vp, VREAD, l->l_cred);
1157                               vput(nd.ni_vp);
1158                               pathbuf_destroy(pb);
1159                               if (error)
1160                                         goto unlock_constty;
1161 
1162                               KASSERT(atomic_load_relaxed(&constty) == ctp ||
1163                                   atomic_load_relaxed(&constty) == NULL);
1164                               atomic_store_release(&constty, tp);
1165                     } else if (tp == ctp) {
1166                               atomic_store_relaxed(&constty, NULL);
1167                     }
1168 unlock_constty:     mutex_exit(&constty_lock);
1169                     if (error)
1170                               return error;
1171                     break;
1172           }
1173           case TIOCDRAIN:                         /* wait till output drained */
1174                     if ((error = ttywait(tp)) != 0)
1175                               return (error);
1176                     break;
1177           case TIOCGETA: {              /* get termios struct */
1178                     struct termios *t = (struct termios *)data;
1179 
1180                     memcpy(t, &tp->t_termios, sizeof(struct termios));
1181                     break;
1182           }
1183           case TIOCGETD:                          /* get line discipline (old) */
1184                     *(int *)data = tp->t_linesw->l_no;
1185                     break;
1186           case TIOCGLINED:              /* get line discipline (new) */
1187                     (void)strncpy((char *)data, tp->t_linesw->l_name,
1188                         TTLINEDNAMELEN - 1);
1189                     break;
1190           case TIOCGWINSZ:              /* get window size */
1191                     *(struct winsize *)data = tp->t_winsize;
1192                     break;
1193           case TIOCGQSIZE:
1194                     *(int *)data = tp->t_qsize;
1195                     break;
1196           case FIOGETOWN:
1197                     mutex_enter(&proc_lock);
1198                     if (tp->t_session != NULL && !isctty(p, tp)) {
1199                               mutex_exit(&proc_lock);
1200                               return (ENOTTY);
1201                     }
1202                     *(int *)data = tp->t_pgrp ? -tp->t_pgrp->pg_id : 0;
1203                     mutex_exit(&proc_lock);
1204                     break;
1205           case TIOCGPGRP:                         /* get pgrp of tty */
1206                     mutex_enter(&proc_lock);
1207                     if (!isctty(p, tp)) {
1208                               mutex_exit(&proc_lock);
1209                               return (ENOTTY);
1210                     }
1211                     *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PGID;
1212                     mutex_exit(&proc_lock);
1213                     break;
1214           case TIOCGSID:                          /* get sid of tty */
1215                     mutex_enter(&proc_lock);
1216                     if (!isctty(p, tp)) {
1217                               mutex_exit(&proc_lock);
1218                               return (ENOTTY);
1219                     }
1220                     *(int *)data = tp->t_session->s_sid;
1221                     mutex_exit(&proc_lock);
1222                     break;
1223 #ifdef TIOCHPCL
1224           case TIOCHPCL:                          /* hang up on last close */
1225                     mutex_spin_enter(&tty_lock);
1226                     SET(tp->t_cflag, HUPCL);
1227                     mutex_spin_exit(&tty_lock);
1228                     break;
1229 #endif
1230           case TIOCNXCL:                          /* reset exclusive use of tty */
1231                     mutex_spin_enter(&tty_lock);
1232                     CLR(tp->t_state, TS_XCLUDE);
1233                     mutex_spin_exit(&tty_lock);
1234                     break;
1235           case TIOCOUTQ:                          /* output queue size */
1236                     *(int *)data = tp->t_outq.c_cc;
1237                     break;
1238           case TIOCSETA:                          /* set termios struct */
1239           case TIOCSETAW:                         /* drain output, set */
1240           case TIOCSETAF: {             /* drn out, fls in, set */
1241                     struct termios *t = (struct termios *)data;
1242 
1243                     if (cmd == TIOCSETAW || cmd == TIOCSETAF) {
1244                               if ((error = ttywait(tp)) != 0)
1245                                         return (error);
1246 
1247                               if (cmd == TIOCSETAF) {
1248                                         mutex_spin_enter(&tty_lock);
1249                                         ttyflush(tp, FREAD);
1250                                         mutex_spin_exit(&tty_lock);
1251                               }
1252                     }
1253 
1254                     s = spltty();
1255                     /*
1256                      * XXXSMP - some drivers call back on us from t_param(), so
1257                      *            don't take the tty spin lock here.
1258                      *            require t_param() to unlock upon callback?
1259                      */
1260                     /* wanted here: mutex_spin_enter(&tty_lock); */
1261                     if (!ISSET(t->c_cflag, CIGNORE)) {
1262                               /*
1263                                * Set device hardware.
1264                                */
1265                               if (tp->t_param && (error = (*tp->t_param)(tp, t))) {
1266                                         /* wanted here: mutex_spin_exit(&tty_lock); */
1267                                         splx(s);
1268                                         return (error);
1269                               } else {
1270                                         tp->t_cflag = t->c_cflag;
1271                                         tp->t_ispeed = t->c_ispeed;
1272                                         tp->t_ospeed = t->c_ospeed;
1273                                         if (t->c_ospeed == 0)
1274                                                   ttysig(tp, TTYSIG_LEADER, SIGHUP);
1275                               }
1276                               ttsetwater(tp);
1277                     }
1278 
1279                     /* delayed lock acquiring */
1280                     mutex_spin_enter(&tty_lock);
1281                     if (cmd != TIOCSETAF) {
1282                               if (ISSET(t->c_lflag, ICANON) !=
1283                                   ISSET(tp->t_lflag, ICANON)) {
1284                                         if (ISSET(t->c_lflag, ICANON)) {
1285                                                   SET(tp->t_lflag, PENDIN);
1286                                                   ttwakeup(tp);
1287                                         } else {
1288                                                   struct clist tq;
1289 
1290                                                   catq(&tp->t_rawq, &tp->t_canq);
1291                                                   tq = tp->t_rawq;
1292                                                   tp->t_rawq = tp->t_canq;
1293                                                   tp->t_canq = tq;
1294                                                   CLR(tp->t_lflag, PENDIN);
1295                                         }
1296                               }
1297                     }
1298                     tp->t_iflag = t->c_iflag;
1299                     tp->t_oflag = t->c_oflag;
1300                     /*
1301                      * Make the EXTPROC bit read only.
1302                      */
1303                     if (ISSET(tp->t_lflag, EXTPROC))
1304                               SET(t->c_lflag, EXTPROC);
1305                     else
1306                               CLR(t->c_lflag, EXTPROC);
1307                     tp->t_lflag = t->c_lflag | ISSET(tp->t_lflag, PENDIN);
1308                     memcpy(tp->t_cc, t->c_cc, sizeof(t->c_cc));
1309                     mutex_spin_exit(&tty_lock);
1310                     splx(s);
1311                     break;
1312           }
1313           case TIOCSETD:                          /* set line discipline (old) */
1314                     lp = ttyldisc_lookup_bynum(*(int *)data);
1315                     goto setldisc;
1316 
1317           case TIOCSLINED: {            /* set line discipline (new) */
1318                     char *name = (char *)data;
1319                     dev_t device;
1320 
1321                     /* Null terminate to prevent buffer overflow */
1322                     name[TTLINEDNAMELEN - 1] = '\0';
1323                     lp = ttyldisc_lookup(name);
1324  setldisc:
1325                     if (lp == NULL)
1326                               return (ENXIO);
1327 
1328                     if (lp != tp->t_linesw) {
1329                               device = tp->t_dev;
1330                               s = spltty();
1331                               (*tp->t_linesw->l_close)(tp, flag);
1332                               error = (*lp->l_open)(device, tp);
1333                               if (error) {
1334                                         (void)(*tp->t_linesw->l_open)(device, tp);
1335                                         splx(s);
1336                                         ttyldisc_release(lp);
1337                                         return (error);
1338                               }
1339                               ttyldisc_release(tp->t_linesw);
1340                               tp->t_linesw = lp;
1341                               splx(s);
1342                     } else {
1343                               /* Drop extra reference. */
1344                               ttyldisc_release(lp);
1345                     }
1346                     break;
1347           }
1348           case TIOCSTART:                         /* start output, like ^Q */
1349                     mutex_spin_enter(&tty_lock);
1350                     if (ISSET(tp->t_state, TS_TTSTOP) ||
1351                         ISSET(tp->t_lflag, FLUSHO)) {
1352                               CLR(tp->t_lflag, FLUSHO);
1353                               CLR(tp->t_state, TS_TTSTOP);
1354                               ttstart(tp);
1355                     }
1356                     mutex_spin_exit(&tty_lock);
1357                     break;
1358           case TIOCSTI:                           /* simulate terminal input */
1359                     if ((error = kauth_authorize_device_tty(l->l_cred,
1360                         KAUTH_DEVICE_TTY_STI, tp)) != 0) {
1361                               if (!ISSET(flag, FREAD))
1362                                         return EPERM;
1363                               if (!isctty(p, tp))
1364                                         return EACCES;
1365                               if (tp->t_session->s_leader->p_cred != p->p_cred)
1366                                         return error;
1367                     }
1368                     (*tp->t_linesw->l_rint)(*(u_char *)data, tp);
1369                     break;
1370           case TIOCSTOP:                          /* stop output, like ^S */
1371           {
1372                     mutex_spin_enter(&tty_lock);
1373                     if (!ISSET(tp->t_state, TS_TTSTOP)) {
1374                               SET(tp->t_state, TS_TTSTOP);
1375                               cdev_stop(tp, 0);
1376                     }
1377                     mutex_spin_exit(&tty_lock);
1378                     break;
1379           }
1380           case TIOCSCTTY:                         /* become controlling tty */
1381                     mutex_enter(&proc_lock);
1382                     mutex_spin_enter(&tty_lock);
1383 
1384                     /* Session ctty vnode pointer set in vnode layer. */
1385                     if (!SESS_LEADER(p) ||
1386                         ((p->p_session->s_ttyvp || tp->t_session) &&
1387                         (tp->t_session != p->p_session))) {
1388                               mutex_spin_exit(&tty_lock);
1389                               mutex_exit(&proc_lock);
1390                               return (EPERM);
1391                     }
1392 
1393                     /*
1394                      * `p_session' acquires a reference.
1395                      * But note that if `t_session' is set at this point,
1396                      * it must equal `p_session', in which case the session
1397                      * already has the correct reference count.
1398                      */
1399                     if (tp->t_session == NULL) {
1400                               proc_sesshold(p->p_session);
1401                     }
1402                     tp->t_session = p->p_session;
1403                     tp->t_pgrp = p->p_pgrp;
1404                     p->p_session->s_ttyp = tp;
1405                     p->p_lflag |= PL_CONTROLT;
1406                     mutex_spin_exit(&tty_lock);
1407                     mutex_exit(&proc_lock);
1408                     break;
1409           case FIOSETOWN: {             /* set pgrp of tty */
1410                     pid_t pgid = *(pid_t *)data;
1411                     struct pgrp *pgrp;
1412 
1413                     mutex_enter(&proc_lock);
1414                     if (tp->t_session != NULL && !isctty(p, tp)) {
1415                               mutex_exit(&proc_lock);
1416                               return (ENOTTY);
1417                     }
1418 
1419                     if (pgid < 0) {
1420                               if (pgid <= INT_MIN) {
1421                                         mutex_exit(&proc_lock);
1422                                         return (EINVAL);
1423                               }
1424                               pgrp = pgrp_find(-pgid);
1425                               if (pgrp == NULL) {
1426                                         mutex_exit(&proc_lock);
1427                                         return (EINVAL);
1428                               }
1429                     } else {
1430                               struct proc *p1;
1431                               p1 = proc_find(pgid);
1432                               if (!p1) {
1433                                         mutex_exit(&proc_lock);
1434                                         return (ESRCH);
1435                               }
1436                               pgrp = p1->p_pgrp;
1437                     }
1438 
1439                     if (pgrp->pg_session != p->p_session) {
1440                               mutex_exit(&proc_lock);
1441                               return (EPERM);
1442                     }
1443                     mutex_spin_enter(&tty_lock);
1444                     tp->t_pgrp = pgrp;
1445                     mutex_spin_exit(&tty_lock);
1446                     mutex_exit(&proc_lock);
1447                     break;
1448           }
1449           case TIOCSPGRP: {             /* set pgrp of tty */
1450                     struct pgrp *pgrp;
1451                     pid_t pgid = *(pid_t *)data;
1452 
1453                     if (pgid == NO_PGID)
1454                               return EINVAL;
1455 
1456                     mutex_enter(&proc_lock);
1457                     if (!isctty(p, tp)) {
1458                               mutex_exit(&proc_lock);
1459                               return (ENOTTY);
1460                     }
1461                     pgrp = pgrp_find(pgid);
1462                     if (pgrp == NULL || pgrp->pg_session != p->p_session) {
1463                               mutex_exit(&proc_lock);
1464                               return (EPERM);
1465                     }
1466                     mutex_spin_enter(&tty_lock);
1467                     tp->t_pgrp = pgrp;
1468                     mutex_spin_exit(&tty_lock);
1469                     mutex_exit(&proc_lock);
1470                     break;
1471           }
1472           case TIOCSTAT:                          /* get load avg stats */
1473                     mutex_enter(&proc_lock);
1474                     ttygetinfo(tp, 0, infobuf, sizeof(infobuf));
1475                     mutex_exit(&proc_lock);
1476 
1477                     mutex_spin_enter(&tty_lock);
1478                     ttyputinfo(tp, infobuf);
1479                     mutex_spin_exit(&tty_lock);
1480                     break;
1481           case TIOCSWINSZ:              /* set window size */
1482                     mutex_spin_enter(&tty_lock);
1483                     if (memcmp((void *)&tp->t_winsize, data,
1484                         sizeof(struct winsize))) {
1485                               tp->t_winsize = *(struct winsize *)data;
1486                               ttysig(tp, TTYSIG_PG1, SIGWINCH);
1487                     }
1488                     mutex_spin_exit(&tty_lock);
1489                     break;
1490           case TIOCSQSIZE:
1491                     if ((error = tty_get_qsize(&s, *(int *)data)) == 0 &&
1492                         s != tp->t_qsize)
1493                               error = tty_set_qsize(tp, s);
1494                     return error;
1495 
1496           case TIOCSBRK:
1497           case TIOCCBRK:
1498           case TIOCSDTR:
1499           case TIOCCDTR:
1500           case TIOCSFLAGS:
1501           case TIOCGFLAGS:
1502           case TIOCMSET:
1503           case TIOCMGET:
1504           case TIOCMBIS:
1505           case TIOCMBIC:
1506                     /* Handled by the driver layer */
1507                     return EPASSTHROUGH;
1508 
1509           case TIOCEXT:
1510           case TIOCPTSNAME:
1511           case TIOCGRANTPT:
1512           case TIOCPKT:
1513           case TIOCUCNTL:
1514           case TIOCREMOTE:
1515           case TIOCSIG:
1516                     /* for ptys */
1517                     return EPASSTHROUGH;
1518 
1519           default:
1520                     /* Pass through various console ioctls */
1521                     switch (IOCGROUP(cmd)) {
1522                     case 'c': /* syscons console */
1523                     case 'v': /* usl console, video - where one letter */
1524                     case 'K': /* usl console, keyboard - aint enough */
1525                     case 'V': /* pcvt compat */
1526                     case 'W': /* wscons console */
1527                               return EPASSTHROUGH;
1528                     default:
1529                               break;
1530                     }
1531 
1532                     /* We may have to load the compat_60 module for this. */
1533                     (void)module_autoload("compat_60", MODULE_CLASS_EXEC);
1534                     MODULE_HOOK_CALL(tty_ttioctl_60_hook,
1535                         (tp, cmd, data, flag, l), enosys(), error);
1536                     if (error != EPASSTHROUGH)
1537                               return error;
1538 
1539                     /* We may have to load the compat_43 module for this. */
1540                     (void)module_autoload("compat_43", MODULE_CLASS_EXEC);
1541                     MODULE_HOOK_CALL(tty_ttioctl_43_hook,
1542                         (tp, cmd, data, flag, l), enosys(), error);
1543                     return error;
1544           }
1545           return (0);
1546 }
1547 
1548 int
ttpoll(struct tty * tp,int events,struct lwp * l)1549 ttpoll(struct tty *tp, int events, struct lwp *l)
1550 {
1551           int       revents;
1552 
1553           revents = 0;
1554           mutex_spin_enter(&tty_lock);
1555           if (events & (POLLIN | POLLRDNORM))
1556                     if (ttnread(tp) > 0)
1557                               revents |= events & (POLLIN | POLLRDNORM);
1558 
1559           if (events & (POLLOUT | POLLWRNORM))
1560                     if (tp->t_outq.c_cc <= tp->t_lowat)
1561                               revents |= events & (POLLOUT | POLLWRNORM);
1562 
1563           if (events & POLLHUP)
1564                     if (!CONNECTED(tp))
1565                               revents |= POLLHUP;
1566 
1567           if (revents == 0) {
1568                     if (events & (POLLIN | POLLHUP | POLLRDNORM))
1569                               selrecord(l, &tp->t_rsel);
1570 
1571                     if (events & (POLLOUT | POLLWRNORM))
1572                               selrecord(l, &tp->t_wsel);
1573           }
1574 
1575           mutex_spin_exit(&tty_lock);
1576 
1577           return (revents);
1578 }
1579 
1580 static void
filt_ttyrdetach(struct knote * kn)1581 filt_ttyrdetach(struct knote *kn)
1582 {
1583           struct tty          *tp;
1584 
1585           tp = kn->kn_hook;
1586           mutex_spin_enter(&tty_lock);
1587           selremove_knote(&tp->t_rsel, kn);
1588           mutex_spin_exit(&tty_lock);
1589 }
1590 
1591 static int
filt_ttyread(struct knote * kn,long hint)1592 filt_ttyread(struct knote *kn, long hint)
1593 {
1594           struct tty          *tp;
1595           int rv;
1596 
1597           tp = kn->kn_hook;
1598           if ((hint & NOTE_SUBMIT) == 0)
1599                     mutex_spin_enter(&tty_lock);
1600           kn->kn_data = ttnread(tp);
1601           rv = kn->kn_data > 0;
1602           if ((hint & NOTE_SUBMIT) == 0)
1603                     mutex_spin_exit(&tty_lock);
1604           return rv;
1605 }
1606 
1607 static void
filt_ttywdetach(struct knote * kn)1608 filt_ttywdetach(struct knote *kn)
1609 {
1610           struct tty          *tp;
1611 
1612           tp = kn->kn_hook;
1613           mutex_spin_enter(&tty_lock);
1614           selremove_knote(&tp->t_wsel, kn);
1615           mutex_spin_exit(&tty_lock);
1616 }
1617 
1618 static int
filt_ttywrite(struct knote * kn,long hint)1619 filt_ttywrite(struct knote *kn, long hint)
1620 {
1621           struct tty          *tp;
1622           int                 canwrite;
1623 
1624           tp = kn->kn_hook;
1625           if ((hint & NOTE_SUBMIT) == 0)
1626                     mutex_spin_enter(&tty_lock);
1627           kn->kn_data = tp->t_outq.c_cn - tp->t_outq.c_cc;
1628           canwrite = (tp->t_outq.c_cc <= tp->t_lowat) && CONNECTED(tp);
1629           if ((hint & NOTE_SUBMIT) == 0)
1630                     mutex_spin_exit(&tty_lock);
1631           return (canwrite);
1632 }
1633 
1634 static const struct filterops ttyread_filtops = {
1635           .f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE,
1636           .f_attach = NULL,
1637           .f_detach = filt_ttyrdetach,
1638           .f_event = filt_ttyread,
1639 };
1640 
1641 static const struct filterops ttywrite_filtops = {
1642           .f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE,
1643           .f_attach = NULL,
1644           .f_detach = filt_ttywdetach,
1645           .f_event = filt_ttywrite,
1646 };
1647 
1648 int
ttykqfilter(dev_t dev,struct knote * kn)1649 ttykqfilter(dev_t dev, struct knote *kn)
1650 {
1651           struct tty          *tp;
1652           struct selinfo      *sip;
1653 
1654           if ((tp = cdev_tty(dev)) == NULL)
1655                     return (ENXIO);
1656 
1657           switch (kn->kn_filter) {
1658           case EVFILT_READ:
1659                     sip = &tp->t_rsel;
1660                     kn->kn_fop = &ttyread_filtops;
1661                     break;
1662           case EVFILT_WRITE:
1663                     sip = &tp->t_wsel;
1664                     kn->kn_fop = &ttywrite_filtops;
1665                     break;
1666           default:
1667                     return EINVAL;
1668           }
1669 
1670           kn->kn_hook = tp;
1671 
1672           mutex_spin_enter(&tty_lock);
1673           selrecord_knote(sip, kn);
1674           mutex_spin_exit(&tty_lock);
1675 
1676           return (0);
1677 }
1678 
1679 /*
1680  * Find the number of chars ready to be read from this tty.
1681  * Call with the tty lock held.
1682  */
1683 static int
ttnread(struct tty * tp)1684 ttnread(struct tty *tp)
1685 {
1686           int       nread;
1687 
1688           KASSERT(mutex_owned(&tty_lock));
1689 
1690           if (ISSET(tp->t_lflag, PENDIN))
1691                     ttypend(tp);
1692           nread = tp->t_canq.c_cc;
1693           if (!ISSET(tp->t_lflag, ICANON)) {
1694                     nread += tp->t_rawq.c_cc;
1695                     if (nread < tp->t_cc[VMIN] && !tp->t_cc[VTIME])
1696                               nread = 0;
1697           }
1698           return (nread);
1699 }
1700 
1701 /*
1702  * Wait for output to drain, or if this times out, flush it.
1703  */
1704 static int
ttywait_timo(struct tty * tp,int timo)1705 ttywait_timo(struct tty *tp, int timo)
1706 {
1707           int       error;
1708 
1709           error = 0;
1710 
1711           mutex_spin_enter(&tty_lock);
1712           while ((tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)) &&
1713               CONNECTED(tp) && tp->t_oproc) {
1714                     (*tp->t_oproc)(tp);
1715                     error = ttysleep(tp, &tp->t_outcv, true, timo);
1716                     if (error == EWOULDBLOCK)
1717                               ttyflush(tp, FWRITE);
1718                     if (error)
1719                               break;
1720           }
1721           mutex_spin_exit(&tty_lock);
1722 
1723           return (error);
1724 }
1725 
1726 /*
1727  * Wait for output to drain.
1728  */
1729 int
ttywait(struct tty * tp)1730 ttywait(struct tty *tp)
1731 {
1732           return ttywait_timo(tp, 0);
1733 }
1734 
1735 /*
1736  * Flush if successfully wait.
1737  */
1738 int
ttywflush(struct tty * tp)1739 ttywflush(struct tty *tp)
1740 {
1741           int       error;
1742 
1743           error = ttywait_timo(tp, 5 * hz);
1744           if (error == 0 || error == EWOULDBLOCK) {
1745                     mutex_spin_enter(&tty_lock);
1746                     ttyflush(tp, FREAD);
1747                     mutex_spin_exit(&tty_lock);
1748           }
1749           return (error);
1750 }
1751 
1752 /*
1753  * Flush tty read and/or write queues, notifying anyone waiting.
1754  * Call with the tty lock held.
1755  */
1756 void
ttyflush(struct tty * tp,int rw)1757 ttyflush(struct tty *tp, int rw)
1758 {
1759 
1760           KASSERT(mutex_owned(&tty_lock));
1761 
1762           if (rw & FREAD) {
1763                     FLUSHQ(&tp->t_canq);
1764                     FLUSHQ(&tp->t_rawq);
1765                     tp->t_rocount = 0;
1766                     tp->t_rocol = 0;
1767                     CLR(tp->t_state, TS_LOCAL);
1768                     ttwakeup(tp);
1769           }
1770           if (rw & FWRITE) {
1771                     CLR(tp->t_state, TS_TTSTOP);
1772                     cdev_stop(tp, rw);
1773                     FLUSHQ(&tp->t_outq);
1774                     cv_broadcast(&tp->t_outcv);
1775                     selnotify(&tp->t_wsel, 0, NOTE_SUBMIT);
1776           }
1777 }
1778 
1779 /*
1780  * Copy in the default termios characters.
1781  */
1782 void
ttychars(struct tty * tp)1783 ttychars(struct tty *tp)
1784 {
1785 
1786           memcpy(tp->t_cc, ttydefchars, sizeof(ttydefchars));
1787 }
1788 
1789 /*
1790  * Send stop character on input overflow.
1791  * Call with the tty lock held.
1792  */
1793 static void
ttyblock(struct tty * tp)1794 ttyblock(struct tty *tp)
1795 {
1796           int       total;
1797 
1798           KASSERT(mutex_owned(&tty_lock));
1799 
1800           total = tp->t_rawq.c_cc + tp->t_canq.c_cc;
1801           if (tp->t_rawq.c_cc > TTYHOG) {
1802                     ttyflush(tp, FREAD | FWRITE);
1803                     CLR(tp->t_state, TS_TBLOCK);
1804           }
1805           /*
1806            * Block further input iff: current input > threshold
1807            * AND input is available to user program.
1808            */
1809           if (total >= TTYHOG / 2 &&
1810               !ISSET(tp->t_state, TS_TBLOCK) &&
1811               (!ISSET(tp->t_lflag, ICANON) || tp->t_canq.c_cc > 0)) {
1812                     if (ISSET(tp->t_iflag, IXOFF) &&
1813                         tp->t_cc[VSTOP] != _POSIX_VDISABLE &&
1814                         putc(tp->t_cc[VSTOP], &tp->t_outq) == 0) {
1815                               SET(tp->t_state, TS_TBLOCK);
1816                               ttstart(tp);
1817                     }
1818                     /* Try to block remote output via hardware flow control. */
1819                     if (ISSET(tp->t_cflag, CHWFLOW) && tp->t_hwiflow &&
1820                         (*tp->t_hwiflow)(tp, 1) != 0)
1821                               SET(tp->t_state, TS_TBLOCK);
1822           }
1823 }
1824 
1825 /*
1826  * Delayed line discipline output
1827  */
1828 void
ttrstrt(void * tp_arg)1829 ttrstrt(void *tp_arg)
1830 {
1831           struct tty          *tp;
1832 
1833 #ifdef DIAGNOSTIC
1834           if (tp_arg == NULL)
1835                     panic("ttrstrt");
1836 #endif
1837           tp = tp_arg;
1838           mutex_spin_enter(&tty_lock);
1839 
1840           CLR(tp->t_state, TS_TIMEOUT);
1841           ttstart(tp); /* XXX - Shouldn't this be tp->l_start(tp)? */
1842 
1843           mutex_spin_exit(&tty_lock);
1844 }
1845 
1846 /*
1847  * start a line discipline
1848  * Always call with tty lock held?
1849  */
1850 int
ttstart(struct tty * tp)1851 ttstart(struct tty *tp)
1852 {
1853 
1854           if (tp->t_oproc != NULL)      /* XXX: Kludge for pty. */
1855                     (*tp->t_oproc)(tp);
1856           return (0);
1857 }
1858 
1859 /*
1860  * "close" a line discipline
1861  */
1862 int
ttylclose(struct tty * tp,int flag)1863 ttylclose(struct tty *tp, int flag)
1864 {
1865 
1866           if (flag & FNONBLOCK) {
1867                     mutex_spin_enter(&tty_lock);
1868                     ttyflush(tp, FREAD | FWRITE);
1869                     mutex_spin_exit(&tty_lock);
1870           } else
1871                     ttywflush(tp);
1872           return (0);
1873 }
1874 
1875 /*
1876  * Handle modem control transition on a tty.
1877  * Flag indicates new state of carrier.
1878  * Returns 0 if the line should be turned off, otherwise 1.
1879  */
1880 int
ttymodem(struct tty * tp,int flag)1881 ttymodem(struct tty *tp, int flag)
1882 {
1883 
1884           mutex_spin_enter(&tty_lock);
1885           if (flag == 0) {
1886                     if (ISSET(tp->t_state, TS_CARR_ON)) {
1887                               /*
1888                                * Lost carrier.
1889                                */
1890                               CLR(tp->t_state, TS_CARR_ON);
1891                               if (ISSET(tp->t_state, TS_ISOPEN) && !CONNECTED(tp)) {
1892                                         ttysig(tp, TTYSIG_LEADER, SIGHUP);
1893                                         ttyflush(tp, FREAD | FWRITE);
1894                                         mutex_spin_exit(&tty_lock);
1895                                         return (0);
1896                               }
1897                     }
1898           } else {
1899                     if (!ISSET(tp->t_state, TS_CARR_ON)) {
1900                               /*
1901                                * Carrier now on.
1902                                */
1903                               SET(tp->t_state, TS_CARR_ON);
1904                               ttwakeup(tp);
1905                     }
1906           }
1907           mutex_spin_exit(&tty_lock);
1908 
1909           return (1);
1910 }
1911 
1912 /*
1913  * Default modem control routine (for other line disciplines).
1914  * Return argument flag, to turn off device on carrier drop.
1915  */
1916 int
nullmodem(struct tty * tp,int flag)1917 nullmodem(struct tty *tp, int flag)
1918 {
1919 
1920           mutex_spin_enter(&tty_lock);
1921           if (flag)
1922                     SET(tp->t_state, TS_CARR_ON);
1923           else {
1924                     CLR(tp->t_state, TS_CARR_ON);
1925                     if (!CONNECTED(tp)) {
1926                               ttysig(tp, TTYSIG_LEADER, SIGHUP);
1927                               mutex_spin_exit(&tty_lock);
1928                               return (0);
1929                     }
1930           }
1931           mutex_spin_exit(&tty_lock);
1932 
1933           return (1);
1934 }
1935 
1936 /*
1937  * Reinput pending characters after state switch.
1938  */
1939 void
ttypend(struct tty * tp)1940 ttypend(struct tty *tp)
1941 {
1942           struct clist        tq;
1943           int                 c;
1944 
1945           KASSERT(mutex_owned(&tty_lock));
1946 
1947           CLR(tp->t_lflag, PENDIN);
1948           SET(tp->t_state, TS_TYPEN);
1949           tq = tp->t_rawq;
1950           tp->t_rawq.c_cc = 0;
1951           tp->t_rawq.c_cf = tp->t_rawq.c_cl = 0;
1952           while ((c = getc(&tq)) >= 0)
1953                     ttyinput_wlock(c, tp);
1954           CLR(tp->t_state, TS_TYPEN);
1955 }
1956 
1957 /*
1958  * Process a read call on a tty device.
1959  */
1960 int
ttread(struct tty * tp,struct uio * uio,int flag)1961 ttread(struct tty *tp, struct uio *uio, int flag)
1962 {
1963           struct clist        *qp;
1964           u_char              *cc;
1965           struct proc         *p;
1966           int                 c, first, error, has_stime, last_cc;
1967           long                lflag, slp;
1968           struct timeval      now, stime;
1969 
1970           if (uio->uio_resid == 0)
1971                     return 0;
1972 
1973           stime.tv_usec = 0;  /* XXX gcc */
1974           stime.tv_sec = 0;   /* XXX gcc */
1975 
1976           cc = tp->t_cc;
1977           p = curproc;
1978           error = 0;
1979           has_stime = 0;
1980           last_cc = 0;
1981           slp = 0;
1982 
1983  loop:
1984           mutex_spin_enter(&tty_lock);
1985           lflag = tp->t_lflag;
1986           /*
1987            * take pending input first
1988            */
1989           if (ISSET(lflag, PENDIN))
1990                     ttypend(tp);
1991 
1992           /*
1993            * Hang process if it's in the background.
1994            */
1995           if (isbackground(p, tp)) {
1996                     if (sigismasked(curlwp, SIGTTIN) ||
1997                         p->p_lflag & PL_PPWAIT || p->p_pgrp->pg_jobc == 0) {
1998                               mutex_spin_exit(&tty_lock);
1999                               return (EIO);
2000                     }
2001                     mutex_spin_exit(&tty_lock);
2002 
2003                     mutex_enter(&proc_lock);
2004                     pgsignal(p->p_pgrp, SIGTTIN, 1);
2005                     mutex_exit(&proc_lock);
2006 
2007                     mutex_spin_enter(&tty_lock);
2008                     error = ttypause(tp, hz);
2009                     mutex_spin_exit(&tty_lock);
2010                     if (error)
2011                               return (error);
2012                     goto loop;
2013           }
2014 
2015           if (!ISSET(lflag, ICANON)) {
2016                     int m = cc[VMIN];
2017                     long t = cc[VTIME];
2018 
2019                     qp = &tp->t_rawq;
2020                     /*
2021                      * Check each of the four combinations.
2022                      * (m > 0 && t == 0) is the normal read case.
2023                      * It should be fairly efficient, so we check that and its
2024                      * companion case (m == 0 && t == 0) first.
2025                      * For the other two cases, we compute the target sleep time
2026                      * into slp.
2027                      */
2028                     if (t == 0) {
2029                               if (qp->c_cc < m)
2030                                         goto sleep;
2031                               goto read;
2032                     }
2033                     t *= hz;            /* time in deca-ticks */
2034 /*
2035  * Time difference in deca-ticks, split division to avoid numeric overflow.
2036  * Ok for hz < ~200kHz
2037  */
2038 #define   diff(t1, t2) (((t1).tv_sec - (t2).tv_sec) * 10 * hz + \
2039                                ((t1).tv_usec - (t2).tv_usec) / 100 * hz / 1000)
2040                     if (m > 0) {
2041                               if (qp->c_cc <= 0)
2042                                         goto sleep;
2043                               if (qp->c_cc >= m)
2044                                         goto read;
2045                               if (!has_stime) {
2046                                         /* first character, start timer */
2047                                         has_stime = 1;
2048                                         getmicrotime(&stime);
2049                                         slp = t;
2050                               } else if (qp->c_cc > last_cc) {
2051                                         /* got a character, restart timer */
2052                                         getmicrotime(&stime);
2053                                         slp = t;
2054                               } else {
2055                                         /* nothing, check expiration */
2056                                         getmicrotime(&now);
2057                                         slp = t - diff(now, stime);
2058                               }
2059                     } else {  /* m == 0 */
2060                               if (qp->c_cc > 0)
2061                                         goto read;
2062                               if (!has_stime) {
2063                                         has_stime = 1;
2064                                         getmicrotime(&stime);
2065                                         slp = t;
2066                               } else {
2067                                         getmicrotime(&now);
2068                                         slp = t - diff(now, stime);
2069                               }
2070                     }
2071                     last_cc = qp->c_cc;
2072 #undef diff
2073                     if (slp > 0) {
2074                               /*
2075                                * Convert deca-ticks back to ticks.
2076                                * Rounding down may make us wake up just short
2077                                * of the target, so we round up.
2078                                * Maybe we should do 'slp/10 + 1' because the
2079                                * first tick maybe almost immediate.
2080                                * However it is more useful for a program that sets
2081                                * VTIME=10 to wakeup every second not every 1.01
2082                                * seconds (if hz=100).
2083                                */
2084                               slp = (slp + 9)/ 10;
2085                               goto sleep;
2086                     }
2087           } else if ((qp = &tp->t_canq)->c_cc <= 0) {
2088                     int       carrier;
2089 
2090  sleep:
2091                     /*
2092                      * If there is no input, sleep on rawq
2093                      * awaiting hardware receipt and notification.
2094                      * If we have data, we don't need to check for carrier.
2095                      */
2096                     carrier = CONNECTED(tp);
2097                     if (!carrier && ISSET(tp->t_state, TS_ISOPEN)) {
2098                               mutex_spin_exit(&tty_lock);
2099                               return (0);         /* EOF */
2100                     }
2101                     if (!has_stime || slp <= 0) {
2102                               if (flag & IO_NDELAY) {
2103                                         mutex_spin_exit(&tty_lock);
2104                                         return (EWOULDBLOCK);
2105                               }
2106                     }
2107                     error = ttysleep(tp, &tp->t_rawcv, true, slp);
2108                     mutex_spin_exit(&tty_lock);
2109                     /* VMIN == 0: any quantity read satisfies */
2110                     if (cc[VMIN] == 0 && error == EWOULDBLOCK)
2111                               return (0);
2112                     if (error && error != EWOULDBLOCK)
2113                               return (error);
2114                     goto loop;
2115           }
2116  read:
2117 
2118           /*
2119            * Input present, check for input mapping and processing.
2120            */
2121           first = 1;
2122           while ((c = getc(qp)) >= 0) {
2123                     /*
2124                      * delayed suspend (^Y)
2125                      */
2126                     if (CCEQ(cc[VDSUSP], c) &&
2127                         ISSET(lflag, IEXTEN|ISIG) == (IEXTEN|ISIG)) {
2128                               ttysig(tp, TTYSIG_PG1, SIGTSTP);
2129                               if (first) {
2130                                         error = ttypause(tp, hz);
2131                                         if (error)
2132                                                   break;
2133                                         mutex_spin_exit(&tty_lock);
2134                                         goto loop;
2135                               }
2136                               break;
2137                     }
2138                     /*
2139                      * Interpret EOF only in canonical mode.
2140                      */
2141                     if (CCEQ(cc[VEOF], c) && ISSET(lflag, ICANON))
2142                               break;
2143                     /*
2144                      * Give user character.
2145                      */
2146                     mutex_spin_exit(&tty_lock);
2147                     error = ureadc(c, uio);
2148                     mutex_spin_enter(&tty_lock);
2149                     if (error)
2150                               break;
2151                     if (uio->uio_resid == 0)
2152                               break;
2153                     /*
2154                      * In canonical mode check for a "break character"
2155                      * marking the end of a "line of input".
2156                      */
2157                     if (ISSET(lflag, ICANON) && TTBREAKC(c, lflag))
2158                               break;
2159                     first = 0;
2160           }
2161 
2162           /*
2163            * Look to unblock output now that (presumably)
2164            * the input queue has gone down.
2165            */
2166           if (ISSET(tp->t_state, TS_TBLOCK) && tp->t_rawq.c_cc < TTYHOG / 5) {
2167                     if (ISSET(tp->t_iflag, IXOFF) &&
2168                         cc[VSTART] != _POSIX_VDISABLE &&
2169                         putc(cc[VSTART], &tp->t_outq) == 0) {
2170                               CLR(tp->t_state, TS_TBLOCK);
2171                               ttstart(tp);
2172                     }
2173                     /* Try to unblock remote output via hardware flow control. */
2174                     if (ISSET(tp->t_cflag, CHWFLOW) && tp->t_hwiflow &&
2175                         (*tp->t_hwiflow)(tp, 0) != 0)
2176                               CLR(tp->t_state, TS_TBLOCK);
2177           }
2178           mutex_spin_exit(&tty_lock);
2179 
2180           return (error);
2181 }
2182 
2183 /*
2184  * Check the output queue on tp for space for a kernel message (from uprintf
2185  * or tprintf).  Allow some space over the normal hiwater mark so we don't
2186  * lose messages due to normal flow control, but don't let the tty run amok.
2187  * Sleeps here are not interruptible, but we return prematurely if new signals
2188  * arrive.
2189  * Call with tty lock held.
2190  */
2191 static int
ttycheckoutq_wlock(struct tty * tp)2192 ttycheckoutq_wlock(struct tty *tp)
2193 {
2194           int       hiwat;
2195 
2196           KASSERT(mutex_owned(&tty_lock));
2197 
2198           hiwat = tp->t_hiwat;
2199           if (tp->t_outq.c_cc > hiwat + 200)
2200                     if (tp->t_outq.c_cc > hiwat) {
2201                               ttstart(tp);
2202                               return (0);
2203                     }
2204 
2205           return (1);
2206 }
2207 
2208 int
ttycheckoutq(struct tty * tp)2209 ttycheckoutq(struct tty *tp)
2210 {
2211           int       r;
2212 
2213           mutex_spin_enter(&tty_lock);
2214           r = ttycheckoutq_wlock(tp);
2215           mutex_spin_exit(&tty_lock);
2216 
2217           return (r);
2218 }
2219 
2220 /*
2221  * Process a write call on a tty device.
2222  */
2223 int
ttwrite(struct tty * tp,struct uio * uio,int flag)2224 ttwrite(struct tty *tp, struct uio *uio, int flag)
2225 {
2226           u_char              *cp;
2227           struct proc         *p;
2228           int                 cc, cc0, ce, i, hiwat, error;
2229           u_char              obuf[OBUFSIZ];
2230 
2231           cp = NULL;
2232           hiwat = tp->t_hiwat;
2233           error = 0;
2234           cc0 = cc = 0;
2235  loop:
2236           mutex_spin_enter(&tty_lock);
2237           if (!CONNECTED(tp)) {
2238                     if (ISSET(tp->t_state, TS_ISOPEN)) {
2239                               mutex_spin_exit(&tty_lock);
2240                               return (EIO);
2241                     } else if (flag & IO_NDELAY) {
2242                               mutex_spin_exit(&tty_lock);
2243                               error = EWOULDBLOCK;
2244                               goto out;
2245                     } else {
2246                               /* Sleep awaiting carrier. */
2247                               error = ttysleep(tp, &tp->t_rawcv, true, 0);
2248                               mutex_spin_exit(&tty_lock);
2249                               if (error)
2250                                         goto out;
2251                               goto loop;
2252                     }
2253           }
2254 
2255           /*
2256            * Hang the process if it's in the background.
2257            */
2258           p = curproc;
2259           if (isbackground(p, tp) &&
2260               ISSET(tp->t_lflag, TOSTOP) && (p->p_lflag & PL_PPWAIT) == 0 &&
2261               !sigismasked(curlwp, SIGTTOU)) {
2262                     if (p->p_pgrp->pg_jobc == 0) {
2263                               error = EIO;
2264                               mutex_spin_exit(&tty_lock);
2265                               goto out;
2266                     }
2267                     mutex_spin_exit(&tty_lock);
2268 
2269                     mutex_enter(&proc_lock);
2270                     pgsignal(p->p_pgrp, SIGTTOU, 1);
2271                     mutex_exit(&proc_lock);
2272 
2273                     mutex_spin_enter(&tty_lock);
2274                     error = ttypause(tp, hz);
2275                     mutex_spin_exit(&tty_lock);
2276                     if (error)
2277                               goto out;
2278                     goto loop;
2279           }
2280           mutex_spin_exit(&tty_lock);
2281 
2282           /*
2283            * Process the user's data in at most OBUFSIZ chunks.  Perform any
2284            * output translation.  Keep track of high water mark, sleep on
2285            * overflow awaiting device aid in acquiring new space.
2286            */
2287           while (uio->uio_resid > 0 || cc > 0) {
2288                     if (ISSET(tp->t_lflag, FLUSHO)) {
2289                               uio->uio_resid = 0;
2290                               return (0);
2291                     }
2292                     if (tp->t_outq.c_cc > hiwat)
2293                               goto ovhiwat;
2294                     /*
2295                      * Grab a hunk of data from the user, unless we have some
2296                      * leftover from last time.
2297                      */
2298                     if (cc == 0) {
2299                               uioskip(cc0, uio);
2300                               cc0 = cc = uimin(uio->uio_resid, OBUFSIZ);
2301                               cp = obuf;
2302                               error = uiopeek(cp, cc, uio);
2303                               if (error) {
2304                                         cc = 0;
2305                                         goto out;
2306                               }
2307                     }
2308                     /*
2309                      * If nothing fancy need be done, grab those characters we
2310                      * can handle without any of ttyoutput's processing and
2311                      * just transfer them to the output q.  For those chars
2312                      * which require special processing (as indicated by the
2313                      * bits in char_type), call ttyoutput.  After processing
2314                      * a hunk of data, look for FLUSHO so ^O's will take effect
2315                      * immediately.
2316                      */
2317                     mutex_spin_enter(&tty_lock);
2318                     while (cc > 0) {
2319                               if (!ISSET(tp->t_oflag, OPOST))
2320                                         ce = cc;
2321                               else {
2322                                         ce = cc - scanc((u_int)cc, cp, char_type,
2323                                             CCLASSMASK);
2324                                         /*
2325                                          * If ce is zero, then we're processing
2326                                          * a special character through ttyoutput.
2327                                          */
2328                                         if (ce == 0) {
2329                                                   tp->t_rocount = 0;
2330                                                   if (ttyoutput(*cp, tp) >= 0) {
2331                                                             /* out of space */
2332                                                             mutex_spin_exit(&tty_lock);
2333                                                             goto overfull;
2334                                                   }
2335                                                   cp++;
2336                                                   cc--;
2337                                                   if (ISSET(tp->t_lflag, FLUSHO) ||
2338                                                       tp->t_outq.c_cc > hiwat) {
2339                                                             mutex_spin_exit(&tty_lock);
2340                                                             goto ovhiwat;
2341                                                   }
2342                                                   continue;
2343                                         }
2344                               }
2345                               /*
2346                                * A bunch of normal characters have been found.
2347                                * Transfer them en masse to the output queue and
2348                                * continue processing at the top of the loop.
2349                                * If there are any further characters in this
2350                                * <= OBUFSIZ chunk, the first should be a character
2351                                * requiring special handling by ttyoutput.
2352                                */
2353                               tp->t_rocount = 0;
2354                               i = b_to_q(cp, ce, &tp->t_outq);
2355                               ce -= i;
2356                               tp->t_column += ce;
2357                               cp += ce, cc -= ce, tk_nout += ce;
2358                               tp->t_outcc += ce;
2359                               if (i > 0) {
2360                                         /* out of space */
2361                                         mutex_spin_exit(&tty_lock);
2362                                         goto overfull;
2363                               }
2364                               if (ISSET(tp->t_lflag, FLUSHO) ||
2365                                   tp->t_outq.c_cc > hiwat)
2366                                         break;
2367                     }
2368                     ttstart(tp);
2369                     mutex_spin_exit(&tty_lock);
2370           }
2371 
2372  out:
2373           KASSERTMSG(error || cc == 0, "error=%d cc=%d", error, cc);
2374           KASSERTMSG(cc0 >= cc, "cc0=%d cc=%d", cc0, cc);
2375           uioskip(cc0 - cc, uio);
2376           return (error);
2377 
2378  overfull:
2379           /*
2380            * Since we are using ring buffers, if we can't insert any more into
2381            * the output queue, we can assume the ring is full and that someone
2382            * forgot to set the high water mark correctly.  We set it and then
2383            * proceed as normal.
2384            */
2385           hiwat = tp->t_outq.c_cc - 1;
2386 
2387  ovhiwat:
2388           mutex_spin_enter(&tty_lock);
2389           ttstart(tp);
2390           /*
2391            * This can only occur if FLUSHO is set in t_lflag,
2392            * or if ttstart/oproc is synchronous (or very fast).
2393            */
2394           if (tp->t_outq.c_cc <= hiwat) {
2395                     mutex_spin_exit(&tty_lock);
2396                     goto loop;
2397           }
2398           if (flag & IO_NDELAY) {
2399                     mutex_spin_exit(&tty_lock);
2400                     error = EWOULDBLOCK;
2401                     goto out;
2402           }
2403           error = ttysleep(tp, &tp->t_outcv, true, 0);
2404           mutex_spin_exit(&tty_lock);
2405           if (error)
2406                     goto out;
2407           goto loop;
2408 }
2409 
2410 /*
2411  * Try to pull more output from the producer.  Return non-zero if
2412  * there is output ready to be sent.
2413  */
2414 bool
ttypull(struct tty * tp)2415 ttypull(struct tty *tp)
2416 {
2417 
2418           /* XXXSMP not yet KASSERT(mutex_owned(&tty_lock)); */
2419 
2420           if (tp->t_outq.c_cc <= tp->t_lowat) {
2421                     cv_broadcast(&tp->t_outcv);
2422                     selnotify(&tp->t_wsel, 0, NOTE_SUBMIT);
2423           }
2424           return tp->t_outq.c_cc != 0;
2425 }
2426 
2427 /*
2428  * Rubout one character from the rawq of tp
2429  * as cleanly as possible.
2430  * Called with tty lock held.
2431  */
2432 void
ttyrub(int c,struct tty * tp)2433 ttyrub(int c, struct tty *tp)
2434 {
2435           u_char    *cp;
2436           int       savecol, tabc;
2437 
2438           KASSERT(mutex_owned(&tty_lock));
2439 
2440           if (!ISSET(tp->t_lflag, ECHO) || ISSET(tp->t_lflag, EXTPROC))
2441                     return;
2442           CLR(tp->t_lflag, FLUSHO);
2443           if (ISSET(tp->t_lflag, ECHOE)) {
2444                     if (tp->t_rocount == 0) {
2445                               /*
2446                                * Screwed by ttwrite; retype
2447                                */
2448                               ttyretype(tp);
2449                               return;
2450                     }
2451                     if (c == ('\t' | TTY_QUOTE) || c == ('\n' | TTY_QUOTE))
2452                               ttyrubo(tp, 2);
2453                     else {
2454                               CLR(c, ~TTY_CHARMASK);
2455                               switch (CCLASS(c)) {
2456                               case ORDINARY:
2457                                         ttyrubo(tp, 1);
2458                                         break;
2459                               case BACKSPACE:
2460                               case CONTROL:
2461                               case NEWLINE:
2462                               case RETURN:
2463                               case VTAB:
2464                                         if (ISSET(tp->t_lflag, ECHOCTL))
2465                                                   ttyrubo(tp, 2);
2466                                         break;
2467                               case TAB:
2468                                         if (tp->t_rocount < tp->t_rawq.c_cc) {
2469                                                   ttyretype(tp);
2470                                                   return;
2471                                         }
2472                                         savecol = tp->t_column;
2473                                         SET(tp->t_state, TS_CNTTB);
2474                                         SET(tp->t_lflag, FLUSHO);
2475                                         tp->t_column = tp->t_rocol;
2476                                         for (cp = firstc(&tp->t_rawq, &tabc); cp;
2477                                             cp = nextc(&tp->t_rawq, cp, &tabc))
2478                                                   ttyecho(tabc, tp);
2479                                         CLR(tp->t_lflag, FLUSHO);
2480                                         CLR(tp->t_state, TS_CNTTB);
2481 
2482                                         /* savecol will now be length of the tab. */
2483                                         savecol -= tp->t_column;
2484                                         tp->t_column += savecol;
2485                                         if (savecol > 8)
2486                                                   savecol = 8;        /* overflow screw */
2487                                         while (--savecol >= 0)
2488                                                   (void)ttyoutput('\b', tp);
2489                                         break;
2490                               default:                      /* XXX */
2491                                         (void)printf("ttyrub: would panic c = %d, "
2492                                             "val = %d\n", c, CCLASS(c));
2493                               }
2494                     }
2495           } else if (ISSET(tp->t_lflag, ECHOPRT)) {
2496                     if (!ISSET(tp->t_state, TS_ERASE)) {
2497                               SET(tp->t_state, TS_ERASE);
2498                               (void)ttyoutput('\\', tp);
2499                     }
2500                     ttyecho(c, tp);
2501           } else
2502                     ttyecho(tp->t_cc[VERASE], tp);
2503           --tp->t_rocount;
2504 }
2505 
2506 /*
2507  * Back over cnt characters, erasing them.
2508  * Called with tty lock held.
2509  */
2510 static void
ttyrubo(struct tty * tp,int cnt)2511 ttyrubo(struct tty *tp, int cnt)
2512 {
2513 
2514           KASSERT(mutex_owned(&tty_lock));
2515 
2516           while (cnt-- > 0) {
2517                     (void)ttyoutput('\b', tp);
2518                     (void)ttyoutput(' ', tp);
2519                     (void)ttyoutput('\b', tp);
2520           }
2521 }
2522 
2523 /*
2524  * ttyretype --
2525  *        Reprint the rawq line.  Note, it is assumed that c_cc has already
2526  *        been checked.
2527  *
2528  * Called with tty lock held.
2529  */
2530 void
ttyretype(struct tty * tp)2531 ttyretype(struct tty *tp)
2532 {
2533           u_char    *cp;
2534           int       c;
2535 
2536           KASSERT(mutex_owned(&tty_lock));
2537 
2538           /* Echo the reprint character. */
2539           if (tp->t_cc[VREPRINT] != _POSIX_VDISABLE)
2540                     ttyecho(tp->t_cc[VREPRINT], tp);
2541 
2542           (void)ttyoutput('\n', tp);
2543 
2544           for (cp = firstc(&tp->t_canq, &c); cp; cp = nextc(&tp->t_canq, cp, &c))
2545                     ttyecho(c, tp);
2546           for (cp = firstc(&tp->t_rawq, &c); cp; cp = nextc(&tp->t_rawq, cp, &c))
2547                     ttyecho(c, tp);
2548           CLR(tp->t_state, TS_ERASE);
2549 
2550           tp->t_rocount = tp->t_rawq.c_cc;
2551           tp->t_rocol = 0;
2552 }
2553 
2554 /*
2555  * Echo a typed character to the terminal.
2556  * Called with tty lock held.
2557  */
2558 static void
ttyecho(int c,struct tty * tp)2559 ttyecho(int c, struct tty *tp)
2560 {
2561 
2562           KASSERT(mutex_owned(&tty_lock));
2563 
2564           if (!ISSET(tp->t_state, TS_CNTTB))
2565                     CLR(tp->t_lflag, FLUSHO);
2566           if ((!ISSET(tp->t_lflag, ECHO) &&
2567               (!ISSET(tp->t_lflag, ECHONL) || c != '\n')) ||
2568               ISSET(tp->t_lflag, EXTPROC))
2569                     return;
2570           if (((ISSET(tp->t_lflag, ECHOCTL) &&
2571               (ISSET(c, TTY_CHARMASK) <= 037 && c != '\t' && c != '\n')) ||
2572               ISSET(c, TTY_CHARMASK) == 0177)) {
2573                     (void)ttyoutput('^', tp);
2574                     CLR(c, ~TTY_CHARMASK);
2575                     if (c == 0177)
2576                               c = '?';
2577                     else
2578                               c += 'A' - 1;
2579           }
2580           (void)ttyoutput(c, tp);
2581 }
2582 
2583 /*
2584  * Wake up any readers on a tty.
2585  * Called with tty lock held.
2586  */
2587 void
ttwakeup(struct tty * tp)2588 ttwakeup(struct tty *tp)
2589 {
2590 
2591           KASSERT(mutex_owned(&tty_lock));
2592 
2593           selnotify(&tp->t_rsel, 0, NOTE_SUBMIT);
2594           if (ISSET(tp->t_state, TS_ASYNC))
2595                     ttysig(tp, TTYSIG_PG2, SIGIO);
2596           cv_broadcast(&tp->t_rawcv);
2597 }
2598 
2599 /*
2600  * Look up a code for a specified speed in a conversion table;
2601  * used by drivers to map software speed values to hardware parameters.
2602  */
2603 int
ttspeedtab(int speed,const struct speedtab * table)2604 ttspeedtab(int speed, const struct speedtab *table)
2605 {
2606 
2607           for (; table->sp_speed != -1; table++)
2608                     if (table->sp_speed == speed)
2609                               return (table->sp_code);
2610           return (-1);
2611 }
2612 
2613 /*
2614  * Set tty hi and low water marks.
2615  *
2616  * Try to arrange the dynamics so there's about one second
2617  * from hi to low water.
2618  */
2619 void
ttsetwater(struct tty * tp)2620 ttsetwater(struct tty *tp)
2621 {
2622           int       cps, x;
2623 
2624           /* XXX not yet KASSERT(mutex_owned(&tty_lock)); */
2625 
2626 #define   CLAMP(x, h, l)      ((x) > h ? h : ((x) < l) ? l : (x))
2627 
2628           cps = tp->t_ospeed / 10;
2629           tp->t_lowat = x = CLAMP(cps / 2, TTMAXLOWAT, TTMINLOWAT);
2630           x += cps;
2631           x = CLAMP(x, TTMAXHIWAT, TTMINHIWAT);
2632           tp->t_hiwat = roundup(x, TTROUND);
2633 #undef    CLAMP
2634 }
2635 
2636 /*
2637  * Prepare report on state of foreground process group.
2638  * Call with &proc_lock held.
2639  */
2640 void
ttygetinfo(struct tty * tp,int fromsig,char * buf,size_t bufsz)2641 ttygetinfo(struct tty *tp, int fromsig, char *buf, size_t bufsz)
2642 {
2643           struct lwp          *l;
2644           struct proc         *p, *pick = NULL;
2645           struct timeval      utime, stime;
2646           int                 tmp;
2647           fixpt_t             pctcpu = 0;
2648           const char          *msg = NULL;
2649           char                lmsg[100];
2650           long                rss;
2651           bool                again = false;
2652 
2653           KASSERT(mutex_owned(&proc_lock));
2654 
2655           *buf = '\0';
2656 
2657  retry:
2658           if (tp->t_session == NULL)
2659                     msg = "not a controlling terminal\n";
2660           else if (tp->t_pgrp == NULL)
2661                     msg = "no foreground process group\n";
2662           else if ((p = LIST_FIRST(&tp->t_pgrp->pg_members)) == NULL)
2663                     msg = "empty foreground process group\n";
2664           else {
2665                     /* Pick interesting process. */
2666                     for (; p != NULL; p = LIST_NEXT(p, p_pglist)) {
2667                               struct proc *oldpick;
2668 
2669                               if (pick == NULL) {
2670                                         pick = p;
2671                                         continue;
2672                               }
2673                               if (pick->p_lock < p->p_lock) {
2674                                         mutex_enter(pick->p_lock);
2675                                         mutex_enter(p->p_lock);
2676                               } else if (pick->p_lock > p->p_lock) {
2677                                         mutex_enter(p->p_lock);
2678                                         mutex_enter(pick->p_lock);
2679                               } else
2680                                         mutex_enter(p->p_lock);
2681                               oldpick = pick;
2682                               if (proc_compare_wrapper(pick, p))
2683                                         pick = p;
2684                               mutex_exit(p->p_lock);
2685                               if (p->p_lock != oldpick->p_lock)
2686                                         mutex_exit(oldpick->p_lock);
2687                     }
2688 
2689                     if (pick != NULL) {
2690                               mutex_enter(pick->p_lock);
2691                               if (P_ZOMBIE(pick)) {
2692                                         mutex_exit(pick->p_lock);
2693                                         pick = NULL;
2694                                         if (!again) {
2695                                                   again = true;
2696                                                   goto retry;
2697                                         }
2698                                         msg = "found only zombie processes\n";
2699                               }
2700                               if (pick && fromsig &&
2701                                   (SIGACTION_PS(pick->p_sigacts, SIGINFO).sa_flags &
2702                                   SA_NOKERNINFO)) {
2703                                         mutex_exit(pick->p_lock);
2704                                         return;
2705                               }
2706                     }
2707           }
2708 
2709           /* Print load average. */
2710           tmp = (averunnable.ldavg[0] * 100 + FSCALE / 2) >> FSHIFT;
2711           snprintf(lmsg, sizeof(lmsg), "load: %d.%02d ", tmp / 100, tmp % 100);
2712           strlcat(buf, lmsg, bufsz);
2713 
2714           if (pick == NULL) {
2715                     strlcat(buf, msg, bufsz);
2716                     return;
2717           }
2718 
2719           snprintf(lmsg, sizeof(lmsg), " cmd: %s %d [", pick->p_comm,
2720               pick->p_pid);
2721           strlcat(buf, lmsg, bufsz);
2722 
2723           KASSERT(mutex_owned(pick->p_lock));
2724           LIST_FOREACH(l, &pick->p_lwps, l_sibling) {
2725                     const char *lp;
2726                     lwp_lock(l);
2727 #ifdef LWP_PC
2728 #define FMT_RUN "%#"PRIxVADDR
2729 #define VAL_RUNNING (vaddr_t)LWP_PC(l)
2730 #define VAL_RUNNABLE (vaddr_t)LWP_PC(l)
2731 #else
2732 #define FMT_RUN "%s"
2733 #define VAL_RUNNING "running"
2734 #define VAL_RUNNABLE "runnable"
2735 #endif
2736                     switch (l->l_stat) {
2737                     case LSONPROC:
2738                               snprintf(lmsg, sizeof(lmsg), FMT_RUN"/%d", VAL_RUNNING,
2739                                   cpu_index(l->l_cpu));
2740                               lp = lmsg;
2741                               break;
2742                     case LSRUN:
2743                               snprintf(lmsg, sizeof(lmsg), FMT_RUN, VAL_RUNNABLE);
2744                               lp = lmsg;
2745                               break;
2746                     default:
2747                               lp = l->l_wchan ? l->l_wmesg : "iowait";
2748                               break;
2749                     }
2750                     strlcat(buf, lp, bufsz);
2751                     strlcat(buf, LIST_NEXT(l, l_sibling) != NULL ? " " : "] ",
2752                         bufsz);
2753                     pctcpu += l->l_pctcpu;
2754                     lwp_unlock(l);
2755           }
2756           pctcpu += pick->p_pctcpu;
2757           calcru(pick, &utime, &stime, NULL, NULL);
2758           mutex_exit(pick->p_lock);
2759 
2760           /* Round up and print user+system time, %CPU and RSS. */
2761           utime.tv_usec += 5000;
2762           if (utime.tv_usec >= 1000000) {
2763                     utime.tv_sec += 1;
2764                     utime.tv_usec -= 1000000;
2765           }
2766           stime.tv_usec += 5000;
2767           if (stime.tv_usec >= 1000000) {
2768                     stime.tv_sec += 1;
2769                     stime.tv_usec -= 1000000;
2770           }
2771 #define   pgtok(a)  (((u_long) ((a) * PAGE_SIZE) / 1024))
2772           tmp = (pctcpu * 10000 + FSCALE / 2) >> FSHIFT;
2773           if (pick->p_stat == SIDL || P_ZOMBIE(pick))
2774                     rss = 0;
2775           else
2776                     rss = pgtok(vm_resident_count(pick->p_vmspace));
2777 
2778           snprintf(lmsg, sizeof(lmsg), "%ld.%02ldu %ld.%02lds %d%% %ldk",
2779               (long)utime.tv_sec, (long)utime.tv_usec / 10000,
2780               (long)stime.tv_sec, (long)stime.tv_usec / 10000,
2781               tmp / 100, rss);
2782           strlcat(buf, lmsg, bufsz);
2783 }
2784 
2785 /*
2786  * Print report on state of foreground process group.
2787  * Call with tty_lock held.
2788  */
2789 void
ttyputinfo(struct tty * tp,char * buf)2790 ttyputinfo(struct tty *tp, char *buf)
2791 {
2792 
2793           KASSERT(mutex_owned(&tty_lock));
2794 
2795           if (ttycheckoutq_wlock(tp) == 0)
2796                     return;
2797           ttyprintf_nolock(tp, "%s\n", buf);
2798           tp->t_rocount = 0;  /* so pending input will be retyped if BS */
2799 }
2800 
2801 /*
2802  * Returns 1 if p2 has a better chance being the active foreground process
2803  * in a terminal instead of p1.
2804  */
2805 static int
proc_compare_wrapper(struct proc * p1,struct proc * p2)2806 proc_compare_wrapper(struct proc *p1, struct proc *p2)
2807 {
2808           lwp_t *l1, *l2;
2809 
2810           KASSERT(mutex_owned(p1->p_lock));
2811           KASSERT(mutex_owned(p2->p_lock));
2812 
2813           l1 = LIST_FIRST(&p1->p_lwps);
2814           l2 = LIST_FIRST(&p2->p_lwps);
2815 
2816           return proc_compare(p1, l1, p2, l2);
2817 }
2818 
2819 /*
2820  * Output char to tty; console putchar style.
2821  * Can be called with tty lock held through kprintf() machinery..
2822  */
2823 int
tputchar(int c,int flags,struct tty * tp)2824 tputchar(int c, int flags, struct tty *tp)
2825 {
2826           int r = 0;
2827 
2828           if ((flags & NOLOCK) == 0)
2829                     mutex_spin_enter(&tty_lock);
2830           if (!CONNECTED(tp)) {
2831                     r = -1;
2832                     goto out;
2833           }
2834           if (c == '\n')
2835                     (void)ttyoutput('\r', tp);
2836           (void)ttyoutput(c, tp);
2837           ttstart(tp);
2838 out:
2839           if ((flags & NOLOCK) == 0)
2840                     mutex_spin_exit(&tty_lock);
2841           return (r);
2842 }
2843 
2844 /*
2845  * Sleep on chan, returning ERESTART if tty changed while we napped and
2846  * returning any errors (e.g. EINTR/EWOULDBLOCK) reported by
2847  * cv_timedwait(_sig).
2848  * If the tty is revoked, restarting a pending call will redo validation done
2849  * at the start of the call.
2850  *
2851  * Must be called with the tty lock held.
2852  */
2853 int
ttysleep(struct tty * tp,kcondvar_t * cv,bool catch_p,int timo)2854 ttysleep(struct tty *tp, kcondvar_t *cv, bool catch_p, int timo)
2855 {
2856           int       error;
2857           short     gen;
2858 
2859           KASSERT(mutex_owned(&tty_lock));
2860 
2861           gen = tp->t_gen;
2862           if (ISSET(tp->t_state, TS_CANCEL))
2863                     error = ERESTART;
2864           else if (cv == NULL)
2865                     error = kpause("ttypause", catch_p, timo, &tty_lock);
2866           else if (catch_p)
2867                     error = cv_timedwait_sig(cv, &tty_lock, timo);
2868           else
2869                     error = cv_timedwait(cv, &tty_lock, timo);
2870           if (error != 0)
2871                     return (error);
2872           return (tp->t_gen == gen ? 0 : ERESTART);
2873 }
2874 
2875 int
ttypause(struct tty * tp,int timo)2876 ttypause(struct tty *tp, int timo)
2877 {
2878           int error;
2879 
2880           error = ttysleep(tp, NULL, true, timo);
2881           if (error == EWOULDBLOCK)
2882                     error = 0;
2883           return error;
2884 }
2885 
2886 /*
2887  * Attach a tty to the tty list.
2888  *
2889  * This should be called ONLY once per real tty (including pty's).
2890  * eg, on the sparc, the keyboard and mouse have struct tty's that are
2891  * distinctly NOT usable as tty's, and thus should not be attached to
2892  * the ttylist.  This is why this call is not done from tty_alloc().
2893  *
2894  * Device drivers should attach tty's at a similar time that they are
2895  * allocated, or, for the case of statically allocated struct tty's
2896  * either in the attach or (first) open routine.
2897  */
2898 void
tty_attach(struct tty * tp)2899 tty_attach(struct tty *tp)
2900 {
2901 
2902           mutex_spin_enter(&tty_lock);
2903           TAILQ_INSERT_TAIL(&ttylist, tp, tty_link);
2904           ++tty_count;
2905           mutex_spin_exit(&tty_lock);
2906 }
2907 
2908 /*
2909  * Remove a tty from the tty list.
2910  */
2911 void
tty_detach(struct tty * tp)2912 tty_detach(struct tty *tp)
2913 {
2914 
2915           mutex_spin_enter(&tty_lock);
2916           --tty_count;
2917 #ifdef DIAGNOSTIC
2918           if (tty_count < 0)
2919                     panic("tty_detach: tty_count < 0");
2920 #endif
2921           TAILQ_REMOVE(&ttylist, tp, tty_link);
2922           mutex_spin_exit(&tty_lock);
2923 }
2924 
2925 /*
2926  * Allocate a tty structure and its associated buffers.
2927  */
2928 struct tty *
tty_alloc(void)2929 tty_alloc(void)
2930 {
2931           struct tty *tp;
2932           int i;
2933 
2934           tp = kmem_zalloc(sizeof(*tp), KM_SLEEP);
2935           callout_init(&tp->t_rstrt_ch, 0);
2936           callout_setfunc(&tp->t_rstrt_ch, ttrstrt, tp);
2937           tp->t_qsize = tty_qsize;
2938           clalloc(&tp->t_rawq, tp->t_qsize, 1);
2939           cv_init(&tp->t_rawcv, "ttyraw");
2940           cv_init(&tp->t_rawcvf, "ttyrawf");
2941           clalloc(&tp->t_canq, tp->t_qsize, 1);
2942           cv_init(&tp->t_cancv, "ttycan");
2943           cv_init(&tp->t_cancvf, "ttycanf");
2944           /* output queue doesn't need quoting */
2945           clalloc(&tp->t_outq, tp->t_qsize, 0);
2946           cv_init(&tp->t_outcv, "ttyout");
2947           cv_init(&tp->t_outcvf, "ttyoutf");
2948           /* Set default line discipline. */
2949           tp->t_linesw = ttyldisc_default();
2950           tp->t_dev = NODEV;
2951           selinit(&tp->t_rsel);
2952           selinit(&tp->t_wsel);
2953           for (i = 0; i < TTYSIG_COUNT; i++)  {
2954                     sigemptyset(&tp->t_sigs[i]);
2955           }
2956 
2957           return tp;
2958 }
2959 
2960 /*
2961  * Free a tty structure and its buffers.
2962  *
2963  * Be sure to call tty_detach() for any tty that has been
2964  * tty_attach()ed.
2965  */
2966 void
tty_free(struct tty * tp)2967 tty_free(struct tty *tp)
2968 {
2969           int i;
2970 
2971           mutex_enter(&proc_lock);
2972           mutex_enter(&tty_lock);
2973           for (i = 0; i < TTYSIG_COUNT; i++)
2974                     sigemptyset(&tp->t_sigs[i]);
2975           if (tp->t_sigcount != 0)
2976                     TAILQ_REMOVE(&tty_sigqueue, tp, t_sigqueue);
2977           mutex_exit(&tty_lock);
2978           mutex_exit(&proc_lock);
2979 
2980           callout_halt(&tp->t_rstrt_ch, NULL);
2981           callout_destroy(&tp->t_rstrt_ch);
2982           ttyldisc_release(tp->t_linesw);
2983           clfree(&tp->t_rawq);
2984           clfree(&tp->t_canq);
2985           clfree(&tp->t_outq);
2986           cv_destroy(&tp->t_rawcv);
2987           cv_destroy(&tp->t_rawcvf);
2988           cv_destroy(&tp->t_cancv);
2989           cv_destroy(&tp->t_cancvf);
2990           cv_destroy(&tp->t_outcv);
2991           cv_destroy(&tp->t_outcvf);
2992           seldestroy(&tp->t_rsel);
2993           seldestroy(&tp->t_wsel);
2994           kmem_free(tp, sizeof(*tp));
2995 }
2996 
2997 /*
2998  * tty_unit: map dev_t to tty unit number, as with TTUNIT
2999  *
3000  * => defined as function for use with struct cdevsw::d_devtounit
3001  * => not for drivers with different unit numbering, e.g. TTUNIT(d) >> 4
3002  */
3003 int
tty_unit(dev_t dev)3004 tty_unit(dev_t dev)
3005 {
3006           return TTUNIT(dev);
3007 }
3008 
3009 /*
3010  * ttyprintf_nolock: send a message to a specific tty, without locking.
3011  *
3012  * => should be used only by tty driver or anything that knows the
3013  *    underlying tty will not be revoked(2)'d away.  [otherwise,
3014  *    use tprintf]
3015  */
3016 static void
ttyprintf_nolock(struct tty * tp,const char * fmt,...)3017 ttyprintf_nolock(struct tty *tp, const char *fmt, ...)
3018 {
3019           va_list ap;
3020 
3021           /* No mutex needed; going to process TTY. */
3022           va_start(ap, fmt);
3023           kprintf(fmt, TOTTY|NOLOCK, tp, NULL, ap);
3024           va_end(ap);
3025 }
3026 
3027 static int
tty_listener_cb(kauth_cred_t cred,kauth_action_t action,void * cookie,void * arg0,void * arg1,void * arg2,void * arg3)3028 tty_listener_cb(kauth_cred_t cred, kauth_action_t action, void *cookie,
3029     void *arg0, void *arg1, void *arg2, void *arg3)
3030 {
3031           struct tty *tty;
3032           int result;
3033 
3034           result = KAUTH_RESULT_DEFER;
3035 
3036           if (action != KAUTH_DEVICE_TTY_OPEN)
3037                     return result;
3038 
3039           tty = arg0;
3040 
3041           /* If it's not opened, we allow. */
3042           if ((tty->t_state & TS_ISOPEN) == 0)
3043                     result = KAUTH_RESULT_ALLOW;
3044           else {
3045                     /*
3046                      * If it's opened, we can only allow if it's not exclusively
3047                      * opened; otherwise, that's a privileged operation and we
3048                      * let the secmodel handle it.
3049                      */
3050                     if ((tty->t_state & TS_XCLUDE) == 0)
3051                               result = KAUTH_RESULT_ALLOW;
3052           }
3053 
3054           return result;
3055 }
3056 
3057 /*
3058  * Initialize the tty subsystem.
3059  */
3060 void
tty_init(void)3061 tty_init(void)
3062 {
3063 
3064           mutex_init(&tty_lock, MUTEX_DEFAULT, IPL_VM);
3065           mutex_init(&constty_lock, MUTEX_DEFAULT, IPL_NONE);
3066           constty_psz = pserialize_create();
3067           cv_init(&ttyref_cv, "ttyref");
3068           tty_sigsih = softint_establish(SOFTINT_CLOCK, ttysigintr, NULL);
3069           KASSERT(tty_sigsih != NULL);
3070 
3071           tty_listener = kauth_listen_scope(KAUTH_SCOPE_DEVICE,
3072               tty_listener_cb, NULL);
3073 
3074           sysctl_kern_tty_setup();
3075 }
3076 
3077 /*
3078  * Send a signal from a tty to its process group or session leader.
3079  * Handoff to the target is deferred to a soft interrupt.
3080  */
3081 void
ttysig(struct tty * tp,enum ttysigtype st,int sig)3082 ttysig(struct tty *tp, enum ttysigtype st, int sig)
3083 {
3084           sigset_t *sp;
3085 
3086           /* XXXSMP not yet KASSERT(mutex_owned(&tty_lock)); */
3087 
3088           sp = &tp->t_sigs[st];
3089           if (sigismember(sp, sig))
3090                     return;
3091           sigaddset(sp, sig);
3092           if (tp->t_sigcount++ == 0)
3093                     TAILQ_INSERT_TAIL(&tty_sigqueue, tp, t_sigqueue);
3094           softint_schedule(tty_sigsih);
3095 }
3096 
3097 /*
3098  * Deliver deferred signals from ttys.  Note that the process groups
3099  * and sessions associated with the ttys may have changed from when
3100  * the signal was originally sent, but in practice it should not matter.
3101  * For signals produced as a result of a syscall, the soft interrupt
3102  * will fire before the syscall returns to the user.
3103  */
3104 static void
ttysigintr(void * cookie)3105 ttysigintr(void *cookie)
3106 {
3107           struct tty *tp;
3108           enum ttysigtype st;
3109           struct pgrp *pgrp;
3110           struct session *sess;
3111           int sig, lflag;
3112           char infobuf[200];
3113 
3114           mutex_enter(&proc_lock);
3115           mutex_spin_enter(&tty_lock);
3116           while ((tp = TAILQ_FIRST(&tty_sigqueue)) != NULL) {
3117                     KASSERT(tp->t_sigcount > 0);
3118                     for (st = TTYSIG_PG1; st < TTYSIG_COUNT; st++) {
3119                               if ((sig = firstsig(&tp->t_sigs[st])) != 0)
3120                                         break;
3121                     }
3122                     KASSERT(st < TTYSIG_COUNT);
3123                     sigdelset(&tp->t_sigs[st], sig);
3124                     if (--tp->t_sigcount == 0)
3125                               TAILQ_REMOVE(&tty_sigqueue, tp, t_sigqueue);
3126                     pgrp = tp->t_pgrp;
3127                     sess = tp->t_session;
3128                     lflag = tp->t_lflag;
3129                     if (sig == SIGINFO) {
3130                               if (ISSET(tp->t_state, TS_SIGINFO)) {
3131                                         /* Via ioctl: ignore tty option. */
3132                                         tp->t_state &= ~TS_SIGINFO;
3133                                         lflag |= ISIG;
3134                               }
3135                               if (!ISSET(lflag, NOKERNINFO)) {
3136                                         mutex_spin_exit(&tty_lock);
3137                                         ttygetinfo(tp, 1, infobuf, sizeof(infobuf));
3138                                         mutex_spin_enter(&tty_lock);
3139                                         ttyputinfo(tp, infobuf);
3140                               }
3141                               if (!ISSET(lflag, ISIG))
3142                                         continue;
3143                     }
3144                     mutex_spin_exit(&tty_lock);
3145                     KASSERT(sig != 0);
3146                     switch (st) {
3147                     case TTYSIG_PG1:
3148                               if (pgrp != NULL)
3149                                         pgsignal(pgrp, sig, 1);
3150                               break;
3151                     case TTYSIG_PG2:
3152                               if (pgrp != NULL)
3153                                         pgsignal(pgrp, sig, sess != NULL);
3154                               break;
3155                     case TTYSIG_LEADER:
3156                               if (sess != NULL && sess->s_leader != NULL)
3157                                         psignal(sess->s_leader, sig);
3158                               break;
3159                     default:
3160                               /* NOTREACHED */
3161                               break;
3162                     }
3163                     mutex_spin_enter(&tty_lock);
3164           }
3165           mutex_spin_exit(&tty_lock);
3166           mutex_exit(&proc_lock);
3167 }
3168 
3169 unsigned char
tty_getctrlchar(struct tty * tp,unsigned which)3170 tty_getctrlchar(struct tty *tp, unsigned which)
3171 {
3172           KASSERT(which < NCCS);
3173           return tp->t_cc[which];
3174 }
3175 
3176 void
tty_setctrlchar(struct tty * tp,unsigned which,unsigned char val)3177 tty_setctrlchar(struct tty *tp, unsigned which, unsigned char val)
3178 {
3179           KASSERT(which < NCCS);
3180           tp->t_cc[which] = val;
3181 }
3182 
3183 int
tty_try_xonxoff(struct tty * tp,unsigned char c)3184 tty_try_xonxoff(struct tty *tp, unsigned char c)
3185 {
3186     const struct cdevsw *cdev;
3187 
3188     if (tp->t_iflag & IXON) {
3189           if (c == tp->t_cc[VSTOP] && tp->t_cc[VSTOP] != _POSIX_VDISABLE) {
3190               if ((tp->t_state & TS_TTSTOP) == 0) {
3191                     tp->t_state |= TS_TTSTOP;
3192                     cdev = cdevsw_lookup(tp->t_dev);
3193                     if (cdev != NULL)
3194                               (*cdev->d_stop)(tp, 0);
3195               }
3196               return 0;
3197           }
3198           if (c == tp->t_cc[VSTART] && tp->t_cc[VSTART] != _POSIX_VDISABLE) {
3199               tp->t_state &= ~TS_TTSTOP;
3200               if (tp->t_oproc != NULL) {
3201                   mutex_spin_enter(&tty_lock);    /* XXX */
3202                     (*tp->t_oproc)(tp);
3203                   mutex_spin_exit(&tty_lock);     /* XXX */
3204               }
3205               return 0;
3206           }
3207     }
3208     return EAGAIN;
3209 }
3210