]> git.saurik.com Git - apple/xnu.git/blame - bsd/kern/tty.c
xnu-1228.15.4.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>
104#include <sys/uio.h>
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
91447636
A
117static int ttnread(struct tty *tp);
118static void ttyecho(int c, struct tty *tp);
2d21ac55 119static int ttyoutput(int c, struct tty *tp);
91447636
A
120static void ttypend(struct tty *tp);
121static void ttyretype(struct tty *tp);
122static void ttyrub(int c, struct tty *tp);
123static void ttyrubo(struct tty *tp, int count);
124static void ttystop(struct tty *tp, int rw);
125static void ttyunblock(struct tty *tp);
126static int ttywflush(struct tty *tp);
2d21ac55
A
127static int proc_compare(proc_t p1, proc_t p2);
128
129static int isctty(proc_t p, struct tty *tp);
130static int isctty_sp(proc_t p, struct tty *tp, struct session *sessp);
1c79356b
A
131
132/*
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.
138 */
139#define E 0x00 /* Even parity. */
140#define O 0x80 /* Odd parity. */
141#define PARITY(c) (char_type[c] & O)
142
143#define ALPHA 0x40 /* Alpha or underscore. */
144#define ISALPHA(c) (char_type[(c) & TTY_CHARMASK] & ALPHA)
145
146#define CCLASSMASK 0x3f
147#define CCLASS(c) (char_type[c] & CCLASSMASK)
2d21ac55
A
148/* 0b10xxxxxx is the mask for UTF-8 continuations */
149#define CCONT(c) ((c & 0xc0) == 0x80)
1c79356b
A
150
151#define BS BACKSPACE
152#define CC CONTROL
153#define CR RETURN
154#define NA ORDINARY | ALPHA
155#define NL NEWLINE
156#define NO ORDINARY
157#define TB TAB
158#define VT VTAB
159
160static 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 */
177 /*
178 * Meta chars; should be settable per character set;
179 * for now, treat them all as normal characters.
180 */
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,
197};
198#undef BS
199#undef CC
200#undef CR
201#undef NA
202#undef NL
203#undef NO
204#undef TB
205#undef VT
206
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))
211
212/*
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.
216 */
217#define I_HIGH_WATER (TTYHOG - 2 * 256) /* XXX */
218#define I_LOW_WATER ((TTYHOG - 2 * 256) * 7 / 8) /* XXX */
219
91447636
A
220static void
221termios32to64(struct termios *in, struct user_termios *out)
222{
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;
227
228 /* bcopy is OK, since this type is ILP32/LP64 size invariant */
229 bcopy(in->c_cc, out->c_cc, sizeof(in->c_cc));
230
231 out->c_ispeed = (user_speed_t)in->c_ispeed;
232 out->c_ospeed = (user_speed_t)in->c_ospeed;
233}
234
235static void
236termios64to32(struct user_termios *in, struct termios *out)
237{
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;
242
243 /* bcopy is OK, since this type is ILP32/LP64 size invariant */
244 bcopy(in->c_cc, out->c_cc, sizeof(in->c_cc));
245
246 out->c_ispeed = (speed_t)in->c_ispeed;
247 out->c_ospeed = (speed_t)in->c_ospeed;
248}
249
250
1c79356b
A
251/*
252 * Initial open of tty, or (re)entry to standard tty line discipline.
253 */
254int
2d21ac55 255ttyopen(dev_t device, struct tty *tp)
1c79356b 256{
0b4e3aa0 257 boolean_t funnel_state;
2d21ac55
A
258 proc_t p = current_proc();
259 struct pgrp * pg, * oldpg;
260 struct session *sessp, *oldsess;
1c79356b 261
0b4e3aa0 262 funnel_state = thread_funnel_set(kernel_flock, TRUE);
2d21ac55 263
1c79356b 264 tp->t_dev = device;
2d21ac55 265
1c79356b
A
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));
271 }
272
2d21ac55
A
273 pg = proc_pgrp(p);
274 sessp = proc_session(p);
275
1c79356b 276 /*
2d21ac55
A
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
1c79356b 280 */
2d21ac55
A
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 */
284 session_lock(sessp);
285 if ((sessp->s_flags & S_NOCTTY) == 0) { /* and no O_NOCTTY */
286 /* Hold on to the reference */
287 sessp->s_ttyp = tp;
288 OSBitOrAtomic(P_CONTROLT, (UInt32 *)&p->p_flag);
289 session_unlock(sessp);
290 proc_list_lock();
291 oldpg = tp->t_pgrp;
292 oldsess = tp->t_session;
293 if (oldsess != SESSION_NULL)
294 oldsess->s_ttypgrpid = NO_PID;
295 tp->t_session = sessp;
296 tp->t_pgrp = pg;
297 sessp->s_ttypgrpid = pg->pg_id;
298 proc_list_unlock();
299 if (oldpg != PGRP_NULL)
300 pg_rele(oldpg);
301 if (oldsess != SESSION_NULL)
302 session_rele(oldsess);
303 goto out;
304 }
305 session_unlock(sessp);
306 }
1c79356b 307
2d21ac55
A
308 if (sessp != SESSION_NULL)
309 session_rele(sessp);
310 if (pg != PGRP_NULL)
311 pg_rele(pg);
312
313out:
0b4e3aa0 314 thread_funnel_set(kernel_flock, funnel_state);
2d21ac55 315
1c79356b
A
316 return (0);
317}
318
319/*
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.
326 */
327int
2d21ac55 328ttyclose(struct tty *tp)
1c79356b 329{
2d21ac55
A
330 struct pgrp * oldpg;
331 struct session * oldsessp;
1c79356b 332
1c79356b
A
333 if (constty == tp) {
334 constty = NULL;
335
1c79356b 336
1c79356b
A
337 /*
338 * Closing current console tty; disable printing of console
339 * messages at bottom-level driver.
340 */
341 (*cdevsw[major(tp->t_dev)].d_ioctl)
342 (tp->t_dev, KMIOCDISABLCONS, NULL, 0, current_proc());
1c79356b
A
343 }
344
345 ttyflush(tp, FREAD | FWRITE);
1c79356b
A
346
347 tp->t_gen++;
348 tp->t_line = TTYDISC;
2d21ac55
A
349 proc_list_lock();
350 oldpg = tp->t_pgrp;
351 oldsessp = tp->t_session;
1c79356b
A
352 tp->t_pgrp = NULL;
353 tp->t_session = NULL;
2d21ac55
A
354 if (oldsessp != SESSION_NULL)
355 oldsessp->s_ttypgrpid = NO_PID;
356 proc_list_unlock();
357 /* drop the reference on prev session and pgrp */
358 if (oldsessp != SESSION_NULL)
359 session_rele(oldsessp);
360 if (oldpg != PGRP_NULL)
361 pg_rele(oldpg);
1c79356b 362 tp->t_state = 0;
1c79356b
A
363 selthreadclear(&tp->t_wsel);
364 selthreadclear(&tp->t_rsel);
1c79356b
A
365 return (0);
366}
367
368#define FLUSHQ(q) { \
369 if ((q)->c_cc) \
370 ndflush(q, (q)->c_cc); \
371}
372
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))
378
379/*
380 * Process input of a single character received on a tty.
381 */
382int
2d21ac55 383ttyinput(int c, struct tty *tp)
1c79356b 384{
2d21ac55
A
385 tcflag_t iflag, lflag;
386 cc_t *cc;
1c79356b
A
387 int i, err, retval;
388 boolean_t funnel_state;
389
390 funnel_state = thread_funnel_set(kernel_flock, TRUE);
391
392 /*
393 * If input is pending take it first.
394 */
395 lflag = tp->t_lflag;
396 if (ISSET(lflag, PENDIN))
397 ttypend(tp);
398 /*
399 * Gather stats.
400 */
401 if (ISSET(lflag, ICANON)) {
402 ++tk_cancc;
403 ++tp->t_cancc;
404 } else {
405 ++tk_rawcc;
406 ++tp->t_rawcc;
407 }
408 ++tk_nin;
409
410 /*
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.
415 */
416 iflag = tp->t_iflag;
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))
421 ttyblock(tp);
422
423 /* Handle exceptional conditions (break, parity, framing). */
424 cc = tp->t_cc;
425 err = (ISSET(c, TTY_ERRORMASK));
426 if (err) {
427 CLR(c, TTY_ERRORMASK);
428 if (ISSET(err, TTY_BI)) {
429 if (ISSET(iflag, IGNBRK)) {
430 thread_funnel_set(kernel_flock, funnel_state);
431 return (0);
432 }
433 if (ISSET(iflag, BRKINT)) {
434 ttyflush(tp, FREAD | FWRITE);
2d21ac55 435 tty_pgsignal(tp, SIGINT, 1);
1c79356b
A
436 goto endcase;
437 }
438 if (ISSET(iflag, PARMRK))
439 goto 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);
444 return (0);
445 }
446 else if (ISSET(iflag, PARMRK)) {
447parmrk:
448 if (tp->t_rawq.c_cc + tp->t_canq.c_cc >
449 MAX_INPUT - 3)
450 goto input_overflow;
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);
454 goto endcase;
455 } else
456 c = 0;
457 }
458 }
459
460 if (!ISSET(tp->t_state, TS_TYPEN) && ISSET(iflag, ISTRIP))
461 CLR(c, 0x80);
462 if (!ISSET(lflag, EXTPROC)) {
463 /*
464 * Check for literal nexting very first
465 */
466 if (ISSET(tp->t_state, TS_LNCH)) {
467 SET(c, TTY_QUOTE);
468 CLR(tp->t_state, TS_LNCH);
469 }
470 /*
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.
476 */
477
478 /*
479 * Control chars which aren't controlled
480 * by ICANON, ISIG, or IXON.
481 */
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);
488 } else
489 ttyecho(c, tp);
490 }
491 SET(tp->t_state, TS_LNCH);
492 goto endcase;
493 }
494 if (CCEQ(cc[VDISCARD], c)) {
495 if (ISSET(lflag, FLUSHO))
496 CLR(tp->t_lflag, FLUSHO);
497 else {
498 ttyflush(tp, FWRITE);
499 ttyecho(c, tp);
500 if (tp->t_rawq.c_cc + tp->t_canq.c_cc)
501 ttyretype(tp);
502 SET(tp->t_lflag, FLUSHO);
503 }
504 goto startoutput;
505 }
506 }
507 /*
508 * Signals.
509 */
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);
514 ttyecho(c, tp);
2d21ac55 515 tty_pgsignal(tp,
1c79356b
A
516 CCEQ(cc[VINTR], c) ? SIGINT : SIGQUIT, 1);
517 goto endcase;
518 }
519 if (CCEQ(cc[VSUSP], c)) {
520 if (!ISSET(lflag, NOFLSH))
521 ttyflush(tp, FREAD);
522 ttyecho(c, tp);
2d21ac55 523 tty_pgsignal(tp, SIGTSTP, 1);
1c79356b
A
524 goto endcase;
525 }
526 }
527 /*
528 * Handle start/stop characters.
529 */
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);
534 ttystop(tp, 0);
535 thread_funnel_set(kernel_flock, funnel_state);
536 return (0);
537 }
538 if (!CCEQ(cc[VSTART], c)) {
539 thread_funnel_set(kernel_flock, funnel_state);
540 return (0);
541 }
542 /*
543 * if VSTART == VSTOP then toggle
544 */
545 goto endcase;
546 }
547 if (CCEQ(cc[VSTART], c))
548 goto restartoutput;
549 }
550 /*
551 * IGNCR, ICRNL, & INLCR
552 */
553 if (c == '\r') {
554 if (ISSET(iflag, IGNCR)) {
555 thread_funnel_set(kernel_flock, funnel_state);
556 return (0);
557 }
558 else if (ISSET(iflag, ICRNL))
559 c = '\n';
560 } else if (c == '\n' && ISSET(iflag, INLCR))
561 c = '\r';
562 }
563 if (!ISSET(tp->t_lflag, EXTPROC) && ISSET(lflag, ICANON)) {
564 /*
565 * From here on down canonical mode character
566 * processing takes place.
567 */
568 /*
569 * erase (^H / ^?)
570 */
571 if (CCEQ(cc[VERASE], c)) {
2d21ac55
A
572 if (tp->t_rawq.c_cc) {
573 if (ISSET(iflag, IUTF8)) {
574 do {
575 ttyrub((c = unputc(&tp->t_rawq)), tp);
576 } while(tp->t_rawq.c_cc && CCONT(c));
577 } else {
578 ttyrub(unputc(&tp->t_rawq), tp);
579 }
580 }
1c79356b
A
581 goto endcase;
582 }
583 /*
584 * kill (^U)
585 */
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);
592 else {
593 ttyecho(c, tp);
594 if (ISSET(lflag, ECHOK) ||
595 ISSET(lflag, ECHOKE))
596 ttyecho('\n', tp);
597 FLUSHQ(&tp->t_rawq);
598 tp->t_rocount = 0;
599 }
600 CLR(tp->t_state, TS_LOCAL);
601 goto endcase;
602 }
603 /*
604 * word erase (^W)
605 */
606 if (CCEQ(cc[VWERASE], c) && ISSET(lflag, IEXTEN)) {
607 int ctype;
608
609 /*
610 * erase whitespace
611 */
612 while ((c = unputc(&tp->t_rawq)) == ' ' || c == '\t')
613 ttyrub(c, tp);
614 if (c == -1)
615 goto endcase;
616 /*
617 * erase last char of word and remember the
618 * next chars type (for ALTWERASE)
619 */
620 ttyrub(c, tp);
621 c = unputc(&tp->t_rawq);
622 if (c == -1)
623 goto endcase;
624 if (c == ' ' || c == '\t') {
625 (void)putc(c, &tp->t_rawq);
626 goto endcase;
627 }
628 ctype = ISALPHA(c);
629 /*
630 * erase rest of word
631 */
632 do {
633 ttyrub(c, tp);
634 c = unputc(&tp->t_rawq);
635 if (c == -1)
636 goto endcase;
637 } while (c != ' ' && c != '\t' &&
638 (!ISSET(lflag, ALTWERASE) || ISALPHA(c) == ctype));
639 (void)putc(c, &tp->t_rawq);
640 goto endcase;
641 }
642 /*
643 * reprint line (^R)
644 */
645 if (CCEQ(cc[VREPRINT], c) && ISSET(lflag, IEXTEN)) {
646 ttyretype(tp);
647 goto endcase;
648 }
649 /*
650 * ^T - kernel info and generate SIGINFO
651 */
652 if (CCEQ(cc[VSTATUS], c) && ISSET(lflag, IEXTEN)) {
653 if (ISSET(lflag, ISIG))
2d21ac55 654 tty_pgsignal(tp, SIGINFO, 1);
1c79356b
A
655 if (!ISSET(lflag, NOKERNINFO))
656 ttyinfo(tp);
657 goto endcase;
658 }
659 }
660 /*
661 * Check for input buffer overflow
662 */
663 if (tp->t_rawq.c_cc + tp->t_canq.c_cc >= MAX_INPUT) {
664input_overflow:
665 if (ISSET(iflag, IMAXBEL)) {
666 if (tp->t_outq.c_cc < tp->t_hiwat)
667 (void)ttyoutput(CTRL('g'), tp);
668 }
669 goto endcase;
670 }
671
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);
675
676 /*
677 * Put data char in q for user and
678 * wakeup on seeing a line delimiter.
679 */
680 if (putc(c, &tp->t_rawq) >= 0) {
681 if (!ISSET(lflag, ICANON)) {
682 ttwakeup(tp);
683 ttyecho(c, tp);
684 goto endcase;
685 }
686 if (TTBREAKC(c, lflag)) {
687 tp->t_rocount = 0;
688 catq(&tp->t_rawq, &tp->t_canq);
689 ttwakeup(tp);
690 } else if (tp->t_rocount++ == 0)
691 tp->t_rocol = tp->t_column;
692 if (ISSET(tp->t_state, TS_ERASE)) {
693 /*
694 * end of prterase \.../
695 */
696 CLR(tp->t_state, TS_ERASE);
697 (void)ttyoutput('/', tp);
698 }
699 i = tp->t_column;
700 ttyecho(c, tp);
701 if (CCEQ(cc[VEOF], c) && ISSET(lflag, ECHO)) {
702 /*
703 * Place the cursor over the '^' of the ^D.
704 */
705 i = min(2, tp->t_column - i);
706 while (i > 0) {
707 (void)ttyoutput('\b', tp);
708 i--;
709 }
710 }
711 }
712endcase:
713 /*
714 * IXANY means allow any character to restart output.
715 */
716 if (ISSET(tp->t_state, TS_TTSTOP) &&
717 !ISSET(iflag, IXANY) && cc[VSTART] != cc[VSTOP]) {
718 thread_funnel_set(kernel_flock, funnel_state);
719 return (0);
720 }
721restartoutput:
722 CLR(tp->t_lflag, FLUSHO);
723 CLR(tp->t_state, TS_TTSTOP);
724startoutput:
725 retval = ttstart(tp);
726 thread_funnel_set(kernel_flock, funnel_state);
727 return (retval);
728}
729
730/*
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.
734 * Must be recursive.
735 */
736static int
2d21ac55 737ttyoutput(int c, struct tty *tp)
1c79356b 738{
2d21ac55
A
739 tcflag_t oflag;
740 int col;
1c79356b
A
741
742 oflag = tp->t_oflag;
743 if (!ISSET(oflag, OPOST)) {
744 if (ISSET(tp->t_lflag, FLUSHO))
745 return (-1);
746 if (putc(c, &tp->t_outq))
747 return (c);
748 tk_nout++;
749 tp->t_outcc++;
750 return (-1);
751 }
752 /*
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
756 * externally.
757 */
758 CLR(c, ~TTY_CHARMASK);
759 if (c == '\t' &&
760 ISSET(oflag, OXTABS) && !ISSET(tp->t_lflag, EXTPROC)) {
2d21ac55 761 col = c = 8 - (tp->t_column & 7);
1c79356b 762 if (!ISSET(tp->t_lflag, FLUSHO)) {
2d21ac55 763 c -= b_to_q((const u_char *)" ", c, &tp->t_outq);
1c79356b
A
764 tk_nout += c;
765 tp->t_outcc += c;
1c79356b
A
766 }
767 tp->t_column += c;
2d21ac55 768 return (c == col ? -1 : '\t');
1c79356b
A
769 }
770 if (c == CEOT && ISSET(oflag, ONOEOT))
771 return (-1);
772
773 /*
774 * Newline translation: if ONLCR is set,
775 * translate newline into "\r\n".
776 */
777 if (c == '\n' && ISSET(tp->t_oflag, ONLCR)) {
778 tk_nout++;
779 tp->t_outcc++;
780 if (putc('\r', &tp->t_outq))
781 return (c);
782 }
2d21ac55
A
783 /* If OCRNL is set, translate "\r" into "\n". */
784 else if (c == '\r' && ISSET(tp->t_oflag, OCRNL))
785 c = '\n';
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)
788 return (-1);
1c79356b
A
789 tk_nout++;
790 tp->t_outcc++;
791 if (!ISSET(tp->t_lflag, FLUSHO) && putc(c, &tp->t_outq))
792 return (c);
793
794 col = tp->t_column;
795 switch (CCLASS(c)) {
796 case BACKSPACE:
797 if (col > 0)
798 --col;
799 break;
800 case CONTROL:
801 break;
802 case NEWLINE:
803 case RETURN:
804 col = 0;
805 break;
806 case ORDINARY:
807 ++col;
808 break;
809 case TAB:
810 col = (col + 8) & ~7;
811 break;
812 }
813 tp->t_column = col;
814 return (-1);
815}
816
817/*
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.
821 */
1c79356b 822int
2d21ac55 823ttioctl(struct tty *tp,
91447636 824 u_long cmd, caddr_t data, int flag,
2d21ac55 825 proc_t p)
1c79356b 826{
2d21ac55 827 int error = 0;
9bccf70c 828 struct uthread *ut;
2d21ac55
A
829 struct pgrp * pg, *oldpg;
830 struct session *sessp, * oldsessp;
1c79356b 831
91447636 832 ut = (struct uthread *)get_bsdthread_info(current_thread());
2d21ac55 833 /* If the ioctl involves modification, signal if in the background. */
1c79356b 834 switch (cmd) {
2d21ac55
A
835 case TIOCIXON:
836 case TIOCIXOFF:
837 case TIOCDRAIN:
1c79356b 838 case TIOCFLUSH:
2d21ac55
A
839 case TIOCSTOP:
840 case TIOCSTART:
1c79356b 841 case TIOCSETA:
91447636 842 case TIOCSETA_64:
1c79356b
A
843 case TIOCSETD:
844 case TIOCSETAF:
91447636 845 case TIOCSETAF_64:
1c79356b 846 case TIOCSETAW:
91447636 847 case TIOCSETAW_64:
1c79356b 848 case TIOCSPGRP:
1c79356b
A
849 case TIOCSTAT:
850 case TIOCSTI:
851 case TIOCSWINSZ:
91447636 852#if COMPAT_43_TTY || defined(COMPAT_SUNOS)
1c79356b
A
853 case TIOCLBIC:
854 case TIOCLBIS:
855 case TIOCLSET:
856 case TIOCSETC:
857 case OTIOCSETD:
858 case TIOCSETN:
859 case TIOCSETP:
860 case TIOCSLTC:
861#endif
862 while (isbackground(p, tp) &&
2d21ac55 863 (p->p_lflag & P_LPPWAIT) == 0 &&
1c79356b 864 (p->p_sigignore & sigmask(SIGTTOU)) == 0 &&
9bccf70c 865 (ut->uu_sigmask & sigmask(SIGTTOU)) == 0) {
2d21ac55
A
866 pg = proc_pgrp(p);
867 if (pg == PGRP_NULL) {
868 error = EIO;
869 goto out;
870 }
871 if (pg->pg_jobc == 0) {
872 pg_rele(pg);
873 error = EIO;
874 goto out;
875 }
876 pgsignal(pg, SIGTTOU, 1);
877 pg_rele(pg);
878
879
880 /*
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.
885 */
886 error = EINTR;
887 goto out;
1c79356b
A
888 }
889 break;
890 }
891
892 switch (cmd) { /* Process the ioctl. */
893 case FIOASYNC: /* set/clear async i/o */
1c79356b
A
894 if (*(int *)data)
895 SET(tp->t_state, TS_ASYNC);
896 else
897 CLR(tp->t_state, TS_ASYNC);
1c79356b
A
898 break;
899 case FIONBIO: /* set/clear non-blocking i/o */
900 break; /* XXX: delete. */
901 case FIONREAD: /* get # bytes to read */
1c79356b 902 *(int *)data = ttnread(tp);
1c79356b
A
903 break;
904 case TIOCEXCL: /* set exclusive use of tty */
1c79356b 905 SET(tp->t_state, TS_XCLUDE);
1c79356b
A
906 break;
907 case TIOCFLUSH: { /* flush buffers */
2d21ac55 908 int flags = *(int *)data;
1c79356b
A
909
910 if (flags == 0)
911 flags = FREAD | FWRITE;
912 else
913 flags &= FREAD | FWRITE;
914 ttyflush(tp, flags);
915 break;
916 }
1c79356b
A
917 case TIOCSCONS: {
918 /* Set current console device to this line */
919 int bogusData = 1;
920 data = (caddr_t) &bogusData;
921
922 /* No break - Fall through to BSD code */
923 }
1c79356b
A
924 case TIOCCONS: { /* become virtual console */
925 if (*(int *)data) {
926 if (constty && constty != tp &&
927 ISSET(constty->t_state, TS_CONNECTED)) {
2d21ac55
A
928 error = EBUSY;
929 goto out;
1c79356b 930 }
2d21ac55
A
931 if ( (error = suser(kauth_cred_get(), &p->p_acflag)) )
932 goto out;
1c79356b
A
933 constty = tp;
934 } else if (tp == constty) {
935 constty = NULL;
936 }
1c79356b
A
937 if (constty) {
938 (*cdevsw[major(cons.t_dev)].d_ioctl)
939 (cons.t_dev, KMIOCDISABLCONS, NULL, 0, p);
940 } else {
941 (*cdevsw[major(tp->t_dev)].d_ioctl)
942 (tp->t_dev, KMIOCDISABLCONS, NULL, 0, p);
943 }
1c79356b
A
944 break;
945 }
946 case TIOCDRAIN: /* wait till output drained */
947 error = ttywait(tp);
948 if (error)
2d21ac55 949 goto out;
1c79356b 950 break;
91447636
A
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);
955 } else {
956 bcopy(&tp->t_termios, data, sizeof(struct termios));
957 }
1c79356b
A
958 break;
959 }
960 case TIOCGETD: /* get line discipline */
961 *(int *)data = tp->t_line;
962 break;
963 case TIOCGWINSZ: /* get window size */
964 *(struct winsize *)data = tp->t_winsize;
965 break;
966 case TIOCGPGRP: /* get pgrp of tty */
2d21ac55
A
967 if (!isctty(p, tp)) {
968 error = ENOTTY;
969 goto out;
970 }
1c79356b
A
971 *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
972 break;
973#ifdef TIOCHPCL
974 case TIOCHPCL: /* hang up on last close */
1c79356b 975 SET(tp->t_cflag, HUPCL);
1c79356b
A
976 break;
977#endif
978 case TIOCNXCL: /* reset exclusive use of tty */
1c79356b 979 CLR(tp->t_state, TS_XCLUDE);
1c79356b
A
980 break;
981 case TIOCOUTQ: /* output queue size */
982 *(int *)data = tp->t_outq.c_cc;
983 break;
984 case TIOCSETA: /* set termios struct */
91447636 985 case TIOCSETA_64:
1c79356b 986 case TIOCSETAW: /* drain output, set */
91447636
A
987 case TIOCSETAW_64:
988 case TIOCSETAF: /* drn out, fls in, set */
989 case TIOCSETAF_64: { /* drn out, fls in, set */
2d21ac55 990 struct termios *t = (struct termios *)data;
91447636 991 struct termios lcl_termios;
1c79356b 992
91447636
A
993 if (IS_64BIT_PROCESS(p)) {
994 termios64to32((struct user_termios *)data, &lcl_termios);
995 t = &lcl_termios;
996 }
2d21ac55
A
997#if 0
998 /* XXX bogus test; always false */
999 if (t->c_ispeed < 0 || t->c_ospeed < 0) {
1000 error = EINVAL;
1001 goto out;
1002 }
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;
91447636
A
1006 if (cmd == TIOCSETAW || cmd == TIOCSETAF ||
1007 cmd == TIOCSETAW_64 || cmd == TIOCSETAF_64) {
1c79356b
A
1008 error = ttywait(tp);
1009 if (error) {
2d21ac55 1010 goto out;
1c79356b 1011 }
91447636 1012 if (cmd == TIOCSETAF || cmd == TIOCSETAF_64)
1c79356b
A
1013 ttyflush(tp, FREAD);
1014 }
1015 if (!ISSET(t->c_cflag, CIGNORE)) {
1016 /*
1017 * Set device hardware.
1018 */
1019 if (tp->t_param && (error = (*tp->t_param)(tp, t))) {
2d21ac55 1020 goto out;
1c79356b
A
1021 }
1022 if (ISSET(t->c_cflag, CLOCAL) &&
1023 !ISSET(tp->t_cflag, CLOCAL)) {
1024 /*
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.
1029 */
1030 CLR(tp->t_state, TS_ZOMBIE);
1031
1032 wakeup(TSA_CARR_ON(tp));
1033 ttwakeup(tp);
1034 ttwwakeup(tp);
1035 }
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);
1040 else
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;
1045 ttsetwater(tp);
1046 }
1047 if (ISSET(t->c_lflag, ICANON) != ISSET(tp->t_lflag, ICANON) &&
91447636 1048 cmd != TIOCSETAF && cmd != TIOCSETAF_64) {
1c79356b
A
1049 if (ISSET(t->c_lflag, ICANON))
1050 SET(tp->t_lflag, PENDIN);
1051 else {
1052 /*
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.
1057 */
1c79356b
A
1058 if (tp->t_rawq.c_cs && tp->t_canq.c_cs) {
1059 struct clist tq;
1060
1061 catq(&tp->t_rawq, &tp->t_canq);
1062 tq = tp->t_rawq;
1063 tp->t_rawq = tp->t_canq;
1064 tp->t_canq = tq;
1065 }
1c79356b
A
1066 CLR(tp->t_lflag, PENDIN);
1067 }
1068 ttwakeup(tp);
1069 }
1070 tp->t_iflag = t->c_iflag;
1071 tp->t_oflag = t->c_oflag;
1072 /*
1073 * Make the EXTPROC bit read only.
1074 */
1075 if (ISSET(tp->t_lflag, EXTPROC))
1076 SET(t->c_lflag, EXTPROC);
1077 else
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])
1082 ttwakeup(tp);
1083 bcopy(t->c_cc, tp->t_cc, sizeof(t->c_cc));
1c79356b
A
1084 break;
1085 }
1086 case TIOCSETD: { /* set line discipline */
2d21ac55 1087 int t = *(int *)data;
1c79356b 1088 dev_t device = tp->t_dev;
1c79356b 1089
2d21ac55
A
1090 if (t >= nlinesw || t < 0) {
1091 error = ENXIO;
1092 goto out;
1093 }
1c79356b 1094 if (t != tp->t_line) {
1c79356b
A
1095 (*linesw[tp->t_line].l_close)(tp, flag);
1096 error = (*linesw[t].l_open)(device, tp);
1097 if (error) {
1098 (void)(*linesw[tp->t_line].l_open)(device, tp);
2d21ac55 1099 goto out;
1c79356b
A
1100 }
1101 tp->t_line = t;
1c79356b
A
1102 }
1103 break;
1104 }
1105 case TIOCSTART: /* start output, like ^Q */
1c79356b
A
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);
1110 ttstart(tp);
1111 }
1c79356b
A
1112 break;
1113 case TIOCSTI: /* simulate terminal input */
2d21ac55
A
1114 if (suser(kauth_cred_get(), NULL) && (flag & FREAD) == 0) {
1115 error = EPERM;
1116 goto out;
1117 }
1118 if (suser(kauth_cred_get(), NULL) && !isctty(p, tp)) {
1119 error = EACCES;
1120 goto out;
1121 }
1c79356b 1122 (*linesw[tp->t_line].l_rint)(*(u_char *)data, tp);
1c79356b
A
1123 break;
1124 case TIOCSTOP: /* stop output, like ^S */
1c79356b
A
1125 if (!ISSET(tp->t_state, TS_TTSTOP)) {
1126 SET(tp->t_state, TS_TTSTOP);
1127 ttystop(tp, 0);
1128 }
2d21ac55
A
1129 break;
1130 case TIOCIXON:
1131 ttyunblock(tp);
1132 break;
1133 case TIOCIXOFF:
1134 ttyblock(tp);
1c79356b
A
1135 break;
1136 case TIOCSCTTY: /* become controlling tty */
1137 /* Session ctty vnode pointer set in vnode layer. */
2d21ac55
A
1138 pg = proc_pgrp(p);
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)
1146 pg_rele(pg);
1147 error = EPERM;
1148 goto out;
1149 }
1150 proc_list_lock();
1151 oldsessp = tp->t_session;
1152 oldpg = tp->t_pgrp;
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;
1158 tp->t_pgrp = pg;
1159 proc_list_unlock();
1160 session_lock(sessp);
1161 sessp->s_ttyp = tp;
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)
1168 pg_rele(oldpg);
1c79356b 1169 break;
2d21ac55 1170
1c79356b 1171 case TIOCSPGRP: { /* set pgrp of tty */
2d21ac55 1172 struct pgrp *pgrp = PGRP_NULL;
1c79356b 1173
2d21ac55
A
1174 sessp = proc_session(p);
1175 if (!isctty_sp(p, tp, sessp)) {
1176 if (sessp != SESSION_NULL)
1177 session_rele(sessp);
1178 error = ENOTTY;
1179 goto out;
1180 }
1181 else if ((pgrp = pgfind(*(int *)data)) == PGRP_NULL) {
1182 if (sessp != SESSION_NULL)
1183 session_rele(sessp);
1184 error = EINVAL;
1185 goto out;
1186 } else if (pgrp->pg_session != sessp) {
1187 if (sessp != SESSION_NULL)
1188 session_rele(sessp);
1189 pg_rele(pgrp);
1190 error = EPERM;
1191 goto out;
1192 }
1193 proc_list_lock();
1194 oldpg = tp->t_pgrp;
1c79356b 1195 tp->t_pgrp = pgrp;
2d21ac55
A
1196 sessp->s_ttypgrpid = pgrp->pg_id;
1197 proc_list_unlock();
1198 if (oldpg != PGRP_NULL)
1199 pg_rele(oldpg);
1200 if (sessp != SESSION_NULL)
1201 session_rele(sessp);
1c79356b
A
1202 break;
1203 }
1204 case TIOCSTAT: /* simulate control-T */
1c79356b 1205 ttyinfo(tp);
1c79356b
A
1206 break;
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;
2d21ac55 1211 tty_pgsignal(tp, SIGWINCH, 1);
1c79356b
A
1212 }
1213 break;
1214 case TIOCSDRAINWAIT:
91447636 1215 error = suser(kauth_cred_get(), &p->p_acflag);
2d21ac55
A
1216 if (error) {
1217 goto out;
1218 }
1c79356b
A
1219 tp->t_timeout = *(int *)data * hz;
1220 wakeup(TSA_OCOMPLETE(tp));
1221 wakeup(TSA_OLOWAT(tp));
1222 break;
1223 case TIOCGDRAINWAIT:
1224 *(int *)data = tp->t_timeout / hz;
2d21ac55 1225 break;
1c79356b 1226 default:
91447636 1227#if COMPAT_43_TTY || defined(COMPAT_SUNOS)
2d21ac55 1228 error = ttcompat(tp, cmd, data, flag, p);
1c79356b 1229#else
2d21ac55 1230 error = ENOTTY;
1c79356b 1231#endif
2d21ac55 1232 goto out;
1c79356b
A
1233 }
1234
2d21ac55
A
1235 error = 0;
1236out:
1237 return(error);
1c79356b
A
1238}
1239
1240int
2d21ac55 1241ttyselect(struct tty *tp, int rw, void *wql, proc_t p)
1c79356b 1242{
1c79356b
A
1243 if (tp == NULL)
1244 return (ENXIO);
1245
1c79356b
A
1246 switch (rw) {
1247 case FREAD:
1248 if (ttnread(tp) > 0 || ISSET(tp->t_state, TS_ZOMBIE))
2d21ac55 1249 return(1);
0b4e3aa0 1250 selrecord(p, &tp->t_rsel, wql);
1c79356b
A
1251 break;
1252 case FWRITE:
1253 if ((tp->t_outq.c_cc <= tp->t_lowat &&
1254 ISSET(tp->t_state, TS_CONNECTED))
1255 || ISSET(tp->t_state, TS_ZOMBIE)) {
1c79356b
A
1256 return (1);
1257 }
0b4e3aa0 1258 selrecord(p, &tp->t_wsel, wql);
1c79356b
A
1259 break;
1260 }
1c79356b
A
1261 return (0);
1262}
1263
1264/*
1265 * This is a wrapper for compatibility with the select vector used by
1266 * cdevsw. It relies on a proper xxxdevtotty routine.
1267 */
1268int
2d21ac55 1269ttselect(dev_t dev, int rw, void *wql, proc_t p)
1c79356b 1270{
0b4e3aa0 1271 return ttyselect(cdevsw[major(dev)].d_ttys[minor(dev)], rw, wql, p);
1c79356b
A
1272}
1273
1274/*
1275 * Must be called at spltty().
1276 */
1277static int
2d21ac55 1278ttnread(struct tty *tp)
1c79356b
A
1279{
1280 int nread;
1281
1282 if (ISSET(tp->t_lflag, PENDIN))
1283 ttypend(tp);
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)
1288 nread = 0;
1289 }
1290 return (nread);
1291}
1292
1293/*
1294 * Wait for output to drain.
1295 */
1296int
2d21ac55 1297ttywait(struct tty *tp)
1c79356b 1298{
2d21ac55 1299 int error;
1c79356b
A
1300
1301 error = 0;
1c79356b
A
1302 while ((tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)) &&
1303 ISSET(tp->t_state, TS_CONNECTED) && tp->t_oproc) {
1304 (*tp->t_oproc)(tp);
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",
1310 tp->t_timeout);
1311 if (error) {
1312 if (error == EWOULDBLOCK)
1313 error = EIO;
1314 break;
1315 }
1316 } else
1317 break;
1318 }
1319 if (!error && (tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)))
1320 error = EIO;
1c79356b
A
1321 return (error);
1322}
1323
1324static void
2d21ac55 1325ttystop(struct tty *tp, int rw)
1c79356b 1326{
1c79356b 1327 (*cdevsw[major(tp->t_dev)].d_stop)(tp, rw);
1c79356b
A
1328}
1329
1330/*
1331 * Flush if successfully wait.
1332 */
1333static int
2d21ac55 1334ttywflush(struct tty *tp)
1c79356b
A
1335{
1336 int error;
1337
1338 if ((error = ttywait(tp)) == 0)
1339 ttyflush(tp, FREAD);
1340 return (error);
1341}
1342
1343/*
1344 * Flush tty read and/or write queues, notifying anyone waiting.
1345 */
1346void
2d21ac55 1347ttyflush(struct tty *tp, int rw)
1c79356b 1348{
1c79356b
A
1349#if 0
1350again:
1351#endif
1352 if (rw & FWRITE) {
1353 FLUSHQ(&tp->t_outq);
1354 CLR(tp->t_state, TS_TTSTOP);
1355 }
1356 ttystop(tp, rw);
1357 if (rw & FREAD) {
1358 FLUSHQ(&tp->t_canq);
1359 FLUSHQ(&tp->t_rawq);
1360 CLR(tp->t_lflag, PENDIN);
1361 tp->t_rocount = 0;
1362 tp->t_rocol = 0;
1363 CLR(tp->t_state, TS_LOCAL);
1364 ttwakeup(tp);
1365 if (ISSET(tp->t_state, TS_TBLOCK)) {
1366 if (rw & FWRITE)
1367 FLUSHQ(&tp->t_outq);
1368 ttyunblock(tp);
1369
1370 /*
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.
1376 */
1377 CLR(tp->t_state, TS_TBLOCK);
1378
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)) {
1381 /*
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
1388 * will save us.
1389 */
1390 SET(tp->t_state, TS_SO_OCOMPLETE);
1391 ttysleep(tp, TSA_OCOMPLETE(tp), TTOPRI,
1392 "ttyfls", hz / 10);
1393 /*
1394 * Don't try sending the stop character again.
1395 */
1396 CLR(tp->t_state, TS_TBLOCK);
1397 goto again;
1398 }
1399#endif
1400 }
1401 }
1402 if (rw & FWRITE) {
1403 FLUSHQ(&tp->t_outq);
1404 ttwwakeup(tp);
1405 }
1c79356b
A
1406}
1407
1408/*
1409 * Copy in the default termios characters.
1410 */
1411void
2d21ac55 1412termioschars(struct termios *t)
1c79356b 1413{
1c79356b
A
1414 bcopy(ttydefchars, t->c_cc, sizeof t->c_cc);
1415}
1416
1417/*
1418 * Old interface.
1419 */
1420void
2d21ac55 1421ttychars(struct tty *tp)
1c79356b 1422{
1c79356b
A
1423 termioschars(&tp->t_termios);
1424}
1425
1426/*
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.
1430 */
1431void
2d21ac55 1432ttyblock(struct tty *tp)
1c79356b 1433{
1c79356b
A
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 */
1438 ttstart(tp);
1439}
1440
1441/*
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.
1445 */
1446static void
2d21ac55 1447ttyunblock(struct tty *tp)
1c79356b 1448{
1c79356b
A
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 */
1453 ttstart(tp);
1454}
1455
1c79356b
A
1456/* FreeBSD: Not used by any current (i386) drivers. */
1457/*
1458 * Restart after an inter-char delay.
1459 */
1460void
2d21ac55 1461ttrstrt(void *tp_arg)
1c79356b
A
1462{
1463 struct tty *tp;
1c79356b
A
1464
1465#if DIAGNOSTIC
1466 if (tp_arg == NULL)
1467 panic("ttrstrt");
1468#endif
1469 tp = tp_arg;
1c79356b
A
1470
1471 CLR(tp->t_state, TS_TIMEOUT);
1472 ttstart(tp);
1473
1c79356b 1474}
1c79356b
A
1475
1476int
2d21ac55 1477ttstart(struct tty *tp)
1c79356b 1478{
0b4e3aa0
A
1479 boolean_t funnel_state;
1480
1481 funnel_state = thread_funnel_set(kernel_flock, TRUE);
1c79356b
A
1482
1483 if (tp->t_oproc != NULL) /* XXX: Kludge for pty. */
1484 (*tp->t_oproc)(tp);
0b4e3aa0 1485 thread_funnel_set(kernel_flock, funnel_state);
1c79356b
A
1486 return (0);
1487}
1488
1489/*
1490 * "close" a line discipline
1491 */
1492int
2d21ac55 1493ttylclose(struct tty *tp, int flag)
1c79356b 1494{
0b4e3aa0
A
1495 boolean_t funnel_state;
1496
1497 funnel_state = thread_funnel_set(kernel_flock, TRUE);
1c79356b
A
1498 if ( (flag & FNONBLOCK) || ttywflush(tp))
1499 ttyflush(tp, FREAD | FWRITE);
0b4e3aa0 1500 thread_funnel_set(kernel_flock, funnel_state);
1c79356b
A
1501 return (0);
1502}
1503
1504/*
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.
1508 */
1509int
2d21ac55 1510ttymodem(struct tty *tp, int flag)
1c79356b 1511{
0b4e3aa0
A
1512 boolean_t funnel_state;
1513
1514 funnel_state = thread_funnel_set(kernel_flock, TRUE);
1c79356b
A
1515
1516 if (ISSET(tp->t_state, TS_CARR_ON) && ISSET(tp->t_cflag, MDMBUF)) {
1517 /*
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.
1521 */
1522 if (flag) {
1523 CLR(tp->t_state, TS_CAR_OFLOW);
1524 CLR(tp->t_state, TS_TTSTOP);
1525 ttstart(tp);
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);
1529 ttystop(tp, 0);
1530 }
1531 } else if (flag == 0) {
1532 /*
1533 * Lost carrier.
1534 */
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);
0b4e3aa0 1543 thread_funnel_set(kernel_flock, funnel_state);
1c79356b
A
1544 return (0);
1545 }
1546 } else {
1547 /*
1548 * Carrier now on.
1549 */
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));
1554 ttwakeup(tp);
1555 ttwwakeup(tp);
1556 }
0b4e3aa0 1557 thread_funnel_set(kernel_flock, funnel_state);
1c79356b
A
1558 return (1);
1559}
1560
1561/*
1562 * Reinput pending characters after state switch
1563 * call at spltty().
1564 */
1565static void
2d21ac55 1566ttypend(struct tty *tp)
1c79356b
A
1567{
1568 struct clist tq;
2d21ac55 1569 int c;
1c79356b
A
1570
1571 CLR(tp->t_lflag, PENDIN);
1572 SET(tp->t_state, TS_TYPEN);
1c79356b
A
1573 tq = tp->t_rawq;
1574 tp->t_rawq.c_cc = 0;
2d21ac55 1575 tp->t_rawq.c_cf = tp->t_rawq.c_cl = NULL;
1c79356b
A
1576 while ((c = getc(&tq)) >= 0)
1577 ttyinput(c, tp);
1578 CLR(tp->t_state, TS_TYPEN);
1579}
1580
1581/*
1582 * Process a read call on a tty device.
1583 */
1584int
2d21ac55 1585ttread(struct tty *tp, struct uio *uio, int flag)
1c79356b 1586{
2d21ac55
A
1587 struct clist *qp;
1588 int c;
1589 tcflag_t lflag;
1590 cc_t *cc = tp->t_cc;
1591 proc_t p = current_proc();
1592 int first, error = 0;
1c79356b
A
1593 int has_etime = 0, last_cc = 0;
1594 long slp = 0; /* XXX this should be renamed `timo'. */
0b4e3aa0 1595 boolean_t funnel_state;
9bccf70c 1596 struct uthread *ut;
2d21ac55 1597 struct pgrp * pg;
1c79356b 1598
0b4e3aa0 1599 funnel_state = thread_funnel_set(kernel_flock, TRUE);
9bccf70c 1600
91447636 1601 ut = (struct uthread *)get_bsdthread_info(current_thread());
9bccf70c 1602
1c79356b 1603loop:
1c79356b
A
1604 lflag = tp->t_lflag;
1605 /*
1606 * take pending input first
1607 */
1608 if (ISSET(lflag, PENDIN)) {
1609 ttypend(tp);
1c79356b
A
1610 lflag = tp->t_lflag; /* XXX ttypend() clobbers it */
1611 }
1612
1613 /*
2d21ac55 1614 * Signal the process if it's in the background.
1c79356b
A
1615 */
1616 if (isbackground(p, tp)) {
1c79356b 1617 if ((p->p_sigignore & sigmask(SIGTTIN)) ||
9bccf70c 1618 (ut->uu_sigmask & sigmask(SIGTTIN)) ||
2d21ac55 1619 p->p_lflag & P_LPPWAIT) {
0b4e3aa0 1620 thread_funnel_set(kernel_flock, funnel_state);
1c79356b 1621 return (EIO);
0b4e3aa0 1622 }
2d21ac55
A
1623 pg = proc_pgrp(p);
1624 if (pg == PGRP_NULL) {
0b4e3aa0 1625 thread_funnel_set(kernel_flock, funnel_state);
2d21ac55 1626 return (EIO);
0b4e3aa0 1627 }
2d21ac55
A
1628 if (pg->pg_jobc == 0) {
1629 pg_rele(pg);
1630 thread_funnel_set(kernel_flock, funnel_state);
1631 return (EIO);
1632 }
1633 pgsignal(pg, SIGTTIN, 1);
1634 pg_rele(pg);
1635
1636 /*
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.
1641 */
1642 thread_funnel_set(kernel_flock, funnel_state);
1643 return (EINTR);
1c79356b
A
1644 }
1645
1646 if (ISSET(tp->t_state, TS_ZOMBIE)) {
0b4e3aa0 1647 thread_funnel_set(kernel_flock, funnel_state);
1c79356b
A
1648 return (0); /* EOF */
1649 }
1650
1651 /*
1652 * If canonical, use the canonical queue,
1653 * else use the raw queue.
1654 *
1655 * (should get rid of clists...)
1656 */
1657 qp = ISSET(lflag, ICANON) ? &tp->t_canq : &tp->t_rawq;
1658
1659 if (flag & IO_NDELAY) {
1660 if (qp->c_cc > 0)
1661 goto read;
1662 if (!ISSET(lflag, ICANON) && cc[VMIN] == 0) {
0b4e3aa0 1663 thread_funnel_set(kernel_flock, funnel_state);
1c79356b
A
1664 return (0);
1665 }
0b4e3aa0 1666 thread_funnel_set(kernel_flock, funnel_state);
1c79356b
A
1667 return (EWOULDBLOCK);
1668 }
1669 if (!ISSET(lflag, ICANON)) {
1670 int m = cc[VMIN];
1671 long t = cc[VTIME];
2d21ac55
A
1672 struct timeval timecopy;
1673 struct timeval etime = {0, 0}; /* protected by !has_etime */
1c79356b
A
1674
1675 /*
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
1681 * into slp.
1682 */
1683 if (t == 0) {
1684 if (qp->c_cc < m)
1685 goto sleep;
1686 if (qp->c_cc > 0)
1687 goto read;
1688
1689 /* m, t and qp->c_cc are all 0. 0 is enough input. */
0b4e3aa0 1690 thread_funnel_set(kernel_flock, funnel_state);
1c79356b
A
1691 return (0);
1692 }
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))
1696 if (m > 0) {
1697 if (qp->c_cc <= 0)
1698 goto sleep;
1699 if (qp->c_cc >= m)
1700 goto read;
91447636 1701 microuptime(&timecopy);
1c79356b
A
1702 if (!has_etime) {
1703 /* first character, start timer */
1704 has_etime = 1;
1705
1706 etime.tv_sec = t / 1000000;
1707 etime.tv_usec = (t - (etime.tv_sec * 1000000));
1708 timeradd(&etime, &timecopy, &etime);
1709
1710 slp = t;
1711 } else if (qp->c_cc > last_cc) {
1712 /* got a character, restart timer */
1713
1714 etime.tv_sec = t / 1000000;
1715 etime.tv_usec = (t - (etime.tv_sec * 1000000));
1716 timeradd(&etime, &timecopy, &etime);
1717
1718 slp = t;
1719 } else {
1720 /* nothing, check expiration */
1721 if (timercmp(&etime, &timecopy, <=))
1722 goto read;
1723
1724 slp = diff(etime, timecopy);
1725 }
1726 last_cc = qp->c_cc;
1727 } else { /* m == 0 */
1728 if (qp->c_cc > 0)
1729 goto read;
91447636 1730 microuptime(&timecopy);
1c79356b
A
1731 if (!has_etime) {
1732 has_etime = 1;
1733
1734 etime.tv_sec = t / 1000000;
1735 etime.tv_usec = (t - (etime.tv_sec * 1000000));
1736 timeradd(&etime, &timecopy, &etime);
1737
1738 slp = t;
1739 } else {
1740 if (timercmp(&etime, &timecopy, <=)) {
1741 /* Timed out, but 0 is enough input. */
0b4e3aa0 1742 thread_funnel_set(kernel_flock, funnel_state);
1c79356b
A
1743 return (0);
1744 }
1745 slp = diff(etime, timecopy);
1746 }
1747 }
1748#undef diff
1749 /*
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).
1757 */
1758 slp = (long) (((u_long)slp * hz) + 999999) / 1000000;
1759 goto sleep;
1760 }
1761 if (qp->c_cc <= 0) {
1762sleep:
1763 /*
1764 * There is no input, or not enough input and we can block.
1765 */
1766 error = ttysleep(tp, TSA_HUP_OR_INPUT(tp), TTIPRI | PCATCH,
1767 ISSET(tp->t_state, TS_CONNECTED) ?
1768 "ttyin" : "ttyhup", (int)slp);
1c79356b
A
1769 if (error == EWOULDBLOCK)
1770 error = 0;
0b4e3aa0
A
1771 else if (error) {
1772 thread_funnel_set(kernel_flock, funnel_state);
1c79356b 1773 return (error);
0b4e3aa0 1774 }
1c79356b
A
1775 /*
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).
1780 */
1781 slp = 0;
1782 goto loop;
1783 }
1784read:
1c79356b
A
1785 /*
1786 * Input present, check for input mapping and processing.
1787 */
1788 first = 1;
1c79356b
A
1789 if (ISSET(lflag, ICANON)
1790 || (ISSET(lflag, IEXTEN | ISIG) == (IEXTEN | ISIG)) )
1c79356b
A
1791 goto slowcase;
1792 for (;;) {
1793 char ibuf[IBUFSIZ];
1794 int icc;
1795
91447636 1796 icc = min(uio_resid(uio), IBUFSIZ);
2d21ac55 1797 icc = q_to_b(qp, (u_char *)ibuf, icc);
1c79356b
A
1798 if (icc <= 0) {
1799 if (first)
1800 goto loop;
1801 break;
1802 }
1803 error = uiomove(ibuf, icc, uio);
1804 /*
1805 * XXX if there was an error then we should ungetc() the
1806 * unmoved chars and reduce icc here.
1807 */
1c79356b
A
1808 if (error)
1809 break;
91447636 1810 if (uio_resid(uio) == 0)
1c79356b
A
1811 break;
1812 first = 0;
1813 }
1814 goto out;
1815slowcase:
1816 for (;;) {
1817 c = getc(qp);
1818 if (c < 0) {
1819 if (first)
1820 goto loop;
1821 break;
1822 }
1823 /*
1824 * delayed suspend (^Y)
1825 */
1826 if (CCEQ(cc[VDSUSP], c) &&
1827 ISSET(lflag, IEXTEN | ISIG) == (IEXTEN | ISIG)) {
2d21ac55 1828 tty_pgsignal(tp, SIGTSTP, 1);
1c79356b
A
1829 if (first) {
1830 error = ttysleep(tp, &lbolt, TTIPRI | PCATCH,
1831 "ttybg3", 0);
1832 if (error)
1833 break;
1834 goto loop;
1835 }
1836 break;
1837 }
1838 /*
1839 * Interpret EOF only in canonical mode.
1840 */
1841 if (CCEQ(cc[VEOF], c) && ISSET(lflag, ICANON))
1842 break;
1843 /*
1844 * Give user character.
1845 */
1846 error = ureadc(c, uio);
1847 if (error)
1848 /* XXX should ungetc(c, qp). */
1849 break;
91447636 1850 if (uio_resid(uio) == 0)
1c79356b
A
1851 break;
1852 /*
1853 * In canonical mode check for a "break character"
1854 * marking the end of a "line of input".
1855 */
1856 if (ISSET(lflag, ICANON) && TTBREAKC(c, lflag))
1857 break;
1858 first = 0;
1859 }
1860
1861out:
1862 /*
1863 * Look to unblock input now that (presumably)
1864 * the input queue has gone down.
1865 */
1c79356b
A
1866 if (ISSET(tp->t_state, TS_TBLOCK) &&
1867 tp->t_rawq.c_cc + tp->t_canq.c_cc <= I_LOW_WATER)
1868 ttyunblock(tp);
1c79356b 1869
0b4e3aa0 1870 thread_funnel_set(kernel_flock, funnel_state);
1c79356b
A
1871 return (error);
1872}
1873
1874/*
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
1879 * arrive.
1880 */
1881int
2d21ac55 1882ttycheckoutq(struct tty *tp, int wait)
1c79356b 1883{
2d21ac55 1884 int hiwat;
91447636 1885 sigset_t oldsig;
9bccf70c
A
1886 struct uthread *ut;
1887
91447636 1888 ut = (struct uthread *)get_bsdthread_info(current_thread());
1c79356b
A
1889
1890 hiwat = tp->t_hiwat;
9bccf70c 1891 oldsig = wait ? ut->uu_siglist : 0;
1c79356b
A
1892 if (tp->t_outq.c_cc > hiwat + OBUFSIZ + 100)
1893 while (tp->t_outq.c_cc > hiwat) {
1894 ttstart(tp);
1895 if (tp->t_outq.c_cc <= hiwat)
1896 break;
9bccf70c 1897 if (wait == 0 || ut->uu_siglist != oldsig) {
1c79356b
A
1898 return (0);
1899 }
1900 SET(tp->t_state, TS_SO_OLOWAT);
1901 tsleep(TSA_OLOWAT(tp), PZERO - 1, "ttoutq", hz);
1902 }
1c79356b
A
1903 return (1);
1904}
1905
1906/*
1907 * Process a write call on a tty device.
1908 */
1909int
2d21ac55 1910ttwrite(struct tty *tp, struct uio *uio, int flag)
1c79356b 1911{
2d21ac55
A
1912 char *cp = NULL;
1913 int cc, ce;
1914 proc_t p;
1915 int i, hiwat, count, error;
1c79356b 1916 char obuf[OBUFSIZ];
0b4e3aa0 1917 boolean_t funnel_state;
9bccf70c 1918 struct uthread *ut;
2d21ac55 1919 struct pgrp * pg;
0b4e3aa0
A
1920
1921 funnel_state = thread_funnel_set(kernel_flock, TRUE);
1c79356b 1922
91447636 1923 ut = (struct uthread *)get_bsdthread_info(current_thread());
1c79356b 1924 hiwat = tp->t_hiwat;
91447636
A
1925 // LP64todo - fix this!
1926 count = uio_resid(uio);
1c79356b
A
1927 error = 0;
1928 cc = 0;
1929loop:
1c79356b 1930 if (ISSET(tp->t_state, TS_ZOMBIE)) {
91447636 1931 if (uio_resid(uio) == count)
1c79356b
A
1932 error = EIO;
1933 goto out;
1934 }
1935 if (!ISSET(tp->t_state, TS_CONNECTED)) {
1936 if (flag & IO_NDELAY) {
1c79356b
A
1937 error = EWOULDBLOCK;
1938 goto out;
1939 }
1940 error = ttysleep(tp, TSA_CARR_ON(tp), TTIPRI | PCATCH,
1941 "ttydcd", 0);
1c79356b
A
1942 if (error) {
1943 goto out; }
1944 goto loop;
1945 }
1c79356b 1946 /*
2d21ac55 1947 * Signal the process if it's in the background.
1c79356b
A
1948 */
1949 p = current_proc();
1950 if (isbackground(p, tp) &&
2d21ac55 1951 ISSET(tp->t_lflag, TOSTOP) && (p->p_lflag & P_LPPWAIT) == 0 &&
1c79356b 1952 (p->p_sigignore & sigmask(SIGTTOU)) == 0 &&
9bccf70c 1953 (ut->uu_sigmask & sigmask(SIGTTOU)) == 0) {
2d21ac55
A
1954
1955 pg = proc_pgrp(p);
1956 if (pg == PGRP_NULL) {
1c79356b
A
1957 error = EIO;
1958 goto out;
1959 }
2d21ac55
A
1960 if (pg->pg_jobc == 0) {
1961 pg_rele(pg);
1962 error = EIO;
1963 goto out;
1964 }
1965 pgsignal(pg, SIGTTOU, 1);
1966 pg_rele(pg);
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 */
1973 error = EINTR;
1c79356b 1974 goto out;
1c79356b
A
1975 }
1976 /*
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.
1980 */
91447636 1981 while (uio_resid(uio) > 0 || cc > 0) {
1c79356b 1982 if (ISSET(tp->t_lflag, FLUSHO)) {
91447636 1983 uio_setresid(uio, 0);
0b4e3aa0 1984 thread_funnel_set(kernel_flock, funnel_state);
1c79356b
A
1985 return (0);
1986 }
1987 if (tp->t_outq.c_cc > hiwat)
1988 goto ovhiwat;
1989 /*
1990 * Grab a hunk of data from the user, unless we have some
1991 * leftover from last time.
1992 */
1993 if (cc == 0) {
91447636 1994 cc = min(uio_resid(uio), OBUFSIZ);
1c79356b
A
1995 cp = obuf;
1996 error = uiomove(cp, cc, uio);
1997 if (error) {
1998 cc = 0;
1999 break;
2000 }
1c79356b
A
2001 }
2002 /*
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
2009 * immediately.
2010 */
2011 while (cc > 0) {
2012 if (!ISSET(tp->t_oflag, OPOST))
2013 ce = cc;
2014 else {
2015 ce = cc - scanc((u_int)cc, (u_char *)cp,
91447636 2016 char_type, CCLASSMASK);
1c79356b
A
2017 /*
2018 * If ce is zero, then we're processing
2019 * a special character through ttyoutput.
2020 */
2021 if (ce == 0) {
2022 tp->t_rocount = 0;
2023 if (ttyoutput(*cp, tp) >= 0) {
1c79356b
A
2024 /* out of space */
2025 goto overfull;
1c79356b
A
2026 }
2027 cp++;
2028 cc--;
2029 if (ISSET(tp->t_lflag, FLUSHO) ||
2030 tp->t_outq.c_cc > hiwat)
2031 goto ovhiwat;
2032 continue;
2033 }
2034 }
2035 /*
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.
2042 */
2043 tp->t_rocount = 0;
2d21ac55 2044 i = b_to_q((u_char *)cp, ce, &tp->t_outq);
1c79356b
A
2045 ce -= i;
2046 tp->t_column += ce;
2047 cp += ce, cc -= ce, tk_nout += ce;
2048 tp->t_outcc += ce;
2049 if (i > 0) {
1c79356b
A
2050 /* out of space */
2051 goto overfull;
1c79356b
A
2052 }
2053 if (ISSET(tp->t_lflag, FLUSHO) ||
2054 tp->t_outq.c_cc > hiwat)
2055 break;
2056 }
2057 ttstart(tp);
2058 }
2059out:
2060 /*
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).
2064 */
91447636 2065 uio_setresid(uio, (uio_resid(uio) + cc));
0b4e3aa0 2066 thread_funnel_set(kernel_flock, funnel_state);
1c79356b
A
2067 return (error);
2068
1c79356b
A
2069overfull:
2070
2071 /*
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.
2076 */
2077 hiwat = tp->t_outq.c_cc - 1;
1c79356b
A
2078
2079ovhiwat:
2080 ttstart(tp);
1c79356b
A
2081 /*
2082 * This can only occur if FLUSHO is set in t_lflag,
2083 * or if ttstart/oproc is synchronous (or very fast).
2084 */
2085 if (tp->t_outq.c_cc <= hiwat) {
1c79356b
A
2086 goto loop;
2087 }
2088 if (flag & IO_NDELAY) {
91447636 2089 uio_setresid(uio, (uio_resid(uio) + cc));
0b4e3aa0 2090 thread_funnel_set(kernel_flock, funnel_state);
91447636 2091 return (uio_resid(uio) == count ? EWOULDBLOCK : 0);
1c79356b
A
2092 }
2093 SET(tp->t_state, TS_SO_OLOWAT);
2094 error = ttysleep(tp, TSA_OLOWAT(tp), TTOPRI | PCATCH, "ttywri",
2095 tp->t_timeout);
1c79356b
A
2096 if (error == EWOULDBLOCK)
2097 error = EIO;
2098 if (error)
2099 goto out;
2100 goto loop;
2101}
2102
2103/*
2104 * Rubout one character from the rawq of tp
2105 * as cleanly as possible.
2106 */
2107static void
2d21ac55 2108ttyrub(int c, struct tty *tp)
1c79356b 2109{
2d21ac55
A
2110 u_char *cp;
2111 int savecol;
2112 int tabc;
1c79356b
A
2113
2114 if (!ISSET(tp->t_lflag, ECHO) || ISSET(tp->t_lflag, EXTPROC))
2115 return;
2116 CLR(tp->t_lflag, FLUSHO);
2117 if (ISSET(tp->t_lflag, ECHOE)) {
2118 if (tp->t_rocount == 0) {
2119 /*
2120 * Messed up by ttwrite; retype
2121 */
2122 ttyretype(tp);
2123 return;
2124 }
2125 if (c == ('\t' | TTY_QUOTE) || c == ('\n' | TTY_QUOTE))
2126 ttyrubo(tp, 2);
2127 else {
2128 CLR(c, ~TTY_CHARMASK);
2129 switch (CCLASS(c)) {
2130 case ORDINARY:
2d21ac55
A
2131 if(!(ISSET(tp->t_iflag, IUTF8) && CCONT(c))) {
2132 ttyrubo(tp, 1);
2133 }
1c79356b
A
2134 break;
2135 case BACKSPACE:
2136 case CONTROL:
2137 case NEWLINE:
2138 case RETURN:
2139 case VTAB:
2140 if (ISSET(tp->t_lflag, ECHOCTL))
2141 ttyrubo(tp, 2);
2142 break;
2143 case TAB:
2144 if (tp->t_rocount < tp->t_rawq.c_cc) {
2145 ttyretype(tp);
2146 return;
2147 }
1c79356b
A
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;
1c79356b
A
2152 for (cp = firstc(&tp->t_rawq, &tabc); cp;
2153 cp = nextc(&tp->t_rawq, cp, &tabc))
2154 ttyecho(tabc, tp);
1c79356b
A
2155 CLR(tp->t_lflag, FLUSHO);
2156 CLR(tp->t_state, TS_CNTTB);
1c79356b
A
2157
2158 /* savecol will now be length of the tab. */
2159 savecol -= tp->t_column;
2160 tp->t_column += savecol;
2161 if (savecol > 8)
2162 savecol = 8; /* overflow fixup */
2163 while (--savecol >= 0)
2164 (void)ttyoutput('\b', tp);
2165 break;
2166 default: /* XXX */
2167#define PANICSTR "ttyrub: would panic c = %d, val = %d\n"
2d21ac55 2168 printf(PANICSTR, c, CCLASS(c));
1c79356b
A
2169#ifdef notdef
2170 panic(PANICSTR, c, CCLASS(c));
2171#endif
2172 }
2173 }
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);
2178 }
2179 ttyecho(c, tp);
2180 } else
2181 ttyecho(tp->t_cc[VERASE], tp);
2182 --tp->t_rocount;
2183}
2184
2185/*
91447636 2186 * Back over count characters, erasing them.
1c79356b
A
2187 */
2188static void
91447636 2189ttyrubo(struct tty *tp, int count)
1c79356b 2190{
91447636 2191 while (count-- > 0) {
1c79356b
A
2192 (void)ttyoutput('\b', tp);
2193 (void)ttyoutput(' ', tp);
2194 (void)ttyoutput('\b', tp);
2195 }
2196}
2197
2198/*
2199 * ttyretype --
2200 * Reprint the rawq line. Note, it is assumed that c_cc has already
2201 * been checked.
2202 */
2203static void
2d21ac55 2204ttyretype(struct tty *tp)
1c79356b 2205{
2d21ac55
A
2206 u_char *cp;
2207 int c;
1c79356b
A
2208
2209 /* Echo the reprint character. */
2210 if (tp->t_cc[VREPRINT] != _POSIX_VDISABLE)
2211 ttyecho(tp->t_cc[VREPRINT], tp);
2212
2213 (void)ttyoutput('\n', tp);
2214
2215 /*
2216 * FREEBSD XXX
2217 * FIX: NEXTC IS BROKEN - DOESN'T CHECK QUOTE
2218 * BIT OF FIRST CHAR.
2219 */
1c79356b
A
2220 for (cp = firstc(&tp->t_canq, &c); cp; cp = nextc(&tp->t_canq, cp, &c))
2221 ttyecho(c, tp);
2222 for (cp = firstc(&tp->t_rawq, &c); cp; cp = nextc(&tp->t_rawq, cp, &c))
2223 ttyecho(c, tp);
1c79356b 2224 CLR(tp->t_state, TS_ERASE);
1c79356b
A
2225
2226 tp->t_rocount = tp->t_rawq.c_cc;
2227 tp->t_rocol = 0;
2228}
2229
2230/*
2231 * Echo a typed character to the terminal.
2232 */
2233static void
2d21ac55 2234ttyecho(int c, struct tty *tp)
1c79356b 2235{
1c79356b
A
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))
2241 return;
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);
2247 if (c == 0177)
2248 c = '?';
2249 else
2250 c += 'A' - 1;
2251 }
2252 (void)ttyoutput(c, tp);
2253}
2254
2255/*
2256 * Wake up any readers on a tty.
2257 */
2258void
2d21ac55 2259ttwakeup(struct tty *tp)
1c79356b 2260{
2d21ac55 2261 selwakeup(&tp->t_rsel);
1c79356b 2262 if (ISSET(tp->t_state, TS_ASYNC))
2d21ac55 2263 tty_pgsignal(tp, SIGIO, 1);
1c79356b
A
2264 wakeup(TSA_HUP_OR_INPUT(tp));
2265}
2266
2267/*
2268 * Wake up any writers on a tty.
2269 */
2270void
2d21ac55 2271ttwwakeup(struct tty *tp)
1c79356b 2272{
1c79356b 2273 if (tp->t_outq.c_cc <= tp->t_lowat)
1c79356b
A
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));
2279 }
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));
2284 }
2285}
2286
2287/*
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.
2290 */
2291int
2d21ac55 2292ttspeedtab(int speed, struct speedtab *table)
1c79356b 2293{
1c79356b
A
2294 for ( ; table->sp_speed != -1; table++)
2295 if (table->sp_speed == speed)
2296 return (table->sp_code);
2297 return (-1);
2298}
2299
2300/*
2301 * Set tty hi and low water marks.
2302 *
2303 * Try to arrange the dynamics so there's about one second
2304 * from hi to low water.
2305 *
2306 */
2307void
91447636 2308ttsetwater(struct tty *tp)
1c79356b 2309{
91447636
A
2310 int cps;
2311 unsigned int x;
1c79356b
A
2312
2313#define CLAMP(x, h, l) ((x) > h ? h : ((x) < l) ? l : (x))
2314
2315 cps = tp->t_ospeed / 10;
2316 tp->t_lowat = x = CLAMP(cps / 2, TTMAXLOWAT, TTMINLOWAT);
2317 x += cps;
2318 x = CLAMP(x, TTMAXHIWAT, TTMINHIWAT);
2319 tp->t_hiwat = roundup(x, CBSIZE);
2320#undef CLAMP
2321}
2322
2d21ac55 2323/* ttyinfo has been converted to the MACH kernel */
1c79356b
A
2324#include <mach/thread_info.h>
2325
91447636
A
2326/* XXX Should be in Mach header <kern/thread.h>, but doesn't work */
2327extern 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);
2331
1c79356b
A
2332/*
2333 * Report on state of foreground process group.
2334 */
2335void
91447636 2336ttyinfo(struct tty *tp)
1c79356b 2337{
91447636
A
2338 int load;
2339 thread_t thread;
2340 uthread_t uthread;
2d21ac55
A
2341 proc_t p;
2342 proc_t pick;
2343 pid_t pickpid;
91447636
A
2344 const char *state;
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;
2d21ac55
A
2349 struct pgrp * pg;
2350
91447636
A
2351
2352 if (ttycheckoutq(tp,0) == 0)
2353 return;
2354
2355 /* Print load average. */
2356 load = (averunnable.ldavg[0] * 100 + FSCALE / 2) >> FSHIFT;
2357 ttyprintf(tp, "load: %d.%02d ", load / 100, load % 100);
2358
2359 /*
2360 * On return following a ttyprintf(), we set tp->t_rocount to 0 so
2361 * that pending input will be retyped on BS.
2362 */
2363 if (tp->t_session == NULL) {
2364 ttyprintf(tp, "not a controlling terminal\n");
2365 tp->t_rocount = 0;
2366 return;
2367}
2368 if (tp->t_pgrp == NULL) {
2369 ttyprintf(tp, "no foreground process group\n");
2370 tp->t_rocount = 0;
2371 return;
2372 }
2373 /* first process in process group */
2d21ac55 2374 /* XXX is there a need for pgrp lock ? */
91447636
A
2375 if ((p = tp->t_pgrp->pg_members.lh_first) == NULL) {
2376 ttyprintf(tp, "empty foreground process group\n");
2377 tp->t_rocount = 0;
2378 return;
2379 }
2380
2381 /*
2382 * Pick the most interesting process and copy some of its
2383 * state for printing later.
2384 */
2d21ac55
A
2385 pg = proc_pgrp(p);
2386 pgrp_lock(pg);
2387 /* the proc_compare is non blocking fn, no need to use iterator */
91447636 2388 for (pick = NULL; p != NULL; p = p->p_pglist.le_next) {
2d21ac55 2389 if (proc_compare(pick, p)) {
91447636 2390 pick = p;
2d21ac55
A
2391 pickpid = p->p_pid;
2392 } else {
2393 pickpid = pick->p_pid;
2394 }
91447636 2395 }
2d21ac55
A
2396 pgrp_unlock(pg);
2397 pg_rele(pg);
2398
2399 pick = proc_find(pickpid);
2400 if (pick == PROC_NULL)
2401 return;
91447636
A
2402
2403 if (TAILQ_EMPTY(&pick->p_uthlist) ||
2404 (uthread = TAILQ_FIRST(&pick->p_uthlist)) == NULL ||
2d21ac55 2405 (thread = vfs_context_thread(&uthread->uu_context)) == NULL ||
91447636
A
2406 (thread_info_internal(thread, THREAD_BASIC_INFO, (thread_info_t)&basic_info, &mmtn) != KERN_SUCCESS)) {
2407 ttyprintf(tp, "foreground process without thread\n");
2408 tp->t_rocount = 0;
2d21ac55 2409 proc_rele(pick);
91447636
A
2410 return;
2411 }
2412
2413 switch(basic_info.run_state) {
2414 case TH_STATE_RUNNING:
2415 state = "running";
2416 break;
2417 case TH_STATE_STOPPED:
2418 state = "stopped";
2419 break;
2420 case TH_STATE_WAITING:
2421 state = "waiting";
2422 break;
2423 case TH_STATE_UNINTERRUPTIBLE:
2424 state = "uninterruptible";
2425 break;
2426 case TH_STATE_HALTED:
2427 state = "halted";
2428 break;
2429 default:
2430 state = "unknown";
2431 break;
2432 }
2433 calcru(pick, &utime, &stime, NULL);
2d21ac55 2434 proc_rele(pick);
91447636
A
2435
2436 /* Print command, pid, state, utime, and stime */
2437 ttyprintf(tp, " cmd: %s %d %s %ld.%02ldu %ld.%02lds\n",
2438 pick->p_comm,
2439 pick->p_pid,
2440 state,
2441 (long)utime.tv_sec, utime.tv_usec / 10000,
2442 (long)stime.tv_sec, stime.tv_usec / 10000);
2443 tp->t_rocount = 0;
1c79356b
A
2444}
2445
1c79356b
A
2446/*
2447 * Returns 1 if p2 is "better" than p1
2448 *
2449 * The algorithm for picking the "interesting" process is thus:
2450 *
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.
91447636 2455 * 3) The sleeper with the shortest sleep time is next.
1c79356b
A
2456 * 4) Further ties are broken by picking the highest pid.
2457 */
2458#define ISRUN(p) (((p)->p_stat == SRUN) || ((p)->p_stat == SIDL))
2459#define TESTAB(a, b) ((a)<<1 | (b))
2460#define ONLYA 2
2461#define ONLYB 1
2462#define BOTH 3
2463
2464static int
2d21ac55 2465proc_compare(proc_t p1, proc_t p2)
1c79356b 2466{
2d21ac55 2467 /* NOTE THIS FN needs to be NON BLOCKING */
1c79356b
A
2468
2469 if (p1 == NULL)
2470 return (1);
2471 /*
2472 * see if at least one of them is runnable
2473 */
2474 switch (TESTAB(ISRUN(p1), ISRUN(p2))) {
2475 case ONLYA:
2476 return (0);
2477 case ONLYB:
2478 return (1);
2479 case BOTH:
2480 /*
2481 * tie - favor one with highest recent cpu utilization
2482 */
2d21ac55
A
2483#ifdef _PROC_HAS_SCHEDINFO_
2484 /* Without the support the fields are always zero */
1c79356b
A
2485 if (p2->p_estcpu > p1->p_estcpu)
2486 return (1);
2487 if (p1->p_estcpu > p2->p_estcpu)
2488 return (0);
2d21ac55 2489#endif /* _PROC_HAS_SCHEDINFO_ */
1c79356b
A
2490 return (p2->p_pid > p1->p_pid); /* tie - return highest pid */
2491 }
2492 /*
2493 * weed out zombies
2494 */
2495 switch (TESTAB(p1->p_stat == SZOMB, p2->p_stat == SZOMB)) {
2496 case ONLYA:
2497 return (1);
2498 case ONLYB:
2499 return (0);
2500 case BOTH:
2501 return (p2->p_pid > p1->p_pid); /* tie - return highest pid */
2502 }
2503 /*
2504 * pick the one with the smallest sleep time
2505 */
2d21ac55
A
2506#ifdef _PROC_HAS_SCHEDINFO_
2507 /* Without the support the fields are always zero */
1c79356b
A
2508 if (p2->p_slptime > p1->p_slptime)
2509 return (0);
2510 if (p1->p_slptime > p2->p_slptime)
2511 return (1);
2d21ac55 2512#endif /* _PROC_HAS_SCHEDINFO_ */
1c79356b
A
2513 return (p2->p_pid > p1->p_pid); /* tie - return highest pid */
2514}
1c79356b
A
2515
2516/*
2517 * Output char to tty; console putchar style.
2518 */
2519int
2d21ac55 2520tputchar(int c, struct tty *tp)
1c79356b 2521{
1c79356b 2522 if (!ISSET(tp->t_state, TS_CONNECTED)) {
1c79356b
A
2523 return (-1);
2524 }
2525 if (c == '\n')
2526 (void)ttyoutput('\r', tp);
2527 (void)ttyoutput(c, tp);
2528 ttstart(tp);
1c79356b
A
2529 return (0);
2530}
2531
2532/*
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.
2537 */
2538int
91447636 2539ttysleep(struct tty *tp, void *chan, int pri, const char *wmesg, int timo)
1c79356b
A
2540{
2541 int error;
2542 int gen;
2543
2544 gen = tp->t_gen;
2545 error = tsleep(chan, pri, wmesg, timo);
2546 if (error)
2547 return (error);
2548 return (tp->t_gen == gen ? 0 : ERESTART);
2549}
2550
1c79356b
A
2551/*
2552 * Allocate a tty structure and its associated buffers.
2d21ac55
A
2553 *
2554 * Parameters: void
2555 *
2556 * Returns: !NULL Address of new struct tty
2557 * NULL Error ("ENOMEM")
1c79356b
A
2558 */
2559struct tty *
91447636 2560ttymalloc(void)
1c79356b
A
2561{
2562 struct tty *tp;
2563
91447636
A
2564 MALLOC(tp, struct tty *, sizeof(struct tty), M_TTYS, M_WAITOK|M_ZERO);
2565 if (tp != NULL) {
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);
2571 }
1c79356b
A
2572 return(tp);
2573}
2574
2575/*
2576 * Free a tty structure and its buffers.
2577 */
2578void
2d21ac55 2579ttyfree(struct tty *tp)
1c79356b
A
2580{
2581 clfree(&tp->t_rawq);
2582 clfree(&tp->t_canq);
2583 clfree(&tp->t_outq);
2584 FREE(tp, M_TTYS);
2585}
2586
2d21ac55
A
2587int
2588isbackground(proc_t p, struct tty *tp)
2589{
2590 return (isctty(p, tp) && (p->p_pgrp != tp->t_pgrp));
2591}
1c79356b 2592
2d21ac55
A
2593static int
2594isctty(proc_t p, struct tty *tp)
1c79356b 2595{
2d21ac55
A
2596 int retval;
2597 struct session * sessp;
1c79356b 2598
2d21ac55
A
2599 sessp = proc_session(p);
2600 retval = (sessp == tp->t_session && p->p_flag & P_CONTROLT);
2601 session_rele(sessp);
2602 return(retval);
1c79356b 2603}
1c79356b 2604
2d21ac55
A
2605static int
2606isctty_sp(proc_t p, struct tty *tp, struct session *sessp)
1c79356b 2607{
2d21ac55
A
2608 return(sessp == tp->t_session && p->p_flag & P_CONTROLT);
2609
1c79356b 2610}
2d21ac55 2611