Annotation of src/sys/kern/tty.c, Revision 1.227.4.2
1.227.4.2! sborrill 1: /* $NetBSD: tty.c,v 1.227.4.1 2009/02/06 02:05:18 snj 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.227.4.2! sborrill 66: __KERNEL_RCSID(0, "$NetBSD: tty.c,v 1.227.4.1 2009/02/06 02:05:18 snj 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.216 ad 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.224 ad 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.220 ad 346: mutex_enter(proc_lock);
1.209 ad 347: if (sess != NULL)
348: SESSRELE(sess);
1.220 ad 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.227.4.1 snj 376: /* XXX static */ int
1.147 pk 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.215 ad 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.215 ad 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.225 ad 865: p->p_pgrp->pg_jobc && (p->p_lflag & PL_PPWAIT) == 0 &&
1.190 ad 866: !sigismasked(l, SIGTTOU)) {
1.210 ad 867: mutex_spin_exit(&tty_lock);
868:
1.220 ad 869: mutex_enter(proc_lock);
1.210 ad 870: pgsignal(p->p_pgrp, SIGTTOU, 1);
1.220 ad 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.220 ad 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.220 ad 972: }
1.158 jdolecek 973: *(int *)data = tp->t_pgrp ? -tp->t_pgrp->pg_id : 0;
1.220 ad 974: mutex_exit(proc_lock);
1.158 jdolecek 975: break;
1.49 cgd 976: case TIOCGPGRP: /* get pgrp of tty */
1.220 ad 977: mutex_enter(proc_lock);
978: if (!isctty(p, tp)) {
979: mutex_exit(proc_lock);
1.49 cgd 980: return (ENOTTY);
1.220 ad 981: }
1.150 dsl 982: *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PGID;
1.220 ad 983: mutex_exit(proc_lock);
1.104 thorpej 984: break;
985: case TIOCGSID: /* get sid of tty */
1.220 ad 986: mutex_enter(proc_lock);
987: if (!isctty(p, tp)) {
988: mutex_exit(proc_lock);
1.104 thorpej 989: return (ENOTTY);
1.220 ad 990: }
1.104 thorpej 991: *(int *)data = tp->t_session->s_sid;
1.220 ad 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.220 ad 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.220 ad 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.220 ad 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.220 ad 1182: mutex_enter(proc_lock);
1.209 ad 1183: if (tp->t_session != NULL && !isctty(p, tp)) {
1.220 ad 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.220 ad 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.220 ad 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.220 ad 1213: mutex_enter(proc_lock);
1.209 ad 1214: if (!isctty(p, tp)) {
1.220 ad 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.220 ad 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.220 ad 1228: mutex_exit(proc_lock);
1.49 cgd 1229: break;
1230: }
1231: case TIOCSTAT: /* get load avg stats */
1.220 ad 1232: mutex_enter(proc_lock);
1.215 ad 1233: ttygetinfo(tp, 0, infobuf, sizeof(infobuf));
1.220 ad 1234: mutex_exit(proc_lock);
1.215 ad 1235:
1.201 ad 1236: mutex_spin_enter(&tty_lock);
1.215 ad 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.224 ad 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.224 ad 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.227.4.2! sborrill 1658: if (uio->uio_resid == 0)
! 1659: return 0;
! 1660:
1.181 mrg 1661: stime.tv_usec = 0; /* XXX gcc */
1662: stime.tv_sec = 0; /* XXX gcc */
1663:
1.126 lukem 1664: cc = tp->t_cc;
1665: p = curproc;
1666: error = 0;
1667: has_stime = 0;
1668: last_cc = 0;
1669: slp = 0;
1670:
1671: loop:
1.201 ad 1672: mutex_spin_enter(&tty_lock);
1.126 lukem 1673: lflag = tp->t_lflag;
1.49 cgd 1674: /*
1675: * take pending input first
1676: */
1677: if (ISSET(lflag, PENDIN))
1678: ttypend(tp);
1679:
1680: /*
1.209 ad 1681: * Hang process if it's in the background.
1.49 cgd 1682: */
1683: if (isbackground(p, tp)) {
1.223 yamt 1684: if (sigismasked(curlwp, SIGTTIN) ||
1.225 ad 1685: p->p_lflag & PL_PPWAIT || p->p_pgrp->pg_jobc == 0) {
1.201 ad 1686: mutex_spin_exit(&tty_lock);
1.49 cgd 1687: return (EIO);
1.147 pk 1688: }
1.210 ad 1689: mutex_spin_exit(&tty_lock);
1690:
1.220 ad 1691: mutex_enter(proc_lock);
1.210 ad 1692: pgsignal(p->p_pgrp, SIGTTIN, 1);
1.220 ad 1693: mutex_exit(proc_lock);
1.210 ad 1694:
1695: mutex_spin_enter(&tty_lock);
1.201 ad 1696: error = ttysleep(tp, &lbolt, true, 0);
1697: mutex_spin_exit(&tty_lock);
1.65 christos 1698: if (error)
1.49 cgd 1699: return (error);
1700: goto loop;
1701: }
1702:
1703: if (!ISSET(lflag, ICANON)) {
1704: int m = cc[VMIN];
1705: long t = cc[VTIME];
1706:
1707: qp = &tp->t_rawq;
1708: /*
1709: * Check each of the four combinations.
1710: * (m > 0 && t == 0) is the normal read case.
1711: * It should be fairly efficient, so we check that and its
1712: * companion case (m == 0 && t == 0) first.
1713: * For the other two cases, we compute the target sleep time
1714: * into slp.
1715: */
1716: if (t == 0) {
1717: if (qp->c_cc < m)
1718: goto sleep;
1719: goto read;
1720: }
1.156 dsl 1721: t *= hz; /* time in deca-ticks */
1722: /*
1723: * Time difference in deca-ticks, split division to avoid numeric overflow.
1724: * Ok for hz < ~200kHz
1725: */
1726: #define diff(t1, t2) (((t1).tv_sec - (t2).tv_sec) * 10 * hz + \
1727: ((t1).tv_usec - (t2).tv_usec) / 100 * hz / 1000)
1.49 cgd 1728: if (m > 0) {
1729: if (qp->c_cc <= 0)
1730: goto sleep;
1731: if (qp->c_cc >= m)
1732: goto read;
1733: if (!has_stime) {
1734: /* first character, start timer */
1735: has_stime = 1;
1.185 kardel 1736: getmicrotime(&stime);
1.49 cgd 1737: slp = t;
1738: } else if (qp->c_cc > last_cc) {
1739: /* got a character, restart timer */
1.185 kardel 1740: getmicrotime(&stime);
1.49 cgd 1741: slp = t;
1742: } else {
1743: /* nothing, check expiration */
1.185 kardel 1744: getmicrotime(&now);
1745: slp = t - diff(now, stime);
1.49 cgd 1746: }
1747: } else { /* m == 0 */
1748: if (qp->c_cc > 0)
1749: goto read;
1750: if (!has_stime) {
1751: has_stime = 1;
1.185 kardel 1752: getmicrotime(&stime);
1.49 cgd 1753: slp = t;
1.185 kardel 1754: } else {
1755: getmicrotime(&now);
1756: slp = t - diff(now, stime);
1757: }
1.49 cgd 1758: }
1.54 mycroft 1759: last_cc = qp->c_cc;
1.49 cgd 1760: #undef diff
1761: if (slp > 0) {
1762: /*
1.156 dsl 1763: * Convert deca-ticks back to ticks.
1.49 cgd 1764: * Rounding down may make us wake up just short
1765: * of the target, so we round up.
1.156 dsl 1766: * Maybe we should do 'slp/10 + 1' because the
1767: * first tick maybe almost immediate.
1768: * However it is more useful for a program that sets
1769: * VTIME=10 to wakeup every second not every 1.01
1770: * seconds (if hz=100).
1.49 cgd 1771: */
1.156 dsl 1772: slp = (slp + 9)/ 10;
1.49 cgd 1773: goto sleep;
1774: }
1775: } else if ((qp = &tp->t_canq)->c_cc <= 0) {
1.126 lukem 1776: int carrier;
1.49 cgd 1777:
1.126 lukem 1778: sleep:
1.49 cgd 1779: /*
1780: * If there is no input, sleep on rawq
1781: * awaiting hardware receipt and notification.
1782: * If we have data, we don't need to check for carrier.
1783: */
1.83 mycroft 1784: carrier = CONNECTED(tp);
1.49 cgd 1785: if (!carrier && ISSET(tp->t_state, TS_ISOPEN)) {
1.201 ad 1786: mutex_spin_exit(&tty_lock);
1.49 cgd 1787: return (0); /* EOF */
1788: }
1789: if (flag & IO_NDELAY) {
1.201 ad 1790: mutex_spin_exit(&tty_lock);
1.49 cgd 1791: return (EWOULDBLOCK);
1792: }
1.224 ad 1793: error = ttysleep(tp, &tp->t_rawcv, true, slp);
1.201 ad 1794: mutex_spin_exit(&tty_lock);
1.82 kleink 1795: /* VMIN == 0: any quantity read satisfies */
1796: if (cc[VMIN] == 0 && error == EWOULDBLOCK)
1797: return (0);
1.54 mycroft 1798: if (error && error != EWOULDBLOCK)
1.49 cgd 1799: return (error);
1800: goto loop;
1801: }
1.126 lukem 1802: read:
1.201 ad 1803: mutex_spin_exit(&tty_lock);
1.49 cgd 1804:
1805: /*
1806: * Input present, check for input mapping and processing.
1807: */
1808: first = 1;
1809: while ((c = getc(qp)) >= 0) {
1810: /*
1811: * delayed suspend (^Y)
1812: */
1.81 kleink 1813: if (CCEQ(cc[VDSUSP], c) &&
1814: ISSET(lflag, IEXTEN|ISIG) == (IEXTEN|ISIG)) {
1.201 ad 1815: mutex_spin_enter(&tty_lock);
1816: ttysig(tp, TTYSIG_PG1, SIGTSTP);
1.49 cgd 1817: if (first) {
1.201 ad 1818: error = ttysleep(tp, &lbolt, true, 0);
1819: mutex_spin_exit(&tty_lock);
1.65 christos 1820: if (error)
1.49 cgd 1821: break;
1822: goto loop;
1.201 ad 1823: } else
1824: mutex_spin_exit(&tty_lock);
1.49 cgd 1825: break;
1826: }
1827: /*
1828: * Interpret EOF only in canonical mode.
1829: */
1830: if (CCEQ(cc[VEOF], c) && ISSET(lflag, ICANON))
1831: break;
1832: /*
1833: * Give user character.
1834: */
1835: error = ureadc(c, uio);
1836: if (error)
1837: break;
1838: if (uio->uio_resid == 0)
1839: break;
1840: /*
1841: * In canonical mode check for a "break character"
1842: * marking the end of a "line of input".
1843: */
1.85 kleink 1844: if (ISSET(lflag, ICANON) && TTBREAKC(c, lflag))
1.49 cgd 1845: break;
1846: first = 0;
1847: }
1848: /*
1849: * Look to unblock output now that (presumably)
1850: * the input queue has gone down.
1851: */
1.201 ad 1852: mutex_spin_enter(&tty_lock);
1.138 enami 1853: if (ISSET(tp->t_state, TS_TBLOCK) && tp->t_rawq.c_cc < TTYHOG / 5) {
1.60 mycroft 1854: if (ISSET(tp->t_iflag, IXOFF) &&
1855: cc[VSTART] != _POSIX_VDISABLE &&
1.49 cgd 1856: putc(cc[VSTART], &tp->t_outq) == 0) {
1857: CLR(tp->t_state, TS_TBLOCK);
1858: ttstart(tp);
1859: }
1.59 mycroft 1860: /* Try to unblock remote output via hardware flow control. */
1861: if (ISSET(tp->t_cflag, CHWFLOW) && tp->t_hwiflow &&
1.49 cgd 1862: (*tp->t_hwiflow)(tp, 0) != 0)
1.59 mycroft 1863: CLR(tp->t_state, TS_TBLOCK);
1.49 cgd 1864: }
1.201 ad 1865: mutex_spin_exit(&tty_lock);
1866:
1.49 cgd 1867: return (error);
1868: }
1869:
1870: /*
1871: * Check the output queue on tp for space for a kernel message (from uprintf
1872: * or tprintf). Allow some space over the normal hiwater mark so we don't
1873: * lose messages due to normal flow control, but don't let the tty run amok.
1874: * Sleeps here are not interruptible, but we return prematurely if new signals
1875: * arrive.
1.201 ad 1876: * Call with tty lock held.
1.49 cgd 1877: */
1.147 pk 1878: static int
1879: ttycheckoutq_wlock(struct tty *tp, int wait)
1.49 cgd 1880: {
1.201 ad 1881: int hiwat, error;
1882:
1883: KASSERT(mutex_owned(&tty_lock));
1.49 cgd 1884:
1885: hiwat = tp->t_hiwat;
1886: if (tp->t_outq.c_cc > hiwat + 200)
1887: while (tp->t_outq.c_cc > hiwat) {
1888: ttstart(tp);
1.201 ad 1889: if (wait == 0)
1.49 cgd 1890: return (0);
1.224 ad 1891: error = ttysleep(tp, &tp->t_outcv, true, hz);
1.112 mycroft 1892: if (error == EINTR)
1893: wait = 0;
1.49 cgd 1894: }
1.147 pk 1895:
1.49 cgd 1896: return (1);
1897: }
1898:
1.147 pk 1899: int
1900: ttycheckoutq(struct tty *tp, int wait)
1901: {
1.201 ad 1902: int r;
1.147 pk 1903:
1.201 ad 1904: mutex_spin_enter(&tty_lock);
1.147 pk 1905: r = ttycheckoutq_wlock(tp, wait);
1.201 ad 1906: mutex_spin_exit(&tty_lock);
1907:
1.147 pk 1908: return (r);
1909: }
1910:
1.49 cgd 1911: /*
1912: * Process a write call on a tty device.
1913: */
1914: int
1.126 lukem 1915: ttwrite(struct tty *tp, struct uio *uio, int flag)
1.49 cgd 1916: {
1.126 lukem 1917: u_char *cp;
1918: struct proc *p;
1.201 ad 1919: int cc, ce, i, hiwat, error;
1.126 lukem 1920: u_char obuf[OBUFSIZ];
1.49 cgd 1921:
1.126 lukem 1922: cp = NULL;
1.49 cgd 1923: hiwat = tp->t_hiwat;
1924: error = 0;
1925: cc = 0;
1.126 lukem 1926: loop:
1.201 ad 1927: mutex_spin_enter(&tty_lock);
1.83 mycroft 1928: if (!CONNECTED(tp)) {
1.49 cgd 1929: if (ISSET(tp->t_state, TS_ISOPEN)) {
1.201 ad 1930: mutex_spin_exit(&tty_lock);
1.49 cgd 1931: return (EIO);
1932: } else if (flag & IO_NDELAY) {
1.201 ad 1933: mutex_spin_exit(&tty_lock);
1.49 cgd 1934: error = EWOULDBLOCK;
1935: goto out;
1936: } else {
1937: /* Sleep awaiting carrier. */
1.224 ad 1938: error = ttysleep(tp, &tp->t_rawcv, true, 0);
1.201 ad 1939: mutex_spin_exit(&tty_lock);
1.49 cgd 1940: if (error)
1941: goto out;
1942: goto loop;
1943: }
1944: }
1.211 ad 1945:
1.49 cgd 1946: /*
1.209 ad 1947: * Hang the process if it's in the background.
1.49 cgd 1948: */
1949: p = curproc;
1950: if (isbackground(p, tp) &&
1.225 ad 1951: ISSET(tp->t_lflag, TOSTOP) && (p->p_lflag & PL_PPWAIT) == 0 &&
1.223 yamt 1952: !sigismasked(curlwp, SIGTTOU)) {
1.86 kleink 1953: if (p->p_pgrp->pg_jobc == 0) {
1954: error = EIO;
1.209 ad 1955: mutex_spin_exit(&tty_lock);
1.86 kleink 1956: goto out;
1957: }
1.210 ad 1958: mutex_spin_exit(&tty_lock);
1959:
1.220 ad 1960: mutex_enter(proc_lock);
1.210 ad 1961: pgsignal(p->p_pgrp, SIGTTOU, 1);
1.220 ad 1962: mutex_exit(proc_lock);
1.210 ad 1963:
1964: mutex_spin_enter(&tty_lock);
1.201 ad 1965: error = ttysleep(tp, &lbolt, true, 0);
1966: mutex_spin_exit(&tty_lock);
1.65 christos 1967: if (error)
1.49 cgd 1968: goto out;
1969: goto loop;
1970: }
1.209 ad 1971: mutex_spin_exit(&tty_lock);
1972:
1.49 cgd 1973: /*
1974: * Process the user's data in at most OBUFSIZ chunks. Perform any
1975: * output translation. Keep track of high water mark, sleep on
1976: * overflow awaiting device aid in acquiring new space.
1977: */
1978: while (uio->uio_resid > 0 || cc > 0) {
1979: if (ISSET(tp->t_lflag, FLUSHO)) {
1980: uio->uio_resid = 0;
1981: return (0);
1982: }
1983: if (tp->t_outq.c_cc > hiwat)
1984: goto ovhiwat;
1985: /*
1986: * Grab a hunk of data from the user, unless we have some
1987: * leftover from last time.
1988: */
1989: if (cc == 0) {
1990: cc = min(uio->uio_resid, OBUFSIZ);
1991: cp = obuf;
1992: error = uiomove(cp, cc, uio);
1993: if (error) {
1994: cc = 0;
1.147 pk 1995: goto out;
1.49 cgd 1996: }
1997: }
1998: /*
1999: * If nothing fancy need be done, grab those characters we
2000: * can handle without any of ttyoutput's processing and
2001: * just transfer them to the output q. For those chars
2002: * which require special processing (as indicated by the
2003: * bits in char_type), call ttyoutput. After processing
2004: * a hunk of data, look for FLUSHO so ^O's will take effect
2005: * immediately.
2006: */
1.201 ad 2007: mutex_spin_enter(&tty_lock);
1.49 cgd 2008: while (cc > 0) {
2009: if (!ISSET(tp->t_oflag, OPOST))
2010: ce = cc;
2011: else {
1.77 cgd 2012: ce = cc - scanc((u_int)cc, cp, char_type,
2013: CCLASSMASK);
1.49 cgd 2014: /*
2015: * If ce is zero, then we're processing
2016: * a special character through ttyoutput.
2017: */
2018: if (ce == 0) {
2019: tp->t_rocount = 0;
2020: if (ttyoutput(*cp, tp) >= 0) {
2021: /* out of space */
1.201 ad 2022: mutex_spin_exit(&tty_lock);
1.49 cgd 2023: goto overfull;
2024: }
2025: cp++;
2026: cc--;
2027: if (ISSET(tp->t_lflag, FLUSHO) ||
1.147 pk 2028: tp->t_outq.c_cc > hiwat) {
1.201 ad 2029: mutex_spin_exit(&tty_lock);
1.49 cgd 2030: goto ovhiwat;
1.147 pk 2031: }
1.49 cgd 2032: continue;
2033: }
2034: }
2035: /*
2036: * A bunch of normal characters have been found.
2037: * Transfer them en masse to the output queue and
2038: * continue processing at the top of the loop.
2039: * If there are any further characters in this
2040: * <= OBUFSIZ chunk, the first should be a character
2041: * requiring special handling by ttyoutput.
2042: */
2043: tp->t_rocount = 0;
2044: i = b_to_q(cp, ce, &tp->t_outq);
2045: ce -= i;
2046: tp->t_column += ce;
2047: cp += ce, cc -= ce, tk_nout += ce;
2048: tp->t_outcc += ce;
2049: if (i > 0) {
2050: /* out of space */
1.201 ad 2051: mutex_spin_exit(&tty_lock);
1.49 cgd 2052: goto overfull;
2053: }
2054: if (ISSET(tp->t_lflag, FLUSHO) ||
2055: tp->t_outq.c_cc > hiwat)
2056: break;
2057: }
1.205 ad 2058: ttstart(tp);
1.201 ad 2059: mutex_spin_exit(&tty_lock);
1.49 cgd 2060: }
1.147 pk 2061:
1.126 lukem 2062: out:
1.49 cgd 2063: /*
2064: * If cc is nonzero, we leave the uio structure inconsistent, as the
2065: * offset and iov pointers have moved forward, but it doesn't matter
2066: * (the call will either return short or restart with a new uio).
2067: */
2068: uio->uio_resid += cc;
2069: return (error);
2070:
1.126 lukem 2071: overfull:
1.49 cgd 2072: /*
2073: * Since we are using ring buffers, if we can't insert any more into
2074: * the output queue, we can assume the ring is full and that someone
2075: * forgot to set the high water mark correctly. We set it and then
2076: * proceed as normal.
2077: */
2078: hiwat = tp->t_outq.c_cc - 1;
2079:
1.126 lukem 2080: ovhiwat:
1.205 ad 2081: mutex_spin_enter(&tty_lock);
1.49 cgd 2082: ttstart(tp);
2083: /*
2084: * This can only occur if FLUSHO is set in t_lflag,
2085: * or if ttstart/oproc is synchronous (or very fast).
2086: */
2087: if (tp->t_outq.c_cc <= hiwat) {
1.201 ad 2088: mutex_spin_exit(&tty_lock);
1.49 cgd 2089: goto loop;
2090: }
2091: if (flag & IO_NDELAY) {
1.201 ad 2092: mutex_spin_exit(&tty_lock);
1.187 christos 2093: error = EWOULDBLOCK;
1.147 pk 2094: goto out;
1.49 cgd 2095: }
1.224 ad 2096: error = ttysleep(tp, &tp->t_outcv, true, 0);
1.201 ad 2097: mutex_spin_exit(&tty_lock);
1.49 cgd 2098: if (error)
2099: goto out;
2100: goto loop;
2101: }
2102:
2103: /*
1.203 ad 2104: * Try to pull more output from the producer. Return non-zero if
2105: * there is output ready to be sent.
2106: */
2107: bool
2108: ttypull(struct tty *tp)
2109: {
2110:
2111: /* XXXSMP not yet KASSERT(mutex_owned(&tty_lock)); */
2112:
2113: if (tp->t_outq.c_cc <= tp->t_lowat) {
1.224 ad 2114: cv_broadcast(&tp->t_outcv);
1.213 rmind 2115: selnotify(&tp->t_wsel, 0, NOTE_SUBMIT);
1.203 ad 2116: }
2117: return tp->t_outq.c_cc != 0;
2118: }
2119:
2120: /*
1.49 cgd 2121: * Rubout one character from the rawq of tp
2122: * as cleanly as possible.
1.201 ad 2123: * Called with tty lock held.
1.49 cgd 2124: */
2125: void
1.126 lukem 2126: ttyrub(int c, struct tty *tp)
1.49 cgd 2127: {
1.126 lukem 2128: u_char *cp;
1.201 ad 2129: int savecol, tabc;
2130:
2131: KASSERT(mutex_owned(&tty_lock));
1.49 cgd 2132:
2133: if (!ISSET(tp->t_lflag, ECHO) || ISSET(tp->t_lflag, EXTPROC))
2134: return;
2135: CLR(tp->t_lflag, FLUSHO);
2136: if (ISSET(tp->t_lflag, ECHOE)) {
2137: if (tp->t_rocount == 0) {
2138: /*
2139: * Screwed by ttwrite; retype
2140: */
2141: ttyretype(tp);
2142: return;
2143: }
2144: if (c == ('\t' | TTY_QUOTE) || c == ('\n' | TTY_QUOTE))
2145: ttyrubo(tp, 2);
2146: else {
2147: CLR(c, ~TTY_CHARMASK);
2148: switch (CCLASS(c)) {
2149: case ORDINARY:
2150: ttyrubo(tp, 1);
2151: break;
2152: case BACKSPACE:
2153: case CONTROL:
2154: case NEWLINE:
2155: case RETURN:
2156: case VTAB:
2157: if (ISSET(tp->t_lflag, ECHOCTL))
2158: ttyrubo(tp, 2);
2159: break;
2160: case TAB:
2161: if (tp->t_rocount < tp->t_rawq.c_cc) {
2162: ttyretype(tp);
2163: return;
2164: }
2165: savecol = tp->t_column;
2166: SET(tp->t_state, TS_CNTTB);
2167: SET(tp->t_lflag, FLUSHO);
2168: tp->t_column = tp->t_rocol;
1.52 deraadt 2169: for (cp = firstc(&tp->t_rawq, &tabc); cp;
1.49 cgd 2170: cp = nextc(&tp->t_rawq, cp, &tabc))
2171: ttyecho(tabc, tp);
2172: CLR(tp->t_lflag, FLUSHO);
2173: CLR(tp->t_state, TS_CNTTB);
2174:
2175: /* savecol will now be length of the tab. */
2176: savecol -= tp->t_column;
2177: tp->t_column += savecol;
2178: if (savecol > 8)
2179: savecol = 8; /* overflow screw */
2180: while (--savecol >= 0)
2181: (void)ttyoutput('\b', tp);
2182: break;
2183: default: /* XXX */
1.172 christos 2184: (void)printf("ttyrub: would panic c = %d, "
2185: "val = %d\n", c, CCLASS(c));
1.49 cgd 2186: }
2187: }
2188: } else if (ISSET(tp->t_lflag, ECHOPRT)) {
2189: if (!ISSET(tp->t_state, TS_ERASE)) {
2190: SET(tp->t_state, TS_ERASE);
2191: (void)ttyoutput('\\', tp);
2192: }
2193: ttyecho(c, tp);
2194: } else
2195: ttyecho(tp->t_cc[VERASE], tp);
2196: --tp->t_rocount;
2197: }
2198:
2199: /*
2200: * Back over cnt characters, erasing them.
1.201 ad 2201: * Called with tty lock held.
1.49 cgd 2202: */
2203: static void
1.126 lukem 2204: ttyrubo(struct tty *tp, int cnt)
1.49 cgd 2205: {
2206:
1.201 ad 2207: KASSERT(mutex_owned(&tty_lock));
2208:
1.49 cgd 2209: while (cnt-- > 0) {
2210: (void)ttyoutput('\b', tp);
2211: (void)ttyoutput(' ', tp);
2212: (void)ttyoutput('\b', tp);
2213: }
2214: }
2215:
2216: /*
2217: * ttyretype --
2218: * Reprint the rawq line. Note, it is assumed that c_cc has already
2219: * been checked.
1.147 pk 2220: *
1.201 ad 2221: * Called with tty lock held.
1.49 cgd 2222: */
2223: void
1.126 lukem 2224: ttyretype(struct tty *tp)
1.49 cgd 2225: {
1.126 lukem 2226: u_char *cp;
1.201 ad 2227: int c;
2228:
2229: KASSERT(mutex_owned(&tty_lock));
1.49 cgd 2230:
2231: /* Echo the reprint character. */
2232: if (tp->t_cc[VREPRINT] != _POSIX_VDISABLE)
2233: ttyecho(tp->t_cc[VREPRINT], tp);
2234:
2235: (void)ttyoutput('\n', tp);
2236:
2237: for (cp = firstc(&tp->t_canq, &c); cp; cp = nextc(&tp->t_canq, cp, &c))
2238: ttyecho(c, tp);
2239: for (cp = firstc(&tp->t_rawq, &c); cp; cp = nextc(&tp->t_rawq, cp, &c))
2240: ttyecho(c, tp);
2241: CLR(tp->t_state, TS_ERASE);
2242:
2243: tp->t_rocount = tp->t_rawq.c_cc;
2244: tp->t_rocol = 0;
2245: }
2246:
2247: /*
2248: * Echo a typed character to the terminal.
1.201 ad 2249: * Called with tty lock held.
1.49 cgd 2250: */
2251: static void
1.126 lukem 2252: ttyecho(int c, struct tty *tp)
1.49 cgd 2253: {
2254:
1.201 ad 2255: KASSERT(mutex_owned(&tty_lock));
2256:
1.49 cgd 2257: if (!ISSET(tp->t_state, TS_CNTTB))
2258: CLR(tp->t_lflag, FLUSHO);
2259: if ((!ISSET(tp->t_lflag, ECHO) &&
1.64 pk 2260: (!ISSET(tp->t_lflag, ECHONL) || c != '\n')) ||
1.49 cgd 2261: ISSET(tp->t_lflag, EXTPROC))
2262: return;
1.65 christos 2263: if (((ISSET(tp->t_lflag, ECHOCTL) &&
1.138 enami 2264: (ISSET(c, TTY_CHARMASK) <= 037 && c != '\t' && c != '\n')) ||
1.49 cgd 2265: ISSET(c, TTY_CHARMASK) == 0177)) {
2266: (void)ttyoutput('^', tp);
2267: CLR(c, ~TTY_CHARMASK);
2268: if (c == 0177)
2269: c = '?';
2270: else
2271: c += 'A' - 1;
2272: }
2273: (void)ttyoutput(c, tp);
2274: }
2275:
2276: /*
2277: * Wake up any readers on a tty.
1.201 ad 2278: * Called with tty lock held.
1.49 cgd 2279: */
2280: void
1.126 lukem 2281: ttwakeup(struct tty *tp)
1.49 cgd 2282: {
2283:
1.201 ad 2284: KASSERT(mutex_owned(&tty_lock));
2285:
1.213 rmind 2286: selnotify(&tp->t_rsel, 0, NOTE_SUBMIT);
1.201 ad 2287: if (ISSET(tp->t_state, TS_ASYNC))
2288: ttysig(tp, TTYSIG_PG2, SIGIO);
1.224 ad 2289: cv_broadcast(&tp->t_rawcv);
1.49 cgd 2290: }
2291:
2292: /*
2293: * Look up a code for a specified speed in a conversion table;
2294: * used by drivers to map software speed values to hardware parameters.
2295: */
2296: int
1.166 matt 2297: ttspeedtab(int speed, const struct speedtab *table)
1.49 cgd 2298: {
2299:
1.138 enami 2300: for (; table->sp_speed != -1; table++)
1.49 cgd 2301: if (table->sp_speed == speed)
2302: return (table->sp_code);
2303: return (-1);
2304: }
2305:
2306: /*
2307: * Set tty hi and low water marks.
2308: *
2309: * Try to arrange the dynamics so there's about one second
2310: * from hi to low water.
2311: */
2312: void
1.126 lukem 2313: ttsetwater(struct tty *tp)
1.49 cgd 2314: {
1.126 lukem 2315: int cps, x;
1.49 cgd 2316:
1.201 ad 2317: /* XXX not yet KASSERT(mutex_owned(&tty_lock)); */
2318:
1.126 lukem 2319: #define CLAMP(x, h, l) ((x) > h ? h : ((x) < l) ? l : (x))
1.49 cgd 2320:
2321: cps = tp->t_ospeed / 10;
2322: tp->t_lowat = x = CLAMP(cps / 2, TTMAXLOWAT, TTMINLOWAT);
2323: x += cps;
2324: x = CLAMP(x, TTMAXHIWAT, TTMINHIWAT);
2325: tp->t_hiwat = roundup(x, CBSIZE);
2326: #undef CLAMP
2327: }
2328:
2329: /*
1.215 ad 2330: * Prepare report on state of foreground process group.
1.220 ad 2331: * Call with proc_lock held.
1.49 cgd 2332: */
2333: void
1.215 ad 2334: ttygetinfo(struct tty *tp, int fromsig, char *buf, size_t bufsz)
1.49 cgd 2335: {
1.145 thorpej 2336: struct lwp *l;
1.184 christos 2337: struct proc *p, *pick = NULL;
1.126 lukem 2338: struct timeval utime, stime;
2339: int tmp;
1.196 yamt 2340: fixpt_t pctcpu = 0;
1.183 christos 2341: const char *msg;
1.215 ad 2342: char lmsg[100];
2343: long rss;
1.49 cgd 2344:
1.220 ad 2345: KASSERT(mutex_owned(proc_lock));
1.215 ad 2346:
2347: *buf = '\0';
1.49 cgd 2348:
2349: if (tp->t_session == NULL)
1.183 christos 2350: msg = "not a controlling terminal\n";
1.49 cgd 2351: else if (tp->t_pgrp == NULL)
1.183 christos 2352: msg = "no foreground process group\n";
2353: else if ((p = LIST_FIRST(&tp->t_pgrp->pg_members)) == NULL)
2354: msg = "empty foreground process group\n";
1.49 cgd 2355: else {
2356: /* Pick interesting process. */
1.215 ad 2357: for (; p != NULL; p = LIST_NEXT(p, p_pglist)) {
1.217 yamt 2358: struct proc *oldpick;
2359:
1.215 ad 2360: if (pick == NULL) {
2361: pick = p;
2362: continue;
2363: }
1.221 ad 2364: if (pick->p_lock < p->p_lock) {
2365: mutex_enter(pick->p_lock);
2366: mutex_enter(p->p_lock);
2367: } else if (pick->p_lock > p->p_lock) {
2368: mutex_enter(p->p_lock);
2369: mutex_enter(pick->p_lock);
2370: } else
2371: mutex_enter(p->p_lock);
1.217 yamt 2372: oldpick = pick;
1.49 cgd 2373: if (proc_compare(pick, p))
2374: pick = p;
1.221 ad 2375: mutex_exit(p->p_lock);
2376: if (p->p_lock != oldpick->p_lock)
2377: mutex_exit(oldpick->p_lock);
1.215 ad 2378: }
1.183 christos 2379: if (fromsig &&
2380: (SIGACTION_PS(pick->p_sigacts, SIGINFO).sa_flags &
2381: SA_NOKERNINFO))
2382: return;
2383: msg = NULL;
2384: }
2385:
2386: /* Print load average. */
2387: tmp = (averunnable.ldavg[0] * 100 + FSCALE / 2) >> FSHIFT;
1.215 ad 2388: snprintf(lmsg, sizeof(lmsg), "load: %d.%02d ", tmp / 100, tmp % 100);
2389: strlcat(buf, lmsg, bufsz);
1.49 cgd 2390:
1.184 christos 2391: if (pick == NULL) {
1.215 ad 2392: strlcat(buf, msg, bufsz);
1.183 christos 2393: return;
2394: }
2395:
1.215 ad 2396: snprintf(lmsg, sizeof(lmsg), " cmd: %s %d [", pick->p_comm,
2397: pick->p_pid);
2398: strlcat(buf, lmsg, bufsz);
2399:
1.221 ad 2400: mutex_enter(pick->p_lock);
1.196 yamt 2401: LIST_FOREACH(l, &pick->p_lwps, l_sibling) {
1.214 yamt 2402: lwp_lock(l);
2403: snprintf(lmsg, sizeof(lmsg), "%s%s",
2404: l->l_stat == LSONPROC ? "running" :
2405: l->l_stat == LSRUN ? "runnable" :
2406: l->l_wchan ? l->l_wmesg : "iowait",
2407: (LIST_NEXT(l, l_sibling) != NULL) ? " " : "] ");
2408: lwp_unlock(l);
1.215 ad 2409: strlcat(buf, lmsg, bufsz);
1.214 yamt 2410: pctcpu += l->l_pctcpu;
1.196 yamt 2411: }
2412: pctcpu += pick->p_pctcpu;
1.190 ad 2413: calcru(pick, &utime, &stime, NULL, NULL);
1.221 ad 2414: mutex_exit(pick->p_lock);
1.183 christos 2415:
1.215 ad 2416: /* Round up and print user+system time, %CPU and RSS. */
1.183 christos 2417: utime.tv_usec += 5000;
2418: if (utime.tv_usec >= 1000000) {
2419: utime.tv_sec += 1;
2420: utime.tv_usec -= 1000000;
2421: }
2422: stime.tv_usec += 5000;
2423: if (stime.tv_usec >= 1000000) {
2424: stime.tv_sec += 1;
2425: stime.tv_usec -= 1000000;
2426: }
1.123 thorpej 2427: #define pgtok(a) (((u_long) ((a) * PAGE_SIZE) / 1024))
1.196 yamt 2428: tmp = (pctcpu * 10000 + FSCALE / 2) >> FSHIFT;
1.215 ad 2429: if (pick->p_stat == SIDL || P_ZOMBIE(pick))
2430: rss = 0;
2431: else
2432: rss = pgtok(vm_resident_count(pick->p_vmspace));
2433:
2434: snprintf(lmsg, sizeof(lmsg), "%ld.%02ldu %ld.%02lds %d%% %ldk",
2435: (long)utime.tv_sec, (long)utime.tv_usec / 10000,
2436: (long)stime.tv_sec, (long)stime.tv_usec / 10000,
2437: tmp / 100, rss);
2438: strlcat(buf, lmsg, bufsz);
2439: }
1.183 christos 2440:
1.215 ad 2441: /*
2442: * Print report on state of foreground process group.
2443: * Call with tty_lock held.
2444: */
2445: void
2446: ttyputinfo(struct tty *tp, char *buf)
2447: {
2448:
2449: KASSERT(mutex_owned(&tty_lock));
2450:
2451: if (ttycheckoutq_wlock(tp, 0) == 0)
2452: return;
2453: ttyprintf_nolock(tp, "%s\n", buf);
1.49 cgd 2454: tp->t_rocount = 0; /* so pending input will be retyped if BS */
2455: }
2456:
2457: /*
2458: * Returns 1 if p2 is "better" than p1
2459: *
2460: * The algorithm for picking the "interesting" process is thus:
2461: *
2462: * 1) Only foreground processes are eligible - implied.
2463: * 2) Runnable processes are favored over anything else. The runner
1.200 ad 2464: * with the highest CPU utilization is picked (l_pctcpu). Ties are
1.49 cgd 2465: * broken by picking the highest pid.
2466: * 3) The sleeper with the shortest sleep time is next. With ties,
2467: * we pick out just "short-term" sleepers (P_SINTR == 0).
2468: * 4) Further ties are broken by picking the highest pid.
2469: */
1.145 thorpej 2470: #define ISRUN(p) ((p)->p_nrlwps > 0)
1.138 enami 2471: #define TESTAB(a, b) ((a)<<1 | (b))
2472: #define ONLYA 2
2473: #define ONLYB 1
2474: #define BOTH 3
1.49 cgd 2475:
2476: static int
1.126 lukem 2477: proc_compare(struct proc *p1, struct proc *p2)
1.49 cgd 2478: {
1.200 ad 2479: lwp_t *l1, *l2;
1.49 cgd 2480:
1.221 ad 2481: KASSERT(mutex_owned(p1->p_lock));
2482: KASSERT(mutex_owned(p2->p_lock));
1.215 ad 2483:
2484: if ((l1 = LIST_FIRST(&p1->p_lwps)) == NULL)
1.49 cgd 2485: return (1);
1.215 ad 2486: if ((l2 = LIST_FIRST(&p2->p_lwps)) == NULL)
2487: return (0);
1.49 cgd 2488: /*
2489: * see if at least one of them is runnable
2490: */
2491: switch (TESTAB(ISRUN(p1), ISRUN(p2))) {
2492: case ONLYA:
2493: return (0);
2494: case ONLYB:
2495: return (1);
2496: case BOTH:
2497: /*
1.161 wiz 2498: * tie - favor one with highest recent CPU utilization
1.49 cgd 2499: */
1.200 ad 2500: if (l2->l_pctcpu > l1->l_pctcpu)
1.49 cgd 2501: return (1);
2502: return (p2->p_pid > p1->p_pid); /* tie - return highest pid */
2503: }
2504: /*
2505: * weed out zombies
2506: */
1.114 thorpej 2507: switch (TESTAB(P_ZOMBIE(p1), P_ZOMBIE(p2))) {
1.49 cgd 2508: case ONLYA:
2509: return (1);
2510: case ONLYB:
2511: return (0);
2512: case BOTH:
1.138 enami 2513: return (p2->p_pid > p1->p_pid); /* tie - return highest pid */
1.49 cgd 2514: }
2515: /*
2516: * pick the one with the smallest sleep time
2517: */
1.215 ad 2518: if (l2->l_slptime > l2->l_slptime)
1.49 cgd 2519: return (0);
1.215 ad 2520: if (l2->l_slptime > l2->l_slptime)
1.49 cgd 2521: return (1);
2522: /*
2523: * favor one sleeping in a non-interruptible sleep
2524: */
1.215 ad 2525: if (l2->l_flag & LW_SINTR && (l2->l_flag & LW_SINTR) == 0)
1.49 cgd 2526: return (1);
1.215 ad 2527: if (l2->l_flag & LW_SINTR && (l2->l_flag & LW_SINTR) == 0)
1.49 cgd 2528: return (0);
2529: return (p2->p_pid > p1->p_pid); /* tie - return highest pid */
2530: }
2531:
2532: /*
2533: * Output char to tty; console putchar style.
1.147 pk 2534: * Can be called with tty lock held through kprintf() machinery..
1.49 cgd 2535: */
2536: int
1.149 christos 2537: tputchar(int c, int flags, struct tty *tp)
1.49 cgd 2538: {
1.201 ad 2539: int r = 0;
1.49 cgd 2540:
1.149 christos 2541: if ((flags & NOLOCK) == 0)
1.201 ad 2542: mutex_spin_enter(&tty_lock);
1.147 pk 2543: if (!CONNECTED(tp)) {
2544: r = -1;
2545: goto out;
1.49 cgd 2546: }
2547: if (c == '\n')
2548: (void)ttyoutput('\r', tp);
2549: (void)ttyoutput(c, tp);
2550: ttstart(tp);
1.147 pk 2551: out:
1.149 christos 2552: if ((flags & NOLOCK) == 0)
1.201 ad 2553: mutex_spin_exit(&tty_lock);
1.147 pk 2554: return (r);
1.49 cgd 2555: }
2556:
2557: /*
2558: * Sleep on chan, returning ERESTART if tty changed while we napped and
2559: * returning any errors (e.g. EINTR/ETIMEDOUT) reported by tsleep. If
2560: * the tty is revoked, restarting a pending call will redo validation done
2561: * at the start of the call.
1.147 pk 2562: *
1.201 ad 2563: * Must be called with the tty lock held.
1.49 cgd 2564: */
2565: int
1.201 ad 2566: ttysleep(struct tty *tp, kcondvar_t *cv, bool catch, int timo)
1.49 cgd 2567: {
1.126 lukem 2568: int error;
2569: short gen;
1.49 cgd 2570:
1.201 ad 2571: KASSERT(mutex_owned(&tty_lock));
2572:
1.49 cgd 2573: gen = tp->t_gen;
1.201 ad 2574: if (catch)
2575: error = cv_timedwait_sig(cv, &tty_lock, timo);
2576: else
2577: error = cv_timedwait(cv, &tty_lock, timo);
2578: if (error != 0)
1.49 cgd 2579: return (error);
2580: return (tp->t_gen == gen ? 0 : ERESTART);
2581: }
2582:
2583: /*
1.69 mrg 2584: * Attach a tty to the tty list.
1.72 mrg 2585: *
2586: * This should be called ONLY once per real tty (including pty's).
2587: * eg, on the sparc, the keyboard and mouse have struct tty's that are
2588: * distinctly NOT usable as tty's, and thus should not be attached to
2589: * the ttylist. This is why this call is not done from ttymalloc().
2590: *
2591: * Device drivers should attach tty's at a similar time that they are
2592: * ttymalloc()'ed, or, for the case of statically allocated struct tty's
2593: * either in the attach or (first) open routine.
1.69 mrg 2594: */
2595: void
1.126 lukem 2596: tty_attach(struct tty *tp)
1.69 mrg 2597: {
1.71 cgd 2598:
1.201 ad 2599: mutex_spin_enter(&tty_lock);
1.69 mrg 2600: TAILQ_INSERT_TAIL(&ttylist, tp, tty_link);
2601: ++tty_count;
1.201 ad 2602: mutex_spin_exit(&tty_lock);
1.69 mrg 2603: }
2604:
2605: /*
2606: * Remove a tty from the tty list.
2607: */
2608: void
1.126 lukem 2609: tty_detach(struct tty *tp)
1.69 mrg 2610: {
1.71 cgd 2611:
1.201 ad 2612: mutex_spin_enter(&tty_lock);
1.69 mrg 2613: --tty_count;
2614: #ifdef DIAGNOSTIC
2615: if (tty_count < 0)
2616: panic("tty_detach: tty_count < 0");
2617: #endif
1.70 mrg 2618: TAILQ_REMOVE(&ttylist, tp, tty_link);
1.201 ad 2619: mutex_spin_exit(&tty_lock);
1.69 mrg 2620: }
2621:
2622: /*
1.49 cgd 2623: * Allocate a tty structure and its associated buffers.
2624: */
2625: struct tty *
1.126 lukem 2626: ttymalloc(void)
1.49 cgd 2627: {
1.126 lukem 2628: struct tty *tp;
1.202 ad 2629: int i;
1.49 cgd 2630:
1.216 ad 2631: tp = kmem_zalloc(sizeof(*tp), KM_SLEEP);
1.197 ad 2632: callout_init(&tp->t_rstrt_ch, 0);
1.199 joerg 2633: callout_setfunc(&tp->t_rstrt_ch, ttrstrt, tp);
1.84 mycroft 2634: /* XXX: default to 1024 chars for now */
2635: clalloc(&tp->t_rawq, 1024, 1);
1.224 ad 2636: cv_init(&tp->t_rawcv, "ttyraw");
2637: cv_init(&tp->t_rawcvf, "ttyrawf");
1.84 mycroft 2638: clalloc(&tp->t_canq, 1024, 1);
1.224 ad 2639: cv_init(&tp->t_cancv, "ttycan");
2640: cv_init(&tp->t_cancvf, "ttycanf");
1.49 cgd 2641: /* output queue doesn't need quoting */
1.84 mycroft 2642: clalloc(&tp->t_outq, 1024, 0);
1.226 uebayasi 2643: cv_init(&tp->t_outcv, "ttyout");
2644: cv_init(&tp->t_outcvf, "ttyoutf");
1.121 eeh 2645: /* Set default line discipline. */
1.177 thorpej 2646: tp->t_linesw = ttyldisc_default();
1.198 ad 2647: selinit(&tp->t_rsel);
2648: selinit(&tp->t_wsel);
1.202 ad 2649: for (i = 0; i < TTYSIG_COUNT; i++)
2650: sigemptyset(&tp->t_sigs[i]);
1.138 enami 2651: return (tp);
1.49 cgd 2652: }
2653:
2654: /*
2655: * Free a tty structure and its buffers.
1.73 mrg 2656: *
2657: * Be sure to call tty_detach() for any tty that has been
2658: * tty_attach()ed.
1.49 cgd 2659: */
2660: void
1.126 lukem 2661: ttyfree(struct tty *tp)
1.49 cgd 2662: {
1.202 ad 2663: int i;
1.71 cgd 2664:
1.220 ad 2665: mutex_enter(proc_lock);
1.201 ad 2666: mutex_enter(&tty_lock);
1.202 ad 2667: for (i = 0; i < TTYSIG_COUNT; i++)
2668: sigemptyset(&tp->t_sigs[i]);
1.201 ad 2669: if (tp->t_sigcount != 0)
2670: TAILQ_REMOVE(&tty_sigqueue, tp, t_sigqueue);
2671: mutex_exit(&tty_lock);
1.220 ad 2672: mutex_exit(proc_lock);
1.201 ad 2673:
1.219 ad 2674: callout_halt(&tp->t_rstrt_ch, NULL);
1.216 ad 2675: callout_destroy(&tp->t_rstrt_ch);
1.177 thorpej 2676: ttyldisc_release(tp->t_linesw);
1.49 cgd 2677: clfree(&tp->t_rawq);
2678: clfree(&tp->t_canq);
2679: clfree(&tp->t_outq);
1.224 ad 2680: cv_destroy(&tp->t_rawcv);
2681: cv_destroy(&tp->t_rawcvf);
2682: cv_destroy(&tp->t_cancv);
2683: cv_destroy(&tp->t_cancvf);
2684: cv_destroy(&tp->t_outcv);
2685: cv_destroy(&tp->t_outcvf);
1.198 ad 2686: seldestroy(&tp->t_rsel);
2687: seldestroy(&tp->t_wsel);
1.216 ad 2688: kmem_free(tp, sizeof(*tp));
1.149 christos 2689: }
2690:
2691: /*
2692: * ttyprintf_nolock: send a message to a specific tty, without locking.
2693: *
2694: * => should be used only by tty driver or anything that knows the
2695: * underlying tty will not be revoked(2)'d away. [otherwise,
2696: * use tprintf]
2697: */
2698: static void
2699: ttyprintf_nolock(struct tty *tp, const char *fmt, ...)
2700: {
2701: va_list ap;
2702:
2703: /* No mutex needed; going to process TTY. */
2704: va_start(ap, fmt);
2705: kprintf(fmt, TOTTY|NOLOCK, tp, NULL, ap);
2706: va_end(ap);
1.49 cgd 2707: }
1.201 ad 2708:
2709: /*
2710: * Initialize the tty subsystem.
2711: */
2712: void
2713: tty_init(void)
2714: {
2715:
2716: mutex_init(&tty_lock, MUTEX_DEFAULT, IPL_VM);
2717: tty_sigsih = softint_establish(SOFTINT_CLOCK, ttysigintr, NULL);
2718: KASSERT(tty_sigsih != NULL);
2719: }
2720:
2721: /*
2722: * Send a signal from a tty to its process group or session leader.
2723: * Handoff to the target is deferred to a soft interrupt.
2724: */
2725: void
2726: ttysig(struct tty *tp, enum ttysigtype st, int sig)
2727: {
1.202 ad 2728: sigset_t *sp;
1.201 ad 2729:
2730: /* XXXSMP not yet KASSERT(mutex_owned(&tty_lock)); */
2731:
1.202 ad 2732: sp = &tp->t_sigs[st];
2733: if (sigismember(sp, sig))
2734: return;
2735: sigaddset(sp, sig);
2736: if (tp->t_sigcount++ == 0)
2737: TAILQ_INSERT_TAIL(&tty_sigqueue, tp, t_sigqueue);
1.201 ad 2738: softint_schedule(tty_sigsih);
2739: }
2740:
2741: /*
2742: * Deliver deferred signals from ttys. Note that the process groups
2743: * and sessions associated with the ttys may have changed from when
2744: * the signal was originally sent, but in practice it should not matter.
2745: * For signals produced as a result of a syscall, the soft interrupt
2746: * will fire before the syscall returns to the user.
2747: */
2748: static void
2749: ttysigintr(void *cookie)
2750: {
2751: struct tty *tp;
2752: enum ttysigtype st;
2753: struct pgrp *pgrp;
2754: struct session *sess;
1.215 ad 2755: int sig, lflag;
2756: char infobuf[200];
1.201 ad 2757:
1.220 ad 2758: mutex_enter(proc_lock);
1.215 ad 2759: mutex_spin_enter(&tty_lock);
2760: while ((tp = TAILQ_FIRST(&tty_sigqueue)) != NULL) {
1.201 ad 2761: KASSERT(tp->t_sigcount > 0);
1.202 ad 2762: for (st = 0; st < TTYSIG_COUNT; st++) {
2763: if ((sig = firstsig(&tp->t_sigs[st])) != 0)
2764: break;
1.201 ad 2765: }
1.202 ad 2766: KASSERT(st < TTYSIG_COUNT);
2767: sigdelset(&tp->t_sigs[st], sig);
1.201 ad 2768: if (--tp->t_sigcount == 0)
2769: TAILQ_REMOVE(&tty_sigqueue, tp, t_sigqueue);
2770: pgrp = tp->t_pgrp;
2771: sess = tp->t_session;
1.215 ad 2772: lflag = tp->t_lflag;
2773: if (sig == SIGINFO) {
2774: if (ISSET(tp->t_state, TS_SIGINFO)) {
2775: /* Via ioctl: ignore tty option. */
2776: tp->t_state &= ~TS_SIGINFO;
1.218 ad 2777: lflag |= ISIG;
1.215 ad 2778: }
2779: if (!ISSET(lflag, NOKERNINFO)) {
2780: mutex_spin_exit(&tty_lock);
2781: ttygetinfo(tp, 1, infobuf, sizeof(infobuf));
2782: mutex_spin_enter(&tty_lock);
2783: ttyputinfo(tp, infobuf);
2784: }
2785: if (!ISSET(lflag, ISIG))
2786: continue;
2787: }
1.201 ad 2788: mutex_spin_exit(&tty_lock);
1.215 ad 2789: KASSERT(sig != 0);
1.201 ad 2790: switch (st) {
2791: case TTYSIG_PG1:
2792: if (pgrp != NULL)
2793: pgsignal(pgrp, sig, 1);
2794: break;
2795: case TTYSIG_PG2:
1.203 ad 2796: if (pgrp != NULL)
2797: pgsignal(pgrp, sig, sess != NULL);
1.201 ad 2798: break;
2799: case TTYSIG_LEADER:
2800: if (sess != NULL && sess->s_leader != NULL)
2801: psignal(sess->s_leader, sig);
2802: break;
1.202 ad 2803: default:
2804: /* NOTREACHED */
2805: break;
1.201 ad 2806: }
1.215 ad 2807: mutex_spin_enter(&tty_lock);
1.201 ad 2808: }
1.215 ad 2809: mutex_spin_exit(&tty_lock);
1.220 ad 2810: mutex_exit(proc_lock);
1.201 ad 2811: }
CVSweb <webmaster@jp.NetBSD.org>