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