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