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