]> git.saurik.com Git - apple/xnu.git/blame - bsd/kern/tty.c
xnu-792.12.6.tar.gz
[apple/xnu.git] / bsd / kern / tty.c
CommitLineData
1c79356b 1/*
8ad349bb 2 * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved.
1c79356b 3 *
8ad349bb 4 * @APPLE_LICENSE_OSREFERENCE_HEADER_START@
1c79356b 5 *
8ad349bb
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
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
14 * agreement.
15 *
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
18 * file.
19 *
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
27 *
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
1c79356b
A
29 */
30/* Copyright (c) 1997 Apple Computer, Inc. All Rights Reserved */
31/*-
32 * Copyright (c) 1982, 1986, 1990, 1991, 1993
33 * The Regents of the University of California. All rights reserved.
34 * (c) UNIX System Laboratories, Inc.
35 * All or some portions of this file are derived from material licensed
36 * to the University of California by American Telephone and Telegraph
37 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
38 * the permission of UNIX System Laboratories, Inc.
39 *
40 * Redistribution and use in source and binary forms, with or without
41 * modification, are permitted provided that the following conditions
42 * are met:
43 * 1. Redistributions of source code must retain the above copyright
44 * notice, this list of conditions and the following disclaimer.
45 * 2. Redistributions in binary form must reproduce the above copyright
46 * notice, this list of conditions and the following disclaimer in the
47 * documentation and/or other materials provided with the distribution.
48 * 3. All advertising materials mentioning features or use of this software
49 * must display the following acknowledgement:
50 * This product includes software developed by the University of
51 * California, Berkeley and its contributors.
52 * 4. Neither the name of the University nor the names of its contributors
53 * may be used to endorse or promote products derived from this software
54 * without specific prior written permission.
55 *
56 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
57 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
58 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
59 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
60 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
61 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
62 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
63 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
64 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
65 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
66 * SUCH DAMAGE.
67 *
68 * @(#)tty.c 8.8 (Berkeley) 1/21/94
69 */
70/*-
71 * TODO:
72 * o Fix races for sending the start char in ttyflush().
73 * o Handle inter-byte timeout for "MIN > 0, TIME > 0" in ttyselect().
74 * With luck, there will be MIN chars before select() returns().
75 * o Handle CLOCAL consistently for ptys. Perhaps disallow setting it.
76 * o Don't allow input in TS_ZOMBIE case. It would be visible through
77 * FIONREAD.
78 * o Do the new sio locking stuff here and use it to avoid special
79 * case for EXTPROC?
80 * o Lock PENDIN too?
81 * o Move EXTPROC and/or PENDIN to t_state?
82 * o Wrap most of ttioctl in spltty/splx.
83 * o Implement TIOCNOTTY or remove it from <sys/ioctl.h>.
84 * o Send STOP if IXOFF is toggled off while TS_TBLOCK is set.
85 * o Don't allow certain termios flags to affect disciplines other
86 * than TTYDISC. Cancel their effects before switch disciplines
87 * and ignore them if they are set while we are in another
88 * discipline.
89 * o Handle c_ispeed = 0 to c_ispeed = c_ospeed conversion here instead
90 * of in drivers and fix drivers that write to tp->t_termios.
91 * o Check for TS_CARR_ON being set while everything is closed and not
92 * waiting for carrier. TS_CARR_ON isn't cleared if nothing is open,
93 * so it would live until the next open even if carrier drops.
94 * o Restore TS_WOPEN since it is useful in pstat. It must be cleared
95 * only when _all_ openers leave open().
96 */
97#ifdef NeXT
98#define NSNP 0
99#else
100#include "snp.h"
101#include "opt_uconsole.h"
102#endif
103
104#include <sys/param.h>
105#define TTYDEFCHARS 1
106#include <sys/systm.h>
107#undef TTYDEFCHARS
108#include <sys/ioctl.h>
91447636
A
109#include <sys/proc_internal.h>
110#include <sys/kauth.h>
111#include <sys/file_internal.h>
1c79356b
A
112#include <sys/conf.h>
113#include <sys/dkstat.h>
114#include <sys/uio.h>
115#include <sys/kernel.h>
116#include <sys/vnode.h>
117#include <sys/syslog.h>
9bccf70c
A
118#include <sys/user.h>
119#include <sys/signalvar.h>
1c79356b
A
120#include <sys/signalvar.h>
121#ifndef NeXT
122#include <sys/resourcevar.h>
123#endif
124#include <sys/malloc.h>
125#if NSNP > 0
126#include <sys/snoop.h>
127#endif
128
129#ifndef NeXT
130#include <vm/vm.h>
131#include <vm/vm_param.h>
132#include <vm/vm_prot.h>
133#include <vm/lock.h>
134#include <vm/pmap.h>
135#include <vm/vm_map.h>
136#else
137#include <dev/kmreg_com.h>
138#include <machine/cons.h>
139#include <machine/spl.h>
140#if 0 /* [ */
141#include <machdep/machine/pmap.h>
142#endif /* 0 ] */
143#endif /* !NeXT */
91447636 144#include <sys/resource.h> /* averunnable */
1c79356b
A
145
146#ifndef NeXT
91447636 147static int proc_compare(struct proc *p1, struct proc *p2);
1c79356b 148#endif /* NeXT */
91447636
A
149static int ttnread(struct tty *tp);
150static void ttyecho(int c, struct tty *tp);
151static int ttyoutput(int c, register struct tty *tp);
152static void ttypend(struct tty *tp);
153static void ttyretype(struct tty *tp);
154static void ttyrub(int c, struct tty *tp);
155static void ttyrubo(struct tty *tp, int count);
156static void ttystop(struct tty *tp, int rw);
157static void ttyunblock(struct tty *tp);
158static int ttywflush(struct tty *tp);
159static int proc_compare(struct proc *p1, struct proc *p2);
1c79356b
A
160
161/*
162 * Table with character classes and parity. The 8th bit indicates parity,
163 * the 7th bit indicates the character is an alphameric or underscore (for
164 * ALTWERASE), and the low 6 bits indicate delay type. If the low 6 bits
165 * are 0 then the character needs no special processing on output; classes
166 * other than 0 might be translated or (not currently) require delays.
167 */
168#define E 0x00 /* Even parity. */
169#define O 0x80 /* Odd parity. */
170#define PARITY(c) (char_type[c] & O)
171
172#define ALPHA 0x40 /* Alpha or underscore. */
173#define ISALPHA(c) (char_type[(c) & TTY_CHARMASK] & ALPHA)
174
175#define CCLASSMASK 0x3f
176#define CCLASS(c) (char_type[c] & CCLASSMASK)
177
178#define BS BACKSPACE
179#define CC CONTROL
180#define CR RETURN
181#define NA ORDINARY | ALPHA
182#define NL NEWLINE
183#define NO ORDINARY
184#define TB TAB
185#define VT VTAB
186
187static u_char const char_type[] = {
188 E|CC, O|CC, O|CC, E|CC, O|CC, E|CC, E|CC, O|CC, /* nul - bel */
189 O|BS, E|TB, E|NL, O|CC, E|VT, O|CR, O|CC, E|CC, /* bs - si */
190 O|CC, E|CC, E|CC, O|CC, E|CC, O|CC, O|CC, E|CC, /* dle - etb */
191 E|CC, O|CC, O|CC, E|CC, O|CC, E|CC, E|CC, O|CC, /* can - us */
192 O|NO, E|NO, E|NO, O|NO, E|NO, O|NO, O|NO, E|NO, /* sp - ' */
193 E|NO, O|NO, O|NO, E|NO, O|NO, E|NO, E|NO, O|NO, /* ( - / */
194 E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* 0 - 7 */
195 O|NA, E|NA, E|NO, O|NO, E|NO, O|NO, O|NO, E|NO, /* 8 - ? */
196 O|NO, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA, /* @ - G */
197 E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* H - O */
198 E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* P - W */
199 O|NA, E|NA, E|NA, O|NO, E|NO, O|NO, O|NO, O|NA, /* X - _ */
200 E|NO, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* ` - g */
201 O|NA, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA, /* h - o */
202 O|NA, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA, /* p - w */
203 E|NA, O|NA, O|NA, E|NO, O|NO, E|NO, E|NO, O|CC, /* x - del */
204 /*
205 * Meta chars; should be settable per character set;
206 * for now, treat them all as normal characters.
207 */
208 NA, NA, NA, NA, NA, NA, NA, NA,
209 NA, NA, NA, NA, NA, NA, NA, NA,
210 NA, NA, NA, NA, NA, NA, NA, NA,
211 NA, NA, NA, NA, NA, NA, NA, NA,
212 NA, NA, NA, NA, NA, NA, NA, NA,
213 NA, NA, NA, NA, NA, NA, NA, NA,
214 NA, NA, NA, NA, NA, NA, NA, NA,
215 NA, NA, NA, NA, NA, NA, NA, NA,
216 NA, NA, NA, NA, NA, NA, NA, NA,
217 NA, NA, NA, NA, NA, NA, NA, NA,
218 NA, NA, NA, NA, NA, NA, NA, NA,
219 NA, NA, NA, NA, NA, NA, NA, NA,
220 NA, NA, NA, NA, NA, NA, NA, NA,
221 NA, NA, NA, NA, NA, NA, NA, NA,
222 NA, NA, NA, NA, NA, NA, NA, NA,
223 NA, NA, NA, NA, NA, NA, NA, NA,
224};
225#undef BS
226#undef CC
227#undef CR
228#undef NA
229#undef NL
230#undef NO
231#undef TB
232#undef VT
233
234/* Macros to clear/set/test flags. */
235#define SET(t, f) (t) |= (f)
236#define CLR(t, f) (t) &= ~(f)
237#define ISSET(t, f) ((t) & (f))
238
239/*
240 * Input control starts when we would not be able to fit the maximum
241 * contents of the ping-pong buffers and finishes when we would be able
242 * to fit that much plus 1/8 more.
243 */
244#define I_HIGH_WATER (TTYHOG - 2 * 256) /* XXX */
245#define I_LOW_WATER ((TTYHOG - 2 * 256) * 7 / 8) /* XXX */
246
247#undef MAX_INPUT /* XXX wrong in <sys/syslimits.h> */
248#define MAX_INPUT TTYHOG
249
91447636
A
250static void
251termios32to64(struct termios *in, struct user_termios *out)
252{
253 out->c_iflag = (user_tcflag_t)in->c_iflag;
254 out->c_oflag = (user_tcflag_t)in->c_oflag;
255 out->c_cflag = (user_tcflag_t)in->c_cflag;
256 out->c_lflag = (user_tcflag_t)in->c_lflag;
257
258 /* bcopy is OK, since this type is ILP32/LP64 size invariant */
259 bcopy(in->c_cc, out->c_cc, sizeof(in->c_cc));
260
261 out->c_ispeed = (user_speed_t)in->c_ispeed;
262 out->c_ospeed = (user_speed_t)in->c_ospeed;
263}
264
265static void
266termios64to32(struct user_termios *in, struct termios *out)
267{
268 out->c_iflag = (tcflag_t)in->c_iflag;
269 out->c_oflag = (tcflag_t)in->c_oflag;
270 out->c_cflag = (tcflag_t)in->c_cflag;
271 out->c_lflag = (tcflag_t)in->c_lflag;
272
273 /* bcopy is OK, since this type is ILP32/LP64 size invariant */
274 bcopy(in->c_cc, out->c_cc, sizeof(in->c_cc));
275
276 out->c_ispeed = (speed_t)in->c_ispeed;
277 out->c_ospeed = (speed_t)in->c_ospeed;
278}
279
280
1c79356b
A
281/*
282 * Initial open of tty, or (re)entry to standard tty line discipline.
283 */
284int
285ttyopen(device, tp)
286 dev_t device;
287 register struct tty *tp;
288{
289 int s;
0b4e3aa0 290 boolean_t funnel_state;
1c79356b 291
0b4e3aa0 292 funnel_state = thread_funnel_set(kernel_flock, TRUE);
1c79356b
A
293 s = spltty();
294 tp->t_dev = device;
295 if (!ISSET(tp->t_state, TS_ISOPEN)) {
296 SET(tp->t_state, TS_ISOPEN);
297 if (ISSET(tp->t_cflag, CLOCAL)) {
298 SET(tp->t_state, TS_CONNECTED); }
299 bzero(&tp->t_winsize, sizeof(tp->t_winsize));
300 }
301
302#ifndef NeXT
303 /*
304 * Initialize or restore a cblock allocation policy suitable for
305 * the standard line discipline.
306 */
307 clist_alloc_cblocks(&tp->t_canq, TTYHOG, 512);
308 clist_alloc_cblocks(&tp->t_outq, TTMAXHIWAT + OBUFSIZ + 100,
309 TTMAXHIWAT + OBUFSIZ + 100);
310 clist_alloc_cblocks(&tp->t_rawq, TTYHOG, TTYHOG);
311#endif /* !NeXT */
312
313 splx(s);
0b4e3aa0 314 thread_funnel_set(kernel_flock, funnel_state);
1c79356b
A
315 return (0);
316}
317
318/*
319 * Handle close() on a tty line: flush and set to initial state,
320 * bumping generation number so that pending read/write calls
321 * can detect recycling of the tty.
322 * XXX our caller should have done `spltty(); l_close(); ttyclose();'
323 * and l_close() should have flushed, but we repeat the spltty() and
324 * the flush in case there are buggy callers.
325 */
326int
327ttyclose(tp)
328 register struct tty *tp;
329{
330 int s;
331
332 s = spltty();
333 if (constty == tp) {
334 constty = NULL;
335
336splx(s);
337spltty();
338
339#ifdef NeXT
340 /*
341 * Closing current console tty; disable printing of console
342 * messages at bottom-level driver.
343 */
344 (*cdevsw[major(tp->t_dev)].d_ioctl)
345 (tp->t_dev, KMIOCDISABLCONS, NULL, 0, current_proc());
346#endif /* NeXT */
347 }
348
349 ttyflush(tp, FREAD | FWRITE);
350#ifndef NeXT
351 clist_free_cblocks(&tp->t_canq);
352 clist_free_cblocks(&tp->t_outq);
353 clist_free_cblocks(&tp->t_rawq);
354#endif
355
356#if NSNP > 0
357 if (ISSET(tp->t_state, TS_SNOOP) && tp->t_sc != NULL)
358 snpdown((struct snoop *)tp->t_sc);
359#endif
360
361 tp->t_gen++;
362 tp->t_line = TTYDISC;
363 tp->t_pgrp = NULL;
364 tp->t_session = NULL;
365 tp->t_state = 0;
366#if NeXT
367 selthreadclear(&tp->t_wsel);
368 selthreadclear(&tp->t_rsel);
369#endif
370 splx(s);
371 return (0);
372}
373
374#define FLUSHQ(q) { \
375 if ((q)->c_cc) \
376 ndflush(q, (q)->c_cc); \
377}
378
379/* Is 'c' a line delimiter ("break" character)? */
380#define TTBREAKC(c, lflag) \
381 ((c) == '\n' || (((c) == cc[VEOF] || \
382 (c) == cc[VEOL] || ((c) == cc[VEOL2] && lflag & IEXTEN)) && \
383 (c) != _POSIX_VDISABLE))
384
385/*
386 * Process input of a single character received on a tty.
387 */
388int
389ttyinput(c, tp)
390 register int c;
391 register struct tty *tp;
392{
393 register tcflag_t iflag, lflag;
394 register cc_t *cc;
395 int i, err, retval;
396 boolean_t funnel_state;
397
398 funnel_state = thread_funnel_set(kernel_flock, TRUE);
399
400 /*
401 * If input is pending take it first.
402 */
403 lflag = tp->t_lflag;
404 if (ISSET(lflag, PENDIN))
405 ttypend(tp);
406 /*
407 * Gather stats.
408 */
409 if (ISSET(lflag, ICANON)) {
410 ++tk_cancc;
411 ++tp->t_cancc;
412 } else {
413 ++tk_rawcc;
414 ++tp->t_rawcc;
415 }
416 ++tk_nin;
417
418 /*
419 * Block further input iff:
420 * current input > threshold AND input is available to user program
421 * AND input flow control is enabled and not yet invoked.
422 * The 3 is slop for PARMRK.
423 */
424 iflag = tp->t_iflag;
425 if (tp->t_rawq.c_cc + tp->t_canq.c_cc > I_HIGH_WATER - 3 &&
426 (!ISSET(lflag, ICANON) || tp->t_canq.c_cc != 0) &&
427 (ISSET(tp->t_cflag, CRTS_IFLOW) || ISSET(iflag, IXOFF)) &&
428 !ISSET(tp->t_state, TS_TBLOCK))
429 ttyblock(tp);
430
431 /* Handle exceptional conditions (break, parity, framing). */
432 cc = tp->t_cc;
433 err = (ISSET(c, TTY_ERRORMASK));
434 if (err) {
435 CLR(c, TTY_ERRORMASK);
436 if (ISSET(err, TTY_BI)) {
437 if (ISSET(iflag, IGNBRK)) {
438 thread_funnel_set(kernel_flock, funnel_state);
439 return (0);
440 }
441 if (ISSET(iflag, BRKINT)) {
442 ttyflush(tp, FREAD | FWRITE);
443 pgsignal(tp->t_pgrp, SIGINT, 1);
444 goto endcase;
445 }
446 if (ISSET(iflag, PARMRK))
447 goto parmrk;
448 } else if ((ISSET(err, TTY_PE) && ISSET(iflag, INPCK))
449 || ISSET(err, TTY_FE)) {
450 if (ISSET(iflag, IGNPAR)) {
451 thread_funnel_set(kernel_flock, funnel_state);
452 return (0);
453 }
454 else if (ISSET(iflag, PARMRK)) {
455parmrk:
456 if (tp->t_rawq.c_cc + tp->t_canq.c_cc >
457 MAX_INPUT - 3)
458 goto input_overflow;
459 (void)putc(0377 | TTY_QUOTE, &tp->t_rawq);
460 (void)putc(0 | TTY_QUOTE, &tp->t_rawq);
461 (void)putc(c | TTY_QUOTE, &tp->t_rawq);
462 goto endcase;
463 } else
464 c = 0;
465 }
466 }
467
468 if (!ISSET(tp->t_state, TS_TYPEN) && ISSET(iflag, ISTRIP))
469 CLR(c, 0x80);
470 if (!ISSET(lflag, EXTPROC)) {
471 /*
472 * Check for literal nexting very first
473 */
474 if (ISSET(tp->t_state, TS_LNCH)) {
475 SET(c, TTY_QUOTE);
476 CLR(tp->t_state, TS_LNCH);
477 }
478 /*
479 * Scan for special characters. This code
480 * is really just a big case statement with
481 * non-constant cases. The bottom of the
482 * case statement is labeled ``endcase'', so goto
483 * it after a case match, or similar.
484 */
485
486 /*
487 * Control chars which aren't controlled
488 * by ICANON, ISIG, or IXON.
489 */
490 if (ISSET(lflag, IEXTEN)) {
491 if (CCEQ(cc[VLNEXT], c)) {
492 if (ISSET(lflag, ECHO)) {
493 if (ISSET(lflag, ECHOE)) {
494 (void)ttyoutput('^', tp);
495 (void)ttyoutput('\b', tp);
496 } else
497 ttyecho(c, tp);
498 }
499 SET(tp->t_state, TS_LNCH);
500 goto endcase;
501 }
502 if (CCEQ(cc[VDISCARD], c)) {
503 if (ISSET(lflag, FLUSHO))
504 CLR(tp->t_lflag, FLUSHO);
505 else {
506 ttyflush(tp, FWRITE);
507 ttyecho(c, tp);
508 if (tp->t_rawq.c_cc + tp->t_canq.c_cc)
509 ttyretype(tp);
510 SET(tp->t_lflag, FLUSHO);
511 }
512 goto startoutput;
513 }
514 }
515 /*
516 * Signals.
517 */
518 if (ISSET(lflag, ISIG)) {
519 if (CCEQ(cc[VINTR], c) || CCEQ(cc[VQUIT], c)) {
520 if (!ISSET(lflag, NOFLSH))
521 ttyflush(tp, FREAD | FWRITE);
522 ttyecho(c, tp);
523 pgsignal(tp->t_pgrp,
524 CCEQ(cc[VINTR], c) ? SIGINT : SIGQUIT, 1);
525 goto endcase;
526 }
527 if (CCEQ(cc[VSUSP], c)) {
528 if (!ISSET(lflag, NOFLSH))
529 ttyflush(tp, FREAD);
530 ttyecho(c, tp);
531 pgsignal(tp->t_pgrp, SIGTSTP, 1);
532 goto endcase;
533 }
534 }
535 /*
536 * Handle start/stop characters.
537 */
538 if (ISSET(iflag, IXON)) {
539 if (CCEQ(cc[VSTOP], c)) {
540 if (!ISSET(tp->t_state, TS_TTSTOP)) {
541 SET(tp->t_state, TS_TTSTOP);
542 ttystop(tp, 0);
543 thread_funnel_set(kernel_flock, funnel_state);
544 return (0);
545 }
546 if (!CCEQ(cc[VSTART], c)) {
547 thread_funnel_set(kernel_flock, funnel_state);
548 return (0);
549 }
550 /*
551 * if VSTART == VSTOP then toggle
552 */
553 goto endcase;
554 }
555 if (CCEQ(cc[VSTART], c))
556 goto restartoutput;
557 }
558 /*
559 * IGNCR, ICRNL, & INLCR
560 */
561 if (c == '\r') {
562 if (ISSET(iflag, IGNCR)) {
563 thread_funnel_set(kernel_flock, funnel_state);
564 return (0);
565 }
566 else if (ISSET(iflag, ICRNL))
567 c = '\n';
568 } else if (c == '\n' && ISSET(iflag, INLCR))
569 c = '\r';
570 }
571 if (!ISSET(tp->t_lflag, EXTPROC) && ISSET(lflag, ICANON)) {
572 /*
573 * From here on down canonical mode character
574 * processing takes place.
575 */
576 /*
577 * erase (^H / ^?)
578 */
579 if (CCEQ(cc[VERASE], c)) {
580 if (tp->t_rawq.c_cc)
581 ttyrub(unputc(&tp->t_rawq), tp);
582 goto endcase;
583 }
584 /*
585 * kill (^U)
586 */
587 if (CCEQ(cc[VKILL], c)) {
588 if (ISSET(lflag, ECHOKE) &&
589 tp->t_rawq.c_cc == tp->t_rocount &&
590 !ISSET(lflag, ECHOPRT))
591 while (tp->t_rawq.c_cc)
592 ttyrub(unputc(&tp->t_rawq), tp);
593 else {
594 ttyecho(c, tp);
595 if (ISSET(lflag, ECHOK) ||
596 ISSET(lflag, ECHOKE))
597 ttyecho('\n', tp);
598 FLUSHQ(&tp->t_rawq);
599 tp->t_rocount = 0;
600 }
601 CLR(tp->t_state, TS_LOCAL);
602 goto endcase;
603 }
604 /*
605 * word erase (^W)
606 */
607 if (CCEQ(cc[VWERASE], c) && ISSET(lflag, IEXTEN)) {
608 int ctype;
609
610 /*
611 * erase whitespace
612 */
613 while ((c = unputc(&tp->t_rawq)) == ' ' || c == '\t')
614 ttyrub(c, tp);
615 if (c == -1)
616 goto endcase;
617 /*
618 * erase last char of word and remember the
619 * next chars type (for ALTWERASE)
620 */
621 ttyrub(c, tp);
622 c = unputc(&tp->t_rawq);
623 if (c == -1)
624 goto endcase;
625 if (c == ' ' || c == '\t') {
626 (void)putc(c, &tp->t_rawq);
627 goto endcase;
628 }
629 ctype = ISALPHA(c);
630 /*
631 * erase rest of word
632 */
633 do {
634 ttyrub(c, tp);
635 c = unputc(&tp->t_rawq);
636 if (c == -1)
637 goto endcase;
638 } while (c != ' ' && c != '\t' &&
639 (!ISSET(lflag, ALTWERASE) || ISALPHA(c) == ctype));
640 (void)putc(c, &tp->t_rawq);
641 goto endcase;
642 }
643 /*
644 * reprint line (^R)
645 */
646 if (CCEQ(cc[VREPRINT], c) && ISSET(lflag, IEXTEN)) {
647 ttyretype(tp);
648 goto endcase;
649 }
650 /*
651 * ^T - kernel info and generate SIGINFO
652 */
653 if (CCEQ(cc[VSTATUS], c) && ISSET(lflag, IEXTEN)) {
654 if (ISSET(lflag, ISIG))
655 pgsignal(tp->t_pgrp, SIGINFO, 1);
656 if (!ISSET(lflag, NOKERNINFO))
657 ttyinfo(tp);
658 goto endcase;
659 }
660 }
661 /*
662 * Check for input buffer overflow
663 */
664 if (tp->t_rawq.c_cc + tp->t_canq.c_cc >= MAX_INPUT) {
665input_overflow:
666 if (ISSET(iflag, IMAXBEL)) {
667 if (tp->t_outq.c_cc < tp->t_hiwat)
668 (void)ttyoutput(CTRL('g'), tp);
669 }
670 goto endcase;
671 }
672
673 if ( c == 0377 && ISSET(iflag, PARMRK) && !ISSET(iflag, ISTRIP)
674 && ISSET(iflag, IGNBRK|IGNPAR) != (IGNBRK|IGNPAR))
675 (void)putc(0377 | TTY_QUOTE, &tp->t_rawq);
676
677 /*
678 * Put data char in q for user and
679 * wakeup on seeing a line delimiter.
680 */
681 if (putc(c, &tp->t_rawq) >= 0) {
682 if (!ISSET(lflag, ICANON)) {
683 ttwakeup(tp);
684 ttyecho(c, tp);
685 goto endcase;
686 }
687 if (TTBREAKC(c, lflag)) {
688 tp->t_rocount = 0;
689 catq(&tp->t_rawq, &tp->t_canq);
690 ttwakeup(tp);
691 } else if (tp->t_rocount++ == 0)
692 tp->t_rocol = tp->t_column;
693 if (ISSET(tp->t_state, TS_ERASE)) {
694 /*
695 * end of prterase \.../
696 */
697 CLR(tp->t_state, TS_ERASE);
698 (void)ttyoutput('/', tp);
699 }
700 i = tp->t_column;
701 ttyecho(c, tp);
702 if (CCEQ(cc[VEOF], c) && ISSET(lflag, ECHO)) {
703 /*
704 * Place the cursor over the '^' of the ^D.
705 */
706 i = min(2, tp->t_column - i);
707 while (i > 0) {
708 (void)ttyoutput('\b', tp);
709 i--;
710 }
711 }
712 }
713endcase:
714 /*
715 * IXANY means allow any character to restart output.
716 */
717 if (ISSET(tp->t_state, TS_TTSTOP) &&
718 !ISSET(iflag, IXANY) && cc[VSTART] != cc[VSTOP]) {
719 thread_funnel_set(kernel_flock, funnel_state);
720 return (0);
721 }
722restartoutput:
723 CLR(tp->t_lflag, FLUSHO);
724 CLR(tp->t_state, TS_TTSTOP);
725startoutput:
726 retval = ttstart(tp);
727 thread_funnel_set(kernel_flock, funnel_state);
728 return (retval);
729}
730
731/*
732 * Output a single character on a tty, doing output processing
733 * as needed (expanding tabs, newline processing, etc.).
734 * Returns < 0 if succeeds, otherwise returns char to resend.
735 * Must be recursive.
736 */
737static int
738ttyoutput(c, tp)
739 register int c;
740 register struct tty *tp;
741{
742 register tcflag_t oflag;
743 register int col, s;
744
745 oflag = tp->t_oflag;
746 if (!ISSET(oflag, OPOST)) {
747 if (ISSET(tp->t_lflag, FLUSHO))
748 return (-1);
749 if (putc(c, &tp->t_outq))
750 return (c);
751 tk_nout++;
752 tp->t_outcc++;
753 return (-1);
754 }
755 /*
756 * Do tab expansion if OXTABS is set. Special case if we external
757 * processing, we don't do the tab expansion because we'll probably
758 * get it wrong. If tab expansion needs to be done, let it happen
759 * externally.
760 */
761 CLR(c, ~TTY_CHARMASK);
762 if (c == '\t' &&
763 ISSET(oflag, OXTABS) && !ISSET(tp->t_lflag, EXTPROC)) {
764 c = 8 - (tp->t_column & 7);
765 if (!ISSET(tp->t_lflag, FLUSHO)) {
766 s = spltty(); /* Don't interrupt tabs. */
767 c -= b_to_q(" ", c, &tp->t_outq);
768 tk_nout += c;
769 tp->t_outcc += c;
770 splx(s);
771 }
772 tp->t_column += c;
773 return (c ? -1 : '\t');
774 }
775 if (c == CEOT && ISSET(oflag, ONOEOT))
776 return (-1);
777
778 /*
779 * Newline translation: if ONLCR is set,
780 * translate newline into "\r\n".
781 */
782 if (c == '\n' && ISSET(tp->t_oflag, ONLCR)) {
783 tk_nout++;
784 tp->t_outcc++;
785 if (putc('\r', &tp->t_outq))
786 return (c);
787 }
788 tk_nout++;
789 tp->t_outcc++;
790 if (!ISSET(tp->t_lflag, FLUSHO) && putc(c, &tp->t_outq))
791 return (c);
792
793 col = tp->t_column;
794 switch (CCLASS(c)) {
795 case BACKSPACE:
796 if (col > 0)
797 --col;
798 break;
799 case CONTROL:
800 break;
801 case NEWLINE:
802 case RETURN:
803 col = 0;
804 break;
805 case ORDINARY:
806 ++col;
807 break;
808 case TAB:
809 col = (col + 8) & ~7;
810 break;
811 }
812 tp->t_column = col;
813 return (-1);
814}
815
816/*
817 * Ioctls for all tty devices. Called after line-discipline specific ioctl
818 * has been called to do discipline-specific functions and/or reject any
819 * of these ioctl commands.
820 */
821/* ARGSUSED */
822int
91447636
A
823ttioctl(register struct tty *tp,
824 u_long cmd, caddr_t data, int flag,
825 struct proc *p)
1c79356b 826{
1c79356b 827 int s, error;
9bccf70c 828 struct uthread *ut;
1c79356b 829
91447636 830 ut = (struct uthread *)get_bsdthread_info(current_thread());
1c79356b
A
831 /* If the ioctl involves modification, hang if in the background. */
832 switch (cmd) {
833 case TIOCFLUSH:
834 case TIOCSETA:
91447636 835 case TIOCSETA_64:
1c79356b
A
836 case TIOCSETD:
837 case TIOCSETAF:
91447636 838 case TIOCSETAF_64:
1c79356b 839 case TIOCSETAW:
91447636 840 case TIOCSETAW_64:
1c79356b
A
841#ifdef notdef
842 case TIOCSPGRP:
843#endif
844 case TIOCSTAT:
845 case TIOCSTI:
846 case TIOCSWINSZ:
91447636 847#if COMPAT_43_TTY || defined(COMPAT_SUNOS)
1c79356b
A
848 case TIOCLBIC:
849 case TIOCLBIS:
850 case TIOCLSET:
851 case TIOCSETC:
852 case OTIOCSETD:
853 case TIOCSETN:
854 case TIOCSETP:
855 case TIOCSLTC:
856#endif
857 while (isbackground(p, tp) &&
858 (p->p_flag & P_PPWAIT) == 0 &&
859 (p->p_sigignore & sigmask(SIGTTOU)) == 0 &&
9bccf70c 860 (ut->uu_sigmask & sigmask(SIGTTOU)) == 0) {
1c79356b
A
861 if (p->p_pgrp->pg_jobc == 0)
862 return (EIO);
863 pgsignal(p->p_pgrp, SIGTTOU, 1);
864 error = ttysleep(tp, &lbolt, TTOPRI | PCATCH | PTTYBLOCK, "ttybg1",
865 0);
866 if (error)
867 return (error);
868 }
869 break;
870 }
871
872 switch (cmd) { /* Process the ioctl. */
873 case FIOASYNC: /* set/clear async i/o */
874 s = spltty();
875 if (*(int *)data)
876 SET(tp->t_state, TS_ASYNC);
877 else
878 CLR(tp->t_state, TS_ASYNC);
879 splx(s);
880 break;
881 case FIONBIO: /* set/clear non-blocking i/o */
882 break; /* XXX: delete. */
883 case FIONREAD: /* get # bytes to read */
884 s = spltty();
885 *(int *)data = ttnread(tp);
886 splx(s);
887 break;
888 case TIOCEXCL: /* set exclusive use of tty */
889 s = spltty();
890 SET(tp->t_state, TS_XCLUDE);
891 splx(s);
892 break;
893 case TIOCFLUSH: { /* flush buffers */
894 register int flags = *(int *)data;
895
896 if (flags == 0)
897 flags = FREAD | FWRITE;
898 else
899 flags &= FREAD | FWRITE;
900 ttyflush(tp, flags);
901 break;
902 }
903#ifdef NeXT
904 case TIOCSCONS: {
905 /* Set current console device to this line */
906 int bogusData = 1;
907 data = (caddr_t) &bogusData;
908
909 /* No break - Fall through to BSD code */
910 }
911#endif /* NeXT */
912 case TIOCCONS: { /* become virtual console */
913 if (*(int *)data) {
914 if (constty && constty != tp &&
915 ISSET(constty->t_state, TS_CONNECTED)) {
916 return (EBUSY);
917 }
918#if defined(NeXT) || !defined(UCONSOLE)
91447636 919 if ( (error = suser(kauth_cred_get(), &p->p_acflag)) )
1c79356b
A
920 return (error);
921#endif
922 constty = tp;
923 } else if (tp == constty) {
924 constty = NULL;
925 }
926#ifdef NeXT
927 if (constty) {
928 (*cdevsw[major(cons.t_dev)].d_ioctl)
929 (cons.t_dev, KMIOCDISABLCONS, NULL, 0, p);
930 } else {
931 (*cdevsw[major(tp->t_dev)].d_ioctl)
932 (tp->t_dev, KMIOCDISABLCONS, NULL, 0, p);
933 }
934#endif /* NeXT */
935 break;
936 }
937 case TIOCDRAIN: /* wait till output drained */
938 error = ttywait(tp);
939 if (error)
940 return (error);
941 break;
91447636
A
942 case TIOCGETA: /* get termios struct */
943 case TIOCGETA_64: { /* get termios struct */
944 if (IS_64BIT_PROCESS(p)) {
945 termios32to64(&tp->t_termios, (struct user_termios *)data);
946 } else {
947 bcopy(&tp->t_termios, data, sizeof(struct termios));
948 }
1c79356b
A
949 break;
950 }
951 case TIOCGETD: /* get line discipline */
952 *(int *)data = tp->t_line;
953 break;
954 case TIOCGWINSZ: /* get window size */
955 *(struct winsize *)data = tp->t_winsize;
956 break;
957 case TIOCGPGRP: /* get pgrp of tty */
958 if (!isctty(p, tp))
959 return (ENOTTY);
960 *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
961 break;
962#ifdef TIOCHPCL
963 case TIOCHPCL: /* hang up on last close */
964 s = spltty();
965 SET(tp->t_cflag, HUPCL);
966 splx(s);
967 break;
968#endif
969 case TIOCNXCL: /* reset exclusive use of tty */
970 s = spltty();
971 CLR(tp->t_state, TS_XCLUDE);
972 splx(s);
973 break;
974 case TIOCOUTQ: /* output queue size */
975 *(int *)data = tp->t_outq.c_cc;
976 break;
977 case TIOCSETA: /* set termios struct */
91447636 978 case TIOCSETA_64:
1c79356b 979 case TIOCSETAW: /* drain output, set */
91447636
A
980 case TIOCSETAW_64:
981 case TIOCSETAF: /* drn out, fls in, set */
982 case TIOCSETAF_64: { /* drn out, fls in, set */
1c79356b 983 register struct termios *t = (struct termios *)data;
91447636 984 struct termios lcl_termios;
1c79356b 985
91447636
A
986 if (IS_64BIT_PROCESS(p)) {
987 termios64to32((struct user_termios *)data, &lcl_termios);
988 t = &lcl_termios;
989 }
1c79356b
A
990 if (t->c_ispeed < 0 || t->c_ospeed < 0)
991 return (EINVAL);
992 s = spltty();
91447636
A
993 if (cmd == TIOCSETAW || cmd == TIOCSETAF ||
994 cmd == TIOCSETAW_64 || cmd == TIOCSETAF_64) {
1c79356b
A
995 error = ttywait(tp);
996 if (error) {
997 splx(s);
998 return (error);
999 }
91447636 1000 if (cmd == TIOCSETAF || cmd == TIOCSETAF_64)
1c79356b
A
1001 ttyflush(tp, FREAD);
1002 }
1003 if (!ISSET(t->c_cflag, CIGNORE)) {
1004 /*
1005 * Set device hardware.
1006 */
1007 if (tp->t_param && (error = (*tp->t_param)(tp, t))) {
1008 splx(s);
1009 return (error);
1010 }
1011 if (ISSET(t->c_cflag, CLOCAL) &&
1012 !ISSET(tp->t_cflag, CLOCAL)) {
1013 /*
1014 * XXX disconnections would be too hard to
1015 * get rid of without this kludge. The only
1016 * way to get rid of controlling terminals
1017 * is to exit from the session leader.
1018 */
1019 CLR(tp->t_state, TS_ZOMBIE);
1020
1021 wakeup(TSA_CARR_ON(tp));
1022 ttwakeup(tp);
1023 ttwwakeup(tp);
1024 }
1025 if ((ISSET(tp->t_state, TS_CARR_ON) ||
1026 ISSET(t->c_cflag, CLOCAL)) &&
1027 !ISSET(tp->t_state, TS_ZOMBIE))
1028 SET(tp->t_state, TS_CONNECTED);
1029 else
1030 CLR(tp->t_state, TS_CONNECTED);
1031 tp->t_cflag = t->c_cflag;
1032 tp->t_ispeed = t->c_ispeed;
1033 tp->t_ospeed = t->c_ospeed;
1034 ttsetwater(tp);
1035 }
1036 if (ISSET(t->c_lflag, ICANON) != ISSET(tp->t_lflag, ICANON) &&
91447636 1037 cmd != TIOCSETAF && cmd != TIOCSETAF_64) {
1c79356b
A
1038 if (ISSET(t->c_lflag, ICANON))
1039 SET(tp->t_lflag, PENDIN);
1040 else {
1041 /*
1042 * XXX we really shouldn't allow toggling
1043 * ICANON while we're in a non-termios line
1044 * discipline. Now we have to worry about
1045 * panicing for a null queue.
1046 */
1047#ifndef NeXT
1048 if (tp->t_canq.c_cbreserved > 0 &&
1049 tp->t_rawq.c_cbreserved > 0) {
1050 catq(&tp->t_rawq, &tp->t_canq);
1051 /*
1052 * XXX the queue limits may be
1053 * different, so the old queue
1054 * swapping method no longer works.
1055 */
1056 catq(&tp->t_canq, &tp->t_rawq);
1057 }
1058#else
1059 if (tp->t_rawq.c_cs && tp->t_canq.c_cs) {
1060 struct clist tq;
1061
1062 catq(&tp->t_rawq, &tp->t_canq);
1063 tq = tp->t_rawq;
1064 tp->t_rawq = tp->t_canq;
1065 tp->t_canq = tq;
1066 }
1067#endif /* !NeXT */
1068 CLR(tp->t_lflag, PENDIN);
1069 }
1070 ttwakeup(tp);
1071 }
1072 tp->t_iflag = t->c_iflag;
1073 tp->t_oflag = t->c_oflag;
1074 /*
1075 * Make the EXTPROC bit read only.
1076 */
1077 if (ISSET(tp->t_lflag, EXTPROC))
1078 SET(t->c_lflag, EXTPROC);
1079 else
1080 CLR(t->c_lflag, EXTPROC);
1081 tp->t_lflag = t->c_lflag | ISSET(tp->t_lflag, PENDIN);
1082 if (t->c_cc[VMIN] != tp->t_cc[VMIN] ||
1083 t->c_cc[VTIME] != tp->t_cc[VTIME])
1084 ttwakeup(tp);
1085 bcopy(t->c_cc, tp->t_cc, sizeof(t->c_cc));
1086 splx(s);
1087 break;
1088 }
1089 case TIOCSETD: { /* set line discipline */
1090 register int t = *(int *)data;
1091 dev_t device = tp->t_dev;
1c79356b 1092
91447636 1093 if (t >= nlinesw)
1c79356b
A
1094 return (ENXIO);
1095 if (t != tp->t_line) {
1096 s = spltty();
1097 (*linesw[tp->t_line].l_close)(tp, flag);
1098 error = (*linesw[t].l_open)(device, tp);
1099 if (error) {
1100 (void)(*linesw[tp->t_line].l_open)(device, tp);
1101 splx(s);
1102 return (error);
1103 }
1104 tp->t_line = t;
1105 splx(s);
1106 }
1107 break;
1108 }
1109 case TIOCSTART: /* start output, like ^Q */
1110 s = spltty();
1111 if (ISSET(tp->t_state, TS_TTSTOP) ||
1112 ISSET(tp->t_lflag, FLUSHO)) {
1113 CLR(tp->t_lflag, FLUSHO);
1114 CLR(tp->t_state, TS_TTSTOP);
1115 ttstart(tp);
1116 }
1117 splx(s);
1118 break;
1119 case TIOCSTI: /* simulate terminal input */
91447636 1120 if (suser(kauth_cred_get(), NULL) && (flag & FREAD) == 0)
1c79356b 1121 return (EPERM);
91447636 1122 if (suser(kauth_cred_get(), NULL) && !isctty(p, tp))
1c79356b
A
1123 return (EACCES);
1124 s = spltty();
1125 (*linesw[tp->t_line].l_rint)(*(u_char *)data, tp);
1126 splx(s);
1127 break;
1128 case TIOCSTOP: /* stop output, like ^S */
1129 s = spltty();
1130 if (!ISSET(tp->t_state, TS_TTSTOP)) {
1131 SET(tp->t_state, TS_TTSTOP);
1132 ttystop(tp, 0);
1133 }
1134 splx(s);
1135 break;
1136 case TIOCSCTTY: /* become controlling tty */
1137 /* Session ctty vnode pointer set in vnode layer. */
1138 if (!SESS_LEADER(p) ||
1139 ((p->p_session->s_ttyvp || tp->t_session) &&
1140 (tp->t_session != p->p_session)))
1141 return (EPERM);
1142 tp->t_session = p->p_session;
1143 tp->t_pgrp = p->p_pgrp;
1144 p->p_session->s_ttyp = tp;
1145 p->p_flag |= P_CONTROLT;
9bccf70c
A
1146 /* The backgrounded process blocking on tty now
1147 * could be foregound process. Wake such processes
1148 */
1149 tty_pgsignal(tp->t_pgrp, SIGCONT);
1c79356b
A
1150 break;
1151 case TIOCSPGRP: { /* set pgrp of tty */
1152 register struct pgrp *pgrp = pgfind(*(int *)data);
1153
1154 if (!isctty(p, tp))
1155 return (ENOTTY);
1156 else if (pgrp == NULL || pgrp->pg_session != p->p_session)
1157 return (EPERM);
1158 tp->t_pgrp = pgrp;
9bccf70c
A
1159 /* The backgrounded process blocking on tty now
1160 * could be foregound process. Wake such processes
1161 */
1162 tty_pgsignal(tp->t_pgrp, SIGCONT);
1c79356b
A
1163 break;
1164 }
1165 case TIOCSTAT: /* simulate control-T */
1166 s = spltty();
1167 ttyinfo(tp);
1168 splx(s);
1169 break;
1170 case TIOCSWINSZ: /* set window size */
1171 if (bcmp((caddr_t)&tp->t_winsize, data,
1172 sizeof (struct winsize))) {
1173 tp->t_winsize = *(struct winsize *)data;
1174 pgsignal(tp->t_pgrp, SIGWINCH, 1);
1175 }
1176 break;
1177 case TIOCSDRAINWAIT:
91447636 1178 error = suser(kauth_cred_get(), &p->p_acflag);
1c79356b
A
1179 if (error)
1180 return (error);
1181 tp->t_timeout = *(int *)data * hz;
1182 wakeup(TSA_OCOMPLETE(tp));
1183 wakeup(TSA_OLOWAT(tp));
1184 break;
1185 case TIOCGDRAINWAIT:
1186 *(int *)data = tp->t_timeout / hz;
1187 break;
1188 default:
91447636 1189#if COMPAT_43_TTY || defined(COMPAT_SUNOS)
1c79356b
A
1190#ifdef NeXT
1191 return (ttcompat(tp, cmd, data, flag, p));
1192#else
1193 return (ttcompat(tp, cmd, data, flag));
1194#endif /* NeXT */
1195#else
91447636 1196 return (ENOTTY);
1c79356b
A
1197#endif
1198 }
1199
1200 return (0);
1201}
1202
1203int
0b4e3aa0 1204ttyselect(tp, rw, wql, p)
1c79356b
A
1205 struct tty *tp;
1206 int rw;
0b4e3aa0 1207 void * wql;
1c79356b
A
1208 struct proc *p;
1209{
1210 int s;
1211
1212 if (tp == NULL)
1213 return (ENXIO);
1214
1215 s = spltty();
1216 switch (rw) {
1217 case FREAD:
1218 if (ttnread(tp) > 0 || ISSET(tp->t_state, TS_ZOMBIE))
1219 goto win;
0b4e3aa0 1220 selrecord(p, &tp->t_rsel, wql);
1c79356b
A
1221 break;
1222 case FWRITE:
1223 if ((tp->t_outq.c_cc <= tp->t_lowat &&
1224 ISSET(tp->t_state, TS_CONNECTED))
1225 || ISSET(tp->t_state, TS_ZOMBIE)) {
1226win: splx(s);
1227 return (1);
1228 }
0b4e3aa0 1229 selrecord(p, &tp->t_wsel, wql);
1c79356b
A
1230 break;
1231 }
1232 splx(s);
1233 return (0);
1234}
1235
1236/*
1237 * This is a wrapper for compatibility with the select vector used by
1238 * cdevsw. It relies on a proper xxxdevtotty routine.
1239 */
1240int
0b4e3aa0 1241ttselect(dev, rw, wql, p)
1c79356b
A
1242 dev_t dev;
1243 int rw;
0b4e3aa0 1244 void * wql;
1c79356b
A
1245 struct proc *p;
1246{
1247#ifndef NeXT
0b4e3aa0 1248 return ttyselect((*cdevsw[major(dev)]->d_devtotty)(dev), rw, wql, p);
1c79356b 1249#else
0b4e3aa0 1250 return ttyselect(cdevsw[major(dev)].d_ttys[minor(dev)], rw, wql, p);
1c79356b
A
1251#endif
1252}
1253
1254/*
1255 * Must be called at spltty().
1256 */
1257static int
1258ttnread(tp)
1259 struct tty *tp;
1260{
1261 int nread;
1262
1263 if (ISSET(tp->t_lflag, PENDIN))
1264 ttypend(tp);
1265 nread = tp->t_canq.c_cc;
1266 if (!ISSET(tp->t_lflag, ICANON)) {
1267 nread += tp->t_rawq.c_cc;
1268 if (nread < tp->t_cc[VMIN] && tp->t_cc[VTIME] == 0)
1269 nread = 0;
1270 }
1271 return (nread);
1272}
1273
1274/*
1275 * Wait for output to drain.
1276 */
1277int
1278ttywait(tp)
1279 register struct tty *tp;
1280{
1281 int error, s;
1282
1283 error = 0;
1284 s = spltty();
1285 while ((tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)) &&
1286 ISSET(tp->t_state, TS_CONNECTED) && tp->t_oproc) {
1287 (*tp->t_oproc)(tp);
1288 if ((tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)) &&
1289 ISSET(tp->t_state, TS_CONNECTED)) {
1290 SET(tp->t_state, TS_SO_OCOMPLETE);
1291 error = ttysleep(tp, TSA_OCOMPLETE(tp),
1292 TTOPRI | PCATCH, "ttywai",
1293 tp->t_timeout);
1294 if (error) {
1295 if (error == EWOULDBLOCK)
1296 error = EIO;
1297 break;
1298 }
1299 } else
1300 break;
1301 }
1302 if (!error && (tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)))
1303 error = EIO;
1304 splx(s);
1305 return (error);
1306}
1307
1308static void
1309ttystop(tp, rw)
1310 struct tty *tp;
1311 int rw;
1312{
1313#ifdef sun4c /* XXX */
1314 (*tp->t_stop)(tp, rw);
1315#elif defined(NeXT)
1316 (*cdevsw[major(tp->t_dev)].d_stop)(tp, rw);
1317#else
1318 (*cdevsw[major(tp->t_dev)]->d_stop)(tp, rw);
1319#endif
1320}
1321
1322/*
1323 * Flush if successfully wait.
1324 */
1325static int
1326ttywflush(tp)
1327 struct tty *tp;
1328{
1329 int error;
1330
1331 if ((error = ttywait(tp)) == 0)
1332 ttyflush(tp, FREAD);
1333 return (error);
1334}
1335
1336/*
1337 * Flush tty read and/or write queues, notifying anyone waiting.
1338 */
1339void
1340ttyflush(tp, rw)
1341 register struct tty *tp;
1342 int rw;
1343{
1344 register int s;
1345
1346 s = spltty();
1347#if 0
1348again:
1349#endif
1350 if (rw & FWRITE) {
1351 FLUSHQ(&tp->t_outq);
1352 CLR(tp->t_state, TS_TTSTOP);
1353 }
1354 ttystop(tp, rw);
1355 if (rw & FREAD) {
1356 FLUSHQ(&tp->t_canq);
1357 FLUSHQ(&tp->t_rawq);
1358 CLR(tp->t_lflag, PENDIN);
1359 tp->t_rocount = 0;
1360 tp->t_rocol = 0;
1361 CLR(tp->t_state, TS_LOCAL);
1362 ttwakeup(tp);
1363 if (ISSET(tp->t_state, TS_TBLOCK)) {
1364 if (rw & FWRITE)
1365 FLUSHQ(&tp->t_outq);
1366 ttyunblock(tp);
1367
1368 /*
1369 * Don't let leave any state that might clobber the
1370 * next line discipline (although we should do more
1371 * to send the START char). Not clearing the state
1372 * may have caused the "putc to a clist with no
1373 * reserved cblocks" panic/printf.
1374 */
1375 CLR(tp->t_state, TS_TBLOCK);
1376
1377#if 0 /* forget it, sleeping isn't always safe and we don't know when it is */
1378 if (ISSET(tp->t_iflag, IXOFF)) {
1379 /*
1380 * XXX wait a bit in the hope that the stop
1381 * character (if any) will go out. Waiting
1382 * isn't good since it allows races. This
1383 * will be fixed when the stop character is
1384 * put in a special queue. Don't bother with
1385 * the checks in ttywait() since the timeout
1386 * will save us.
1387 */
1388 SET(tp->t_state, TS_SO_OCOMPLETE);
1389 ttysleep(tp, TSA_OCOMPLETE(tp), TTOPRI,
1390 "ttyfls", hz / 10);
1391 /*
1392 * Don't try sending the stop character again.
1393 */
1394 CLR(tp->t_state, TS_TBLOCK);
1395 goto again;
1396 }
1397#endif
1398 }
1399 }
1400 if (rw & FWRITE) {
1401 FLUSHQ(&tp->t_outq);
1402 ttwwakeup(tp);
1403 }
1404 splx(s);
1405}
1406
1407/*
1408 * Copy in the default termios characters.
1409 */
1410void
1411termioschars(t)
1412 struct termios *t;
1413{
1414
1415 bcopy(ttydefchars, t->c_cc, sizeof t->c_cc);
1416}
1417
1418/*
1419 * Old interface.
1420 */
1421void
1422ttychars(tp)
1423 struct tty *tp;
1424{
1425
1426 termioschars(&tp->t_termios);
1427}
1428
1429/*
1430 * Handle input high water. Send stop character for the IXOFF case. Turn
1431 * on our input flow control bit and propagate the changes to the driver.
1432 * XXX the stop character should be put in a special high priority queue.
1433 */
1434void
1435ttyblock(tp)
1436 struct tty *tp;
1437{
1438
1439 SET(tp->t_state, TS_TBLOCK);
1440 if (ISSET(tp->t_iflag, IXOFF) && tp->t_cc[VSTOP] != _POSIX_VDISABLE &&
1441 putc(tp->t_cc[VSTOP], &tp->t_outq) != 0)
1442 CLR(tp->t_state, TS_TBLOCK); /* try again later */
1443 ttstart(tp);
1444}
1445
1446/*
1447 * Handle input low water. Send start character for the IXOFF case. Turn
1448 * off our input flow control bit and propagate the changes to the driver.
1449 * XXX the start character should be put in a special high priority queue.
1450 */
1451static void
1452ttyunblock(tp)
1453 struct tty *tp;
1454{
1455
1456 CLR(tp->t_state, TS_TBLOCK);
1457 if (ISSET(tp->t_iflag, IXOFF) && tp->t_cc[VSTART] != _POSIX_VDISABLE &&
1458 putc(tp->t_cc[VSTART], &tp->t_outq) != 0)
1459 SET(tp->t_state, TS_TBLOCK); /* try again later */
1460 ttstart(tp);
1461}
1462
1463#if defined(NeXT) || defined(notyet)
1464/* FreeBSD: Not used by any current (i386) drivers. */
1465/*
1466 * Restart after an inter-char delay.
1467 */
1468void
1469ttrstrt(tp_arg)
1470 void *tp_arg;
1471{
1472 struct tty *tp;
1473 int s;
1474
1475#if DIAGNOSTIC
1476 if (tp_arg == NULL)
1477 panic("ttrstrt");
1478#endif
1479 tp = tp_arg;
1480 s = spltty();
1481
1482 CLR(tp->t_state, TS_TIMEOUT);
1483 ttstart(tp);
1484
1485 splx(s);
1486}
1487#endif /* NeXT || notyet */
1488
1489int
1490ttstart(tp)
1491 struct tty *tp;
1492{
0b4e3aa0
A
1493 boolean_t funnel_state;
1494
1495 funnel_state = thread_funnel_set(kernel_flock, TRUE);
1c79356b
A
1496
1497 if (tp->t_oproc != NULL) /* XXX: Kludge for pty. */
1498 (*tp->t_oproc)(tp);
0b4e3aa0 1499 thread_funnel_set(kernel_flock, funnel_state);
1c79356b
A
1500 return (0);
1501}
1502
1503/*
1504 * "close" a line discipline
1505 */
1506int
1507ttylclose(tp, flag)
1508 struct tty *tp;
1509 int flag;
1510{
0b4e3aa0
A
1511 boolean_t funnel_state;
1512
1513 funnel_state = thread_funnel_set(kernel_flock, TRUE);
1c79356b
A
1514 if ( (flag & FNONBLOCK) || ttywflush(tp))
1515 ttyflush(tp, FREAD | FWRITE);
0b4e3aa0 1516 thread_funnel_set(kernel_flock, funnel_state);
1c79356b
A
1517 return (0);
1518}
1519
1520/*
1521 * Handle modem control transition on a tty.
1522 * Flag indicates new state of carrier.
1523 * Returns 0 if the line should be turned off, otherwise 1.
1524 */
1525int
1526ttymodem(tp, flag)
1527 register struct tty *tp;
1528 int flag;
1529{
0b4e3aa0
A
1530 boolean_t funnel_state;
1531
1532 funnel_state = thread_funnel_set(kernel_flock, TRUE);
1c79356b
A
1533
1534 if (ISSET(tp->t_state, TS_CARR_ON) && ISSET(tp->t_cflag, MDMBUF)) {
1535 /*
1536 * MDMBUF: do flow control according to carrier flag
1537 * XXX TS_CAR_OFLOW doesn't do anything yet. TS_TTSTOP
1538 * works if IXON and IXANY are clear.
1539 */
1540 if (flag) {
1541 CLR(tp->t_state, TS_CAR_OFLOW);
1542 CLR(tp->t_state, TS_TTSTOP);
1543 ttstart(tp);
1544 } else if (!ISSET(tp->t_state, TS_CAR_OFLOW)) {
1545 SET(tp->t_state, TS_CAR_OFLOW);
1546 SET(tp->t_state, TS_TTSTOP);
1547 ttystop(tp, 0);
1548 }
1549 } else if (flag == 0) {
1550 /*
1551 * Lost carrier.
1552 */
1553 CLR(tp->t_state, TS_CARR_ON);
1554 if (ISSET(tp->t_state, TS_ISOPEN) &&
1555 !ISSET(tp->t_cflag, CLOCAL)) {
1556 SET(tp->t_state, TS_ZOMBIE);
1557 CLR(tp->t_state, TS_CONNECTED);
1558 if (tp->t_session && tp->t_session->s_leader)
1559 psignal(tp->t_session->s_leader, SIGHUP);
1560 ttyflush(tp, FREAD | FWRITE);
0b4e3aa0 1561 thread_funnel_set(kernel_flock, funnel_state);
1c79356b
A
1562 return (0);
1563 }
1564 } else {
1565 /*
1566 * Carrier now on.
1567 */
1568 SET(tp->t_state, TS_CARR_ON);
1569 if (!ISSET(tp->t_state, TS_ZOMBIE))
1570 SET(tp->t_state, TS_CONNECTED);
1571 wakeup(TSA_CARR_ON(tp));
1572 ttwakeup(tp);
1573 ttwwakeup(tp);
1574 }
0b4e3aa0 1575 thread_funnel_set(kernel_flock, funnel_state);
1c79356b
A
1576 return (1);
1577}
1578
1579/*
1580 * Reinput pending characters after state switch
1581 * call at spltty().
1582 */
1583static void
1584ttypend(tp)
1585 register struct tty *tp;
1586{
1587 struct clist tq;
1588 register int c;
1589
1590 CLR(tp->t_lflag, PENDIN);
1591 SET(tp->t_state, TS_TYPEN);
1592#ifndef NeXT
1593 /*
1594 * XXX this assumes too much about clist internals. It may even
1595 * fail if the cblock slush pool is empty. We can't allocate more
1596 * cblocks here because we are called from an interrupt handler
1597 * and clist_alloc_cblocks() can wait.
1598 */
1599 tq = tp->t_rawq;
1600 bzero(&tp->t_rawq, sizeof tp->t_rawq);
1601 tp->t_rawq.c_cbmax = tq.c_cbmax;
1602 tp->t_rawq.c_cbreserved = tq.c_cbreserved;
1603#else
1604 tq = tp->t_rawq;
1605 tp->t_rawq.c_cc = 0;
1606 tp->t_rawq.c_cf = tp->t_rawq.c_cl = 0;
1607#endif /* !NeXT */
1608 while ((c = getc(&tq)) >= 0)
1609 ttyinput(c, tp);
1610 CLR(tp->t_state, TS_TYPEN);
1611}
1612
1613/*
1614 * Process a read call on a tty device.
1615 */
1616int
1617ttread(tp, uio, flag)
1618 register struct tty *tp;
1619 struct uio *uio;
1620 int flag;
1621{
1622 register struct clist *qp;
1623 register int c;
1624 register tcflag_t lflag;
1625 register cc_t *cc = tp->t_cc;
1626 register struct proc *p = current_proc();
1627 int s, first, error = 0;
1628 int has_etime = 0, last_cc = 0;
1629 long slp = 0; /* XXX this should be renamed `timo'. */
0b4e3aa0 1630 boolean_t funnel_state;
9bccf70c 1631 struct uthread *ut;
1c79356b 1632
0b4e3aa0 1633 funnel_state = thread_funnel_set(kernel_flock, TRUE);
9bccf70c 1634
91447636 1635 ut = (struct uthread *)get_bsdthread_info(current_thread());
9bccf70c 1636
1c79356b
A
1637loop:
1638 s = spltty();
1639 lflag = tp->t_lflag;
1640 /*
1641 * take pending input first
1642 */
1643 if (ISSET(lflag, PENDIN)) {
1644 ttypend(tp);
1645 splx(s); /* reduce latency */
1646 s = spltty();
1647 lflag = tp->t_lflag; /* XXX ttypend() clobbers it */
1648 }
1649
1650 /*
1651 * Hang process if it's in the background.
1652 */
1653 if (isbackground(p, tp)) {
1654 splx(s);
1655 if ((p->p_sigignore & sigmask(SIGTTIN)) ||
9bccf70c 1656 (ut->uu_sigmask & sigmask(SIGTTIN)) ||
0b4e3aa0
A
1657 p->p_flag & P_PPWAIT || p->p_pgrp->pg_jobc == 0) {
1658 thread_funnel_set(kernel_flock, funnel_state);
1c79356b 1659 return (EIO);
0b4e3aa0 1660 }
1c79356b
A
1661 pgsignal(p->p_pgrp, SIGTTIN, 1);
1662 error = ttysleep(tp, &lbolt, TTIPRI | PCATCH | PTTYBLOCK, "ttybg2", 0);
0b4e3aa0
A
1663 if (error){
1664 thread_funnel_set(kernel_flock, funnel_state);
1c79356b 1665 return (error);
0b4e3aa0 1666 }
1c79356b
A
1667 goto loop;
1668 }
1669
1670 if (ISSET(tp->t_state, TS_ZOMBIE)) {
1671 splx(s);
0b4e3aa0 1672 thread_funnel_set(kernel_flock, funnel_state);
1c79356b
A
1673 return (0); /* EOF */
1674 }
1675
1676 /*
1677 * If canonical, use the canonical queue,
1678 * else use the raw queue.
1679 *
1680 * (should get rid of clists...)
1681 */
1682 qp = ISSET(lflag, ICANON) ? &tp->t_canq : &tp->t_rawq;
1683
1684 if (flag & IO_NDELAY) {
1685 if (qp->c_cc > 0)
1686 goto read;
1687 if (!ISSET(lflag, ICANON) && cc[VMIN] == 0) {
1688 splx(s);
0b4e3aa0 1689 thread_funnel_set(kernel_flock, funnel_state);
1c79356b
A
1690 return (0);
1691 }
1692 splx(s);
0b4e3aa0 1693 thread_funnel_set(kernel_flock, funnel_state);
1c79356b
A
1694 return (EWOULDBLOCK);
1695 }
1696 if (!ISSET(lflag, ICANON)) {
1697 int m = cc[VMIN];
1698 long t = cc[VTIME];
1699 struct timeval etime, timecopy;
1c79356b
A
1700
1701 /*
1702 * Check each of the four combinations.
1703 * (m > 0 && t == 0) is the normal read case.
1704 * It should be fairly efficient, so we check that and its
1705 * companion case (m == 0 && t == 0) first.
1706 * For the other two cases, we compute the target sleep time
1707 * into slp.
1708 */
1709 if (t == 0) {
1710 if (qp->c_cc < m)
1711 goto sleep;
1712 if (qp->c_cc > 0)
1713 goto read;
1714
1715 /* m, t and qp->c_cc are all 0. 0 is enough input. */
1716 splx(s);
0b4e3aa0 1717 thread_funnel_set(kernel_flock, funnel_state);
1c79356b
A
1718 return (0);
1719 }
1720 t *= 100000; /* time in us */
1721#define diff(t1, t2) (((t1).tv_sec - (t2).tv_sec) * 1000000 + \
1722 ((t1).tv_usec - (t2).tv_usec))
1723 if (m > 0) {
1724 if (qp->c_cc <= 0)
1725 goto sleep;
1726 if (qp->c_cc >= m)
1727 goto read;
91447636 1728 microuptime(&timecopy);
1c79356b
A
1729 if (!has_etime) {
1730 /* first character, start timer */
1731 has_etime = 1;
1732
1733 etime.tv_sec = t / 1000000;
1734 etime.tv_usec = (t - (etime.tv_sec * 1000000));
1735 timeradd(&etime, &timecopy, &etime);
1736
1737 slp = t;
1738 } else if (qp->c_cc > last_cc) {
1739 /* got a character, restart timer */
1740
1741 etime.tv_sec = t / 1000000;
1742 etime.tv_usec = (t - (etime.tv_sec * 1000000));
1743 timeradd(&etime, &timecopy, &etime);
1744
1745 slp = t;
1746 } else {
1747 /* nothing, check expiration */
1748 if (timercmp(&etime, &timecopy, <=))
1749 goto read;
1750
1751 slp = diff(etime, timecopy);
1752 }
1753 last_cc = qp->c_cc;
1754 } else { /* m == 0 */
1755 if (qp->c_cc > 0)
1756 goto read;
91447636 1757 microuptime(&timecopy);
1c79356b
A
1758 if (!has_etime) {
1759 has_etime = 1;
1760
1761 etime.tv_sec = t / 1000000;
1762 etime.tv_usec = (t - (etime.tv_sec * 1000000));
1763 timeradd(&etime, &timecopy, &etime);
1764
1765 slp = t;
1766 } else {
1767 if (timercmp(&etime, &timecopy, <=)) {
1768 /* Timed out, but 0 is enough input. */
1769 splx(s);
0b4e3aa0 1770 thread_funnel_set(kernel_flock, funnel_state);
1c79356b
A
1771 return (0);
1772 }
1773 slp = diff(etime, timecopy);
1774 }
1775 }
1776#undef diff
1777 /*
1778 * Rounding down may make us wake up just short
1779 * of the target, so we round up.
1780 * The formula is ceiling(slp * hz/1000000).
1781 * 32-bit arithmetic is enough for hz < 169.
1782 * XXX see hzto() for how to avoid overflow if hz
1783 * is large (divide by `tick' and/or arrange to
1784 * use hzto() if hz is large).
1785 */
1786 slp = (long) (((u_long)slp * hz) + 999999) / 1000000;
1787 goto sleep;
1788 }
1789 if (qp->c_cc <= 0) {
1790sleep:
1791 /*
1792 * There is no input, or not enough input and we can block.
1793 */
1794 error = ttysleep(tp, TSA_HUP_OR_INPUT(tp), TTIPRI | PCATCH,
1795 ISSET(tp->t_state, TS_CONNECTED) ?
1796 "ttyin" : "ttyhup", (int)slp);
1797 splx(s);
1798 if (error == EWOULDBLOCK)
1799 error = 0;
0b4e3aa0
A
1800 else if (error) {
1801 thread_funnel_set(kernel_flock, funnel_state);
1c79356b 1802 return (error);
0b4e3aa0 1803 }
1c79356b
A
1804 /*
1805 * XXX what happens if another process eats some input
1806 * while we are asleep (not just here)? It would be
1807 * safest to detect changes and reset our state variables
1808 * (has_stime and last_cc).
1809 */
1810 slp = 0;
1811 goto loop;
1812 }
1813read:
1814 splx(s);
1815 /*
1816 * Input present, check for input mapping and processing.
1817 */
1818 first = 1;
1819#ifdef NeXT
1820 if (ISSET(lflag, ICANON)
1821 || (ISSET(lflag, IEXTEN | ISIG) == (IEXTEN | ISIG)) )
1822#else
1823 if (ISSET(lflag, ICANON | ISIG))
1824#endif
1825 goto slowcase;
1826 for (;;) {
1827 char ibuf[IBUFSIZ];
1828 int icc;
1829
91447636 1830 icc = min(uio_resid(uio), IBUFSIZ);
1c79356b
A
1831 icc = q_to_b(qp, ibuf, icc);
1832 if (icc <= 0) {
1833 if (first)
1834 goto loop;
1835 break;
1836 }
1837 error = uiomove(ibuf, icc, uio);
1838 /*
1839 * XXX if there was an error then we should ungetc() the
1840 * unmoved chars and reduce icc here.
1841 */
1842#if NSNP > 0
1843 if (ISSET(tp->t_lflag, ECHO) &&
1844 ISSET(tp->t_state, TS_SNOOP) && tp->t_sc != NULL)
1845 snpin((struct snoop *)tp->t_sc, ibuf, icc);
1846#endif
1847 if (error)
1848 break;
91447636 1849 if (uio_resid(uio) == 0)
1c79356b
A
1850 break;
1851 first = 0;
1852 }
1853 goto out;
1854slowcase:
1855 for (;;) {
1856 c = getc(qp);
1857 if (c < 0) {
1858 if (first)
1859 goto loop;
1860 break;
1861 }
1862 /*
1863 * delayed suspend (^Y)
1864 */
1865 if (CCEQ(cc[VDSUSP], c) &&
1866 ISSET(lflag, IEXTEN | ISIG) == (IEXTEN | ISIG)) {
1867 pgsignal(tp->t_pgrp, SIGTSTP, 1);
1868 if (first) {
1869 error = ttysleep(tp, &lbolt, TTIPRI | PCATCH,
1870 "ttybg3", 0);
1871 if (error)
1872 break;
1873 goto loop;
1874 }
1875 break;
1876 }
1877 /*
1878 * Interpret EOF only in canonical mode.
1879 */
1880 if (CCEQ(cc[VEOF], c) && ISSET(lflag, ICANON))
1881 break;
1882 /*
1883 * Give user character.
1884 */
1885 error = ureadc(c, uio);
1886 if (error)
1887 /* XXX should ungetc(c, qp). */
1888 break;
1889#if NSNP > 0
1890 /*
1891 * Only snoop directly on input in echo mode. Non-echoed
1892 * input will be snooped later iff the application echoes it.
1893 */
1894 if (ISSET(tp->t_lflag, ECHO) &&
1895 ISSET(tp->t_state, TS_SNOOP) && tp->t_sc != NULL)
1896 snpinc((struct snoop *)tp->t_sc, (char)c);
1897#endif
91447636 1898 if (uio_resid(uio) == 0)
1c79356b
A
1899 break;
1900 /*
1901 * In canonical mode check for a "break character"
1902 * marking the end of a "line of input".
1903 */
1904 if (ISSET(lflag, ICANON) && TTBREAKC(c, lflag))
1905 break;
1906 first = 0;
1907 }
1908
1909out:
1910 /*
1911 * Look to unblock input now that (presumably)
1912 * the input queue has gone down.
1913 */
1914 s = spltty();
1915 if (ISSET(tp->t_state, TS_TBLOCK) &&
1916 tp->t_rawq.c_cc + tp->t_canq.c_cc <= I_LOW_WATER)
1917 ttyunblock(tp);
1918 splx(s);
1919
0b4e3aa0 1920 thread_funnel_set(kernel_flock, funnel_state);
1c79356b
A
1921 return (error);
1922}
1923
1924/*
1925 * Check the output queue on tp for space for a kernel message (from uprintf
1926 * or tprintf). Allow some space over the normal hiwater mark so we don't
1927 * lose messages due to normal flow control, but don't let the tty run amok.
1928 * Sleeps here are not interruptible, but we return prematurely if new signals
1929 * arrive.
1930 */
1931int
1932ttycheckoutq(tp, wait)
1933 register struct tty *tp;
1934 int wait;
1935{
91447636
A
1936 int hiwat, s;
1937 sigset_t oldsig;
9bccf70c
A
1938 struct uthread *ut;
1939
91447636 1940 ut = (struct uthread *)get_bsdthread_info(current_thread());
1c79356b
A
1941
1942 hiwat = tp->t_hiwat;
1943 s = spltty();
9bccf70c 1944 oldsig = wait ? ut->uu_siglist : 0;
1c79356b
A
1945 if (tp->t_outq.c_cc > hiwat + OBUFSIZ + 100)
1946 while (tp->t_outq.c_cc > hiwat) {
1947 ttstart(tp);
1948 if (tp->t_outq.c_cc <= hiwat)
1949 break;
9bccf70c 1950 if (wait == 0 || ut->uu_siglist != oldsig) {
1c79356b
A
1951 splx(s);
1952 return (0);
1953 }
1954 SET(tp->t_state, TS_SO_OLOWAT);
1955 tsleep(TSA_OLOWAT(tp), PZERO - 1, "ttoutq", hz);
1956 }
1957 splx(s);
1958 return (1);
1959}
1960
1961/*
1962 * Process a write call on a tty device.
1963 */
1964int
1965ttwrite(tp, uio, flag)
1966 register struct tty *tp;
1967 register struct uio *uio;
1968 int flag;
1969{
1970 register char *cp = NULL;
1971 register int cc, ce;
1972 register struct proc *p;
91447636 1973 int i, hiwat, count, error, s;
1c79356b 1974 char obuf[OBUFSIZ];
0b4e3aa0 1975 boolean_t funnel_state;
9bccf70c 1976 struct uthread *ut;
0b4e3aa0
A
1977
1978 funnel_state = thread_funnel_set(kernel_flock, TRUE);
1c79356b 1979
91447636 1980 ut = (struct uthread *)get_bsdthread_info(current_thread());
1c79356b 1981 hiwat = tp->t_hiwat;
91447636
A
1982 // LP64todo - fix this!
1983 count = uio_resid(uio);
1c79356b
A
1984 error = 0;
1985 cc = 0;
1986loop:
1987 s = spltty();
1988 if (ISSET(tp->t_state, TS_ZOMBIE)) {
1989 splx(s);
91447636 1990 if (uio_resid(uio) == count)
1c79356b
A
1991 error = EIO;
1992 goto out;
1993 }
1994 if (!ISSET(tp->t_state, TS_CONNECTED)) {
1995 if (flag & IO_NDELAY) {
1996 splx(s);
1997 error = EWOULDBLOCK;
1998 goto out;
1999 }
2000 error = ttysleep(tp, TSA_CARR_ON(tp), TTIPRI | PCATCH,
2001 "ttydcd", 0);
2002 splx(s);
2003 if (error) {
2004 goto out; }
2005 goto loop;
2006 }
2007 splx(s);
2008 /*
2009 * Hang the process if it's in the background.
2010 */
2011 p = current_proc();
2012 if (isbackground(p, tp) &&
2013 ISSET(tp->t_lflag, TOSTOP) && (p->p_flag & P_PPWAIT) == 0 &&
2014 (p->p_sigignore & sigmask(SIGTTOU)) == 0 &&
9bccf70c 2015 (ut->uu_sigmask & sigmask(SIGTTOU)) == 0) {
1c79356b
A
2016 if (p->p_pgrp->pg_jobc == 0) {
2017 error = EIO;
2018 goto out;
2019 }
2020 pgsignal(p->p_pgrp, SIGTTOU, 1);
2021 error = ttysleep(tp, &lbolt, TTIPRI | PCATCH | PTTYBLOCK, "ttybg4", 0);
2022 if (error)
2023 goto out;
2024 goto loop;
2025 }
2026 /*
2027 * Process the user's data in at most OBUFSIZ chunks. Perform any
2028 * output translation. Keep track of high water mark, sleep on
2029 * overflow awaiting device aid in acquiring new space.
2030 */
91447636 2031 while (uio_resid(uio) > 0 || cc > 0) {
1c79356b 2032 if (ISSET(tp->t_lflag, FLUSHO)) {
91447636 2033 uio_setresid(uio, 0);
0b4e3aa0 2034 thread_funnel_set(kernel_flock, funnel_state);
1c79356b
A
2035 return (0);
2036 }
2037 if (tp->t_outq.c_cc > hiwat)
2038 goto ovhiwat;
2039 /*
2040 * Grab a hunk of data from the user, unless we have some
2041 * leftover from last time.
2042 */
2043 if (cc == 0) {
91447636 2044 cc = min(uio_resid(uio), OBUFSIZ);
1c79356b
A
2045 cp = obuf;
2046 error = uiomove(cp, cc, uio);
2047 if (error) {
2048 cc = 0;
2049 break;
2050 }
2051#if NSNP > 0
2052 if (ISSET(tp->t_state, TS_SNOOP) && tp->t_sc != NULL)
2053 snpin((struct snoop *)tp->t_sc, cp, cc);
2054#endif
2055 }
2056 /*
2057 * If nothing fancy need be done, grab those characters we
2058 * can handle without any of ttyoutput's processing and
2059 * just transfer them to the output q. For those chars
2060 * which require special processing (as indicated by the
2061 * bits in char_type), call ttyoutput. After processing
2062 * a hunk of data, look for FLUSHO so ^O's will take effect
2063 * immediately.
2064 */
2065 while (cc > 0) {
2066 if (!ISSET(tp->t_oflag, OPOST))
2067 ce = cc;
2068 else {
2069 ce = cc - scanc((u_int)cc, (u_char *)cp,
91447636 2070 char_type, CCLASSMASK);
1c79356b
A
2071 /*
2072 * If ce is zero, then we're processing
2073 * a special character through ttyoutput.
2074 */
2075 if (ce == 0) {
2076 tp->t_rocount = 0;
2077 if (ttyoutput(*cp, tp) >= 0) {
2078#ifdef NeXT
2079 /* out of space */
2080 goto overfull;
2081#else
2082 /* No Clists, wait a bit. */
2083 ttstart(tp);
2084 if (flag & IO_NDELAY) {
2085 error = EWOULDBLOCK;
2086 goto out;
2087 }
2088 error = ttysleep(tp, &lbolt,
2089 TTOPRI|PCATCH,
2090 "ttybf1", 0);
2091 if (error)
2092 goto out;
2093 goto loop;
2094#endif /* NeXT */
2095 }
2096 cp++;
2097 cc--;
2098 if (ISSET(tp->t_lflag, FLUSHO) ||
2099 tp->t_outq.c_cc > hiwat)
2100 goto ovhiwat;
2101 continue;
2102 }
2103 }
2104 /*
2105 * A bunch of normal characters have been found.
2106 * Transfer them en masse to the output queue and
2107 * continue processing at the top of the loop.
2108 * If there are any further characters in this
2109 * <= OBUFSIZ chunk, the first should be a character
2110 * requiring special handling by ttyoutput.
2111 */
2112 tp->t_rocount = 0;
2113 i = b_to_q(cp, ce, &tp->t_outq);
2114 ce -= i;
2115 tp->t_column += ce;
2116 cp += ce, cc -= ce, tk_nout += ce;
2117 tp->t_outcc += ce;
2118 if (i > 0) {
2119#ifdef NeXT
2120 /* out of space */
2121 goto overfull;
2122#else
2123 /* No Clists, wait a bit. */
2124 ttstart(tp);
2125 if (flag & IO_NDELAY) {
2126 error = EWOULDBLOCK;
2127 goto out;
2128 }
2129 error = ttysleep(tp, &lbolt, TTOPRI | PCATCH,
2130 "ttybf2", 0);
2131 if (error)
2132 goto out;
2133 goto loop;
2134#endif /* NeXT */
2135 }
2136 if (ISSET(tp->t_lflag, FLUSHO) ||
2137 tp->t_outq.c_cc > hiwat)
2138 break;
2139 }
2140 ttstart(tp);
2141 }
2142out:
2143 /*
2144 * If cc is nonzero, we leave the uio structure inconsistent, as the
2145 * offset and iov pointers have moved forward, but it doesn't matter
2146 * (the call will either return short or restart with a new uio).
2147 */
91447636 2148 uio_setresid(uio, (uio_resid(uio) + cc));
0b4e3aa0 2149 thread_funnel_set(kernel_flock, funnel_state);
1c79356b
A
2150 return (error);
2151
2152#ifdef NeXT
2153overfull:
2154
2155 /*
2156 * Since we are using ring buffers, if we can't insert any more into
2157 * the output queue, we can assume the ring is full and that someone
2158 * forgot to set the high water mark correctly. We set it and then
2159 * proceed as normal.
2160 */
2161 hiwat = tp->t_outq.c_cc - 1;
2162#endif
2163
2164ovhiwat:
2165 ttstart(tp);
2166 s = spltty();
2167 /*
2168 * This can only occur if FLUSHO is set in t_lflag,
2169 * or if ttstart/oproc is synchronous (or very fast).
2170 */
2171 if (tp->t_outq.c_cc <= hiwat) {
2172 splx(s);
2173 goto loop;
2174 }
2175 if (flag & IO_NDELAY) {
2176 splx(s);
91447636 2177 uio_setresid(uio, (uio_resid(uio) + cc));
0b4e3aa0 2178 thread_funnel_set(kernel_flock, funnel_state);
91447636 2179 return (uio_resid(uio) == count ? EWOULDBLOCK : 0);
1c79356b
A
2180 }
2181 SET(tp->t_state, TS_SO_OLOWAT);
2182 error = ttysleep(tp, TSA_OLOWAT(tp), TTOPRI | PCATCH, "ttywri",
2183 tp->t_timeout);
2184 splx(s);
2185 if (error == EWOULDBLOCK)
2186 error = EIO;
2187 if (error)
2188 goto out;
2189 goto loop;
2190}
2191
2192/*
2193 * Rubout one character from the rawq of tp
2194 * as cleanly as possible.
2195 */
2196static void
2197ttyrub(c, tp)
2198 register int c;
2199 register struct tty *tp;
2200{
2201 register u_char *cp;
2202 register int savecol;
2203 int tabc, s;
2204
2205 if (!ISSET(tp->t_lflag, ECHO) || ISSET(tp->t_lflag, EXTPROC))
2206 return;
2207 CLR(tp->t_lflag, FLUSHO);
2208 if (ISSET(tp->t_lflag, ECHOE)) {
2209 if (tp->t_rocount == 0) {
2210 /*
2211 * Messed up by ttwrite; retype
2212 */
2213 ttyretype(tp);
2214 return;
2215 }
2216 if (c == ('\t' | TTY_QUOTE) || c == ('\n' | TTY_QUOTE))
2217 ttyrubo(tp, 2);
2218 else {
2219 CLR(c, ~TTY_CHARMASK);
2220 switch (CCLASS(c)) {
2221 case ORDINARY:
2222 ttyrubo(tp, 1);
2223 break;
2224 case BACKSPACE:
2225 case CONTROL:
2226 case NEWLINE:
2227 case RETURN:
2228 case VTAB:
2229 if (ISSET(tp->t_lflag, ECHOCTL))
2230 ttyrubo(tp, 2);
2231 break;
2232 case TAB:
2233 if (tp->t_rocount < tp->t_rawq.c_cc) {
2234 ttyretype(tp);
2235 return;
2236 }
2237 s = spltty();
2238 savecol = tp->t_column;
2239 SET(tp->t_state, TS_CNTTB);
2240 SET(tp->t_lflag, FLUSHO);
2241 tp->t_column = tp->t_rocol;
2242#ifndef NeXT
2243 cp = tp->t_rawq.c_cf;
2244 if (cp)
2245 tabc = *cp; /* XXX FIX NEXTC */
2246 for (; cp; cp = nextc(&tp->t_rawq, cp, &tabc))
2247 ttyecho(tabc, tp);
2248#else
2249 for (cp = firstc(&tp->t_rawq, &tabc); cp;
2250 cp = nextc(&tp->t_rawq, cp, &tabc))
2251 ttyecho(tabc, tp);
2252#endif /* !NeXT */
2253 CLR(tp->t_lflag, FLUSHO);
2254 CLR(tp->t_state, TS_CNTTB);
2255 splx(s);
2256
2257 /* savecol will now be length of the tab. */
2258 savecol -= tp->t_column;
2259 tp->t_column += savecol;
2260 if (savecol > 8)
2261 savecol = 8; /* overflow fixup */
2262 while (--savecol >= 0)
2263 (void)ttyoutput('\b', tp);
2264 break;
2265 default: /* XXX */
2266#define PANICSTR "ttyrub: would panic c = %d, val = %d\n"
2267 (void)printf(PANICSTR, c, CCLASS(c));
2268#ifdef notdef
2269 panic(PANICSTR, c, CCLASS(c));
2270#endif
2271 }
2272 }
2273 } else if (ISSET(tp->t_lflag, ECHOPRT)) {
2274 if (!ISSET(tp->t_state, TS_ERASE)) {
2275 SET(tp->t_state, TS_ERASE);
2276 (void)ttyoutput('\\', tp);
2277 }
2278 ttyecho(c, tp);
2279 } else
2280 ttyecho(tp->t_cc[VERASE], tp);
2281 --tp->t_rocount;
2282}
2283
2284/*
91447636 2285 * Back over count characters, erasing them.
1c79356b
A
2286 */
2287static void
91447636 2288ttyrubo(struct tty *tp, int count)
1c79356b
A
2289{
2290
91447636 2291 while (count-- > 0) {
1c79356b
A
2292 (void)ttyoutput('\b', tp);
2293 (void)ttyoutput(' ', tp);
2294 (void)ttyoutput('\b', tp);
2295 }
2296}
2297
2298/*
2299 * ttyretype --
2300 * Reprint the rawq line. Note, it is assumed that c_cc has already
2301 * been checked.
2302 */
2303static void
2304ttyretype(tp)
2305 register struct tty *tp;
2306{
2307 register u_char *cp;
2308 int s, c;
2309
2310 /* Echo the reprint character. */
2311 if (tp->t_cc[VREPRINT] != _POSIX_VDISABLE)
2312 ttyecho(tp->t_cc[VREPRINT], tp);
2313
2314 (void)ttyoutput('\n', tp);
2315
2316 /*
2317 * FREEBSD XXX
2318 * FIX: NEXTC IS BROKEN - DOESN'T CHECK QUOTE
2319 * BIT OF FIRST CHAR.
2320 */
2321 s = spltty();
2322#ifndef NeXT
2323 for (cp = tp->t_canq.c_cf, c = (cp != NULL ? *cp : 0);
2324 cp != NULL; cp = nextc(&tp->t_canq, cp, &c))
2325 ttyecho(c, tp);
2326 for (cp = tp->t_rawq.c_cf, c = (cp != NULL ? *cp : 0);
2327 cp != NULL; cp = nextc(&tp->t_rawq, cp, &c))
2328 ttyecho(c, tp);
2329#else NeXT
2330 for (cp = firstc(&tp->t_canq, &c); cp; cp = nextc(&tp->t_canq, cp, &c))
2331 ttyecho(c, tp);
2332 for (cp = firstc(&tp->t_rawq, &c); cp; cp = nextc(&tp->t_rawq, cp, &c))
2333 ttyecho(c, tp);
2334#endif /* !NeXT */
2335 CLR(tp->t_state, TS_ERASE);
2336 splx(s);
2337
2338 tp->t_rocount = tp->t_rawq.c_cc;
2339 tp->t_rocol = 0;
2340}
2341
2342/*
2343 * Echo a typed character to the terminal.
2344 */
2345static void
2346ttyecho(c, tp)
2347 register int c;
2348 register struct tty *tp;
2349{
2350
2351 if (!ISSET(tp->t_state, TS_CNTTB))
2352 CLR(tp->t_lflag, FLUSHO);
2353 if ((!ISSET(tp->t_lflag, ECHO) &&
2354 (c != '\n' || !ISSET(tp->t_lflag, ECHONL))) ||
2355 ISSET(tp->t_lflag, EXTPROC))
2356 return;
2357 if (ISSET(tp->t_lflag, ECHOCTL) &&
2358 ((ISSET(c, TTY_CHARMASK) <= 037 && c != '\t' && c != '\n') ||
2359 ISSET(c, TTY_CHARMASK) == 0177)) {
2360 (void)ttyoutput('^', tp);
2361 CLR(c, ~TTY_CHARMASK);
2362 if (c == 0177)
2363 c = '?';
2364 else
2365 c += 'A' - 1;
2366 }
2367 (void)ttyoutput(c, tp);
2368}
2369
2370/*
2371 * Wake up any readers on a tty.
2372 */
2373void
2374ttwakeup(tp)
2375 register struct tty *tp;
2376{
2377
2378#ifndef NeXT
2379 if (tp->t_rsel.si_pid != 0)
2380#endif
2381 selwakeup(&tp->t_rsel);
2382 if (ISSET(tp->t_state, TS_ASYNC))
2383 pgsignal(tp->t_pgrp, SIGIO, 1);
2384 wakeup(TSA_HUP_OR_INPUT(tp));
2385}
2386
2387/*
2388 * Wake up any writers on a tty.
2389 */
2390void
2391ttwwakeup(tp)
2392 register struct tty *tp;
2393{
2394#ifndef NeXT
2395 if (tp->t_wsel.si_pid != 0 && tp->t_outq.c_cc <= tp->t_lowat)
2396#else
2397 if (tp->t_outq.c_cc <= tp->t_lowat)
2398#endif
2399 selwakeup(&tp->t_wsel);
2400 if (ISSET(tp->t_state, TS_BUSY | TS_SO_OCOMPLETE) ==
2401 TS_SO_OCOMPLETE && tp->t_outq.c_cc == 0) {
2402 CLR(tp->t_state, TS_SO_OCOMPLETE);
2403 wakeup(TSA_OCOMPLETE(tp));
2404 }
2405 if (ISSET(tp->t_state, TS_SO_OLOWAT) &&
2406 tp->t_outq.c_cc <= tp->t_lowat) {
2407 CLR(tp->t_state, TS_SO_OLOWAT);
2408 wakeup(TSA_OLOWAT(tp));
2409 }
2410}
2411
2412/*
2413 * Look up a code for a specified speed in a conversion table;
2414 * used by drivers to map software speed values to hardware parameters.
2415 */
2416int
2417ttspeedtab(speed, table)
2418 int speed;
2419 register struct speedtab *table;
2420{
2421
2422 for ( ; table->sp_speed != -1; table++)
2423 if (table->sp_speed == speed)
2424 return (table->sp_code);
2425 return (-1);
2426}
2427
2428/*
2429 * Set tty hi and low water marks.
2430 *
2431 * Try to arrange the dynamics so there's about one second
2432 * from hi to low water.
2433 *
2434 */
2435void
91447636 2436ttsetwater(struct tty *tp)
1c79356b 2437{
91447636
A
2438 int cps;
2439 unsigned int x;
1c79356b
A
2440
2441#define CLAMP(x, h, l) ((x) > h ? h : ((x) < l) ? l : (x))
2442
2443 cps = tp->t_ospeed / 10;
2444 tp->t_lowat = x = CLAMP(cps / 2, TTMAXLOWAT, TTMINLOWAT);
2445 x += cps;
2446 x = CLAMP(x, TTMAXHIWAT, TTMINHIWAT);
2447 tp->t_hiwat = roundup(x, CBSIZE);
2448#undef CLAMP
2449}
2450
2451/* NeXT ttyinfo has been converted to the MACH kernel */
2452#include <mach/thread_info.h>
2453
91447636
A
2454/* XXX Should be in Mach header <kern/thread.h>, but doesn't work */
2455extern kern_return_t thread_info_internal(thread_t thread,
2456 thread_flavor_t flavor,
2457 thread_info_t thread_info_out,
2458 mach_msg_type_number_t *thread_info_count);
2459
1c79356b
A
2460/*
2461 * Report on state of foreground process group.
2462 */
2463void
91447636 2464ttyinfo(struct tty *tp)
1c79356b 2465{
91447636
A
2466 int load;
2467 thread_t thread;
2468 uthread_t uthread;
2469 struct proc *p;
2470 struct proc *pick;
2471 const char *state;
2472 struct timeval utime;
2473 struct timeval stime;
2474 thread_basic_info_data_t basic_info;
2475 mach_msg_type_number_t mmtn = THREAD_BASIC_INFO_COUNT;
2476
2477 if (ttycheckoutq(tp,0) == 0)
2478 return;
2479
2480 /* Print load average. */
2481 load = (averunnable.ldavg[0] * 100 + FSCALE / 2) >> FSHIFT;
2482 ttyprintf(tp, "load: %d.%02d ", load / 100, load % 100);
2483
2484 /*
2485 * On return following a ttyprintf(), we set tp->t_rocount to 0 so
2486 * that pending input will be retyped on BS.
2487 */
2488 if (tp->t_session == NULL) {
2489 ttyprintf(tp, "not a controlling terminal\n");
2490 tp->t_rocount = 0;
2491 return;
2492}
2493 if (tp->t_pgrp == NULL) {
2494 ttyprintf(tp, "no foreground process group\n");
2495 tp->t_rocount = 0;
2496 return;
2497 }
2498 /* first process in process group */
2499 if ((p = tp->t_pgrp->pg_members.lh_first) == NULL) {
2500 ttyprintf(tp, "empty foreground process group\n");
2501 tp->t_rocount = 0;
2502 return;
2503 }
2504
2505 /*
2506 * Pick the most interesting process and copy some of its
2507 * state for printing later.
2508 */
2509 for (pick = NULL; p != NULL; p = p->p_pglist.le_next) {
2510 if (proc_compare(pick, p))
2511 pick = p;
2512 }
2513
2514 if (TAILQ_EMPTY(&pick->p_uthlist) ||
2515 (uthread = TAILQ_FIRST(&pick->p_uthlist)) == NULL ||
2516 (thread = uthread->uu_act) == NULL ||
2517 (thread_info_internal(thread, THREAD_BASIC_INFO, (thread_info_t)&basic_info, &mmtn) != KERN_SUCCESS)) {
2518 ttyprintf(tp, "foreground process without thread\n");
2519 tp->t_rocount = 0;
2520 return;
2521 }
2522
2523 switch(basic_info.run_state) {
2524 case TH_STATE_RUNNING:
2525 state = "running";
2526 break;
2527 case TH_STATE_STOPPED:
2528 state = "stopped";
2529 break;
2530 case TH_STATE_WAITING:
2531 state = "waiting";
2532 break;
2533 case TH_STATE_UNINTERRUPTIBLE:
2534 state = "uninterruptible";
2535 break;
2536 case TH_STATE_HALTED:
2537 state = "halted";
2538 break;
2539 default:
2540 state = "unknown";
2541 break;
2542 }
2543 calcru(pick, &utime, &stime, NULL);
2544
2545 /* Print command, pid, state, utime, and stime */
2546 ttyprintf(tp, " cmd: %s %d %s %ld.%02ldu %ld.%02lds\n",
2547 pick->p_comm,
2548 pick->p_pid,
2549 state,
2550 (long)utime.tv_sec, utime.tv_usec / 10000,
2551 (long)stime.tv_sec, stime.tv_usec / 10000);
2552 tp->t_rocount = 0;
1c79356b
A
2553}
2554
1c79356b
A
2555/*
2556 * Returns 1 if p2 is "better" than p1
2557 *
2558 * The algorithm for picking the "interesting" process is thus:
2559 *
2560 * 1) Only foreground processes are eligible - implied.
2561 * 2) Runnable processes are favored over anything else. The runner
2562 * with the highest cpu utilization is picked (p_estcpu). Ties are
2563 * broken by picking the highest pid.
91447636 2564 * 3) The sleeper with the shortest sleep time is next.
1c79356b
A
2565 * 4) Further ties are broken by picking the highest pid.
2566 */
2567#define ISRUN(p) (((p)->p_stat == SRUN) || ((p)->p_stat == SIDL))
2568#define TESTAB(a, b) ((a)<<1 | (b))
2569#define ONLYA 2
2570#define ONLYB 1
2571#define BOTH 3
2572
2573static int
2574proc_compare(p1, p2)
2575 register struct proc *p1, *p2;
2576{
2577
2578 if (p1 == NULL)
2579 return (1);
2580 /*
2581 * see if at least one of them is runnable
2582 */
2583 switch (TESTAB(ISRUN(p1), ISRUN(p2))) {
2584 case ONLYA:
2585 return (0);
2586 case ONLYB:
2587 return (1);
2588 case BOTH:
2589 /*
2590 * tie - favor one with highest recent cpu utilization
2591 */
2592 if (p2->p_estcpu > p1->p_estcpu)
2593 return (1);
2594 if (p1->p_estcpu > p2->p_estcpu)
2595 return (0);
2596 return (p2->p_pid > p1->p_pid); /* tie - return highest pid */
2597 }
2598 /*
2599 * weed out zombies
2600 */
2601 switch (TESTAB(p1->p_stat == SZOMB, p2->p_stat == SZOMB)) {
2602 case ONLYA:
2603 return (1);
2604 case ONLYB:
2605 return (0);
2606 case BOTH:
2607 return (p2->p_pid > p1->p_pid); /* tie - return highest pid */
2608 }
2609 /*
2610 * pick the one with the smallest sleep time
2611 */
2612 if (p2->p_slptime > p1->p_slptime)
2613 return (0);
2614 if (p1->p_slptime > p2->p_slptime)
2615 return (1);
1c79356b
A
2616 return (p2->p_pid > p1->p_pid); /* tie - return highest pid */
2617}
1c79356b
A
2618
2619/*
2620 * Output char to tty; console putchar style.
2621 */
2622int
2623tputchar(c, tp)
2624 int c;
2625 struct tty *tp;
2626{
2627 register int s;
2628
2629 s = spltty();
2630 if (!ISSET(tp->t_state, TS_CONNECTED)) {
2631 splx(s);
2632 return (-1);
2633 }
2634 if (c == '\n')
2635 (void)ttyoutput('\r', tp);
2636 (void)ttyoutput(c, tp);
2637 ttstart(tp);
2638 splx(s);
2639 return (0);
2640}
2641
2642/*
2643 * Sleep on chan, returning ERESTART if tty changed while we napped and
2644 * returning any errors (e.g. EINTR/EWOULDBLOCK) reported by tsleep. If
2645 * the tty is revoked, restarting a pending call will redo validation done
2646 * at the start of the call.
2647 */
2648int
91447636 2649ttysleep(struct tty *tp, void *chan, int pri, const char *wmesg, int timo)
1c79356b
A
2650{
2651 int error;
2652 int gen;
2653
2654 gen = tp->t_gen;
2655 error = tsleep(chan, pri, wmesg, timo);
2656 if (error)
2657 return (error);
2658 return (tp->t_gen == gen ? 0 : ERESTART);
2659}
2660
2661#ifdef NeXT
2662/*
2663 * Allocate a tty structure and its associated buffers.
2664 */
2665struct tty *
91447636 2666ttymalloc(void)
1c79356b
A
2667{
2668 struct tty *tp;
2669
91447636
A
2670 MALLOC(tp, struct tty *, sizeof(struct tty), M_TTYS, M_WAITOK|M_ZERO);
2671 if (tp != NULL) {
2672 /* XXX: default to TTYCLSIZE(1024) chars for now */
2673 clalloc(&tp->t_rawq, TTYCLSIZE, 1);
2674 clalloc(&tp->t_canq, TTYCLSIZE, 1);
2675 /* output queue doesn't need quoting */
2676 clalloc(&tp->t_outq, TTYCLSIZE, 0);
2677 }
1c79356b
A
2678 return(tp);
2679}
2680
2681/*
2682 * Free a tty structure and its buffers.
2683 */
2684void
2685ttyfree(tp)
2686struct tty *tp;
2687{
2688 clfree(&tp->t_rawq);
2689 clfree(&tp->t_canq);
2690 clfree(&tp->t_outq);
2691 FREE(tp, M_TTYS);
2692}
2693
2694#else /* !NeXT */
2695
2696#ifdef notyet
2697/*
2698 * XXX this is usable not useful or used. Most tty drivers have
2699 * ifdefs for using ttymalloc() but assume a different interface.
2700 */
2701/*
2702 * Allocate a tty struct. Clists in the struct will be allocated by
2703 * ttyopen().
2704 */
2705struct tty *
2706ttymalloc()
2707{
2708 struct tty *tp;
2709
91447636 2710 MALLOC(tp, struct tty *, sizeof *tp, M_TTYS, M_WAITOK|M_ZERO);
1c79356b
A
2711 return (tp);
2712}
2713#endif
2714
2715#if 0 /* XXX not yet usable: session leader holds a ref (see kern_exit.c). */
2716/*
2717 * Free a tty struct. Clists in the struct should have been freed by
2718 * ttyclose().
2719 */
2720void
2721ttyfree(tp)
2722 struct tty *tp;
2723{
2724 FREE(tp, M_TTYS);
2725}
2726#endif /* 0 */
2727#endif /* NeXT */