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