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