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