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