Annotation of src/sys/kern/tty.c, Revision 1.173.2.4
1.173.2.4! yamt 1: /* $NetBSD: tty.c,v 1.173.2.3 2007/02/26 09:11:19 yamt Exp $ */
1.49 cgd 2:
3: /*-
4: * Copyright (c) 1982, 1986, 1990, 1991, 1993
5: * The Regents of the University of California. All rights reserved.
6: * (c) UNIX System Laboratories, Inc.
7: * All or some portions of this file are derived from material licensed
8: * to the University of California by American Telephone and Telegraph
9: * Co. or Unix System Laboratories, Inc. and are reproduced herein with
10: * the permission of UNIX System Laboratories, Inc.
11: *
12: * Redistribution and use in source and binary forms, with or without
13: * modification, are permitted provided that the following conditions
14: * are met:
15: * 1. Redistributions of source code must retain the above copyright
16: * notice, this list of conditions and the following disclaimer.
17: * 2. Redistributions in binary form must reproduce the above copyright
18: * notice, this list of conditions and the following disclaimer in the
19: * documentation and/or other materials provided with the distribution.
1.155 agc 20: * 3. Neither the name of the University nor the names of its contributors
1.49 cgd 21: * may be used to endorse or promote products derived from this software
22: * without specific prior written permission.
23: *
24: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34: * SUCH DAMAGE.
35: *
1.105 fvdl 36: * @(#)tty.c 8.13 (Berkeley) 1/9/95
1.49 cgd 37: */
1.129 lukem 38:
39: #include <sys/cdefs.h>
1.173.2.4! yamt 40: __KERNEL_RCSID(0, "$NetBSD: tty.c,v 1.173.2.3 2007/02/26 09:11:19 yamt Exp $");
1.49 cgd 41:
42: #include <sys/param.h>
43: #include <sys/systm.h>
44: #include <sys/ioctl.h>
45: #include <sys/proc.h>
46: #define TTYDEFCHARS
47: #include <sys/tty.h>
48: #undef TTYDEFCHARS
49: #include <sys/file.h>
50: #include <sys/conf.h>
51: #include <sys/dkstat.h>
52: #include <sys/uio.h>
53: #include <sys/kernel.h>
54: #include <sys/vnode.h>
55: #include <sys/syslog.h>
56: #include <sys/malloc.h>
1.111 thorpej 57: #include <sys/pool.h>
1.65 christos 58: #include <sys/signalvar.h>
59: #include <sys/resourcevar.h>
1.74 mycroft 60: #include <sys/poll.h>
1.149 christos 61: #include <sys/kprintf.h>
1.151 christos 62: #include <sys/namei.h>
1.159 atatat 63: #include <sys/sysctl.h>
1.173.2.1 yamt 64: #include <sys/kauth.h>
1.149 christos 65:
66: #include <machine/stdarg.h>
1.49 cgd 67:
1.126 lukem 68: static int ttnread(struct tty *);
69: static void ttyblock(struct tty *);
70: static void ttyecho(int, struct tty *);
71: static void ttyrubo(struct tty *, int);
1.149 christos 72: static void ttyprintf_nolock(struct tty *, const char *fmt, ...)
73: __attribute__((__format__(__printf__,2,3)));
1.126 lukem 74: static int proc_compare(struct proc *, struct proc *);
1.49 cgd 75:
76: /* Symbolic sleep message strings. */
1.98 mycroft 77: const char ttclos[] = "ttycls";
78: const char ttopen[] = "ttyopn";
79: const char ttybg[] = "ttybg";
80: const char ttyin[] = "ttyin";
81: const char ttyout[] = "ttyout";
1.49 cgd 82:
83: /*
1.83 mycroft 84: * Used to determine whether we still have a connection. This is true in
85: * one of 3 cases:
86: * 1) We have carrier.
87: * 2) It's a locally attached terminal, and we are therefore ignoring carrier.
88: * 3) We're using a flow control mechanism that overloads the carrier signal.
89: */
90: #define CONNECTED(tp) (ISSET(tp->t_state, TS_CARR_ON) || \
91: ISSET(tp->t_cflag, CLOCAL | MDMBUF))
92:
93: /*
1.49 cgd 94: * Table with character classes and parity. The 8th bit indicates parity,
95: * the 7th bit indicates the character is an alphameric or underscore (for
96: * ALTWERASE), and the low 6 bits indicate delay type. If the low 6 bits
97: * are 0 then the character needs no special processing on output; classes
98: * other than 0 might be translated or (not currently) require delays.
99: */
100: #define E 0x00 /* Even parity. */
101: #define O 0x80 /* Odd parity. */
102: #define PARITY(c) (char_type[c] & O)
103:
104: #define ALPHA 0x40 /* Alpha or underscore. */
105: #define ISALPHA(c) (char_type[(c) & TTY_CHARMASK] & ALPHA)
106:
107: #define CCLASSMASK 0x3f
108: #define CCLASS(c) (char_type[c] & CCLASSMASK)
109:
110: #define BS BACKSPACE
111: #define CC CONTROL
112: #define CR RETURN
113: #define NA ORDINARY | ALPHA
114: #define NL NEWLINE
115: #define NO ORDINARY
116: #define TB TAB
117: #define VT VTAB
118:
1.146 simonb 119: unsigned char const char_type[] = {
1.49 cgd 120: E|CC, O|CC, O|CC, E|CC, O|CC, E|CC, E|CC, O|CC, /* nul - bel */
1.137 simonb 121: O|BS, E|TB, E|NL, O|CC, E|VT, O|CR, O|CC, E|CC, /* bs - si */
1.138 enami 122: O|CC, E|CC, E|CC, O|CC, E|CC, O|CC, O|CC, E|CC, /* dle - etb */
123: E|CC, O|CC, O|CC, E|CC, O|CC, E|CC, E|CC, O|CC, /* can - us */
124: O|NO, E|NO, E|NO, O|NO, E|NO, O|NO, O|NO, E|NO, /* sp - ' */
125: E|NO, O|NO, O|NO, E|NO, O|NO, E|NO, E|NO, O|NO, /* ( - / */
126: E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* 0 - 7 */
127: O|NA, E|NA, E|NO, O|NO, E|NO, O|NO, O|NO, E|NO, /* 8 - ? */
128: O|NO, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA, /* @ - G */
129: E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* H - O */
130: E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* P - W */
131: O|NA, E|NA, E|NA, O|NO, E|NO, O|NO, O|NO, O|NA, /* X - _ */
132: E|NO, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* ` - g */
133: O|NA, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA, /* h - o */
134: O|NA, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA, /* p - w */
135: E|NA, O|NA, O|NA, E|NO, O|NO, E|NO, E|NO, O|CC, /* x - del */
1.49 cgd 136: /*
137: * Meta chars; should be settable per character set;
138: * for now, treat them all as normal characters.
139: */
140: NA, NA, NA, NA, NA, NA, NA, NA,
141: NA, NA, NA, NA, NA, NA, NA, NA,
142: NA, NA, NA, NA, NA, NA, NA, NA,
143: NA, NA, NA, NA, NA, NA, NA, NA,
144: NA, NA, NA, NA, NA, NA, NA, NA,
145: NA, NA, NA, NA, NA, NA, NA, NA,
146: NA, NA, NA, NA, NA, NA, NA, NA,
147: NA, NA, NA, NA, NA, NA, NA, NA,
148: NA, NA, NA, NA, NA, NA, NA, NA,
149: NA, NA, NA, NA, NA, NA, NA, NA,
150: NA, NA, NA, NA, NA, NA, NA, NA,
151: NA, NA, NA, NA, NA, NA, NA, NA,
152: NA, NA, NA, NA, NA, NA, NA, NA,
153: NA, NA, NA, NA, NA, NA, NA, NA,
154: NA, NA, NA, NA, NA, NA, NA, NA,
155: NA, NA, NA, NA, NA, NA, NA, NA,
156: };
157: #undef BS
158: #undef CC
159: #undef CR
160: #undef NA
161: #undef NL
162: #undef NO
163: #undef TB
164: #undef VT
165:
1.173.2.4! yamt 166: kmutex_t ttylist_lock;
1.169 thorpej 167: struct ttylist_head ttylist = TAILQ_HEAD_INITIALIZER(ttylist);
1.69 mrg 168: int tty_count;
169:
1.167 simonb 170: POOL_INIT(tty_pool, sizeof(struct tty), 0, 0, 0, "ttypl",
1.173.2.4! yamt 171: &pool_allocator_nointr, IPL_NONE);
1.130 simonb 172:
1.173.2.1 yamt 173: uint64_t tk_cancc;
174: uint64_t tk_nin;
175: uint64_t tk_nout;
176: uint64_t tk_rawcc;
1.159 atatat 177:
178: SYSCTL_SETUP(sysctl_kern_tkstat_setup, "sysctl kern.tkstat subtree setup")
179: {
180:
1.165 atatat 181: sysctl_createv(clog, 0, NULL, NULL,
182: CTLFLAG_PERMANENT,
1.159 atatat 183: CTLTYPE_NODE, "kern", NULL,
184: NULL, 0, NULL, 0,
185: CTL_KERN, CTL_EOL);
1.165 atatat 186: sysctl_createv(clog, 0, NULL, NULL,
187: CTLFLAG_PERMANENT,
1.168 atatat 188: CTLTYPE_NODE, "tkstat",
189: SYSCTL_DESCR("Number of characters sent and and "
190: "received on ttys"),
1.159 atatat 191: NULL, 0, NULL, 0,
192: CTL_KERN, KERN_TKSTAT, CTL_EOL);
193:
1.165 atatat 194: sysctl_createv(clog, 0, NULL, NULL,
195: CTLFLAG_PERMANENT,
1.168 atatat 196: CTLTYPE_QUAD, "nin",
197: SYSCTL_DESCR("Total number of tty input characters"),
1.159 atatat 198: NULL, 0, &tk_nin, 0,
199: CTL_KERN, KERN_TKSTAT, KERN_TKSTAT_NIN, CTL_EOL);
1.165 atatat 200: sysctl_createv(clog, 0, NULL, NULL,
201: CTLFLAG_PERMANENT,
1.168 atatat 202: CTLTYPE_QUAD, "nout",
203: SYSCTL_DESCR("Total number of tty output characters"),
1.159 atatat 204: NULL, 0, &tk_nout, 0,
205: CTL_KERN, KERN_TKSTAT, KERN_TKSTAT_NOUT, CTL_EOL);
1.165 atatat 206: sysctl_createv(clog, 0, NULL, NULL,
207: CTLFLAG_PERMANENT,
1.168 atatat 208: CTLTYPE_QUAD, "cancc",
209: SYSCTL_DESCR("Number of canonical tty input characters"),
1.159 atatat 210: NULL, 0, &tk_cancc, 0,
211: CTL_KERN, KERN_TKSTAT, KERN_TKSTAT_CANCC, CTL_EOL);
1.165 atatat 212: sysctl_createv(clog, 0, NULL, NULL,
213: CTLFLAG_PERMANENT,
1.168 atatat 214: CTLTYPE_QUAD, "rawcc",
215: SYSCTL_DESCR("Number of raw tty input characters"),
1.159 atatat 216: NULL, 0, &tk_rawcc, 0,
217: CTL_KERN, KERN_TKSTAT, KERN_TKSTAT_RAWCC, CTL_EOL);
218: }
1.111 thorpej 219:
1.107 mycroft 220: int
1.126 lukem 221: ttyopen(struct tty *tp, int dialout, int nonblock)
1.107 mycroft 222: {
1.126 lukem 223: int s, error;
1.107 mycroft 224:
1.147 pk 225: error = 0;
226:
1.107 mycroft 227: s = spltty();
1.147 pk 228: TTY_LOCK(tp);
1.107 mycroft 229:
230: if (dialout) {
231: /*
232: * If the device is already open for non-dialout, fail.
233: * Otherwise, set TS_DIALOUT to block any pending non-dialout
234: * opens.
235: */
236: if (ISSET(tp->t_state, TS_ISOPEN) &&
237: !ISSET(tp->t_state, TS_DIALOUT)) {
1.147 pk 238: error = EBUSY;
239: goto out;
1.107 mycroft 240: }
241: SET(tp->t_state, TS_DIALOUT);
242: } else {
243: if (!nonblock) {
244: /*
245: * Wait for carrier. Also wait for any dialout
246: * processes to close the tty first.
247: */
248: while (ISSET(tp->t_state, TS_DIALOUT) ||
1.147 pk 249: !CONNECTED(tp)) {
1.107 mycroft 250: tp->t_wopen++;
251: error = ttysleep(tp, &tp->t_rawq,
252: TTIPRI | PCATCH, ttopen, 0);
253: tp->t_wopen--;
1.147 pk 254: if (error)
255: goto out;
1.107 mycroft 256: }
257: } else {
258: /*
259: * Don't allow a non-blocking non-dialout open if the
260: * device is already open for dialout.
261: */
1.138 enami 262: if (ISSET(tp->t_state, TS_DIALOUT)) {
1.147 pk 263: error = EBUSY;
264: goto out;
1.107 mycroft 265: }
266: }
267: }
268:
1.147 pk 269: out:
270: TTY_UNLOCK(tp);
1.107 mycroft 271: splx(s);
1.147 pk 272: return (error);
1.107 mycroft 273: }
274:
1.49 cgd 275: /*
276: * Initial open of tty, or (re)entry to standard tty line discipline.
277: */
278: int
1.126 lukem 279: ttylopen(dev_t device, struct tty *tp)
1.49 cgd 280: {
1.126 lukem 281: int s;
1.49 cgd 282:
283: s = spltty();
1.147 pk 284: TTY_LOCK(tp);
1.49 cgd 285: tp->t_dev = device;
286: if (!ISSET(tp->t_state, TS_ISOPEN)) {
287: SET(tp->t_state, TS_ISOPEN);
1.109 perry 288: memset(&tp->t_winsize, 0, sizeof(tp->t_winsize));
1.66 christos 289: #ifdef COMPAT_OLDTTY
1.50 mycroft 290: tp->t_flags = 0;
291: #endif
1.49 cgd 292: }
1.147 pk 293: TTY_UNLOCK(tp);
1.49 cgd 294: splx(s);
295: return (0);
296: }
297:
298: /*
299: * Handle close() on a tty line: flush and set to initial state,
300: * bumping generation number so that pending read/write calls
301: * can detect recycling of the tty.
302: */
303: int
1.126 lukem 304: ttyclose(struct tty *tp)
1.49 cgd 305: {
306: extern struct tty *constty; /* Temporary virtual console. */
1.147 pk 307: int s;
308:
309: s = spltty();
310: TTY_LOCK(tp);
1.49 cgd 311:
312: if (constty == tp)
313: constty = NULL;
314:
315: ttyflush(tp, FREAD | FWRITE);
316:
317: tp->t_gen++;
318: tp->t_pgrp = NULL;
1.173.2.3 yamt 319: tp->t_state = 0;
320:
321: TTY_UNLOCK(tp);
322: splx(s);
323:
1.173.2.4! yamt 324: mutex_enter(&proclist_lock);
1.173.2.3 yamt 325: s = spltty();
326: TTY_LOCK(tp);
1.136 christos 327: if (tp->t_session != NULL) {
328: SESSRELE(tp->t_session);
329: tp->t_session = NULL;
330: }
1.147 pk 331: TTY_UNLOCK(tp);
332: splx(s);
1.173.2.4! yamt 333: mutex_exit(&proclist_lock);
1.173.2.3 yamt 334:
1.49 cgd 335: return (0);
336: }
337:
338: #define FLUSHQ(q) { \
339: if ((q)->c_cc) \
340: ndflush(q, (q)->c_cc); \
341: }
342:
1.88 kleink 343: /*
344: * This macro is used in canonical mode input processing, where a read
345: * request shall not return unless a 'line delimiter' ('\n') or 'break'
346: * (EOF, EOL, EOL2) character (or a signal) has been received. As EOL2
347: * is an extension to the POSIX.1 defined set of special characters,
348: * recognize it only if IEXTEN is set in the set of local flags.
349: */
1.85 kleink 350: #define TTBREAKC(c, lflg) \
1.87 cgd 351: ((c) == '\n' || (((c) == cc[VEOF] || (c) == cc[VEOL] || \
1.85 kleink 352: ((c) == cc[VEOL2] && ISSET(lflg, IEXTEN))) && (c) != _POSIX_VDISABLE))
1.49 cgd 353:
354:
1.147 pk 355:
1.49 cgd 356: /*
1.147 pk 357: * ttyinput() helper.
358: * Call at spltty() and with the tty slock held.
1.49 cgd 359: */
1.147 pk 360: static int
361: ttyinput_wlock(int c, struct tty *tp)
1.49 cgd 362: {
1.142 gehenna 363: const struct cdevsw *cdev;
1.126 lukem 364: int iflag, lflag, i, error;
365: u_char *cc;
1.78 christos 366:
367: /*
1.49 cgd 368: * If input is pending take it first.
369: */
370: lflag = tp->t_lflag;
371: if (ISSET(lflag, PENDIN))
372: ttypend(tp);
373: /*
374: * Gather stats.
375: */
376: if (ISSET(lflag, ICANON)) {
377: ++tk_cancc;
378: ++tp->t_cancc;
379: } else {
380: ++tk_rawcc;
381: ++tp->t_rawcc;
382: }
383: ++tk_nin;
384:
385: cc = tp->t_cc;
1.94 kleink 386:
387: /*
388: * Handle exceptional conditions (break, parity, framing).
389: */
1.49 cgd 390: iflag = tp->t_iflag;
1.65 christos 391: if ((error = (ISSET(c, TTY_ERRORMASK))) != 0) {
1.49 cgd 392: CLR(c, TTY_ERRORMASK);
1.94 kleink 393: if (ISSET(error, TTY_FE) && c == 0) { /* Break. */
1.49 cgd 394: if (ISSET(iflag, IGNBRK))
1.94 kleink 395: return (0);
396: else if (ISSET(iflag, BRKINT)) {
397: ttyflush(tp, FREAD | FWRITE);
1.173.2.3 yamt 398: mutex_enter(&proclist_mutex);
1.94 kleink 399: pgsignal(tp->t_pgrp, SIGINT, 1);
1.173.2.3 yamt 400: mutex_exit(&proclist_mutex);
1.94 kleink 401: return (0);
1.138 enami 402: } else if (ISSET(iflag, PARMRK))
1.49 cgd 403: goto parmrk;
1.138 enami 404: } else if ((ISSET(error, TTY_PE) && ISSET(iflag, INPCK)) ||
1.94 kleink 405: ISSET(error, TTY_FE)) {
1.49 cgd 406: if (ISSET(iflag, IGNPAR))
1.94 kleink 407: return (0);
1.49 cgd 408: else if (ISSET(iflag, PARMRK)) {
1.126 lukem 409: parmrk: (void)putc(0377 | TTY_QUOTE, &tp->t_rawq);
1.94 kleink 410: (void)putc(0 | TTY_QUOTE, &tp->t_rawq);
411: (void)putc(c | TTY_QUOTE, &tp->t_rawq);
412: return (0);
1.138 enami 413: } else
1.49 cgd 414: c = 0;
415: }
1.138 enami 416: } else if (c == 0377 &&
1.94 kleink 417: ISSET(iflag, ISTRIP|IGNPAR|INPCK|PARMRK) == (INPCK|PARMRK)) {
418: /* "Escape" a valid character of '\377'. */
419: (void)putc(0377 | TTY_QUOTE, &tp->t_rawq);
420: (void)putc(0377 | TTY_QUOTE, &tp->t_rawq);
421: goto endcase;
422: }
423:
1.49 cgd 424: /*
425: * In tandem mode, check high water mark.
426: */
427: if (ISSET(iflag, IXOFF) || ISSET(tp->t_cflag, CHWFLOW))
428: ttyblock(tp);
429: if (!ISSET(tp->t_state, TS_TYPEN) && ISSET(iflag, ISTRIP))
430: CLR(c, 0x80);
431: if (!ISSET(lflag, EXTPROC)) {
432: /*
433: * Check for literal nexting very first
434: */
435: if (ISSET(tp->t_state, TS_LNCH)) {
436: SET(c, TTY_QUOTE);
437: CLR(tp->t_state, TS_LNCH);
438: }
439: /*
440: * Scan for special characters. This code
441: * is really just a big case statement with
442: * non-constant cases. The bottom of the
443: * case statement is labeled ``endcase'', so goto
444: * it after a case match, or similar.
445: */
446:
447: /*
448: * Control chars which aren't controlled
449: * by ICANON, ISIG, or IXON.
450: */
451: if (ISSET(lflag, IEXTEN)) {
452: if (CCEQ(cc[VLNEXT], c)) {
453: if (ISSET(lflag, ECHO)) {
454: if (ISSET(lflag, ECHOE)) {
455: (void)ttyoutput('^', tp);
456: (void)ttyoutput('\b', tp);
457: } else
458: ttyecho(c, tp);
459: }
460: SET(tp->t_state, TS_LNCH);
461: goto endcase;
462: }
463: if (CCEQ(cc[VDISCARD], c)) {
464: if (ISSET(lflag, FLUSHO))
465: CLR(tp->t_lflag, FLUSHO);
466: else {
467: ttyflush(tp, FWRITE);
468: ttyecho(c, tp);
469: if (tp->t_rawq.c_cc + tp->t_canq.c_cc)
470: ttyretype(tp);
471: SET(tp->t_lflag, FLUSHO);
472: }
473: goto startoutput;
474: }
475: }
476: /*
477: * Signals.
478: */
479: if (ISSET(lflag, ISIG)) {
480: if (CCEQ(cc[VINTR], c) || CCEQ(cc[VQUIT], c)) {
481: if (!ISSET(lflag, NOFLSH))
482: ttyflush(tp, FREAD | FWRITE);
483: ttyecho(c, tp);
1.173.2.3 yamt 484: mutex_enter(&proclist_mutex);
1.49 cgd 485: pgsignal(tp->t_pgrp,
486: CCEQ(cc[VINTR], c) ? SIGINT : SIGQUIT, 1);
1.173.2.3 yamt 487: mutex_exit(&proclist_mutex);
1.49 cgd 488: goto endcase;
489: }
490: if (CCEQ(cc[VSUSP], c)) {
491: if (!ISSET(lflag, NOFLSH))
492: ttyflush(tp, FREAD);
493: ttyecho(c, tp);
1.173.2.3 yamt 494: mutex_enter(&proclist_mutex);
1.49 cgd 495: pgsignal(tp->t_pgrp, SIGTSTP, 1);
1.173.2.3 yamt 496: mutex_exit(&proclist_mutex);
1.49 cgd 497: goto endcase;
498: }
499: }
500: /*
501: * Handle start/stop characters.
502: */
503: if (ISSET(iflag, IXON)) {
504: if (CCEQ(cc[VSTOP], c)) {
505: if (!ISSET(tp->t_state, TS_TTSTOP)) {
506: SET(tp->t_state, TS_TTSTOP);
1.142 gehenna 507: cdev = cdevsw_lookup(tp->t_dev);
508: if (cdev != NULL)
509: (*cdev->d_stop)(tp, 0);
1.49 cgd 510: return (0);
511: }
512: if (!CCEQ(cc[VSTART], c))
513: return (0);
514: /*
515: * if VSTART == VSTOP then toggle
516: */
517: goto endcase;
518: }
519: if (CCEQ(cc[VSTART], c))
520: goto restartoutput;
521: }
522: /*
523: * IGNCR, ICRNL, & INLCR
524: */
525: if (c == '\r') {
526: if (ISSET(iflag, IGNCR))
527: goto endcase;
528: else if (ISSET(iflag, ICRNL))
529: c = '\n';
530: } else if (c == '\n' && ISSET(iflag, INLCR))
531: c = '\r';
532: }
1.147 pk 533: if (!ISSET(lflag, EXTPROC) && ISSET(lflag, ICANON)) {
1.49 cgd 534: /*
535: * From here on down canonical mode character
536: * processing takes place.
537: */
538: /*
539: * erase (^H / ^?)
540: */
541: if (CCEQ(cc[VERASE], c)) {
542: if (tp->t_rawq.c_cc)
543: ttyrub(unputc(&tp->t_rawq), tp);
544: goto endcase;
545: }
546: /*
547: * kill (^U)
548: */
549: if (CCEQ(cc[VKILL], c)) {
550: if (ISSET(lflag, ECHOKE) &&
551: tp->t_rawq.c_cc == tp->t_rocount &&
552: !ISSET(lflag, ECHOPRT))
553: while (tp->t_rawq.c_cc)
554: ttyrub(unputc(&tp->t_rawq), tp);
555: else {
556: ttyecho(c, tp);
557: if (ISSET(lflag, ECHOK) ||
558: ISSET(lflag, ECHOKE))
559: ttyecho('\n', tp);
560: FLUSHQ(&tp->t_rawq);
561: tp->t_rocount = 0;
562: }
563: CLR(tp->t_state, TS_LOCAL);
564: goto endcase;
565: }
566: /*
1.81 kleink 567: * Extensions to the POSIX.1 GTI set of functions.
1.49 cgd 568: */
1.81 kleink 569: if (ISSET(lflag, IEXTEN)) {
1.49 cgd 570: /*
1.81 kleink 571: * word erase (^W)
1.49 cgd 572: */
1.81 kleink 573: if (CCEQ(cc[VWERASE], c)) {
574: int alt = ISSET(lflag, ALTWERASE);
575: int ctype;
576:
577: /*
578: * erase whitespace
579: */
580: while ((c = unputc(&tp->t_rawq)) == ' ' ||
1.138 enami 581: c == '\t')
1.81 kleink 582: ttyrub(c, tp);
583: if (c == -1)
584: goto endcase;
585: /*
586: * erase last char of word and remember the
587: * next chars type (for ALTWERASE)
588: */
1.49 cgd 589: ttyrub(c, tp);
1.81 kleink 590: c = unputc(&tp->t_rawq);
591: if (c == -1)
592: goto endcase;
593: if (c == ' ' || c == '\t') {
594: (void)putc(c, &tp->t_rawq);
595: goto endcase;
596: }
597: ctype = ISALPHA(c);
598: /*
599: * erase rest of word
600: */
601: do {
602: ttyrub(c, tp);
603: c = unputc(&tp->t_rawq);
604: if (c == -1)
605: goto endcase;
606: } while (c != ' ' && c != '\t' &&
1.138 enami 607: (alt == 0 || ISALPHA(c) == ctype));
1.81 kleink 608: (void)putc(c, &tp->t_rawq);
1.49 cgd 609: goto endcase;
1.81 kleink 610: }
1.49 cgd 611: /*
1.81 kleink 612: * reprint line (^R)
1.49 cgd 613: */
1.81 kleink 614: if (CCEQ(cc[VREPRINT], c)) {
615: ttyretype(tp);
1.49 cgd 616: goto endcase;
617: }
618: /*
1.81 kleink 619: * ^T - kernel info and generate SIGINFO
1.49 cgd 620: */
1.81 kleink 621: if (CCEQ(cc[VSTATUS], c)) {
1.135 itohy 622: if (!ISSET(lflag, NOKERNINFO))
1.173.2.1 yamt 623: ttyinfo(tp, 1);
1.173.2.3 yamt 624: if (ISSET(lflag, ISIG)) {
625: mutex_enter(&proclist_mutex);
1.81 kleink 626: pgsignal(tp->t_pgrp, SIGINFO, 1);
1.173.2.3 yamt 627: mutex_exit(&proclist_mutex);
628: }
1.81 kleink 629: goto endcase;
630: }
1.49 cgd 631: }
632: }
633: /*
634: * Check for input buffer overflow
635: */
636: if (tp->t_rawq.c_cc + tp->t_canq.c_cc >= TTYHOG) {
637: if (ISSET(iflag, IMAXBEL)) {
638: if (tp->t_outq.c_cc < tp->t_hiwat)
639: (void)ttyoutput(CTRL('g'), tp);
640: } else
641: ttyflush(tp, FREAD | FWRITE);
642: goto endcase;
643: }
644: /*
645: * Put data char in q for user and
646: * wakeup on seeing a line delimiter.
647: */
648: if (putc(c, &tp->t_rawq) >= 0) {
649: if (!ISSET(lflag, ICANON)) {
650: ttwakeup(tp);
651: ttyecho(c, tp);
652: goto endcase;
653: }
1.85 kleink 654: if (TTBREAKC(c, lflag)) {
1.49 cgd 655: tp->t_rocount = 0;
656: catq(&tp->t_rawq, &tp->t_canq);
657: ttwakeup(tp);
658: } else if (tp->t_rocount++ == 0)
659: tp->t_rocol = tp->t_column;
660: if (ISSET(tp->t_state, TS_ERASE)) {
661: /*
662: * end of prterase \.../
663: */
664: CLR(tp->t_state, TS_ERASE);
665: (void)ttyoutput('/', tp);
666: }
667: i = tp->t_column;
668: ttyecho(c, tp);
669: if (CCEQ(cc[VEOF], c) && ISSET(lflag, ECHO)) {
670: /*
671: * Place the cursor over the '^' of the ^D.
672: */
673: i = min(2, tp->t_column - i);
674: while (i > 0) {
675: (void)ttyoutput('\b', tp);
676: i--;
677: }
678: }
679: }
1.126 lukem 680: endcase:
1.49 cgd 681: /*
682: * IXANY means allow any character to restart output.
683: */
684: if (ISSET(tp->t_state, TS_TTSTOP) &&
1.147 pk 685: !ISSET(iflag, IXANY) && cc[VSTART] != cc[VSTOP]) {
1.49 cgd 686: return (0);
1.147 pk 687: }
1.126 lukem 688: restartoutput:
1.49 cgd 689: CLR(tp->t_lflag, FLUSHO);
690: CLR(tp->t_state, TS_TTSTOP);
1.126 lukem 691: startoutput:
1.49 cgd 692: return (ttstart(tp));
693: }
694:
695: /*
1.147 pk 696: * Process input of a single character received on a tty.
697: * Must be called at spltty().
698: *
699: * XXX - this is a hack, all drivers must changed to acquire the
700: * lock before calling linesw->l_rint()
701: */
702: int
703: ttyinput(int c, struct tty *tp)
704: {
705: int error;
1.164 dbj 706: int s;
1.147 pk 707:
708: /*
709: * Unless the receiver is enabled, drop incoming data.
710: */
711: if (!ISSET(tp->t_cflag, CREAD))
712: return (0);
713:
1.164 dbj 714: s = spltty();
1.147 pk 715: TTY_LOCK(tp);
716: error = ttyinput_wlock(c, tp);
717: TTY_UNLOCK(tp);
1.164 dbj 718: splx(s);
1.147 pk 719: return (error);
720: }
721:
722: /*
1.49 cgd 723: * Output a single character on a tty, doing output processing
724: * as needed (expanding tabs, newline processing, etc.).
725: * Returns < 0 if succeeds, otherwise returns char to resend.
726: * Must be recursive.
1.147 pk 727: * Call with tty slock held.
1.49 cgd 728: */
729: int
1.126 lukem 730: ttyoutput(int c, struct tty *tp)
1.49 cgd 731: {
1.126 lukem 732: long oflag;
733: int col, notout, s;
1.49 cgd 734:
735: oflag = tp->t_oflag;
736: if (!ISSET(oflag, OPOST)) {
737: tk_nout++;
738: tp->t_outcc++;
1.99 mycroft 739: if (!ISSET(tp->t_lflag, FLUSHO) && putc(c, &tp->t_outq))
740: return (c);
1.49 cgd 741: return (-1);
742: }
743: /*
1.103 kleink 744: * Do tab expansion if OXTABS is set. Special case if we do external
1.49 cgd 745: * processing, we don't do the tab expansion because we'll probably
746: * get it wrong. If tab expansion needs to be done, let it happen
747: * externally.
748: */
749: CLR(c, ~TTY_CHARMASK);
750: if (c == '\t' &&
751: ISSET(oflag, OXTABS) && !ISSET(tp->t_lflag, EXTPROC)) {
752: c = 8 - (tp->t_column & 7);
753: if (ISSET(tp->t_lflag, FLUSHO)) {
754: notout = 0;
755: } else {
756: s = spltty(); /* Don't interrupt tabs. */
757: notout = b_to_q(" ", c, &tp->t_outq);
758: c -= notout;
759: tk_nout += c;
760: tp->t_outcc += c;
761: splx(s);
762: }
763: tp->t_column += c;
764: return (notout ? '\t' : -1);
765: }
766: if (c == CEOT && ISSET(oflag, ONOEOT))
767: return (-1);
768:
769: /*
770: * Newline translation: if ONLCR is set,
771: * translate newline into "\r\n".
772: */
773: if (c == '\n' && ISSET(tp->t_oflag, ONLCR)) {
774: tk_nout++;
775: tp->t_outcc++;
1.99 mycroft 776: if (!ISSET(tp->t_lflag, FLUSHO) && putc('\r', &tp->t_outq))
1.49 cgd 777: return (c);
778: }
1.103 kleink 779: /* If OCRNL is set, translate "\r" into "\n". */
1.79 kleink 780: else if (c == '\r' && ISSET(tp->t_oflag, OCRNL))
781: c = '\n';
1.103 kleink 782: /* If ONOCR is set, don't transmit CRs when on column 0. */
783: else if (c == '\r' && ISSET(tp->t_oflag, ONOCR) && tp->t_column == 0)
784: return (-1);
1.79 kleink 785:
1.49 cgd 786: tk_nout++;
787: tp->t_outcc++;
788: if (!ISSET(tp->t_lflag, FLUSHO) && putc(c, &tp->t_outq))
789: return (c);
790:
791: col = tp->t_column;
792: switch (CCLASS(c)) {
793: case BACKSPACE:
794: if (col > 0)
795: --col;
796: break;
797: case CONTROL:
798: break;
799: case NEWLINE:
1.103 kleink 800: if (ISSET(tp->t_oflag, ONLCR | ONLRET))
1.79 kleink 801: col = 0;
802: break;
1.49 cgd 803: case RETURN:
804: col = 0;
805: break;
806: case ORDINARY:
807: ++col;
808: break;
809: case TAB:
810: col = (col + 8) & ~7;
811: break;
812: }
813: tp->t_column = col;
814: return (-1);
815: }
816:
817: /*
818: * Ioctls for all tty devices. Called after line-discipline specific ioctl
819: * has been called to do discipline-specific functions and/or reject any
820: * of these ioctl commands.
821: */
822: /* ARGSUSED */
823: int
1.173.2.4! yamt 824: ttioctl(struct tty *tp, u_long cmd, void *data, int flag, struct lwp *l)
1.49 cgd 825: {
826: extern struct tty *constty; /* Temporary virtual console. */
1.173.2.2 yamt 827: struct proc *p = l ? l->l_proc : NULL;
1.126 lukem 828: struct linesw *lp;
829: int s, error;
1.151 christos 830: struct nameidata nd;
1.49 cgd 831:
832: /* If the ioctl involves modification, hang if in the background. */
833: switch (cmd) {
834: case TIOCFLUSH:
1.92 kleink 835: case TIOCDRAIN:
1.95 kleink 836: case TIOCSBRK:
837: case TIOCCBRK:
838: case TIOCSTART:
1.49 cgd 839: case TIOCSETA:
840: case TIOCSETD:
1.121 eeh 841: case TIOCSLINED:
1.49 cgd 842: case TIOCSETAF:
843: case TIOCSETAW:
844: #ifdef notdef
845: case TIOCSPGRP:
1.158 jdolecek 846: case FIOSETOWN:
1.49 cgd 847: #endif
848: case TIOCSTAT:
849: case TIOCSTI:
850: case TIOCSWINSZ:
1.66 christos 851: #ifdef COMPAT_OLDTTY
1.49 cgd 852: case TIOCLBIC:
853: case TIOCLBIS:
854: case TIOCLSET:
855: case TIOCSETC:
856: case OTIOCSETD:
857: case TIOCSETN:
858: case TIOCSETP:
859: case TIOCSLTC:
860: #endif
1.173.2.3 yamt 861: /* XXXSMP */
1.49 cgd 862: while (isbackground(curproc, tp) &&
1.173.2.3 yamt 863: p->p_pgrp->pg_jobc && (p->p_sflag & PS_PPWAIT) == 0 &&
864: !sigismasked(l, SIGTTOU)) {
865: mutex_enter(&proclist_mutex);
1.49 cgd 866: pgsignal(p->p_pgrp, SIGTTOU, 1);
1.173.2.3 yamt 867: mutex_exit(&proclist_mutex);
1.147 pk 868: s = spltty();
869: TTY_LOCK(tp);
870: error = ttysleep(tp, &lbolt,
871: TTOPRI | PCATCH | PNORELOCK, ttybg, 0);
872: splx(s);
873: if (error) {
1.49 cgd 874: return (error);
1.147 pk 875: }
1.49 cgd 876: }
877: break;
878: }
879:
880: switch (cmd) { /* Process the ioctl. */
881: case FIOASYNC: /* set/clear async i/o */
882: s = spltty();
1.147 pk 883: TTY_LOCK(tp);
1.49 cgd 884: if (*(int *)data)
885: SET(tp->t_state, TS_ASYNC);
886: else
887: CLR(tp->t_state, TS_ASYNC);
1.147 pk 888: TTY_UNLOCK(tp);
1.49 cgd 889: splx(s);
890: break;
891: case FIONBIO: /* set/clear non-blocking i/o */
892: break; /* XXX: delete. */
893: case FIONREAD: /* get # bytes to read */
1.147 pk 894: s = spltty();
895: TTY_LOCK(tp);
1.49 cgd 896: *(int *)data = ttnread(tp);
1.147 pk 897: TTY_UNLOCK(tp);
898: splx(s);
1.49 cgd 899: break;
1.170 wrstuden 900: case FIONWRITE: /* get # bytes to written & unsent */
901: s = spltty();
902: TTY_LOCK(tp);
903: *(int *)data = tp->t_outq.c_cc;
904: TTY_UNLOCK(tp);
905: splx(s);
906: break;
907: case FIONSPACE: /* get # bytes to written & unsent */
908: s = spltty();
909: TTY_LOCK(tp);
910: *(int *)data = tp->t_outq.c_cn - tp->t_outq.c_cc;
911: TTY_UNLOCK(tp);
912: splx(s);
913: break;
1.49 cgd 914: case TIOCEXCL: /* set exclusive use of tty */
915: s = spltty();
1.147 pk 916: TTY_LOCK(tp);
1.49 cgd 917: SET(tp->t_state, TS_XCLUDE);
918: splx(s);
1.147 pk 919: TTY_UNLOCK(tp);
1.49 cgd 920: break;
921: case TIOCFLUSH: { /* flush buffers */
1.118 augustss 922: int flags = *(int *)data;
1.49 cgd 923:
924: if (flags == 0)
925: flags = FREAD | FWRITE;
926: else
927: flags &= FREAD | FWRITE;
1.147 pk 928: s = spltty();
929: TTY_LOCK(tp);
1.49 cgd 930: ttyflush(tp, flags);
1.147 pk 931: TTY_UNLOCK(tp);
932: splx(s);
1.49 cgd 933: break;
934: }
935: case TIOCCONS: /* become virtual console */
936: if (*(int *)data) {
937: if (constty && constty != tp &&
938: ISSET(constty->t_state, TS_CARR_ON | TS_ISOPEN) ==
939: (TS_CARR_ON | TS_ISOPEN))
1.151 christos 940: return EBUSY;
941:
942: NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE,
1.173.2.1 yamt 943: "/dev/console", l);
1.151 christos 944: if ((error = namei(&nd)) != 0)
945: return error;
1.173.2.2 yamt 946: error = VOP_ACCESS(nd.ni_vp, VREAD, l->l_cred, l);
1.151 christos 947: vput(nd.ni_vp);
948: if (error)
949: return error;
950:
1.49 cgd 951: constty = tp;
952: } else if (tp == constty)
953: constty = NULL;
954: break;
955: case TIOCDRAIN: /* wait till output drained */
1.65 christos 956: if ((error = ttywait(tp)) != 0)
1.49 cgd 957: return (error);
958: break;
959: case TIOCGETA: { /* get termios struct */
960: struct termios *t = (struct termios *)data;
961:
1.109 perry 962: memcpy(t, &tp->t_termios, sizeof(struct termios));
1.49 cgd 963: break;
964: }
1.173.2.1 yamt 965: case TIOCGETD: /* get line discipline (old) */
1.127 enami 966: *(int *)data = tp->t_linesw->l_no;
1.121 eeh 967: break;
1.173.2.1 yamt 968: case TIOCGLINED: /* get line discipline (new) */
1.138 enami 969: (void)strncpy((char *)data, tp->t_linesw->l_name,
1.131 christos 970: TTLINEDNAMELEN - 1);
1.49 cgd 971: break;
972: case TIOCGWINSZ: /* get window size */
973: *(struct winsize *)data = tp->t_winsize;
974: break;
1.158 jdolecek 975: case FIOGETOWN:
1.173.2.1 yamt 976: if (tp->t_session != NULL && !isctty(p, tp))
1.158 jdolecek 977: return (ENOTTY);
978: *(int *)data = tp->t_pgrp ? -tp->t_pgrp->pg_id : 0;
979: break;
1.49 cgd 980: case TIOCGPGRP: /* get pgrp of tty */
981: if (!isctty(p, tp))
982: return (ENOTTY);
1.150 dsl 983: *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PGID;
1.104 thorpej 984: break;
985: case TIOCGSID: /* get sid of tty */
986: if (!isctty(p, tp))
987: return (ENOTTY);
988: *(int *)data = tp->t_session->s_sid;
1.49 cgd 989: break;
990: #ifdef TIOCHPCL
991: case TIOCHPCL: /* hang up on last close */
992: s = spltty();
1.147 pk 993: TTY_LOCK(tp);
1.49 cgd 994: SET(tp->t_cflag, HUPCL);
1.147 pk 995: TTY_UNLOCK(tp);
1.49 cgd 996: splx(s);
997: break;
998: #endif
999: case TIOCNXCL: /* reset exclusive use of tty */
1000: s = spltty();
1.147 pk 1001: TTY_LOCK(tp);
1.49 cgd 1002: CLR(tp->t_state, TS_XCLUDE);
1.147 pk 1003: TTY_UNLOCK(tp);
1.49 cgd 1004: splx(s);
1005: break;
1006: case TIOCOUTQ: /* output queue size */
1007: *(int *)data = tp->t_outq.c_cc;
1008: break;
1009: case TIOCSETA: /* set termios struct */
1010: case TIOCSETAW: /* drain output, set */
1011: case TIOCSETAF: { /* drn out, fls in, set */
1.118 augustss 1012: struct termios *t = (struct termios *)data;
1.49 cgd 1013:
1014: if (cmd == TIOCSETAW || cmd == TIOCSETAF) {
1.147 pk 1015: if ((error = ttywait(tp)) != 0)
1016: return (error);
1017:
1018: if (cmd == TIOCSETAF) {
1019: s = spltty();
1020: TTY_LOCK(tp);
1021: ttyflush(tp, FREAD);
1022: TTY_UNLOCK(tp);
1.49 cgd 1023: splx(s);
1024: }
1025: }
1.147 pk 1026:
1027: s = spltty();
1.148 pk 1028: /*
1029: * XXXSMP - some drivers call back on us from t_param(), so
1030: * don't take the tty spin lock here.
1031: * require t_param() to unlock upon callback?
1032: */
1033: /* wanted here: TTY_LOCK(tp); */
1.49 cgd 1034: if (!ISSET(t->c_cflag, CIGNORE)) {
1035: /*
1036: * Set device hardware.
1037: */
1038: if (tp->t_param && (error = (*tp->t_param)(tp, t))) {
1.148 pk 1039: /* wanted here: TTY_UNLOCK(tp); */
1.49 cgd 1040: splx(s);
1041: return (error);
1042: } else {
1043: tp->t_cflag = t->c_cflag;
1044: tp->t_ispeed = t->c_ispeed;
1045: tp->t_ospeed = t->c_ospeed;
1046: if (t->c_ospeed == 0 && tp->t_session &&
1.173.2.3 yamt 1047: tp->t_session->s_leader) {
1048: mutex_enter(&proclist_mutex);
1.49 cgd 1049: psignal(tp->t_session->s_leader,
1050: SIGHUP);
1.173.2.3 yamt 1051: mutex_exit(&proclist_mutex);
1052: }
1.49 cgd 1053: }
1054: ttsetwater(tp);
1055: }
1.148 pk 1056:
1057: /* delayed lock acquiring */TTY_LOCK(tp);
1.49 cgd 1058: if (cmd != TIOCSETAF) {
1059: if (ISSET(t->c_lflag, ICANON) !=
1.110 thorpej 1060: ISSET(tp->t_lflag, ICANON)) {
1.49 cgd 1061: if (ISSET(t->c_lflag, ICANON)) {
1062: SET(tp->t_lflag, PENDIN);
1063: ttwakeup(tp);
1064: } else {
1065: struct clist tq;
1066:
1067: catq(&tp->t_rawq, &tp->t_canq);
1068: tq = tp->t_rawq;
1069: tp->t_rawq = tp->t_canq;
1070: tp->t_canq = tq;
1071: CLR(tp->t_lflag, PENDIN);
1072: }
1.110 thorpej 1073: }
1.49 cgd 1074: }
1075: tp->t_iflag = t->c_iflag;
1076: tp->t_oflag = t->c_oflag;
1077: /*
1078: * Make the EXTPROC bit read only.
1079: */
1080: if (ISSET(tp->t_lflag, EXTPROC))
1081: SET(t->c_lflag, EXTPROC);
1082: else
1083: CLR(t->c_lflag, EXTPROC);
1084: tp->t_lflag = t->c_lflag | ISSET(tp->t_lflag, PENDIN);
1.109 perry 1085: memcpy(tp->t_cc, t->c_cc, sizeof(t->c_cc));
1.147 pk 1086: TTY_UNLOCK(tp);
1.49 cgd 1087: splx(s);
1088: break;
1089: }
1.173.2.1 yamt 1090: case TIOCSETD: /* set line discipline (old) */
1091: lp = ttyldisc_lookup_bynum(*(int *)data);
1.124 enami 1092: goto setldisc;
1.173.2.1 yamt 1093:
1094: case TIOCSLINED: { /* set line discipline (new) */
1.121 eeh 1095: char *name = (char *)data;
1.124 enami 1096: dev_t device;
1.121 eeh 1097:
1098: /* Null terminate to prevent buffer overflow */
1.138 enami 1099: name[TTLINEDNAMELEN - 1] = '\0';
1.121 eeh 1100: lp = ttyldisc_lookup(name);
1.126 lukem 1101: setldisc:
1.124 enami 1102: if (lp == NULL)
1.121 eeh 1103: return (ENXIO);
1104:
1105: if (lp != tp->t_linesw) {
1.124 enami 1106: device = tp->t_dev;
1.49 cgd 1107: s = spltty();
1.124 enami 1108: (*tp->t_linesw->l_close)(tp, flag);
1.121 eeh 1109: error = (*lp->l_open)(device, tp);
1.49 cgd 1110: if (error) {
1.121 eeh 1111: (void)(*tp->t_linesw->l_open)(device, tp);
1.49 cgd 1112: splx(s);
1.173.2.1 yamt 1113: ttyldisc_release(lp);
1.49 cgd 1114: return (error);
1115: }
1.173.2.1 yamt 1116: ttyldisc_release(tp->t_linesw);
1.121 eeh 1117: tp->t_linesw = lp;
1.49 cgd 1118: splx(s);
1.173.2.1 yamt 1119: } else {
1120: /* Drop extra reference. */
1121: ttyldisc_release(lp);
1.49 cgd 1122: }
1123: break;
1124: }
1125: case TIOCSTART: /* start output, like ^Q */
1126: s = spltty();
1.147 pk 1127: TTY_LOCK(tp);
1.49 cgd 1128: if (ISSET(tp->t_state, TS_TTSTOP) ||
1129: ISSET(tp->t_lflag, FLUSHO)) {
1130: CLR(tp->t_lflag, FLUSHO);
1131: CLR(tp->t_state, TS_TTSTOP);
1132: ttstart(tp);
1133: }
1.147 pk 1134: TTY_UNLOCK(tp);
1.49 cgd 1135: splx(s);
1136: break;
1137: case TIOCSTI: /* simulate terminal input */
1.173.2.3 yamt 1138: if (kauth_authorize_generic(l->l_cred, KAUTH_GENERIC_ISSUSER,
1139: NULL) != 0) {
1140: if (!ISSET(flag, FREAD))
1141: return (EPERM);
1142: if (!isctty(p, tp))
1143: return (EACCES);
1144: }
1.121 eeh 1145: (*tp->t_linesw->l_rint)(*(u_char *)data, tp);
1.49 cgd 1146: break;
1147: case TIOCSTOP: /* stop output, like ^S */
1.142 gehenna 1148: {
1149: const struct cdevsw *cdev;
1.49 cgd 1150: s = spltty();
1.147 pk 1151: TTY_LOCK(tp);
1.49 cgd 1152: if (!ISSET(tp->t_state, TS_TTSTOP)) {
1153: SET(tp->t_state, TS_TTSTOP);
1.142 gehenna 1154: cdev = cdevsw_lookup(tp->t_dev);
1155: if (cdev != NULL)
1156: (*cdev->d_stop)(tp, 0);
1.49 cgd 1157: }
1.147 pk 1158: TTY_UNLOCK(tp);
1.49 cgd 1159: splx(s);
1160: break;
1.142 gehenna 1161: }
1.49 cgd 1162: case TIOCSCTTY: /* become controlling tty */
1.173.2.4! yamt 1163: mutex_enter(&proclist_lock);
1.173.2.3 yamt 1164:
1.49 cgd 1165: /* Session ctty vnode pointer set in vnode layer. */
1166: if (!SESS_LEADER(p) ||
1.65 christos 1167: ((p->p_session->s_ttyvp || tp->t_session) &&
1.173.2.3 yamt 1168: (tp->t_session != p->p_session))) {
1.173.2.4! yamt 1169: mutex_exit(&proclist_lock);
1.49 cgd 1170: return (EPERM);
1.173.2.3 yamt 1171: }
1.139 jdolecek 1172:
1.160 pk 1173: /*
1174: * `p_session' acquires a reference.
1175: * But note that if `t_session' is set at this point,
1176: * it must equal `p_session', in which case the session
1177: * already has the correct reference count.
1178: */
1179: if (tp->t_session == NULL)
1180: SESSHOLD(p->p_session);
1.139 jdolecek 1181:
1.49 cgd 1182: tp->t_session = p->p_session;
1183: tp->t_pgrp = p->p_pgrp;
1184: p->p_session->s_ttyp = tp;
1.173.2.3 yamt 1185: p->p_lflag |= PL_CONTROLT;
1.173.2.4! yamt 1186: mutex_exit(&proclist_lock);
1.49 cgd 1187: break;
1.158 jdolecek 1188: case FIOSETOWN: { /* set pgrp of tty */
1189: pid_t pgid = *(int *)data;
1190: struct pgrp *pgrp;
1191:
1.173.2.1 yamt 1192: if (tp->t_session != NULL && !isctty(p, tp))
1.158 jdolecek 1193: return (ENOTTY);
1194:
1.173.2.4! yamt 1195: mutex_enter(&proclist_lock);
1.173.2.3 yamt 1196:
1197: if (pgid < 0) {
1198: pgrp = pg_find(-pgid, PFIND_LOCKED | PFIND_UNLOCK_FAIL);
1199: if (pgrp == NULL)
1200: return (EINVAL);
1201: } else {
1202: struct proc *p1;
1203: p1 = p_find(pgid, PFIND_LOCKED | PFIND_UNLOCK_FAIL);
1.158 jdolecek 1204: if (!p1)
1205: return (ESRCH);
1206: pgrp = p1->p_pgrp;
1207: }
1208:
1.173.2.3 yamt 1209: if (pgrp->pg_session != p->p_session) {
1.173.2.4! yamt 1210: mutex_exit(&proclist_lock);
1.158 jdolecek 1211: return (EPERM);
1.173.2.3 yamt 1212: }
1.158 jdolecek 1213: tp->t_pgrp = pgrp;
1.173.2.4! yamt 1214: mutex_exit(&proclist_lock);
1.158 jdolecek 1215: break;
1216: }
1.49 cgd 1217: case TIOCSPGRP: { /* set pgrp of tty */
1.173.2.3 yamt 1218: struct pgrp *pgrp;
1.49 cgd 1219:
1220: if (!isctty(p, tp))
1221: return (ENOTTY);
1.173.2.4! yamt 1222: mutex_enter(&proclist_lock);
1.173.2.3 yamt 1223: pgrp = pg_find(*(int *)data, PFIND_LOCKED | PFIND_UNLOCK_FAIL);
1224: if (pgrp == NULL)
1.93 kleink 1225: return (EINVAL);
1.173.2.3 yamt 1226: if (pgrp->pg_session != p->p_session) {
1.173.2.4! yamt 1227: mutex_exit(&proclist_lock);
1.49 cgd 1228: return (EPERM);
1.173.2.3 yamt 1229: }
1.49 cgd 1230: tp->t_pgrp = pgrp;
1.173.2.4! yamt 1231: mutex_exit(&proclist_lock);
1.49 cgd 1232: break;
1233: }
1234: case TIOCSTAT: /* get load avg stats */
1.163 dbj 1235: s = spltty();
1.147 pk 1236: TTY_LOCK(tp);
1.173.2.1 yamt 1237: ttyinfo(tp, 0);
1.147 pk 1238: TTY_UNLOCK(tp);
1.163 dbj 1239: splx(s);
1.49 cgd 1240: break;
1241: case TIOCSWINSZ: /* set window size */
1.173.2.4! yamt 1242: if (memcmp((void *)&tp->t_winsize, data,
1.108 perry 1243: sizeof(struct winsize))) {
1.49 cgd 1244: tp->t_winsize = *(struct winsize *)data;
1.173.2.3 yamt 1245: mutex_enter(&proclist_mutex);
1.49 cgd 1246: pgsignal(tp->t_pgrp, SIGWINCH, 1);
1.173.2.3 yamt 1247: mutex_exit(&proclist_mutex);
1.49 cgd 1248: }
1249: break;
1250: default:
1.66 christos 1251: #ifdef COMPAT_OLDTTY
1.173.2.1 yamt 1252: return (ttcompat(tp, cmd, data, flag, l));
1.49 cgd 1253: #else
1.134 atatat 1254: return (EPASSTHROUGH);
1.49 cgd 1255: #endif
1256: }
1257: return (0);
1258: }
1259:
1260: int
1.173.2.1 yamt 1261: ttpoll(struct tty *tp, int events, struct lwp *l)
1.126 lukem 1262: {
1.128 scw 1263: int revents, s;
1.74 mycroft 1264:
1.126 lukem 1265: revents = 0;
1266: s = spltty();
1.147 pk 1267: TTY_LOCK(tp);
1.74 mycroft 1268: if (events & (POLLIN | POLLRDNORM))
1269: if (ttnread(tp) > 0)
1270: revents |= events & (POLLIN | POLLRDNORM);
1271:
1272: if (events & (POLLOUT | POLLWRNORM))
1273: if (tp->t_outq.c_cc <= tp->t_lowat)
1274: revents |= events & (POLLOUT | POLLWRNORM);
1275:
1276: if (events & POLLHUP)
1.83 mycroft 1277: if (!CONNECTED(tp))
1.74 mycroft 1278: revents |= POLLHUP;
1279:
1280: if (revents == 0) {
1281: if (events & (POLLIN | POLLHUP | POLLRDNORM))
1.173.2.1 yamt 1282: selrecord(l, &tp->t_rsel);
1.49 cgd 1283:
1.74 mycroft 1284: if (events & (POLLOUT | POLLWRNORM))
1.173.2.1 yamt 1285: selrecord(l, &tp->t_wsel);
1.74 mycroft 1286: }
1.49 cgd 1287:
1.147 pk 1288: TTY_UNLOCK(tp);
1.49 cgd 1289: splx(s);
1.74 mycroft 1290: return (revents);
1.49 cgd 1291: }
1292:
1.143 jdolecek 1293: static void
1294: filt_ttyrdetach(struct knote *kn)
1295: {
1296: struct tty *tp;
1297: int s;
1298:
1299: tp = kn->kn_hook;
1300: s = spltty();
1.173.2.1 yamt 1301: TTY_LOCK(tp);
1.144 christos 1302: SLIST_REMOVE(&tp->t_rsel.sel_klist, kn, knote, kn_selnext);
1.173.2.1 yamt 1303: TTY_UNLOCK(tp);
1.143 jdolecek 1304: splx(s);
1305: }
1306:
1307: static int
1308: filt_ttyread(struct knote *kn, long hint)
1309: {
1310: struct tty *tp;
1.147 pk 1311: int s;
1.143 jdolecek 1312:
1313: tp = kn->kn_hook;
1.147 pk 1314: s = spltty();
1.162 jdolecek 1315: if ((hint & NOTE_SUBMIT) == 0)
1316: TTY_LOCK(tp);
1.143 jdolecek 1317: kn->kn_data = ttnread(tp);
1.162 jdolecek 1318: if ((hint & NOTE_SUBMIT) == 0)
1319: TTY_UNLOCK(tp);
1.147 pk 1320: splx(s);
1.143 jdolecek 1321: return (kn->kn_data > 0);
1322: }
1323:
1324: static void
1325: filt_ttywdetach(struct knote *kn)
1326: {
1327: struct tty *tp;
1328: int s;
1329:
1330: tp = kn->kn_hook;
1331: s = spltty();
1.147 pk 1332: TTY_LOCK(tp);
1.144 christos 1333: SLIST_REMOVE(&tp->t_wsel.sel_klist, kn, knote, kn_selnext);
1.147 pk 1334: TTY_UNLOCK(tp);
1.143 jdolecek 1335: splx(s);
1336: }
1337:
1338: static int
1339: filt_ttywrite(struct knote *kn, long hint)
1340: {
1341: struct tty *tp;
1.147 pk 1342: int canwrite, s;
1.143 jdolecek 1343:
1344: tp = kn->kn_hook;
1.147 pk 1345: s = spltty();
1.162 jdolecek 1346: if ((hint & NOTE_SUBMIT) == 0)
1347: TTY_LOCK(tp);
1.143 jdolecek 1348: kn->kn_data = tp->t_outq.c_cn - tp->t_outq.c_cc;
1.147 pk 1349: canwrite = (tp->t_outq.c_cc <= tp->t_lowat) && CONNECTED(tp);
1.162 jdolecek 1350: if ((hint & NOTE_SUBMIT) == 0)
1351: TTY_UNLOCK(tp);
1.147 pk 1352: splx(s);
1353: return (canwrite);
1.143 jdolecek 1354: }
1355:
1356: static const struct filterops ttyread_filtops =
1357: { 1, NULL, filt_ttyrdetach, filt_ttyread };
1358: static const struct filterops ttywrite_filtops =
1359: { 1, NULL, filt_ttywdetach, filt_ttywrite };
1360:
1361: int
1362: ttykqfilter(dev_t dev, struct knote *kn)
1363: {
1364: struct tty *tp;
1365: struct klist *klist;
1366: int s;
1367: const struct cdevsw *cdev;
1368:
1.157 manu 1369: if (((cdev = cdevsw_lookup(dev)) == NULL) ||
1370: (cdev->d_tty == NULL) ||
1371: ((tp = (*cdev->d_tty)(dev)) == NULL))
1.143 jdolecek 1372: return (ENXIO);
1.157 manu 1373:
1.143 jdolecek 1374: switch (kn->kn_filter) {
1375: case EVFILT_READ:
1.144 christos 1376: klist = &tp->t_rsel.sel_klist;
1.143 jdolecek 1377: kn->kn_fop = &ttyread_filtops;
1378: break;
1379: case EVFILT_WRITE:
1.144 christos 1380: klist = &tp->t_wsel.sel_klist;
1.143 jdolecek 1381: kn->kn_fop = &ttywrite_filtops;
1382: break;
1383: default:
1.173.2.1 yamt 1384: return EINVAL;
1.143 jdolecek 1385: }
1386:
1387: kn->kn_hook = tp;
1388:
1389: s = spltty();
1.147 pk 1390: TTY_LOCK(tp);
1.143 jdolecek 1391: SLIST_INSERT_HEAD(klist, kn, kn_selnext);
1.147 pk 1392: TTY_UNLOCK(tp);
1.143 jdolecek 1393: splx(s);
1394:
1395: return (0);
1396: }
1397:
1.147 pk 1398: /*
1399: * Find the number of chars ready to be read from this tty.
1400: * Call at spltty() and with the tty slock held.
1401: */
1.49 cgd 1402: static int
1.126 lukem 1403: ttnread(struct tty *tp)
1.49 cgd 1404: {
1.126 lukem 1405: int nread;
1.49 cgd 1406:
1407: if (ISSET(tp->t_lflag, PENDIN))
1408: ttypend(tp);
1409: nread = tp->t_canq.c_cc;
1410: if (!ISSET(tp->t_lflag, ICANON)) {
1411: nread += tp->t_rawq.c_cc;
1412: if (nread < tp->t_cc[VMIN] && !tp->t_cc[VTIME])
1413: nread = 0;
1414: }
1415: return (nread);
1416: }
1417:
1418: /*
1419: * Wait for output to drain.
1420: */
1421: int
1.138 enami 1422: ttywait(struct tty *tp)
1.49 cgd 1423: {
1.126 lukem 1424: int error, s;
1.49 cgd 1425:
1426: error = 0;
1427: s = spltty();
1.147 pk 1428: TTY_LOCK(tp);
1.49 cgd 1429: while ((tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)) &&
1.83 mycroft 1430: CONNECTED(tp) && tp->t_oproc) {
1.49 cgd 1431: (*tp->t_oproc)(tp);
1432: SET(tp->t_state, TS_ASLEEP);
1.65 christos 1433: error = ttysleep(tp, &tp->t_outq, TTOPRI | PCATCH, ttyout, 0);
1434: if (error)
1.49 cgd 1435: break;
1436: }
1.147 pk 1437: TTY_UNLOCK(tp);
1.49 cgd 1438: splx(s);
1439: return (error);
1440: }
1441:
1442: /*
1443: * Flush if successfully wait.
1444: */
1445: int
1.126 lukem 1446: ttywflush(struct tty *tp)
1.49 cgd 1447: {
1.126 lukem 1448: int error;
1.147 pk 1449: int s;
1.49 cgd 1450:
1.147 pk 1451: if ((error = ttywait(tp)) == 0) {
1452: s = spltty();
1453: TTY_LOCK(tp);
1.49 cgd 1454: ttyflush(tp, FREAD);
1.147 pk 1455: TTY_UNLOCK(tp);
1456: splx(s);
1457: }
1.49 cgd 1458: return (error);
1459: }
1460:
1461: /*
1462: * Flush tty read and/or write queues, notifying anyone waiting.
1.147 pk 1463: * Call at spltty() and with the tty slock held.
1.49 cgd 1464: */
1465: void
1.126 lukem 1466: ttyflush(struct tty *tp, int rw)
1.49 cgd 1467: {
1.142 gehenna 1468: const struct cdevsw *cdev;
1.49 cgd 1469:
1470: if (rw & FREAD) {
1471: FLUSHQ(&tp->t_canq);
1472: FLUSHQ(&tp->t_rawq);
1473: tp->t_rocount = 0;
1474: tp->t_rocol = 0;
1475: CLR(tp->t_state, TS_LOCAL);
1476: ttwakeup(tp);
1477: }
1478: if (rw & FWRITE) {
1479: CLR(tp->t_state, TS_TTSTOP);
1.142 gehenna 1480: cdev = cdevsw_lookup(tp->t_dev);
1481: if (cdev != NULL)
1482: (*cdev->d_stop)(tp, rw);
1.49 cgd 1483: FLUSHQ(&tp->t_outq);
1.173.2.4! yamt 1484: wakeup((void *)&tp->t_outq);
1.162 jdolecek 1485: selnotify(&tp->t_wsel, NOTE_SUBMIT);
1.49 cgd 1486: }
1487: }
1488:
1489: /*
1490: * Copy in the default termios characters.
1491: */
1492: void
1.126 lukem 1493: ttychars(struct tty *tp)
1.49 cgd 1494: {
1495:
1.109 perry 1496: memcpy(tp->t_cc, ttydefchars, sizeof(ttydefchars));
1.49 cgd 1497: }
1498:
1499: /*
1500: * Send stop character on input overflow.
1.147 pk 1501: * Call at spltty() and with the tty slock held.
1.49 cgd 1502: */
1503: static void
1.126 lukem 1504: ttyblock(struct tty *tp)
1.49 cgd 1505: {
1.126 lukem 1506: int total;
1.49 cgd 1507:
1508: total = tp->t_rawq.c_cc + tp->t_canq.c_cc;
1509: if (tp->t_rawq.c_cc > TTYHOG) {
1510: ttyflush(tp, FREAD | FWRITE);
1511: CLR(tp->t_state, TS_TBLOCK);
1512: }
1513: /*
1514: * Block further input iff: current input > threshold
1515: * AND input is available to user program.
1516: */
1.101 drochner 1517: if (total >= TTYHOG / 2 &&
1518: !ISSET(tp->t_state, TS_TBLOCK) &&
1519: (!ISSET(tp->t_lflag, ICANON) || tp->t_canq.c_cc > 0)) {
1.60 mycroft 1520: if (ISSET(tp->t_iflag, IXOFF) &&
1521: tp->t_cc[VSTOP] != _POSIX_VDISABLE &&
1522: putc(tp->t_cc[VSTOP], &tp->t_outq) == 0) {
1.49 cgd 1523: SET(tp->t_state, TS_TBLOCK);
1524: ttstart(tp);
1525: }
1.59 mycroft 1526: /* Try to block remote output via hardware flow control. */
1.49 cgd 1527: if (ISSET(tp->t_cflag, CHWFLOW) && tp->t_hwiflow &&
1528: (*tp->t_hwiflow)(tp, 1) != 0)
1529: SET(tp->t_state, TS_TBLOCK);
1530: }
1531: }
1532:
1.147 pk 1533: /*
1534: * Delayed line discipline output
1535: */
1.49 cgd 1536: void
1.126 lukem 1537: ttrstrt(void *tp_arg)
1.49 cgd 1538: {
1.126 lukem 1539: struct tty *tp;
1540: int s;
1.49 cgd 1541:
1542: #ifdef DIAGNOSTIC
1543: if (tp_arg == NULL)
1544: panic("ttrstrt");
1545: #endif
1546: tp = tp_arg;
1547: s = spltty();
1.147 pk 1548: TTY_LOCK(tp);
1.49 cgd 1549:
1550: CLR(tp->t_state, TS_TIMEOUT);
1.147 pk 1551: ttstart(tp); /* XXX - Shouldn't this be tp->l_start(tp)? */
1.49 cgd 1552:
1.147 pk 1553: TTY_UNLOCK(tp);
1.49 cgd 1554: splx(s);
1555: }
1556:
1.147 pk 1557: /*
1558: * start a line discipline
1559: * Always call at spltty() and with tty slock held?
1560: */
1.49 cgd 1561: int
1.126 lukem 1562: ttstart(struct tty *tp)
1.49 cgd 1563: {
1564:
1565: if (tp->t_oproc != NULL) /* XXX: Kludge for pty. */
1566: (*tp->t_oproc)(tp);
1567: return (0);
1568: }
1569:
1570: /*
1571: * "close" a line discipline
1572: */
1573: int
1.126 lukem 1574: ttylclose(struct tty *tp, int flag)
1.49 cgd 1575: {
1.147 pk 1576: int s;
1.49 cgd 1577:
1.147 pk 1578: if (flag & FNONBLOCK) {
1579: s = spltty();
1580: TTY_LOCK(tp);
1.49 cgd 1581: ttyflush(tp, FREAD | FWRITE);
1.147 pk 1582: TTY_UNLOCK(tp);
1583: splx(s);
1584: } else
1.49 cgd 1585: ttywflush(tp);
1586: return (0);
1587: }
1588:
1589: /*
1590: * Handle modem control transition on a tty.
1591: * Flag indicates new state of carrier.
1592: * Returns 0 if the line should be turned off, otherwise 1.
1.147 pk 1593: *
1594: * Must be called at spltty().
1.164 dbj 1595: * XXX except that it is often isn't, which should be fixed.
1.49 cgd 1596: */
1597: int
1.126 lukem 1598: ttymodem(struct tty *tp, int flag)
1.49 cgd 1599: {
1.164 dbj 1600: int s;
1.49 cgd 1601:
1.164 dbj 1602: s = spltty();
1.147 pk 1603: TTY_LOCK(tp);
1.83 mycroft 1604: if (flag == 0) {
1.96 kleink 1605: if (ISSET(tp->t_state, TS_CARR_ON)) {
1606: /*
1607: * Lost carrier.
1608: */
1609: CLR(tp->t_state, TS_CARR_ON);
1610: if (ISSET(tp->t_state, TS_ISOPEN) && !CONNECTED(tp)) {
1.173.2.3 yamt 1611: if (tp->t_session && tp->t_session->s_leader) {
1612: mutex_enter(&proclist_mutex);
1.138 enami 1613: psignal(tp->t_session->s_leader,
1614: SIGHUP);
1.173.2.3 yamt 1615: mutex_exit(&proclist_mutex);
1616: }
1.96 kleink 1617: ttyflush(tp, FREAD | FWRITE);
1.147 pk 1618: TTY_UNLOCK(tp);
1.164 dbj 1619: splx(s);
1.96 kleink 1620: return (0);
1621: }
1.49 cgd 1622: }
1623: } else {
1.96 kleink 1624: if (!ISSET(tp->t_state, TS_CARR_ON)) {
1625: /*
1626: * Carrier now on.
1627: */
1628: SET(tp->t_state, TS_CARR_ON);
1629: ttwakeup(tp);
1630: }
1.49 cgd 1631: }
1.147 pk 1632: TTY_UNLOCK(tp);
1.164 dbj 1633: splx(s);
1.49 cgd 1634: return (1);
1635: }
1636:
1637: /*
1638: * Default modem control routine (for other line disciplines).
1639: * Return argument flag, to turn off device on carrier drop.
1.147 pk 1640: *
1641: * Must be called at spltty().
1.164 dbj 1642: * XXX except that it is often isn't, which should be fixed.
1.49 cgd 1643: */
1644: int
1.126 lukem 1645: nullmodem(struct tty *tp, int flag)
1.49 cgd 1646: {
1.164 dbj 1647: int s;
1.49 cgd 1648:
1.164 dbj 1649: s = spltty();
1.147 pk 1650: TTY_LOCK(tp);
1.49 cgd 1651: if (flag)
1652: SET(tp->t_state, TS_CARR_ON);
1653: else {
1654: CLR(tp->t_state, TS_CARR_ON);
1.83 mycroft 1655: if (!CONNECTED(tp)) {
1.173.2.3 yamt 1656: if (tp->t_session && tp->t_session->s_leader) {
1657: mutex_enter(&proclist_mutex);
1.49 cgd 1658: psignal(tp->t_session->s_leader, SIGHUP);
1.173.2.3 yamt 1659: mutex_exit(&proclist_mutex);
1660: }
1.147 pk 1661: TTY_UNLOCK(tp);
1.164 dbj 1662: splx(s);
1.49 cgd 1663: return (0);
1664: }
1665: }
1.147 pk 1666: TTY_UNLOCK(tp);
1.164 dbj 1667: splx(s);
1.49 cgd 1668: return (1);
1669: }
1670:
1671: /*
1.147 pk 1672: * Reinput pending characters after state switch.
1673: * Call at spltty() and with the tty slock held.
1.49 cgd 1674: */
1675: void
1.126 lukem 1676: ttypend(struct tty *tp)
1.49 cgd 1677: {
1.126 lukem 1678: struct clist tq;
1679: int c;
1.49 cgd 1680:
1681: CLR(tp->t_lflag, PENDIN);
1682: SET(tp->t_state, TS_TYPEN);
1683: tq = tp->t_rawq;
1684: tp->t_rawq.c_cc = 0;
1685: tp->t_rawq.c_cf = tp->t_rawq.c_cl = 0;
1686: while ((c = getc(&tq)) >= 0)
1.147 pk 1687: ttyinput_wlock(c, tp);
1.49 cgd 1688: CLR(tp->t_state, TS_TYPEN);
1689: }
1690:
1691: /*
1692: * Process a read call on a tty device.
1693: */
1694: int
1.126 lukem 1695: ttread(struct tty *tp, struct uio *uio, int flag)
1.49 cgd 1696: {
1.126 lukem 1697: struct clist *qp;
1698: u_char *cc;
1699: struct proc *p;
1700: int c, s, first, error, has_stime, last_cc;
1701: long lflag, slp;
1.173.2.1 yamt 1702: struct timeval now, stime;
1703:
1704: stime.tv_usec = 0; /* XXX gcc */
1705: stime.tv_sec = 0; /* XXX gcc */
1.49 cgd 1706:
1.126 lukem 1707: cc = tp->t_cc;
1708: p = curproc;
1709: error = 0;
1710: has_stime = 0;
1711: last_cc = 0;
1712: slp = 0;
1713:
1714: loop:
1.147 pk 1715: s = spltty();
1716: TTY_LOCK(tp);
1.126 lukem 1717: lflag = tp->t_lflag;
1.49 cgd 1718: /*
1719: * take pending input first
1720: */
1721: if (ISSET(lflag, PENDIN))
1722: ttypend(tp);
1723:
1724: /*
1.173.2.3 yamt 1725: * Hang process if it's in the background. XXXSMP
1.49 cgd 1726: */
1727: if (isbackground(p, tp)) {
1.125 jdolecek 1728: if (sigismember(&p->p_sigctx.ps_sigignore, SIGTTIN) ||
1.173.2.3 yamt 1729: sigismember(&curlwp->l_sigmask, SIGTTIN) ||
1730: p->p_sflag & PS_PPWAIT || p->p_pgrp->pg_jobc == 0) {
1.147 pk 1731: TTY_UNLOCK(tp);
1732: splx(s);
1.49 cgd 1733: return (EIO);
1.147 pk 1734: }
1.173.2.3 yamt 1735: mutex_enter(&proclist_mutex);
1.49 cgd 1736: pgsignal(p->p_pgrp, SIGTTIN, 1);
1.173.2.3 yamt 1737: mutex_exit(&proclist_mutex);
1.147 pk 1738: error = ttysleep(tp, &lbolt, TTIPRI | PCATCH | PNORELOCK, ttybg, 0);
1739: splx(s);
1.65 christos 1740: if (error)
1.49 cgd 1741: return (error);
1742: goto loop;
1743: }
1744:
1745: if (!ISSET(lflag, ICANON)) {
1746: int m = cc[VMIN];
1747: long t = cc[VTIME];
1748:
1749: qp = &tp->t_rawq;
1750: /*
1751: * Check each of the four combinations.
1752: * (m > 0 && t == 0) is the normal read case.
1753: * It should be fairly efficient, so we check that and its
1754: * companion case (m == 0 && t == 0) first.
1755: * For the other two cases, we compute the target sleep time
1756: * into slp.
1757: */
1758: if (t == 0) {
1759: if (qp->c_cc < m)
1760: goto sleep;
1761: goto read;
1762: }
1.156 dsl 1763: t *= hz; /* time in deca-ticks */
1764: /*
1765: * Time difference in deca-ticks, split division to avoid numeric overflow.
1766: * Ok for hz < ~200kHz
1767: */
1768: #define diff(t1, t2) (((t1).tv_sec - (t2).tv_sec) * 10 * hz + \
1769: ((t1).tv_usec - (t2).tv_usec) / 100 * hz / 1000)
1.49 cgd 1770: if (m > 0) {
1771: if (qp->c_cc <= 0)
1772: goto sleep;
1773: if (qp->c_cc >= m)
1774: goto read;
1775: if (!has_stime) {
1776: /* first character, start timer */
1777: has_stime = 1;
1.173.2.1 yamt 1778: getmicrotime(&stime);
1.49 cgd 1779: slp = t;
1780: } else if (qp->c_cc > last_cc) {
1781: /* got a character, restart timer */
1.173.2.1 yamt 1782: getmicrotime(&stime);
1.49 cgd 1783: slp = t;
1784: } else {
1785: /* nothing, check expiration */
1.173.2.1 yamt 1786: getmicrotime(&now);
1787: slp = t - diff(now, stime);
1.49 cgd 1788: }
1789: } else { /* m == 0 */
1790: if (qp->c_cc > 0)
1791: goto read;
1792: if (!has_stime) {
1793: has_stime = 1;
1.173.2.1 yamt 1794: getmicrotime(&stime);
1.49 cgd 1795: slp = t;
1.173.2.1 yamt 1796: } else {
1797: getmicrotime(&now);
1798: slp = t - diff(now, stime);
1799: }
1.49 cgd 1800: }
1.54 mycroft 1801: last_cc = qp->c_cc;
1.49 cgd 1802: #undef diff
1803: if (slp > 0) {
1804: /*
1.156 dsl 1805: * Convert deca-ticks back to ticks.
1.49 cgd 1806: * Rounding down may make us wake up just short
1807: * of the target, so we round up.
1.156 dsl 1808: * Maybe we should do 'slp/10 + 1' because the
1809: * first tick maybe almost immediate.
1810: * However it is more useful for a program that sets
1811: * VTIME=10 to wakeup every second not every 1.01
1812: * seconds (if hz=100).
1.49 cgd 1813: */
1.156 dsl 1814: slp = (slp + 9)/ 10;
1.49 cgd 1815: goto sleep;
1816: }
1817: } else if ((qp = &tp->t_canq)->c_cc <= 0) {
1.126 lukem 1818: int carrier;
1.49 cgd 1819:
1.126 lukem 1820: sleep:
1.49 cgd 1821: /*
1822: * If there is no input, sleep on rawq
1823: * awaiting hardware receipt and notification.
1824: * If we have data, we don't need to check for carrier.
1825: */
1.83 mycroft 1826: carrier = CONNECTED(tp);
1.49 cgd 1827: if (!carrier && ISSET(tp->t_state, TS_ISOPEN)) {
1.147 pk 1828: TTY_UNLOCK(tp);
1.49 cgd 1829: splx(s);
1830: return (0); /* EOF */
1831: }
1832: if (flag & IO_NDELAY) {
1.147 pk 1833: TTY_UNLOCK(tp);
1.49 cgd 1834: splx(s);
1835: return (EWOULDBLOCK);
1836: }
1.147 pk 1837: error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH | PNORELOCK,
1.53 mycroft 1838: carrier ? ttyin : ttopen, slp);
1.49 cgd 1839: splx(s);
1.82 kleink 1840: /* VMIN == 0: any quantity read satisfies */
1841: if (cc[VMIN] == 0 && error == EWOULDBLOCK)
1842: return (0);
1.54 mycroft 1843: if (error && error != EWOULDBLOCK)
1.49 cgd 1844: return (error);
1845: goto loop;
1846: }
1.126 lukem 1847: read:
1.147 pk 1848: TTY_UNLOCK(tp);
1.49 cgd 1849: splx(s);
1850:
1851: /*
1852: * Input present, check for input mapping and processing.
1853: */
1854: first = 1;
1855: while ((c = getc(qp)) >= 0) {
1856: /*
1857: * delayed suspend (^Y)
1858: */
1.81 kleink 1859: if (CCEQ(cc[VDSUSP], c) &&
1860: ISSET(lflag, IEXTEN|ISIG) == (IEXTEN|ISIG)) {
1.173.2.3 yamt 1861: mutex_enter(&proclist_mutex);
1.49 cgd 1862: pgsignal(tp->t_pgrp, SIGTSTP, 1);
1.173.2.3 yamt 1863: mutex_exit(&proclist_mutex);
1.49 cgd 1864: if (first) {
1.163 dbj 1865: s = spltty();
1.147 pk 1866: TTY_LOCK(tp);
1.65 christos 1867: error = ttysleep(tp, &lbolt,
1.147 pk 1868: TTIPRI | PCATCH | PNORELOCK, ttybg, 0);
1.163 dbj 1869: splx(s);
1.65 christos 1870: if (error)
1.49 cgd 1871: break;
1872: goto loop;
1873: }
1874: break;
1875: }
1876: /*
1877: * Interpret EOF only in canonical mode.
1878: */
1879: if (CCEQ(cc[VEOF], c) && ISSET(lflag, ICANON))
1880: break;
1881: /*
1882: * Give user character.
1883: */
1884: error = ureadc(c, uio);
1885: if (error)
1886: break;
1887: if (uio->uio_resid == 0)
1888: break;
1889: /*
1890: * In canonical mode check for a "break character"
1891: * marking the end of a "line of input".
1892: */
1.85 kleink 1893: if (ISSET(lflag, ICANON) && TTBREAKC(c, lflag))
1.49 cgd 1894: break;
1895: first = 0;
1896: }
1897: /*
1898: * Look to unblock output now that (presumably)
1899: * the input queue has gone down.
1900: */
1901: s = spltty();
1.147 pk 1902: TTY_LOCK(tp);
1.138 enami 1903: if (ISSET(tp->t_state, TS_TBLOCK) && tp->t_rawq.c_cc < TTYHOG / 5) {
1.60 mycroft 1904: if (ISSET(tp->t_iflag, IXOFF) &&
1905: cc[VSTART] != _POSIX_VDISABLE &&
1.49 cgd 1906: putc(cc[VSTART], &tp->t_outq) == 0) {
1907: CLR(tp->t_state, TS_TBLOCK);
1908: ttstart(tp);
1909: }
1.59 mycroft 1910: /* Try to unblock remote output via hardware flow control. */
1911: if (ISSET(tp->t_cflag, CHWFLOW) && tp->t_hwiflow &&
1.49 cgd 1912: (*tp->t_hwiflow)(tp, 0) != 0)
1.59 mycroft 1913: CLR(tp->t_state, TS_TBLOCK);
1.49 cgd 1914: }
1.147 pk 1915: TTY_UNLOCK(tp);
1.49 cgd 1916: splx(s);
1917: return (error);
1918: }
1919:
1920: /*
1921: * Check the output queue on tp for space for a kernel message (from uprintf
1922: * or tprintf). Allow some space over the normal hiwater mark so we don't
1923: * lose messages due to normal flow control, but don't let the tty run amok.
1924: * Sleeps here are not interruptible, but we return prematurely if new signals
1925: * arrive.
1.147 pk 1926: * Call with tty slock held.
1.49 cgd 1927: */
1.147 pk 1928: static int
1929: ttycheckoutq_wlock(struct tty *tp, int wait)
1.49 cgd 1930: {
1.126 lukem 1931: int hiwat, s, error;
1.49 cgd 1932:
1933: hiwat = tp->t_hiwat;
1934: s = spltty();
1935: if (tp->t_outq.c_cc > hiwat + 200)
1936: while (tp->t_outq.c_cc > hiwat) {
1937: ttstart(tp);
1.112 mycroft 1938: if (wait == 0) {
1.49 cgd 1939: splx(s);
1940: return (0);
1941: }
1942: SET(tp->t_state, TS_ASLEEP);
1.147 pk 1943: error = ltsleep(&tp->t_outq, (PZERO - 1) | PCATCH,
1944: "ttckoutq", hz, &tp->t_slock);
1.112 mycroft 1945: if (error == EINTR)
1946: wait = 0;
1.49 cgd 1947: }
1.147 pk 1948:
1.49 cgd 1949: splx(s);
1950: return (1);
1951: }
1952:
1.147 pk 1953: int
1954: ttycheckoutq(struct tty *tp, int wait)
1955: {
1956: int r, s;
1957:
1958: s = spltty();
1959: TTY_LOCK(tp);
1960: r = ttycheckoutq_wlock(tp, wait);
1961: TTY_UNLOCK(tp);
1962: splx(s);
1963: return (r);
1964: }
1965:
1.49 cgd 1966: /*
1967: * Process a write call on a tty device.
1968: */
1969: int
1.126 lukem 1970: ttwrite(struct tty *tp, struct uio *uio, int flag)
1.49 cgd 1971: {
1.126 lukem 1972: u_char *cp;
1973: struct proc *p;
1.140 thorpej 1974: int cc, ce, i, hiwat, error, s;
1975: size_t cnt;
1.126 lukem 1976: u_char obuf[OBUFSIZ];
1.49 cgd 1977:
1.126 lukem 1978: cp = NULL;
1.49 cgd 1979: hiwat = tp->t_hiwat;
1980: cnt = uio->uio_resid;
1981: error = 0;
1982: cc = 0;
1.126 lukem 1983: loop:
1.49 cgd 1984: s = spltty();
1.147 pk 1985: TTY_LOCK(tp);
1.83 mycroft 1986: if (!CONNECTED(tp)) {
1.49 cgd 1987: if (ISSET(tp->t_state, TS_ISOPEN)) {
1.147 pk 1988: TTY_UNLOCK(tp);
1.49 cgd 1989: splx(s);
1990: return (EIO);
1991: } else if (flag & IO_NDELAY) {
1.147 pk 1992: TTY_UNLOCK(tp);
1.49 cgd 1993: splx(s);
1994: error = EWOULDBLOCK;
1995: goto out;
1996: } else {
1997: /* Sleep awaiting carrier. */
1998: error = ttysleep(tp,
1.147 pk 1999: &tp->t_rawq, TTIPRI | PCATCH | PNORELOCK, ttopen, 0);
1.49 cgd 2000: splx(s);
2001: if (error)
2002: goto out;
2003: goto loop;
2004: }
2005: }
1.147 pk 2006: TTY_UNLOCK(tp);
1.49 cgd 2007: splx(s);
2008: /*
1.173.2.3 yamt 2009: * Hang the process if it's in the background. XXXSMP
1.49 cgd 2010: */
2011: p = curproc;
2012: if (isbackground(p, tp) &&
1.173.2.3 yamt 2013: ISSET(tp->t_lflag, TOSTOP) && (p->p_sflag & PS_PPWAIT) == 0 &&
1.125 jdolecek 2014: !sigismember(&p->p_sigctx.ps_sigignore, SIGTTOU) &&
1.173.2.3 yamt 2015: !sigismember(&curlwp->l_sigmask, SIGTTOU)) {
1.86 kleink 2016: if (p->p_pgrp->pg_jobc == 0) {
2017: error = EIO;
2018: goto out;
2019: }
1.173.2.3 yamt 2020: mutex_enter(&proclist_mutex);
1.49 cgd 2021: pgsignal(p->p_pgrp, SIGTTOU, 1);
1.173.2.3 yamt 2022: mutex_exit(&proclist_mutex);
1.147 pk 2023: s = spltty();
2024: TTY_LOCK(tp);
2025: error = ttysleep(tp, &lbolt, TTIPRI | PCATCH | PNORELOCK, ttybg, 0);
2026: splx(s);
1.65 christos 2027: if (error)
1.49 cgd 2028: goto out;
2029: goto loop;
2030: }
2031: /*
2032: * Process the user's data in at most OBUFSIZ chunks. Perform any
2033: * output translation. Keep track of high water mark, sleep on
2034: * overflow awaiting device aid in acquiring new space.
2035: */
2036: while (uio->uio_resid > 0 || cc > 0) {
2037: if (ISSET(tp->t_lflag, FLUSHO)) {
2038: uio->uio_resid = 0;
2039: return (0);
2040: }
2041: if (tp->t_outq.c_cc > hiwat)
2042: goto ovhiwat;
2043: /*
2044: * Grab a hunk of data from the user, unless we have some
2045: * leftover from last time.
2046: */
2047: if (cc == 0) {
2048: cc = min(uio->uio_resid, OBUFSIZ);
2049: cp = obuf;
2050: error = uiomove(cp, cc, uio);
2051: if (error) {
2052: cc = 0;
1.147 pk 2053: goto out;
1.49 cgd 2054: }
2055: }
2056: /*
2057: * If nothing fancy need be done, grab those characters we
2058: * can handle without any of ttyoutput's processing and
2059: * just transfer them to the output q. For those chars
2060: * which require special processing (as indicated by the
2061: * bits in char_type), call ttyoutput. After processing
2062: * a hunk of data, look for FLUSHO so ^O's will take effect
2063: * immediately.
2064: */
1.147 pk 2065: s = spltty();
2066: TTY_LOCK(tp);
1.49 cgd 2067: while (cc > 0) {
2068: if (!ISSET(tp->t_oflag, OPOST))
2069: ce = cc;
2070: else {
1.77 cgd 2071: ce = cc - scanc((u_int)cc, cp, char_type,
2072: CCLASSMASK);
1.49 cgd 2073: /*
2074: * If ce is zero, then we're processing
2075: * a special character through ttyoutput.
2076: */
2077: if (ce == 0) {
2078: tp->t_rocount = 0;
2079: if (ttyoutput(*cp, tp) >= 0) {
2080: /* out of space */
1.147 pk 2081: TTY_UNLOCK(tp);
2082: splx(s);
1.49 cgd 2083: goto overfull;
2084: }
2085: cp++;
2086: cc--;
2087: if (ISSET(tp->t_lflag, FLUSHO) ||
1.147 pk 2088: tp->t_outq.c_cc > hiwat) {
2089: TTY_UNLOCK(tp);
2090: splx(s);
1.49 cgd 2091: goto ovhiwat;
1.147 pk 2092: }
1.49 cgd 2093: continue;
2094: }
2095: }
2096: /*
2097: * A bunch of normal characters have been found.
2098: * Transfer them en masse to the output queue and
2099: * continue processing at the top of the loop.
2100: * If there are any further characters in this
2101: * <= OBUFSIZ chunk, the first should be a character
2102: * requiring special handling by ttyoutput.
2103: */
2104: tp->t_rocount = 0;
2105: i = b_to_q(cp, ce, &tp->t_outq);
2106: ce -= i;
2107: tp->t_column += ce;
2108: cp += ce, cc -= ce, tk_nout += ce;
2109: tp->t_outcc += ce;
2110: if (i > 0) {
2111: /* out of space */
1.147 pk 2112: TTY_UNLOCK(tp);
2113: splx(s);
1.49 cgd 2114: goto overfull;
2115: }
2116: if (ISSET(tp->t_lflag, FLUSHO) ||
2117: tp->t_outq.c_cc > hiwat)
2118: break;
2119: }
1.147 pk 2120: TTY_UNLOCK(tp);
2121: splx(s);
1.49 cgd 2122: ttstart(tp);
2123: }
1.147 pk 2124:
1.126 lukem 2125: out:
1.49 cgd 2126: /*
2127: * If cc is nonzero, we leave the uio structure inconsistent, as the
2128: * offset and iov pointers have moved forward, but it doesn't matter
2129: * (the call will either return short or restart with a new uio).
2130: */
2131: uio->uio_resid += cc;
2132: return (error);
2133:
1.126 lukem 2134: overfull:
1.49 cgd 2135: /*
2136: * Since we are using ring buffers, if we can't insert any more into
2137: * the output queue, we can assume the ring is full and that someone
2138: * forgot to set the high water mark correctly. We set it and then
2139: * proceed as normal.
2140: */
2141: hiwat = tp->t_outq.c_cc - 1;
2142:
1.126 lukem 2143: ovhiwat:
1.49 cgd 2144: ttstart(tp);
2145: s = spltty();
1.147 pk 2146: TTY_LOCK(tp);
1.49 cgd 2147: /*
2148: * This can only occur if FLUSHO is set in t_lflag,
2149: * or if ttstart/oproc is synchronous (or very fast).
2150: */
2151: if (tp->t_outq.c_cc <= hiwat) {
1.147 pk 2152: TTY_UNLOCK(tp);
1.49 cgd 2153: splx(s);
2154: goto loop;
2155: }
2156: if (flag & IO_NDELAY) {
1.147 pk 2157: TTY_UNLOCK(tp);
1.49 cgd 2158: splx(s);
1.173.2.2 yamt 2159: error = EWOULDBLOCK;
1.147 pk 2160: goto out;
1.49 cgd 2161: }
2162: SET(tp->t_state, TS_ASLEEP);
1.147 pk 2163: error = ttysleep(tp, &tp->t_outq, TTOPRI | PCATCH | PNORELOCK, ttyout, 0);
1.49 cgd 2164: splx(s);
2165: if (error)
2166: goto out;
2167: goto loop;
2168: }
2169:
2170: /*
2171: * Rubout one character from the rawq of tp
2172: * as cleanly as possible.
1.147 pk 2173: * Called with tty slock held.
1.49 cgd 2174: */
2175: void
1.126 lukem 2176: ttyrub(int c, struct tty *tp)
1.49 cgd 2177: {
1.126 lukem 2178: u_char *cp;
2179: int savecol, tabc, s;
1.49 cgd 2180:
2181: if (!ISSET(tp->t_lflag, ECHO) || ISSET(tp->t_lflag, EXTPROC))
2182: return;
2183: CLR(tp->t_lflag, FLUSHO);
2184: if (ISSET(tp->t_lflag, ECHOE)) {
2185: if (tp->t_rocount == 0) {
2186: /*
2187: * Screwed by ttwrite; retype
2188: */
2189: ttyretype(tp);
2190: return;
2191: }
2192: if (c == ('\t' | TTY_QUOTE) || c == ('\n' | TTY_QUOTE))
2193: ttyrubo(tp, 2);
2194: else {
2195: CLR(c, ~TTY_CHARMASK);
2196: switch (CCLASS(c)) {
2197: case ORDINARY:
2198: ttyrubo(tp, 1);
2199: break;
2200: case BACKSPACE:
2201: case CONTROL:
2202: case NEWLINE:
2203: case RETURN:
2204: case VTAB:
2205: if (ISSET(tp->t_lflag, ECHOCTL))
2206: ttyrubo(tp, 2);
2207: break;
2208: case TAB:
2209: if (tp->t_rocount < tp->t_rawq.c_cc) {
2210: ttyretype(tp);
2211: return;
2212: }
2213: s = spltty();
2214: savecol = tp->t_column;
2215: SET(tp->t_state, TS_CNTTB);
2216: SET(tp->t_lflag, FLUSHO);
2217: tp->t_column = tp->t_rocol;
1.52 deraadt 2218: for (cp = firstc(&tp->t_rawq, &tabc); cp;
1.49 cgd 2219: cp = nextc(&tp->t_rawq, cp, &tabc))
2220: ttyecho(tabc, tp);
2221: CLR(tp->t_lflag, FLUSHO);
2222: CLR(tp->t_state, TS_CNTTB);
2223: splx(s);
2224:
2225: /* savecol will now be length of the tab. */
2226: savecol -= tp->t_column;
2227: tp->t_column += savecol;
2228: if (savecol > 8)
2229: savecol = 8; /* overflow screw */
2230: while (--savecol >= 0)
2231: (void)ttyoutput('\b', tp);
2232: break;
2233: default: /* XXX */
1.172 christos 2234: (void)printf("ttyrub: would panic c = %d, "
2235: "val = %d\n", c, CCLASS(c));
1.49 cgd 2236: }
2237: }
2238: } else if (ISSET(tp->t_lflag, ECHOPRT)) {
2239: if (!ISSET(tp->t_state, TS_ERASE)) {
2240: SET(tp->t_state, TS_ERASE);
2241: (void)ttyoutput('\\', tp);
2242: }
2243: ttyecho(c, tp);
2244: } else
2245: ttyecho(tp->t_cc[VERASE], tp);
2246: --tp->t_rocount;
2247: }
2248:
2249: /*
2250: * Back over cnt characters, erasing them.
1.147 pk 2251: * Called with tty slock held.
1.49 cgd 2252: */
2253: static void
1.126 lukem 2254: ttyrubo(struct tty *tp, int cnt)
1.49 cgd 2255: {
2256:
2257: while (cnt-- > 0) {
2258: (void)ttyoutput('\b', tp);
2259: (void)ttyoutput(' ', tp);
2260: (void)ttyoutput('\b', tp);
2261: }
2262: }
2263:
2264: /*
2265: * ttyretype --
2266: * Reprint the rawq line. Note, it is assumed that c_cc has already
2267: * been checked.
1.147 pk 2268: *
2269: * Called with tty slock held.
1.49 cgd 2270: */
2271: void
1.126 lukem 2272: ttyretype(struct tty *tp)
1.49 cgd 2273: {
1.126 lukem 2274: u_char *cp;
2275: int s, c;
1.49 cgd 2276:
2277: /* Echo the reprint character. */
2278: if (tp->t_cc[VREPRINT] != _POSIX_VDISABLE)
2279: ttyecho(tp->t_cc[VREPRINT], tp);
2280:
2281: (void)ttyoutput('\n', tp);
2282:
2283: s = spltty();
2284: for (cp = firstc(&tp->t_canq, &c); cp; cp = nextc(&tp->t_canq, cp, &c))
2285: ttyecho(c, tp);
2286: for (cp = firstc(&tp->t_rawq, &c); cp; cp = nextc(&tp->t_rawq, cp, &c))
2287: ttyecho(c, tp);
2288: CLR(tp->t_state, TS_ERASE);
2289: splx(s);
2290:
2291: tp->t_rocount = tp->t_rawq.c_cc;
2292: tp->t_rocol = 0;
2293: }
2294:
2295: /*
2296: * Echo a typed character to the terminal.
1.147 pk 2297: * Called with tty slock held.
1.49 cgd 2298: */
2299: static void
1.126 lukem 2300: ttyecho(int c, struct tty *tp)
1.49 cgd 2301: {
2302:
2303: if (!ISSET(tp->t_state, TS_CNTTB))
2304: CLR(tp->t_lflag, FLUSHO);
2305: if ((!ISSET(tp->t_lflag, ECHO) &&
1.64 pk 2306: (!ISSET(tp->t_lflag, ECHONL) || c != '\n')) ||
1.49 cgd 2307: ISSET(tp->t_lflag, EXTPROC))
2308: return;
1.65 christos 2309: if (((ISSET(tp->t_lflag, ECHOCTL) &&
1.138 enami 2310: (ISSET(c, TTY_CHARMASK) <= 037 && c != '\t' && c != '\n')) ||
1.49 cgd 2311: ISSET(c, TTY_CHARMASK) == 0177)) {
2312: (void)ttyoutput('^', tp);
2313: CLR(c, ~TTY_CHARMASK);
2314: if (c == 0177)
2315: c = '?';
2316: else
2317: c += 'A' - 1;
2318: }
2319: (void)ttyoutput(c, tp);
2320: }
2321:
2322: /*
2323: * Wake up any readers on a tty.
1.147 pk 2324: * Called with tty slock held.
1.49 cgd 2325: */
2326: void
1.126 lukem 2327: ttwakeup(struct tty *tp)
1.49 cgd 2328: {
2329:
1.162 jdolecek 2330: selnotify(&tp->t_rsel, NOTE_SUBMIT);
1.173.2.3 yamt 2331: if (ISSET(tp->t_state, TS_ASYNC)) {
2332: mutex_enter(&proclist_mutex);
1.173.2.1 yamt 2333: pgsignal(tp->t_pgrp, SIGIO, tp->t_session != NULL);
1.173.2.3 yamt 2334: mutex_exit(&proclist_mutex);
2335: }
1.173.2.4! yamt 2336: wakeup((void *)&tp->t_rawq);
1.49 cgd 2337: }
2338:
2339: /*
2340: * Look up a code for a specified speed in a conversion table;
2341: * used by drivers to map software speed values to hardware parameters.
2342: */
2343: int
1.166 matt 2344: ttspeedtab(int speed, const struct speedtab *table)
1.49 cgd 2345: {
2346:
1.138 enami 2347: for (; table->sp_speed != -1; table++)
1.49 cgd 2348: if (table->sp_speed == speed)
2349: return (table->sp_code);
2350: return (-1);
2351: }
2352:
2353: /*
2354: * Set tty hi and low water marks.
2355: *
2356: * Try to arrange the dynamics so there's about one second
2357: * from hi to low water.
2358: */
2359: void
1.126 lukem 2360: ttsetwater(struct tty *tp)
1.49 cgd 2361: {
1.126 lukem 2362: int cps, x;
1.49 cgd 2363:
1.126 lukem 2364: #define CLAMP(x, h, l) ((x) > h ? h : ((x) < l) ? l : (x))
1.49 cgd 2365:
2366: cps = tp->t_ospeed / 10;
2367: tp->t_lowat = x = CLAMP(cps / 2, TTMAXLOWAT, TTMINLOWAT);
2368: x += cps;
2369: x = CLAMP(x, TTMAXHIWAT, TTMINHIWAT);
2370: tp->t_hiwat = roundup(x, CBSIZE);
2371: #undef CLAMP
2372: }
2373:
2374: /*
2375: * Report on state of foreground process group.
1.147 pk 2376: * Call with tty slock held.
1.173.2.3 yamt 2377: * XXXSMP locking.
1.49 cgd 2378: */
2379: void
1.173.2.1 yamt 2380: ttyinfo(struct tty *tp, int fromsig)
1.49 cgd 2381: {
1.145 thorpej 2382: struct lwp *l;
1.173.2.1 yamt 2383: struct proc *p, *pick = NULL;
1.126 lukem 2384: struct timeval utime, stime;
2385: int tmp;
1.173.2.4! yamt 2386: fixpt_t pctcpu = 0;
1.173.2.1 yamt 2387: const char *msg;
1.49 cgd 2388:
1.147 pk 2389: if (ttycheckoutq_wlock(tp, 0) == 0)
1.49 cgd 2390: return;
2391:
2392: if (tp->t_session == NULL)
1.173.2.1 yamt 2393: msg = "not a controlling terminal\n";
1.49 cgd 2394: else if (tp->t_pgrp == NULL)
1.173.2.1 yamt 2395: msg = "no foreground process group\n";
2396: else if ((p = LIST_FIRST(&tp->t_pgrp->pg_members)) == NULL)
2397: msg = "empty foreground process group\n";
1.49 cgd 2398: else {
2399: /* Pick interesting process. */
1.173.2.1 yamt 2400: for (; p != NULL; p = LIST_NEXT(p, p_pglist))
1.49 cgd 2401: if (proc_compare(pick, p))
2402: pick = p;
1.173.2.1 yamt 2403: if (fromsig &&
2404: (SIGACTION_PS(pick->p_sigacts, SIGINFO).sa_flags &
2405: SA_NOKERNINFO))
2406: return;
2407: msg = NULL;
2408: }
1.49 cgd 2409:
1.173.2.1 yamt 2410: /* Print load average. */
2411: tmp = (averunnable.ldavg[0] * 100 + FSCALE / 2) >> FSHIFT;
2412: ttyprintf_nolock(tp, "load: %d.%02d ", tmp / 100, tmp % 100);
2413:
2414: if (pick == NULL) {
2415: ttyprintf_nolock(tp, msg);
2416: tp->t_rocount = 0; /* so pending input will be retyped if BS */
2417: return;
2418: }
2419:
2420: ttyprintf_nolock(tp, " cmd: %s %d [", pick->p_comm, pick->p_pid);
1.173.2.4! yamt 2421: LIST_FOREACH(l, &pick->p_lwps, l_sibling) {
1.173.2.1 yamt 2422: ttyprintf_nolock(tp, "%s%s",
2423: l->l_stat == LSONPROC ? "running" :
2424: l->l_stat == LSRUN ? "runnable" :
2425: l->l_wmesg ? l->l_wmesg : "iowait",
2426: (LIST_NEXT(l, l_sibling) != NULL) ? " " : "] ");
1.173.2.4! yamt 2427: pctcpu += l->l_pctcpu;
! 2428: }
! 2429: pctcpu += pick->p_pctcpu;
1.173.2.1 yamt 2430:
1.173.2.3 yamt 2431: mutex_enter(&pick->p_smutex);
2432: calcru(pick, &utime, &stime, NULL, NULL);
2433: mutex_exit(&pick->p_smutex);
1.173.2.1 yamt 2434:
2435: /* Round up and print user time. */
2436: utime.tv_usec += 5000;
2437: if (utime.tv_usec >= 1000000) {
2438: utime.tv_sec += 1;
2439: utime.tv_usec -= 1000000;
2440: }
2441: ttyprintf_nolock(tp, "%ld.%02ldu ", (long int)utime.tv_sec,
2442: (long int)utime.tv_usec / 10000);
2443:
2444: /* Round up and print system time. */
2445: stime.tv_usec += 5000;
2446: if (stime.tv_usec >= 1000000) {
2447: stime.tv_sec += 1;
2448: stime.tv_usec -= 1000000;
2449: }
2450: ttyprintf_nolock(tp, "%ld.%02lds ", (long int)stime.tv_sec,
2451: (long int)stime.tv_usec / 10000);
1.49 cgd 2452:
1.123 thorpej 2453: #define pgtok(a) (((u_long) ((a) * PAGE_SIZE) / 1024))
1.173.2.1 yamt 2454: /* Print percentage CPU. */
1.173.2.4! yamt 2455: tmp = (pctcpu * 10000 + FSCALE / 2) >> FSHIFT;
1.173.2.1 yamt 2456: ttyprintf_nolock(tp, "%d%% ", tmp / 100);
2457:
2458: /* Print resident set size. */
2459: if (pick->p_stat == SIDL || P_ZOMBIE(pick))
2460: tmp = 0;
2461: else {
2462: struct vmspace *vm = pick->p_vmspace;
2463: tmp = pgtok(vm_resident_count(vm));
1.49 cgd 2464: }
1.173.2.1 yamt 2465: ttyprintf_nolock(tp, "%dk\n", tmp);
1.49 cgd 2466: tp->t_rocount = 0; /* so pending input will be retyped if BS */
2467: }
2468:
2469: /*
2470: * Returns 1 if p2 is "better" than p1
2471: *
2472: * The algorithm for picking the "interesting" process is thus:
2473: *
2474: * 1) Only foreground processes are eligible - implied.
2475: * 2) Runnable processes are favored over anything else. The runner
1.161 wiz 2476: * with the highest CPU utilization is picked (p_estcpu). Ties are
1.49 cgd 2477: * broken by picking the highest pid.
2478: * 3) The sleeper with the shortest sleep time is next. With ties,
2479: * we pick out just "short-term" sleepers (P_SINTR == 0).
2480: * 4) Further ties are broken by picking the highest pid.
1.173.2.3 yamt 2481: *
2482: * XXXSMP
1.49 cgd 2483: */
1.145 thorpej 2484: #define ISRUN(p) ((p)->p_nrlwps > 0)
1.138 enami 2485: #define TESTAB(a, b) ((a)<<1 | (b))
2486: #define ONLYA 2
2487: #define ONLYB 1
2488: #define BOTH 3
1.49 cgd 2489:
2490: static int
1.126 lukem 2491: proc_compare(struct proc *p1, struct proc *p2)
1.49 cgd 2492: {
2493:
2494: if (p1 == NULL)
2495: return (1);
2496: /*
2497: * see if at least one of them is runnable
2498: */
2499: switch (TESTAB(ISRUN(p1), ISRUN(p2))) {
2500: case ONLYA:
2501: return (0);
2502: case ONLYB:
2503: return (1);
2504: case BOTH:
2505: /*
1.161 wiz 2506: * tie - favor one with highest recent CPU utilization
1.49 cgd 2507: */
2508: if (p2->p_estcpu > p1->p_estcpu)
2509: return (1);
2510: if (p1->p_estcpu > p2->p_estcpu)
2511: return (0);
2512: return (p2->p_pid > p1->p_pid); /* tie - return highest pid */
2513: }
2514: /*
2515: * weed out zombies
2516: */
1.114 thorpej 2517: switch (TESTAB(P_ZOMBIE(p1), P_ZOMBIE(p2))) {
1.49 cgd 2518: case ONLYA:
2519: return (1);
2520: case ONLYB:
2521: return (0);
2522: case BOTH:
1.138 enami 2523: return (p2->p_pid > p1->p_pid); /* tie - return highest pid */
1.49 cgd 2524: }
1.145 thorpej 2525: #if 0 /* XXX NJWLWP */
1.49 cgd 2526: /*
2527: * pick the one with the smallest sleep time
2528: */
2529: if (p2->p_slptime > p1->p_slptime)
2530: return (0);
2531: if (p1->p_slptime > p2->p_slptime)
2532: return (1);
2533: /*
2534: * favor one sleeping in a non-interruptible sleep
2535: */
2536: if (p1->p_flag & P_SINTR && (p2->p_flag & P_SINTR) == 0)
2537: return (1);
2538: if (p2->p_flag & P_SINTR && (p1->p_flag & P_SINTR) == 0)
2539: return (0);
1.145 thorpej 2540: #endif
1.49 cgd 2541: return (p2->p_pid > p1->p_pid); /* tie - return highest pid */
2542: }
2543:
2544: /*
2545: * Output char to tty; console putchar style.
1.147 pk 2546: * Can be called with tty lock held through kprintf() machinery..
1.49 cgd 2547: */
2548: int
1.149 christos 2549: tputchar(int c, int flags, struct tty *tp)
1.49 cgd 2550: {
1.149 christos 2551: int s, r = 0;
1.49 cgd 2552:
2553: s = spltty();
1.149 christos 2554: if ((flags & NOLOCK) == 0)
2555: simple_lock(&tp->t_slock);
1.147 pk 2556: if (!CONNECTED(tp)) {
2557: r = -1;
2558: goto out;
1.49 cgd 2559: }
2560: if (c == '\n')
2561: (void)ttyoutput('\r', tp);
2562: (void)ttyoutput(c, tp);
2563: ttstart(tp);
1.147 pk 2564: out:
1.149 christos 2565: if ((flags & NOLOCK) == 0)
1.147 pk 2566: TTY_UNLOCK(tp);
1.49 cgd 2567: splx(s);
1.147 pk 2568: return (r);
1.49 cgd 2569: }
2570:
2571: /*
2572: * Sleep on chan, returning ERESTART if tty changed while we napped and
2573: * returning any errors (e.g. EINTR/ETIMEDOUT) reported by tsleep. If
2574: * the tty is revoked, restarting a pending call will redo validation done
2575: * at the start of the call.
1.147 pk 2576: *
2577: * Must be called with the tty slock held.
1.49 cgd 2578: */
2579: int
1.126 lukem 2580: ttysleep(struct tty *tp, void *chan, int pri, const char *wmesg, int timo)
1.49 cgd 2581: {
1.126 lukem 2582: int error;
2583: short gen;
1.49 cgd 2584:
2585: gen = tp->t_gen;
1.147 pk 2586: if ((error = ltsleep(chan, pri, wmesg, timo, &tp->t_slock)) != 0)
1.49 cgd 2587: return (error);
2588: return (tp->t_gen == gen ? 0 : ERESTART);
2589: }
2590:
2591: /*
1.69 mrg 2592: * Attach a tty to the tty list.
1.72 mrg 2593: *
2594: * This should be called ONLY once per real tty (including pty's).
2595: * eg, on the sparc, the keyboard and mouse have struct tty's that are
2596: * distinctly NOT usable as tty's, and thus should not be attached to
2597: * the ttylist. This is why this call is not done from ttymalloc().
2598: *
2599: * Device drivers should attach tty's at a similar time that they are
2600: * ttymalloc()'ed, or, for the case of statically allocated struct tty's
2601: * either in the attach or (first) open routine.
1.69 mrg 2602: */
2603: void
1.126 lukem 2604: tty_attach(struct tty *tp)
1.69 mrg 2605: {
1.173.2.4! yamt 2606: static bool again;
! 2607:
! 2608: if (!again) {
! 2609: again = true;
! 2610: mutex_init(&ttylist_lock, MUTEX_DEFAULT, IPL_NONE);
! 2611: }
1.71 cgd 2612:
1.173.2.4! yamt 2613: mutex_enter(&ttylist_lock);
1.69 mrg 2614: TAILQ_INSERT_TAIL(&ttylist, tp, tty_link);
2615: ++tty_count;
1.173.2.4! yamt 2616: mutex_exit(&ttylist_lock);
1.69 mrg 2617: }
2618:
2619: /*
2620: * Remove a tty from the tty list.
2621: */
2622: void
1.126 lukem 2623: tty_detach(struct tty *tp)
1.69 mrg 2624: {
1.71 cgd 2625:
1.173.2.4! yamt 2626: mutex_enter(&ttylist_lock);
1.69 mrg 2627: --tty_count;
2628: #ifdef DIAGNOSTIC
2629: if (tty_count < 0)
2630: panic("tty_detach: tty_count < 0");
2631: #endif
1.70 mrg 2632: TAILQ_REMOVE(&ttylist, tp, tty_link);
1.173.2.4! yamt 2633: mutex_exit(&ttylist_lock);
1.69 mrg 2634: }
2635:
2636: /*
1.49 cgd 2637: * Allocate a tty structure and its associated buffers.
2638: */
2639: struct tty *
1.126 lukem 2640: ttymalloc(void)
1.49 cgd 2641: {
1.126 lukem 2642: struct tty *tp;
1.49 cgd 2643:
1.111 thorpej 2644: tp = pool_get(&tty_pool, PR_WAITOK);
1.109 perry 2645: memset(tp, 0, sizeof(*tp));
1.147 pk 2646: simple_lock_init(&tp->t_slock);
1.173.2.4! yamt 2647: callout_init(&tp->t_rstrt_ch, 0);
1.84 mycroft 2648: /* XXX: default to 1024 chars for now */
2649: clalloc(&tp->t_rawq, 1024, 1);
2650: clalloc(&tp->t_canq, 1024, 1);
1.49 cgd 2651: /* output queue doesn't need quoting */
1.84 mycroft 2652: clalloc(&tp->t_outq, 1024, 0);
1.121 eeh 2653: /* Set default line discipline. */
1.173.2.1 yamt 2654: tp->t_linesw = ttyldisc_default();
1.138 enami 2655: return (tp);
1.49 cgd 2656: }
2657:
2658: /*
2659: * Free a tty structure and its buffers.
1.73 mrg 2660: *
2661: * Be sure to call tty_detach() for any tty that has been
2662: * tty_attach()ed.
1.49 cgd 2663: */
2664: void
1.126 lukem 2665: ttyfree(struct tty *tp)
1.49 cgd 2666: {
1.71 cgd 2667:
1.116 thorpej 2668: callout_stop(&tp->t_rstrt_ch);
1.173.2.1 yamt 2669: ttyldisc_release(tp->t_linesw);
1.49 cgd 2670: clfree(&tp->t_rawq);
2671: clfree(&tp->t_canq);
2672: clfree(&tp->t_outq);
1.111 thorpej 2673: pool_put(&tty_pool, tp);
1.149 christos 2674: }
2675:
2676: /*
2677: * ttyprintf_nolock: send a message to a specific tty, without locking.
2678: *
2679: * => should be used only by tty driver or anything that knows the
2680: * underlying tty will not be revoked(2)'d away. [otherwise,
2681: * use tprintf]
2682: */
2683: static void
2684: ttyprintf_nolock(struct tty *tp, const char *fmt, ...)
2685: {
2686: va_list ap;
2687:
2688: /* No mutex needed; going to process TTY. */
2689: va_start(ap, fmt);
2690: kprintf(fmt, TOTTY|NOLOCK, tp, NULL, ap);
2691: va_end(ap);
1.49 cgd 2692: }
CVSweb <webmaster@jp.NetBSD.org>