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