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