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