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