]> git.saurik.com Git - apple/xnu.git/blame - bsd/kern/tty.c
xnu-6153.81.5.tar.gz
[apple/xnu.git] / bsd / kern / tty.c
CommitLineData
1c79356b 1/*
cb323159 2 * Copyright (c) 1997-2019 Apple Inc. All rights reserved.
5d5c5d0d 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
0a7de745 5 *
2d21ac55
A
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
0a7de745 14 *
2d21ac55
A
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
0a7de745 17 *
2d21ac55
A
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
0a7de745 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b 27 */
1c79356b
A
28/*-
29 * Copyright (c) 1982, 1986, 1990, 1991, 1993
30 * The Regents of the University of California. All rights reserved.
31 * (c) UNIX System Laboratories, Inc.
32 * All or some portions of this file are derived from material licensed
33 * to the University of California by American Telephone and Telegraph
34 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
35 * the permission of UNIX System Laboratories, Inc.
36 *
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
39 * are met:
40 * 1. Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in the
44 * documentation and/or other materials provided with the distribution.
45 * 3. All advertising materials mentioning features or use of this software
46 * must display the following acknowledgement:
47 * This product includes software developed by the University of
48 * California, Berkeley and its contributors.
49 * 4. Neither the name of the University nor the names of its contributors
50 * may be used to endorse or promote products derived from this software
51 * without specific prior written permission.
52 *
53 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
57 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
59 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
63 * SUCH DAMAGE.
64 *
65 * @(#)tty.c 8.8 (Berkeley) 1/21/94
66 */
67/*-
68 * TODO:
69 * o Fix races for sending the start char in ttyflush().
70 * o Handle inter-byte timeout for "MIN > 0, TIME > 0" in ttyselect().
71 * With luck, there will be MIN chars before select() returns().
72 * o Handle CLOCAL consistently for ptys. Perhaps disallow setting it.
73 * o Don't allow input in TS_ZOMBIE case. It would be visible through
74 * FIONREAD.
75 * o Do the new sio locking stuff here and use it to avoid special
76 * case for EXTPROC?
77 * o Lock PENDIN too?
78 * o Move EXTPROC and/or PENDIN to t_state?
79 * o Wrap most of ttioctl in spltty/splx.
80 * o Implement TIOCNOTTY or remove it from <sys/ioctl.h>.
81 * o Send STOP if IXOFF is toggled off while TS_TBLOCK is set.
82 * o Don't allow certain termios flags to affect disciplines other
83 * than TTYDISC. Cancel their effects before switch disciplines
84 * and ignore them if they are set while we are in another
85 * discipline.
86 * o Handle c_ispeed = 0 to c_ispeed = c_ospeed conversion here instead
87 * of in drivers and fix drivers that write to tp->t_termios.
88 * o Check for TS_CARR_ON being set while everything is closed and not
89 * waiting for carrier. TS_CARR_ON isn't cleared if nothing is open,
90 * so it would live until the next open even if carrier drops.
91 * o Restore TS_WOPEN since it is useful in pstat. It must be cleared
92 * only when _all_ openers leave open().
93 */
1c79356b 94#include <sys/param.h>
0a7de745 95#define TTYDEFCHARS 1
1c79356b 96#include <sys/systm.h>
0a7de745 97#undef TTYDEFCHARS
1c79356b 98#include <sys/ioctl.h>
91447636
A
99#include <sys/proc_internal.h>
100#include <sys/kauth.h>
101#include <sys/file_internal.h>
1c79356b
A
102#include <sys/conf.h>
103#include <sys/dkstat.h>
b0d623f7 104#include <sys/uio_internal.h>
1c79356b
A
105#include <sys/kernel.h>
106#include <sys/vnode.h>
107#include <sys/syslog.h>
9bccf70c
A
108#include <sys/user.h>
109#include <sys/signalvar.h>
1c79356b 110#include <sys/signalvar.h>
1c79356b 111#include <sys/malloc.h>
1c79356b 112
1c79356b
A
113#include <dev/kmreg_com.h>
114#include <machine/cons.h>
0a7de745 115#include <sys/resource.h> /* averunnable */
5ba3f43e
A
116#include <kern/waitq.h>
117#include <libkern/section_keywords.h>
b0d623f7 118
0a7de745
A
119static lck_grp_t *tty_lck_grp;
120static lck_grp_attr_t *tty_lck_grp_attr;
b0d623f7
A
121static lck_attr_t *tty_lck_attr;
122
fe8ab488 123__private_extern__ int ttnread(struct tty *tp);
0a7de745
A
124static void ttyecho(int c, struct tty *tp);
125static int ttyoutput(int c, struct tty *tp);
126static void ttypend(struct tty *tp);
127static void ttyretype(struct tty *tp);
128static void ttyrub(int c, struct tty *tp);
129static void ttyrubo(struct tty *tp, int count);
130static void ttystop(struct tty *tp, int rw);
131static void ttyunblock(struct tty *tp);
132static int ttywflush(struct tty *tp);
133static int proc_compare(proc_t p1, proc_t p2);
2d21ac55 134
5ba3f43e 135void ttyhold(struct tty *tp);
0a7de745 136static void ttydeallocate(struct tty *tp);
316670eb 137
2d21ac55
A
138static int isctty(proc_t p, struct tty *tp);
139static int isctty_sp(proc_t p, struct tty *tp, struct session *sessp);
1c79356b
A
140
141/*
142 * Table with character classes and parity. The 8th bit indicates parity,
143 * the 7th bit indicates the character is an alphameric or underscore (for
144 * ALTWERASE), and the low 6 bits indicate delay type. If the low 6 bits
145 * are 0 then the character needs no special processing on output; classes
146 * other than 0 might be translated or (not currently) require delays.
147 */
0a7de745
A
148#define E 0x00 /* Even parity. */
149#define O 0x80 /* Odd parity. */
150#define PARITY(c) (char_type[c] & O)
1c79356b 151
0a7de745
A
152#define ALPHA 0x40 /* Alpha or underscore. */
153#define ISALPHA(c) (char_type[(c) & TTY_CHARMASK] & ALPHA)
1c79356b 154
0a7de745
A
155#define CCLASSMASK 0x3f
156#define CCLASS(c) (char_type[c] & CCLASSMASK)
2d21ac55 157/* 0b10xxxxxx is the mask for UTF-8 continuations */
0a7de745 158#define CCONT(c) ((c & 0xc0) == 0x80)
1c79356b 159
0a7de745
A
160#define BS BACKSPACE
161#define CC CONTROL
162#define CR RETURN
163#define NA ORDINARY | ALPHA
164#define NL NEWLINE
165#define NO ORDINARY
166#define TB TAB
167#define VT VTAB
1c79356b
A
168
169static u_char const char_type[] = {
0a7de745
A
170 E | CC, O | CC, O | CC, E | CC, O | CC, E | CC, E | CC, O | CC, /* nul - bel */
171 O | BS, E | TB, E | NL, O | CC, E | VT, O | CR, O | CC, E | CC, /* bs - si */
172 O | CC, E | CC, E | CC, O | CC, E | CC, O | CC, O | CC, E | CC, /* dle - etb */
173 E | CC, O | CC, O | CC, E | CC, O | CC, E | CC, E | CC, O | CC, /* can - us */
174 O | NO, E | NO, E | NO, O | NO, E | NO, O | NO, O | NO, E | NO, /* sp - ' */
175 E | NO, O | NO, O | NO, E | NO, O | NO, E | NO, E | NO, O | NO, /* ( - / */
176 E | NA, O | NA, O | NA, E | NA, O | NA, E | NA, E | NA, O | NA, /* 0 - 7 */
177 O | NA, E | NA, E | NO, O | NO, E | NO, O | NO, O | NO, E | NO, /* 8 - ? */
178 O | NO, E | NA, E | NA, O | NA, E | NA, O | NA, O | NA, E | NA, /* @ - G */
179 E | NA, O | NA, O | NA, E | NA, O | NA, E | NA, E | NA, O | NA, /* H - O */
180 E | NA, O | NA, O | NA, E | NA, O | NA, E | NA, E | NA, O | NA, /* P - W */
181 O | NA, E | NA, E | NA, O | NO, E | NO, O | NO, O | NO, O | NA, /* X - _ */
182 E | NO, O | NA, O | NA, E | NA, O | NA, E | NA, E | NA, O | NA, /* ` - g */
183 O | NA, E | NA, E | NA, O | NA, E | NA, O | NA, O | NA, E | NA, /* h - o */
184 O | NA, E | NA, E | NA, O | NA, E | NA, O | NA, O | NA, E | NA, /* p - w */
185 E | NA, O | NA, O | NA, E | NO, O | NO, E | NO, E | NO, O | CC, /* x - del */
1c79356b
A
186 /*
187 * Meta chars; should be settable per character set;
188 * for now, treat them all as normal characters.
189 */
0a7de745
A
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 NA, NA, NA, NA, NA, NA, NA, NA,
196 NA, NA, NA, NA, NA, NA, NA, NA,
197 NA, NA, NA, NA, NA, NA, NA, NA,
198 NA, NA, NA, NA, NA, NA, NA, NA,
199 NA, NA, NA, NA, NA, NA, NA, NA,
200 NA, NA, NA, NA, NA, NA, NA, NA,
201 NA, NA, NA, NA, NA, NA, NA, NA,
202 NA, NA, NA, NA, NA, NA, NA, NA,
203 NA, NA, NA, NA, NA, NA, NA, NA,
204 NA, NA, NA, NA, NA, NA, NA, NA,
205 NA, NA, NA, NA, NA, NA, NA, NA,
1c79356b 206};
0a7de745
A
207#undef BS
208#undef CC
209#undef CR
210#undef NA
211#undef NL
212#undef NO
213#undef TB
214#undef VT
1c79356b
A
215
216/* Macros to clear/set/test flags. */
0a7de745
A
217#define SET(t, f) (t) |= (f)
218#define CLR(t, f) (t) &= ~(f)
219#define ISSET(t, f) ((t) & (f))
1c79356b
A
220
221/*
222 * Input control starts when we would not be able to fit the maximum
223 * contents of the ping-pong buffers and finishes when we would be able
224 * to fit that much plus 1/8 more.
225 */
0a7de745
A
226#define I_HIGH_WATER (TTYHOG - 2 * 256) /* XXX */
227#define I_LOW_WATER ((TTYHOG - 2 * 256) * 7 / 8) /* XXX */
1c79356b 228
91447636 229static void
b0d623f7 230termios32to64(struct termios32 *in, struct user_termios *out)
91447636
A
231{
232 out->c_iflag = (user_tcflag_t)in->c_iflag;
233 out->c_oflag = (user_tcflag_t)in->c_oflag;
234 out->c_cflag = (user_tcflag_t)in->c_cflag;
235 out->c_lflag = (user_tcflag_t)in->c_lflag;
236
237 /* bcopy is OK, since this type is ILP32/LP64 size invariant */
238 bcopy(in->c_cc, out->c_cc, sizeof(in->c_cc));
239
240 out->c_ispeed = (user_speed_t)in->c_ispeed;
241 out->c_ospeed = (user_speed_t)in->c_ospeed;
242}
243
244static void
b0d623f7 245termios64to32(struct user_termios *in, struct termios32 *out)
91447636
A
246{
247 out->c_iflag = (tcflag_t)in->c_iflag;
248 out->c_oflag = (tcflag_t)in->c_oflag;
249 out->c_cflag = (tcflag_t)in->c_cflag;
250 out->c_lflag = (tcflag_t)in->c_lflag;
251
252 /* bcopy is OK, since this type is ILP32/LP64 size invariant */
253 bcopy(in->c_cc, out->c_cc, sizeof(in->c_cc));
254
255 out->c_ispeed = (speed_t)in->c_ispeed;
256 out->c_ospeed = (speed_t)in->c_ospeed;
257}
258
259
1c79356b 260/*
b0d623f7
A
261 * tty_init
262 *
263 * Initialize the tty line discipline subsystem.
264 *
265 * Parameters: void
266 *
267 * Returns: void
268 *
269 * Locks: No ttys can be allocated and no tty locks can be used
270 * until after this function is called
271 *
272 * Notes: The intent of this is to set up a log group attribute,
273 * lock group, and loc atribute for subsequent per-tty locks.
274 * This function is called early in bsd_init(), prior to the
275 * console device initialization.
276 */
277void
278tty_init(void)
279{
280 tty_lck_grp_attr = lck_grp_attr_alloc_init();
0a7de745 281 tty_lck_grp = lck_grp_alloc_init("tty", tty_lck_grp_attr);
b0d623f7
A
282 tty_lck_attr = lck_attr_alloc_init();
283}
284
285
286/*
287 * tty_lock
288 *
289 * Lock the requested tty structure.
290 *
291 * Parameters: tp The tty we want to lock
292 *
293 * Returns: void
294 *
295 * Locks: On return, tp is locked
296 */
297void
298tty_lock(struct tty *tp)
299{
0a7de745 300 TTY_LOCK_NOTOWNED(tp); /* debug assert */
b0d623f7
A
301 lck_mtx_lock(&tp->t_lock);
302}
303
304
305/*
306 * tty_unlock
307 *
308 * Unlock the requested tty structure.
309 *
310 * Parameters: tp The tty we want to unlock
311 *
312 * Returns: void
313 *
314 * Locks: On return, tp is unlocked
315 */
316void
317tty_unlock(struct tty *tp)
318{
0a7de745 319 TTY_LOCK_OWNED(tp); /* debug assert */
b0d623f7
A
320 lck_mtx_unlock(&tp->t_lock);
321}
322
b0d623f7
A
323/*
324 * ttyopen (LDISC)
325 *
1c79356b 326 * Initial open of tty, or (re)entry to standard tty line discipline.
b0d623f7
A
327 *
328 * Locks: Assumes tty_lock() is held prior to calling.
1c79356b
A
329 */
330int
2d21ac55 331ttyopen(dev_t device, struct tty *tp)
1c79356b 332{
0a7de745 333 TTY_LOCK_OWNED(tp); /* debug assert */
2d21ac55 334
1c79356b 335 tp->t_dev = device;
2d21ac55 336
1c79356b
A
337 if (!ISSET(tp->t_state, TS_ISOPEN)) {
338 SET(tp->t_state, TS_ISOPEN);
339 if (ISSET(tp->t_cflag, CLOCAL)) {
0a7de745
A
340 SET(tp->t_state, TS_CONNECTED);
341 }
1c79356b
A
342 bzero(&tp->t_winsize, sizeof(tp->t_winsize));
343 }
344
0a7de745 345 return 0;
1c79356b
A
346}
347
348/*
b0d623f7
A
349 * ttyclose
350 *
1c79356b
A
351 * Handle close() on a tty line: flush and set to initial state,
352 * bumping generation number so that pending read/write calls
353 * can detect recycling of the tty.
354 * XXX our caller should have done `spltty(); l_close(); ttyclose();'
355 * and l_close() should have flushed, but we repeat the spltty() and
356 * the flush in case there are buggy callers.
b0d623f7
A
357 *
358 * Locks: Assumes tty_lock() is held prior to calling.
1c79356b
A
359 */
360int
2d21ac55 361ttyclose(struct tty *tp)
1c79356b 362{
2d21ac55
A
363 struct pgrp * oldpg;
364 struct session * oldsessp;
5ba3f43e 365 struct knote *kn;
1c79356b 366
0a7de745 367 TTY_LOCK_OWNED(tp); /* debug assert */
b0d623f7 368
1c79356b
A
369 if (constty == tp) {
370 constty = NULL;
371
1c79356b 372
1c79356b
A
373 /*
374 * Closing current console tty; disable printing of console
0a7de745 375 * messages at bottom-level driver.
1c79356b
A
376 */
377 (*cdevsw[major(tp->t_dev)].d_ioctl)
0a7de745 378 (tp->t_dev, KMIOCDISABLCONS, NULL, 0, current_proc());
1c79356b
A
379 }
380
381 ttyflush(tp, FREAD | FWRITE);
1c79356b
A
382
383 tp->t_gen++;
384 tp->t_line = TTYDISC;
2d21ac55
A
385 proc_list_lock();
386 oldpg = tp->t_pgrp;
387 oldsessp = tp->t_session;
1c79356b
A
388 tp->t_pgrp = NULL;
389 tp->t_session = NULL;
0a7de745 390 if (oldsessp != SESSION_NULL) {
2d21ac55 391 oldsessp->s_ttypgrpid = NO_PID;
0a7de745 392 }
2d21ac55
A
393 proc_list_unlock();
394 /* drop the reference on prev session and pgrp */
b0d623f7
A
395 /* SAFE: All callers drop the lock on return */
396 tty_unlock(tp);
0a7de745 397 if (oldsessp != SESSION_NULL) {
2d21ac55 398 session_rele(oldsessp);
0a7de745
A
399 }
400 if (oldpg != PGRP_NULL) {
2d21ac55 401 pg_rele(oldpg);
0a7de745 402 }
b0d623f7 403 tty_lock(tp);
1c79356b 404 tp->t_state = 0;
5ba3f43e
A
405 SLIST_FOREACH(kn, &tp->t_wsel.si_note, kn_selnext) {
406 KNOTE_DETACH(&tp->t_wsel.si_note, kn);
407 }
1c79356b 408 selthreadclear(&tp->t_wsel);
5ba3f43e
A
409 SLIST_FOREACH(kn, &tp->t_rsel.si_note, kn_selnext) {
410 KNOTE_DETACH(&tp->t_rsel.si_note, kn);
411 }
1c79356b 412 selthreadclear(&tp->t_rsel);
5ba3f43e 413
0a7de745 414 return 0;
1c79356b
A
415}
416
0a7de745
A
417#define FLUSHQ(q) { \
418 if ((q)->c_cc) \
419 ndflush(q, (q)->c_cc); \
1c79356b
A
420}
421
422/* Is 'c' a line delimiter ("break" character)? */
0a7de745
A
423#define TTBREAKC(c, lflag) \
424 ((c) == '\n' || (((c) == cc[VEOF] || \
425 (c) == cc[VEOL] || ((c) == cc[VEOL2] && lflag & IEXTEN)) && \
1c79356b
A
426 (c) != _POSIX_VDISABLE))
427
428/*
b0d623f7
A
429 * ttyinput (LDISC)
430 *
1c79356b 431 * Process input of a single character received on a tty.
b0d623f7
A
432 *
433 * Parameters: c The character received
434 * tp The tty on which it was received
435 *
436 * Returns: .
437 *
438 * Locks: Assumes tty_lock() is held prior to calling.
1c79356b
A
439 */
440int
2d21ac55 441ttyinput(int c, struct tty *tp)
1c79356b 442{
2d21ac55
A
443 tcflag_t iflag, lflag;
444 cc_t *cc;
b0d623f7 445 int i, err;
0a7de745
A
446 int retval = 0; /* default return value */
447
448 TTY_LOCK_OWNED(tp); /* debug assert */
1c79356b 449
1c79356b
A
450 /*
451 * If input is pending take it first.
452 */
453 lflag = tp->t_lflag;
0a7de745 454 if (ISSET(lflag, PENDIN)) {
1c79356b 455 ttypend(tp);
0a7de745 456 }
1c79356b
A
457 /*
458 * Gather stats.
459 */
460 if (ISSET(lflag, ICANON)) {
461 ++tk_cancc;
462 ++tp->t_cancc;
463 } else {
464 ++tk_rawcc;
465 ++tp->t_rawcc;
466 }
467 ++tk_nin;
468
469 /*
470 * Block further input iff:
471 * current input > threshold AND input is available to user program
472 * AND input flow control is enabled and not yet invoked.
473 * The 3 is slop for PARMRK.
474 */
475 iflag = tp->t_iflag;
476 if (tp->t_rawq.c_cc + tp->t_canq.c_cc > I_HIGH_WATER - 3 &&
477 (!ISSET(lflag, ICANON) || tp->t_canq.c_cc != 0) &&
478 (ISSET(tp->t_cflag, CRTS_IFLOW) || ISSET(iflag, IXOFF)) &&
0a7de745 479 !ISSET(tp->t_state, TS_TBLOCK)) {
1c79356b 480 ttyblock(tp);
0a7de745 481 }
1c79356b
A
482
483 /* Handle exceptional conditions (break, parity, framing). */
484 cc = tp->t_cc;
485 err = (ISSET(c, TTY_ERRORMASK));
486 if (err) {
487 CLR(c, TTY_ERRORMASK);
488 if (ISSET(err, TTY_BI)) {
489 if (ISSET(iflag, IGNBRK)) {
b0d623f7 490 goto out;
0a7de745 491 }
1c79356b
A
492 if (ISSET(iflag, BRKINT)) {
493 ttyflush(tp, FREAD | FWRITE);
b0d623f7
A
494 /* SAFE: All callers drop the lock on return */
495 tty_unlock(tp);
2d21ac55 496 tty_pgsignal(tp, SIGINT, 1);
b0d623f7 497 tty_lock(tp);
1c79356b
A
498 goto endcase;
499 }
0a7de745 500 if (ISSET(iflag, PARMRK)) {
1c79356b 501 goto parmrk;
0a7de745 502 }
1c79356b 503 } else if ((ISSET(err, TTY_PE) && ISSET(iflag, INPCK))
0a7de745 504 || ISSET(err, TTY_FE)) {
1c79356b 505 if (ISSET(iflag, IGNPAR)) {
b0d623f7 506 goto out;
0a7de745 507 } else if (ISSET(iflag, PARMRK)) {
1c79356b
A
508parmrk:
509 if (tp->t_rawq.c_cc + tp->t_canq.c_cc >
0a7de745 510 MAX_INPUT - 3) {
1c79356b 511 goto input_overflow;
0a7de745 512 }
1c79356b
A
513 (void)putc(0377 | TTY_QUOTE, &tp->t_rawq);
514 (void)putc(0 | TTY_QUOTE, &tp->t_rawq);
515 (void)putc(c | TTY_QUOTE, &tp->t_rawq);
516 goto endcase;
0a7de745 517 } else {
1c79356b 518 c = 0;
0a7de745 519 }
1c79356b
A
520 }
521 }
522
0a7de745 523 if (!ISSET(tp->t_state, TS_TYPEN) && ISSET(iflag, ISTRIP)) {
1c79356b 524 CLR(c, 0x80);
0a7de745 525 }
1c79356b
A
526 if (!ISSET(lflag, EXTPROC)) {
527 /*
528 * Check for literal nexting very first
529 */
530 if (ISSET(tp->t_state, TS_LNCH)) {
531 SET(c, TTY_QUOTE);
532 CLR(tp->t_state, TS_LNCH);
533 }
534 /*
535 * Scan for special characters. This code
536 * is really just a big case statement with
537 * non-constant cases. The bottom of the
538 * case statement is labeled ``endcase'', so goto
539 * it after a case match, or similar.
540 */
541
542 /*
543 * Control chars which aren't controlled
544 * by ICANON, ISIG, or IXON.
545 */
546 if (ISSET(lflag, IEXTEN)) {
547 if (CCEQ(cc[VLNEXT], c)) {
548 if (ISSET(lflag, ECHO)) {
549 if (ISSET(lflag, ECHOE)) {
550 (void)ttyoutput('^', tp);
551 (void)ttyoutput('\b', tp);
0a7de745 552 } else {
1c79356b 553 ttyecho(c, tp);
0a7de745 554 }
1c79356b
A
555 }
556 SET(tp->t_state, TS_LNCH);
557 goto endcase;
558 }
559 if (CCEQ(cc[VDISCARD], c)) {
0a7de745 560 if (ISSET(lflag, FLUSHO)) {
1c79356b 561 CLR(tp->t_lflag, FLUSHO);
0a7de745 562 } else {
1c79356b
A
563 ttyflush(tp, FWRITE);
564 ttyecho(c, tp);
0a7de745 565 if (tp->t_rawq.c_cc + tp->t_canq.c_cc) {
1c79356b 566 ttyretype(tp);
0a7de745 567 }
1c79356b
A
568 SET(tp->t_lflag, FLUSHO);
569 }
570 goto startoutput;
571 }
572 }
573 /*
574 * Signals.
575 */
576 if (ISSET(lflag, ISIG)) {
577 if (CCEQ(cc[VINTR], c) || CCEQ(cc[VQUIT], c)) {
0a7de745 578 if (!ISSET(lflag, NOFLSH)) {
1c79356b 579 ttyflush(tp, FREAD | FWRITE);
0a7de745 580 }
1c79356b 581 ttyecho(c, tp);
b0d623f7
A
582 /*
583 * SAFE: All callers drop the lock on return;
584 * SAFE: if we lose a threaded race on change
585 * SAFE: of the interrupt character, we could
586 * SAFE: have lost that race anyway due to the
587 * SAFE: scheduler executing threads in
588 * SAFE: priority order rather than "last
589 * SAFE: active thread" order (FEATURE).
590 */
591 tty_unlock(tp);
2d21ac55 592 tty_pgsignal(tp,
1c79356b 593 CCEQ(cc[VINTR], c) ? SIGINT : SIGQUIT, 1);
b0d623f7 594 tty_lock(tp);
1c79356b
A
595 goto endcase;
596 }
597 if (CCEQ(cc[VSUSP], c)) {
0a7de745 598 if (!ISSET(lflag, NOFLSH)) {
1c79356b 599 ttyflush(tp, FREAD);
0a7de745 600 }
1c79356b 601 ttyecho(c, tp);
b0d623f7
A
602 /* SAFE: All callers drop the lock on return */
603 tty_unlock(tp);
2d21ac55 604 tty_pgsignal(tp, SIGTSTP, 1);
b0d623f7 605 tty_lock(tp);
1c79356b
A
606 goto endcase;
607 }
608 }
609 /*
610 * Handle start/stop characters.
611 */
612 if (ISSET(iflag, IXON)) {
613 if (CCEQ(cc[VSTOP], c)) {
614 if (!ISSET(tp->t_state, TS_TTSTOP)) {
615 SET(tp->t_state, TS_TTSTOP);
0a7de745 616 ttystop(tp, 0);
b0d623f7 617 goto out;
1c79356b
A
618 }
619 if (!CCEQ(cc[VSTART], c)) {
b0d623f7 620 goto out;
0a7de745 621 }
1c79356b
A
622 /*
623 * if VSTART == VSTOP then toggle
624 */
625 goto endcase;
626 }
0a7de745 627 if (CCEQ(cc[VSTART], c)) {
1c79356b 628 goto restartoutput;
0a7de745 629 }
1c79356b
A
630 }
631 /*
632 * IGNCR, ICRNL, & INLCR
633 */
634 if (c == '\r') {
635 if (ISSET(iflag, IGNCR)) {
b0d623f7 636 goto out;
0a7de745 637 } else if (ISSET(iflag, ICRNL)) {
1c79356b 638 c = '\n';
0a7de745
A
639 }
640 } else if (c == '\n' && ISSET(iflag, INLCR)) {
1c79356b 641 c = '\r';
0a7de745 642 }
1c79356b
A
643 }
644 if (!ISSET(tp->t_lflag, EXTPROC) && ISSET(lflag, ICANON)) {
645 /*
646 * From here on down canonical mode character
647 * processing takes place.
648 */
649 /*
650 * erase (^H / ^?)
651 */
652 if (CCEQ(cc[VERASE], c)) {
2d21ac55
A
653 if (tp->t_rawq.c_cc) {
654 if (ISSET(iflag, IUTF8)) {
655 do {
656 ttyrub((c = unputc(&tp->t_rawq)), tp);
0a7de745 657 } while (tp->t_rawq.c_cc && CCONT(c));
2d21ac55
A
658 } else {
659 ttyrub(unputc(&tp->t_rawq), tp);
660 }
661 }
1c79356b
A
662 goto endcase;
663 }
664 /*
665 * kill (^U)
666 */
667 if (CCEQ(cc[VKILL], c)) {
668 if (ISSET(lflag, ECHOKE) &&
669 tp->t_rawq.c_cc == tp->t_rocount &&
0a7de745
A
670 !ISSET(lflag, ECHOPRT)) {
671 while (tp->t_rawq.c_cc) {
1c79356b 672 ttyrub(unputc(&tp->t_rawq), tp);
0a7de745
A
673 }
674 } else {
1c79356b
A
675 ttyecho(c, tp);
676 if (ISSET(lflag, ECHOK) ||
0a7de745 677 ISSET(lflag, ECHOKE)) {
1c79356b 678 ttyecho('\n', tp);
0a7de745 679 }
1c79356b
A
680 FLUSHQ(&tp->t_rawq);
681 tp->t_rocount = 0;
682 }
683 CLR(tp->t_state, TS_LOCAL);
684 goto endcase;
685 }
686 /*
687 * word erase (^W)
688 */
689 if (CCEQ(cc[VWERASE], c) && ISSET(lflag, IEXTEN)) {
690 int ctype;
691
692 /*
693 * erase whitespace
694 */
0a7de745 695 while ((c = unputc(&tp->t_rawq)) == ' ' || c == '\t') {
1c79356b 696 ttyrub(c, tp);
0a7de745
A
697 }
698 if (c == -1) {
1c79356b 699 goto endcase;
0a7de745 700 }
1c79356b
A
701 /*
702 * erase last char of word and remember the
703 * next chars type (for ALTWERASE)
704 */
705 ttyrub(c, tp);
706 c = unputc(&tp->t_rawq);
0a7de745 707 if (c == -1) {
1c79356b 708 goto endcase;
0a7de745 709 }
1c79356b
A
710 if (c == ' ' || c == '\t') {
711 (void)putc(c, &tp->t_rawq);
712 goto endcase;
713 }
714 ctype = ISALPHA(c);
715 /*
716 * erase rest of word
717 */
718 do {
719 ttyrub(c, tp);
720 c = unputc(&tp->t_rawq);
0a7de745 721 if (c == -1) {
1c79356b 722 goto endcase;
0a7de745 723 }
1c79356b
A
724 } while (c != ' ' && c != '\t' &&
725 (!ISSET(lflag, ALTWERASE) || ISALPHA(c) == ctype));
726 (void)putc(c, &tp->t_rawq);
727 goto endcase;
728 }
729 /*
730 * reprint line (^R)
731 */
732 if (CCEQ(cc[VREPRINT], c) && ISSET(lflag, IEXTEN)) {
733 ttyretype(tp);
734 goto endcase;
735 }
736 /*
737 * ^T - kernel info and generate SIGINFO
738 */
739 if (CCEQ(cc[VSTATUS], c) && ISSET(lflag, IEXTEN)) {
b0d623f7
A
740 if (ISSET(lflag, ISIG)) {
741 /* SAFE: All callers drop the lock on return */
742 tty_unlock(tp);
2d21ac55 743 tty_pgsignal(tp, SIGINFO, 1);
b0d623f7
A
744 tty_lock(tp);
745 }
0a7de745 746 if (!ISSET(lflag, NOKERNINFO)) {
b0d623f7 747 ttyinfo_locked(tp);
0a7de745 748 }
1c79356b
A
749 goto endcase;
750 }
751 }
752 /*
753 * Check for input buffer overflow
754 */
755 if (tp->t_rawq.c_cc + tp->t_canq.c_cc >= MAX_INPUT) {
756input_overflow:
757 if (ISSET(iflag, IMAXBEL)) {
0a7de745 758 if (tp->t_outq.c_cc < tp->t_hiwat) {
1c79356b 759 (void)ttyoutput(CTRL('g'), tp);
0a7de745 760 }
1c79356b
A
761 }
762 goto endcase;
763 }
764
0a7de745
A
765 if (c == 0377 && ISSET(iflag, PARMRK) && !ISSET(iflag, ISTRIP)
766 && ISSET(iflag, IGNBRK | IGNPAR) != (IGNBRK | IGNPAR)) {
1c79356b 767 (void)putc(0377 | TTY_QUOTE, &tp->t_rawq);
0a7de745 768 }
1c79356b
A
769
770 /*
771 * Put data char in q for user and
772 * wakeup on seeing a line delimiter.
773 */
774 if (putc(c, &tp->t_rawq) >= 0) {
775 if (!ISSET(lflag, ICANON)) {
776 ttwakeup(tp);
777 ttyecho(c, tp);
778 goto endcase;
779 }
780 if (TTBREAKC(c, lflag)) {
781 tp->t_rocount = 0;
782 catq(&tp->t_rawq, &tp->t_canq);
783 ttwakeup(tp);
0a7de745 784 } else if (tp->t_rocount++ == 0) {
1c79356b 785 tp->t_rocol = tp->t_column;
0a7de745 786 }
1c79356b
A
787 if (ISSET(tp->t_state, TS_ERASE)) {
788 /*
789 * end of prterase \.../
790 */
791 CLR(tp->t_state, TS_ERASE);
792 (void)ttyoutput('/', tp);
793 }
794 i = tp->t_column;
795 ttyecho(c, tp);
796 if (CCEQ(cc[VEOF], c) && ISSET(lflag, ECHO)) {
797 /*
798 * Place the cursor over the '^' of the ^D.
799 */
800 i = min(2, tp->t_column - i);
801 while (i > 0) {
802 (void)ttyoutput('\b', tp);
803 i--;
804 }
805 }
806 }
b0d623f7 807
1c79356b
A
808endcase:
809 /*
810 * IXANY means allow any character to restart output.
811 */
812 if (ISSET(tp->t_state, TS_TTSTOP) &&
813 !ISSET(iflag, IXANY) && cc[VSTART] != cc[VSTOP]) {
0a7de745
A
814 goto out;
815 }
b0d623f7 816
1c79356b
A
817restartoutput:
818 CLR(tp->t_lflag, FLUSHO);
819 CLR(tp->t_state, TS_TTSTOP);
b0d623f7 820
1c79356b 821startoutput:
b0d623f7
A
822 /* Start the output */
823 retval = ttstart(tp);
824
825out:
0a7de745 826 return retval;
1c79356b
A
827}
828
b0d623f7 829
1c79356b 830/*
b0d623f7
A
831 * ttyoutput
832 *
1c79356b
A
833 * Output a single character on a tty, doing output processing
834 * as needed (expanding tabs, newline processing, etc.).
b0d623f7
A
835 *
836 * Parameters: c The character to output
837 * tp The tty on which to output on the tty
838 *
839 * Returns: < 0 Success
840 * >= 0 Character to resend (failure)
841 *
842 * Locks: Assumes tp is locked on entry, remains locked on exit
843 *
844 * Notes: Must be recursive.
1c79356b
A
845 */
846static int
2d21ac55 847ttyoutput(int c, struct tty *tp)
1c79356b 848{
2d21ac55
A
849 tcflag_t oflag;
850 int col;
1c79356b 851
0a7de745 852 TTY_LOCK_OWNED(tp); /* debug assert */
b0d623f7 853
1c79356b
A
854 oflag = tp->t_oflag;
855 if (!ISSET(oflag, OPOST)) {
0a7de745
A
856 if (ISSET(tp->t_lflag, FLUSHO)) {
857 return -1;
858 }
859 if (putc(c, &tp->t_outq)) {
860 return c;
861 }
1c79356b
A
862 tk_nout++;
863 tp->t_outcc++;
0a7de745 864 return -1;
1c79356b
A
865 }
866 /*
867 * Do tab expansion if OXTABS is set. Special case if we external
868 * processing, we don't do the tab expansion because we'll probably
869 * get it wrong. If tab expansion needs to be done, let it happen
870 * externally.
871 */
872 CLR(c, ~TTY_CHARMASK);
873 if (c == '\t' &&
874 ISSET(oflag, OXTABS) && !ISSET(tp->t_lflag, EXTPROC)) {
2d21ac55 875 col = c = 8 - (tp->t_column & 7);
1c79356b 876 if (!ISSET(tp->t_lflag, FLUSHO)) {
2d21ac55 877 c -= b_to_q((const u_char *)" ", c, &tp->t_outq);
1c79356b
A
878 tk_nout += c;
879 tp->t_outcc += c;
1c79356b
A
880 }
881 tp->t_column += c;
0a7de745
A
882 return c == col ? -1 : '\t';
883 }
884 if (c == CEOT && ISSET(oflag, ONOEOT)) {
885 return -1;
1c79356b 886 }
1c79356b
A
887
888 /*
889 * Newline translation: if ONLCR is set,
890 * translate newline into "\r\n".
891 */
892 if (c == '\n' && ISSET(tp->t_oflag, ONLCR)) {
893 tk_nout++;
894 tp->t_outcc++;
0a7de745
A
895 if (putc('\r', &tp->t_outq)) {
896 return c;
897 }
898 }
899 /* If OCRNL is set, translate "\r" into "\n". */
900 else if (c == '\r' && ISSET(tp->t_oflag, OCRNL)) {
901 c = '\n';
902 }
903 /* If ONOCR is set, don't transmit CRs when on column 0. */
904 else if (c == '\r' && ISSET(tp->t_oflag, ONOCR) && tp->t_column == 0) {
905 return -1;
906 }
1c79356b
A
907 tk_nout++;
908 tp->t_outcc++;
0a7de745
A
909 if (!ISSET(tp->t_lflag, FLUSHO) && putc(c, &tp->t_outq)) {
910 return c;
911 }
1c79356b
A
912
913 col = tp->t_column;
914 switch (CCLASS(c)) {
915 case BACKSPACE:
0a7de745 916 if (col > 0) {
1c79356b 917 --col;
0a7de745 918 }
1c79356b
A
919 break;
920 case CONTROL:
921 break;
922 case NEWLINE:
923 case RETURN:
924 col = 0;
925 break;
926 case ORDINARY:
927 ++col;
928 break;
929 case TAB:
930 col = (col + 8) & ~7;
931 break;
932 }
933 tp->t_column = col;
0a7de745 934 return -1;
1c79356b
A
935}
936
fe8ab488
A
937/*
938 * Sets the tty state to not allow any more changes of foreground process
939 * group. This is required to be done so that a subsequent revoke on a vnode
940 * is able to always successfully complete.
941 *
942 * Locks : Assumes tty_lock held on entry
943 */
944void
945ttysetpgrphup(struct tty *tp)
946{
947 TTY_LOCK_OWNED(tp); /* debug assert */
948 SET(tp->t_state, TS_PGRPHUP);
d9a64523
A
949 /*
950 * Also wake up sleeping readers which may or may not belong to the
951 * current foreground process group.
952 *
953 * This forces any non-fg readers (which entered read when
954 * that process group was in the fg) to return with EIO (if they're
955 * catching SIGTTIN or with SIGTTIN). The ones which do belong to the fg
956 * process group will promptly go back to sleep and get a SIGHUP shortly
957 * This would normally happen as part of the close in revoke but if
958 * there is a sleeping reader from a non-fg process group we never get
959 * to the close because the sleeping reader holds an iocount on the
960 * vnode of the terminal which is going to get revoked->reclaimed.
961 */
962 wakeup(TSA_HUP_OR_INPUT(tp));
fe8ab488
A
963}
964
965/*
966 * Locks : Assumes tty lock held on entry
967 */
968void
969ttyclrpgrphup(struct tty *tp)
970{
971 TTY_LOCK_OWNED(tp); /* debug assert */
972 CLR(tp->t_state, TS_PGRPHUP);
973}
b0d623f7 974
1c79356b 975/*
b0d623f7
A
976 * ttioctl
977 *
978 * Identical to ttioctl_locked, only the lock is not held
979 *
980 * Parameters: <See ttioctl_locked()>
981 *
982 * Returns: <See ttioctl_locked()>
983 *
984 * Locks: This function assumes the tty_lock() is not held on entry;
985 * it takes the lock, and releases it before returning.
986 *
987 * Notes: This is supported to ensure the line discipline interfaces
988 * all have the same locking semantics.
989 *
0a7de745 990 * This function is called from
1c79356b 991 */
1c79356b 992int
b0d623f7
A
993ttioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, proc_t p)
994{
0a7de745 995 int retval;
b0d623f7
A
996
997 tty_lock(tp);
998 retval = ttioctl_locked(tp, cmd, data, flag, p);
999 tty_unlock(tp);
1000
0a7de745 1001 return retval;
b0d623f7
A
1002}
1003
1004
1005/*
1006 * ttioctl_locked
1007 *
1008 * Ioctls for all tty devices.
1009 *
1010 * Parameters: tp Tty on which ioctl() is being called
1011 * cmd ioctl() command parameter
1012 * data ioctl() data argument (if any)
1013 * flag fileglob open modes from fcntl.h;
1014 * if called internally, this is usually
1015 * set to 0, rather than something useful
1016 * p Process context for the call; if the
1017 * call is proxied to a worker thread,
1018 * this will not be the current process!!!
1019 *
1020 * Returns: 0 Success
1021 * EIO I/O error (no process group, job
1022 * control, etc.)
1023 * EINTR Interrupted by signal
1024 * EBUSY Attempt to become the console while
1025 * the console is busy
1026 * ENOTTY TIOCGPGRP on a non-controlling tty
1027 * EINVAL Invalid baud rate
1028 * ENXIO TIOCSETD of invalid line discipline
1029 * EPERM TIOCSTI, not root, not open for read
1030 * EACCES TIOCSTI, not root, not your controlling
1031 * tty
1032 * EPERM TIOCSCTTY failed
1033 * ENOTTY/EINVAL/EPERM TIOCSPGRP failed
1034 * EPERM TIOCSDRAINWAIT as non-root user
1035 * suser:EPERM Console control denied
1036 * ttywait:EIO t_timeout too small/expired
1037 * ttywait:ERESTART Upper layer must redrive the call;
1038 * this is usually done by the Libc
1039 * stub in user space
1040 * ttywait:EINTR Interrupted (usually a signal)
1041 * ttcompat:EINVAL
1042 * ttcompat:ENOTTY
1043 * ttcompat:EIOCTL
1044 * ttcompat:ENOTTY TIOCGSID, if no session or session
1045 * leader
1046 * ttcompat:ENOTTY All unrecognized ioctls
1047 * *tp->t_param:? TIOCSETA* underlying function
1048 * *linesw[t].l_open:? TIOCSETD line discipline open failure
1049 *
1050 *
1051 * Locks: This function assumes that the tty_lock() is held for the
1052 * tp at the time of the call. The lock remains held on return.
1053 *
1054 * Notes: This function is called after line-discipline specific ioctl
1055 * has been called to do discipline-specific functions and/or
1056 * reject any of these ioctl() commands.
1057 *
1058 * This function calls ttcompat(), which can re-call ttioctl()
1059 * to a depth of one (FORTRAN style mutual recursion); at some
1060 * point, we should just in-line ttcompat() here.
1061 */
1062int
1063ttioctl_locked(struct tty *tp, u_long cmd, caddr_t data, int flag, proc_t p)
1c79356b 1064{
2d21ac55 1065 int error = 0;
3e170ce0 1066 int bogusData = 1;
9bccf70c 1067 struct uthread *ut;
316670eb
A
1068 struct pgrp *pg, *oldpg;
1069 struct session *sessp, *oldsessp;
1070 struct tty *oldtp;
1c79356b 1071
0a7de745 1072 TTY_LOCK_OWNED(tp); /* debug assert */
b0d623f7 1073
91447636 1074 ut = (struct uthread *)get_bsdthread_info(current_thread());
2d21ac55 1075 /* If the ioctl involves modification, signal if in the background. */
1c79356b 1076 switch (cmd) {
2d21ac55
A
1077 case TIOCIXON:
1078 case TIOCIXOFF:
1079 case TIOCDRAIN:
1c79356b 1080 case TIOCFLUSH:
2d21ac55
A
1081 case TIOCSTOP:
1082 case TIOCSTART:
b0d623f7 1083 case TIOCSETA_32:
91447636 1084 case TIOCSETA_64:
1c79356b 1085 case TIOCSETD:
b0d623f7 1086 case TIOCSETAF_32:
91447636 1087 case TIOCSETAF_64:
b0d623f7 1088 case TIOCSETAW_32:
91447636 1089 case TIOCSETAW_64:
1c79356b 1090 case TIOCSPGRP:
1c79356b
A
1091 case TIOCSTAT:
1092 case TIOCSTI:
1093 case TIOCSWINSZ:
1c79356b
A
1094 case TIOCLBIC:
1095 case TIOCLBIS:
1096 case TIOCLSET:
1097 case TIOCSETC:
1098 case OTIOCSETD:
1099 case TIOCSETN:
1100 case TIOCSETP:
1101 case TIOCSLTC:
1c79356b 1102 while (isbackground(p, tp) &&
2d21ac55 1103 (p->p_lflag & P_LPPWAIT) == 0 &&
1c79356b 1104 (p->p_sigignore & sigmask(SIGTTOU)) == 0 &&
9bccf70c 1105 (ut->uu_sigmask & sigmask(SIGTTOU)) == 0) {
2d21ac55
A
1106 pg = proc_pgrp(p);
1107 if (pg == PGRP_NULL) {
1108 error = EIO;
1109 goto out;
1110 }
b0d623f7
A
1111 /* SAFE: All callers drop the lock on return */
1112 tty_unlock(tp);
2d21ac55
A
1113 if (pg->pg_jobc == 0) {
1114 pg_rele(pg);
b0d623f7 1115 tty_lock(tp);
2d21ac55
A
1116 error = EIO;
1117 goto out;
1118 }
1119 pgsignal(pg, SIGTTOU, 1);
1120 pg_rele(pg);
b0d623f7 1121 tty_lock(tp);
2d21ac55
A
1122
1123
1124 /*
1125 * We signalled ourself, so we need to act as if we
1126 * have been "interrupted" from a "sleep" to act on
1127 * the signal. If it's a signal that stops the
1128 * process, that's handled in the signal sending code.
1129 */
1130 error = EINTR;
1131 goto out;
1c79356b
A
1132 }
1133 break;
1134 }
1135
0a7de745
A
1136 switch (cmd) { /* Process the ioctl. */
1137 case FIOASYNC: /* set/clear async i/o */
1138 if (*(int *)data) {
1c79356b 1139 SET(tp->t_state, TS_ASYNC);
0a7de745 1140 } else {
1c79356b 1141 CLR(tp->t_state, TS_ASYNC);
0a7de745 1142 }
1c79356b 1143 break;
0a7de745
A
1144 case FIONBIO: /* set/clear non-blocking i/o */
1145 break; /* XXX: delete. */
1146 case FIONREAD: /* get # bytes to read */
1c79356b 1147 *(int *)data = ttnread(tp);
1c79356b 1148 break;
0a7de745 1149 case TIOCEXCL: /* set exclusive use of tty */
1c79356b 1150 SET(tp->t_state, TS_XCLUDE);
1c79356b 1151 break;
0a7de745 1152 case TIOCFLUSH: { /* flush buffers */
2d21ac55 1153 int flags = *(int *)data;
1c79356b 1154
0a7de745 1155 if (flags == 0) {
1c79356b 1156 flags = FREAD | FWRITE;
0a7de745 1157 } else {
1c79356b 1158 flags &= FREAD | FWRITE;
0a7de745 1159 }
1c79356b
A
1160 ttyflush(tp, flags);
1161 break;
1162 }
1c79356b
A
1163 case TIOCSCONS: {
1164 /* Set current console device to this line */
1c79356b
A
1165 data = (caddr_t) &bogusData;
1166
1167 /* No break - Fall through to BSD code */
1168 }
0a7de745 1169 case TIOCCONS: { /* become virtual console */
1c79356b
A
1170 if (*(int *)data) {
1171 if (constty && constty != tp &&
1172 ISSET(constty->t_state, TS_CONNECTED)) {
2d21ac55
A
1173 error = EBUSY;
1174 goto out;
1c79356b 1175 }
0a7de745 1176 if ((error = suser(kauth_cred_get(), &p->p_acflag))) {
2d21ac55 1177 goto out;
0a7de745 1178 }
1c79356b
A
1179 constty = tp;
1180 } else if (tp == constty) {
1181 constty = NULL;
1182 }
1c79356b 1183 if (constty) {
b0d623f7 1184 (*cdevsw[major(constty->t_dev)].d_ioctl)
0a7de745 1185 (constty->t_dev, KMIOCDISABLCONS, NULL, 0, p);
1c79356b
A
1186 } else {
1187 (*cdevsw[major(tp->t_dev)].d_ioctl)
0a7de745 1188 (tp->t_dev, KMIOCDISABLCONS, NULL, 0, p);
1c79356b 1189 }
1c79356b
A
1190 break;
1191 }
0a7de745 1192 case TIOCDRAIN: /* wait till output drained */
1c79356b 1193 error = ttywait(tp);
0a7de745 1194 if (error) {
2d21ac55 1195 goto out;
0a7de745 1196 }
1c79356b 1197 break;
0a7de745 1198 case TIOCGETA_32: /* get termios struct */
b0d623f7
A
1199#ifdef __LP64__
1200 termios64to32((struct user_termios *)&tp->t_termios, (struct termios32 *)data);
1201#else
1202 bcopy(&tp->t_termios, data, sizeof(struct termios));
1203#endif
1204 break;
0a7de745 1205 case TIOCGETA_64: /* get termios struct */
b0d623f7
A
1206#ifdef __LP64__
1207 bcopy(&tp->t_termios, data, sizeof(struct termios));
1208#else
1209 termios32to64((struct termios32 *)&tp->t_termios, (struct user_termios *)data);
1210#endif
1c79356b 1211 break;
0a7de745 1212 case TIOCGETD: /* get line discipline */
1c79356b
A
1213 *(int *)data = tp->t_line;
1214 break;
0a7de745 1215 case TIOCGWINSZ: /* get window size */
1c79356b
A
1216 *(struct winsize *)data = tp->t_winsize;
1217 break;
0a7de745 1218 case TIOCGPGRP: /* get pgrp of tty */
2d21ac55
A
1219 if (!isctty(p, tp)) {
1220 error = ENOTTY;
1221 goto out;
1222 }
1c79356b
A
1223 *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
1224 break;
1225#ifdef TIOCHPCL
0a7de745 1226 case TIOCHPCL: /* hang up on last close */
1c79356b 1227 SET(tp->t_cflag, HUPCL);
1c79356b
A
1228 break;
1229#endif
0a7de745 1230 case TIOCNXCL: /* reset exclusive use of tty */
1c79356b 1231 CLR(tp->t_state, TS_XCLUDE);
1c79356b 1232 break;
0a7de745 1233 case TIOCOUTQ: /* output queue size */
1c79356b
A
1234 *(int *)data = tp->t_outq.c_cc;
1235 break;
0a7de745 1236 case TIOCSETA_32: /* set termios struct */
91447636 1237 case TIOCSETA_64:
0a7de745 1238 case TIOCSETAW_32: /* drain output, set */
91447636 1239 case TIOCSETAW_64:
0a7de745 1240 case TIOCSETAF_32: /* drn out, fls in, set */
b0d623f7 1241 case TIOCSETAF_64:
0a7de745 1242 { /* drn out, fls in, set */
2d21ac55 1243 struct termios *t = (struct termios *)data;
91447636 1244 struct termios lcl_termios;
1c79356b 1245
b0d623f7 1246#ifdef __LP64__
0a7de745 1247 if (cmd == TIOCSETA_32 || cmd == TIOCSETAW_32 || cmd == TIOCSETAF_32) {
b0d623f7
A
1248 termios32to64((struct termios32 *)data, (struct user_termios *)&lcl_termios);
1249 t = &lcl_termios;
1250 }
1251#else
0a7de745 1252 if (cmd == TIOCSETA_64 || cmd == TIOCSETAW_64 || cmd == TIOCSETAF_64) {
b0d623f7 1253 termios64to32((struct user_termios *)data, (struct termios32 *)&lcl_termios);
91447636
A
1254 t = &lcl_termios;
1255 }
b0d623f7 1256#endif
2d21ac55 1257#if 0
0a7de745 1258 /* XXX bogus test; always false */
2d21ac55
A
1259 if (t->c_ispeed < 0 || t->c_ospeed < 0) {
1260 error = EINVAL;
1261 goto out;
1262 }
0a7de745
A
1263#endif /* 0 - leave in; may end up being a conformance issue */
1264 if (t->c_ispeed == 0) {
2d21ac55 1265 t->c_ispeed = t->c_ospeed;
0a7de745 1266 }
b0d623f7 1267 if (cmd == TIOCSETAW_32 || cmd == TIOCSETAF_32 ||
91447636 1268 cmd == TIOCSETAW_64 || cmd == TIOCSETAF_64) {
1c79356b
A
1269 error = ttywait(tp);
1270 if (error) {
2d21ac55 1271 goto out;
1c79356b 1272 }
0a7de745 1273 if (cmd == TIOCSETAF_32 || cmd == TIOCSETAF_64) {
1c79356b 1274 ttyflush(tp, FREAD);
0a7de745 1275 }
1c79356b
A
1276 }
1277 if (!ISSET(t->c_cflag, CIGNORE)) {
1278 /*
1279 * Set device hardware.
1280 */
1281 if (tp->t_param && (error = (*tp->t_param)(tp, t))) {
2d21ac55 1282 goto out;
1c79356b
A
1283 }
1284 if (ISSET(t->c_cflag, CLOCAL) &&
1285 !ISSET(tp->t_cflag, CLOCAL)) {
1286 /*
1287 * XXX disconnections would be too hard to
1288 * get rid of without this kludge. The only
1289 * way to get rid of controlling terminals
1290 * is to exit from the session leader.
1291 */
1292 CLR(tp->t_state, TS_ZOMBIE);
1293
1294 wakeup(TSA_CARR_ON(tp));
1295 ttwakeup(tp);
1296 ttwwakeup(tp);
1297 }
1298 if ((ISSET(tp->t_state, TS_CARR_ON) ||
0a7de745
A
1299 ISSET(t->c_cflag, CLOCAL)) &&
1300 !ISSET(tp->t_state, TS_ZOMBIE)) {
1c79356b 1301 SET(tp->t_state, TS_CONNECTED);
0a7de745 1302 } else {
1c79356b 1303 CLR(tp->t_state, TS_CONNECTED);
0a7de745 1304 }
1c79356b
A
1305 tp->t_cflag = t->c_cflag;
1306 tp->t_ispeed = t->c_ispeed;
1307 tp->t_ospeed = t->c_ospeed;
1308 ttsetwater(tp);
1309 }
1310 if (ISSET(t->c_lflag, ICANON) != ISSET(tp->t_lflag, ICANON) &&
b0d623f7 1311 cmd != TIOCSETAF_32 && cmd != TIOCSETAF_64) {
0a7de745 1312 if (ISSET(t->c_lflag, ICANON)) {
1c79356b 1313 SET(tp->t_lflag, PENDIN);
0a7de745 1314 } else {
1c79356b
A
1315 /*
1316 * XXX we really shouldn't allow toggling
1317 * ICANON while we're in a non-termios line
1318 * discipline. Now we have to worry about
1319 * panicing for a null queue.
1320 */
1c79356b 1321 if (tp->t_rawq.c_cs && tp->t_canq.c_cs) {
0a7de745 1322 struct clist tq;
1c79356b 1323
0a7de745
A
1324 catq(&tp->t_rawq, &tp->t_canq);
1325 tq = tp->t_rawq;
1326 tp->t_rawq = tp->t_canq;
1327 tp->t_canq = tq;
1c79356b 1328 }
1c79356b
A
1329 CLR(tp->t_lflag, PENDIN);
1330 }
1331 ttwakeup(tp);
1332 }
1333 tp->t_iflag = t->c_iflag;
1334 tp->t_oflag = t->c_oflag;
1335 /*
1336 * Make the EXTPROC bit read only.
1337 */
0a7de745 1338 if (ISSET(tp->t_lflag, EXTPROC)) {
1c79356b 1339 SET(t->c_lflag, EXTPROC);
0a7de745 1340 } else {
1c79356b 1341 CLR(t->c_lflag, EXTPROC);
0a7de745 1342 }
1c79356b
A
1343 tp->t_lflag = t->c_lflag | ISSET(tp->t_lflag, PENDIN);
1344 if (t->c_cc[VMIN] != tp->t_cc[VMIN] ||
0a7de745 1345 t->c_cc[VTIME] != tp->t_cc[VTIME]) {
1c79356b 1346 ttwakeup(tp);
0a7de745 1347 }
1c79356b 1348 bcopy(t->c_cc, tp->t_cc, sizeof(t->c_cc));
1c79356b
A
1349 break;
1350 }
0a7de745 1351 case TIOCSETD: { /* set line discipline */
2d21ac55 1352 int t = *(int *)data;
1c79356b 1353 dev_t device = tp->t_dev;
1c79356b 1354
2d21ac55
A
1355 if (t >= nlinesw || t < 0) {
1356 error = ENXIO;
1357 goto out;
1358 }
b0d623f7
A
1359 /*
1360 * If the new line discipline is not equal to the old one,
1361 * close the old one and open the new one.
1362 */
1c79356b 1363 if (t != tp->t_line) {
1c79356b
A
1364 (*linesw[tp->t_line].l_close)(tp, flag);
1365 error = (*linesw[t].l_open)(device, tp);
1366 if (error) {
b0d623f7 1367 /* This is racy; it's possible to lose both */
1c79356b 1368 (void)(*linesw[tp->t_line].l_open)(device, tp);
2d21ac55 1369 goto out;
1c79356b
A
1370 }
1371 tp->t_line = t;
1c79356b
A
1372 }
1373 break;
1374 }
0a7de745 1375 case TIOCSTART: /* start output, like ^Q */
1c79356b
A
1376 if (ISSET(tp->t_state, TS_TTSTOP) ||
1377 ISSET(tp->t_lflag, FLUSHO)) {
1378 CLR(tp->t_lflag, FLUSHO);
1379 CLR(tp->t_state, TS_TTSTOP);
1380 ttstart(tp);
1381 }
1c79356b 1382 break;
0a7de745 1383 case TIOCSTI: /* simulate terminal input */
2d21ac55
A
1384 if (suser(kauth_cred_get(), NULL) && (flag & FREAD) == 0) {
1385 error = EPERM;
1386 goto out;
1387 }
1388 if (suser(kauth_cred_get(), NULL) && !isctty(p, tp)) {
1389 error = EACCES;
1390 goto out;
1391 }
1c79356b 1392 (*linesw[tp->t_line].l_rint)(*(u_char *)data, tp);
1c79356b 1393 break;
0a7de745 1394 case TIOCSTOP: /* stop output, like ^S */
1c79356b
A
1395 if (!ISSET(tp->t_state, TS_TTSTOP)) {
1396 SET(tp->t_state, TS_TTSTOP);
0a7de745 1397 ttystop(tp, 0);
1c79356b 1398 }
2d21ac55
A
1399 break;
1400 case TIOCIXON:
1401 ttyunblock(tp);
1402 break;
1403 case TIOCIXOFF:
1404 ttyblock(tp);
1c79356b 1405 break;
0a7de745 1406 case TIOCSCTTY: /* become controlling tty */
1c79356b 1407 /* Session ctty vnode pointer set in vnode layer. */
2d21ac55 1408 sessp = proc_session(p);
3e170ce0
A
1409 if (sessp == SESSION_NULL) {
1410 error = EPERM;
1411 goto out;
1412 }
1413
1414 /*
1415 * This can only be done by a session leader.
1416 */
1417 if (!SESS_LEADER(p, sessp)) {
b0d623f7
A
1418 /* SAFE: All callers drop the lock on return */
1419 tty_unlock(tp);
3e170ce0
A
1420 session_rele(sessp);
1421 tty_lock(tp);
1422 error = EPERM;
1423 goto out;
1424 }
1425 /*
1426 * If this terminal is already the controlling terminal for the
1427 * session, nothing to do here.
1428 */
1429 if (tp->t_session == sessp) {
1430 /* SAFE: All callers drop the lock on return */
1431 tty_unlock(tp);
1432 session_rele(sessp);
1433 tty_lock(tp);
1434 error = 0;
1435 goto out;
1436 }
1437 pg = proc_pgrp(p);
1438 /*
1439 * Deny if the terminal is already attached to another session or
1440 * the session already has a terminal vnode.
1441 */
1442 session_lock(sessp);
1443 if (sessp->s_ttyvp || tp->t_session) {
1444 session_unlock(sessp);
1445 /* SAFE: All callers drop the lock on return */
1446 tty_unlock(tp);
1447 if (pg != PGRP_NULL) {
2d21ac55 1448 pg_rele(pg);
3e170ce0
A
1449 }
1450 session_rele(sessp);
b0d623f7 1451 tty_lock(tp);
2d21ac55
A
1452 error = EPERM;
1453 goto out;
1454 }
3e170ce0
A
1455 sessp->s_ttypgrpid = pg->pg_id;
1456 oldtp = sessp->s_ttyp;
1457 ttyhold(tp);
1458 sessp->s_ttyp = tp;
1459 session_unlock(sessp);
2d21ac55
A
1460 proc_list_lock();
1461 oldsessp = tp->t_session;
1462 oldpg = tp->t_pgrp;
0a7de745 1463 if (oldsessp != SESSION_NULL) {
2d21ac55 1464 oldsessp->s_ttypgrpid = NO_PID;
0a7de745 1465 }
2d21ac55
A
1466 /* do not drop refs on sessp and pg as tp holds them */
1467 tp->t_session = sessp;
2d21ac55
A
1468 tp->t_pgrp = pg;
1469 proc_list_unlock();
b0d623f7
A
1470 OSBitOrAtomic(P_CONTROLT, &p->p_flag);
1471 /* SAFE: All callers drop the lock on return */
1472 tty_unlock(tp);
2d21ac55 1473 /* drop the reference on prev session and pgrp */
0a7de745 1474 if (oldsessp != SESSION_NULL) {
2d21ac55 1475 session_rele(oldsessp);
0a7de745
A
1476 }
1477 if (oldpg != PGRP_NULL) {
2d21ac55 1478 pg_rele(oldpg);
0a7de745
A
1479 }
1480 if (NULL != oldtp) {
316670eb 1481 ttyfree(oldtp);
0a7de745 1482 }
b0d623f7 1483 tty_lock(tp);
1c79356b 1484 break;
2d21ac55 1485
0a7de745 1486 case TIOCSPGRP: { /* set pgrp of tty */
2d21ac55 1487 struct pgrp *pgrp = PGRP_NULL;
1c79356b 1488
2d21ac55
A
1489 sessp = proc_session(p);
1490 if (!isctty_sp(p, tp, sessp)) {
0a7de745 1491 if (sessp != SESSION_NULL) {
2d21ac55 1492 session_rele(sessp);
0a7de745 1493 }
2d21ac55
A
1494 error = ENOTTY;
1495 goto out;
0a7de745
A
1496 } else if ((pgrp = pgfind(*(int *)data)) == PGRP_NULL) {
1497 if (sessp != SESSION_NULL) {
2d21ac55 1498 session_rele(sessp);
0a7de745 1499 }
2d21ac55
A
1500 error = EINVAL;
1501 goto out;
0a7de745 1502 } else if (pgrp->pg_session != sessp) {
b0d623f7
A
1503 /* SAFE: All callers drop the lock on return */
1504 tty_unlock(tp);
0a7de745 1505 if (sessp != SESSION_NULL) {
2d21ac55 1506 session_rele(sessp);
0a7de745 1507 }
2d21ac55 1508 pg_rele(pgrp);
b0d623f7 1509 tty_lock(tp);
2d21ac55
A
1510 error = EPERM;
1511 goto out;
1512 }
fe8ab488
A
1513 /*
1514 * The session leader is going away and is possibly going to revoke
1515 * the terminal, we can't change the process group when that is the
1516 * case.
1517 */
1518 if (ISSET(tp->t_state, TS_PGRPHUP)) {
0a7de745 1519 if (sessp != SESSION_NULL) {
d9a64523 1520 session_rele(sessp);
0a7de745 1521 }
d9a64523 1522 pg_rele(pgrp);
fe8ab488
A
1523 error = EPERM;
1524 goto out;
1525 }
2d21ac55
A
1526 proc_list_lock();
1527 oldpg = tp->t_pgrp;
1c79356b 1528 tp->t_pgrp = pgrp;
2d21ac55
A
1529 sessp->s_ttypgrpid = pgrp->pg_id;
1530 proc_list_unlock();
d9a64523
A
1531
1532 /*
1533 * Wakeup readers to recheck if they are still the foreground
1534 * process group.
1535 *
1536 * ttwakeup() isn't called because the readers aren't getting
1537 * woken up becuse there is something to read but to force
1538 * the re-evaluation of their foreground process group status.
1539 *
1540 * Ordinarily leaving these readers waiting wouldn't be an issue
1541 * as launchd would send them a termination signal eventually
1542 * (if nobody else does). But if this terminal happens to be
1543 * /dev/console, launchd itself could get blocked forever behind
1544 * a revoke of /dev/console and leave the system deadlocked.
1545 */
1546 wakeup(TSA_HUP_OR_INPUT(tp));
1547
b0d623f7
A
1548 /* SAFE: All callers drop the lock on return */
1549 tty_unlock(tp);
0a7de745 1550 if (oldpg != PGRP_NULL) {
2d21ac55 1551 pg_rele(oldpg);
0a7de745
A
1552 }
1553 if (sessp != SESSION_NULL) {
2d21ac55 1554 session_rele(sessp);
0a7de745 1555 }
b0d623f7 1556 tty_lock(tp);
1c79356b
A
1557 break;
1558 }
0a7de745 1559 case TIOCSTAT: /* simulate control-T */
b0d623f7 1560 ttyinfo_locked(tp);
1c79356b 1561 break;
0a7de745 1562 case TIOCSWINSZ: /* set window size */
1c79356b 1563 if (bcmp((caddr_t)&tp->t_winsize, data,
0a7de745 1564 sizeof(struct winsize))) {
1c79356b 1565 tp->t_winsize = *(struct winsize *)data;
b0d623f7
A
1566 /* SAFE: All callers drop the lock on return */
1567 tty_unlock(tp);
2d21ac55 1568 tty_pgsignal(tp, SIGWINCH, 1);
b0d623f7 1569 tty_lock(tp);
1c79356b
A
1570 }
1571 break;
1572 case TIOCSDRAINWAIT:
91447636 1573 error = suser(kauth_cred_get(), &p->p_acflag);
2d21ac55
A
1574 if (error) {
1575 goto out;
1576 }
1c79356b
A
1577 tp->t_timeout = *(int *)data * hz;
1578 wakeup(TSA_OCOMPLETE(tp));
1579 wakeup(TSA_OLOWAT(tp));
1580 break;
1581 case TIOCGDRAINWAIT:
1582 *(int *)data = tp->t_timeout / hz;
0a7de745 1583 break;
cb323159
A
1584 case TIOCREVOKE:
1585 if (ISSET(tp->t_state, TS_PGRPHUP)) {
1586 tp->t_gen++;
1587 wakeup(TSA_HUP_OR_INPUT(tp));
1588 }
1589 break;
1c79356b 1590 default:
2d21ac55 1591 error = ttcompat(tp, cmd, data, flag, p);
2d21ac55 1592 goto out;
1c79356b
A
1593 }
1594
2d21ac55
A
1595 error = 0;
1596out:
0a7de745 1597 return error;
1c79356b
A
1598}
1599
b0d623f7
A
1600
1601/*
1602 * Locks: Assumes tp is locked on entry, remains locked on exit
1603 */
1c79356b 1604int
2d21ac55 1605ttyselect(struct tty *tp, int rw, void *wql, proc_t p)
1c79356b 1606{
6d2010ae 1607 int retval = 0;
5ba3f43e
A
1608 /*
1609 * Attaching knotes to TTYs needs to call selrecord in order to hook
1610 * up the waitq to the selinfo, regardless of data being ready. See
1611 * filt_ttyattach.
1612 */
1613 bool needs_selrecord = rw & FMARK;
1614 rw &= ~FMARK;
6d2010ae 1615
5ba3f43e
A
1616 if (tp == NULL) {
1617 return ENXIO;
1618 }
1c79356b 1619
5ba3f43e
A
1620 TTY_LOCK_OWNED(tp);
1621
1622 if (tp->t_state & TS_ZOMBIE) {
1623 retval = 1;
1624 goto out;
1625 }
b0d623f7 1626
1c79356b
A
1627 switch (rw) {
1628 case FREAD:
6d2010ae
A
1629 retval = ttnread(tp);
1630 if (retval > 0) {
1631 break;
1632 }
1633
0b4e3aa0 1634 selrecord(p, &tp->t_rsel, wql);
1c79356b
A
1635 break;
1636 case FWRITE:
6d2010ae 1637 if ((tp->t_outq.c_cc <= tp->t_lowat) &&
5ba3f43e 1638 (tp->t_state & TS_CONNECTED)) {
6d2010ae
A
1639 retval = tp->t_hiwat - tp->t_outq.c_cc;
1640 break;
1641 }
1642
0b4e3aa0 1643 selrecord(p, &tp->t_wsel, wql);
1c79356b
A
1644 break;
1645 }
5ba3f43e
A
1646
1647out:
1648 if (retval > 0 && needs_selrecord) {
1649 switch (rw) {
1650 case FREAD:
1651 selrecord(p, &tp->t_rsel, wql);
1652 break;
1653 case FWRITE:
1654 selrecord(p, &tp->t_wsel, wql);
1655 break;
1656 }
1657 }
1658
6d2010ae 1659 return retval;
1c79356b
A
1660}
1661
b0d623f7 1662
1c79356b
A
1663/*
1664 * This is a wrapper for compatibility with the select vector used by
1665 * cdevsw. It relies on a proper xxxdevtotty routine.
b0d623f7
A
1666 *
1667 * Locks: Assumes tty_lock() is not held prior to calling.
1c79356b
A
1668 */
1669int
2d21ac55 1670ttselect(dev_t dev, int rw, void *wql, proc_t p)
1c79356b 1671{
0a7de745 1672 int rv;
b0d623f7
A
1673 struct tty *tp = cdevsw[major(dev)].d_ttys[minor(dev)];
1674
1675 tty_lock(tp);
1676 rv = ttyselect(tp, rw, wql, p);
1677 tty_unlock(tp);
1678
0a7de745 1679 return rv;
1c79356b
A
1680}
1681
b0d623f7 1682
1c79356b 1683/*
b0d623f7 1684 * Locks: Assumes tp is locked on entry, remains locked on exit
1c79356b 1685 */
fe8ab488 1686__private_extern__ int
2d21ac55 1687ttnread(struct tty *tp)
1c79356b
A
1688{
1689 int nread;
1690
0a7de745 1691 TTY_LOCK_OWNED(tp); /* debug assert */
b0d623f7 1692
0a7de745 1693 if (ISSET(tp->t_lflag, PENDIN)) {
1c79356b 1694 ttypend(tp);
0a7de745 1695 }
1c79356b
A
1696 nread = tp->t_canq.c_cc;
1697 if (!ISSET(tp->t_lflag, ICANON)) {
1698 nread += tp->t_rawq.c_cc;
0a7de745 1699 if (nread < tp->t_cc[VMIN] && tp->t_cc[VTIME] == 0) {
1c79356b 1700 nread = 0;
0a7de745 1701 }
1c79356b 1702 }
0a7de745 1703 return nread;
1c79356b
A
1704}
1705
b0d623f7 1706
1c79356b 1707/*
b0d623f7
A
1708 * ttywait
1709 *
1c79356b 1710 * Wait for output to drain.
b0d623f7
A
1711 *
1712 * Parameters: tp Tty on which to wait for output to drain
1713 *
1714 * Returns: 0 Success
1715 * EIO t_timeout too small/expired
1716 * ttysleep:ERESTART Upper layer must redrive the call;
1717 * this is usually done by the Libc
1718 * stub in user space
1719 * ttysleep:EINTR Interrupted (usually a signal)
1720 *
1721 * Notes: Called from proc_exit() and vproc_exit().
1722 *
1723 * Locks: Assumes tp is locked on entry, remains locked on exit
1c79356b
A
1724 */
1725int
2d21ac55 1726ttywait(struct tty *tp)
1c79356b 1727{
2d21ac55 1728 int error;
1c79356b 1729
0a7de745 1730 TTY_LOCK_OWNED(tp); /* debug assert */
b0d623f7 1731
1c79356b 1732 error = 0;
1c79356b 1733 while ((tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)) &&
0a7de745 1734 ISSET(tp->t_state, TS_CONNECTED) && tp->t_oproc) {
1c79356b
A
1735 (*tp->t_oproc)(tp);
1736 if ((tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)) &&
1737 ISSET(tp->t_state, TS_CONNECTED)) {
1738 SET(tp->t_state, TS_SO_OCOMPLETE);
1739 error = ttysleep(tp, TSA_OCOMPLETE(tp),
0a7de745
A
1740 TTOPRI | PCATCH, "ttywai",
1741 tp->t_timeout);
1c79356b 1742 if (error) {
0a7de745 1743 if (error == EWOULDBLOCK) {
1c79356b 1744 error = EIO;
0a7de745 1745 }
1c79356b
A
1746 break;
1747 }
0a7de745 1748 } else {
1c79356b 1749 break;
0a7de745 1750 }
1c79356b 1751 }
0a7de745 1752 if (!error && (tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY))) {
1c79356b 1753 error = EIO;
0a7de745
A
1754 }
1755 return error;
1c79356b
A
1756}
1757
b0d623f7
A
1758/*
1759 * Stop the underlying device driver.
1760 *
1761 * Locks: Assumes tty_lock() is held prior to calling.
1762 */
1c79356b 1763static void
2d21ac55 1764ttystop(struct tty *tp, int rw)
1c79356b 1765{
0a7de745 1766 TTY_LOCK_OWNED(tp); /* debug assert */
b0d623f7 1767
1c79356b 1768 (*cdevsw[major(tp->t_dev)].d_stop)(tp, rw);
1c79356b
A
1769}
1770
1771/*
1772 * Flush if successfully wait.
b0d623f7
A
1773 *
1774 * Locks: Assumes tty_lock() is held prior to calling.
1c79356b
A
1775 */
1776static int
2d21ac55 1777ttywflush(struct tty *tp)
1c79356b
A
1778{
1779 int error;
1780
0a7de745 1781 TTY_LOCK_OWNED(tp); /* debug assert */
b0d623f7 1782
0a7de745 1783 if ((error = ttywait(tp)) == 0) {
1c79356b 1784 ttyflush(tp, FREAD);
0a7de745
A
1785 }
1786 return error;
1c79356b
A
1787}
1788
1789/*
1790 * Flush tty read and/or write queues, notifying anyone waiting.
b0d623f7
A
1791 *
1792 * Locks: Assumes tty_lock() is held prior to calling.
1c79356b
A
1793 */
1794void
2d21ac55 1795ttyflush(struct tty *tp, int rw)
1c79356b 1796{
0a7de745 1797 TTY_LOCK_OWNED(tp); /* debug assert */
b0d623f7 1798
1c79356b
A
1799#if 0
1800again:
1801#endif
1802 if (rw & FWRITE) {
1803 FLUSHQ(&tp->t_outq);
1804 CLR(tp->t_state, TS_TTSTOP);
1805 }
0a7de745
A
1806 ttystop(tp, rw);
1807 if (rw & FREAD) {
1c79356b
A
1808 FLUSHQ(&tp->t_canq);
1809 FLUSHQ(&tp->t_rawq);
1810 CLR(tp->t_lflag, PENDIN);
1811 tp->t_rocount = 0;
1812 tp->t_rocol = 0;
1813 CLR(tp->t_state, TS_LOCAL);
1814 ttwakeup(tp);
1815 if (ISSET(tp->t_state, TS_TBLOCK)) {
0a7de745 1816 if (rw & FWRITE) {
1c79356b 1817 FLUSHQ(&tp->t_outq);
0a7de745 1818 }
1c79356b
A
1819 ttyunblock(tp);
1820
1821 /*
1822 * Don't let leave any state that might clobber the
1823 * next line discipline (although we should do more
1824 * to send the START char). Not clearing the state
1825 * may have caused the "putc to a clist with no
1826 * reserved cblocks" panic/printf.
1827 */
1828 CLR(tp->t_state, TS_TBLOCK);
1829
1830#if 0 /* forget it, sleeping isn't always safe and we don't know when it is */
1831 if (ISSET(tp->t_iflag, IXOFF)) {
1832 /*
1833 * XXX wait a bit in the hope that the stop
1834 * character (if any) will go out. Waiting
1835 * isn't good since it allows races. This
1836 * will be fixed when the stop character is
1837 * put in a special queue. Don't bother with
1838 * the checks in ttywait() since the timeout
1839 * will save us.
1840 */
1841 SET(tp->t_state, TS_SO_OCOMPLETE);
1842 ttysleep(tp, TSA_OCOMPLETE(tp), TTOPRI,
0a7de745 1843 "ttyfls", hz / 10);
1c79356b
A
1844 /*
1845 * Don't try sending the stop character again.
1846 */
1847 CLR(tp->t_state, TS_TBLOCK);
1848 goto again;
1849 }
1850#endif
1851 }
1852 }
1853 if (rw & FWRITE) {
1854 FLUSHQ(&tp->t_outq);
1855 ttwwakeup(tp);
1856 }
1c79356b
A
1857}
1858
1859/*
1860 * Copy in the default termios characters.
b0d623f7
A
1861 *
1862 * Locks: Assumes tty_lock() is held prior to calling.
1863 *
1864 * Notes: No assertion; tp is not in scope.
1c79356b
A
1865 */
1866void
2d21ac55 1867termioschars(struct termios *t)
1c79356b 1868{
1c79356b
A
1869 bcopy(ttydefchars, t->c_cc, sizeof t->c_cc);
1870}
1871
1c79356b
A
1872
1873/*
1874 * Handle input high water. Send stop character for the IXOFF case. Turn
1875 * on our input flow control bit and propagate the changes to the driver.
1876 * XXX the stop character should be put in a special high priority queue.
b0d623f7
A
1877 *
1878 * Locks: Assumes tty_lock() is held for the call.
1c79356b
A
1879 */
1880void
2d21ac55 1881ttyblock(struct tty *tp)
1c79356b 1882{
0a7de745 1883 TTY_LOCK_OWNED(tp); /* debug assert */
b0d623f7 1884
1c79356b
A
1885 SET(tp->t_state, TS_TBLOCK);
1886 if (ISSET(tp->t_iflag, IXOFF) && tp->t_cc[VSTOP] != _POSIX_VDISABLE &&
0a7de745
A
1887 putc(tp->t_cc[VSTOP], &tp->t_outq) != 0) {
1888 CLR(tp->t_state, TS_TBLOCK); /* try again later */
1889 }
1c79356b
A
1890 ttstart(tp);
1891}
1892
b0d623f7 1893
1c79356b
A
1894/*
1895 * Handle input low water. Send start character for the IXOFF case. Turn
1896 * off our input flow control bit and propagate the changes to the driver.
1897 * XXX the start character should be put in a special high priority queue.
b0d623f7
A
1898 *
1899 * Locks: Assumes tty_lock() is held for the call.
1c79356b
A
1900 */
1901static void
2d21ac55 1902ttyunblock(struct tty *tp)
1c79356b 1903{
0a7de745 1904 TTY_LOCK_OWNED(tp); /* debug assert */
b0d623f7 1905
1c79356b
A
1906 CLR(tp->t_state, TS_TBLOCK);
1907 if (ISSET(tp->t_iflag, IXOFF) && tp->t_cc[VSTART] != _POSIX_VDISABLE &&
0a7de745
A
1908 putc(tp->t_cc[VSTART], &tp->t_outq) != 0) {
1909 SET(tp->t_state, TS_TBLOCK); /* try again later */
1910 }
1c79356b
A
1911 ttstart(tp);
1912}
1913
b0d623f7 1914
1c79356b 1915/*
b0d623f7
A
1916 * ttstart
1917 *
1918 * Start tty output
1919 *
1920 * Parameters: tp tty on which to start output
1921 *
1922 * Returns: 0 Success
1923 *
1924 * Locks: Assumes tty_lock() is held for the call.
1925 *
1926 * Notes: This function might as well be void; it always returns success
1927 *
1928 * Called from ttioctl_locked(), LDISC routines, and
1929 * ttycheckoutq(), ttyblock(), ttyunblock(), and tputchar()
1c79356b 1930 */
1c79356b 1931int
2d21ac55 1932ttstart(struct tty *tp)
1c79356b 1933{
0a7de745 1934 TTY_LOCK_OWNED(tp); /* debug assert */
1c79356b 1935
0a7de745 1936 if (tp->t_oproc != NULL) { /* XXX: Kludge for pty. */
1c79356b 1937 (*tp->t_oproc)(tp);
0a7de745 1938 }
b0d623f7 1939
0a7de745 1940 return 0;
1c79356b
A
1941}
1942
b0d623f7 1943
1c79356b 1944/*
b0d623f7
A
1945 * ttylclose (LDISC)
1946 *
1c79356b 1947 * "close" a line discipline
b0d623f7
A
1948 *
1949 * Locks: Assumes tty_lock() is held prior to calling.
1c79356b
A
1950 */
1951int
2d21ac55 1952ttylclose(struct tty *tp, int flag)
1c79356b 1953{
0a7de745 1954 TTY_LOCK_OWNED(tp); /* debug assert */
0b4e3aa0 1955
0a7de745 1956 if ((flag & FNONBLOCK) || ttywflush(tp)) {
1c79356b 1957 ttyflush(tp, FREAD | FWRITE);
0a7de745 1958 }
b0d623f7 1959
0a7de745 1960 return 0;
1c79356b
A
1961}
1962
b0d623f7 1963
1c79356b 1964/*
b0d623f7
A
1965 * ttymodem (LDISC)
1966 *
1c79356b
A
1967 * Handle modem control transition on a tty.
1968 * Flag indicates new state of carrier.
1969 * Returns 0 if the line should be turned off, otherwise 1.
b0d623f7
A
1970 *
1971 * Locks: Assumes tty_lock() is held prior to calling.
1c79356b
A
1972 */
1973int
2d21ac55 1974ttymodem(struct tty *tp, int flag)
1c79356b 1975{
0a7de745 1976 int rval = 1; /* default return value */
0b4e3aa0 1977
0a7de745 1978 TTY_LOCK_OWNED(tp); /* debug assert */
1c79356b
A
1979
1980 if (ISSET(tp->t_state, TS_CARR_ON) && ISSET(tp->t_cflag, MDMBUF)) {
1981 /*
1982 * MDMBUF: do flow control according to carrier flag
1983 * XXX TS_CAR_OFLOW doesn't do anything yet. TS_TTSTOP
1984 * works if IXON and IXANY are clear.
1985 */
1986 if (flag) {
1987 CLR(tp->t_state, TS_CAR_OFLOW);
1988 CLR(tp->t_state, TS_TTSTOP);
1989 ttstart(tp);
1990 } else if (!ISSET(tp->t_state, TS_CAR_OFLOW)) {
1991 SET(tp->t_state, TS_CAR_OFLOW);
1992 SET(tp->t_state, TS_TTSTOP);
0a7de745 1993 ttystop(tp, 0);
1c79356b
A
1994 }
1995 } else if (flag == 0) {
1996 /*
1997 * Lost carrier.
1998 */
1999 CLR(tp->t_state, TS_CARR_ON);
2000 if (ISSET(tp->t_state, TS_ISOPEN) &&
2001 !ISSET(tp->t_cflag, CLOCAL)) {
2002 SET(tp->t_state, TS_ZOMBIE);
2003 CLR(tp->t_state, TS_CONNECTED);
0a7de745 2004 if (tp->t_session && tp->t_session->s_leader) {
1c79356b 2005 psignal(tp->t_session->s_leader, SIGHUP);
0a7de745 2006 }
1c79356b 2007 ttyflush(tp, FREAD | FWRITE);
b0d623f7
A
2008 rval = 0;
2009 goto out;
1c79356b
A
2010 }
2011 } else {
2012 /*
2013 * Carrier now on.
2014 */
2015 SET(tp->t_state, TS_CARR_ON);
0a7de745 2016 if (!ISSET(tp->t_state, TS_ZOMBIE)) {
1c79356b 2017 SET(tp->t_state, TS_CONNECTED);
0a7de745 2018 }
1c79356b
A
2019 wakeup(TSA_CARR_ON(tp));
2020 ttwakeup(tp);
2021 ttwwakeup(tp);
2022 }
b0d623f7
A
2023
2024out:
0a7de745 2025 return rval;
1c79356b
A
2026}
2027
b0d623f7 2028
1c79356b
A
2029/*
2030 * Reinput pending characters after state switch
2031 * call at spltty().
b0d623f7
A
2032 *
2033 * Locks: Assumes tty_lock() is held for the call.
1c79356b
A
2034 */
2035static void
2d21ac55 2036ttypend(struct tty *tp)
1c79356b
A
2037{
2038 struct clist tq;
2d21ac55 2039 int c;
1c79356b 2040
0a7de745 2041 TTY_LOCK_OWNED(tp); /* debug assert */
b0d623f7 2042
1c79356b
A
2043 CLR(tp->t_lflag, PENDIN);
2044 SET(tp->t_state, TS_TYPEN);
1c79356b
A
2045 tq = tp->t_rawq;
2046 tp->t_rawq.c_cc = 0;
2d21ac55 2047 tp->t_rawq.c_cf = tp->t_rawq.c_cl = NULL;
0a7de745 2048 while ((c = getc(&tq)) >= 0) {
1c79356b 2049 ttyinput(c, tp);
0a7de745 2050 }
1c79356b
A
2051 CLR(tp->t_state, TS_TYPEN);
2052}
2053
b0d623f7 2054
1c79356b 2055/*
b0d623f7
A
2056 * ttread (LDISC)
2057 *
1c79356b 2058 * Process a read call on a tty device.
b0d623f7
A
2059 *
2060 * Locks: Assumes tty_lock() is held prior to calling.
1c79356b
A
2061 */
2062int
2d21ac55 2063ttread(struct tty *tp, struct uio *uio, int flag)
1c79356b 2064{
2d21ac55
A
2065 struct clist *qp;
2066 int c;
2067 tcflag_t lflag;
2068 cc_t *cc = tp->t_cc;
2069 proc_t p = current_proc();
2070 int first, error = 0;
1c79356b 2071 int has_etime = 0, last_cc = 0;
0a7de745 2072 long slp = 0; /* XXX this should be renamed `timo'. */
9bccf70c 2073 struct uthread *ut;
2d21ac55 2074 struct pgrp * pg;
1c79356b 2075
0a7de745 2076 TTY_LOCK_OWNED(tp); /* debug assert */
9bccf70c 2077
91447636 2078 ut = (struct uthread *)get_bsdthread_info(current_thread());
9bccf70c 2079
1c79356b 2080loop:
1c79356b
A
2081 lflag = tp->t_lflag;
2082 /*
2083 * take pending input first
2084 */
2085 if (ISSET(lflag, PENDIN)) {
2086 ttypend(tp);
0a7de745 2087 lflag = tp->t_lflag; /* XXX ttypend() clobbers it */
1c79356b
A
2088 }
2089
2090 /*
2d21ac55 2091 * Signal the process if it's in the background.
1c79356b
A
2092 */
2093 if (isbackground(p, tp)) {
1c79356b 2094 if ((p->p_sigignore & sigmask(SIGTTIN)) ||
0a7de745 2095 (ut->uu_sigmask & sigmask(SIGTTIN)) ||
2d21ac55 2096 p->p_lflag & P_LPPWAIT) {
0a7de745 2097 error = EIO;
b0d623f7 2098 goto err;
0b4e3aa0 2099 }
2d21ac55
A
2100 pg = proc_pgrp(p);
2101 if (pg == PGRP_NULL) {
0a7de745 2102 error = EIO;
b0d623f7 2103 goto err;
0b4e3aa0 2104 }
2d21ac55 2105 if (pg->pg_jobc == 0) {
b0d623f7
A
2106 /* SAFE: All callers drop the lock on return */
2107 tty_unlock(tp);
2d21ac55 2108 pg_rele(pg);
b0d623f7 2109 tty_lock(tp);
0a7de745 2110 error = EIO;
b0d623f7 2111 goto err;
2d21ac55 2112 }
b0d623f7
A
2113 /* SAFE: All callers drop the lock on return */
2114 tty_unlock(tp);
2d21ac55
A
2115 pgsignal(pg, SIGTTIN, 1);
2116 pg_rele(pg);
b0d623f7 2117 tty_lock(tp);
2d21ac55
A
2118
2119 /*
2120 * We signalled ourself, so we need to act as if we
2121 * have been "interrupted" from a "sleep" to act on
2122 * the signal. If it's a signal that stops the
2123 * process, that's handled in the signal sending code.
2124 */
b0d623f7
A
2125 error = EINTR;
2126 goto err;
1c79356b
A
2127 }
2128
2129 if (ISSET(tp->t_state, TS_ZOMBIE)) {
b0d623f7
A
2130 /* EOF - returning 0 */
2131 goto err;
1c79356b
A
2132 }
2133
2134 /*
2135 * If canonical, use the canonical queue,
2136 * else use the raw queue.
2137 *
2138 * (should get rid of clists...)
2139 */
2140 qp = ISSET(lflag, ICANON) ? &tp->t_canq : &tp->t_rawq;
2141
2142 if (flag & IO_NDELAY) {
0a7de745 2143 if (qp->c_cc > 0) {
1c79356b 2144 goto read;
0a7de745 2145 }
b0d623f7 2146 if (ISSET(lflag, ICANON) || cc[VMIN] != 0) {
0a7de745 2147 error = EWOULDBLOCK;
1c79356b 2148 }
b0d623f7
A
2149 /* else polling - returning 0 */
2150 goto err;
1c79356b
A
2151 }
2152 if (!ISSET(lflag, ICANON)) {
2153 int m = cc[VMIN];
2154 long t = cc[VTIME];
2d21ac55 2155 struct timeval timecopy;
cb323159 2156 struct timeval etime = {.tv_sec = 0, .tv_usec = 0}; /* protected by !has_etime */
1c79356b
A
2157
2158 /*
2159 * Check each of the four combinations.
2160 * (m > 0 && t == 0) is the normal read case.
2161 * It should be fairly efficient, so we check that and its
2162 * companion case (m == 0 && t == 0) first.
2163 * For the other two cases, we compute the target sleep time
2164 * into slp.
2165 */
2166 if (t == 0) {
0a7de745 2167 if (qp->c_cc < m) {
1c79356b 2168 goto sleep;
0a7de745
A
2169 }
2170 if (qp->c_cc > 0) {
1c79356b 2171 goto read;
0a7de745 2172 }
1c79356b
A
2173
2174 /* m, t and qp->c_cc are all 0. 0 is enough input. */
b0d623f7 2175 goto err;
1c79356b 2176 }
0a7de745 2177 t *= 100000; /* time in us */
1c79356b 2178#define diff(t1, t2) (((t1).tv_sec - (t2).tv_sec) * 1000000 + \
0a7de745 2179 ((t1).tv_usec - (t2).tv_usec))
1c79356b 2180 if (m > 0) {
0a7de745 2181 if (qp->c_cc <= 0) {
1c79356b 2182 goto sleep;
0a7de745
A
2183 }
2184 if (qp->c_cc >= m) {
1c79356b 2185 goto read;
0a7de745 2186 }
91447636 2187 microuptime(&timecopy);
1c79356b
A
2188 if (!has_etime) {
2189 /* first character, start timer */
2190 has_etime = 1;
2191
2192 etime.tv_sec = t / 1000000;
2193 etime.tv_usec = (t - (etime.tv_sec * 1000000));
2194 timeradd(&etime, &timecopy, &etime);
0a7de745 2195
1c79356b
A
2196 slp = t;
2197 } else if (qp->c_cc > last_cc) {
2198 /* got a character, restart timer */
2199
2200 etime.tv_sec = t / 1000000;
2201 etime.tv_usec = (t - (etime.tv_sec * 1000000));
2202 timeradd(&etime, &timecopy, &etime);
2203
2204 slp = t;
2205 } else {
2206 /* nothing, check expiration */
0a7de745 2207 if (timercmp(&etime, &timecopy, <=)) {
1c79356b 2208 goto read;
0a7de745 2209 }
1c79356b
A
2210
2211 slp = diff(etime, timecopy);
2212 }
2213 last_cc = qp->c_cc;
0a7de745
A
2214 } else { /* m == 0 */
2215 if (qp->c_cc > 0) {
1c79356b 2216 goto read;
0a7de745 2217 }
91447636 2218 microuptime(&timecopy);
1c79356b
A
2219 if (!has_etime) {
2220 has_etime = 1;
2221
2222 etime.tv_sec = t / 1000000;
2223 etime.tv_usec = (t - (etime.tv_sec * 1000000));
2224 timeradd(&etime, &timecopy, &etime);
2225
2226 slp = t;
2227 } else {
0a7de745 2228 if (timercmp(&etime, &timecopy, <=)) {
1c79356b 2229 /* Timed out, but 0 is enough input. */
b0d623f7 2230 goto err;
1c79356b
A
2231 }
2232 slp = diff(etime, timecopy);
2233 }
2234 }
2235#undef diff
2236 /*
2237 * Rounding down may make us wake up just short
2238 * of the target, so we round up.
2239 * The formula is ceiling(slp * hz/1000000).
2240 * 32-bit arithmetic is enough for hz < 169.
2241 * XXX see hzto() for how to avoid overflow if hz
2242 * is large (divide by `tick' and/or arrange to
2243 * use hzto() if hz is large).
2244 */
b0d623f7 2245 slp = (long) (((u_int32_t)slp * hz) + 999999) / 1000000;
1c79356b
A
2246 goto sleep;
2247 }
2248 if (qp->c_cc <= 0) {
2249sleep:
2250 /*
2251 * There is no input, or not enough input and we can block.
2252 */
2253 error = ttysleep(tp, TSA_HUP_OR_INPUT(tp), TTIPRI | PCATCH,
0a7de745
A
2254 ISSET(tp->t_state, TS_CONNECTED) ?
2255 "ttyin" : "ttyhup", (int)slp);
2256 if (error == EWOULDBLOCK) {
1c79356b 2257 error = 0;
0a7de745 2258 } else if (error) {
b0d623f7 2259 goto err;
0b4e3aa0 2260 }
1c79356b
A
2261 /*
2262 * XXX what happens if another process eats some input
2263 * while we are asleep (not just here)? It would be
2264 * safest to detect changes and reset our state variables
2265 * (has_stime and last_cc).
2266 */
2267 slp = 0;
2268 goto loop;
2269 }
2270read:
1c79356b
A
2271 /*
2272 * Input present, check for input mapping and processing.
2273 */
2274 first = 1;
1c79356b 2275 if (ISSET(lflag, ICANON)
0a7de745 2276 || (ISSET(lflag, IEXTEN | ISIG) == (IEXTEN | ISIG))) {
1c79356b 2277 goto slowcase;
0a7de745 2278 }
1c79356b
A
2279 for (;;) {
2280 char ibuf[IBUFSIZ];
2281 int icc;
2282
39236c6e 2283 icc = MIN(uio_resid(uio), IBUFSIZ);
2d21ac55 2284 icc = q_to_b(qp, (u_char *)ibuf, icc);
1c79356b 2285 if (icc <= 0) {
0a7de745 2286 if (first) {
1c79356b 2287 goto loop;
0a7de745 2288 }
1c79356b
A
2289 break;
2290 }
2291 error = uiomove(ibuf, icc, uio);
2292 /*
2293 * XXX if there was an error then we should ungetc() the
2294 * unmoved chars and reduce icc here.
2295 */
0a7de745 2296 if (error) {
1c79356b 2297 break;
0a7de745
A
2298 }
2299 if (uio_resid(uio) == 0) {
1c79356b 2300 break;
0a7de745 2301 }
1c79356b
A
2302 first = 0;
2303 }
2304 goto out;
2305slowcase:
2306 for (;;) {
2307 c = getc(qp);
2308 if (c < 0) {
0a7de745 2309 if (first) {
1c79356b 2310 goto loop;
0a7de745 2311 }
1c79356b
A
2312 break;
2313 }
2314 /*
2315 * delayed suspend (^Y)
2316 */
2317 if (CCEQ(cc[VDSUSP], c) &&
2318 ISSET(lflag, IEXTEN | ISIG) == (IEXTEN | ISIG)) {
b0d623f7
A
2319 /*
2320 * SAFE: All callers drop the lock on return and
2321 * SAFE: current thread will not change out from
2322 * SAFE: under us in the "goto loop" case.
2323 */
2324 tty_unlock(tp);
2d21ac55 2325 tty_pgsignal(tp, SIGTSTP, 1);
b0d623f7 2326 tty_lock(tp);
1c79356b 2327 if (first) {
39236c6e 2328 error = ttysleep(tp, &ttread, TTIPRI | PCATCH,
0a7de745
A
2329 "ttybg3", hz);
2330 if (error) {
1c79356b 2331 break;
0a7de745 2332 }
1c79356b
A
2333 goto loop;
2334 }
2335 break;
2336 }
2337 /*
2338 * Interpret EOF only in canonical mode.
2339 */
0a7de745 2340 if (CCEQ(cc[VEOF], c) && ISSET(lflag, ICANON)) {
1c79356b 2341 break;
0a7de745 2342 }
1c79356b
A
2343 /*
2344 * Give user character.
2345 */
0a7de745
A
2346 error = ureadc(c, uio);
2347 if (error) {
1c79356b
A
2348 /* XXX should ungetc(c, qp). */
2349 break;
0a7de745
A
2350 }
2351 if (uio_resid(uio) == 0) {
1c79356b 2352 break;
0a7de745 2353 }
1c79356b
A
2354 /*
2355 * In canonical mode check for a "break character"
2356 * marking the end of a "line of input".
2357 */
0a7de745 2358 if (ISSET(lflag, ICANON) && TTBREAKC(c, lflag)) {
1c79356b 2359 break;
0a7de745 2360 }
1c79356b
A
2361 first = 0;
2362 }
2363
2364out:
2365 /*
2366 * Look to unblock input now that (presumably)
2367 * the input queue has gone down.
2368 */
1c79356b 2369 if (ISSET(tp->t_state, TS_TBLOCK) &&
0a7de745 2370 tp->t_rawq.c_cc + tp->t_canq.c_cc <= I_LOW_WATER) {
1c79356b 2371 ttyunblock(tp);
0a7de745 2372 }
1c79356b 2373
b0d623f7 2374err:
0a7de745 2375 return error;
1c79356b
A
2376}
2377
b0d623f7 2378
1c79356b
A
2379/*
2380 * Check the output queue on tp for space for a kernel message (from uprintf
2381 * or tprintf). Allow some space over the normal hiwater mark so we don't
2382 * lose messages due to normal flow control, but don't let the tty run amok.
2383 * Sleeps here are not interruptible, but we return prematurely if new signals
2384 * arrive.
b0d623f7
A
2385 *
2386 * Locks: Assumes tty_lock() is held before calling
2387 *
2388 * Notes: This function is called from tprintf() in subr_prf.c
1c79356b
A
2389 */
2390int
2d21ac55 2391ttycheckoutq(struct tty *tp, int wait)
1c79356b 2392{
2d21ac55 2393 int hiwat;
91447636 2394 sigset_t oldsig;
9bccf70c
A
2395 struct uthread *ut;
2396
0a7de745 2397 TTY_LOCK_OWNED(tp); /* debug assert */
b0d623f7 2398
91447636 2399 ut = (struct uthread *)get_bsdthread_info(current_thread());
1c79356b
A
2400
2401 hiwat = tp->t_hiwat;
9bccf70c 2402 oldsig = wait ? ut->uu_siglist : 0;
0a7de745 2403 if (tp->t_outq.c_cc > hiwat + OBUFSIZ + 100) {
1c79356b
A
2404 while (tp->t_outq.c_cc > hiwat) {
2405 ttstart(tp);
0a7de745 2406 if (tp->t_outq.c_cc <= hiwat) {
1c79356b 2407 break;
0a7de745 2408 }
9bccf70c 2409 if (wait == 0 || ut->uu_siglist != oldsig) {
0a7de745 2410 return 0;
1c79356b
A
2411 }
2412 SET(tp->t_state, TS_SO_OLOWAT);
b0d623f7 2413 ttysleep(tp, TSA_OLOWAT(tp), PZERO - 1, "ttoutq", hz);
1c79356b 2414 }
0a7de745
A
2415 }
2416 return 1;
1c79356b
A
2417}
2418
b0d623f7 2419
1c79356b 2420/*
b0d623f7
A
2421 * ttwrite (LDISC)
2422 *
1c79356b 2423 * Process a write call on a tty device.
b0d623f7
A
2424 *
2425 * Locks: Assumes tty_lock() is held prior to calling.
1c79356b
A
2426 */
2427int
2d21ac55 2428ttwrite(struct tty *tp, struct uio *uio, int flag)
1c79356b 2429{
2d21ac55
A
2430 char *cp = NULL;
2431 int cc, ce;
2432 proc_t p;
b0d623f7
A
2433 int i, hiwat, error;
2434 user_ssize_t count;
1c79356b 2435 char obuf[OBUFSIZ];
9bccf70c 2436 struct uthread *ut;
2d21ac55 2437 struct pgrp * pg;
0b4e3aa0 2438
0a7de745 2439 TTY_LOCK_OWNED(tp); /* debug assert */
1c79356b 2440
91447636 2441 ut = (struct uthread *)get_bsdthread_info(current_thread());
1c79356b 2442 hiwat = tp->t_hiwat;
91447636 2443 count = uio_resid(uio);
1c79356b
A
2444 error = 0;
2445 cc = 0;
2446loop:
1c79356b 2447 if (ISSET(tp->t_state, TS_ZOMBIE)) {
0a7de745 2448 if (uio_resid(uio) == count) {
1c79356b 2449 error = EIO;
0a7de745 2450 }
1c79356b
A
2451 goto out;
2452 }
2453 if (!ISSET(tp->t_state, TS_CONNECTED)) {
2454 if (flag & IO_NDELAY) {
1c79356b
A
2455 error = EWOULDBLOCK;
2456 goto out;
2457 }
2458 error = ttysleep(tp, TSA_CARR_ON(tp), TTIPRI | PCATCH,
0a7de745 2459 "ttydcd", 0);
1c79356b 2460 if (error) {
0a7de745
A
2461 goto out;
2462 }
1c79356b
A
2463 goto loop;
2464 }
1c79356b 2465 /*
2d21ac55 2466 * Signal the process if it's in the background.
1c79356b
A
2467 */
2468 p = current_proc();
2469 if (isbackground(p, tp) &&
2d21ac55 2470 ISSET(tp->t_lflag, TOSTOP) && (p->p_lflag & P_LPPWAIT) == 0 &&
1c79356b 2471 (p->p_sigignore & sigmask(SIGTTOU)) == 0 &&
9bccf70c 2472 (ut->uu_sigmask & sigmask(SIGTTOU)) == 0) {
2d21ac55
A
2473 pg = proc_pgrp(p);
2474 if (pg == PGRP_NULL) {
1c79356b
A
2475 error = EIO;
2476 goto out;
2477 }
2d21ac55 2478 if (pg->pg_jobc == 0) {
b0d623f7
A
2479 /* SAFE: All callers drop the lock on return */
2480 tty_unlock(tp);
2d21ac55 2481 pg_rele(pg);
b0d623f7 2482 tty_lock(tp);
2d21ac55
A
2483 error = EIO;
2484 goto out;
2485 }
b0d623f7
A
2486 /* SAFE: All callers drop the lock on return */
2487 tty_unlock(tp);
2d21ac55
A
2488 pgsignal(pg, SIGTTOU, 1);
2489 pg_rele(pg);
b0d623f7 2490 tty_lock(tp);
2d21ac55
A
2491 /*
2492 * We signalled ourself, so we need to act as if we
2493 * have been "interrupted" from a "sleep" to act on
2494 * the signal. If it's a signal that stops the
2495 * process, that's handled in the signal sending code.
2496 */
2497 error = EINTR;
0a7de745 2498 goto out;
1c79356b
A
2499 }
2500 /*
2501 * Process the user's data in at most OBUFSIZ chunks. Perform any
2502 * output translation. Keep track of high water mark, sleep on
2503 * overflow awaiting device aid in acquiring new space.
2504 */
91447636 2505 while (uio_resid(uio) > 0 || cc > 0) {
1c79356b 2506 if (ISSET(tp->t_lflag, FLUSHO)) {
91447636 2507 uio_setresid(uio, 0);
0a7de745 2508 return 0;
1c79356b 2509 }
0a7de745 2510 if (tp->t_outq.c_cc > hiwat) {
1c79356b 2511 goto ovhiwat;
0a7de745 2512 }
1c79356b
A
2513 /*
2514 * Grab a hunk of data from the user, unless we have some
2515 * leftover from last time.
2516 */
2517 if (cc == 0) {
39236c6e 2518 cc = MIN(uio_resid(uio), OBUFSIZ);
1c79356b
A
2519 cp = obuf;
2520 error = uiomove(cp, cc, uio);
2521 if (error) {
2522 cc = 0;
2523 break;
2524 }
1c79356b
A
2525 }
2526 /*
2527 * If nothing fancy need be done, grab those characters we
2528 * can handle without any of ttyoutput's processing and
2529 * just transfer them to the output q. For those chars
2530 * which require special processing (as indicated by the
2531 * bits in char_type), call ttyoutput. After processing
2532 * a hunk of data, look for FLUSHO so ^O's will take effect
2533 * immediately.
2534 */
2535 while (cc > 0) {
0a7de745 2536 if (!ISSET(tp->t_oflag, OPOST)) {
1c79356b 2537 ce = cc;
0a7de745 2538 } else {
1c79356b 2539 ce = cc - scanc((u_int)cc, (u_char *)cp,
0a7de745 2540 char_type, CCLASSMASK);
1c79356b
A
2541 /*
2542 * If ce is zero, then we're processing
2543 * a special character through ttyoutput.
2544 */
2545 if (ce == 0) {
2546 tp->t_rocount = 0;
2547 if (ttyoutput(*cp, tp) >= 0) {
1c79356b
A
2548 /* out of space */
2549 goto overfull;
1c79356b
A
2550 }
2551 cp++;
2552 cc--;
2553 if (ISSET(tp->t_lflag, FLUSHO) ||
0a7de745 2554 tp->t_outq.c_cc > hiwat) {
1c79356b 2555 goto ovhiwat;
0a7de745 2556 }
1c79356b
A
2557 continue;
2558 }
2559 }
2560 /*
2561 * A bunch of normal characters have been found.
2562 * Transfer them en masse to the output queue and
2563 * continue processing at the top of the loop.
2564 * If there are any further characters in this
2565 * <= OBUFSIZ chunk, the first should be a character
2566 * requiring special handling by ttyoutput.
2567 */
2568 tp->t_rocount = 0;
2d21ac55 2569 i = b_to_q((u_char *)cp, ce, &tp->t_outq);
1c79356b
A
2570 ce -= i;
2571 tp->t_column += ce;
39037602
A
2572 cp += ce;
2573 cc -= ce;
2574 tk_nout += ce;
1c79356b
A
2575 tp->t_outcc += ce;
2576 if (i > 0) {
1c79356b
A
2577 /* out of space */
2578 goto overfull;
1c79356b
A
2579 }
2580 if (ISSET(tp->t_lflag, FLUSHO) ||
0a7de745 2581 tp->t_outq.c_cc > hiwat) {
1c79356b 2582 break;
0a7de745 2583 }
1c79356b
A
2584 }
2585 ttstart(tp);
2586 }
2587out:
2588 /*
2589 * If cc is nonzero, we leave the uio structure inconsistent, as the
2590 * offset and iov pointers have moved forward, but it doesn't matter
2591 * (the call will either return short or restart with a new uio).
2592 */
91447636 2593 uio_setresid(uio, (uio_resid(uio) + cc));
0a7de745 2594 return error;
1c79356b 2595
1c79356b
A
2596overfull:
2597
2598 /*
2599 * Since we are using ring buffers, if we can't insert any more into
2600 * the output queue, we can assume the ring is full and that someone
2601 * forgot to set the high water mark correctly. We set it and then
2602 * proceed as normal.
2603 */
2604 hiwat = tp->t_outq.c_cc - 1;
1c79356b
A
2605
2606ovhiwat:
2607 ttstart(tp);
1c79356b
A
2608 /*
2609 * This can only occur if FLUSHO is set in t_lflag,
2610 * or if ttstart/oproc is synchronous (or very fast).
2611 */
2612 if (tp->t_outq.c_cc <= hiwat) {
1c79356b
A
2613 goto loop;
2614 }
2615 if (flag & IO_NDELAY) {
91447636 2616 uio_setresid(uio, (uio_resid(uio) + cc));
0a7de745 2617 return uio_resid(uio) == count ? EWOULDBLOCK : 0;
1c79356b
A
2618 }
2619 SET(tp->t_state, TS_SO_OLOWAT);
2620 error = ttysleep(tp, TSA_OLOWAT(tp), TTOPRI | PCATCH, "ttywri",
0a7de745
A
2621 tp->t_timeout);
2622 if (error == EWOULDBLOCK) {
1c79356b 2623 error = EIO;
0a7de745
A
2624 }
2625 if (error) {
1c79356b 2626 goto out;
0a7de745 2627 }
1c79356b
A
2628 goto loop;
2629}
2630
b0d623f7 2631
1c79356b
A
2632/*
2633 * Rubout one character from the rawq of tp
2634 * as cleanly as possible.
b0d623f7
A
2635 *
2636 * Locks: Assumes tty_lock() is held prior to calling.
1c79356b
A
2637 */
2638static void
2d21ac55 2639ttyrub(int c, struct tty *tp)
1c79356b 2640{
2d21ac55
A
2641 u_char *cp;
2642 int savecol;
2643 int tabc;
1c79356b 2644
0a7de745 2645 TTY_LOCK_OWNED(tp); /* debug assert */
b0d623f7 2646
0a7de745 2647 if (!ISSET(tp->t_lflag, ECHO) || ISSET(tp->t_lflag, EXTPROC)) {
1c79356b 2648 return;
0a7de745 2649 }
1c79356b
A
2650 CLR(tp->t_lflag, FLUSHO);
2651 if (ISSET(tp->t_lflag, ECHOE)) {
2652 if (tp->t_rocount == 0) {
2653 /*
2654 * Messed up by ttwrite; retype
2655 */
2656 ttyretype(tp);
2657 return;
2658 }
0a7de745 2659 if (c == ('\t' | TTY_QUOTE) || c == ('\n' | TTY_QUOTE)) {
1c79356b 2660 ttyrubo(tp, 2);
0a7de745 2661 } else {
1c79356b
A
2662 CLR(c, ~TTY_CHARMASK);
2663 switch (CCLASS(c)) {
2664 case ORDINARY:
0a7de745 2665 if (!(ISSET(tp->t_iflag, IUTF8) && CCONT(c))) {
2d21ac55
A
2666 ttyrubo(tp, 1);
2667 }
1c79356b
A
2668 break;
2669 case BACKSPACE:
2670 case CONTROL:
2671 case NEWLINE:
2672 case RETURN:
2673 case VTAB:
0a7de745 2674 if (ISSET(tp->t_lflag, ECHOCTL)) {
1c79356b 2675 ttyrubo(tp, 2);
0a7de745 2676 }
1c79356b
A
2677 break;
2678 case TAB:
2679 if (tp->t_rocount < tp->t_rawq.c_cc) {
2680 ttyretype(tp);
2681 return;
2682 }
1c79356b
A
2683 savecol = tp->t_column;
2684 SET(tp->t_state, TS_CNTTB);
2685 SET(tp->t_lflag, FLUSHO);
2686 tp->t_column = tp->t_rocol;
1c79356b 2687 for (cp = firstc(&tp->t_rawq, &tabc); cp;
0a7de745 2688 cp = nextc(&tp->t_rawq, cp, &tabc)) {
1c79356b 2689 ttyecho(tabc, tp);
0a7de745 2690 }
1c79356b
A
2691 CLR(tp->t_lflag, FLUSHO);
2692 CLR(tp->t_state, TS_CNTTB);
1c79356b
A
2693
2694 /* savecol will now be length of the tab. */
2695 savecol -= tp->t_column;
2696 tp->t_column += savecol;
0a7de745
A
2697 if (savecol > 8) {
2698 savecol = 8; /* overflow fixup */
2699 }
2700 while (--savecol >= 0) {
1c79356b 2701 (void)ttyoutput('\b', tp);
0a7de745 2702 }
1c79356b 2703 break;
0a7de745
A
2704 default: /* XXX */
2705#define PANICSTR "ttyrub: would panic c = %d, val = %d\n"
2d21ac55 2706 printf(PANICSTR, c, CCLASS(c));
1c79356b
A
2707#ifdef notdef
2708 panic(PANICSTR, c, CCLASS(c));
2709#endif
2710 }
2711 }
2712 } else if (ISSET(tp->t_lflag, ECHOPRT)) {
2713 if (!ISSET(tp->t_state, TS_ERASE)) {
2714 SET(tp->t_state, TS_ERASE);
2715 (void)ttyoutput('\\', tp);
2716 }
2717 ttyecho(c, tp);
0a7de745 2718 } else {
1c79356b 2719 ttyecho(tp->t_cc[VERASE], tp);
0a7de745 2720 }
1c79356b
A
2721 --tp->t_rocount;
2722}
2723
b0d623f7 2724
1c79356b 2725/*
91447636 2726 * Back over count characters, erasing them.
b0d623f7
A
2727 *
2728 * Locks: Assumes tty_lock() is held prior to calling.
1c79356b
A
2729 */
2730static void
91447636 2731ttyrubo(struct tty *tp, int count)
1c79356b 2732{
0a7de745 2733 TTY_LOCK_OWNED(tp); /* debug assert */
b0d623f7 2734
91447636 2735 while (count-- > 0) {
1c79356b
A
2736 (void)ttyoutput('\b', tp);
2737 (void)ttyoutput(' ', tp);
2738 (void)ttyoutput('\b', tp);
2739 }
2740}
2741
b0d623f7 2742
1c79356b
A
2743/*
2744 * ttyretype --
2745 * Reprint the rawq line. Note, it is assumed that c_cc has already
2746 * been checked.
b0d623f7
A
2747 *
2748 * Locks: Assumes tty_lock() is held prior to calling.
1c79356b
A
2749 */
2750static void
2d21ac55 2751ttyretype(struct tty *tp)
1c79356b 2752{
2d21ac55
A
2753 u_char *cp;
2754 int c;
1c79356b 2755
0a7de745 2756 TTY_LOCK_OWNED(tp); /* debug assert */
b0d623f7 2757
1c79356b 2758 /* Echo the reprint character. */
0a7de745 2759 if (tp->t_cc[VREPRINT] != _POSIX_VDISABLE) {
1c79356b 2760 ttyecho(tp->t_cc[VREPRINT], tp);
0a7de745 2761 }
1c79356b
A
2762
2763 (void)ttyoutput('\n', tp);
2764
2765 /*
2766 * FREEBSD XXX
2767 * FIX: NEXTC IS BROKEN - DOESN'T CHECK QUOTE
2768 * BIT OF FIRST CHAR.
2769 */
0a7de745 2770 for (cp = firstc(&tp->t_canq, &c); cp; cp = nextc(&tp->t_canq, cp, &c)) {
1c79356b 2771 ttyecho(c, tp);
0a7de745
A
2772 }
2773 for (cp = firstc(&tp->t_rawq, &c); cp; cp = nextc(&tp->t_rawq, cp, &c)) {
1c79356b 2774 ttyecho(c, tp);
0a7de745 2775 }
1c79356b 2776 CLR(tp->t_state, TS_ERASE);
1c79356b
A
2777
2778 tp->t_rocount = tp->t_rawq.c_cc;
2779 tp->t_rocol = 0;
2780}
2781
b0d623f7 2782
1c79356b
A
2783/*
2784 * Echo a typed character to the terminal.
b0d623f7
A
2785 *
2786 * Locks: Assumes tty_lock() is held prior to calling.
1c79356b
A
2787 */
2788static void
2d21ac55 2789ttyecho(int c, struct tty *tp)
1c79356b 2790{
0a7de745 2791 TTY_LOCK_OWNED(tp); /* debug assert */
b0d623f7 2792
0a7de745 2793 if (!ISSET(tp->t_state, TS_CNTTB)) {
1c79356b 2794 CLR(tp->t_lflag, FLUSHO);
0a7de745 2795 }
1c79356b 2796 if ((!ISSET(tp->t_lflag, ECHO) &&
0a7de745
A
2797 (c != '\n' || !ISSET(tp->t_lflag, ECHONL))) ||
2798 ISSET(tp->t_lflag, EXTPROC)) {
1c79356b 2799 return;
0a7de745 2800 }
1c79356b
A
2801 if (ISSET(tp->t_lflag, ECHOCTL) &&
2802 ((ISSET(c, TTY_CHARMASK) <= 037 && c != '\t' && c != '\n') ||
2803 ISSET(c, TTY_CHARMASK) == 0177)) {
2804 (void)ttyoutput('^', tp);
2805 CLR(c, ~TTY_CHARMASK);
0a7de745 2806 if (c == 0177) {
1c79356b 2807 c = '?';
0a7de745 2808 } else {
1c79356b 2809 c += 'A' - 1;
0a7de745 2810 }
1c79356b
A
2811 }
2812 (void)ttyoutput(c, tp);
2813}
2814
cb323159
A
2815static void
2816ttwakeup_knote(struct selinfo *sip, long hint)
2817{
2818 if ((sip->si_flags & SI_KNPOSTING) == 0) {
2819 sip->si_flags |= SI_KNPOSTING;
2820 KNOTE(&sip->si_note, hint);
2821 sip->si_flags &= ~SI_KNPOSTING;
2822 }
2823}
2824
b0d623f7 2825
1c79356b
A
2826/*
2827 * Wake up any readers on a tty.
b0d623f7
A
2828 *
2829 * Locks: Assumes tty_lock() is held for the call.
1c79356b
A
2830 */
2831void
2d21ac55 2832ttwakeup(struct tty *tp)
1c79356b 2833{
0a7de745 2834 TTY_LOCK_OWNED(tp); /* debug assert */
b0d623f7 2835
2d21ac55 2836 selwakeup(&tp->t_rsel);
cb323159 2837 ttwakeup_knote(&tp->t_rsel, 0);
b0d623f7
A
2838 if (ISSET(tp->t_state, TS_ASYNC)) {
2839 /*
2840 * XXX: Callers may not revalidate it the tty is closed
2841 * XXX: out from under them by another thread, but we do
2842 * XXX: not support queued signals. This should be safe,
2843 * XXX: since the process we intend to wakeup is in the
2844 * XXX: process group, and will wake up because of the
2845 * XXX: signal anyway.
2846 */
2847 tty_unlock(tp);
2d21ac55 2848 tty_pgsignal(tp, SIGIO, 1);
b0d623f7
A
2849 tty_lock(tp);
2850 }
1c79356b
A
2851 wakeup(TSA_HUP_OR_INPUT(tp));
2852}
2853
b0d623f7 2854
1c79356b 2855/*
b0d623f7
A
2856 * ttwwakeup (LDISC)
2857 *
1c79356b 2858 * Wake up any writers on a tty.
b0d623f7
A
2859 *
2860 * Locks: Assumes tty_lock() is held prior to calling.
1c79356b
A
2861 */
2862void
2d21ac55 2863ttwwakeup(struct tty *tp)
1c79356b 2864{
0a7de745 2865 TTY_LOCK_OWNED(tp); /* debug assert */
b0d623f7
A
2866
2867 if (tp->t_outq.c_cc <= tp->t_lowat) {
1c79356b 2868 selwakeup(&tp->t_wsel);
cb323159 2869 ttwakeup_knote(&tp->t_wsel, 0);
b0d623f7 2870 }
1c79356b
A
2871 if (ISSET(tp->t_state, TS_BUSY | TS_SO_OCOMPLETE) ==
2872 TS_SO_OCOMPLETE && tp->t_outq.c_cc == 0) {
2873 CLR(tp->t_state, TS_SO_OCOMPLETE);
2874 wakeup(TSA_OCOMPLETE(tp));
2875 }
2876 if (ISSET(tp->t_state, TS_SO_OLOWAT) &&
2877 tp->t_outq.c_cc <= tp->t_lowat) {
2878 CLR(tp->t_state, TS_SO_OLOWAT);
2879 wakeup(TSA_OLOWAT(tp));
2880 }
2881}
2882
b0d623f7 2883
1c79356b
A
2884/*
2885 * Look up a code for a specified speed in a conversion table;
2886 * used by drivers to map software speed values to hardware parameters.
b0d623f7
A
2887 *
2888 * Notes: No locks are assumed for this function; it does not
2889 * directly access struct tty.
1c79356b
A
2890 */
2891int
2d21ac55 2892ttspeedtab(int speed, struct speedtab *table)
1c79356b 2893{
0a7de745
A
2894 for (; table->sp_speed != -1; table++) {
2895 if (table->sp_speed == speed) {
2896 return table->sp_code;
2897 }
2898 }
2899 return -1;
1c79356b
A
2900}
2901
b0d623f7 2902
1c79356b
A
2903/*
2904 * Set tty hi and low water marks.
2905 *
2906 * Try to arrange the dynamics so there's about one second
2907 * from hi to low water.
2908 *
b0d623f7 2909 * Locks: Assumes tty_lock() is held prior to calling.
1c79356b
A
2910 */
2911void
91447636 2912ttsetwater(struct tty *tp)
1c79356b 2913{
91447636
A
2914 int cps;
2915 unsigned int x;
1c79356b 2916
0a7de745 2917 TTY_LOCK_OWNED(tp); /* debug assert */
b0d623f7 2918
0a7de745 2919#define CLAMP(x, h, l) ((x) > h ? h : ((x) < l) ? l : (x))
1c79356b
A
2920
2921 cps = tp->t_ospeed / 10;
2922 tp->t_lowat = x = CLAMP(cps / 2, TTMAXLOWAT, TTMINLOWAT);
2923 x += cps;
2924 x = CLAMP(x, TTMAXHIWAT, TTMINHIWAT);
2925 tp->t_hiwat = roundup(x, CBSIZE);
0a7de745 2926#undef CLAMP
1c79356b
A
2927}
2928
2d21ac55 2929/* ttyinfo has been converted to the MACH kernel */
1c79356b
A
2930#include <mach/thread_info.h>
2931
91447636 2932/* XXX Should be in Mach header <kern/thread.h>, but doesn't work */
0a7de745
A
2933extern kern_return_t thread_info_internal(thread_t thread,
2934 thread_flavor_t flavor,
2935 thread_info_t thread_info_out,
2936 mach_msg_type_number_t *thread_info_count);
91447636 2937
b0d623f7 2938
1c79356b
A
2939/*
2940 * Report on state of foreground process group.
b0d623f7
A
2941 *
2942 * Locks: Assumes tty_lock() is held prior to calling.
1c79356b
A
2943 */
2944void
b0d623f7 2945ttyinfo_locked(struct tty *tp)
1c79356b 2946{
0a7de745
A
2947 int load;
2948 thread_t thread;
2949 uthread_t uthread;
2950 proc_t p;
2951 proc_t pick;
2d21ac55 2952 pid_t pickpid;
0a7de745
A
2953 const char *state;
2954 struct timeval utime;
2955 struct timeval stime;
2956 thread_basic_info_data_t basic_info;
2957 mach_msg_type_number_t mmtn = THREAD_BASIC_INFO_COUNT;
2d21ac55
A
2958 struct pgrp * pg;
2959
0a7de745 2960 TTY_LOCK_OWNED(tp); /* debug assert */
91447636 2961
0a7de745 2962 if (ttycheckoutq(tp, 0) == 0) {
91447636 2963 return;
0a7de745 2964 }
91447636
A
2965
2966 /* Print load average. */
2967 load = (averunnable.ldavg[0] * 100 + FSCALE / 2) >> FSHIFT;
2968 ttyprintf(tp, "load: %d.%02d ", load / 100, load % 100);
2969
2970 /*
2971 * On return following a ttyprintf(), we set tp->t_rocount to 0 so
2972 * that pending input will be retyped on BS.
2973 */
2974 if (tp->t_session == NULL) {
2975 ttyprintf(tp, "not a controlling terminal\n");
2976 tp->t_rocount = 0;
2977 return;
0a7de745 2978 }
91447636
A
2979 if (tp->t_pgrp == NULL) {
2980 ttyprintf(tp, "no foreground process group\n");
2981 tp->t_rocount = 0;
2982 return;
2983 }
2984 /* first process in process group */
2d21ac55 2985 /* XXX is there a need for pgrp lock ? */
91447636
A
2986 if ((p = tp->t_pgrp->pg_members.lh_first) == NULL) {
2987 ttyprintf(tp, "empty foreground process group\n");
2988 tp->t_rocount = 0;
2989 return;
2990 }
2991
2992 /*
2993 * Pick the most interesting process and copy some of its
2994 * state for printing later.
2995 */
2d21ac55
A
2996 pg = proc_pgrp(p);
2997 pgrp_lock(pg);
2998 /* the proc_compare is non blocking fn, no need to use iterator */
91447636 2999 for (pick = NULL; p != NULL; p = p->p_pglist.le_next) {
2d21ac55 3000 if (proc_compare(pick, p)) {
91447636 3001 pick = p;
2d21ac55
A
3002 pickpid = p->p_pid;
3003 } else {
3004 pickpid = pick->p_pid;
3005 }
91447636 3006 }
2d21ac55 3007 pgrp_unlock(pg);
b0d623f7
A
3008 /* SAFE: All callers drop the lock on return */
3009 tty_unlock(tp);
2d21ac55 3010 pg_rele(pg);
b0d623f7 3011 tty_lock(tp);
2d21ac55
A
3012
3013 pick = proc_find(pickpid);
0a7de745 3014 if (pick == PROC_NULL) {
2d21ac55 3015 return;
0a7de745 3016 }
91447636
A
3017
3018 if (TAILQ_EMPTY(&pick->p_uthlist) ||
3019 (uthread = TAILQ_FIRST(&pick->p_uthlist)) == NULL ||
2d21ac55 3020 (thread = vfs_context_thread(&uthread->uu_context)) == NULL ||
91447636
A
3021 (thread_info_internal(thread, THREAD_BASIC_INFO, (thread_info_t)&basic_info, &mmtn) != KERN_SUCCESS)) {
3022 ttyprintf(tp, "foreground process without thread\n");
3023 tp->t_rocount = 0;
2d21ac55 3024 proc_rele(pick);
91447636
A
3025 return;
3026 }
3027
0a7de745 3028 switch (basic_info.run_state) {
91447636
A
3029 case TH_STATE_RUNNING:
3030 state = "running";
3031 break;
3032 case TH_STATE_STOPPED:
3033 state = "stopped";
3034 break;
3035 case TH_STATE_WAITING:
3036 state = "waiting";
3037 break;
3038 case TH_STATE_UNINTERRUPTIBLE:
3039 state = "uninterruptible";
3040 break;
3041 case TH_STATE_HALTED:
3042 state = "halted";
3043 break;
3044 default:
3045 state = "unknown";
3046 break;
3047 }
3048 calcru(pick, &utime, &stime, NULL);
3049
3050 /* Print command, pid, state, utime, and stime */
b0d623f7 3051 ttyprintf(tp, " cmd: %s %d %s %ld.%02du %ld.%02ds\n",
0a7de745
A
3052 pick->p_comm,
3053 pick->p_pid,
3054 state,
3055 (long)utime.tv_sec, utime.tv_usec / 10000,
3056 (long)stime.tv_sec, stime.tv_usec / 10000);
cb323159
A
3057
3058 proc_rele(pick);
91447636 3059 tp->t_rocount = 0;
1c79356b
A
3060}
3061
b0d623f7 3062
1c79356b
A
3063/*
3064 * Returns 1 if p2 is "better" than p1
3065 *
3066 * The algorithm for picking the "interesting" process is thus:
3067 *
3068 * 1) Only foreground processes are eligible - implied.
3069 * 2) Runnable processes are favored over anything else. The runner
3070 * with the highest cpu utilization is picked (p_estcpu). Ties are
3071 * broken by picking the highest pid.
91447636 3072 * 3) The sleeper with the shortest sleep time is next.
1c79356b
A
3073 * 4) Further ties are broken by picking the highest pid.
3074 */
0a7de745 3075#define ISRUN(p) (((p)->p_stat == SRUN) || ((p)->p_stat == SIDL))
1c79356b
A
3076#define TESTAB(a, b) ((a)<<1 | (b))
3077#define ONLYA 2
3078#define ONLYB 1
3079#define BOTH 3
3080
b0d623f7
A
3081/*
3082 * Locks: pgrp_lock(p2) held on call to this function
3083 * tty_lock(tp) for p2's tty, for which p2 is the foreground
3084 * process, held on call to this function
3085 */
1c79356b 3086static int
2d21ac55 3087proc_compare(proc_t p1, proc_t p2)
1c79356b 3088{
2d21ac55 3089 /* NOTE THIS FN needs to be NON BLOCKING */
1c79356b 3090
0a7de745
A
3091 if (p1 == NULL) {
3092 return 1;
3093 }
1c79356b
A
3094 /*
3095 * see if at least one of them is runnable
3096 */
3097 switch (TESTAB(ISRUN(p1), ISRUN(p2))) {
3098 case ONLYA:
0a7de745 3099 return 0;
1c79356b 3100 case ONLYB:
0a7de745 3101 return 1;
1c79356b
A
3102 case BOTH:
3103 /*
3104 * tie - favor one with highest recent cpu utilization
3105 */
2d21ac55
A
3106#ifdef _PROC_HAS_SCHEDINFO_
3107 /* Without the support the fields are always zero */
0a7de745
A
3108 if (p2->p_estcpu > p1->p_estcpu) {
3109 return 1;
3110 }
3111 if (p1->p_estcpu > p2->p_estcpu) {
3112 return 0;
3113 }
2d21ac55 3114#endif /* _PROC_HAS_SCHEDINFO_ */
0a7de745 3115 return p2->p_pid > p1->p_pid; /* tie - return highest pid */
1c79356b
A
3116 }
3117 /*
0a7de745 3118 * weed out zombies
1c79356b
A
3119 */
3120 switch (TESTAB(p1->p_stat == SZOMB, p2->p_stat == SZOMB)) {
3121 case ONLYA:
0a7de745 3122 return 1;
1c79356b 3123 case ONLYB:
0a7de745 3124 return 0;
1c79356b 3125 case BOTH:
0a7de745 3126 return p2->p_pid > p1->p_pid; /* tie - return highest pid */
1c79356b
A
3127 }
3128 /*
3129 * pick the one with the smallest sleep time
3130 */
2d21ac55
A
3131#ifdef _PROC_HAS_SCHEDINFO_
3132 /* Without the support the fields are always zero */
0a7de745
A
3133 if (p2->p_slptime > p1->p_slptime) {
3134 return 0;
3135 }
3136 if (p1->p_slptime > p2->p_slptime) {
3137 return 1;
3138 }
2d21ac55 3139#endif /* _PROC_HAS_SCHEDINFO_ */
0a7de745 3140 return p2->p_pid > p1->p_pid; /* tie - return highest pid */
1c79356b 3141}
1c79356b 3142
b0d623f7 3143
1c79356b
A
3144/*
3145 * Output char to tty; console putchar style.
b0d623f7
A
3146 *
3147 * Locks: Assumes tty_lock() is held prior to calling.
3148 *
3149 * Notes: Only ever called from putchar() in subr_prf.c
1c79356b
A
3150 */
3151int
2d21ac55 3152tputchar(int c, struct tty *tp)
1c79356b 3153{
0a7de745 3154 TTY_LOCK_OWNED(tp); /* debug assert */
b0d623f7 3155
1c79356b 3156 if (!ISSET(tp->t_state, TS_CONNECTED)) {
0a7de745 3157 return -1;
1c79356b 3158 }
0a7de745 3159 if (c == '\n') {
1c79356b 3160 (void)ttyoutput('\r', tp);
0a7de745 3161 }
1c79356b
A
3162 (void)ttyoutput(c, tp);
3163 ttstart(tp);
0a7de745 3164 return 0;
1c79356b
A
3165}
3166
b0d623f7 3167
1c79356b 3168/*
b0d623f7
A
3169 * ttysleep
3170 *
3171 * Sleep on a wait channel waiting for an interrupt or a condition to come
3172 * true so that we are woken up.
3173 *
3174 * Parameters: tp Tty going to sleep
3175 * chan The sleep channel (usually an address
3176 * of a structure member)
3177 * pri priority and flags
3178 * wmesg Wait message; shows up in debugger,
3179 * should show up in "ps", but doesn't
3180 * timo Timeout for the sleep
3181 *
3182 * Returns: 0 Condition came true
3183 * ERESTART Upper layer must redrive the call;
3184 * this is usually done by the Libc
3185 * stub in user space
3186 * msleep0:EINTR Interrupted (usually a signal)
3187 * msleep0:ERESTART Interrupted (usually a masked signal)
3188 * msleep0:EWOULDBLOCK Timeout (timo) already expired
3189 *
3190 * Locks: Assumes tty_lock() is held prior to calling.
3191 *
1c79356b 3192 * Sleep on chan, returning ERESTART if tty changed while we napped and
b0d623f7 3193 * returning any errors (e.g. EINTR/EWOULDBLOCK) reported by msleep0. If
1c79356b
A
3194 * the tty is revoked, restarting a pending call will redo validation done
3195 * at the start of the call.
3196 */
3197int
91447636 3198ttysleep(struct tty *tp, void *chan, int pri, const char *wmesg, int timo)
1c79356b
A
3199{
3200 int error;
3201 int gen;
3202
b0d623f7
A
3203 TTY_LOCK_OWNED(tp);
3204
1c79356b 3205 gen = tp->t_gen;
b0d623f7
A
3206 /* Use of msleep0() avoids conversion timo/timespec/timo */
3207 error = msleep0(chan, &tp->t_lock, pri, wmesg, timo, (int (*)(int))0);
0a7de745
A
3208 if (error) {
3209 return error;
3210 }
3211 return tp->t_gen == gen ? 0 : ERESTART;
1c79356b
A
3212}
3213
b0d623f7 3214
1c79356b
A
3215/*
3216 * Allocate a tty structure and its associated buffers.
2d21ac55
A
3217 *
3218 * Parameters: void
3219 *
3220 * Returns: !NULL Address of new struct tty
3221 * NULL Error ("ENOMEM")
b0d623f7
A
3222 *
3223 * Locks: The tty_lock() of the returned tty is not held when it
3224 * is returned.
1c79356b
A
3225 */
3226struct tty *
91447636 3227ttymalloc(void)
1c79356b
A
3228{
3229 struct tty *tp;
3230
0a7de745 3231 MALLOC(tp, struct tty *, sizeof(struct tty), M_TTYS, M_WAITOK | M_ZERO);
91447636
A
3232 if (tp != NULL) {
3233 /* XXX: default to TTYCLSIZE(1024) chars for now */
3234 clalloc(&tp->t_rawq, TTYCLSIZE, 1);
3235 clalloc(&tp->t_canq, TTYCLSIZE, 1);
3236 /* output queue doesn't need quoting */
3237 clalloc(&tp->t_outq, TTYCLSIZE, 0);
b0d623f7 3238 lck_mtx_init(&tp->t_lock, tty_lck_grp, tty_lck_attr);
0b4c1975
A
3239 klist_init(&tp->t_rsel.si_note);
3240 klist_init(&tp->t_wsel.si_note);
316670eb 3241 tp->t_refcnt = 1;
91447636 3242 }
0a7de745 3243 return tp;
1c79356b
A
3244}
3245
316670eb
A
3246/*
3247 * Increment the reference count on a tty.
3248 */
5ba3f43e 3249void
316670eb
A
3250ttyhold(struct tty *tp)
3251{
3252 TTY_LOCK_OWNED(tp);
3253 tp->t_refcnt++;
3254}
b0d623f7 3255
1c79356b 3256/*
316670eb
A
3257 * Drops a reference count on a tty structure; if the reference count reaches
3258 * zero, then also frees the structure and associated buffers.
1c79356b
A
3259 */
3260void
2d21ac55 3261ttyfree(struct tty *tp)
316670eb
A
3262{
3263 TTY_LOCK_NOTOWNED(tp);
3264
3265 tty_lock(tp);
3266 if (--tp->t_refcnt == 0) {
3267 tty_unlock(tp);
3268 ttydeallocate(tp);
3269 } else if (tp->t_refcnt < 0) {
3270 panic("%s: freeing free tty %p", __func__, tp);
0a7de745 3271 } else {
316670eb 3272 tty_unlock(tp);
0a7de745 3273 }
316670eb
A
3274}
3275
3276/*
3277 * Deallocate a tty structure and its buffers.
3278 *
3279 * Locks: The tty_lock() is assumed to not be held at the time of
3280 * the free; this function destroys the mutex.
3281 */
3282static void
3283ttydeallocate(struct tty *tp)
1c79356b 3284{
0a7de745 3285 TTY_LOCK_NOTOWNED(tp); /* debug assert */
b0d623f7 3286
6d2010ae
A
3287#if DEBUG
3288 if (!(SLIST_EMPTY(&tp->t_rsel.si_note) && SLIST_EMPTY(&tp->t_wsel.si_note))) {
3289 panic("knotes hooked into a tty when the tty is freed.\n");
3290 }
3291#endif /* DEBUG */
3292
1c79356b
A
3293 clfree(&tp->t_rawq);
3294 clfree(&tp->t_canq);
3295 clfree(&tp->t_outq);
b0d623f7 3296 lck_mtx_destroy(&tp->t_lock, tty_lck_grp);
1c79356b
A
3297 FREE(tp, M_TTYS);
3298}
3299
b0d623f7
A
3300
3301/*
3302 * Locks: Assumes tty_lock() is held prior to calling.
3303 */
2d21ac55
A
3304int
3305isbackground(proc_t p, struct tty *tp)
3306{
b0d623f7
A
3307 TTY_LOCK_OWNED(tp);
3308
0a7de745 3309 return tp->t_session != NULL && p->p_pgrp != NULL && (p->p_pgrp != tp->t_pgrp) && isctty_sp(p, tp, p->p_pgrp->pg_session);
2d21ac55 3310}
1c79356b 3311
0a7de745 3312static int
2d21ac55 3313isctty(proc_t p, struct tty *tp)
1c79356b 3314{
2d21ac55
A
3315 int retval;
3316 struct session * sessp;
1c79356b 3317
2d21ac55
A
3318 sessp = proc_session(p);
3319 retval = (sessp == tp->t_session && p->p_flag & P_CONTROLT);
3320 session_rele(sessp);
0a7de745 3321 return retval;
1c79356b 3322}
1c79356b 3323
2d21ac55
A
3324static int
3325isctty_sp(proc_t p, struct tty *tp, struct session *sessp)
1c79356b 3326{
0a7de745 3327 return sessp == tp->t_session && p->p_flag & P_CONTROLT;
1c79356b 3328}
5ba3f43e
A
3329
3330
cb323159 3331static int filt_ttyattach(struct knote *kn, struct kevent_qos_s *kev);
5ba3f43e
A
3332static void filt_ttydetach(struct knote *kn);
3333static int filt_ttyevent(struct knote *kn, long hint);
cb323159
A
3334static int filt_ttytouch(struct knote *kn, struct kevent_qos_s *kev);
3335static int filt_ttyprocess(struct knote *kn, struct kevent_qos_s *kev);
5ba3f43e
A
3336
3337SECURITY_READ_ONLY_EARLY(struct filterops) tty_filtops = {
3338 .f_isfd = 1,
3339 .f_attach = filt_ttyattach,
3340 .f_detach = filt_ttydetach,
3341 .f_event = filt_ttyevent,
3342 .f_touch = filt_ttytouch,
3343 .f_process = filt_ttyprocess
3344};
3345
3346/*
3347 * Called with struct tty locked. Returns non-zero if there is data to be read
3348 * or written.
3349 */
3350static int
cb323159 3351filt_tty_common(struct knote *kn, struct kevent_qos_s *kev, struct tty *tp)
5ba3f43e
A
3352{
3353 int retval = 0;
cb323159 3354 int64_t data = 0;
5ba3f43e
A
3355
3356 TTY_LOCK_OWNED(tp); /* debug assert */
3357
cb323159
A
3358 switch (kn->kn_filter) {
3359 case EVFILT_READ:
3360 /*
3361 * ttnread can change the tty state,
3362 * hence must be done upfront, before any other check.
3363 */
3364 data = ttnread(tp);
3365 retval = (data != 0);
5ba3f43e 3366 break;
cb323159 3367 case EVFILT_WRITE:
5ba3f43e
A
3368 if ((tp->t_outq.c_cc <= tp->t_lowat) &&
3369 (tp->t_state & TS_CONNECTED)) {
cb323159
A
3370 data = tp->t_hiwat - tp->t_outq.c_cc;
3371 retval = (data != 0);
5ba3f43e
A
3372 }
3373 break;
cb323159
A
3374 default:
3375 panic("tty kevent: unexpected filter: %d, kn = %p, tty = %p",
3376 kn->kn_filter, kn, tp);
3377 break;
5ba3f43e
A
3378 }
3379
5ba3f43e
A
3380 /*
3381 * TODO(mwidmann, jandrus): For native knote low watermark support,
3382 * check the kn_sfflags for NOTE_LOWAT and check against kn_sdata.
3383 *
3384 * res = ((kn->kn_sfflags & NOTE_LOWAT) != 0) ?
3385 * (kn->kn_data >= kn->kn_sdata) : kn->kn_data;
3386 */
3387
cb323159
A
3388 if (tp->t_state & TS_ZOMBIE) {
3389 kn->kn_flags |= EV_EOF;
3390 }
3391 if (kn->kn_flags & EV_EOF) {
3392 retval = 1;
3393 }
3394 if (retval && kev) {
3395 knote_fill_kevent(kn, kev, data);
3396 }
3397
5ba3f43e
A
3398 return retval;
3399}
3400
3401/*
3402 * Find the struct tty from a waitq, which is a member of one of the two struct
3403 * selinfos inside the struct tty. Use the seltype to determine which selinfo.
3404 */
3405static struct tty *
3406tty_from_waitq(struct waitq *wq, int seltype)
3407{
3408 struct selinfo *si;
3409 struct tty *tp = NULL;
3410
3411 /*
3412 * The waitq is part of the selinfo structure managed by the driver. For
3413 * certain drivers, we want to hook the knote into the selinfo
3414 * structure's si_note field so selwakeup can call KNOTE.
3415 *
3416 * While 'wq' is not really a queue element, this macro only uses the
3417 * pointer to calculate the offset into a structure given an element
3418 * name.
3419 */
3420 si = qe_element(wq, struct selinfo, si_waitq);
3421
3422 /*
3423 * For TTY drivers, the selinfo structure is somewhere in the struct
3424 * tty. There are two different selinfo structures, and the one used
3425 * corresponds to the type of filter requested.
3426 *
3427 * While 'si' is not really a queue element, this macro only uses the
3428 * pointer to calculate the offset into a structure given an element
3429 * name.
3430 */
3431 switch (seltype) {
3432 case FREAD:
3433 tp = qe_element(si, struct tty, t_rsel);
3434 break;
3435 case FWRITE:
3436 tp = qe_element(si, struct tty, t_wsel);
3437 break;
3438 }
3439
3440 return tp;
3441}
3442
3443static struct tty *
3444tty_from_knote(struct knote *kn)
3445{
3446 return (struct tty *)kn->kn_hook;
3447}
3448
5ba3f43e
A
3449/*
3450 * Set the knote's struct tty to the kn_hook field.
3451 *
3452 * The idea is to fake a call to select with our own waitq set. If the driver
3453 * calls selrecord, we'll get a link to their waitq and access to the tty
3454 * structure.
3455 *
3456 * Returns -1 on failure, with the error set in the knote, or selres on success.
3457 */
3458static int
3459tty_set_knote_hook(struct knote *kn)
3460{
3461 uthread_t uth;
3462 vfs_context_t ctx;
3463 vnode_t vp;
3464 kern_return_t kr;
3465 struct waitq *wq = NULL;
3466 struct waitq_set *old_wqs;
3467 struct waitq_set tmp_wqs;
3468 uint64_t rsvd, rsvd_arg;
3469 uint64_t *rlptr = NULL;
3470 int selres = -1;
3471 struct tty *tp;
3472
3473 uth = get_bsdthread_info(current_thread());
3474
3475 ctx = vfs_context_current();
3476 vp = (vnode_t)kn->kn_fp->f_fglob->fg_data;
3477
3478 /*
3479 * Reserve a link element to avoid potential allocation under
3480 * a spinlock.
3481 */
3482 rsvd = rsvd_arg = waitq_link_reserve(NULL);
3483 rlptr = (void *)&rsvd_arg;
3484
3485 /*
3486 * Trick selrecord into hooking a known waitq set into the device's selinfo
3487 * waitq. Once the link is in place, we can get back into the selinfo from
3488 * the waitq and subsequently the tty (see tty_from_waitq).
3489 *
3490 * We can't use a real waitq set (such as the kqueue's) because wakeups
3491 * might happen before we can unlink it.
3492 */
3493 kr = waitq_set_init(&tmp_wqs, SYNC_POLICY_FIFO | SYNC_POLICY_PREPOST, NULL,
0a7de745 3494 NULL);
5ba3f43e
A
3495 assert(kr == KERN_SUCCESS);
3496
d9a64523
A
3497 /*
3498 * Lazy allocate the waitqset to avoid potential allocation under
3499 * a spinlock;
3500 */
3501 waitq_set_lazy_init_link(&tmp_wqs);
3502
5ba3f43e
A
3503 old_wqs = uth->uu_wqset;
3504 uth->uu_wqset = &tmp_wqs;
3505 /*
3506 * FMARK forces selects to always call selrecord, even if data is
3507 * available. See ttselect, ptsselect, ptcselect.
3508 *
3509 * selres also contains the data currently available in the tty.
3510 */
3511 selres = VNOP_SELECT(vp, knote_get_seltype(kn) | FMARK, 0, rlptr, ctx);
3512 uth->uu_wqset = old_wqs;
3513
3514 /*
3515 * Make sure to cleanup the reserved link - this guards against
3516 * drivers that may not actually call selrecord().
3517 */
3518 waitq_link_release(rsvd);
3519 if (rsvd == rsvd_arg) {
3520 /*
3521 * The driver didn't call selrecord -- there's no tty hooked up so we
3522 * can't attach.
3523 */
3524 knote_set_error(kn, ENOTTY);
3525 selres = -1;
3526 goto out;
3527 }
3528
3529 /* rlptr may not point to a properly aligned pointer */
3530 memcpy(&wq, rlptr, sizeof(void *));
3531
3532 tp = tty_from_waitq(wq, knote_get_seltype(kn));
3533 assert(tp != NULL);
3534
3535 /*
3536 * Take a reference and stash the tty in the knote.
3537 */
3538 tty_lock(tp);
3539 ttyhold(tp);
3540 kn->kn_hook = tp;
3541 tty_unlock(tp);
3542
3543out:
3544 /*
3545 * Cleaning up the wqset will unlink its waitq and clean up any preposts
3546 * that occurred as a result of data coming in while the tty was attached.
3547 */
3548 waitq_set_deinit(&tmp_wqs);
3549
3550 return selres;
3551}
3552
3553static int
cb323159 3554filt_ttyattach(struct knote *kn, __unused struct kevent_qos_s *kev)
5ba3f43e
A
3555{
3556 int selres = 0;
3557 struct tty *tp;
3558
3559 /*
3560 * This function should be called from filt_specattach (spec_vnops.c),
3561 * so most of the knote data structure should already be initialized.
3562 */
3563
3564 /* don't support offsets in ttys or drivers that don't use struct tty */
3565 if (kn->kn_vnode_use_ofst || !kn->kn_vnode_kqok) {
3566 knote_set_error(kn, ENOTSUP);
3567 return 0;
3568 }
3569
3570 /*
3571 * Connect the struct tty to the knote through the selinfo structure
3572 * referenced by the waitq within the selinfo.
3573 */
3574 selres = tty_set_knote_hook(kn);
3575 if (selres < 0) {
3576 return 0;
3577 }
3578
3579 /*
3580 * Attach the knote to selinfo's klist.
3581 */
cb323159
A
3582 tp = tty_from_knote(kn);
3583 tty_lock(tp);
5ba3f43e 3584
cb323159
A
3585 switch (kn->kn_filter) {
3586 case EVFILT_READ:
5ba3f43e
A
3587 KNOTE_ATTACH(&tp->t_rsel.si_note, kn);
3588 break;
cb323159 3589 case EVFILT_WRITE:
5ba3f43e
A
3590 KNOTE_ATTACH(&tp->t_wsel.si_note, kn);
3591 break;
cb323159
A
3592 default:
3593 panic("invalid knote %p attach, filter: %d", kn, kn->kn_filter);
5ba3f43e
A
3594 }
3595
3596 tty_unlock(tp);
3597
3598 return selres;
3599}
3600
3601static void
3602filt_ttydetach(struct knote *kn)
3603{
cb323159 3604 struct tty *tp = tty_from_knote(kn);
5ba3f43e 3605
cb323159 3606 tty_lock(tp);
5ba3f43e 3607
cb323159
A
3608 switch (kn->kn_filter) {
3609 case EVFILT_READ:
3610 KNOTE_DETACH(&tp->t_rsel.si_note, kn);
5ba3f43e 3611 break;
cb323159
A
3612 case EVFILT_WRITE:
3613 KNOTE_DETACH(&tp->t_wsel.si_note, kn);
3614 break;
3615 default:
3616 panic("invalid knote %p detach, filter: %d", kn, kn->kn_filter);
5ba3f43e 3617 break;
5ba3f43e
A
3618 }
3619
5ba3f43e
A
3620 tty_unlock(tp);
3621 ttyfree(tp);
3622}
3623
3624static int
3625filt_ttyevent(struct knote *kn, long hint)
3626{
cb323159 3627 struct tty *tp = tty_from_knote(kn);
5ba3f43e 3628 int ret;
5ba3f43e 3629
cb323159 3630 TTY_LOCK_OWNED(tp);
5ba3f43e 3631
cb323159 3632 if (hint & NOTE_REVOKE) {
5ba3f43e
A
3633 kn->kn_flags |= EV_EOF | EV_ONESHOT;
3634 ret = 1;
3635 } else {
cb323159 3636 ret = filt_tty_common(kn, NULL, tp);
5ba3f43e
A
3637 }
3638
3639 return ret;
3640}
3641
3642static int
cb323159 3643filt_ttytouch(struct knote *kn, struct kevent_qos_s *kev)
5ba3f43e 3644{
cb323159 3645 struct tty *tp = tty_from_knote(kn);
5ba3f43e
A
3646 int res = 0;
3647
cb323159 3648 tty_lock(tp);
5ba3f43e
A
3649
3650 kn->kn_sdata = kev->data;
3651 kn->kn_sfflags = kev->fflags;
5ba3f43e
A
3652
3653 if (kn->kn_vnode_kqok) {
cb323159 3654 res = filt_tty_common(kn, NULL, tp);
5ba3f43e
A
3655 }
3656
3657 tty_unlock(tp);
3658
3659 return res;
3660}
3661
3662static int
cb323159 3663filt_ttyprocess(struct knote *kn, struct kevent_qos_s *kev)
5ba3f43e 3664{
cb323159 3665 struct tty *tp = tty_from_knote(kn);
5ba3f43e
A
3666 int res;
3667
cb323159 3668 tty_lock(tp);
5ba3f43e 3669
cb323159 3670 res = filt_tty_common(kn, kev, tp);
5ba3f43e
A
3671
3672 tty_unlock(tp);
3673
3674 return res;
3675}