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