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