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