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