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