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