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