Deleted Added
full compact
tty.c (7469) tty.c (7470)
1/*-
2 * Copyright (c) 1982, 1986, 1990, 1991, 1993
3 * The Regents of the University of California. All rights reserved.
4 * (c) UNIX System Laboratories, Inc.
5 * All or some portions of this file are derived from material licensed
6 * to the University of California by American Telephone and Telegraph
7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8 * the permission of UNIX System Laboratories, Inc.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 * @(#)tty.c 8.8 (Berkeley) 1/21/94
1/*-
2 * Copyright (c) 1982, 1986, 1990, 1991, 1993
3 * The Regents of the University of California. All rights reserved.
4 * (c) UNIX System Laboratories, Inc.
5 * All or some portions of this file are derived from material licensed
6 * to the University of California by American Telephone and Telegraph
7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8 * the permission of UNIX System Laboratories, Inc.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 * @(#)tty.c 8.8 (Berkeley) 1/21/94
39 * $Id: tty.c,v 1.39 1995/03/29 18:55:20 ache Exp $
39 * $Id: tty.c,v 1.40 1995/03/29 19:22:37 ache Exp $
40 */
41
42#include "snp.h"
43
44#include <sys/param.h>
45#include <sys/systm.h>
46#include <sys/ioctl.h>
47#include <sys/proc.h>
48#define TTYDEFCHARS
49#include <sys/tty.h>
50#undef TTYDEFCHARS
51#include <sys/file.h>
52#include <sys/conf.h>
53#include <sys/dkstat.h>
54#include <sys/uio.h>
55#include <sys/kernel.h>
56#include <sys/vnode.h>
57#include <sys/syslog.h>
58#include <sys/signalvar.h>
59#include <sys/resourcevar.h>
60#include <sys/malloc.h>
61#if NSNP > 0
62#include <sys/snoop.h>
63#endif
64
65#include <vm/vm.h>
66
67
68static int proc_compare __P((struct proc *p1, struct proc *p2));
69static void ttyblock __P((struct tty *tp));
70static void ttyecho __P((int, struct tty *tp));
71static void ttyrubo __P((struct tty *, int));
72
73/* Symbolic sleep message strings. */
74char ttclos[] = "ttycls";
75char ttopen[] = "ttyopn";
76char ttybg[] = "ttybg";
77char ttybuf[] = "ttybuf";
78char ttyin[] = "ttyin";
79char ttyout[] = "ttyout";
80
81/*
82 * Table with character classes and parity. The 8th bit indicates parity,
83 * the 7th bit indicates the character is an alphameric or underscore (for
84 * ALTWERASE), and the low 6 bits indicate delay type. If the low 6 bits
85 * are 0 then the character needs no special processing on output; classes
86 * other than 0 might be translated or (not currently) require delays.
87 */
88#define E 0x00 /* Even parity. */
89#define O 0x80 /* Odd parity. */
90#define PARITY(c) (char_type[c] & O)
91
92#define ALPHA 0x40 /* Alpha or underscore. */
93#define ISALPHA(c) (char_type[(c) & TTY_CHARMASK] & ALPHA)
94
95#define CCLASSMASK 0x3f
96#define CCLASS(c) (char_type[c] & CCLASSMASK)
97
98#define BS BACKSPACE
99#define CC CONTROL
100#define CR RETURN
101#define NA ORDINARY | ALPHA
102#define NL NEWLINE
103#define NO ORDINARY
104#define TB TAB
105#define VT VTAB
106
107char const char_type[] = {
108 E|CC, O|CC, O|CC, E|CC, O|CC, E|CC, E|CC, O|CC, /* nul - bel */
109 O|BS, E|TB, E|NL, O|CC, E|VT, O|CR, O|CC, E|CC, /* bs - si */
110 O|CC, E|CC, E|CC, O|CC, E|CC, O|CC, O|CC, E|CC, /* dle - etb */
111 E|CC, O|CC, O|CC, E|CC, O|CC, E|CC, E|CC, O|CC, /* can - us */
112 O|NO, E|NO, E|NO, O|NO, E|NO, O|NO, O|NO, E|NO, /* sp - ' */
113 E|NO, O|NO, O|NO, E|NO, O|NO, E|NO, E|NO, O|NO, /* ( - / */
114 E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* 0 - 7 */
115 O|NA, E|NA, E|NO, O|NO, E|NO, O|NO, O|NO, E|NO, /* 8 - ? */
116 O|NO, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA, /* @ - G */
117 E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* H - O */
118 E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* P - W */
119 O|NA, E|NA, E|NA, O|NO, E|NO, O|NO, O|NO, O|NA, /* X - _ */
120 E|NO, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* ` - g */
121 O|NA, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA, /* h - o */
122 O|NA, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA, /* p - w */
123 E|NA, O|NA, O|NA, E|NO, O|NO, E|NO, E|NO, O|CC, /* x - del */
124 /*
125 * Meta chars; should be settable per character set;
126 * for now, treat them all as normal characters.
127 */
128 NA, NA, NA, NA, NA, NA, NA, NA,
129 NA, NA, NA, NA, NA, NA, NA, NA,
130 NA, NA, NA, NA, NA, NA, NA, NA,
131 NA, NA, NA, NA, NA, NA, NA, NA,
132 NA, NA, NA, NA, NA, NA, NA, NA,
133 NA, NA, NA, NA, NA, NA, NA, NA,
134 NA, NA, NA, NA, NA, NA, NA, NA,
135 NA, NA, NA, NA, NA, NA, NA, NA,
136 NA, NA, NA, NA, NA, NA, NA, NA,
137 NA, NA, NA, NA, NA, NA, NA, NA,
138 NA, NA, NA, NA, NA, NA, NA, NA,
139 NA, NA, NA, NA, NA, NA, NA, NA,
140 NA, NA, NA, NA, NA, NA, NA, NA,
141 NA, NA, NA, NA, NA, NA, NA, NA,
142 NA, NA, NA, NA, NA, NA, NA, NA,
143 NA, NA, NA, NA, NA, NA, NA, NA,
144};
145#undef BS
146#undef CC
147#undef CR
148#undef NA
149#undef NL
150#undef NO
151#undef TB
152#undef VT
153
154/* Macros to clear/set/test flags. */
155#define SET(t, f) (t) |= (f)
156#define CLR(t, f) (t) &= ~(f)
157#define ISSET(t, f) ((t) & (f))
158
159/*
160 * Initial open of tty, or (re)entry to standard tty line discipline.
161 */
162int
163ttyopen(device, tp)
164 dev_t device;
165 register struct tty *tp;
166{
167 int s;
168
169 s = spltty();
170 tp->t_dev = device;
171 if (!ISSET(tp->t_state, TS_ISOPEN)) {
172 SET(tp->t_state, TS_ISOPEN);
173 bzero(&tp->t_winsize, sizeof(tp->t_winsize));
174 }
175 CLR(tp->t_state, TS_WOPEN);
176
177 /*
178 * Initialize or restore a cblock allocation policy suitable for
179 * the standard line discipline.
180 */
181 clist_alloc_cblocks(&tp->t_canq, TTYHOG, 512);
182 clist_alloc_cblocks(&tp->t_outq, TTMAXHIWAT + 200, 512);
183 clist_alloc_cblocks(&tp->t_rawq, TTYHOG, TTYHOG);
184
185 splx(s);
186 return (0);
187}
188
189/*
190 * Handle close() on a tty line: flush and set to initial state,
191 * bumping generation number so that pending read/write calls
192 * can detect recycling of the tty.
193 */
194int
195ttyclose(tp)
196 register struct tty *tp;
197{
198 int s;
199
200 s = spltty();
201 if (constty == tp)
202 constty = NULL;
203
204 ttyflush(tp, FREAD | FWRITE);
205 clist_free_cblocks(&tp->t_canq);
206 clist_free_cblocks(&tp->t_outq);
207 clist_free_cblocks(&tp->t_rawq);
208
209#if NSNP > 0
210 if (ISSET(tp->t_state, TS_SNOOP) && tp->t_sc != NULL)
211 snpdown((struct snoop *)tp->t_sc);
212#endif
213
214 tp->t_gen++;
215 tp->t_pgrp = NULL;
216 tp->t_session = NULL;
217 tp->t_state = 0;
218 splx(s);
219 return (0);
220}
221
222#define FLUSHQ(q) { \
223 if ((q)->c_cc) \
224 ndflush(q, (q)->c_cc); \
225}
226
227/* Is 'c' a line delimiter ("break" character)? */
228#define TTBREAKC(c) \
229 ((c) == '\n' || (((c) == cc[VEOF] || \
230 (c) == cc[VEOL] || (c) == cc[VEOL2]) && (c) != _POSIX_VDISABLE))
231
232/*-
233 * TODO:
234 * o Fix races for sending the start char in ttyflush().
235 * o Handle inter-byte timeout for "MIN > 0, TIME > 0" in ttyselect().
236 * With luck, there will be MIN chars before select() returns().
237 * o Handle CLOCAL consistently for ptys. Perhaps disallow setting it.
238 * o Don't allow input in TS_ZOMBIE case. It would be visible through
239 * FIONREAD.
240 * o Do the new sio locking stuff here and use it to avoid special
241 * case for EXTPROC?
242 * o Lock PENDIN too?
243 * o Move EXTPROC and/or PENDIN to t_state?
244 * o Wrap most of ttioctl in spltty/splx.
245 * o Implement TIOCNOTTY or remove it from <sys/ioctl.h>.
246 */
247
248
249/*
250 * Process input of a single character received on a tty.
251 */
252int
253ttyinput(c, tp)
254 register int c;
255 register struct tty *tp;
256{
257 register int iflag, lflag;
258 register u_char *cc;
259 int i, err;
260
261 /*
262 * If input is pending take it first.
263 */
264 lflag = tp->t_lflag;
265 if (ISSET(lflag, PENDIN))
266 ttypend(tp);
267 /*
268 * Gather stats.
269 */
270 if (ISSET(lflag, ICANON)) {
271 ++tk_cancc;
272 ++tp->t_cancc;
273 } else {
274 ++tk_rawcc;
275 ++tp->t_rawcc;
276 }
277 ++tk_nin;
278
279 /* Handle exceptional conditions (break, parity, framing). */
280 cc = tp->t_cc;
281 iflag = tp->t_iflag;
282 err = (ISSET(c, TTY_ERRORMASK));
283 if (err) {
284 CLR(c, TTY_ERRORMASK);
40 */
41
42#include "snp.h"
43
44#include <sys/param.h>
45#include <sys/systm.h>
46#include <sys/ioctl.h>
47#include <sys/proc.h>
48#define TTYDEFCHARS
49#include <sys/tty.h>
50#undef TTYDEFCHARS
51#include <sys/file.h>
52#include <sys/conf.h>
53#include <sys/dkstat.h>
54#include <sys/uio.h>
55#include <sys/kernel.h>
56#include <sys/vnode.h>
57#include <sys/syslog.h>
58#include <sys/signalvar.h>
59#include <sys/resourcevar.h>
60#include <sys/malloc.h>
61#if NSNP > 0
62#include <sys/snoop.h>
63#endif
64
65#include <vm/vm.h>
66
67
68static int proc_compare __P((struct proc *p1, struct proc *p2));
69static void ttyblock __P((struct tty *tp));
70static void ttyecho __P((int, struct tty *tp));
71static void ttyrubo __P((struct tty *, int));
72
73/* Symbolic sleep message strings. */
74char ttclos[] = "ttycls";
75char ttopen[] = "ttyopn";
76char ttybg[] = "ttybg";
77char ttybuf[] = "ttybuf";
78char ttyin[] = "ttyin";
79char ttyout[] = "ttyout";
80
81/*
82 * Table with character classes and parity. The 8th bit indicates parity,
83 * the 7th bit indicates the character is an alphameric or underscore (for
84 * ALTWERASE), and the low 6 bits indicate delay type. If the low 6 bits
85 * are 0 then the character needs no special processing on output; classes
86 * other than 0 might be translated or (not currently) require delays.
87 */
88#define E 0x00 /* Even parity. */
89#define O 0x80 /* Odd parity. */
90#define PARITY(c) (char_type[c] & O)
91
92#define ALPHA 0x40 /* Alpha or underscore. */
93#define ISALPHA(c) (char_type[(c) & TTY_CHARMASK] & ALPHA)
94
95#define CCLASSMASK 0x3f
96#define CCLASS(c) (char_type[c] & CCLASSMASK)
97
98#define BS BACKSPACE
99#define CC CONTROL
100#define CR RETURN
101#define NA ORDINARY | ALPHA
102#define NL NEWLINE
103#define NO ORDINARY
104#define TB TAB
105#define VT VTAB
106
107char const char_type[] = {
108 E|CC, O|CC, O|CC, E|CC, O|CC, E|CC, E|CC, O|CC, /* nul - bel */
109 O|BS, E|TB, E|NL, O|CC, E|VT, O|CR, O|CC, E|CC, /* bs - si */
110 O|CC, E|CC, E|CC, O|CC, E|CC, O|CC, O|CC, E|CC, /* dle - etb */
111 E|CC, O|CC, O|CC, E|CC, O|CC, E|CC, E|CC, O|CC, /* can - us */
112 O|NO, E|NO, E|NO, O|NO, E|NO, O|NO, O|NO, E|NO, /* sp - ' */
113 E|NO, O|NO, O|NO, E|NO, O|NO, E|NO, E|NO, O|NO, /* ( - / */
114 E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* 0 - 7 */
115 O|NA, E|NA, E|NO, O|NO, E|NO, O|NO, O|NO, E|NO, /* 8 - ? */
116 O|NO, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA, /* @ - G */
117 E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* H - O */
118 E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* P - W */
119 O|NA, E|NA, E|NA, O|NO, E|NO, O|NO, O|NO, O|NA, /* X - _ */
120 E|NO, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* ` - g */
121 O|NA, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA, /* h - o */
122 O|NA, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA, /* p - w */
123 E|NA, O|NA, O|NA, E|NO, O|NO, E|NO, E|NO, O|CC, /* x - del */
124 /*
125 * Meta chars; should be settable per character set;
126 * for now, treat them all as normal characters.
127 */
128 NA, NA, NA, NA, NA, NA, NA, NA,
129 NA, NA, NA, NA, NA, NA, NA, NA,
130 NA, NA, NA, NA, NA, NA, NA, NA,
131 NA, NA, NA, NA, NA, NA, NA, NA,
132 NA, NA, NA, NA, NA, NA, NA, NA,
133 NA, NA, NA, NA, NA, NA, NA, NA,
134 NA, NA, NA, NA, NA, NA, NA, NA,
135 NA, NA, NA, NA, NA, NA, NA, NA,
136 NA, NA, NA, NA, NA, NA, NA, NA,
137 NA, NA, NA, NA, NA, NA, NA, NA,
138 NA, NA, NA, NA, NA, NA, NA, NA,
139 NA, NA, NA, NA, NA, NA, NA, NA,
140 NA, NA, NA, NA, NA, NA, NA, NA,
141 NA, NA, NA, NA, NA, NA, NA, NA,
142 NA, NA, NA, NA, NA, NA, NA, NA,
143 NA, NA, NA, NA, NA, NA, NA, NA,
144};
145#undef BS
146#undef CC
147#undef CR
148#undef NA
149#undef NL
150#undef NO
151#undef TB
152#undef VT
153
154/* Macros to clear/set/test flags. */
155#define SET(t, f) (t) |= (f)
156#define CLR(t, f) (t) &= ~(f)
157#define ISSET(t, f) ((t) & (f))
158
159/*
160 * Initial open of tty, or (re)entry to standard tty line discipline.
161 */
162int
163ttyopen(device, tp)
164 dev_t device;
165 register struct tty *tp;
166{
167 int s;
168
169 s = spltty();
170 tp->t_dev = device;
171 if (!ISSET(tp->t_state, TS_ISOPEN)) {
172 SET(tp->t_state, TS_ISOPEN);
173 bzero(&tp->t_winsize, sizeof(tp->t_winsize));
174 }
175 CLR(tp->t_state, TS_WOPEN);
176
177 /*
178 * Initialize or restore a cblock allocation policy suitable for
179 * the standard line discipline.
180 */
181 clist_alloc_cblocks(&tp->t_canq, TTYHOG, 512);
182 clist_alloc_cblocks(&tp->t_outq, TTMAXHIWAT + 200, 512);
183 clist_alloc_cblocks(&tp->t_rawq, TTYHOG, TTYHOG);
184
185 splx(s);
186 return (0);
187}
188
189/*
190 * Handle close() on a tty line: flush and set to initial state,
191 * bumping generation number so that pending read/write calls
192 * can detect recycling of the tty.
193 */
194int
195ttyclose(tp)
196 register struct tty *tp;
197{
198 int s;
199
200 s = spltty();
201 if (constty == tp)
202 constty = NULL;
203
204 ttyflush(tp, FREAD | FWRITE);
205 clist_free_cblocks(&tp->t_canq);
206 clist_free_cblocks(&tp->t_outq);
207 clist_free_cblocks(&tp->t_rawq);
208
209#if NSNP > 0
210 if (ISSET(tp->t_state, TS_SNOOP) && tp->t_sc != NULL)
211 snpdown((struct snoop *)tp->t_sc);
212#endif
213
214 tp->t_gen++;
215 tp->t_pgrp = NULL;
216 tp->t_session = NULL;
217 tp->t_state = 0;
218 splx(s);
219 return (0);
220}
221
222#define FLUSHQ(q) { \
223 if ((q)->c_cc) \
224 ndflush(q, (q)->c_cc); \
225}
226
227/* Is 'c' a line delimiter ("break" character)? */
228#define TTBREAKC(c) \
229 ((c) == '\n' || (((c) == cc[VEOF] || \
230 (c) == cc[VEOL] || (c) == cc[VEOL2]) && (c) != _POSIX_VDISABLE))
231
232/*-
233 * TODO:
234 * o Fix races for sending the start char in ttyflush().
235 * o Handle inter-byte timeout for "MIN > 0, TIME > 0" in ttyselect().
236 * With luck, there will be MIN chars before select() returns().
237 * o Handle CLOCAL consistently for ptys. Perhaps disallow setting it.
238 * o Don't allow input in TS_ZOMBIE case. It would be visible through
239 * FIONREAD.
240 * o Do the new sio locking stuff here and use it to avoid special
241 * case for EXTPROC?
242 * o Lock PENDIN too?
243 * o Move EXTPROC and/or PENDIN to t_state?
244 * o Wrap most of ttioctl in spltty/splx.
245 * o Implement TIOCNOTTY or remove it from <sys/ioctl.h>.
246 */
247
248
249/*
250 * Process input of a single character received on a tty.
251 */
252int
253ttyinput(c, tp)
254 register int c;
255 register struct tty *tp;
256{
257 register int iflag, lflag;
258 register u_char *cc;
259 int i, err;
260
261 /*
262 * If input is pending take it first.
263 */
264 lflag = tp->t_lflag;
265 if (ISSET(lflag, PENDIN))
266 ttypend(tp);
267 /*
268 * Gather stats.
269 */
270 if (ISSET(lflag, ICANON)) {
271 ++tk_cancc;
272 ++tp->t_cancc;
273 } else {
274 ++tk_rawcc;
275 ++tp->t_rawcc;
276 }
277 ++tk_nin;
278
279 /* Handle exceptional conditions (break, parity, framing). */
280 cc = tp->t_cc;
281 iflag = tp->t_iflag;
282 err = (ISSET(c, TTY_ERRORMASK));
283 if (err) {
284 CLR(c, TTY_ERRORMASK);
285 if (ISSET(err, TTY_BI) { /* Break. */
285 if (ISSET(err, TTY_BI)) { /* Break. */
286 if (ISSET(iflag, IGNBRK))
287 return (0);
288 else if (ISSET(iflag, BRKINT) &&
289 ISSET(lflag, ISIG) &&
290 (cc[VINTR] != _POSIX_VDISABLE))
291 c = cc[VINTR];
292 else if (ISSET(iflag, PARMRK))
293 goto parmrk;
294 } else if ((ISSET(err, TTY_PE) && ISSET(iflag, INPCK))
295 || ISSET(err, TTY_FE)) {
296 if (ISSET(iflag, IGNPAR))
297 return (0);
298 else if (ISSET(iflag, PARMRK)) {
299parmrk: (void)putc(0377 | TTY_QUOTE, &tp->t_rawq);
300 (void)putc(0 | TTY_QUOTE, &tp->t_rawq);
301 (void)putc(c | TTY_QUOTE, &tp->t_rawq);
302 goto endcase;
303 } else
304 c = 0;
305 }
306 }
307 /*
308 * In tandem mode, check high water mark.
309 */
310 if (ISSET(iflag, IXOFF) || ISSET(tp->t_cflag, CRTS_IFLOW))
311 ttyblock(tp);
312 if (!ISSET(tp->t_state, TS_TYPEN) && ISSET(iflag, ISTRIP))
313 CLR(c, 0x80);
314 if (!ISSET(lflag, EXTPROC)) {
315 /*
316 * Check for literal nexting very first
317 */
318 if (ISSET(tp->t_state, TS_LNCH)) {
319 SET(c, TTY_QUOTE);
320 CLR(tp->t_state, TS_LNCH);
321 }
322 /*
323 * Scan for special characters. This code
324 * is really just a big case statement with
325 * non-constant cases. The bottom of the
326 * case statement is labeled ``endcase'', so goto
327 * it after a case match, or similar.
328 */
329
330 /*
331 * Control chars which aren't controlled
332 * by ICANON, ISIG, or IXON.
333 */
334 if (ISSET(lflag, IEXTEN)) {
335 if (CCEQ(cc[VLNEXT], c)) {
336 if (ISSET(lflag, ECHO)) {
337 if (ISSET(lflag, ECHOE)) {
338 (void)ttyoutput('^', tp);
339 (void)ttyoutput('\b', tp);
340 } else
341 ttyecho(c, tp);
342 }
343 SET(tp->t_state, TS_LNCH);
344 goto endcase;
345 }
346 if (CCEQ(cc[VDISCARD], c)) {
347 if (ISSET(lflag, FLUSHO))
348 CLR(tp->t_lflag, FLUSHO);
349 else {
350 ttyflush(tp, FWRITE);
351 ttyecho(c, tp);
352 if (tp->t_rawq.c_cc + tp->t_canq.c_cc)
353 ttyretype(tp);
354 SET(tp->t_lflag, FLUSHO);
355 }
356 goto startoutput;
357 }
358 }
359 /*
360 * Signals.
361 */
362 if (ISSET(lflag, ISIG)) {
363 if (CCEQ(cc[VINTR], c) || CCEQ(cc[VQUIT], c)) {
364 if (!ISSET(lflag, NOFLSH))
365 ttyflush(tp, FREAD | FWRITE);
366 ttyecho(c, tp);
367 pgsignal(tp->t_pgrp,
368 CCEQ(cc[VINTR], c) ? SIGINT : SIGQUIT, 1);
369 goto endcase;
370 }
371 if (CCEQ(cc[VSUSP], c)) {
372 if (!ISSET(lflag, NOFLSH))
373 ttyflush(tp, FREAD);
374 ttyecho(c, tp);
375 pgsignal(tp->t_pgrp, SIGTSTP, 1);
376 goto endcase;
377 }
378 }
379 /*
380 * Handle start/stop characters.
381 */
382 if (ISSET(iflag, IXON)) {
383 if (CCEQ(cc[VSTOP], c)) {
384 if (!ISSET(tp->t_state, TS_TTSTOP)) {
385 SET(tp->t_state, TS_TTSTOP);
386#ifdef sun4c /* XXX */
387 (*tp->t_stop)(tp, 0);
388#else
389 (*cdevsw[major(tp->t_dev)].d_stop)(tp,
390 0);
391#endif
392 return (0);
393 }
394 if (!CCEQ(cc[VSTART], c))
395 return (0);
396 /*
397 * if VSTART == VSTOP then toggle
398 */
399 goto endcase;
400 }
401 if (CCEQ(cc[VSTART], c))
402 goto restartoutput;
403 }
404 /*
405 * IGNCR, ICRNL, & INLCR
406 */
407 if (c == '\r') {
408 if (ISSET(iflag, IGNCR))
409 return (0);
410 else if (ISSET(iflag, ICRNL))
411 c = '\n';
412 } else if (c == '\n' && ISSET(iflag, INLCR))
413 c = '\r';
414 }
415 if (!ISSET(tp->t_lflag, EXTPROC) && ISSET(lflag, ICANON)) {
416 /*
417 * From here on down canonical mode character
418 * processing takes place.
419 */
420 /*
421 * erase (^H / ^?)
422 */
423 if (CCEQ(cc[VERASE], c)) {
424 if (tp->t_rawq.c_cc)
425 ttyrub(unputc(&tp->t_rawq), tp);
426 goto endcase;
427 }
428 /*
429 * kill (^U)
430 */
431 if (CCEQ(cc[VKILL], c)) {
432 if (ISSET(lflag, ECHOKE) &&
433 tp->t_rawq.c_cc == tp->t_rocount &&
434 !ISSET(lflag, ECHOPRT))
435 while (tp->t_rawq.c_cc)
436 ttyrub(unputc(&tp->t_rawq), tp);
437 else {
438 ttyecho(c, tp);
439 if (ISSET(lflag, ECHOK) ||
440 ISSET(lflag, ECHOKE))
441 ttyecho('\n', tp);
442 FLUSHQ(&tp->t_rawq);
443 tp->t_rocount = 0;
444 }
445 CLR(tp->t_state, TS_LOCAL);
446 goto endcase;
447 }
448 /*
449 * word erase (^W)
450 */
451 if (CCEQ(cc[VWERASE], c)) {
452 int alt = ISSET(lflag, ALTWERASE);
453 int ctype;
454
455 /*
456 * erase whitespace
457 */
458 while ((c = unputc(&tp->t_rawq)) == ' ' || c == '\t')
459 ttyrub(c, tp);
460 if (c == -1)
461 goto endcase;
462 /*
463 * erase last char of word and remember the
464 * next chars type (for ALTWERASE)
465 */
466 ttyrub(c, tp);
467 c = unputc(&tp->t_rawq);
468 if (c == -1)
469 goto endcase;
470 if (c == ' ' || c == '\t') {
471 (void)putc(c, &tp->t_rawq);
472 goto endcase;
473 }
474 ctype = ISALPHA(c);
475 /*
476 * erase rest of word
477 */
478 do {
479 ttyrub(c, tp);
480 c = unputc(&tp->t_rawq);
481 if (c == -1)
482 goto endcase;
483 } while (c != ' ' && c != '\t' &&
484 (alt == 0 || ISALPHA(c) == ctype));
485 (void)putc(c, &tp->t_rawq);
486 goto endcase;
487 }
488 /*
489 * reprint line (^R)
490 */
491 if (CCEQ(cc[VREPRINT], c)) {
492 ttyretype(tp);
493 goto endcase;
494 }
495 /*
496 * ^T - kernel info and generate SIGINFO
497 */
498 if (CCEQ(cc[VSTATUS], c)) {
499 if (ISSET(lflag, ISIG))
500 pgsignal(tp->t_pgrp, SIGINFO, 1);
501 if (!ISSET(lflag, NOKERNINFO))
502 ttyinfo(tp);
503 goto endcase;
504 }
505 }
506 /*
507 * Check for input buffer overflow
508 */
509 if (tp->t_rawq.c_cc + tp->t_canq.c_cc >= TTYHOG) {
510 if (ISSET(iflag, IMAXBEL)) {
511 if (tp->t_outq.c_cc < tp->t_hiwat)
512 (void)ttyoutput(CTRL('g'), tp);
513 }
514 goto endcase;
515 }
516
517 if ( c == 0377 && ISSET(iflag, PARMRK) && !ISSET(iflag, ISTRIP)
518 && ISSET(iflag, IGNBRK|IGNPAR) != (IGNBRK|IGNPAR))
519 (void)putc(0377 | TTY_QUOTE, &tp->t_rawq);
520
521 /*
522 * Put data char in q for user and
523 * wakeup on seeing a line delimiter.
524 */
525 if (putc(c, &tp->t_rawq) >= 0) {
526 if (!ISSET(lflag, ICANON)) {
527 ttwakeup(tp);
528 ttyecho(c, tp);
529 goto endcase;
530 }
531 if (TTBREAKC(c)) {
532 tp->t_rocount = 0;
533 catq(&tp->t_rawq, &tp->t_canq);
534 ttwakeup(tp);
535 } else if (tp->t_rocount++ == 0)
536 tp->t_rocol = tp->t_column;
537 if (ISSET(tp->t_state, TS_ERASE)) {
538 /*
539 * end of prterase \.../
540 */
541 CLR(tp->t_state, TS_ERASE);
542 (void)ttyoutput('/', tp);
543 }
544 i = tp->t_column;
545 ttyecho(c, tp);
546 if (CCEQ(cc[VEOF], c) && ISSET(lflag, ECHO)) {
547 /*
548 * Place the cursor over the '^' of the ^D.
549 */
550 i = min(2, tp->t_column - i);
551 while (i > 0) {
552 (void)ttyoutput('\b', tp);
553 i--;
554 }
555 }
556 }
557endcase:
558 /*
559 * IXANY means allow any character to restart output.
560 */
561 if (ISSET(tp->t_state, TS_TTSTOP) &&
562 !ISSET(iflag, IXANY) && cc[VSTART] != cc[VSTOP])
563 return (0);
564restartoutput:
565 CLR(tp->t_lflag, FLUSHO);
566 CLR(tp->t_state, TS_TTSTOP);
567startoutput:
568 return (ttstart(tp));
569}
570
571/*
572 * Output a single character on a tty, doing output processing
573 * as needed (expanding tabs, newline processing, etc.).
574 * Returns < 0 if succeeds, otherwise returns char to resend.
575 * Must be recursive.
576 */
577int
578ttyoutput(c, tp)
579 register int c;
580 register struct tty *tp;
581{
582 register long oflag;
583 register int col, s;
584
585 oflag = tp->t_oflag;
586 if (!ISSET(oflag, OPOST)) {
587 if (ISSET(tp->t_lflag, FLUSHO))
588 return (-1);
589 if (putc(c, &tp->t_outq))
590 return (c);
591 tk_nout++;
592 tp->t_outcc++;
593 return (-1);
594 }
595 /*
596 * Do tab expansion if OXTABS is set. Special case if we external
597 * processing, we don't do the tab expansion because we'll probably
598 * get it wrong. If tab expansion needs to be done, let it happen
599 * externally.
600 */
601 CLR(c, ~TTY_CHARMASK);
602 if (c == '\t' &&
603 ISSET(oflag, OXTABS) && !ISSET(tp->t_lflag, EXTPROC)) {
604 c = 8 - (tp->t_column & 7);
605 if (!ISSET(tp->t_lflag, FLUSHO)) {
606 s = spltty(); /* Don't interrupt tabs. */
607 c -= b_to_q(" ", c, &tp->t_outq);
608 tk_nout += c;
609 tp->t_outcc += c;
610 splx(s);
611 }
612 tp->t_column += c;
613 return (c ? -1 : '\t');
614 }
615 if (c == CEOT && ISSET(oflag, ONOEOT))
616 return (-1);
617
618 /*
619 * Newline translation: if ONLCR is set,
620 * translate newline into "\r\n".
621 */
622 if (c == '\n' && ISSET(tp->t_oflag, ONLCR)) {
623 tk_nout++;
624 tp->t_outcc++;
625 if (putc('\r', &tp->t_outq))
626 return (c);
627 }
628 tk_nout++;
629 tp->t_outcc++;
630 if (!ISSET(tp->t_lflag, FLUSHO) && putc(c, &tp->t_outq))
631 return (c);
632
633 col = tp->t_column;
634 switch (CCLASS(c)) {
635 case BACKSPACE:
636 if (col > 0)
637 --col;
638 break;
639 case CONTROL:
640 break;
641 case NEWLINE:
642 case RETURN:
643 col = 0;
644 break;
645 case ORDINARY:
646 ++col;
647 break;
648 case TAB:
649 col = (col + 8) & ~7;
650 break;
651 }
652 tp->t_column = col;
653 return (-1);
654}
655
656/*
657 * Ioctls for all tty devices. Called after line-discipline specific ioctl
658 * has been called to do discipline-specific functions and/or reject any
659 * of these ioctl commands.
660 */
661/* ARGSUSED */
662int
663ttioctl(tp, cmd, data, flag)
664 register struct tty *tp;
665 int cmd, flag;
666 void *data;
667{
668 register struct proc *p;
669 int s, error;
670
671 p = curproc; /* XXX */
672
673 /* If the ioctl involves modification, hang if in the background. */
674 switch (cmd) {
675 case TIOCFLUSH:
676 case TIOCSETA:
677 case TIOCSETD:
678 case TIOCSETAF:
679 case TIOCSETAW:
680#ifdef notdef
681 case TIOCSPGRP:
682#endif
683 case TIOCSTAT:
684 case TIOCSTI:
685 case TIOCSWINSZ:
686#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
687 case TIOCLBIC:
688 case TIOCLBIS:
689 case TIOCLSET:
690 case TIOCSETC:
691 case OTIOCSETD:
692 case TIOCSETN:
693 case TIOCSETP:
694 case TIOCSLTC:
695#endif
696 while (isbackground(curproc, tp) &&
697 p->p_pgrp->pg_jobc && (p->p_flag & P_PPWAIT) == 0 &&
698 (p->p_sigignore & sigmask(SIGTTOU)) == 0 &&
699 (p->p_sigmask & sigmask(SIGTTOU)) == 0) {
700 pgsignal(p->p_pgrp, SIGTTOU, 1);
701 error = ttysleep(tp, &lbolt, TTOPRI | PCATCH, ttybg, 0);
702 if (error)
703 return (error);
704 }
705 break;
706 }
707
708 switch (cmd) { /* Process the ioctl. */
709 case FIOASYNC: /* set/clear async i/o */
710 s = spltty();
711 if (*(int *)data)
712 SET(tp->t_state, TS_ASYNC);
713 else
714 CLR(tp->t_state, TS_ASYNC);
715 splx(s);
716 break;
717 case FIONBIO: /* set/clear non-blocking i/o */
718 break; /* XXX: delete. */
719 case FIONREAD: /* get # bytes to read */
720 *(int *)data = ttnread(tp);
721 break;
722 case TIOCEXCL: /* set exclusive use of tty */
723 s = spltty();
724 SET(tp->t_state, TS_XCLUDE);
725 splx(s);
726 break;
727 case TIOCFLUSH: { /* flush buffers */
728 register int flags = *(int *)data;
729
730 if (flags == 0)
731 flags = FREAD | FWRITE;
732 else
733 flags &= FREAD | FWRITE;
734 ttyflush(tp, flags);
735 break;
736 }
737 case TIOCCONS: /* become virtual console */
738 if (*(int *)data) {
739 if (constty && constty != tp &&
740 ISSET(constty->t_state, TS_CARR_ON | TS_ISOPEN) ==
741 (TS_CARR_ON | TS_ISOPEN))
742 return (EBUSY);
743#ifndef UCONSOLE
744 if (error = suser(p->p_ucred, &p->p_acflag))
745 return (error);
746#endif
747 constty = tp;
748 } else if (tp == constty)
749 constty = NULL;
750 break;
751 case TIOCDRAIN: /* wait till output drained */
752 error = ttywait(tp);
753 if (error)
754 return (error);
755 break;
756 case TIOCGETA: { /* get termios struct */
757 struct termios *t = (struct termios *)data;
758
759 bcopy(&tp->t_termios, t, sizeof(struct termios));
760 break;
761 }
762 case TIOCGETD: /* get line discipline */
763 *(int *)data = tp->t_line;
764 break;
765 case TIOCGWINSZ: /* get window size */
766 *(struct winsize *)data = tp->t_winsize;
767 break;
768 case TIOCGPGRP: /* get pgrp of tty */
769 if (!isctty(p, tp))
770 return (ENOTTY);
771 *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
772 break;
773#ifdef TIOCHPCL
774 case TIOCHPCL: /* hang up on last close */
775 s = spltty();
776 SET(tp->t_cflag, HUPCL);
777 splx(s);
778 break;
779#endif
780 case TIOCNXCL: /* reset exclusive use of tty */
781 s = spltty();
782 CLR(tp->t_state, TS_XCLUDE);
783 splx(s);
784 break;
785 case TIOCOUTQ: /* output queue size */
786 *(int *)data = tp->t_outq.c_cc;
787 break;
788 case TIOCSETA: /* set termios struct */
789 case TIOCSETAW: /* drain output, set */
790 case TIOCSETAF: { /* drn out, fls in, set */
791 register struct termios *t = (struct termios *)data;
792
793 s = spltty();
794 if (cmd == TIOCSETAW || cmd == TIOCSETAF) {
795 error = ttywait(tp);
796 if (error) {
797 splx(s);
798 return (error);
799 }
800 if (cmd == TIOCSETAF)
801 ttyflush(tp, FREAD);
802 }
803 if (!ISSET(t->c_cflag, CIGNORE)) {
804 /*
805 * Set device hardware.
806 */
807 if (tp->t_param && (error = (*tp->t_param)(tp, t))) {
808 splx(s);
809 return (error);
810 } else {
811 if (!ISSET(tp->t_state, TS_CARR_ON) &&
812 ISSET(tp->t_cflag, CLOCAL) &&
813 !ISSET(t->c_cflag, CLOCAL)) {
814#if 0
815 CLR(tp->t_state, TS_ISOPEN);
816 SET(tp->t_state, TS_WOPEN);
817#endif
818 ttwakeup(tp);
819 }
820 tp->t_cflag = t->c_cflag;
821 tp->t_ispeed = t->c_ispeed;
822 tp->t_ospeed = t->c_ospeed;
823 }
824 ttsetwater(tp);
825 }
826 if (cmd != TIOCSETAF) {
827 if (ISSET(t->c_lflag, ICANON) !=
828 ISSET(tp->t_lflag, ICANON))
829 if (ISSET(t->c_lflag, ICANON)) {
830 SET(tp->t_lflag, PENDIN);
831 ttwakeup(tp);
832 } else {
833 struct clist tq;
834
835 catq(&tp->t_rawq, &tp->t_canq);
836 tq = tp->t_rawq;
837 tp->t_rawq = tp->t_canq;
838 tp->t_canq = tq;
839 CLR(tp->t_lflag, PENDIN);
840 }
841 }
842 tp->t_iflag = t->c_iflag;
843 tp->t_oflag = t->c_oflag;
844 /*
845 * Make the EXTPROC bit read only.
846 */
847 if (ISSET(tp->t_lflag, EXTPROC))
848 SET(t->c_lflag, EXTPROC);
849 else
850 CLR(t->c_lflag, EXTPROC);
851 tp->t_lflag = t->c_lflag | ISSET(tp->t_lflag, PENDIN);
852 if (t->c_cc[VMIN] != tp->t_cc[VMIN] ||
853 t->c_cc[VTIME] != tp->t_cc[VTIME])
854 ttwakeup(tp);
855 bcopy(t->c_cc, tp->t_cc, sizeof(t->c_cc));
856 splx(s);
857 break;
858 }
859 case TIOCSETD: { /* set line discipline */
860 register int t = *(int *)data;
861 dev_t device = tp->t_dev;
862
863 if ((u_int)t >= nlinesw)
864 return (ENXIO);
865 if (t != tp->t_line) {
866 s = spltty();
867 (*linesw[tp->t_line].l_close)(tp, flag);
868 error = (*linesw[t].l_open)(device, tp);
869 if (error) {
870 (void)(*linesw[tp->t_line].l_open)(device, tp);
871 splx(s);
872 return (error);
873 }
874 tp->t_line = t;
875 splx(s);
876 }
877 break;
878 }
879 case TIOCSTART: /* start output, like ^Q */
880 s = spltty();
881 if (ISSET(tp->t_state, TS_TTSTOP) ||
882 ISSET(tp->t_lflag, FLUSHO)) {
883 CLR(tp->t_lflag, FLUSHO);
884 CLR(tp->t_state, TS_TTSTOP);
885 ttstart(tp);
886 }
887 splx(s);
888 break;
889 case TIOCSTI: /* simulate terminal input */
890 if (p->p_ucred->cr_uid && (flag & FREAD) == 0)
891 return (EPERM);
892 if (p->p_ucred->cr_uid && !isctty(p, tp))
893 return (EACCES);
894 (*linesw[tp->t_line].l_rint)(*(u_char *)data, tp);
895 break;
896 case TIOCSTOP: /* stop output, like ^S */
897 s = spltty();
898 if (!ISSET(tp->t_state, TS_TTSTOP)) {
899 SET(tp->t_state, TS_TTSTOP);
900#ifdef sun4c /* XXX */
901 (*tp->t_stop)(tp, 0);
902#else
903 (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
904#endif
905 }
906 splx(s);
907 break;
908 case TIOCSCTTY: /* become controlling tty */
909 /* Session ctty vnode pointer set in vnode layer. */
910 if (!SESS_LEADER(p) ||
911 ((p->p_session->s_ttyvp || tp->t_session) &&
912 (tp->t_session != p->p_session)))
913 return (EPERM);
914 tp->t_session = p->p_session;
915 tp->t_pgrp = p->p_pgrp;
916 p->p_session->s_ttyp = tp;
917 p->p_flag |= P_CONTROLT;
918 break;
919 case TIOCSPGRP: { /* set pgrp of tty */
920 register struct pgrp *pgrp = pgfind(*(int *)data);
921
922 if (!isctty(p, tp))
923 return (ENOTTY);
924 else if (pgrp == NULL || pgrp->pg_session != p->p_session)
925 return (EPERM);
926 tp->t_pgrp = pgrp;
927 break;
928 }
929 case TIOCSTAT: /* simulate control-T */
930 ttyinfo(tp);
931 break;
932 case TIOCSWINSZ: /* set window size */
933 if (bcmp((caddr_t)&tp->t_winsize, data,
934 sizeof (struct winsize))) {
935 tp->t_winsize = *(struct winsize *)data;
936 pgsignal(tp->t_pgrp, SIGWINCH, 1);
937 }
938 break;
939 case TIOCSDRAINWAIT:
940 error = suser(p->p_ucred, &p->p_acflag);
941 if (error)
942 return (error);
943 tp->t_timeout = *(int *)data * hz;
944 wakeup((caddr_t)&tp->t_outq);
945 break;
946 case TIOCGDRAINWAIT:
947 *(int *)data = tp->t_timeout / hz;
948 break;
949 default:
950#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
951 return (ttcompat(tp, cmd, data, flag));
952#else
953 return (-1);
954#endif
955 }
956 return (0);
957}
958
959int
960ttyselect(tp, rw, p)
961 struct tty *tp;
962 int rw;
963 struct proc *p;
964{
965 int nread, s;
966
967 if (tp == NULL)
968 return (ENXIO);
969
970 s = spltty();
971 switch (rw) {
972 case FREAD:
973 nread = ttnread(tp);
974 if (nread > 0 || (!ISSET(tp->t_cflag, CLOCAL) &&
975 !ISSET(tp->t_state, TS_CARR_ON)))
976 goto win;
977 selrecord(p, &tp->t_rsel);
978 break;
979 case FWRITE:
980 if (tp->t_outq.c_cc <= tp->t_lowat) {
981win: splx(s);
982 return (1);
983 }
984 selrecord(p, &tp->t_wsel);
985 break;
986 }
987 splx(s);
988 return (0);
989}
990
991/*
992 * This is a wrapper for compatibility with the select vector used by
993 * cdevsw. It relies on a proper xxxdevtotty routine.
994 */
995int
996ttselect(dev, rw, p)
997 dev_t dev;
998 int rw;
999 struct proc *p;
1000{
1001 return ttyselect((*cdevsw[major(dev)].d_devtotty)(dev), rw, p);
1002}
1003
1004/*
1005 * This is now exported to the cy driver as well; if you hack this code,
1006 * then be sure to keep /sys/i386/isa/cy.c properly advised! -jkh
1007 */
1008int
1009ttnread(tp)
1010 struct tty *tp;
1011{
1012 int nread;
1013
1014 if (ISSET(tp->t_lflag, PENDIN))
1015 ttypend(tp);
1016 nread = tp->t_canq.c_cc;
1017 if (!ISSET(tp->t_lflag, ICANON)) {
1018 nread += tp->t_rawq.c_cc;
1019 if (nread < tp->t_cc[VMIN] && tp->t_cc[VTIME] == 0)
1020 nread = 0;
1021 }
1022 return (nread);
1023}
1024
1025/*
1026 * Wait for output to drain.
1027 */
1028int
1029ttywait(tp)
1030 register struct tty *tp;
1031{
1032 int error, s;
1033
1034 error = 0;
1035 s = spltty();
1036 while ((tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)) &&
1037 (ISSET(tp->t_state, TS_CARR_ON) || ISSET(tp->t_cflag, CLOCAL))
1038 && tp->t_oproc) {
1039 (*tp->t_oproc)(tp);
1040 if ((tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)) &&
1041 (ISSET(tp->t_state, TS_CARR_ON) || ISSET(tp->t_cflag, CLOCAL))) {
1042 SET(tp->t_state, TS_ASLEEP);
1043 error = ttysleep(tp, &tp->t_outq, TTOPRI | PCATCH,
1044 ttyout, tp->t_timeout);
1045 if (error)
1046 break;
1047 }
1048 }
1049 if (!error && (tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)))
1050 error = EIO;
1051 splx(s);
1052 return (error);
1053}
1054
1055/*
1056 * Flush if successfully wait.
1057 */
1058int
1059ttywflush(tp)
1060 struct tty *tp;
1061{
1062 int error;
1063
1064 if ((error = ttywait(tp)) == 0)
1065 ttyflush(tp, FREAD);
1066 return (error);
1067}
1068
1069/*
1070 * Flush tty read and/or write queues, notifying anyone waiting.
1071 */
1072void
1073ttyflush(tp, rw)
1074 register struct tty *tp;
1075 int rw;
1076{
1077 register int s;
1078
1079 s = spltty();
1080 if (rw & FWRITE)
1081 CLR(tp->t_state, TS_TTSTOP);
1082#ifdef sun4c /* XXX */
1083 (*tp->t_stop)(tp, rw);
1084#else
1085 (*cdevsw[major(tp->t_dev)].d_stop)(tp, rw);
1086#endif
1087 if (rw & FREAD) {
1088 FLUSHQ(&tp->t_canq);
1089 FLUSHQ(&tp->t_rawq);
1090 tp->t_rocount = 0;
1091 tp->t_rocol = 0;
1092 CLR(tp->t_state, TS_LOCAL);
1093 ttwakeup(tp);
1094 }
1095 if (rw & FWRITE) {
1096 FLUSHQ(&tp->t_outq);
1097 wakeup((caddr_t)&tp->t_outq);
1098 selwakeup(&tp->t_wsel);
1099 }
1100 if ((rw & FREAD) &&
1101 ISSET(tp->t_state, TS_TBLOCK) && tp->t_rawq.c_cc < TTYHOG/5) {
1102 int queue_full = 0;
1103
1104 if (ISSET(tp->t_iflag, IXOFF) &&
1105 tp->t_cc[VSTART] != _POSIX_VDISABLE &&
1106 (queue_full = putc(tp->t_cc[VSTART], &tp->t_outq)) == 0 ||
1107 ISSET(tp->t_cflag, CRTS_IFLOW)) {
1108 CLR(tp->t_state, TS_TBLOCK);
1109 ttstart(tp);
1110 if (queue_full) /* try again */
1111 SET(tp->t_state, TS_TBLOCK);
1112 }
1113 }
1114 splx(s);
1115}
1116
1117/*
1118 * Copy in the default termios characters.
1119 */
1120void
1121ttychars(tp)
1122 struct tty *tp;
1123{
1124
1125 bcopy(ttydefchars, tp->t_cc, sizeof(ttydefchars));
1126}
1127
1128/*
1129 * Send stop character on input overflow.
1130 */
1131static void
1132ttyblock(tp)
1133 register struct tty *tp;
1134{
1135 register int total;
1136
1137 total = tp->t_rawq.c_cc + tp->t_canq.c_cc;
1138 /*
1139 * Block further input iff: current input > threshold
1140 * AND input is available to user program.
1141 */
1142 if (total >= TTYHOG / 2 &&
1143 !ISSET(tp->t_state, TS_TBLOCK) &&
1144 (!ISSET(tp->t_lflag, ICANON) || tp->t_canq.c_cc > 0)) {
1145 int queue_full = 0;
1146
1147 if (ISSET(tp->t_iflag, IXOFF) &&
1148 tp->t_cc[VSTOP] != _POSIX_VDISABLE &&
1149 (queue_full = putc(tp->t_cc[VSTOP], &tp->t_outq)) == 0 ||
1150 ISSET(tp->t_cflag, CRTS_IFLOW)) {
1151 SET(tp->t_state, TS_TBLOCK);
1152 ttstart(tp);
1153 if (queue_full) /* try again */
1154 CLR(tp->t_state, TS_TBLOCK);
1155 }
1156 }
1157}
1158
1159void
1160ttrstrt(tp_arg)
1161 void *tp_arg;
1162{
1163 struct tty *tp;
1164 int s;
1165
1166#ifdef DIAGNOSTIC
1167 if (tp_arg == NULL)
1168 panic("ttrstrt");
1169#endif
1170 tp = tp_arg;
1171 s = spltty();
1172
1173 CLR(tp->t_state, TS_TIMEOUT);
1174 ttstart(tp);
1175
1176 splx(s);
1177}
1178
1179int
1180ttstart(tp)
1181 struct tty *tp;
1182{
1183
1184 if (tp->t_oproc != NULL) /* XXX: Kludge for pty. */
1185 (*tp->t_oproc)(tp);
1186 return (0);
1187}
1188
1189/*
1190 * "close" a line discipline
1191 */
1192int
1193ttylclose(tp, flag)
1194 struct tty *tp;
1195 int flag;
1196{
1197
1198 if ((flag & IO_NDELAY) || ttywflush(tp))
1199 ttyflush(tp, FREAD | FWRITE);
1200 return (0);
1201}
1202
1203/*
1204 * Handle modem control transition on a tty.
1205 * Flag indicates new state of carrier.
1206 * Returns 0 if the line should be turned off, otherwise 1.
1207 */
1208int
1209ttymodem(tp, flag)
1210 register struct tty *tp;
1211 int flag;
1212{
1213
1214 if (!ISSET(tp->t_state, TS_WOPEN) && ISSET(tp->t_cflag, MDMBUF)) {
1215 /*
1216 * MDMBUF: do flow control according to carrier flag
1217 */
1218 if (flag) {
1219 CLR(tp->t_state, TS_TTSTOP);
1220 ttstart(tp);
1221 } else if (!ISSET(tp->t_state, TS_TTSTOP)) {
1222 SET(tp->t_state, TS_TTSTOP);
1223#ifdef sun4c /* XXX */
1224 (*tp->t_stop)(tp, 0);
1225#else
1226 (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
1227#endif
1228 }
1229 } else if (flag == 0) {
1230 /*
1231 * Lost carrier.
1232 */
1233 CLR(tp->t_state, TS_CARR_ON);
1234 if (ISSET(tp->t_state, TS_ISOPEN) &&
1235 !ISSET(tp->t_cflag, CLOCAL)) {
1236 if (tp->t_session && tp->t_session->s_leader)
1237 psignal(tp->t_session->s_leader, SIGHUP);
1238 ttyflush(tp, FREAD | FWRITE);
1239 return (0);
1240 }
1241 } else {
1242 /*
1243 * Carrier now on.
1244 */
1245 SET(tp->t_state, TS_CARR_ON);
1246 ttwakeup(tp);
1247 }
1248 return (1);
1249}
1250
1251/*
1252 * Default modem control routine (for other line disciplines).
1253 * Return argument flag, to turn off device on carrier drop.
1254 */
1255int
1256nullmodem(tp, flag)
1257 register struct tty *tp;
1258 int flag;
1259{
1260
1261 if (flag)
1262 SET(tp->t_state, TS_CARR_ON);
1263 else {
1264 CLR(tp->t_state, TS_CARR_ON);
1265 if (!ISSET(tp->t_cflag, CLOCAL)) {
1266 if (tp->t_session && tp->t_session->s_leader)
1267 psignal(tp->t_session->s_leader, SIGHUP);
1268 return (0);
1269 }
1270 }
1271 return (1);
1272}
1273
1274/*
1275 * Reinput pending characters after state switch
1276 * call at spltty().
1277 */
1278void
1279ttypend(tp)
1280 register struct tty *tp;
1281{
1282 struct clist tq;
1283 register c;
1284
1285 CLR(tp->t_lflag, PENDIN);
1286 SET(tp->t_state, TS_TYPEN);
1287 /*
1288 * XXX this assumes too much about clist internals. It may even
1289 * fail if the cblock slush pool is empty. We can't allocate more
1290 * cblocks here because we are called from an interrupt handler
1291 * and clist_alloc_cblocks() can wait.
1292 */
1293 tq = tp->t_rawq;
1294 bzero(&tp->t_rawq, sizeof tp->t_rawq);
1295 tp->t_rawq.c_cbmax = tq.c_cbmax;
1296 tp->t_rawq.c_cbreserved = tq.c_cbreserved;
1297 while ((c = getc(&tq)) >= 0)
1298 ttyinput(c, tp);
1299 CLR(tp->t_state, TS_TYPEN);
1300}
1301
1302/*
1303 * Process a read call on a tty device.
1304 */
1305int
1306ttread(tp, uio, flag)
1307 register struct tty *tp;
1308 struct uio *uio;
1309 int flag;
1310{
1311 register struct clist *qp;
1312 register int c;
1313 register tcflag_t lflag;
1314 register cc_t *cc = tp->t_cc;
1315 register struct proc *p = curproc;
1316 int s, first, error = 0, carrier;
1317 int has_stime = 0, last_cc = 0;
1318 long slp = 0; /* XXX this should be renamed `timo'. */
1319
1320loop:
1321 s = spltty();
1322 lflag = tp->t_lflag;
1323 /*
1324 * take pending input first
1325 */
1326 if (ISSET(lflag, PENDIN)) {
1327 ttypend(tp);
1328 splx(s); /* reduce latency */
1329 s = spltty();
1330 lflag = tp->t_lflag; /* XXX ttypend() clobbers it */
1331 }
1332
1333 /*
1334 * Hang process if it's in the background.
1335 */
1336 if (isbackground(p, tp)) {
1337 splx(s);
1338 if ((p->p_sigignore & sigmask(SIGTTIN)) ||
1339 (p->p_sigmask & sigmask(SIGTTIN)) ||
1340 p->p_flag & P_PPWAIT || p->p_pgrp->pg_jobc == 0)
1341 return (EIO);
1342 pgsignal(p->p_pgrp, SIGTTIN, 1);
1343 error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, ttybg, 0);
1344 if (error)
1345 return (error);
1346 goto loop;
1347 }
1348
1349 /*
1350 * If canonical, use the canonical queue,
1351 * else use the raw queue.
1352 *
1353 * (should get rid of clists...)
1354 */
1355 qp = ISSET(lflag, ICANON) ? &tp->t_canq : &tp->t_rawq;
1356
1357 if (flag & IO_NDELAY) {
1358 if (qp->c_cc > 0)
1359 goto read;
1360 carrier = ISSET(tp->t_state, TS_CARR_ON) ||
1361 ISSET(tp->t_cflag, CLOCAL);
1362 if ((!carrier && ISSET(tp->t_state, TS_ISOPEN)) ||
1363 !ISSET(lflag, ICANON) && cc[VMIN] == 0) {
1364 splx(s);
1365 return (0);
1366 }
1367 splx(s);
1368 return (EWOULDBLOCK);
1369 }
1370 if (!ISSET(lflag, ICANON)) {
1371 int m = cc[VMIN];
1372 long t = cc[VTIME];
1373 struct timeval stime, timecopy;
1374 int x;
1375
1376 /*
1377 * Check each of the four combinations.
1378 * (m > 0 && t == 0) is the normal read case.
1379 * It should be fairly efficient, so we check that and its
1380 * companion case (m == 0 && t == 0) first.
1381 * For the other two cases, we compute the target sleep time
1382 * into slp.
1383 */
1384 if (t == 0) {
1385 if (qp->c_cc < m)
1386 goto sleep;
1387 if (qp->c_cc > 0)
1388 goto read;
1389
1390 /* m, t and qp->c_cc are all 0. 0 is enough input. */
1391 splx(s);
1392 return (0);
1393 }
1394 t *= 100000; /* time in us */
1395#define diff(t1, t2) (((t1).tv_sec - (t2).tv_sec) * 1000000 + \
1396 ((t1).tv_usec - (t2).tv_usec))
1397 if (m > 0) {
1398 if (qp->c_cc <= 0)
1399 goto sleep;
1400 if (qp->c_cc >= m)
1401 goto read;
1402 x = splclock();
1403 timecopy = time;
1404 splx(x);
1405 if (!has_stime) {
1406 /* first character, start timer */
1407 has_stime = 1;
1408 stime = timecopy;
1409 slp = t;
1410 } else if (qp->c_cc > last_cc) {
1411 /* got a character, restart timer */
1412 stime = timecopy;
1413 slp = t;
1414 } else {
1415 /* nothing, check expiration */
1416 slp = t - diff(timecopy, stime);
1417 if (slp <= 0)
1418 goto read;
1419 }
1420 last_cc = qp->c_cc;
1421 } else { /* m == 0 */
1422 if (qp->c_cc > 0)
1423 goto read;
1424 x = splclock();
1425 timecopy = time;
1426 splx(x);
1427 if (!has_stime) {
1428 has_stime = 1;
1429 stime = timecopy;
1430 slp = t;
1431 } else {
1432 slp = t - diff(timecopy, stime);
1433 if (slp <= 0) {
1434 /* Timed out, but 0 is enough input. */
1435 splx(s);
1436 return (0);
1437 }
1438 }
1439 }
1440#undef diff
1441 /*
1442 * Rounding down may make us wake up just short
1443 * of the target, so we round up.
1444 * The formula is ceiling(slp * hz/1000000).
1445 * 32-bit arithmetic is enough for hz < 169.
1446 * XXX see hzto() for how to avoid overflow if hz
1447 * is large (divide by `tick' and/or arrange to
1448 * use hzto() if hz is large).
1449 */
1450 slp = (long) (((u_long)slp * hz) + 999999) / 1000000;
1451 goto sleep;
1452 }
1453
1454 /*
1455 * If there is no input, sleep on rawq
1456 * awaiting hardware receipt and notification.
1457 * If we have data, we don't need to check for carrier.
1458 */
1459 if (qp->c_cc <= 0) {
1460sleep:
1461 carrier = ISSET(tp->t_state, TS_CARR_ON) ||
1462 ISSET(tp->t_cflag, CLOCAL);
1463 if (!carrier && ISSET(tp->t_state, TS_ISOPEN)) {
1464 splx(s);
1465 return (0); /* EOF */
1466 }
1467 error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH,
1468 carrier ? ttyin : ttopen, (int)slp);
1469 splx(s);
1470 if (error == EWOULDBLOCK)
1471 error = 0;
1472 else if (error)
1473 return (error);
1474 /*
1475 * XXX what happens if another process eats some input
1476 * while we are asleep (not just here)? It would be
1477 * safest to detect changes and reset our state variables
1478 * (has_stime and last_cc).
1479 */
1480 slp = 0;
1481 goto loop;
1482 }
1483read:
1484 splx(s);
1485 /*
1486 * Input present, check for input mapping and processing.
1487 */
1488 first = 1;
1489 while ((c = getc(qp)) >= 0) {
1490 /*
1491 * delayed suspend (^Y)
1492 */
1493 if (CCEQ(cc[VDSUSP], c) && ISSET(lflag, ISIG)) {
1494 pgsignal(tp->t_pgrp, SIGTSTP, 1);
1495 if (first) {
1496 error = ttysleep(tp,
1497 &lbolt, TTIPRI | PCATCH, ttybg, 0);
1498 if (error)
1499 break;
1500 goto loop;
1501 }
1502 break;
1503 }
1504 /*
1505 * Interpret EOF only in canonical mode.
1506 */
1507 if (CCEQ(cc[VEOF], c) && ISSET(lflag, ICANON))
1508 break;
1509
1510#if NSNP > 0
1511 /*
1512 * Only when tty echoes characters , we want to
1513 * feed them to the snoop device.Else they will come
1514 * there if the application would like to.
1515 */
1516 if (ISSET(tp->t_lflag, ECHO))
1517 if (ISSET(tp->t_state, TS_SNOOP) && tp->t_sc != NULL)
1518 snpinc((struct snoop *)tp->t_sc, (char)c);
1519#endif
1520
1521 /*
1522 * Give user character.
1523 */
1524 error = ureadc(c, uio);
1525 if (error)
1526 break;
1527 if (uio->uio_resid == 0)
1528 break;
1529 /*
1530 * In canonical mode check for a "break character"
1531 * marking the end of a "line of input".
1532 */
1533 if (ISSET(lflag, ICANON) && TTBREAKC(c))
1534 break;
1535 first = 0;
1536 }
1537 /*
1538 * Look to unblock output now that (presumably)
1539 * the input queue has gone down.
1540 */
1541 s = spltty();
1542 if (ISSET(tp->t_state, TS_TBLOCK) && tp->t_rawq.c_cc < TTYHOG/5) {
1543 int queue_full = 0;
1544
1545 if (ISSET(tp->t_iflag, IXOFF) &&
1546 cc[VSTART] != _POSIX_VDISABLE &&
1547 (queue_full = putc(cc[VSTART], &tp->t_outq)) == 0 ||
1548 ISSET(tp->t_cflag, CRTS_IFLOW)) {
1549 CLR(tp->t_state, TS_TBLOCK);
1550 ttstart(tp);
1551 if (queue_full) /* try again */
1552 SET(tp->t_state, TS_TBLOCK);
1553 }
1554 }
1555 splx(s);
1556 return (error);
1557}
1558
1559/*
1560 * Check the output queue on tp for space for a kernel message (from uprintf
1561 * or tprintf). Allow some space over the normal hiwater mark so we don't
1562 * lose messages due to normal flow control, but don't let the tty run amok.
1563 * Sleeps here are not interruptible, but we return prematurely if new signals
1564 * arrive.
1565 */
1566int
1567ttycheckoutq(tp, wait)
1568 register struct tty *tp;
1569 int wait;
1570{
1571 int hiwat, s, oldsig;
1572
1573 hiwat = tp->t_hiwat;
1574 s = spltty();
1575 oldsig = wait ? curproc->p_siglist : 0;
1576 if (tp->t_outq.c_cc > hiwat + 200)
1577 while (tp->t_outq.c_cc > hiwat) {
1578 ttstart(tp);
1579 if (wait == 0 || curproc->p_siglist != oldsig) {
1580 splx(s);
1581 return (0);
1582 }
1583 timeout((void (*)__P((void *)))wakeup,
1584 (void *)&tp->t_outq, hz);
1585 SET(tp->t_state, TS_ASLEEP);
1586 (void) tsleep((caddr_t)&tp->t_outq, PZERO - 1, "ttoutq", 0);
1587 }
1588 splx(s);
1589 return (1);
1590}
1591
1592/*
1593 * Process a write call on a tty device.
1594 */
1595int
1596ttwrite(tp, uio, flag)
1597 register struct tty *tp;
1598 register struct uio *uio;
1599 int flag;
1600{
1601 register char *cp = 0;
1602 register int cc, ce;
1603 register struct proc *p;
1604 int i, hiwat, cnt, error, s;
1605 char obuf[OBUFSIZ];
1606
1607 hiwat = tp->t_hiwat;
1608 cnt = uio->uio_resid;
1609 error = 0;
1610 cc = 0;
1611loop:
1612 s = spltty();
1613 if (!ISSET(tp->t_state, TS_CARR_ON) &&
1614 !ISSET(tp->t_cflag, CLOCAL)) {
1615 if (ISSET(tp->t_state, TS_ISOPEN)) {
1616 splx(s);
1617 return (EIO);
1618 } else if (flag & IO_NDELAY) {
1619 splx(s);
1620 error = EWOULDBLOCK;
1621 goto out;
1622 } else {
1623 /* Sleep awaiting carrier. */
1624 error = ttysleep(tp,
1625 &tp->t_rawq, TTIPRI | PCATCH,ttopen, 0);
1626 splx(s);
1627 if (error)
1628 goto out;
1629 goto loop;
1630 }
1631 }
1632 splx(s);
1633 /*
1634 * Hang the process if it's in the background.
1635 */
1636 p = curproc;
1637 if (isbackground(p, tp) &&
1638 ISSET(tp->t_lflag, TOSTOP) && (p->p_flag & P_PPWAIT) == 0 &&
1639 (p->p_sigignore & sigmask(SIGTTOU)) == 0 &&
1640 (p->p_sigmask & sigmask(SIGTTOU)) == 0 &&
1641 p->p_pgrp->pg_jobc) {
1642 pgsignal(p->p_pgrp, SIGTTOU, 1);
1643 error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, ttybg, 0);
1644 if (error)
1645 goto out;
1646 goto loop;
1647 }
1648 /*
1649 * Process the user's data in at most OBUFSIZ chunks. Perform any
1650 * output translation. Keep track of high water mark, sleep on
1651 * overflow awaiting device aid in acquiring new space.
1652 */
1653 while (uio->uio_resid > 0 || cc > 0) {
1654 if (ISSET(tp->t_lflag, FLUSHO)) {
1655 uio->uio_resid = 0;
1656 return (0);
1657 }
1658 if (tp->t_outq.c_cc > hiwat)
1659 goto ovhiwat;
1660 /*
1661 * Grab a hunk of data from the user, unless we have some
1662 * leftover from last time.
1663 */
1664 if (cc == 0) {
1665 cc = min(uio->uio_resid, OBUFSIZ);
1666 cp = obuf;
1667 error = uiomove(cp, cc, uio);
1668 if (error) {
1669 cc = 0;
1670 break;
1671 }
1672#if NSNP > 0
1673 if (ISSET(tp->t_state, TS_SNOOP) && tp->t_sc != NULL)
1674 snpin((struct snoop *)tp->t_sc, cp, cc);
1675#endif
1676 }
1677 /*
1678 * If nothing fancy need be done, grab those characters we
1679 * can handle without any of ttyoutput's processing and
1680 * just transfer them to the output q. For those chars
1681 * which require special processing (as indicated by the
1682 * bits in char_type), call ttyoutput. After processing
1683 * a hunk of data, look for FLUSHO so ^O's will take effect
1684 * immediately.
1685 */
1686 while (cc > 0) {
1687 if (!ISSET(tp->t_oflag, OPOST))
1688 ce = cc;
1689 else {
1690 ce = cc - scanc((u_int)cc, (u_char *)cp,
1691 (u_char *)char_type, CCLASSMASK);
1692 /*
1693 * If ce is zero, then we're processing
1694 * a special character through ttyoutput.
1695 */
1696 if (ce == 0) {
1697 tp->t_rocount = 0;
1698 if (ttyoutput(*cp, tp) >= 0) {
1699 /* No Clists, wait a bit. */
1700 ttstart(tp);
1701 if (flag & IO_NDELAY) {
1702 error = EWOULDBLOCK;
1703 goto out;
1704 }
1705 error = ttysleep(tp, &lbolt,
1706 TTOPRI | PCATCH, ttybuf, 0);
1707 if (error)
1708 goto out;
1709 goto loop;
1710 }
1711 cp++;
1712 cc--;
1713 if (ISSET(tp->t_lflag, FLUSHO) ||
1714 tp->t_outq.c_cc > hiwat)
1715 goto ovhiwat;
1716 continue;
1717 }
1718 }
1719 /*
1720 * A bunch of normal characters have been found.
1721 * Transfer them en masse to the output queue and
1722 * continue processing at the top of the loop.
1723 * If there are any further characters in this
1724 * <= OBUFSIZ chunk, the first should be a character
1725 * requiring special handling by ttyoutput.
1726 */
1727 tp->t_rocount = 0;
1728 i = b_to_q(cp, ce, &tp->t_outq);
1729 ce -= i;
1730 tp->t_column += ce;
1731 cp += ce, cc -= ce, tk_nout += ce;
1732 tp->t_outcc += ce;
1733 if (i > 0) {
1734 /* No Clists, wait a bit. */
1735 ttstart(tp);
1736 if (flag & IO_NDELAY) {
1737 error = EWOULDBLOCK;
1738 goto out;
1739 }
1740 error = ttysleep(tp,
1741 &lbolt, TTOPRI | PCATCH, ttybuf, 0);
1742 if (error)
1743 goto out;
1744 goto loop;
1745 }
1746 if (ISSET(tp->t_lflag, FLUSHO) ||
1747 tp->t_outq.c_cc > hiwat)
1748 break;
1749 }
1750 ttstart(tp);
1751 }
1752out:
1753 /*
1754 * If cc is nonzero, we leave the uio structure inconsistent, as the
1755 * offset and iov pointers have moved forward, but it doesn't matter
1756 * (the call will either return short or restart with a new uio).
1757 */
1758 uio->uio_resid += cc;
1759 return (error);
1760
1761ovhiwat:
1762 ttstart(tp);
1763 s = spltty();
1764 /*
1765 * This can only occur if FLUSHO is set in t_lflag,
1766 * or if ttstart/oproc is synchronous (or very fast).
1767 */
1768 if (tp->t_outq.c_cc <= hiwat) {
1769 splx(s);
1770 goto loop;
1771 }
1772 if (flag & IO_NDELAY) {
1773 splx(s);
1774 uio->uio_resid += cc;
1775 return (uio->uio_resid == cnt ? EWOULDBLOCK : 0);
1776 }
1777 SET(tp->t_state, TS_ASLEEP);
1778 error = ttysleep(tp, &tp->t_outq, TTOPRI | PCATCH, ttyout, 0);
1779 splx(s);
1780 if (error)
1781 goto out;
1782 goto loop;
1783}
1784
1785/*
1786 * Rubout one character from the rawq of tp
1787 * as cleanly as possible.
1788 */
1789void
1790ttyrub(c, tp)
1791 register int c;
1792 register struct tty *tp;
1793{
1794 register char *cp;
1795 register int savecol;
1796 int tabc, s;
1797
1798 if (!ISSET(tp->t_lflag, ECHO) || ISSET(tp->t_lflag, EXTPROC))
1799 return;
1800 CLR(tp->t_lflag, FLUSHO);
1801 if (ISSET(tp->t_lflag, ECHOE)) {
1802 if (tp->t_rocount == 0) {
1803 /*
1804 * Screwed by ttwrite; retype
1805 */
1806 ttyretype(tp);
1807 return;
1808 }
1809 if (c == ('\t' | TTY_QUOTE) || c == ('\n' | TTY_QUOTE))
1810 ttyrubo(tp, 2);
1811 else {
1812 CLR(c, ~TTY_CHARMASK);
1813 switch (CCLASS(c)) {
1814 case ORDINARY:
1815 ttyrubo(tp, 1);
1816 break;
1817 case BACKSPACE:
1818 case CONTROL:
1819 case NEWLINE:
1820 case RETURN:
1821 case VTAB:
1822 if (ISSET(tp->t_lflag, ECHOCTL))
1823 ttyrubo(tp, 2);
1824 break;
1825 case TAB:
1826 if (tp->t_rocount < tp->t_rawq.c_cc) {
1827 ttyretype(tp);
1828 return;
1829 }
1830 s = spltty();
1831 savecol = tp->t_column;
1832 SET(tp->t_state, TS_CNTTB);
1833 SET(tp->t_lflag, FLUSHO);
1834 tp->t_column = tp->t_rocol;
1835 cp = tp->t_rawq.c_cf;
1836 if (cp)
1837 tabc = *cp; /* XXX FIX NEXTC */
1838 for (; cp; cp = nextc(&tp->t_rawq, cp, &tabc))
1839 ttyecho(tabc, tp);
1840 CLR(tp->t_lflag, FLUSHO);
1841 CLR(tp->t_state, TS_CNTTB);
1842 splx(s);
1843
1844 /* savecol will now be length of the tab. */
1845 savecol -= tp->t_column;
1846 tp->t_column += savecol;
1847 if (savecol > 8)
1848 savecol = 8; /* overflow screw */
1849 while (--savecol >= 0)
1850 (void)ttyoutput('\b', tp);
1851 break;
1852 default: /* XXX */
1853#define PANICSTR "ttyrub: would panic c = %d, val = %d\n"
1854 (void)printf(PANICSTR, c, CCLASS(c));
1855#ifdef notdef
1856 panic(PANICSTR, c, CCLASS(c));
1857#endif
1858 }
1859 }
1860 } else if (ISSET(tp->t_lflag, ECHOPRT)) {
1861 if (!ISSET(tp->t_state, TS_ERASE)) {
1862 SET(tp->t_state, TS_ERASE);
1863 (void)ttyoutput('\\', tp);
1864 }
1865 ttyecho(c, tp);
1866 } else
1867 ttyecho(tp->t_cc[VERASE], tp);
1868 --tp->t_rocount;
1869}
1870
1871/*
1872 * Back over cnt characters, erasing them.
1873 */
1874static void
1875ttyrubo(tp, cnt)
1876 register struct tty *tp;
1877 int cnt;
1878{
1879
1880 while (cnt-- > 0) {
1881 (void)ttyoutput('\b', tp);
1882 (void)ttyoutput(' ', tp);
1883 (void)ttyoutput('\b', tp);
1884 }
1885}
1886
1887/*
1888 * ttyretype --
1889 * Reprint the rawq line. Note, it is assumed that c_cc has already
1890 * been checked.
1891 */
1892void
1893ttyretype(tp)
1894 register struct tty *tp;
1895{
1896 register char *cp;
1897 int s, c;
1898
1899 /* Echo the reprint character. */
1900 if (tp->t_cc[VREPRINT] != _POSIX_VDISABLE)
1901 ttyecho(tp->t_cc[VREPRINT], tp);
1902
1903 (void)ttyoutput('\n', tp);
1904
1905 /*
1906 * XXX
1907 * FIX: NEXTC IS BROKEN - DOESN'T CHECK QUOTE
1908 * BIT OF FIRST CHAR.
1909 */
1910 s = spltty();
1911 for (cp = tp->t_canq.c_cf, c = (cp != NULL ? *cp : 0);
1912 cp != NULL; cp = nextc(&tp->t_canq, cp, &c))
1913 ttyecho(c, tp);
1914 for (cp = tp->t_rawq.c_cf, c = (cp != NULL ? *cp : 0);
1915 cp != NULL; cp = nextc(&tp->t_rawq, cp, &c))
1916 ttyecho(c, tp);
1917 CLR(tp->t_state, TS_ERASE);
1918 splx(s);
1919
1920 tp->t_rocount = tp->t_rawq.c_cc;
1921 tp->t_rocol = 0;
1922}
1923
1924/*
1925 * Echo a typed character to the terminal.
1926 */
1927static void
1928ttyecho(c, tp)
1929 register int c;
1930 register struct tty *tp;
1931{
1932
1933 if (!ISSET(tp->t_state, TS_CNTTB))
1934 CLR(tp->t_lflag, FLUSHO);
1935 if ((!ISSET(tp->t_lflag, ECHO) &&
1936 (!ISSET(tp->t_lflag, ECHONL) || c == '\n')) ||
1937 ISSET(tp->t_lflag, EXTPROC))
1938 return;
1939 if (ISSET(tp->t_lflag, ECHOCTL) &&
1940 ((ISSET(c, TTY_CHARMASK) <= 037 && c != '\t' && c != '\n') ||
1941 ISSET(c, TTY_CHARMASK) == 0177)) {
1942 (void)ttyoutput('^', tp);
1943 CLR(c, ~TTY_CHARMASK);
1944 if (c == 0177)
1945 c = '?';
1946 else
1947 c += 'A' - 1;
1948 }
1949 (void)ttyoutput(c, tp);
1950}
1951
1952/*
1953 * Wake up any readers on a tty.
1954 */
1955void
1956ttwakeup(tp)
1957 register struct tty *tp;
1958{
1959
1960 selwakeup(&tp->t_rsel);
1961 if (ISSET(tp->t_state, TS_ASYNC))
1962 pgsignal(tp->t_pgrp, SIGIO, 1);
1963 wakeup((caddr_t)&tp->t_rawq);
1964}
1965
1966/*
1967 * Look up a code for a specified speed in a conversion table;
1968 * used by drivers to map software speed values to hardware parameters.
1969 */
1970int
1971ttspeedtab(speed, table)
1972 int speed;
1973 register struct speedtab *table;
1974{
1975
1976 for ( ; table->sp_speed != -1; table++)
1977 if (table->sp_speed == speed)
1978 return (table->sp_code);
1979 return (-1);
1980}
1981
1982/*
1983 * Set tty hi and low water marks.
1984 *
1985 * Try to arrange the dynamics so there's about one second
1986 * from hi to low water.
1987 *
1988 */
1989void
1990ttsetwater(tp)
1991 struct tty *tp;
1992{
1993 register int cps, x;
1994
1995#define CLAMP(x, h, l) ((x) > h ? h : ((x) < l) ? l : (x))
1996
1997 cps = tp->t_ospeed / 10;
1998 tp->t_lowat = x = CLAMP(cps / 2, TTMAXLOWAT, TTMINLOWAT);
1999 x += cps;
2000 x = CLAMP(x, TTMAXHIWAT, TTMINHIWAT);
2001 tp->t_hiwat = roundup(x, CBSIZE);
2002#undef CLAMP
2003}
2004
2005/*
2006 * Report on state of foreground process group.
2007 */
2008void
2009ttyinfo(tp)
2010 register struct tty *tp;
2011{
2012 register struct proc *p, *pick;
2013 struct timeval utime, stime;
2014 int tmp;
2015
2016 if (ttycheckoutq(tp,0) == 0)
2017 return;
2018
2019 /* Print load average. */
2020 tmp = (averunnable.ldavg[0] * 100 + FSCALE / 2) >> FSHIFT;
2021 ttyprintf(tp, "load: %d.%02d ", tmp / 100, tmp % 100);
2022
2023 if (tp->t_session == NULL)
2024 ttyprintf(tp, "not a controlling terminal\n");
2025 else if (tp->t_pgrp == NULL)
2026 ttyprintf(tp, "no foreground process group\n");
2027 else if ((p = tp->t_pgrp->pg_mem) == NULL)
2028 ttyprintf(tp, "empty foreground process group\n");
2029 else {
2030 /* Pick interesting process. */
2031 for (pick = NULL; p != NULL; p = p->p_pgrpnxt)
2032 if (proc_compare(pick, p))
2033 pick = p;
2034
2035 ttyprintf(tp, " cmd: %s %d [%s] ", pick->p_comm, pick->p_pid,
2036 pick->p_stat == SRUN ? "running" :
2037 pick->p_wmesg ? pick->p_wmesg : "iowait");
2038
2039 calcru(pick, &utime, &stime, NULL);
2040
2041 /* Print user time. */
2042 ttyprintf(tp, "%d.%02du ",
2043 utime.tv_sec, utime.tv_usec / 10000);
2044
2045 /* Print system time. */
2046 ttyprintf(tp, "%d.%02ds ",
2047 stime.tv_sec, stime.tv_usec / 10000);
2048
2049#define pgtok(a) (((a) * NBPG) / 1024)
2050 /* Print percentage cpu, resident set size. */
2051 tmp = (pick->p_pctcpu * 10000 + FSCALE / 2) >> FSHIFT;
2052 ttyprintf(tp, "%d%% %dk\n",
2053 tmp / 100,
2054 pick->p_stat == SIDL || pick->p_stat == SZOMB ? 0 :
2055#ifdef pmap_resident_count
2056 pgtok(pmap_resident_count(&pick->p_vmspace->vm_pmap))
2057#else
2058 pgtok(pick->p_vmspace->vm_rssize)
2059#endif
2060 );
2061 }
2062 tp->t_rocount = 0; /* so pending input will be retyped if BS */
2063}
2064
2065/*
2066 * Returns 1 if p2 is "better" than p1
2067 *
2068 * The algorithm for picking the "interesting" process is thus:
2069 *
2070 * 1) Only foreground processes are eligible - implied.
2071 * 2) Runnable processes are favored over anything else. The runner
2072 * with the highest cpu utilization is picked (p_estcpu). Ties are
2073 * broken by picking the highest pid.
2074 * 3) The sleeper with the shortest sleep time is next. With ties,
2075 * we pick out just "short-term" sleepers (P_SINTR == 0).
2076 * 4) Further ties are broken by picking the highest pid.
2077 */
2078#define ISRUN(p) (((p)->p_stat == SRUN) || ((p)->p_stat == SIDL))
2079#define TESTAB(a, b) ((a)<<1 | (b))
2080#define ONLYA 2
2081#define ONLYB 1
2082#define BOTH 3
2083
2084static int
2085proc_compare(p1, p2)
2086 register struct proc *p1, *p2;
2087{
2088
2089 if (p1 == NULL)
2090 return (1);
2091 /*
2092 * see if at least one of them is runnable
2093 */
2094 switch (TESTAB(ISRUN(p1), ISRUN(p2))) {
2095 case ONLYA:
2096 return (0);
2097 case ONLYB:
2098 return (1);
2099 case BOTH:
2100 /*
2101 * tie - favor one with highest recent cpu utilization
2102 */
2103 if (p2->p_estcpu > p1->p_estcpu)
2104 return (1);
2105 if (p1->p_estcpu > p2->p_estcpu)
2106 return (0);
2107 return (p2->p_pid > p1->p_pid); /* tie - return highest pid */
2108 }
2109 /*
2110 * weed out zombies
2111 */
2112 switch (TESTAB(p1->p_stat == SZOMB, p2->p_stat == SZOMB)) {
2113 case ONLYA:
2114 return (1);
2115 case ONLYB:
2116 return (0);
2117 case BOTH:
2118 return (p2->p_pid > p1->p_pid); /* tie - return highest pid */
2119 }
2120 /*
2121 * pick the one with the smallest sleep time
2122 */
2123 if (p2->p_slptime > p1->p_slptime)
2124 return (0);
2125 if (p1->p_slptime > p2->p_slptime)
2126 return (1);
2127 /*
2128 * favor one sleeping in a non-interruptible sleep
2129 */
2130 if (p1->p_flag & P_SINTR && (p2->p_flag & P_SINTR) == 0)
2131 return (1);
2132 if (p2->p_flag & P_SINTR && (p1->p_flag & P_SINTR) == 0)
2133 return (0);
2134 return (p2->p_pid > p1->p_pid); /* tie - return highest pid */
2135}
2136
2137/*
2138 * Output char to tty; console putchar style.
2139 */
2140int
2141tputchar(c, tp)
2142 int c;
2143 struct tty *tp;
2144{
2145 register int s;
2146
2147 s = spltty();
2148 if (ISSET(tp->t_state,
2149 TS_CARR_ON | TS_ISOPEN) != (TS_CARR_ON | TS_ISOPEN)) {
2150 splx(s);
2151 return (-1);
2152 }
2153 if (c == '\n')
2154 (void)ttyoutput('\r', tp);
2155 (void)ttyoutput(c, tp);
2156 ttstart(tp);
2157 splx(s);
2158 return (0);
2159}
2160
2161/*
2162 * Sleep on chan, returning ERESTART if tty changed while we napped and
2163 * returning any errors (e.g. EINTR/ETIMEDOUT) reported by tsleep. If
2164 * the tty is revoked, restarting a pending call will redo validation done
2165 * at the start of the call.
2166 */
2167int
2168ttysleep(tp, chan, pri, wmesg, timo)
2169 struct tty *tp;
2170 void *chan;
2171 int pri, timo;
2172 char *wmesg;
2173{
2174 int error;
2175 short gen;
2176
2177 gen = tp->t_gen;
2178 error = tsleep(chan, pri, wmesg, timo);
2179 if (error)
2180 return (error);
2181 return (tp->t_gen == gen ? 0 : ERESTART);
2182}
2183
2184/*
2185 * XXX this is usable not useful or used. Most tty drivers have
2186 * ifdefs for using ttymalloc() but assume a different interface.
2187 */
2188/*
2189 * Allocate a tty struct. Clists in the struct will be allocated by
2190 * ttyopen().
2191 */
2192struct tty *
2193ttymalloc()
2194{
2195 struct tty *tp;
2196
2197 tp = malloc(sizeof *tp, M_TTYS, M_WAITOK);
2198 bzero(tp, sizeof *tp);
2199 return (tp);
2200}
2201
2202#if 0 /* XXX not yet usable: session leader holds a ref (see kern_exit.c). */
2203/*
2204 * Free a tty struct. Clists in the struct should have been freed by
2205 * ttyclose().
2206 */
2207void
2208ttyfree(tp)
2209 struct tty *tp;
2210{
2211 free(tp, M_TTYS);
2212}
2213#endif /* 0 */
286 if (ISSET(iflag, IGNBRK))
287 return (0);
288 else if (ISSET(iflag, BRKINT) &&
289 ISSET(lflag, ISIG) &&
290 (cc[VINTR] != _POSIX_VDISABLE))
291 c = cc[VINTR];
292 else if (ISSET(iflag, PARMRK))
293 goto parmrk;
294 } else if ((ISSET(err, TTY_PE) && ISSET(iflag, INPCK))
295 || ISSET(err, TTY_FE)) {
296 if (ISSET(iflag, IGNPAR))
297 return (0);
298 else if (ISSET(iflag, PARMRK)) {
299parmrk: (void)putc(0377 | TTY_QUOTE, &tp->t_rawq);
300 (void)putc(0 | TTY_QUOTE, &tp->t_rawq);
301 (void)putc(c | TTY_QUOTE, &tp->t_rawq);
302 goto endcase;
303 } else
304 c = 0;
305 }
306 }
307 /*
308 * In tandem mode, check high water mark.
309 */
310 if (ISSET(iflag, IXOFF) || ISSET(tp->t_cflag, CRTS_IFLOW))
311 ttyblock(tp);
312 if (!ISSET(tp->t_state, TS_TYPEN) && ISSET(iflag, ISTRIP))
313 CLR(c, 0x80);
314 if (!ISSET(lflag, EXTPROC)) {
315 /*
316 * Check for literal nexting very first
317 */
318 if (ISSET(tp->t_state, TS_LNCH)) {
319 SET(c, TTY_QUOTE);
320 CLR(tp->t_state, TS_LNCH);
321 }
322 /*
323 * Scan for special characters. This code
324 * is really just a big case statement with
325 * non-constant cases. The bottom of the
326 * case statement is labeled ``endcase'', so goto
327 * it after a case match, or similar.
328 */
329
330 /*
331 * Control chars which aren't controlled
332 * by ICANON, ISIG, or IXON.
333 */
334 if (ISSET(lflag, IEXTEN)) {
335 if (CCEQ(cc[VLNEXT], c)) {
336 if (ISSET(lflag, ECHO)) {
337 if (ISSET(lflag, ECHOE)) {
338 (void)ttyoutput('^', tp);
339 (void)ttyoutput('\b', tp);
340 } else
341 ttyecho(c, tp);
342 }
343 SET(tp->t_state, TS_LNCH);
344 goto endcase;
345 }
346 if (CCEQ(cc[VDISCARD], c)) {
347 if (ISSET(lflag, FLUSHO))
348 CLR(tp->t_lflag, FLUSHO);
349 else {
350 ttyflush(tp, FWRITE);
351 ttyecho(c, tp);
352 if (tp->t_rawq.c_cc + tp->t_canq.c_cc)
353 ttyretype(tp);
354 SET(tp->t_lflag, FLUSHO);
355 }
356 goto startoutput;
357 }
358 }
359 /*
360 * Signals.
361 */
362 if (ISSET(lflag, ISIG)) {
363 if (CCEQ(cc[VINTR], c) || CCEQ(cc[VQUIT], c)) {
364 if (!ISSET(lflag, NOFLSH))
365 ttyflush(tp, FREAD | FWRITE);
366 ttyecho(c, tp);
367 pgsignal(tp->t_pgrp,
368 CCEQ(cc[VINTR], c) ? SIGINT : SIGQUIT, 1);
369 goto endcase;
370 }
371 if (CCEQ(cc[VSUSP], c)) {
372 if (!ISSET(lflag, NOFLSH))
373 ttyflush(tp, FREAD);
374 ttyecho(c, tp);
375 pgsignal(tp->t_pgrp, SIGTSTP, 1);
376 goto endcase;
377 }
378 }
379 /*
380 * Handle start/stop characters.
381 */
382 if (ISSET(iflag, IXON)) {
383 if (CCEQ(cc[VSTOP], c)) {
384 if (!ISSET(tp->t_state, TS_TTSTOP)) {
385 SET(tp->t_state, TS_TTSTOP);
386#ifdef sun4c /* XXX */
387 (*tp->t_stop)(tp, 0);
388#else
389 (*cdevsw[major(tp->t_dev)].d_stop)(tp,
390 0);
391#endif
392 return (0);
393 }
394 if (!CCEQ(cc[VSTART], c))
395 return (0);
396 /*
397 * if VSTART == VSTOP then toggle
398 */
399 goto endcase;
400 }
401 if (CCEQ(cc[VSTART], c))
402 goto restartoutput;
403 }
404 /*
405 * IGNCR, ICRNL, & INLCR
406 */
407 if (c == '\r') {
408 if (ISSET(iflag, IGNCR))
409 return (0);
410 else if (ISSET(iflag, ICRNL))
411 c = '\n';
412 } else if (c == '\n' && ISSET(iflag, INLCR))
413 c = '\r';
414 }
415 if (!ISSET(tp->t_lflag, EXTPROC) && ISSET(lflag, ICANON)) {
416 /*
417 * From here on down canonical mode character
418 * processing takes place.
419 */
420 /*
421 * erase (^H / ^?)
422 */
423 if (CCEQ(cc[VERASE], c)) {
424 if (tp->t_rawq.c_cc)
425 ttyrub(unputc(&tp->t_rawq), tp);
426 goto endcase;
427 }
428 /*
429 * kill (^U)
430 */
431 if (CCEQ(cc[VKILL], c)) {
432 if (ISSET(lflag, ECHOKE) &&
433 tp->t_rawq.c_cc == tp->t_rocount &&
434 !ISSET(lflag, ECHOPRT))
435 while (tp->t_rawq.c_cc)
436 ttyrub(unputc(&tp->t_rawq), tp);
437 else {
438 ttyecho(c, tp);
439 if (ISSET(lflag, ECHOK) ||
440 ISSET(lflag, ECHOKE))
441 ttyecho('\n', tp);
442 FLUSHQ(&tp->t_rawq);
443 tp->t_rocount = 0;
444 }
445 CLR(tp->t_state, TS_LOCAL);
446 goto endcase;
447 }
448 /*
449 * word erase (^W)
450 */
451 if (CCEQ(cc[VWERASE], c)) {
452 int alt = ISSET(lflag, ALTWERASE);
453 int ctype;
454
455 /*
456 * erase whitespace
457 */
458 while ((c = unputc(&tp->t_rawq)) == ' ' || c == '\t')
459 ttyrub(c, tp);
460 if (c == -1)
461 goto endcase;
462 /*
463 * erase last char of word and remember the
464 * next chars type (for ALTWERASE)
465 */
466 ttyrub(c, tp);
467 c = unputc(&tp->t_rawq);
468 if (c == -1)
469 goto endcase;
470 if (c == ' ' || c == '\t') {
471 (void)putc(c, &tp->t_rawq);
472 goto endcase;
473 }
474 ctype = ISALPHA(c);
475 /*
476 * erase rest of word
477 */
478 do {
479 ttyrub(c, tp);
480 c = unputc(&tp->t_rawq);
481 if (c == -1)
482 goto endcase;
483 } while (c != ' ' && c != '\t' &&
484 (alt == 0 || ISALPHA(c) == ctype));
485 (void)putc(c, &tp->t_rawq);
486 goto endcase;
487 }
488 /*
489 * reprint line (^R)
490 */
491 if (CCEQ(cc[VREPRINT], c)) {
492 ttyretype(tp);
493 goto endcase;
494 }
495 /*
496 * ^T - kernel info and generate SIGINFO
497 */
498 if (CCEQ(cc[VSTATUS], c)) {
499 if (ISSET(lflag, ISIG))
500 pgsignal(tp->t_pgrp, SIGINFO, 1);
501 if (!ISSET(lflag, NOKERNINFO))
502 ttyinfo(tp);
503 goto endcase;
504 }
505 }
506 /*
507 * Check for input buffer overflow
508 */
509 if (tp->t_rawq.c_cc + tp->t_canq.c_cc >= TTYHOG) {
510 if (ISSET(iflag, IMAXBEL)) {
511 if (tp->t_outq.c_cc < tp->t_hiwat)
512 (void)ttyoutput(CTRL('g'), tp);
513 }
514 goto endcase;
515 }
516
517 if ( c == 0377 && ISSET(iflag, PARMRK) && !ISSET(iflag, ISTRIP)
518 && ISSET(iflag, IGNBRK|IGNPAR) != (IGNBRK|IGNPAR))
519 (void)putc(0377 | TTY_QUOTE, &tp->t_rawq);
520
521 /*
522 * Put data char in q for user and
523 * wakeup on seeing a line delimiter.
524 */
525 if (putc(c, &tp->t_rawq) >= 0) {
526 if (!ISSET(lflag, ICANON)) {
527 ttwakeup(tp);
528 ttyecho(c, tp);
529 goto endcase;
530 }
531 if (TTBREAKC(c)) {
532 tp->t_rocount = 0;
533 catq(&tp->t_rawq, &tp->t_canq);
534 ttwakeup(tp);
535 } else if (tp->t_rocount++ == 0)
536 tp->t_rocol = tp->t_column;
537 if (ISSET(tp->t_state, TS_ERASE)) {
538 /*
539 * end of prterase \.../
540 */
541 CLR(tp->t_state, TS_ERASE);
542 (void)ttyoutput('/', tp);
543 }
544 i = tp->t_column;
545 ttyecho(c, tp);
546 if (CCEQ(cc[VEOF], c) && ISSET(lflag, ECHO)) {
547 /*
548 * Place the cursor over the '^' of the ^D.
549 */
550 i = min(2, tp->t_column - i);
551 while (i > 0) {
552 (void)ttyoutput('\b', tp);
553 i--;
554 }
555 }
556 }
557endcase:
558 /*
559 * IXANY means allow any character to restart output.
560 */
561 if (ISSET(tp->t_state, TS_TTSTOP) &&
562 !ISSET(iflag, IXANY) && cc[VSTART] != cc[VSTOP])
563 return (0);
564restartoutput:
565 CLR(tp->t_lflag, FLUSHO);
566 CLR(tp->t_state, TS_TTSTOP);
567startoutput:
568 return (ttstart(tp));
569}
570
571/*
572 * Output a single character on a tty, doing output processing
573 * as needed (expanding tabs, newline processing, etc.).
574 * Returns < 0 if succeeds, otherwise returns char to resend.
575 * Must be recursive.
576 */
577int
578ttyoutput(c, tp)
579 register int c;
580 register struct tty *tp;
581{
582 register long oflag;
583 register int col, s;
584
585 oflag = tp->t_oflag;
586 if (!ISSET(oflag, OPOST)) {
587 if (ISSET(tp->t_lflag, FLUSHO))
588 return (-1);
589 if (putc(c, &tp->t_outq))
590 return (c);
591 tk_nout++;
592 tp->t_outcc++;
593 return (-1);
594 }
595 /*
596 * Do tab expansion if OXTABS is set. Special case if we external
597 * processing, we don't do the tab expansion because we'll probably
598 * get it wrong. If tab expansion needs to be done, let it happen
599 * externally.
600 */
601 CLR(c, ~TTY_CHARMASK);
602 if (c == '\t' &&
603 ISSET(oflag, OXTABS) && !ISSET(tp->t_lflag, EXTPROC)) {
604 c = 8 - (tp->t_column & 7);
605 if (!ISSET(tp->t_lflag, FLUSHO)) {
606 s = spltty(); /* Don't interrupt tabs. */
607 c -= b_to_q(" ", c, &tp->t_outq);
608 tk_nout += c;
609 tp->t_outcc += c;
610 splx(s);
611 }
612 tp->t_column += c;
613 return (c ? -1 : '\t');
614 }
615 if (c == CEOT && ISSET(oflag, ONOEOT))
616 return (-1);
617
618 /*
619 * Newline translation: if ONLCR is set,
620 * translate newline into "\r\n".
621 */
622 if (c == '\n' && ISSET(tp->t_oflag, ONLCR)) {
623 tk_nout++;
624 tp->t_outcc++;
625 if (putc('\r', &tp->t_outq))
626 return (c);
627 }
628 tk_nout++;
629 tp->t_outcc++;
630 if (!ISSET(tp->t_lflag, FLUSHO) && putc(c, &tp->t_outq))
631 return (c);
632
633 col = tp->t_column;
634 switch (CCLASS(c)) {
635 case BACKSPACE:
636 if (col > 0)
637 --col;
638 break;
639 case CONTROL:
640 break;
641 case NEWLINE:
642 case RETURN:
643 col = 0;
644 break;
645 case ORDINARY:
646 ++col;
647 break;
648 case TAB:
649 col = (col + 8) & ~7;
650 break;
651 }
652 tp->t_column = col;
653 return (-1);
654}
655
656/*
657 * Ioctls for all tty devices. Called after line-discipline specific ioctl
658 * has been called to do discipline-specific functions and/or reject any
659 * of these ioctl commands.
660 */
661/* ARGSUSED */
662int
663ttioctl(tp, cmd, data, flag)
664 register struct tty *tp;
665 int cmd, flag;
666 void *data;
667{
668 register struct proc *p;
669 int s, error;
670
671 p = curproc; /* XXX */
672
673 /* If the ioctl involves modification, hang if in the background. */
674 switch (cmd) {
675 case TIOCFLUSH:
676 case TIOCSETA:
677 case TIOCSETD:
678 case TIOCSETAF:
679 case TIOCSETAW:
680#ifdef notdef
681 case TIOCSPGRP:
682#endif
683 case TIOCSTAT:
684 case TIOCSTI:
685 case TIOCSWINSZ:
686#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
687 case TIOCLBIC:
688 case TIOCLBIS:
689 case TIOCLSET:
690 case TIOCSETC:
691 case OTIOCSETD:
692 case TIOCSETN:
693 case TIOCSETP:
694 case TIOCSLTC:
695#endif
696 while (isbackground(curproc, tp) &&
697 p->p_pgrp->pg_jobc && (p->p_flag & P_PPWAIT) == 0 &&
698 (p->p_sigignore & sigmask(SIGTTOU)) == 0 &&
699 (p->p_sigmask & sigmask(SIGTTOU)) == 0) {
700 pgsignal(p->p_pgrp, SIGTTOU, 1);
701 error = ttysleep(tp, &lbolt, TTOPRI | PCATCH, ttybg, 0);
702 if (error)
703 return (error);
704 }
705 break;
706 }
707
708 switch (cmd) { /* Process the ioctl. */
709 case FIOASYNC: /* set/clear async i/o */
710 s = spltty();
711 if (*(int *)data)
712 SET(tp->t_state, TS_ASYNC);
713 else
714 CLR(tp->t_state, TS_ASYNC);
715 splx(s);
716 break;
717 case FIONBIO: /* set/clear non-blocking i/o */
718 break; /* XXX: delete. */
719 case FIONREAD: /* get # bytes to read */
720 *(int *)data = ttnread(tp);
721 break;
722 case TIOCEXCL: /* set exclusive use of tty */
723 s = spltty();
724 SET(tp->t_state, TS_XCLUDE);
725 splx(s);
726 break;
727 case TIOCFLUSH: { /* flush buffers */
728 register int flags = *(int *)data;
729
730 if (flags == 0)
731 flags = FREAD | FWRITE;
732 else
733 flags &= FREAD | FWRITE;
734 ttyflush(tp, flags);
735 break;
736 }
737 case TIOCCONS: /* become virtual console */
738 if (*(int *)data) {
739 if (constty && constty != tp &&
740 ISSET(constty->t_state, TS_CARR_ON | TS_ISOPEN) ==
741 (TS_CARR_ON | TS_ISOPEN))
742 return (EBUSY);
743#ifndef UCONSOLE
744 if (error = suser(p->p_ucred, &p->p_acflag))
745 return (error);
746#endif
747 constty = tp;
748 } else if (tp == constty)
749 constty = NULL;
750 break;
751 case TIOCDRAIN: /* wait till output drained */
752 error = ttywait(tp);
753 if (error)
754 return (error);
755 break;
756 case TIOCGETA: { /* get termios struct */
757 struct termios *t = (struct termios *)data;
758
759 bcopy(&tp->t_termios, t, sizeof(struct termios));
760 break;
761 }
762 case TIOCGETD: /* get line discipline */
763 *(int *)data = tp->t_line;
764 break;
765 case TIOCGWINSZ: /* get window size */
766 *(struct winsize *)data = tp->t_winsize;
767 break;
768 case TIOCGPGRP: /* get pgrp of tty */
769 if (!isctty(p, tp))
770 return (ENOTTY);
771 *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
772 break;
773#ifdef TIOCHPCL
774 case TIOCHPCL: /* hang up on last close */
775 s = spltty();
776 SET(tp->t_cflag, HUPCL);
777 splx(s);
778 break;
779#endif
780 case TIOCNXCL: /* reset exclusive use of tty */
781 s = spltty();
782 CLR(tp->t_state, TS_XCLUDE);
783 splx(s);
784 break;
785 case TIOCOUTQ: /* output queue size */
786 *(int *)data = tp->t_outq.c_cc;
787 break;
788 case TIOCSETA: /* set termios struct */
789 case TIOCSETAW: /* drain output, set */
790 case TIOCSETAF: { /* drn out, fls in, set */
791 register struct termios *t = (struct termios *)data;
792
793 s = spltty();
794 if (cmd == TIOCSETAW || cmd == TIOCSETAF) {
795 error = ttywait(tp);
796 if (error) {
797 splx(s);
798 return (error);
799 }
800 if (cmd == TIOCSETAF)
801 ttyflush(tp, FREAD);
802 }
803 if (!ISSET(t->c_cflag, CIGNORE)) {
804 /*
805 * Set device hardware.
806 */
807 if (tp->t_param && (error = (*tp->t_param)(tp, t))) {
808 splx(s);
809 return (error);
810 } else {
811 if (!ISSET(tp->t_state, TS_CARR_ON) &&
812 ISSET(tp->t_cflag, CLOCAL) &&
813 !ISSET(t->c_cflag, CLOCAL)) {
814#if 0
815 CLR(tp->t_state, TS_ISOPEN);
816 SET(tp->t_state, TS_WOPEN);
817#endif
818 ttwakeup(tp);
819 }
820 tp->t_cflag = t->c_cflag;
821 tp->t_ispeed = t->c_ispeed;
822 tp->t_ospeed = t->c_ospeed;
823 }
824 ttsetwater(tp);
825 }
826 if (cmd != TIOCSETAF) {
827 if (ISSET(t->c_lflag, ICANON) !=
828 ISSET(tp->t_lflag, ICANON))
829 if (ISSET(t->c_lflag, ICANON)) {
830 SET(tp->t_lflag, PENDIN);
831 ttwakeup(tp);
832 } else {
833 struct clist tq;
834
835 catq(&tp->t_rawq, &tp->t_canq);
836 tq = tp->t_rawq;
837 tp->t_rawq = tp->t_canq;
838 tp->t_canq = tq;
839 CLR(tp->t_lflag, PENDIN);
840 }
841 }
842 tp->t_iflag = t->c_iflag;
843 tp->t_oflag = t->c_oflag;
844 /*
845 * Make the EXTPROC bit read only.
846 */
847 if (ISSET(tp->t_lflag, EXTPROC))
848 SET(t->c_lflag, EXTPROC);
849 else
850 CLR(t->c_lflag, EXTPROC);
851 tp->t_lflag = t->c_lflag | ISSET(tp->t_lflag, PENDIN);
852 if (t->c_cc[VMIN] != tp->t_cc[VMIN] ||
853 t->c_cc[VTIME] != tp->t_cc[VTIME])
854 ttwakeup(tp);
855 bcopy(t->c_cc, tp->t_cc, sizeof(t->c_cc));
856 splx(s);
857 break;
858 }
859 case TIOCSETD: { /* set line discipline */
860 register int t = *(int *)data;
861 dev_t device = tp->t_dev;
862
863 if ((u_int)t >= nlinesw)
864 return (ENXIO);
865 if (t != tp->t_line) {
866 s = spltty();
867 (*linesw[tp->t_line].l_close)(tp, flag);
868 error = (*linesw[t].l_open)(device, tp);
869 if (error) {
870 (void)(*linesw[tp->t_line].l_open)(device, tp);
871 splx(s);
872 return (error);
873 }
874 tp->t_line = t;
875 splx(s);
876 }
877 break;
878 }
879 case TIOCSTART: /* start output, like ^Q */
880 s = spltty();
881 if (ISSET(tp->t_state, TS_TTSTOP) ||
882 ISSET(tp->t_lflag, FLUSHO)) {
883 CLR(tp->t_lflag, FLUSHO);
884 CLR(tp->t_state, TS_TTSTOP);
885 ttstart(tp);
886 }
887 splx(s);
888 break;
889 case TIOCSTI: /* simulate terminal input */
890 if (p->p_ucred->cr_uid && (flag & FREAD) == 0)
891 return (EPERM);
892 if (p->p_ucred->cr_uid && !isctty(p, tp))
893 return (EACCES);
894 (*linesw[tp->t_line].l_rint)(*(u_char *)data, tp);
895 break;
896 case TIOCSTOP: /* stop output, like ^S */
897 s = spltty();
898 if (!ISSET(tp->t_state, TS_TTSTOP)) {
899 SET(tp->t_state, TS_TTSTOP);
900#ifdef sun4c /* XXX */
901 (*tp->t_stop)(tp, 0);
902#else
903 (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
904#endif
905 }
906 splx(s);
907 break;
908 case TIOCSCTTY: /* become controlling tty */
909 /* Session ctty vnode pointer set in vnode layer. */
910 if (!SESS_LEADER(p) ||
911 ((p->p_session->s_ttyvp || tp->t_session) &&
912 (tp->t_session != p->p_session)))
913 return (EPERM);
914 tp->t_session = p->p_session;
915 tp->t_pgrp = p->p_pgrp;
916 p->p_session->s_ttyp = tp;
917 p->p_flag |= P_CONTROLT;
918 break;
919 case TIOCSPGRP: { /* set pgrp of tty */
920 register struct pgrp *pgrp = pgfind(*(int *)data);
921
922 if (!isctty(p, tp))
923 return (ENOTTY);
924 else if (pgrp == NULL || pgrp->pg_session != p->p_session)
925 return (EPERM);
926 tp->t_pgrp = pgrp;
927 break;
928 }
929 case TIOCSTAT: /* simulate control-T */
930 ttyinfo(tp);
931 break;
932 case TIOCSWINSZ: /* set window size */
933 if (bcmp((caddr_t)&tp->t_winsize, data,
934 sizeof (struct winsize))) {
935 tp->t_winsize = *(struct winsize *)data;
936 pgsignal(tp->t_pgrp, SIGWINCH, 1);
937 }
938 break;
939 case TIOCSDRAINWAIT:
940 error = suser(p->p_ucred, &p->p_acflag);
941 if (error)
942 return (error);
943 tp->t_timeout = *(int *)data * hz;
944 wakeup((caddr_t)&tp->t_outq);
945 break;
946 case TIOCGDRAINWAIT:
947 *(int *)data = tp->t_timeout / hz;
948 break;
949 default:
950#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
951 return (ttcompat(tp, cmd, data, flag));
952#else
953 return (-1);
954#endif
955 }
956 return (0);
957}
958
959int
960ttyselect(tp, rw, p)
961 struct tty *tp;
962 int rw;
963 struct proc *p;
964{
965 int nread, s;
966
967 if (tp == NULL)
968 return (ENXIO);
969
970 s = spltty();
971 switch (rw) {
972 case FREAD:
973 nread = ttnread(tp);
974 if (nread > 0 || (!ISSET(tp->t_cflag, CLOCAL) &&
975 !ISSET(tp->t_state, TS_CARR_ON)))
976 goto win;
977 selrecord(p, &tp->t_rsel);
978 break;
979 case FWRITE:
980 if (tp->t_outq.c_cc <= tp->t_lowat) {
981win: splx(s);
982 return (1);
983 }
984 selrecord(p, &tp->t_wsel);
985 break;
986 }
987 splx(s);
988 return (0);
989}
990
991/*
992 * This is a wrapper for compatibility with the select vector used by
993 * cdevsw. It relies on a proper xxxdevtotty routine.
994 */
995int
996ttselect(dev, rw, p)
997 dev_t dev;
998 int rw;
999 struct proc *p;
1000{
1001 return ttyselect((*cdevsw[major(dev)].d_devtotty)(dev), rw, p);
1002}
1003
1004/*
1005 * This is now exported to the cy driver as well; if you hack this code,
1006 * then be sure to keep /sys/i386/isa/cy.c properly advised! -jkh
1007 */
1008int
1009ttnread(tp)
1010 struct tty *tp;
1011{
1012 int nread;
1013
1014 if (ISSET(tp->t_lflag, PENDIN))
1015 ttypend(tp);
1016 nread = tp->t_canq.c_cc;
1017 if (!ISSET(tp->t_lflag, ICANON)) {
1018 nread += tp->t_rawq.c_cc;
1019 if (nread < tp->t_cc[VMIN] && tp->t_cc[VTIME] == 0)
1020 nread = 0;
1021 }
1022 return (nread);
1023}
1024
1025/*
1026 * Wait for output to drain.
1027 */
1028int
1029ttywait(tp)
1030 register struct tty *tp;
1031{
1032 int error, s;
1033
1034 error = 0;
1035 s = spltty();
1036 while ((tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)) &&
1037 (ISSET(tp->t_state, TS_CARR_ON) || ISSET(tp->t_cflag, CLOCAL))
1038 && tp->t_oproc) {
1039 (*tp->t_oproc)(tp);
1040 if ((tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)) &&
1041 (ISSET(tp->t_state, TS_CARR_ON) || ISSET(tp->t_cflag, CLOCAL))) {
1042 SET(tp->t_state, TS_ASLEEP);
1043 error = ttysleep(tp, &tp->t_outq, TTOPRI | PCATCH,
1044 ttyout, tp->t_timeout);
1045 if (error)
1046 break;
1047 }
1048 }
1049 if (!error && (tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)))
1050 error = EIO;
1051 splx(s);
1052 return (error);
1053}
1054
1055/*
1056 * Flush if successfully wait.
1057 */
1058int
1059ttywflush(tp)
1060 struct tty *tp;
1061{
1062 int error;
1063
1064 if ((error = ttywait(tp)) == 0)
1065 ttyflush(tp, FREAD);
1066 return (error);
1067}
1068
1069/*
1070 * Flush tty read and/or write queues, notifying anyone waiting.
1071 */
1072void
1073ttyflush(tp, rw)
1074 register struct tty *tp;
1075 int rw;
1076{
1077 register int s;
1078
1079 s = spltty();
1080 if (rw & FWRITE)
1081 CLR(tp->t_state, TS_TTSTOP);
1082#ifdef sun4c /* XXX */
1083 (*tp->t_stop)(tp, rw);
1084#else
1085 (*cdevsw[major(tp->t_dev)].d_stop)(tp, rw);
1086#endif
1087 if (rw & FREAD) {
1088 FLUSHQ(&tp->t_canq);
1089 FLUSHQ(&tp->t_rawq);
1090 tp->t_rocount = 0;
1091 tp->t_rocol = 0;
1092 CLR(tp->t_state, TS_LOCAL);
1093 ttwakeup(tp);
1094 }
1095 if (rw & FWRITE) {
1096 FLUSHQ(&tp->t_outq);
1097 wakeup((caddr_t)&tp->t_outq);
1098 selwakeup(&tp->t_wsel);
1099 }
1100 if ((rw & FREAD) &&
1101 ISSET(tp->t_state, TS_TBLOCK) && tp->t_rawq.c_cc < TTYHOG/5) {
1102 int queue_full = 0;
1103
1104 if (ISSET(tp->t_iflag, IXOFF) &&
1105 tp->t_cc[VSTART] != _POSIX_VDISABLE &&
1106 (queue_full = putc(tp->t_cc[VSTART], &tp->t_outq)) == 0 ||
1107 ISSET(tp->t_cflag, CRTS_IFLOW)) {
1108 CLR(tp->t_state, TS_TBLOCK);
1109 ttstart(tp);
1110 if (queue_full) /* try again */
1111 SET(tp->t_state, TS_TBLOCK);
1112 }
1113 }
1114 splx(s);
1115}
1116
1117/*
1118 * Copy in the default termios characters.
1119 */
1120void
1121ttychars(tp)
1122 struct tty *tp;
1123{
1124
1125 bcopy(ttydefchars, tp->t_cc, sizeof(ttydefchars));
1126}
1127
1128/*
1129 * Send stop character on input overflow.
1130 */
1131static void
1132ttyblock(tp)
1133 register struct tty *tp;
1134{
1135 register int total;
1136
1137 total = tp->t_rawq.c_cc + tp->t_canq.c_cc;
1138 /*
1139 * Block further input iff: current input > threshold
1140 * AND input is available to user program.
1141 */
1142 if (total >= TTYHOG / 2 &&
1143 !ISSET(tp->t_state, TS_TBLOCK) &&
1144 (!ISSET(tp->t_lflag, ICANON) || tp->t_canq.c_cc > 0)) {
1145 int queue_full = 0;
1146
1147 if (ISSET(tp->t_iflag, IXOFF) &&
1148 tp->t_cc[VSTOP] != _POSIX_VDISABLE &&
1149 (queue_full = putc(tp->t_cc[VSTOP], &tp->t_outq)) == 0 ||
1150 ISSET(tp->t_cflag, CRTS_IFLOW)) {
1151 SET(tp->t_state, TS_TBLOCK);
1152 ttstart(tp);
1153 if (queue_full) /* try again */
1154 CLR(tp->t_state, TS_TBLOCK);
1155 }
1156 }
1157}
1158
1159void
1160ttrstrt(tp_arg)
1161 void *tp_arg;
1162{
1163 struct tty *tp;
1164 int s;
1165
1166#ifdef DIAGNOSTIC
1167 if (tp_arg == NULL)
1168 panic("ttrstrt");
1169#endif
1170 tp = tp_arg;
1171 s = spltty();
1172
1173 CLR(tp->t_state, TS_TIMEOUT);
1174 ttstart(tp);
1175
1176 splx(s);
1177}
1178
1179int
1180ttstart(tp)
1181 struct tty *tp;
1182{
1183
1184 if (tp->t_oproc != NULL) /* XXX: Kludge for pty. */
1185 (*tp->t_oproc)(tp);
1186 return (0);
1187}
1188
1189/*
1190 * "close" a line discipline
1191 */
1192int
1193ttylclose(tp, flag)
1194 struct tty *tp;
1195 int flag;
1196{
1197
1198 if ((flag & IO_NDELAY) || ttywflush(tp))
1199 ttyflush(tp, FREAD | FWRITE);
1200 return (0);
1201}
1202
1203/*
1204 * Handle modem control transition on a tty.
1205 * Flag indicates new state of carrier.
1206 * Returns 0 if the line should be turned off, otherwise 1.
1207 */
1208int
1209ttymodem(tp, flag)
1210 register struct tty *tp;
1211 int flag;
1212{
1213
1214 if (!ISSET(tp->t_state, TS_WOPEN) && ISSET(tp->t_cflag, MDMBUF)) {
1215 /*
1216 * MDMBUF: do flow control according to carrier flag
1217 */
1218 if (flag) {
1219 CLR(tp->t_state, TS_TTSTOP);
1220 ttstart(tp);
1221 } else if (!ISSET(tp->t_state, TS_TTSTOP)) {
1222 SET(tp->t_state, TS_TTSTOP);
1223#ifdef sun4c /* XXX */
1224 (*tp->t_stop)(tp, 0);
1225#else
1226 (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
1227#endif
1228 }
1229 } else if (flag == 0) {
1230 /*
1231 * Lost carrier.
1232 */
1233 CLR(tp->t_state, TS_CARR_ON);
1234 if (ISSET(tp->t_state, TS_ISOPEN) &&
1235 !ISSET(tp->t_cflag, CLOCAL)) {
1236 if (tp->t_session && tp->t_session->s_leader)
1237 psignal(tp->t_session->s_leader, SIGHUP);
1238 ttyflush(tp, FREAD | FWRITE);
1239 return (0);
1240 }
1241 } else {
1242 /*
1243 * Carrier now on.
1244 */
1245 SET(tp->t_state, TS_CARR_ON);
1246 ttwakeup(tp);
1247 }
1248 return (1);
1249}
1250
1251/*
1252 * Default modem control routine (for other line disciplines).
1253 * Return argument flag, to turn off device on carrier drop.
1254 */
1255int
1256nullmodem(tp, flag)
1257 register struct tty *tp;
1258 int flag;
1259{
1260
1261 if (flag)
1262 SET(tp->t_state, TS_CARR_ON);
1263 else {
1264 CLR(tp->t_state, TS_CARR_ON);
1265 if (!ISSET(tp->t_cflag, CLOCAL)) {
1266 if (tp->t_session && tp->t_session->s_leader)
1267 psignal(tp->t_session->s_leader, SIGHUP);
1268 return (0);
1269 }
1270 }
1271 return (1);
1272}
1273
1274/*
1275 * Reinput pending characters after state switch
1276 * call at spltty().
1277 */
1278void
1279ttypend(tp)
1280 register struct tty *tp;
1281{
1282 struct clist tq;
1283 register c;
1284
1285 CLR(tp->t_lflag, PENDIN);
1286 SET(tp->t_state, TS_TYPEN);
1287 /*
1288 * XXX this assumes too much about clist internals. It may even
1289 * fail if the cblock slush pool is empty. We can't allocate more
1290 * cblocks here because we are called from an interrupt handler
1291 * and clist_alloc_cblocks() can wait.
1292 */
1293 tq = tp->t_rawq;
1294 bzero(&tp->t_rawq, sizeof tp->t_rawq);
1295 tp->t_rawq.c_cbmax = tq.c_cbmax;
1296 tp->t_rawq.c_cbreserved = tq.c_cbreserved;
1297 while ((c = getc(&tq)) >= 0)
1298 ttyinput(c, tp);
1299 CLR(tp->t_state, TS_TYPEN);
1300}
1301
1302/*
1303 * Process a read call on a tty device.
1304 */
1305int
1306ttread(tp, uio, flag)
1307 register struct tty *tp;
1308 struct uio *uio;
1309 int flag;
1310{
1311 register struct clist *qp;
1312 register int c;
1313 register tcflag_t lflag;
1314 register cc_t *cc = tp->t_cc;
1315 register struct proc *p = curproc;
1316 int s, first, error = 0, carrier;
1317 int has_stime = 0, last_cc = 0;
1318 long slp = 0; /* XXX this should be renamed `timo'. */
1319
1320loop:
1321 s = spltty();
1322 lflag = tp->t_lflag;
1323 /*
1324 * take pending input first
1325 */
1326 if (ISSET(lflag, PENDIN)) {
1327 ttypend(tp);
1328 splx(s); /* reduce latency */
1329 s = spltty();
1330 lflag = tp->t_lflag; /* XXX ttypend() clobbers it */
1331 }
1332
1333 /*
1334 * Hang process if it's in the background.
1335 */
1336 if (isbackground(p, tp)) {
1337 splx(s);
1338 if ((p->p_sigignore & sigmask(SIGTTIN)) ||
1339 (p->p_sigmask & sigmask(SIGTTIN)) ||
1340 p->p_flag & P_PPWAIT || p->p_pgrp->pg_jobc == 0)
1341 return (EIO);
1342 pgsignal(p->p_pgrp, SIGTTIN, 1);
1343 error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, ttybg, 0);
1344 if (error)
1345 return (error);
1346 goto loop;
1347 }
1348
1349 /*
1350 * If canonical, use the canonical queue,
1351 * else use the raw queue.
1352 *
1353 * (should get rid of clists...)
1354 */
1355 qp = ISSET(lflag, ICANON) ? &tp->t_canq : &tp->t_rawq;
1356
1357 if (flag & IO_NDELAY) {
1358 if (qp->c_cc > 0)
1359 goto read;
1360 carrier = ISSET(tp->t_state, TS_CARR_ON) ||
1361 ISSET(tp->t_cflag, CLOCAL);
1362 if ((!carrier && ISSET(tp->t_state, TS_ISOPEN)) ||
1363 !ISSET(lflag, ICANON) && cc[VMIN] == 0) {
1364 splx(s);
1365 return (0);
1366 }
1367 splx(s);
1368 return (EWOULDBLOCK);
1369 }
1370 if (!ISSET(lflag, ICANON)) {
1371 int m = cc[VMIN];
1372 long t = cc[VTIME];
1373 struct timeval stime, timecopy;
1374 int x;
1375
1376 /*
1377 * Check each of the four combinations.
1378 * (m > 0 && t == 0) is the normal read case.
1379 * It should be fairly efficient, so we check that and its
1380 * companion case (m == 0 && t == 0) first.
1381 * For the other two cases, we compute the target sleep time
1382 * into slp.
1383 */
1384 if (t == 0) {
1385 if (qp->c_cc < m)
1386 goto sleep;
1387 if (qp->c_cc > 0)
1388 goto read;
1389
1390 /* m, t and qp->c_cc are all 0. 0 is enough input. */
1391 splx(s);
1392 return (0);
1393 }
1394 t *= 100000; /* time in us */
1395#define diff(t1, t2) (((t1).tv_sec - (t2).tv_sec) * 1000000 + \
1396 ((t1).tv_usec - (t2).tv_usec))
1397 if (m > 0) {
1398 if (qp->c_cc <= 0)
1399 goto sleep;
1400 if (qp->c_cc >= m)
1401 goto read;
1402 x = splclock();
1403 timecopy = time;
1404 splx(x);
1405 if (!has_stime) {
1406 /* first character, start timer */
1407 has_stime = 1;
1408 stime = timecopy;
1409 slp = t;
1410 } else if (qp->c_cc > last_cc) {
1411 /* got a character, restart timer */
1412 stime = timecopy;
1413 slp = t;
1414 } else {
1415 /* nothing, check expiration */
1416 slp = t - diff(timecopy, stime);
1417 if (slp <= 0)
1418 goto read;
1419 }
1420 last_cc = qp->c_cc;
1421 } else { /* m == 0 */
1422 if (qp->c_cc > 0)
1423 goto read;
1424 x = splclock();
1425 timecopy = time;
1426 splx(x);
1427 if (!has_stime) {
1428 has_stime = 1;
1429 stime = timecopy;
1430 slp = t;
1431 } else {
1432 slp = t - diff(timecopy, stime);
1433 if (slp <= 0) {
1434 /* Timed out, but 0 is enough input. */
1435 splx(s);
1436 return (0);
1437 }
1438 }
1439 }
1440#undef diff
1441 /*
1442 * Rounding down may make us wake up just short
1443 * of the target, so we round up.
1444 * The formula is ceiling(slp * hz/1000000).
1445 * 32-bit arithmetic is enough for hz < 169.
1446 * XXX see hzto() for how to avoid overflow if hz
1447 * is large (divide by `tick' and/or arrange to
1448 * use hzto() if hz is large).
1449 */
1450 slp = (long) (((u_long)slp * hz) + 999999) / 1000000;
1451 goto sleep;
1452 }
1453
1454 /*
1455 * If there is no input, sleep on rawq
1456 * awaiting hardware receipt and notification.
1457 * If we have data, we don't need to check for carrier.
1458 */
1459 if (qp->c_cc <= 0) {
1460sleep:
1461 carrier = ISSET(tp->t_state, TS_CARR_ON) ||
1462 ISSET(tp->t_cflag, CLOCAL);
1463 if (!carrier && ISSET(tp->t_state, TS_ISOPEN)) {
1464 splx(s);
1465 return (0); /* EOF */
1466 }
1467 error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH,
1468 carrier ? ttyin : ttopen, (int)slp);
1469 splx(s);
1470 if (error == EWOULDBLOCK)
1471 error = 0;
1472 else if (error)
1473 return (error);
1474 /*
1475 * XXX what happens if another process eats some input
1476 * while we are asleep (not just here)? It would be
1477 * safest to detect changes and reset our state variables
1478 * (has_stime and last_cc).
1479 */
1480 slp = 0;
1481 goto loop;
1482 }
1483read:
1484 splx(s);
1485 /*
1486 * Input present, check for input mapping and processing.
1487 */
1488 first = 1;
1489 while ((c = getc(qp)) >= 0) {
1490 /*
1491 * delayed suspend (^Y)
1492 */
1493 if (CCEQ(cc[VDSUSP], c) && ISSET(lflag, ISIG)) {
1494 pgsignal(tp->t_pgrp, SIGTSTP, 1);
1495 if (first) {
1496 error = ttysleep(tp,
1497 &lbolt, TTIPRI | PCATCH, ttybg, 0);
1498 if (error)
1499 break;
1500 goto loop;
1501 }
1502 break;
1503 }
1504 /*
1505 * Interpret EOF only in canonical mode.
1506 */
1507 if (CCEQ(cc[VEOF], c) && ISSET(lflag, ICANON))
1508 break;
1509
1510#if NSNP > 0
1511 /*
1512 * Only when tty echoes characters , we want to
1513 * feed them to the snoop device.Else they will come
1514 * there if the application would like to.
1515 */
1516 if (ISSET(tp->t_lflag, ECHO))
1517 if (ISSET(tp->t_state, TS_SNOOP) && tp->t_sc != NULL)
1518 snpinc((struct snoop *)tp->t_sc, (char)c);
1519#endif
1520
1521 /*
1522 * Give user character.
1523 */
1524 error = ureadc(c, uio);
1525 if (error)
1526 break;
1527 if (uio->uio_resid == 0)
1528 break;
1529 /*
1530 * In canonical mode check for a "break character"
1531 * marking the end of a "line of input".
1532 */
1533 if (ISSET(lflag, ICANON) && TTBREAKC(c))
1534 break;
1535 first = 0;
1536 }
1537 /*
1538 * Look to unblock output now that (presumably)
1539 * the input queue has gone down.
1540 */
1541 s = spltty();
1542 if (ISSET(tp->t_state, TS_TBLOCK) && tp->t_rawq.c_cc < TTYHOG/5) {
1543 int queue_full = 0;
1544
1545 if (ISSET(tp->t_iflag, IXOFF) &&
1546 cc[VSTART] != _POSIX_VDISABLE &&
1547 (queue_full = putc(cc[VSTART], &tp->t_outq)) == 0 ||
1548 ISSET(tp->t_cflag, CRTS_IFLOW)) {
1549 CLR(tp->t_state, TS_TBLOCK);
1550 ttstart(tp);
1551 if (queue_full) /* try again */
1552 SET(tp->t_state, TS_TBLOCK);
1553 }
1554 }
1555 splx(s);
1556 return (error);
1557}
1558
1559/*
1560 * Check the output queue on tp for space for a kernel message (from uprintf
1561 * or tprintf). Allow some space over the normal hiwater mark so we don't
1562 * lose messages due to normal flow control, but don't let the tty run amok.
1563 * Sleeps here are not interruptible, but we return prematurely if new signals
1564 * arrive.
1565 */
1566int
1567ttycheckoutq(tp, wait)
1568 register struct tty *tp;
1569 int wait;
1570{
1571 int hiwat, s, oldsig;
1572
1573 hiwat = tp->t_hiwat;
1574 s = spltty();
1575 oldsig = wait ? curproc->p_siglist : 0;
1576 if (tp->t_outq.c_cc > hiwat + 200)
1577 while (tp->t_outq.c_cc > hiwat) {
1578 ttstart(tp);
1579 if (wait == 0 || curproc->p_siglist != oldsig) {
1580 splx(s);
1581 return (0);
1582 }
1583 timeout((void (*)__P((void *)))wakeup,
1584 (void *)&tp->t_outq, hz);
1585 SET(tp->t_state, TS_ASLEEP);
1586 (void) tsleep((caddr_t)&tp->t_outq, PZERO - 1, "ttoutq", 0);
1587 }
1588 splx(s);
1589 return (1);
1590}
1591
1592/*
1593 * Process a write call on a tty device.
1594 */
1595int
1596ttwrite(tp, uio, flag)
1597 register struct tty *tp;
1598 register struct uio *uio;
1599 int flag;
1600{
1601 register char *cp = 0;
1602 register int cc, ce;
1603 register struct proc *p;
1604 int i, hiwat, cnt, error, s;
1605 char obuf[OBUFSIZ];
1606
1607 hiwat = tp->t_hiwat;
1608 cnt = uio->uio_resid;
1609 error = 0;
1610 cc = 0;
1611loop:
1612 s = spltty();
1613 if (!ISSET(tp->t_state, TS_CARR_ON) &&
1614 !ISSET(tp->t_cflag, CLOCAL)) {
1615 if (ISSET(tp->t_state, TS_ISOPEN)) {
1616 splx(s);
1617 return (EIO);
1618 } else if (flag & IO_NDELAY) {
1619 splx(s);
1620 error = EWOULDBLOCK;
1621 goto out;
1622 } else {
1623 /* Sleep awaiting carrier. */
1624 error = ttysleep(tp,
1625 &tp->t_rawq, TTIPRI | PCATCH,ttopen, 0);
1626 splx(s);
1627 if (error)
1628 goto out;
1629 goto loop;
1630 }
1631 }
1632 splx(s);
1633 /*
1634 * Hang the process if it's in the background.
1635 */
1636 p = curproc;
1637 if (isbackground(p, tp) &&
1638 ISSET(tp->t_lflag, TOSTOP) && (p->p_flag & P_PPWAIT) == 0 &&
1639 (p->p_sigignore & sigmask(SIGTTOU)) == 0 &&
1640 (p->p_sigmask & sigmask(SIGTTOU)) == 0 &&
1641 p->p_pgrp->pg_jobc) {
1642 pgsignal(p->p_pgrp, SIGTTOU, 1);
1643 error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, ttybg, 0);
1644 if (error)
1645 goto out;
1646 goto loop;
1647 }
1648 /*
1649 * Process the user's data in at most OBUFSIZ chunks. Perform any
1650 * output translation. Keep track of high water mark, sleep on
1651 * overflow awaiting device aid in acquiring new space.
1652 */
1653 while (uio->uio_resid > 0 || cc > 0) {
1654 if (ISSET(tp->t_lflag, FLUSHO)) {
1655 uio->uio_resid = 0;
1656 return (0);
1657 }
1658 if (tp->t_outq.c_cc > hiwat)
1659 goto ovhiwat;
1660 /*
1661 * Grab a hunk of data from the user, unless we have some
1662 * leftover from last time.
1663 */
1664 if (cc == 0) {
1665 cc = min(uio->uio_resid, OBUFSIZ);
1666 cp = obuf;
1667 error = uiomove(cp, cc, uio);
1668 if (error) {
1669 cc = 0;
1670 break;
1671 }
1672#if NSNP > 0
1673 if (ISSET(tp->t_state, TS_SNOOP) && tp->t_sc != NULL)
1674 snpin((struct snoop *)tp->t_sc, cp, cc);
1675#endif
1676 }
1677 /*
1678 * If nothing fancy need be done, grab those characters we
1679 * can handle without any of ttyoutput's processing and
1680 * just transfer them to the output q. For those chars
1681 * which require special processing (as indicated by the
1682 * bits in char_type), call ttyoutput. After processing
1683 * a hunk of data, look for FLUSHO so ^O's will take effect
1684 * immediately.
1685 */
1686 while (cc > 0) {
1687 if (!ISSET(tp->t_oflag, OPOST))
1688 ce = cc;
1689 else {
1690 ce = cc - scanc((u_int)cc, (u_char *)cp,
1691 (u_char *)char_type, CCLASSMASK);
1692 /*
1693 * If ce is zero, then we're processing
1694 * a special character through ttyoutput.
1695 */
1696 if (ce == 0) {
1697 tp->t_rocount = 0;
1698 if (ttyoutput(*cp, tp) >= 0) {
1699 /* No Clists, wait a bit. */
1700 ttstart(tp);
1701 if (flag & IO_NDELAY) {
1702 error = EWOULDBLOCK;
1703 goto out;
1704 }
1705 error = ttysleep(tp, &lbolt,
1706 TTOPRI | PCATCH, ttybuf, 0);
1707 if (error)
1708 goto out;
1709 goto loop;
1710 }
1711 cp++;
1712 cc--;
1713 if (ISSET(tp->t_lflag, FLUSHO) ||
1714 tp->t_outq.c_cc > hiwat)
1715 goto ovhiwat;
1716 continue;
1717 }
1718 }
1719 /*
1720 * A bunch of normal characters have been found.
1721 * Transfer them en masse to the output queue and
1722 * continue processing at the top of the loop.
1723 * If there are any further characters in this
1724 * <= OBUFSIZ chunk, the first should be a character
1725 * requiring special handling by ttyoutput.
1726 */
1727 tp->t_rocount = 0;
1728 i = b_to_q(cp, ce, &tp->t_outq);
1729 ce -= i;
1730 tp->t_column += ce;
1731 cp += ce, cc -= ce, tk_nout += ce;
1732 tp->t_outcc += ce;
1733 if (i > 0) {
1734 /* No Clists, wait a bit. */
1735 ttstart(tp);
1736 if (flag & IO_NDELAY) {
1737 error = EWOULDBLOCK;
1738 goto out;
1739 }
1740 error = ttysleep(tp,
1741 &lbolt, TTOPRI | PCATCH, ttybuf, 0);
1742 if (error)
1743 goto out;
1744 goto loop;
1745 }
1746 if (ISSET(tp->t_lflag, FLUSHO) ||
1747 tp->t_outq.c_cc > hiwat)
1748 break;
1749 }
1750 ttstart(tp);
1751 }
1752out:
1753 /*
1754 * If cc is nonzero, we leave the uio structure inconsistent, as the
1755 * offset and iov pointers have moved forward, but it doesn't matter
1756 * (the call will either return short or restart with a new uio).
1757 */
1758 uio->uio_resid += cc;
1759 return (error);
1760
1761ovhiwat:
1762 ttstart(tp);
1763 s = spltty();
1764 /*
1765 * This can only occur if FLUSHO is set in t_lflag,
1766 * or if ttstart/oproc is synchronous (or very fast).
1767 */
1768 if (tp->t_outq.c_cc <= hiwat) {
1769 splx(s);
1770 goto loop;
1771 }
1772 if (flag & IO_NDELAY) {
1773 splx(s);
1774 uio->uio_resid += cc;
1775 return (uio->uio_resid == cnt ? EWOULDBLOCK : 0);
1776 }
1777 SET(tp->t_state, TS_ASLEEP);
1778 error = ttysleep(tp, &tp->t_outq, TTOPRI | PCATCH, ttyout, 0);
1779 splx(s);
1780 if (error)
1781 goto out;
1782 goto loop;
1783}
1784
1785/*
1786 * Rubout one character from the rawq of tp
1787 * as cleanly as possible.
1788 */
1789void
1790ttyrub(c, tp)
1791 register int c;
1792 register struct tty *tp;
1793{
1794 register char *cp;
1795 register int savecol;
1796 int tabc, s;
1797
1798 if (!ISSET(tp->t_lflag, ECHO) || ISSET(tp->t_lflag, EXTPROC))
1799 return;
1800 CLR(tp->t_lflag, FLUSHO);
1801 if (ISSET(tp->t_lflag, ECHOE)) {
1802 if (tp->t_rocount == 0) {
1803 /*
1804 * Screwed by ttwrite; retype
1805 */
1806 ttyretype(tp);
1807 return;
1808 }
1809 if (c == ('\t' | TTY_QUOTE) || c == ('\n' | TTY_QUOTE))
1810 ttyrubo(tp, 2);
1811 else {
1812 CLR(c, ~TTY_CHARMASK);
1813 switch (CCLASS(c)) {
1814 case ORDINARY:
1815 ttyrubo(tp, 1);
1816 break;
1817 case BACKSPACE:
1818 case CONTROL:
1819 case NEWLINE:
1820 case RETURN:
1821 case VTAB:
1822 if (ISSET(tp->t_lflag, ECHOCTL))
1823 ttyrubo(tp, 2);
1824 break;
1825 case TAB:
1826 if (tp->t_rocount < tp->t_rawq.c_cc) {
1827 ttyretype(tp);
1828 return;
1829 }
1830 s = spltty();
1831 savecol = tp->t_column;
1832 SET(tp->t_state, TS_CNTTB);
1833 SET(tp->t_lflag, FLUSHO);
1834 tp->t_column = tp->t_rocol;
1835 cp = tp->t_rawq.c_cf;
1836 if (cp)
1837 tabc = *cp; /* XXX FIX NEXTC */
1838 for (; cp; cp = nextc(&tp->t_rawq, cp, &tabc))
1839 ttyecho(tabc, tp);
1840 CLR(tp->t_lflag, FLUSHO);
1841 CLR(tp->t_state, TS_CNTTB);
1842 splx(s);
1843
1844 /* savecol will now be length of the tab. */
1845 savecol -= tp->t_column;
1846 tp->t_column += savecol;
1847 if (savecol > 8)
1848 savecol = 8; /* overflow screw */
1849 while (--savecol >= 0)
1850 (void)ttyoutput('\b', tp);
1851 break;
1852 default: /* XXX */
1853#define PANICSTR "ttyrub: would panic c = %d, val = %d\n"
1854 (void)printf(PANICSTR, c, CCLASS(c));
1855#ifdef notdef
1856 panic(PANICSTR, c, CCLASS(c));
1857#endif
1858 }
1859 }
1860 } else if (ISSET(tp->t_lflag, ECHOPRT)) {
1861 if (!ISSET(tp->t_state, TS_ERASE)) {
1862 SET(tp->t_state, TS_ERASE);
1863 (void)ttyoutput('\\', tp);
1864 }
1865 ttyecho(c, tp);
1866 } else
1867 ttyecho(tp->t_cc[VERASE], tp);
1868 --tp->t_rocount;
1869}
1870
1871/*
1872 * Back over cnt characters, erasing them.
1873 */
1874static void
1875ttyrubo(tp, cnt)
1876 register struct tty *tp;
1877 int cnt;
1878{
1879
1880 while (cnt-- > 0) {
1881 (void)ttyoutput('\b', tp);
1882 (void)ttyoutput(' ', tp);
1883 (void)ttyoutput('\b', tp);
1884 }
1885}
1886
1887/*
1888 * ttyretype --
1889 * Reprint the rawq line. Note, it is assumed that c_cc has already
1890 * been checked.
1891 */
1892void
1893ttyretype(tp)
1894 register struct tty *tp;
1895{
1896 register char *cp;
1897 int s, c;
1898
1899 /* Echo the reprint character. */
1900 if (tp->t_cc[VREPRINT] != _POSIX_VDISABLE)
1901 ttyecho(tp->t_cc[VREPRINT], tp);
1902
1903 (void)ttyoutput('\n', tp);
1904
1905 /*
1906 * XXX
1907 * FIX: NEXTC IS BROKEN - DOESN'T CHECK QUOTE
1908 * BIT OF FIRST CHAR.
1909 */
1910 s = spltty();
1911 for (cp = tp->t_canq.c_cf, c = (cp != NULL ? *cp : 0);
1912 cp != NULL; cp = nextc(&tp->t_canq, cp, &c))
1913 ttyecho(c, tp);
1914 for (cp = tp->t_rawq.c_cf, c = (cp != NULL ? *cp : 0);
1915 cp != NULL; cp = nextc(&tp->t_rawq, cp, &c))
1916 ttyecho(c, tp);
1917 CLR(tp->t_state, TS_ERASE);
1918 splx(s);
1919
1920 tp->t_rocount = tp->t_rawq.c_cc;
1921 tp->t_rocol = 0;
1922}
1923
1924/*
1925 * Echo a typed character to the terminal.
1926 */
1927static void
1928ttyecho(c, tp)
1929 register int c;
1930 register struct tty *tp;
1931{
1932
1933 if (!ISSET(tp->t_state, TS_CNTTB))
1934 CLR(tp->t_lflag, FLUSHO);
1935 if ((!ISSET(tp->t_lflag, ECHO) &&
1936 (!ISSET(tp->t_lflag, ECHONL) || c == '\n')) ||
1937 ISSET(tp->t_lflag, EXTPROC))
1938 return;
1939 if (ISSET(tp->t_lflag, ECHOCTL) &&
1940 ((ISSET(c, TTY_CHARMASK) <= 037 && c != '\t' && c != '\n') ||
1941 ISSET(c, TTY_CHARMASK) == 0177)) {
1942 (void)ttyoutput('^', tp);
1943 CLR(c, ~TTY_CHARMASK);
1944 if (c == 0177)
1945 c = '?';
1946 else
1947 c += 'A' - 1;
1948 }
1949 (void)ttyoutput(c, tp);
1950}
1951
1952/*
1953 * Wake up any readers on a tty.
1954 */
1955void
1956ttwakeup(tp)
1957 register struct tty *tp;
1958{
1959
1960 selwakeup(&tp->t_rsel);
1961 if (ISSET(tp->t_state, TS_ASYNC))
1962 pgsignal(tp->t_pgrp, SIGIO, 1);
1963 wakeup((caddr_t)&tp->t_rawq);
1964}
1965
1966/*
1967 * Look up a code for a specified speed in a conversion table;
1968 * used by drivers to map software speed values to hardware parameters.
1969 */
1970int
1971ttspeedtab(speed, table)
1972 int speed;
1973 register struct speedtab *table;
1974{
1975
1976 for ( ; table->sp_speed != -1; table++)
1977 if (table->sp_speed == speed)
1978 return (table->sp_code);
1979 return (-1);
1980}
1981
1982/*
1983 * Set tty hi and low water marks.
1984 *
1985 * Try to arrange the dynamics so there's about one second
1986 * from hi to low water.
1987 *
1988 */
1989void
1990ttsetwater(tp)
1991 struct tty *tp;
1992{
1993 register int cps, x;
1994
1995#define CLAMP(x, h, l) ((x) > h ? h : ((x) < l) ? l : (x))
1996
1997 cps = tp->t_ospeed / 10;
1998 tp->t_lowat = x = CLAMP(cps / 2, TTMAXLOWAT, TTMINLOWAT);
1999 x += cps;
2000 x = CLAMP(x, TTMAXHIWAT, TTMINHIWAT);
2001 tp->t_hiwat = roundup(x, CBSIZE);
2002#undef CLAMP
2003}
2004
2005/*
2006 * Report on state of foreground process group.
2007 */
2008void
2009ttyinfo(tp)
2010 register struct tty *tp;
2011{
2012 register struct proc *p, *pick;
2013 struct timeval utime, stime;
2014 int tmp;
2015
2016 if (ttycheckoutq(tp,0) == 0)
2017 return;
2018
2019 /* Print load average. */
2020 tmp = (averunnable.ldavg[0] * 100 + FSCALE / 2) >> FSHIFT;
2021 ttyprintf(tp, "load: %d.%02d ", tmp / 100, tmp % 100);
2022
2023 if (tp->t_session == NULL)
2024 ttyprintf(tp, "not a controlling terminal\n");
2025 else if (tp->t_pgrp == NULL)
2026 ttyprintf(tp, "no foreground process group\n");
2027 else if ((p = tp->t_pgrp->pg_mem) == NULL)
2028 ttyprintf(tp, "empty foreground process group\n");
2029 else {
2030 /* Pick interesting process. */
2031 for (pick = NULL; p != NULL; p = p->p_pgrpnxt)
2032 if (proc_compare(pick, p))
2033 pick = p;
2034
2035 ttyprintf(tp, " cmd: %s %d [%s] ", pick->p_comm, pick->p_pid,
2036 pick->p_stat == SRUN ? "running" :
2037 pick->p_wmesg ? pick->p_wmesg : "iowait");
2038
2039 calcru(pick, &utime, &stime, NULL);
2040
2041 /* Print user time. */
2042 ttyprintf(tp, "%d.%02du ",
2043 utime.tv_sec, utime.tv_usec / 10000);
2044
2045 /* Print system time. */
2046 ttyprintf(tp, "%d.%02ds ",
2047 stime.tv_sec, stime.tv_usec / 10000);
2048
2049#define pgtok(a) (((a) * NBPG) / 1024)
2050 /* Print percentage cpu, resident set size. */
2051 tmp = (pick->p_pctcpu * 10000 + FSCALE / 2) >> FSHIFT;
2052 ttyprintf(tp, "%d%% %dk\n",
2053 tmp / 100,
2054 pick->p_stat == SIDL || pick->p_stat == SZOMB ? 0 :
2055#ifdef pmap_resident_count
2056 pgtok(pmap_resident_count(&pick->p_vmspace->vm_pmap))
2057#else
2058 pgtok(pick->p_vmspace->vm_rssize)
2059#endif
2060 );
2061 }
2062 tp->t_rocount = 0; /* so pending input will be retyped if BS */
2063}
2064
2065/*
2066 * Returns 1 if p2 is "better" than p1
2067 *
2068 * The algorithm for picking the "interesting" process is thus:
2069 *
2070 * 1) Only foreground processes are eligible - implied.
2071 * 2) Runnable processes are favored over anything else. The runner
2072 * with the highest cpu utilization is picked (p_estcpu). Ties are
2073 * broken by picking the highest pid.
2074 * 3) The sleeper with the shortest sleep time is next. With ties,
2075 * we pick out just "short-term" sleepers (P_SINTR == 0).
2076 * 4) Further ties are broken by picking the highest pid.
2077 */
2078#define ISRUN(p) (((p)->p_stat == SRUN) || ((p)->p_stat == SIDL))
2079#define TESTAB(a, b) ((a)<<1 | (b))
2080#define ONLYA 2
2081#define ONLYB 1
2082#define BOTH 3
2083
2084static int
2085proc_compare(p1, p2)
2086 register struct proc *p1, *p2;
2087{
2088
2089 if (p1 == NULL)
2090 return (1);
2091 /*
2092 * see if at least one of them is runnable
2093 */
2094 switch (TESTAB(ISRUN(p1), ISRUN(p2))) {
2095 case ONLYA:
2096 return (0);
2097 case ONLYB:
2098 return (1);
2099 case BOTH:
2100 /*
2101 * tie - favor one with highest recent cpu utilization
2102 */
2103 if (p2->p_estcpu > p1->p_estcpu)
2104 return (1);
2105 if (p1->p_estcpu > p2->p_estcpu)
2106 return (0);
2107 return (p2->p_pid > p1->p_pid); /* tie - return highest pid */
2108 }
2109 /*
2110 * weed out zombies
2111 */
2112 switch (TESTAB(p1->p_stat == SZOMB, p2->p_stat == SZOMB)) {
2113 case ONLYA:
2114 return (1);
2115 case ONLYB:
2116 return (0);
2117 case BOTH:
2118 return (p2->p_pid > p1->p_pid); /* tie - return highest pid */
2119 }
2120 /*
2121 * pick the one with the smallest sleep time
2122 */
2123 if (p2->p_slptime > p1->p_slptime)
2124 return (0);
2125 if (p1->p_slptime > p2->p_slptime)
2126 return (1);
2127 /*
2128 * favor one sleeping in a non-interruptible sleep
2129 */
2130 if (p1->p_flag & P_SINTR && (p2->p_flag & P_SINTR) == 0)
2131 return (1);
2132 if (p2->p_flag & P_SINTR && (p1->p_flag & P_SINTR) == 0)
2133 return (0);
2134 return (p2->p_pid > p1->p_pid); /* tie - return highest pid */
2135}
2136
2137/*
2138 * Output char to tty; console putchar style.
2139 */
2140int
2141tputchar(c, tp)
2142 int c;
2143 struct tty *tp;
2144{
2145 register int s;
2146
2147 s = spltty();
2148 if (ISSET(tp->t_state,
2149 TS_CARR_ON | TS_ISOPEN) != (TS_CARR_ON | TS_ISOPEN)) {
2150 splx(s);
2151 return (-1);
2152 }
2153 if (c == '\n')
2154 (void)ttyoutput('\r', tp);
2155 (void)ttyoutput(c, tp);
2156 ttstart(tp);
2157 splx(s);
2158 return (0);
2159}
2160
2161/*
2162 * Sleep on chan, returning ERESTART if tty changed while we napped and
2163 * returning any errors (e.g. EINTR/ETIMEDOUT) reported by tsleep. If
2164 * the tty is revoked, restarting a pending call will redo validation done
2165 * at the start of the call.
2166 */
2167int
2168ttysleep(tp, chan, pri, wmesg, timo)
2169 struct tty *tp;
2170 void *chan;
2171 int pri, timo;
2172 char *wmesg;
2173{
2174 int error;
2175 short gen;
2176
2177 gen = tp->t_gen;
2178 error = tsleep(chan, pri, wmesg, timo);
2179 if (error)
2180 return (error);
2181 return (tp->t_gen == gen ? 0 : ERESTART);
2182}
2183
2184/*
2185 * XXX this is usable not useful or used. Most tty drivers have
2186 * ifdefs for using ttymalloc() but assume a different interface.
2187 */
2188/*
2189 * Allocate a tty struct. Clists in the struct will be allocated by
2190 * ttyopen().
2191 */
2192struct tty *
2193ttymalloc()
2194{
2195 struct tty *tp;
2196
2197 tp = malloc(sizeof *tp, M_TTYS, M_WAITOK);
2198 bzero(tp, sizeof *tp);
2199 return (tp);
2200}
2201
2202#if 0 /* XXX not yet usable: session leader holds a ref (see kern_exit.c). */
2203/*
2204 * Free a tty struct. Clists in the struct should have been freed by
2205 * ttyclose().
2206 */
2207void
2208ttyfree(tp)
2209 struct tty *tp;
2210{
2211 free(tp, M_TTYS);
2212}
2213#endif /* 0 */