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