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