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