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