|
|
1.1 root 1: /*
2: * Copyright (c) 1983 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms are permitted
6: * provided that the above copyright notice and this paragraph are
7: * duplicated in all such forms and that any documentation,
8: * advertising materials, and other materials related to such
9: * distribution and use acknowledge that the software was developed
10: * by the University of California, Berkeley. The name of the
11: * University may not be used to endorse or promote products derived
12: * from this software without specific prior written permission.
13: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15: * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16: */
17:
18: #ifndef lint
19: static char sccsid[] = "@(#)wwiomux.c 3.19 (Berkeley) 6/29/88";
20: #endif /* not lint */
21:
22: #include "ww.h"
23: #include <sys/time.h>
24: #include <sys/types.h>
25: #include <fcntl.h>
26:
27: /*
28: * Multiple window output handler.
29: * The idea is to copy window outputs to the terminal, via the
30: * display package. We try to give the top most window highest
31: * priority. The only return condition is when there is keyboard
32: * input or when a child process dies which are serviced by signal
33: * catchers (wwrint() and wwchild()).
34: * When there's nothing to do, we sleep in a select().
35: * This can be done better with interrupt driven io. But that's
36: * not supported on ptys, yet.
37: * The history of this routine is interesting.
38: */
39: wwiomux()
40: {
41: register struct ww *w;
42: fd_set imask;
43: register n;
44: register char *p;
45: char c;
46: struct timeval tv;
47: char noblock;
48:
49: for (;;) {
50: if (wwinterrupt()) {
51: wwclrintr();
52: return;
53: }
54:
55: FD_ZERO(&imask);
56: noblock = 0;
57: for (w = wwhead.ww_forw; w != &wwhead; w = w->ww_forw) {
58: if (w->ww_pty < 0)
59: continue;
60: if (w->ww_obq < w->ww_obe)
61: FD_SET(w->ww_pty, &imask);
62: if (w->ww_obq > w->ww_obp && !w->ww_stopped)
63: noblock = 1;
64: }
65:
66: if (!noblock) {
67: if (wwcurwin != 0)
68: wwcurtowin(wwcurwin);
69: wwupdate();
70: wwflush();
71: setjmp(wwjmpbuf);
72: wwsetjmp = 1;
73: if (wwinterrupt()) {
74: wwsetjmp = 0;
75: wwclrintr();
76: return;
77: }
78: /*
79: * Defensive code. If somebody else (for example,
80: * wall) clears the ASYNC flag on us, we will block
81: * forever. So we need a finite timeout and set
82: * the flag again. Anything more clever will probably
83: * need even more system calls. (This is a bug
84: * in the kernel.)
85: * I don't like this one bit.
86: */
87: fcntl(0, F_SETFL, wwnewtty.ww_fflags);
88: tv.tv_sec = 30;
89: } else
90: tv.tv_sec = 0;
91: tv.tv_usec = 0;
92: wwnselect++;
93: n = select(wwdtablesize, &imask, (fd_set *)0, (fd_set *)0, &tv);
94: wwsetjmp = 0;
95:
96: if (n < 0)
97: wwnselecte++;
98: else if (n == 0)
99: wwnselectz++;
100: else
101: for (w = wwhead.ww_forw; w != &wwhead; w = w->ww_forw) {
102: if (w->ww_pty < 0 ||
103: !FD_ISSET(w->ww_pty, &imask))
104: continue;
105: wwnwread++;
106: p = w->ww_obq;
107: if (w->ww_ispty) {
108: if (p == w->ww_ob) {
109: w->ww_obp++;
110: w->ww_obq++;
111: } else
112: p--;
113: c = *p;
114: }
115: n = read(w->ww_pty, p, w->ww_obe - p);
116: if (n < 0) {
117: wwnwreade++;
118: (void) close(w->ww_pty);
119: w->ww_pty = -1;
120: } else if (n == 0) {
121: wwnwreadz++;
122: (void) close(w->ww_pty);
123: w->ww_pty = -1;
124: } else if (!w->ww_ispty) {
125: wwnwreadd++;
126: wwnwreadc += n;
127: w->ww_obq += n;
128: } else if (*p == TIOCPKT_DATA) {
129: n--;
130: wwnwreadd++;
131: wwnwreadc += n;
132: w->ww_obq += n;
133: } else {
134: wwnwreadp++;
135: if (*p & TIOCPKT_STOP)
136: w->ww_stopped = 1;
137: if (*p & TIOCPKT_START)
138: w->ww_stopped = 0;
139: if (*p & TIOCPKT_FLUSHWRITE) {
140: w->ww_stopped = 0;
141: w->ww_obq = w->ww_obp =
142: w->ww_ob;
143: }
144: }
145: if (w->ww_ispty)
146: *p = c;
147: }
148: for (w = wwhead.ww_forw; w != &wwhead; w = w->ww_forw)
149: if (w->ww_pty >= 0 && w->ww_obq > w->ww_obp &&
150: !w->ww_stopped) {
151: n = wwwrite(w, w->ww_obp,
152: w->ww_obq - w->ww_obp);
153: if ((w->ww_obp += n) == w->ww_obq)
154: w->ww_obq = w->ww_obp = w->ww_ob;
155: if (wwinterrupt()) {
156: wwclrintr();
157: return;
158: }
159: break;
160: }
161: }
162: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.