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