2 * Copyright (c) 1997-2007 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
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.
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
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.
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
65 * @(#)tty.c 8.8 (Berkeley) 1/21/94
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
75 * o Do the new sio locking stuff here and use it to avoid special
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
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().
94 #include <sys/param.h>
96 #include <sys/systm.h>
98 #include <sys/ioctl.h>
99 #include <sys/proc_internal.h>
100 #include <sys/kauth.h>
101 #include <sys/file_internal.h>
102 #include <sys/conf.h>
103 #include <sys/dkstat.h>
105 #include <sys/kernel.h>
106 #include <sys/vnode.h>
107 #include <sys/syslog.h>
108 #include <sys/user.h>
109 #include <sys/signalvar.h>
110 #include <sys/signalvar.h>
111 #include <sys/malloc.h>
113 #include <dev/kmreg_com.h>
114 #include <machine/cons.h>
115 #include <sys/resource.h> /* averunnable */
117 static int ttnread(struct tty
*tp
);
118 static void ttyecho(int c
, struct tty
*tp
);
119 static int ttyoutput(int c
, struct tty
*tp
);
120 static void ttypend(struct tty
*tp
);
121 static void ttyretype(struct tty
*tp
);
122 static void ttyrub(int c
, struct tty
*tp
);
123 static void ttyrubo(struct tty
*tp
, int count
);
124 static void ttystop(struct tty
*tp
, int rw
);
125 static void ttyunblock(struct tty
*tp
);
126 static int ttywflush(struct tty
*tp
);
127 static int proc_compare(proc_t p1
, proc_t p2
);
129 static int isctty(proc_t p
, struct tty
*tp
);
130 static int isctty_sp(proc_t p
, struct tty
*tp
, struct session
*sessp
);
133 * Table with character classes and parity. The 8th bit indicates parity,
134 * the 7th bit indicates the character is an alphameric or underscore (for
135 * ALTWERASE), and the low 6 bits indicate delay type. If the low 6 bits
136 * are 0 then the character needs no special processing on output; classes
137 * other than 0 might be translated or (not currently) require delays.
139 #define E 0x00 /* Even parity. */
140 #define O 0x80 /* Odd parity. */
141 #define PARITY(c) (char_type[c] & O)
143 #define ALPHA 0x40 /* Alpha or underscore. */
144 #define ISALPHA(c) (char_type[(c) & TTY_CHARMASK] & ALPHA)
146 #define CCLASSMASK 0x3f
147 #define CCLASS(c) (char_type[c] & CCLASSMASK)
148 /* 0b10xxxxxx is the mask for UTF-8 continuations */
149 #define CCONT(c) ((c & 0xc0) == 0x80)
154 #define NA ORDINARY | ALPHA
160 static u_char
const char_type
[] = {
161 E
|CC
, O
|CC
, O
|CC
, E
|CC
, O
|CC
, E
|CC
, E
|CC
, O
|CC
, /* nul - bel */
162 O
|BS
, E
|TB
, E
|NL
, O
|CC
, E
|VT
, O
|CR
, O
|CC
, E
|CC
, /* bs - si */
163 O
|CC
, E
|CC
, E
|CC
, O
|CC
, E
|CC
, O
|CC
, O
|CC
, E
|CC
, /* dle - etb */
164 E
|CC
, O
|CC
, O
|CC
, E
|CC
, O
|CC
, E
|CC
, E
|CC
, O
|CC
, /* can - us */
165 O
|NO
, E
|NO
, E
|NO
, O
|NO
, E
|NO
, O
|NO
, O
|NO
, E
|NO
, /* sp - ' */
166 E
|NO
, O
|NO
, O
|NO
, E
|NO
, O
|NO
, E
|NO
, E
|NO
, O
|NO
, /* ( - / */
167 E
|NA
, O
|NA
, O
|NA
, E
|NA
, O
|NA
, E
|NA
, E
|NA
, O
|NA
, /* 0 - 7 */
168 O
|NA
, E
|NA
, E
|NO
, O
|NO
, E
|NO
, O
|NO
, O
|NO
, E
|NO
, /* 8 - ? */
169 O
|NO
, E
|NA
, E
|NA
, O
|NA
, E
|NA
, O
|NA
, O
|NA
, E
|NA
, /* @ - G */
170 E
|NA
, O
|NA
, O
|NA
, E
|NA
, O
|NA
, E
|NA
, E
|NA
, O
|NA
, /* H - O */
171 E
|NA
, O
|NA
, O
|NA
, E
|NA
, O
|NA
, E
|NA
, E
|NA
, O
|NA
, /* P - W */
172 O
|NA
, E
|NA
, E
|NA
, O
|NO
, E
|NO
, O
|NO
, O
|NO
, O
|NA
, /* X - _ */
173 E
|NO
, O
|NA
, O
|NA
, E
|NA
, O
|NA
, E
|NA
, E
|NA
, O
|NA
, /* ` - g */
174 O
|NA
, E
|NA
, E
|NA
, O
|NA
, E
|NA
, O
|NA
, O
|NA
, E
|NA
, /* h - o */
175 O
|NA
, E
|NA
, E
|NA
, O
|NA
, E
|NA
, O
|NA
, O
|NA
, E
|NA
, /* p - w */
176 E
|NA
, O
|NA
, O
|NA
, E
|NO
, O
|NO
, E
|NO
, E
|NO
, O
|CC
, /* x - del */
178 * Meta chars; should be settable per character set;
179 * for now, treat them all as normal characters.
181 NA
, NA
, NA
, NA
, NA
, NA
, NA
, NA
,
182 NA
, NA
, NA
, NA
, NA
, NA
, NA
, NA
,
183 NA
, NA
, NA
, NA
, NA
, NA
, NA
, NA
,
184 NA
, NA
, NA
, NA
, NA
, NA
, NA
, NA
,
185 NA
, NA
, NA
, NA
, NA
, NA
, NA
, NA
,
186 NA
, NA
, NA
, NA
, NA
, NA
, NA
, NA
,
187 NA
, NA
, NA
, NA
, NA
, NA
, NA
, NA
,
188 NA
, NA
, NA
, NA
, NA
, NA
, NA
, NA
,
189 NA
, NA
, NA
, NA
, NA
, NA
, NA
, NA
,
190 NA
, NA
, NA
, NA
, NA
, NA
, NA
, NA
,
191 NA
, NA
, NA
, NA
, NA
, NA
, NA
, NA
,
192 NA
, NA
, NA
, NA
, NA
, NA
, NA
, NA
,
193 NA
, NA
, NA
, NA
, NA
, NA
, NA
, NA
,
194 NA
, NA
, NA
, NA
, NA
, NA
, NA
, NA
,
195 NA
, NA
, NA
, NA
, NA
, NA
, NA
, NA
,
196 NA
, NA
, NA
, NA
, NA
, NA
, NA
, NA
,
207 /* Macros to clear/set/test flags. */
208 #define SET(t, f) (t) |= (f)
209 #define CLR(t, f) (t) &= ~(f)
210 #define ISSET(t, f) ((t) & (f))
213 * Input control starts when we would not be able to fit the maximum
214 * contents of the ping-pong buffers and finishes when we would be able
215 * to fit that much plus 1/8 more.
217 #define I_HIGH_WATER (TTYHOG - 2 * 256) /* XXX */
218 #define I_LOW_WATER ((TTYHOG - 2 * 256) * 7 / 8) /* XXX */
221 termios32to64(struct termios
*in
, struct user_termios
*out
)
223 out
->c_iflag
= (user_tcflag_t
)in
->c_iflag
;
224 out
->c_oflag
= (user_tcflag_t
)in
->c_oflag
;
225 out
->c_cflag
= (user_tcflag_t
)in
->c_cflag
;
226 out
->c_lflag
= (user_tcflag_t
)in
->c_lflag
;
228 /* bcopy is OK, since this type is ILP32/LP64 size invariant */
229 bcopy(in
->c_cc
, out
->c_cc
, sizeof(in
->c_cc
));
231 out
->c_ispeed
= (user_speed_t
)in
->c_ispeed
;
232 out
->c_ospeed
= (user_speed_t
)in
->c_ospeed
;
236 termios64to32(struct user_termios
*in
, struct termios
*out
)
238 out
->c_iflag
= (tcflag_t
)in
->c_iflag
;
239 out
->c_oflag
= (tcflag_t
)in
->c_oflag
;
240 out
->c_cflag
= (tcflag_t
)in
->c_cflag
;
241 out
->c_lflag
= (tcflag_t
)in
->c_lflag
;
243 /* bcopy is OK, since this type is ILP32/LP64 size invariant */
244 bcopy(in
->c_cc
, out
->c_cc
, sizeof(in
->c_cc
));
246 out
->c_ispeed
= (speed_t
)in
->c_ispeed
;
247 out
->c_ospeed
= (speed_t
)in
->c_ospeed
;
252 * Initial open of tty, or (re)entry to standard tty line discipline.
255 ttyopen(dev_t device
, struct tty
*tp
)
257 boolean_t funnel_state
;
258 proc_t p
= current_proc();
259 struct pgrp
* pg
, * oldpg
;
260 struct session
*sessp
, *oldsess
;
262 funnel_state
= thread_funnel_set(kernel_flock
, TRUE
);
266 if (!ISSET(tp
->t_state
, TS_ISOPEN
)) {
267 SET(tp
->t_state
, TS_ISOPEN
);
268 if (ISSET(tp
->t_cflag
, CLOCAL
)) {
269 SET(tp
->t_state
, TS_CONNECTED
); }
270 bzero(&tp
->t_winsize
, sizeof(tp
->t_winsize
));
274 sessp
= proc_session(p
);
277 * First tty open affter setsid() call makes this tty its controlling
278 * tty, if the tty does not already have a session associated with it.
279 * Only do this if the process
281 if (SESS_LEADER(p
, sessp
) && /* process is session leader */
282 sessp
->s_ttyvp
== NULL
&& /* but has no controlling tty */
283 tp
->t_session
== NULL
) { /* and tty not controlling */
285 if ((sessp
->s_flags
& S_NOCTTY
) == 0) { /* and no O_NOCTTY */
286 /* Hold on to the reference */
288 OSBitOrAtomic(P_CONTROLT
, (UInt32
*)&p
->p_flag
);
289 session_unlock(sessp
);
292 oldsess
= tp
->t_session
;
293 if (oldsess
!= SESSION_NULL
)
294 oldsess
->s_ttypgrpid
= NO_PID
;
295 tp
->t_session
= sessp
;
297 sessp
->s_ttypgrpid
= pg
->pg_id
;
299 if (oldpg
!= PGRP_NULL
)
301 if (oldsess
!= SESSION_NULL
)
302 session_rele(oldsess
);
305 session_unlock(sessp
);
308 if (sessp
!= SESSION_NULL
)
314 thread_funnel_set(kernel_flock
, funnel_state
);
320 * Handle close() on a tty line: flush and set to initial state,
321 * bumping generation number so that pending read/write calls
322 * can detect recycling of the tty.
323 * XXX our caller should have done `spltty(); l_close(); ttyclose();'
324 * and l_close() should have flushed, but we repeat the spltty() and
325 * the flush in case there are buggy callers.
328 ttyclose(struct tty
*tp
)
331 struct session
* oldsessp
;
338 * Closing current console tty; disable printing of console
339 * messages at bottom-level driver.
341 (*cdevsw
[major(tp
->t_dev
)].d_ioctl
)
342 (tp
->t_dev
, KMIOCDISABLCONS
, NULL
, 0, current_proc());
345 ttyflush(tp
, FREAD
| FWRITE
);
348 tp
->t_line
= TTYDISC
;
351 oldsessp
= tp
->t_session
;
353 tp
->t_session
= NULL
;
354 if (oldsessp
!= SESSION_NULL
)
355 oldsessp
->s_ttypgrpid
= NO_PID
;
357 /* drop the reference on prev session and pgrp */
358 if (oldsessp
!= SESSION_NULL
)
359 session_rele(oldsessp
);
360 if (oldpg
!= PGRP_NULL
)
363 selthreadclear(&tp
->t_wsel
);
364 selthreadclear(&tp
->t_rsel
);
368 #define FLUSHQ(q) { \
370 ndflush(q, (q)->c_cc); \
373 /* Is 'c' a line delimiter ("break" character)? */
374 #define TTBREAKC(c, lflag) \
375 ((c) == '\n' || (((c) == cc[VEOF] || \
376 (c) == cc[VEOL] || ((c) == cc[VEOL2] && lflag & IEXTEN)) && \
377 (c) != _POSIX_VDISABLE))
380 * Process input of a single character received on a tty.
383 ttyinput(int c
, struct tty
*tp
)
385 tcflag_t iflag
, lflag
;
388 boolean_t funnel_state
;
390 funnel_state
= thread_funnel_set(kernel_flock
, TRUE
);
393 * If input is pending take it first.
396 if (ISSET(lflag
, PENDIN
))
401 if (ISSET(lflag
, ICANON
)) {
411 * Block further input iff:
412 * current input > threshold AND input is available to user program
413 * AND input flow control is enabled and not yet invoked.
414 * The 3 is slop for PARMRK.
417 if (tp
->t_rawq
.c_cc
+ tp
->t_canq
.c_cc
> I_HIGH_WATER
- 3 &&
418 (!ISSET(lflag
, ICANON
) || tp
->t_canq
.c_cc
!= 0) &&
419 (ISSET(tp
->t_cflag
, CRTS_IFLOW
) || ISSET(iflag
, IXOFF
)) &&
420 !ISSET(tp
->t_state
, TS_TBLOCK
))
423 /* Handle exceptional conditions (break, parity, framing). */
425 err
= (ISSET(c
, TTY_ERRORMASK
));
427 CLR(c
, TTY_ERRORMASK
);
428 if (ISSET(err
, TTY_BI
)) {
429 if (ISSET(iflag
, IGNBRK
)) {
430 thread_funnel_set(kernel_flock
, funnel_state
);
433 if (ISSET(iflag
, BRKINT
)) {
434 ttyflush(tp
, FREAD
| FWRITE
);
435 tty_pgsignal(tp
, SIGINT
, 1);
438 if (ISSET(iflag
, PARMRK
))
440 } else if ((ISSET(err
, TTY_PE
) && ISSET(iflag
, INPCK
))
441 || ISSET(err
, TTY_FE
)) {
442 if (ISSET(iflag
, IGNPAR
)) {
443 thread_funnel_set(kernel_flock
, funnel_state
);
446 else if (ISSET(iflag
, PARMRK
)) {
448 if (tp
->t_rawq
.c_cc
+ tp
->t_canq
.c_cc
>
451 (void)putc(0377 | TTY_QUOTE
, &tp
->t_rawq
);
452 (void)putc(0 | TTY_QUOTE
, &tp
->t_rawq
);
453 (void)putc(c
| TTY_QUOTE
, &tp
->t_rawq
);
460 if (!ISSET(tp
->t_state
, TS_TYPEN
) && ISSET(iflag
, ISTRIP
))
462 if (!ISSET(lflag
, EXTPROC
)) {
464 * Check for literal nexting very first
466 if (ISSET(tp
->t_state
, TS_LNCH
)) {
468 CLR(tp
->t_state
, TS_LNCH
);
471 * Scan for special characters. This code
472 * is really just a big case statement with
473 * non-constant cases. The bottom of the
474 * case statement is labeled ``endcase'', so goto
475 * it after a case match, or similar.
479 * Control chars which aren't controlled
480 * by ICANON, ISIG, or IXON.
482 if (ISSET(lflag
, IEXTEN
)) {
483 if (CCEQ(cc
[VLNEXT
], c
)) {
484 if (ISSET(lflag
, ECHO
)) {
485 if (ISSET(lflag
, ECHOE
)) {
486 (void)ttyoutput('^', tp
);
487 (void)ttyoutput('\b', tp
);
491 SET(tp
->t_state
, TS_LNCH
);
494 if (CCEQ(cc
[VDISCARD
], c
)) {
495 if (ISSET(lflag
, FLUSHO
))
496 CLR(tp
->t_lflag
, FLUSHO
);
498 ttyflush(tp
, FWRITE
);
500 if (tp
->t_rawq
.c_cc
+ tp
->t_canq
.c_cc
)
502 SET(tp
->t_lflag
, FLUSHO
);
510 if (ISSET(lflag
, ISIG
)) {
511 if (CCEQ(cc
[VINTR
], c
) || CCEQ(cc
[VQUIT
], c
)) {
512 if (!ISSET(lflag
, NOFLSH
))
513 ttyflush(tp
, FREAD
| FWRITE
);
516 CCEQ(cc
[VINTR
], c
) ? SIGINT
: SIGQUIT
, 1);
519 if (CCEQ(cc
[VSUSP
], c
)) {
520 if (!ISSET(lflag
, NOFLSH
))
523 tty_pgsignal(tp
, SIGTSTP
, 1);
528 * Handle start/stop characters.
530 if (ISSET(iflag
, IXON
)) {
531 if (CCEQ(cc
[VSTOP
], c
)) {
532 if (!ISSET(tp
->t_state
, TS_TTSTOP
)) {
533 SET(tp
->t_state
, TS_TTSTOP
);
535 thread_funnel_set(kernel_flock
, funnel_state
);
538 if (!CCEQ(cc
[VSTART
], c
)) {
539 thread_funnel_set(kernel_flock
, funnel_state
);
543 * if VSTART == VSTOP then toggle
547 if (CCEQ(cc
[VSTART
], c
))
551 * IGNCR, ICRNL, & INLCR
554 if (ISSET(iflag
, IGNCR
)) {
555 thread_funnel_set(kernel_flock
, funnel_state
);
558 else if (ISSET(iflag
, ICRNL
))
560 } else if (c
== '\n' && ISSET(iflag
, INLCR
))
563 if (!ISSET(tp
->t_lflag
, EXTPROC
) && ISSET(lflag
, ICANON
)) {
565 * From here on down canonical mode character
566 * processing takes place.
571 if (CCEQ(cc
[VERASE
], c
)) {
572 if (tp
->t_rawq
.c_cc
) {
573 if (ISSET(iflag
, IUTF8
)) {
575 ttyrub((c
= unputc(&tp
->t_rawq
)), tp
);
576 } while(tp
->t_rawq
.c_cc
&& CCONT(c
));
578 ttyrub(unputc(&tp
->t_rawq
), tp
);
586 if (CCEQ(cc
[VKILL
], c
)) {
587 if (ISSET(lflag
, ECHOKE
) &&
588 tp
->t_rawq
.c_cc
== tp
->t_rocount
&&
589 !ISSET(lflag
, ECHOPRT
))
590 while (tp
->t_rawq
.c_cc
)
591 ttyrub(unputc(&tp
->t_rawq
), tp
);
594 if (ISSET(lflag
, ECHOK
) ||
595 ISSET(lflag
, ECHOKE
))
600 CLR(tp
->t_state
, TS_LOCAL
);
606 if (CCEQ(cc
[VWERASE
], c
) && ISSET(lflag
, IEXTEN
)) {
612 while ((c
= unputc(&tp
->t_rawq
)) == ' ' || c
== '\t')
617 * erase last char of word and remember the
618 * next chars type (for ALTWERASE)
621 c
= unputc(&tp
->t_rawq
);
624 if (c
== ' ' || c
== '\t') {
625 (void)putc(c
, &tp
->t_rawq
);
634 c
= unputc(&tp
->t_rawq
);
637 } while (c
!= ' ' && c
!= '\t' &&
638 (!ISSET(lflag
, ALTWERASE
) || ISALPHA(c
) == ctype
));
639 (void)putc(c
, &tp
->t_rawq
);
645 if (CCEQ(cc
[VREPRINT
], c
) && ISSET(lflag
, IEXTEN
)) {
650 * ^T - kernel info and generate SIGINFO
652 if (CCEQ(cc
[VSTATUS
], c
) && ISSET(lflag
, IEXTEN
)) {
653 if (ISSET(lflag
, ISIG
))
654 tty_pgsignal(tp
, SIGINFO
, 1);
655 if (!ISSET(lflag
, NOKERNINFO
))
661 * Check for input buffer overflow
663 if (tp
->t_rawq
.c_cc
+ tp
->t_canq
.c_cc
>= MAX_INPUT
) {
665 if (ISSET(iflag
, IMAXBEL
)) {
666 if (tp
->t_outq
.c_cc
< tp
->t_hiwat
)
667 (void)ttyoutput(CTRL('g'), tp
);
672 if ( c
== 0377 && ISSET(iflag
, PARMRK
) && !ISSET(iflag
, ISTRIP
)
673 && ISSET(iflag
, IGNBRK
|IGNPAR
) != (IGNBRK
|IGNPAR
))
674 (void)putc(0377 | TTY_QUOTE
, &tp
->t_rawq
);
677 * Put data char in q for user and
678 * wakeup on seeing a line delimiter.
680 if (putc(c
, &tp
->t_rawq
) >= 0) {
681 if (!ISSET(lflag
, ICANON
)) {
686 if (TTBREAKC(c
, lflag
)) {
688 catq(&tp
->t_rawq
, &tp
->t_canq
);
690 } else if (tp
->t_rocount
++ == 0)
691 tp
->t_rocol
= tp
->t_column
;
692 if (ISSET(tp
->t_state
, TS_ERASE
)) {
694 * end of prterase \.../
696 CLR(tp
->t_state
, TS_ERASE
);
697 (void)ttyoutput('/', tp
);
701 if (CCEQ(cc
[VEOF
], c
) && ISSET(lflag
, ECHO
)) {
703 * Place the cursor over the '^' of the ^D.
705 i
= min(2, tp
->t_column
- i
);
707 (void)ttyoutput('\b', tp
);
714 * IXANY means allow any character to restart output.
716 if (ISSET(tp
->t_state
, TS_TTSTOP
) &&
717 !ISSET(iflag
, IXANY
) && cc
[VSTART
] != cc
[VSTOP
]) {
718 thread_funnel_set(kernel_flock
, funnel_state
);
722 CLR(tp
->t_lflag
, FLUSHO
);
723 CLR(tp
->t_state
, TS_TTSTOP
);
725 retval
= ttstart(tp
);
726 thread_funnel_set(kernel_flock
, funnel_state
);
731 * Output a single character on a tty, doing output processing
732 * as needed (expanding tabs, newline processing, etc.).
733 * Returns < 0 if succeeds, otherwise returns char to resend.
737 ttyoutput(int c
, struct tty
*tp
)
743 if (!ISSET(oflag
, OPOST
)) {
744 if (ISSET(tp
->t_lflag
, FLUSHO
))
746 if (putc(c
, &tp
->t_outq
))
753 * Do tab expansion if OXTABS is set. Special case if we external
754 * processing, we don't do the tab expansion because we'll probably
755 * get it wrong. If tab expansion needs to be done, let it happen
758 CLR(c
, ~TTY_CHARMASK
);
760 ISSET(oflag
, OXTABS
) && !ISSET(tp
->t_lflag
, EXTPROC
)) {
761 col
= c
= 8 - (tp
->t_column
& 7);
762 if (!ISSET(tp
->t_lflag
, FLUSHO
)) {
763 c
-= b_to_q((const u_char
*)" ", c
, &tp
->t_outq
);
768 return (c
== col
? -1 : '\t');
770 if (c
== CEOT
&& ISSET(oflag
, ONOEOT
))
774 * Newline translation: if ONLCR is set,
775 * translate newline into "\r\n".
777 if (c
== '\n' && ISSET(tp
->t_oflag
, ONLCR
)) {
780 if (putc('\r', &tp
->t_outq
))
783 /* If OCRNL is set, translate "\r" into "\n". */
784 else if (c
== '\r' && ISSET(tp
->t_oflag
, OCRNL
))
786 /* If ONOCR is set, don't transmit CRs when on column 0. */
787 else if (c
== '\r' && ISSET(tp
->t_oflag
, ONOCR
) && tp
->t_column
== 0)
791 if (!ISSET(tp
->t_lflag
, FLUSHO
) && putc(c
, &tp
->t_outq
))
810 col
= (col
+ 8) & ~7;
818 * Ioctls for all tty devices. Called after line-discipline specific ioctl
819 * has been called to do discipline-specific functions and/or reject any
820 * of these ioctl commands.
823 ttioctl(struct tty
*tp
,
824 u_long cmd
, caddr_t data
, int flag
,
829 struct pgrp
* pg
, *oldpg
;
830 struct session
*sessp
, * oldsessp
;
832 ut
= (struct uthread
*)get_bsdthread_info(current_thread());
833 /* If the ioctl involves modification, signal if in the background. */
852 #if COMPAT_43_TTY || defined(COMPAT_SUNOS)
862 while (isbackground(p
, tp
) &&
863 (p
->p_lflag
& P_LPPWAIT
) == 0 &&
864 (p
->p_sigignore
& sigmask(SIGTTOU
)) == 0 &&
865 (ut
->uu_sigmask
& sigmask(SIGTTOU
)) == 0) {
867 if (pg
== PGRP_NULL
) {
871 if (pg
->pg_jobc
== 0) {
876 pgsignal(pg
, SIGTTOU
, 1);
881 * We signalled ourself, so we need to act as if we
882 * have been "interrupted" from a "sleep" to act on
883 * the signal. If it's a signal that stops the
884 * process, that's handled in the signal sending code.
892 switch (cmd
) { /* Process the ioctl. */
893 case FIOASYNC
: /* set/clear async i/o */
895 SET(tp
->t_state
, TS_ASYNC
);
897 CLR(tp
->t_state
, TS_ASYNC
);
899 case FIONBIO
: /* set/clear non-blocking i/o */
900 break; /* XXX: delete. */
901 case FIONREAD
: /* get # bytes to read */
902 *(int *)data
= ttnread(tp
);
904 case TIOCEXCL
: /* set exclusive use of tty */
905 SET(tp
->t_state
, TS_XCLUDE
);
907 case TIOCFLUSH
: { /* flush buffers */
908 int flags
= *(int *)data
;
911 flags
= FREAD
| FWRITE
;
913 flags
&= FREAD
| FWRITE
;
918 /* Set current console device to this line */
920 data
= (caddr_t
) &bogusData
;
922 /* No break - Fall through to BSD code */
924 case TIOCCONS
: { /* become virtual console */
926 if (constty
&& constty
!= tp
&&
927 ISSET(constty
->t_state
, TS_CONNECTED
)) {
931 if ( (error
= suser(kauth_cred_get(), &p
->p_acflag
)) )
934 } else if (tp
== constty
) {
938 (*cdevsw
[major(cons
.t_dev
)].d_ioctl
)
939 (cons
.t_dev
, KMIOCDISABLCONS
, NULL
, 0, p
);
941 (*cdevsw
[major(tp
->t_dev
)].d_ioctl
)
942 (tp
->t_dev
, KMIOCDISABLCONS
, NULL
, 0, p
);
946 case TIOCDRAIN
: /* wait till output drained */
951 case TIOCGETA
: /* get termios struct */
952 case TIOCGETA_64
: { /* get termios struct */
953 if (IS_64BIT_PROCESS(p
)) {
954 termios32to64(&tp
->t_termios
, (struct user_termios
*)data
);
956 bcopy(&tp
->t_termios
, data
, sizeof(struct termios
));
960 case TIOCGETD
: /* get line discipline */
961 *(int *)data
= tp
->t_line
;
963 case TIOCGWINSZ
: /* get window size */
964 *(struct winsize
*)data
= tp
->t_winsize
;
966 case TIOCGPGRP
: /* get pgrp of tty */
967 if (!isctty(p
, tp
)) {
971 *(int *)data
= tp
->t_pgrp
? tp
->t_pgrp
->pg_id
: NO_PID
;
974 case TIOCHPCL
: /* hang up on last close */
975 SET(tp
->t_cflag
, HUPCL
);
978 case TIOCNXCL
: /* reset exclusive use of tty */
979 CLR(tp
->t_state
, TS_XCLUDE
);
981 case TIOCOUTQ
: /* output queue size */
982 *(int *)data
= tp
->t_outq
.c_cc
;
984 case TIOCSETA
: /* set termios struct */
986 case TIOCSETAW
: /* drain output, set */
988 case TIOCSETAF
: /* drn out, fls in, set */
989 case TIOCSETAF_64
: { /* drn out, fls in, set */
990 struct termios
*t
= (struct termios
*)data
;
991 struct termios lcl_termios
;
993 if (IS_64BIT_PROCESS(p
)) {
994 termios64to32((struct user_termios
*)data
, &lcl_termios
);
998 /* XXX bogus test; always false */
999 if (t
->c_ispeed
< 0 || t
->c_ospeed
< 0) {
1003 #endif /* 0 - leave in; may end up being a conformance issue */
1004 if (t
->c_ispeed
== 0)
1005 t
->c_ispeed
= t
->c_ospeed
;
1006 if (cmd
== TIOCSETAW
|| cmd
== TIOCSETAF
||
1007 cmd
== TIOCSETAW_64
|| cmd
== TIOCSETAF_64
) {
1008 error
= ttywait(tp
);
1012 if (cmd
== TIOCSETAF
|| cmd
== TIOCSETAF_64
)
1013 ttyflush(tp
, FREAD
);
1015 if (!ISSET(t
->c_cflag
, CIGNORE
)) {
1017 * Set device hardware.
1019 if (tp
->t_param
&& (error
= (*tp
->t_param
)(tp
, t
))) {
1022 if (ISSET(t
->c_cflag
, CLOCAL
) &&
1023 !ISSET(tp
->t_cflag
, CLOCAL
)) {
1025 * XXX disconnections would be too hard to
1026 * get rid of without this kludge. The only
1027 * way to get rid of controlling terminals
1028 * is to exit from the session leader.
1030 CLR(tp
->t_state
, TS_ZOMBIE
);
1032 wakeup(TSA_CARR_ON(tp
));
1036 if ((ISSET(tp
->t_state
, TS_CARR_ON
) ||
1037 ISSET(t
->c_cflag
, CLOCAL
)) &&
1038 !ISSET(tp
->t_state
, TS_ZOMBIE
))
1039 SET(tp
->t_state
, TS_CONNECTED
);
1041 CLR(tp
->t_state
, TS_CONNECTED
);
1042 tp
->t_cflag
= t
->c_cflag
;
1043 tp
->t_ispeed
= t
->c_ispeed
;
1044 tp
->t_ospeed
= t
->c_ospeed
;
1047 if (ISSET(t
->c_lflag
, ICANON
) != ISSET(tp
->t_lflag
, ICANON
) &&
1048 cmd
!= TIOCSETAF
&& cmd
!= TIOCSETAF_64
) {
1049 if (ISSET(t
->c_lflag
, ICANON
))
1050 SET(tp
->t_lflag
, PENDIN
);
1053 * XXX we really shouldn't allow toggling
1054 * ICANON while we're in a non-termios line
1055 * discipline. Now we have to worry about
1056 * panicing for a null queue.
1058 if (tp
->t_rawq
.c_cs
&& tp
->t_canq
.c_cs
) {
1061 catq(&tp
->t_rawq
, &tp
->t_canq
);
1063 tp
->t_rawq
= tp
->t_canq
;
1066 CLR(tp
->t_lflag
, PENDIN
);
1070 tp
->t_iflag
= t
->c_iflag
;
1071 tp
->t_oflag
= t
->c_oflag
;
1073 * Make the EXTPROC bit read only.
1075 if (ISSET(tp
->t_lflag
, EXTPROC
))
1076 SET(t
->c_lflag
, EXTPROC
);
1078 CLR(t
->c_lflag
, EXTPROC
);
1079 tp
->t_lflag
= t
->c_lflag
| ISSET(tp
->t_lflag
, PENDIN
);
1080 if (t
->c_cc
[VMIN
] != tp
->t_cc
[VMIN
] ||
1081 t
->c_cc
[VTIME
] != tp
->t_cc
[VTIME
])
1083 bcopy(t
->c_cc
, tp
->t_cc
, sizeof(t
->c_cc
));
1086 case TIOCSETD
: { /* set line discipline */
1087 int t
= *(int *)data
;
1088 dev_t device
= tp
->t_dev
;
1090 if (t
>= nlinesw
|| t
< 0) {
1094 if (t
!= tp
->t_line
) {
1095 (*linesw
[tp
->t_line
].l_close
)(tp
, flag
);
1096 error
= (*linesw
[t
].l_open
)(device
, tp
);
1098 (void)(*linesw
[tp
->t_line
].l_open
)(device
, tp
);
1105 case TIOCSTART
: /* start output, like ^Q */
1106 if (ISSET(tp
->t_state
, TS_TTSTOP
) ||
1107 ISSET(tp
->t_lflag
, FLUSHO
)) {
1108 CLR(tp
->t_lflag
, FLUSHO
);
1109 CLR(tp
->t_state
, TS_TTSTOP
);
1113 case TIOCSTI
: /* simulate terminal input */
1114 if (suser(kauth_cred_get(), NULL
) && (flag
& FREAD
) == 0) {
1118 if (suser(kauth_cred_get(), NULL
) && !isctty(p
, tp
)) {
1122 (*linesw
[tp
->t_line
].l_rint
)(*(u_char
*)data
, tp
);
1124 case TIOCSTOP
: /* stop output, like ^S */
1125 if (!ISSET(tp
->t_state
, TS_TTSTOP
)) {
1126 SET(tp
->t_state
, TS_TTSTOP
);
1136 case TIOCSCTTY
: /* become controlling tty */
1137 /* Session ctty vnode pointer set in vnode layer. */
1139 sessp
= proc_session(p
);
1140 if (!SESS_LEADER(p
, sessp
) ||
1141 ((sessp
->s_ttyvp
|| tp
->t_session
) &&
1142 (tp
->t_session
!= sessp
))) {
1143 if (sessp
!= SESSION_NULL
)
1144 session_rele(sessp
);
1145 if (pg
!= PGRP_NULL
)
1151 oldsessp
= tp
->t_session
;
1153 if (oldsessp
!= SESSION_NULL
)
1154 oldsessp
->s_ttypgrpid
= NO_PID
;
1155 /* do not drop refs on sessp and pg as tp holds them */
1156 tp
->t_session
= sessp
;
1157 sessp
->s_ttypgrpid
= pg
->pg_id
;
1160 session_lock(sessp
);
1162 session_unlock(sessp
);
1163 OSBitOrAtomic(P_CONTROLT
, (UInt32
*)&p
->p_flag
);
1164 /* drop the reference on prev session and pgrp */
1165 if (oldsessp
!= SESSION_NULL
)
1166 session_rele(oldsessp
);
1167 if (oldpg
!= PGRP_NULL
)
1171 case TIOCSPGRP
: { /* set pgrp of tty */
1172 struct pgrp
*pgrp
= PGRP_NULL
;
1174 sessp
= proc_session(p
);
1175 if (!isctty_sp(p
, tp
, sessp
)) {
1176 if (sessp
!= SESSION_NULL
)
1177 session_rele(sessp
);
1181 else if ((pgrp
= pgfind(*(int *)data
)) == PGRP_NULL
) {
1182 if (sessp
!= SESSION_NULL
)
1183 session_rele(sessp
);
1186 } else if (pgrp
->pg_session
!= sessp
) {
1187 if (sessp
!= SESSION_NULL
)
1188 session_rele(sessp
);
1196 sessp
->s_ttypgrpid
= pgrp
->pg_id
;
1198 if (oldpg
!= PGRP_NULL
)
1200 if (sessp
!= SESSION_NULL
)
1201 session_rele(sessp
);
1204 case TIOCSTAT
: /* simulate control-T */
1207 case TIOCSWINSZ
: /* set window size */
1208 if (bcmp((caddr_t
)&tp
->t_winsize
, data
,
1209 sizeof (struct winsize
))) {
1210 tp
->t_winsize
= *(struct winsize
*)data
;
1211 tty_pgsignal(tp
, SIGWINCH
, 1);
1214 case TIOCSDRAINWAIT
:
1215 error
= suser(kauth_cred_get(), &p
->p_acflag
);
1219 tp
->t_timeout
= *(int *)data
* hz
;
1220 wakeup(TSA_OCOMPLETE(tp
));
1221 wakeup(TSA_OLOWAT(tp
));
1223 case TIOCGDRAINWAIT
:
1224 *(int *)data
= tp
->t_timeout
/ hz
;
1227 #if COMPAT_43_TTY || defined(COMPAT_SUNOS)
1228 error
= ttcompat(tp
, cmd
, data
, flag
, p
);
1241 ttyselect(struct tty
*tp
, int rw
, void *wql
, proc_t p
)
1248 if (ttnread(tp
) > 0 || ISSET(tp
->t_state
, TS_ZOMBIE
))
1250 selrecord(p
, &tp
->t_rsel
, wql
);
1253 if ((tp
->t_outq
.c_cc
<= tp
->t_lowat
&&
1254 ISSET(tp
->t_state
, TS_CONNECTED
))
1255 || ISSET(tp
->t_state
, TS_ZOMBIE
)) {
1258 selrecord(p
, &tp
->t_wsel
, wql
);
1265 * This is a wrapper for compatibility with the select vector used by
1266 * cdevsw. It relies on a proper xxxdevtotty routine.
1269 ttselect(dev_t dev
, int rw
, void *wql
, proc_t p
)
1271 return ttyselect(cdevsw
[major(dev
)].d_ttys
[minor(dev
)], rw
, wql
, p
);
1275 * Must be called at spltty().
1278 ttnread(struct tty
*tp
)
1282 if (ISSET(tp
->t_lflag
, PENDIN
))
1284 nread
= tp
->t_canq
.c_cc
;
1285 if (!ISSET(tp
->t_lflag
, ICANON
)) {
1286 nread
+= tp
->t_rawq
.c_cc
;
1287 if (nread
< tp
->t_cc
[VMIN
] && tp
->t_cc
[VTIME
] == 0)
1294 * Wait for output to drain.
1297 ttywait(struct tty
*tp
)
1302 while ((tp
->t_outq
.c_cc
|| ISSET(tp
->t_state
, TS_BUSY
)) &&
1303 ISSET(tp
->t_state
, TS_CONNECTED
) && tp
->t_oproc
) {
1305 if ((tp
->t_outq
.c_cc
|| ISSET(tp
->t_state
, TS_BUSY
)) &&
1306 ISSET(tp
->t_state
, TS_CONNECTED
)) {
1307 SET(tp
->t_state
, TS_SO_OCOMPLETE
);
1308 error
= ttysleep(tp
, TSA_OCOMPLETE(tp
),
1309 TTOPRI
| PCATCH
, "ttywai",
1312 if (error
== EWOULDBLOCK
)
1319 if (!error
&& (tp
->t_outq
.c_cc
|| ISSET(tp
->t_state
, TS_BUSY
)))
1325 ttystop(struct tty
*tp
, int rw
)
1327 (*cdevsw
[major(tp
->t_dev
)].d_stop
)(tp
, rw
);
1331 * Flush if successfully wait.
1334 ttywflush(struct tty
*tp
)
1338 if ((error
= ttywait(tp
)) == 0)
1339 ttyflush(tp
, FREAD
);
1344 * Flush tty read and/or write queues, notifying anyone waiting.
1347 ttyflush(struct tty
*tp
, int rw
)
1353 FLUSHQ(&tp
->t_outq
);
1354 CLR(tp
->t_state
, TS_TTSTOP
);
1358 FLUSHQ(&tp
->t_canq
);
1359 FLUSHQ(&tp
->t_rawq
);
1360 CLR(tp
->t_lflag
, PENDIN
);
1363 CLR(tp
->t_state
, TS_LOCAL
);
1365 if (ISSET(tp
->t_state
, TS_TBLOCK
)) {
1367 FLUSHQ(&tp
->t_outq
);
1371 * Don't let leave any state that might clobber the
1372 * next line discipline (although we should do more
1373 * to send the START char). Not clearing the state
1374 * may have caused the "putc to a clist with no
1375 * reserved cblocks" panic/printf.
1377 CLR(tp
->t_state
, TS_TBLOCK
);
1379 #if 0 /* forget it, sleeping isn't always safe and we don't know when it is */
1380 if (ISSET(tp
->t_iflag
, IXOFF
)) {
1382 * XXX wait a bit in the hope that the stop
1383 * character (if any) will go out. Waiting
1384 * isn't good since it allows races. This
1385 * will be fixed when the stop character is
1386 * put in a special queue. Don't bother with
1387 * the checks in ttywait() since the timeout
1390 SET(tp
->t_state
, TS_SO_OCOMPLETE
);
1391 ttysleep(tp
, TSA_OCOMPLETE(tp
), TTOPRI
,
1394 * Don't try sending the stop character again.
1396 CLR(tp
->t_state
, TS_TBLOCK
);
1403 FLUSHQ(&tp
->t_outq
);
1409 * Copy in the default termios characters.
1412 termioschars(struct termios
*t
)
1414 bcopy(ttydefchars
, t
->c_cc
, sizeof t
->c_cc
);
1421 ttychars(struct tty
*tp
)
1423 termioschars(&tp
->t_termios
);
1427 * Handle input high water. Send stop character for the IXOFF case. Turn
1428 * on our input flow control bit and propagate the changes to the driver.
1429 * XXX the stop character should be put in a special high priority queue.
1432 ttyblock(struct tty
*tp
)
1434 SET(tp
->t_state
, TS_TBLOCK
);
1435 if (ISSET(tp
->t_iflag
, IXOFF
) && tp
->t_cc
[VSTOP
] != _POSIX_VDISABLE
&&
1436 putc(tp
->t_cc
[VSTOP
], &tp
->t_outq
) != 0)
1437 CLR(tp
->t_state
, TS_TBLOCK
); /* try again later */
1442 * Handle input low water. Send start character for the IXOFF case. Turn
1443 * off our input flow control bit and propagate the changes to the driver.
1444 * XXX the start character should be put in a special high priority queue.
1447 ttyunblock(struct tty
*tp
)
1449 CLR(tp
->t_state
, TS_TBLOCK
);
1450 if (ISSET(tp
->t_iflag
, IXOFF
) && tp
->t_cc
[VSTART
] != _POSIX_VDISABLE
&&
1451 putc(tp
->t_cc
[VSTART
], &tp
->t_outq
) != 0)
1452 SET(tp
->t_state
, TS_TBLOCK
); /* try again later */
1456 /* FreeBSD: Not used by any current (i386) drivers. */
1458 * Restart after an inter-char delay.
1461 ttrstrt(void *tp_arg
)
1471 CLR(tp
->t_state
, TS_TIMEOUT
);
1477 ttstart(struct tty
*tp
)
1479 boolean_t funnel_state
;
1481 funnel_state
= thread_funnel_set(kernel_flock
, TRUE
);
1483 if (tp
->t_oproc
!= NULL
) /* XXX: Kludge for pty. */
1485 thread_funnel_set(kernel_flock
, funnel_state
);
1490 * "close" a line discipline
1493 ttylclose(struct tty
*tp
, int flag
)
1495 boolean_t funnel_state
;
1497 funnel_state
= thread_funnel_set(kernel_flock
, TRUE
);
1498 if ( (flag
& FNONBLOCK
) || ttywflush(tp
))
1499 ttyflush(tp
, FREAD
| FWRITE
);
1500 thread_funnel_set(kernel_flock
, funnel_state
);
1505 * Handle modem control transition on a tty.
1506 * Flag indicates new state of carrier.
1507 * Returns 0 if the line should be turned off, otherwise 1.
1510 ttymodem(struct tty
*tp
, int flag
)
1512 boolean_t funnel_state
;
1514 funnel_state
= thread_funnel_set(kernel_flock
, TRUE
);
1516 if (ISSET(tp
->t_state
, TS_CARR_ON
) && ISSET(tp
->t_cflag
, MDMBUF
)) {
1518 * MDMBUF: do flow control according to carrier flag
1519 * XXX TS_CAR_OFLOW doesn't do anything yet. TS_TTSTOP
1520 * works if IXON and IXANY are clear.
1523 CLR(tp
->t_state
, TS_CAR_OFLOW
);
1524 CLR(tp
->t_state
, TS_TTSTOP
);
1526 } else if (!ISSET(tp
->t_state
, TS_CAR_OFLOW
)) {
1527 SET(tp
->t_state
, TS_CAR_OFLOW
);
1528 SET(tp
->t_state
, TS_TTSTOP
);
1531 } else if (flag
== 0) {
1535 CLR(tp
->t_state
, TS_CARR_ON
);
1536 if (ISSET(tp
->t_state
, TS_ISOPEN
) &&
1537 !ISSET(tp
->t_cflag
, CLOCAL
)) {
1538 SET(tp
->t_state
, TS_ZOMBIE
);
1539 CLR(tp
->t_state
, TS_CONNECTED
);
1540 if (tp
->t_session
&& tp
->t_session
->s_leader
)
1541 psignal(tp
->t_session
->s_leader
, SIGHUP
);
1542 ttyflush(tp
, FREAD
| FWRITE
);
1543 thread_funnel_set(kernel_flock
, funnel_state
);
1550 SET(tp
->t_state
, TS_CARR_ON
);
1551 if (!ISSET(tp
->t_state
, TS_ZOMBIE
))
1552 SET(tp
->t_state
, TS_CONNECTED
);
1553 wakeup(TSA_CARR_ON(tp
));
1557 thread_funnel_set(kernel_flock
, funnel_state
);
1562 * Reinput pending characters after state switch
1566 ttypend(struct tty
*tp
)
1571 CLR(tp
->t_lflag
, PENDIN
);
1572 SET(tp
->t_state
, TS_TYPEN
);
1574 tp
->t_rawq
.c_cc
= 0;
1575 tp
->t_rawq
.c_cf
= tp
->t_rawq
.c_cl
= NULL
;
1576 while ((c
= getc(&tq
)) >= 0)
1578 CLR(tp
->t_state
, TS_TYPEN
);
1582 * Process a read call on a tty device.
1585 ttread(struct tty
*tp
, struct uio
*uio
, int flag
)
1590 cc_t
*cc
= tp
->t_cc
;
1591 proc_t p
= current_proc();
1592 int first
, error
= 0;
1593 int has_etime
= 0, last_cc
= 0;
1594 long slp
= 0; /* XXX this should be renamed `timo'. */
1595 boolean_t funnel_state
;
1599 funnel_state
= thread_funnel_set(kernel_flock
, TRUE
);
1601 ut
= (struct uthread
*)get_bsdthread_info(current_thread());
1604 lflag
= tp
->t_lflag
;
1606 * take pending input first
1608 if (ISSET(lflag
, PENDIN
)) {
1610 lflag
= tp
->t_lflag
; /* XXX ttypend() clobbers it */
1614 * Signal the process if it's in the background.
1616 if (isbackground(p
, tp
)) {
1617 if ((p
->p_sigignore
& sigmask(SIGTTIN
)) ||
1618 (ut
->uu_sigmask
& sigmask(SIGTTIN
)) ||
1619 p
->p_lflag
& P_LPPWAIT
) {
1620 thread_funnel_set(kernel_flock
, funnel_state
);
1624 if (pg
== PGRP_NULL
) {
1625 thread_funnel_set(kernel_flock
, funnel_state
);
1628 if (pg
->pg_jobc
== 0) {
1630 thread_funnel_set(kernel_flock
, funnel_state
);
1633 pgsignal(pg
, SIGTTIN
, 1);
1637 * We signalled ourself, so we need to act as if we
1638 * have been "interrupted" from a "sleep" to act on
1639 * the signal. If it's a signal that stops the
1640 * process, that's handled in the signal sending code.
1642 thread_funnel_set(kernel_flock
, funnel_state
);
1646 if (ISSET(tp
->t_state
, TS_ZOMBIE
)) {
1647 thread_funnel_set(kernel_flock
, funnel_state
);
1648 return (0); /* EOF */
1652 * If canonical, use the canonical queue,
1653 * else use the raw queue.
1655 * (should get rid of clists...)
1657 qp
= ISSET(lflag
, ICANON
) ? &tp
->t_canq
: &tp
->t_rawq
;
1659 if (flag
& IO_NDELAY
) {
1662 if (!ISSET(lflag
, ICANON
) && cc
[VMIN
] == 0) {
1663 thread_funnel_set(kernel_flock
, funnel_state
);
1666 thread_funnel_set(kernel_flock
, funnel_state
);
1667 return (EWOULDBLOCK
);
1669 if (!ISSET(lflag
, ICANON
)) {
1672 struct timeval timecopy
;
1673 struct timeval etime
= {0, 0}; /* protected by !has_etime */
1676 * Check each of the four combinations.
1677 * (m > 0 && t == 0) is the normal read case.
1678 * It should be fairly efficient, so we check that and its
1679 * companion case (m == 0 && t == 0) first.
1680 * For the other two cases, we compute the target sleep time
1689 /* m, t and qp->c_cc are all 0. 0 is enough input. */
1690 thread_funnel_set(kernel_flock
, funnel_state
);
1693 t
*= 100000; /* time in us */
1694 #define diff(t1, t2) (((t1).tv_sec - (t2).tv_sec) * 1000000 + \
1695 ((t1).tv_usec - (t2).tv_usec))
1701 microuptime(&timecopy
);
1703 /* first character, start timer */
1706 etime
.tv_sec
= t
/ 1000000;
1707 etime
.tv_usec
= (t
- (etime
.tv_sec
* 1000000));
1708 timeradd(&etime
, &timecopy
, &etime
);
1711 } else if (qp
->c_cc
> last_cc
) {
1712 /* got a character, restart timer */
1714 etime
.tv_sec
= t
/ 1000000;
1715 etime
.tv_usec
= (t
- (etime
.tv_sec
* 1000000));
1716 timeradd(&etime
, &timecopy
, &etime
);
1720 /* nothing, check expiration */
1721 if (timercmp(&etime
, &timecopy
, <=))
1724 slp
= diff(etime
, timecopy
);
1727 } else { /* m == 0 */
1730 microuptime(&timecopy
);
1734 etime
.tv_sec
= t
/ 1000000;
1735 etime
.tv_usec
= (t
- (etime
.tv_sec
* 1000000));
1736 timeradd(&etime
, &timecopy
, &etime
);
1740 if (timercmp(&etime
, &timecopy
, <=)) {
1741 /* Timed out, but 0 is enough input. */
1742 thread_funnel_set(kernel_flock
, funnel_state
);
1745 slp
= diff(etime
, timecopy
);
1750 * Rounding down may make us wake up just short
1751 * of the target, so we round up.
1752 * The formula is ceiling(slp * hz/1000000).
1753 * 32-bit arithmetic is enough for hz < 169.
1754 * XXX see hzto() for how to avoid overflow if hz
1755 * is large (divide by `tick' and/or arrange to
1756 * use hzto() if hz is large).
1758 slp
= (long) (((u_long
)slp
* hz
) + 999999) / 1000000;
1761 if (qp
->c_cc
<= 0) {
1764 * There is no input, or not enough input and we can block.
1766 error
= ttysleep(tp
, TSA_HUP_OR_INPUT(tp
), TTIPRI
| PCATCH
,
1767 ISSET(tp
->t_state
, TS_CONNECTED
) ?
1768 "ttyin" : "ttyhup", (int)slp
);
1769 if (error
== EWOULDBLOCK
)
1772 thread_funnel_set(kernel_flock
, funnel_state
);
1776 * XXX what happens if another process eats some input
1777 * while we are asleep (not just here)? It would be
1778 * safest to detect changes and reset our state variables
1779 * (has_stime and last_cc).
1786 * Input present, check for input mapping and processing.
1789 if (ISSET(lflag
, ICANON
)
1790 || (ISSET(lflag
, IEXTEN
| ISIG
) == (IEXTEN
| ISIG
)) )
1796 icc
= min(uio_resid(uio
), IBUFSIZ
);
1797 icc
= q_to_b(qp
, (u_char
*)ibuf
, icc
);
1803 error
= uiomove(ibuf
, icc
, uio
);
1805 * XXX if there was an error then we should ungetc() the
1806 * unmoved chars and reduce icc here.
1810 if (uio_resid(uio
) == 0)
1824 * delayed suspend (^Y)
1826 if (CCEQ(cc
[VDSUSP
], c
) &&
1827 ISSET(lflag
, IEXTEN
| ISIG
) == (IEXTEN
| ISIG
)) {
1828 tty_pgsignal(tp
, SIGTSTP
, 1);
1830 error
= ttysleep(tp
, &lbolt
, TTIPRI
| PCATCH
,
1839 * Interpret EOF only in canonical mode.
1841 if (CCEQ(cc
[VEOF
], c
) && ISSET(lflag
, ICANON
))
1844 * Give user character.
1846 error
= ureadc(c
, uio
);
1848 /* XXX should ungetc(c, qp). */
1850 if (uio_resid(uio
) == 0)
1853 * In canonical mode check for a "break character"
1854 * marking the end of a "line of input".
1856 if (ISSET(lflag
, ICANON
) && TTBREAKC(c
, lflag
))
1863 * Look to unblock input now that (presumably)
1864 * the input queue has gone down.
1866 if (ISSET(tp
->t_state
, TS_TBLOCK
) &&
1867 tp
->t_rawq
.c_cc
+ tp
->t_canq
.c_cc
<= I_LOW_WATER
)
1870 thread_funnel_set(kernel_flock
, funnel_state
);
1875 * Check the output queue on tp for space for a kernel message (from uprintf
1876 * or tprintf). Allow some space over the normal hiwater mark so we don't
1877 * lose messages due to normal flow control, but don't let the tty run amok.
1878 * Sleeps here are not interruptible, but we return prematurely if new signals
1882 ttycheckoutq(struct tty
*tp
, int wait
)
1888 ut
= (struct uthread
*)get_bsdthread_info(current_thread());
1890 hiwat
= tp
->t_hiwat
;
1891 oldsig
= wait
? ut
->uu_siglist
: 0;
1892 if (tp
->t_outq
.c_cc
> hiwat
+ OBUFSIZ
+ 100)
1893 while (tp
->t_outq
.c_cc
> hiwat
) {
1895 if (tp
->t_outq
.c_cc
<= hiwat
)
1897 if (wait
== 0 || ut
->uu_siglist
!= oldsig
) {
1900 SET(tp
->t_state
, TS_SO_OLOWAT
);
1901 tsleep(TSA_OLOWAT(tp
), PZERO
- 1, "ttoutq", hz
);
1907 * Process a write call on a tty device.
1910 ttwrite(struct tty
*tp
, struct uio
*uio
, int flag
)
1915 int i
, hiwat
, count
, error
;
1917 boolean_t funnel_state
;
1921 funnel_state
= thread_funnel_set(kernel_flock
, TRUE
);
1923 ut
= (struct uthread
*)get_bsdthread_info(current_thread());
1924 hiwat
= tp
->t_hiwat
;
1925 // LP64todo - fix this!
1926 count
= uio_resid(uio
);
1930 if (ISSET(tp
->t_state
, TS_ZOMBIE
)) {
1931 if (uio_resid(uio
) == count
)
1935 if (!ISSET(tp
->t_state
, TS_CONNECTED
)) {
1936 if (flag
& IO_NDELAY
) {
1937 error
= EWOULDBLOCK
;
1940 error
= ttysleep(tp
, TSA_CARR_ON(tp
), TTIPRI
| PCATCH
,
1947 * Signal the process if it's in the background.
1950 if (isbackground(p
, tp
) &&
1951 ISSET(tp
->t_lflag
, TOSTOP
) && (p
->p_lflag
& P_LPPWAIT
) == 0 &&
1952 (p
->p_sigignore
& sigmask(SIGTTOU
)) == 0 &&
1953 (ut
->uu_sigmask
& sigmask(SIGTTOU
)) == 0) {
1956 if (pg
== PGRP_NULL
) {
1960 if (pg
->pg_jobc
== 0) {
1965 pgsignal(pg
, SIGTTOU
, 1);
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.
1977 * Process the user's data in at most OBUFSIZ chunks. Perform any
1978 * output translation. Keep track of high water mark, sleep on
1979 * overflow awaiting device aid in acquiring new space.
1981 while (uio_resid(uio
) > 0 || cc
> 0) {
1982 if (ISSET(tp
->t_lflag
, FLUSHO
)) {
1983 uio_setresid(uio
, 0);
1984 thread_funnel_set(kernel_flock
, funnel_state
);
1987 if (tp
->t_outq
.c_cc
> hiwat
)
1990 * Grab a hunk of data from the user, unless we have some
1991 * leftover from last time.
1994 cc
= min(uio_resid(uio
), OBUFSIZ
);
1996 error
= uiomove(cp
, cc
, uio
);
2003 * If nothing fancy need be done, grab those characters we
2004 * can handle without any of ttyoutput's processing and
2005 * just transfer them to the output q. For those chars
2006 * which require special processing (as indicated by the
2007 * bits in char_type), call ttyoutput. After processing
2008 * a hunk of data, look for FLUSHO so ^O's will take effect
2012 if (!ISSET(tp
->t_oflag
, OPOST
))
2015 ce
= cc
- scanc((u_int
)cc
, (u_char
*)cp
,
2016 char_type
, CCLASSMASK
);
2018 * If ce is zero, then we're processing
2019 * a special character through ttyoutput.
2023 if (ttyoutput(*cp
, tp
) >= 0) {
2029 if (ISSET(tp
->t_lflag
, FLUSHO
) ||
2030 tp
->t_outq
.c_cc
> hiwat
)
2036 * A bunch of normal characters have been found.
2037 * Transfer them en masse to the output queue and
2038 * continue processing at the top of the loop.
2039 * If there are any further characters in this
2040 * <= OBUFSIZ chunk, the first should be a character
2041 * requiring special handling by ttyoutput.
2044 i
= b_to_q((u_char
*)cp
, ce
, &tp
->t_outq
);
2047 cp
+= ce
, cc
-= ce
, tk_nout
+= ce
;
2053 if (ISSET(tp
->t_lflag
, FLUSHO
) ||
2054 tp
->t_outq
.c_cc
> hiwat
)
2061 * If cc is nonzero, we leave the uio structure inconsistent, as the
2062 * offset and iov pointers have moved forward, but it doesn't matter
2063 * (the call will either return short or restart with a new uio).
2065 uio_setresid(uio
, (uio_resid(uio
) + cc
));
2066 thread_funnel_set(kernel_flock
, funnel_state
);
2072 * Since we are using ring buffers, if we can't insert any more into
2073 * the output queue, we can assume the ring is full and that someone
2074 * forgot to set the high water mark correctly. We set it and then
2075 * proceed as normal.
2077 hiwat
= tp
->t_outq
.c_cc
- 1;
2082 * This can only occur if FLUSHO is set in t_lflag,
2083 * or if ttstart/oproc is synchronous (or very fast).
2085 if (tp
->t_outq
.c_cc
<= hiwat
) {
2088 if (flag
& IO_NDELAY
) {
2089 uio_setresid(uio
, (uio_resid(uio
) + cc
));
2090 thread_funnel_set(kernel_flock
, funnel_state
);
2091 return (uio_resid(uio
) == count
? EWOULDBLOCK
: 0);
2093 SET(tp
->t_state
, TS_SO_OLOWAT
);
2094 error
= ttysleep(tp
, TSA_OLOWAT(tp
), TTOPRI
| PCATCH
, "ttywri",
2096 if (error
== EWOULDBLOCK
)
2104 * Rubout one character from the rawq of tp
2105 * as cleanly as possible.
2108 ttyrub(int c
, struct tty
*tp
)
2114 if (!ISSET(tp
->t_lflag
, ECHO
) || ISSET(tp
->t_lflag
, EXTPROC
))
2116 CLR(tp
->t_lflag
, FLUSHO
);
2117 if (ISSET(tp
->t_lflag
, ECHOE
)) {
2118 if (tp
->t_rocount
== 0) {
2120 * Messed up by ttwrite; retype
2125 if (c
== ('\t' | TTY_QUOTE
) || c
== ('\n' | TTY_QUOTE
))
2128 CLR(c
, ~TTY_CHARMASK
);
2129 switch (CCLASS(c
)) {
2131 if(!(ISSET(tp
->t_iflag
, IUTF8
) && CCONT(c
))) {
2140 if (ISSET(tp
->t_lflag
, ECHOCTL
))
2144 if (tp
->t_rocount
< tp
->t_rawq
.c_cc
) {
2148 savecol
= tp
->t_column
;
2149 SET(tp
->t_state
, TS_CNTTB
);
2150 SET(tp
->t_lflag
, FLUSHO
);
2151 tp
->t_column
= tp
->t_rocol
;
2152 for (cp
= firstc(&tp
->t_rawq
, &tabc
); cp
;
2153 cp
= nextc(&tp
->t_rawq
, cp
, &tabc
))
2155 CLR(tp
->t_lflag
, FLUSHO
);
2156 CLR(tp
->t_state
, TS_CNTTB
);
2158 /* savecol will now be length of the tab. */
2159 savecol
-= tp
->t_column
;
2160 tp
->t_column
+= savecol
;
2162 savecol
= 8; /* overflow fixup */
2163 while (--savecol
>= 0)
2164 (void)ttyoutput('\b', tp
);
2167 #define PANICSTR "ttyrub: would panic c = %d, val = %d\n"
2168 printf(PANICSTR
, c
, CCLASS(c
));
2170 panic(PANICSTR
, c
, CCLASS(c
));
2174 } else if (ISSET(tp
->t_lflag
, ECHOPRT
)) {
2175 if (!ISSET(tp
->t_state
, TS_ERASE
)) {
2176 SET(tp
->t_state
, TS_ERASE
);
2177 (void)ttyoutput('\\', tp
);
2181 ttyecho(tp
->t_cc
[VERASE
], tp
);
2186 * Back over count characters, erasing them.
2189 ttyrubo(struct tty
*tp
, int count
)
2191 while (count
-- > 0) {
2192 (void)ttyoutput('\b', tp
);
2193 (void)ttyoutput(' ', tp
);
2194 (void)ttyoutput('\b', tp
);
2200 * Reprint the rawq line. Note, it is assumed that c_cc has already
2204 ttyretype(struct tty
*tp
)
2209 /* Echo the reprint character. */
2210 if (tp
->t_cc
[VREPRINT
] != _POSIX_VDISABLE
)
2211 ttyecho(tp
->t_cc
[VREPRINT
], tp
);
2213 (void)ttyoutput('\n', tp
);
2217 * FIX: NEXTC IS BROKEN - DOESN'T CHECK QUOTE
2218 * BIT OF FIRST CHAR.
2220 for (cp
= firstc(&tp
->t_canq
, &c
); cp
; cp
= nextc(&tp
->t_canq
, cp
, &c
))
2222 for (cp
= firstc(&tp
->t_rawq
, &c
); cp
; cp
= nextc(&tp
->t_rawq
, cp
, &c
))
2224 CLR(tp
->t_state
, TS_ERASE
);
2226 tp
->t_rocount
= tp
->t_rawq
.c_cc
;
2231 * Echo a typed character to the terminal.
2234 ttyecho(int c
, struct tty
*tp
)
2236 if (!ISSET(tp
->t_state
, TS_CNTTB
))
2237 CLR(tp
->t_lflag
, FLUSHO
);
2238 if ((!ISSET(tp
->t_lflag
, ECHO
) &&
2239 (c
!= '\n' || !ISSET(tp
->t_lflag
, ECHONL
))) ||
2240 ISSET(tp
->t_lflag
, EXTPROC
))
2242 if (ISSET(tp
->t_lflag
, ECHOCTL
) &&
2243 ((ISSET(c
, TTY_CHARMASK
) <= 037 && c
!= '\t' && c
!= '\n') ||
2244 ISSET(c
, TTY_CHARMASK
) == 0177)) {
2245 (void)ttyoutput('^', tp
);
2246 CLR(c
, ~TTY_CHARMASK
);
2252 (void)ttyoutput(c
, tp
);
2256 * Wake up any readers on a tty.
2259 ttwakeup(struct tty
*tp
)
2261 selwakeup(&tp
->t_rsel
);
2262 if (ISSET(tp
->t_state
, TS_ASYNC
))
2263 tty_pgsignal(tp
, SIGIO
, 1);
2264 wakeup(TSA_HUP_OR_INPUT(tp
));
2268 * Wake up any writers on a tty.
2271 ttwwakeup(struct tty
*tp
)
2273 if (tp
->t_outq
.c_cc
<= tp
->t_lowat
)
2274 selwakeup(&tp
->t_wsel
);
2275 if (ISSET(tp
->t_state
, TS_BUSY
| TS_SO_OCOMPLETE
) ==
2276 TS_SO_OCOMPLETE
&& tp
->t_outq
.c_cc
== 0) {
2277 CLR(tp
->t_state
, TS_SO_OCOMPLETE
);
2278 wakeup(TSA_OCOMPLETE(tp
));
2280 if (ISSET(tp
->t_state
, TS_SO_OLOWAT
) &&
2281 tp
->t_outq
.c_cc
<= tp
->t_lowat
) {
2282 CLR(tp
->t_state
, TS_SO_OLOWAT
);
2283 wakeup(TSA_OLOWAT(tp
));
2288 * Look up a code for a specified speed in a conversion table;
2289 * used by drivers to map software speed values to hardware parameters.
2292 ttspeedtab(int speed
, struct speedtab
*table
)
2294 for ( ; table
->sp_speed
!= -1; table
++)
2295 if (table
->sp_speed
== speed
)
2296 return (table
->sp_code
);
2301 * Set tty hi and low water marks.
2303 * Try to arrange the dynamics so there's about one second
2304 * from hi to low water.
2308 ttsetwater(struct tty
*tp
)
2313 #define CLAMP(x, h, l) ((x) > h ? h : ((x) < l) ? l : (x))
2315 cps
= tp
->t_ospeed
/ 10;
2316 tp
->t_lowat
= x
= CLAMP(cps
/ 2, TTMAXLOWAT
, TTMINLOWAT
);
2318 x
= CLAMP(x
, TTMAXHIWAT
, TTMINHIWAT
);
2319 tp
->t_hiwat
= roundup(x
, CBSIZE
);
2323 /* ttyinfo has been converted to the MACH kernel */
2324 #include <mach/thread_info.h>
2326 /* XXX Should be in Mach header <kern/thread.h>, but doesn't work */
2327 extern kern_return_t
thread_info_internal(thread_t thread
,
2328 thread_flavor_t flavor
,
2329 thread_info_t thread_info_out
,
2330 mach_msg_type_number_t
*thread_info_count
);
2333 * Report on state of foreground process group.
2336 ttyinfo(struct tty
*tp
)
2345 struct timeval utime
;
2346 struct timeval stime
;
2347 thread_basic_info_data_t basic_info
;
2348 mach_msg_type_number_t mmtn
= THREAD_BASIC_INFO_COUNT
;
2352 if (ttycheckoutq(tp
,0) == 0)
2355 /* Print load average. */
2356 load
= (averunnable
.ldavg
[0] * 100 + FSCALE
/ 2) >> FSHIFT
;
2357 ttyprintf(tp
, "load: %d.%02d ", load
/ 100, load
% 100);
2360 * On return following a ttyprintf(), we set tp->t_rocount to 0 so
2361 * that pending input will be retyped on BS.
2363 if (tp
->t_session
== NULL
) {
2364 ttyprintf(tp
, "not a controlling terminal\n");
2368 if (tp
->t_pgrp
== NULL
) {
2369 ttyprintf(tp
, "no foreground process group\n");
2373 /* first process in process group */
2374 /* XXX is there a need for pgrp lock ? */
2375 if ((p
= tp
->t_pgrp
->pg_members
.lh_first
) == NULL
) {
2376 ttyprintf(tp
, "empty foreground process group\n");
2382 * Pick the most interesting process and copy some of its
2383 * state for printing later.
2387 /* the proc_compare is non blocking fn, no need to use iterator */
2388 for (pick
= NULL
; p
!= NULL
; p
= p
->p_pglist
.le_next
) {
2389 if (proc_compare(pick
, p
)) {
2393 pickpid
= pick
->p_pid
;
2399 pick
= proc_find(pickpid
);
2400 if (pick
== PROC_NULL
)
2403 if (TAILQ_EMPTY(&pick
->p_uthlist
) ||
2404 (uthread
= TAILQ_FIRST(&pick
->p_uthlist
)) == NULL
||
2405 (thread
= vfs_context_thread(&uthread
->uu_context
)) == NULL
||
2406 (thread_info_internal(thread
, THREAD_BASIC_INFO
, (thread_info_t
)&basic_info
, &mmtn
) != KERN_SUCCESS
)) {
2407 ttyprintf(tp
, "foreground process without thread\n");
2413 switch(basic_info
.run_state
) {
2414 case TH_STATE_RUNNING
:
2417 case TH_STATE_STOPPED
:
2420 case TH_STATE_WAITING
:
2423 case TH_STATE_UNINTERRUPTIBLE
:
2424 state
= "uninterruptible";
2426 case TH_STATE_HALTED
:
2433 calcru(pick
, &utime
, &stime
, NULL
);
2436 /* Print command, pid, state, utime, and stime */
2437 ttyprintf(tp
, " cmd: %s %d %s %ld.%02ldu %ld.%02lds\n",
2441 (long)utime
.tv_sec
, utime
.tv_usec
/ 10000,
2442 (long)stime
.tv_sec
, stime
.tv_usec
/ 10000);
2447 * Returns 1 if p2 is "better" than p1
2449 * The algorithm for picking the "interesting" process is thus:
2451 * 1) Only foreground processes are eligible - implied.
2452 * 2) Runnable processes are favored over anything else. The runner
2453 * with the highest cpu utilization is picked (p_estcpu). Ties are
2454 * broken by picking the highest pid.
2455 * 3) The sleeper with the shortest sleep time is next.
2456 * 4) Further ties are broken by picking the highest pid.
2458 #define ISRUN(p) (((p)->p_stat == SRUN) || ((p)->p_stat == SIDL))
2459 #define TESTAB(a, b) ((a)<<1 | (b))
2465 proc_compare(proc_t p1
, proc_t p2
)
2467 /* NOTE THIS FN needs to be NON BLOCKING */
2472 * see if at least one of them is runnable
2474 switch (TESTAB(ISRUN(p1
), ISRUN(p2
))) {
2481 * tie - favor one with highest recent cpu utilization
2483 #ifdef _PROC_HAS_SCHEDINFO_
2484 /* Without the support the fields are always zero */
2485 if (p2
->p_estcpu
> p1
->p_estcpu
)
2487 if (p1
->p_estcpu
> p2
->p_estcpu
)
2489 #endif /* _PROC_HAS_SCHEDINFO_ */
2490 return (p2
->p_pid
> p1
->p_pid
); /* tie - return highest pid */
2495 switch (TESTAB(p1
->p_stat
== SZOMB
, p2
->p_stat
== SZOMB
)) {
2501 return (p2
->p_pid
> p1
->p_pid
); /* tie - return highest pid */
2504 * pick the one with the smallest sleep time
2506 #ifdef _PROC_HAS_SCHEDINFO_
2507 /* Without the support the fields are always zero */
2508 if (p2
->p_slptime
> p1
->p_slptime
)
2510 if (p1
->p_slptime
> p2
->p_slptime
)
2512 #endif /* _PROC_HAS_SCHEDINFO_ */
2513 return (p2
->p_pid
> p1
->p_pid
); /* tie - return highest pid */
2517 * Output char to tty; console putchar style.
2520 tputchar(int c
, struct tty
*tp
)
2522 if (!ISSET(tp
->t_state
, TS_CONNECTED
)) {
2526 (void)ttyoutput('\r', tp
);
2527 (void)ttyoutput(c
, tp
);
2533 * Sleep on chan, returning ERESTART if tty changed while we napped and
2534 * returning any errors (e.g. EINTR/EWOULDBLOCK) reported by tsleep. If
2535 * the tty is revoked, restarting a pending call will redo validation done
2536 * at the start of the call.
2539 ttysleep(struct tty
*tp
, void *chan
, int pri
, const char *wmesg
, int timo
)
2545 error
= tsleep(chan
, pri
, wmesg
, timo
);
2548 return (tp
->t_gen
== gen
? 0 : ERESTART
);
2552 * Allocate a tty structure and its associated buffers.
2556 * Returns: !NULL Address of new struct tty
2557 * NULL Error ("ENOMEM")
2564 MALLOC(tp
, struct tty
*, sizeof(struct tty
), M_TTYS
, M_WAITOK
|M_ZERO
);
2566 /* XXX: default to TTYCLSIZE(1024) chars for now */
2567 clalloc(&tp
->t_rawq
, TTYCLSIZE
, 1);
2568 clalloc(&tp
->t_canq
, TTYCLSIZE
, 1);
2569 /* output queue doesn't need quoting */
2570 clalloc(&tp
->t_outq
, TTYCLSIZE
, 0);
2576 * Free a tty structure and its buffers.
2579 ttyfree(struct tty
*tp
)
2581 clfree(&tp
->t_rawq
);
2582 clfree(&tp
->t_canq
);
2583 clfree(&tp
->t_outq
);
2588 isbackground(proc_t p
, struct tty
*tp
)
2590 return (isctty(p
, tp
) && (p
->p_pgrp
!= tp
->t_pgrp
));
2594 isctty(proc_t p
, struct tty
*tp
)
2597 struct session
* sessp
;
2599 sessp
= proc_session(p
);
2600 retval
= (sessp
== tp
->t_session
&& p
->p_flag
& P_CONTROLT
);
2601 session_rele(sessp
);
2606 isctty_sp(proc_t p
, struct tty
*tp
, struct session
*sessp
)
2608 return(sessp
== tp
->t_session
&& p
->p_flag
& P_CONTROLT
);