xref: /original-bsd/usr.bin/window/wwiomux.c (revision fd1dcdc9)
1 #ifndef lint
2 static char sccsid[] = "@(#)wwiomux.c	3.11 05/23/84";
3 #endif
4 
5 #include "ww.h"
6 #include <sys/time.h>
7 
8 /*
9  * Multiple window output handler.
10  * The idea is to copy window outputs to the terminal, via the
11  * display package.  We try to give the top most window highest
12  * priority.  The only return condition is when there is keyboard
13  * input, which is serviced asynchronously by wwrint().
14  * When there's nothing to do, we sleep in a select().
15  * This can be done better with interrupt driven io.  But that's
16  * not supported on ptys, yet.
17  * The history of this routine is interesting.
18  */
19 wwiomux()
20 {
21 	register struct ww *w;
22 	int imask;
23 	register n;
24 	register char *p;
25 	char c;
26 	static struct timeval tv = { 0, 0 };
27 	char noblock;
28 
29 loop:
30 	if (wwinterrupt())
31 		return;
32 
33 	imask = 0;
34 	noblock = 0;
35 	for (w = wwhead.ww_forw; w != &wwhead; w = w->ww_forw) {
36 		if (w->ww_pty < 0)
37 			continue;
38 		imask |= 1 << w->ww_pty;
39 		if (w->ww_obq > w->ww_obp && !w->ww_stopped)
40 			noblock = 1;
41 	}
42 
43 	if (!noblock) {
44 		if (wwcurwin != 0)
45 			wwcurtowin(wwcurwin);
46 		wwupdate();
47 		wwflush();
48 		if (setjmp(wwjmpbuf))
49 			return;
50 		wwsetjmp = 1;
51 		if (wwinterrupt()) {
52 			wwsetjmp = 0;
53 			return;
54 		}
55 	}
56 	wwnselect++;
57 	n = select(wwdtablesize, &imask, (int *)0, (int *)0,
58 		noblock ? &tv : (struct timeval *)0);
59 	wwsetjmp = 0;
60 
61 	if (n < 0)
62 		wwnselecte++;
63 	else if (n == 0)
64 		wwnselectz++;
65 	else
66 		for (w = wwhead.ww_forw; w != &wwhead; w = w->ww_forw) {
67 			if (w->ww_pty < 0 || (imask & 1 << w->ww_pty) == 0)
68 				continue;
69 			wwnwread++;
70 			p = w->ww_obq;
71 			if (w->ww_ispty) {
72 				if (p == w->ww_ob) {
73 					w->ww_obp++;
74 					w->ww_obq++;
75 				} else
76 					p--;
77 				c = *p;
78 			}
79 			n = read(w->ww_pty, p, w->ww_obe - p);
80 			if (n < 0) {
81 				wwnwreade++;
82 				(void) close(w->ww_pty);
83 				w->ww_pty = -1;
84 				continue;
85 			} else if (n == 0) {
86 				wwnwreadz++;
87 			} else if (!w->ww_ispty) {
88 				wwnwreadd++;
89 				wwnwreadc += n;
90 				w->ww_obq += n;
91 			} else if (*p == TIOCPKT_DATA) {
92 				n--;
93 				wwnwreadd++;
94 				wwnwreadc += n;
95 				w->ww_obq += n;
96 			} else {
97 				wwnwreadp++;
98 				if (*p & TIOCPKT_STOP)
99 					w->ww_stopped = 1;
100 				if (*p & TIOCPKT_START)
101 					w->ww_stopped = 0;
102 				if (*p & TIOCPKT_FLUSHWRITE) {
103 					w->ww_stopped = 0;
104 					w->ww_obq = w->ww_obp = w->ww_ob;
105 				}
106 			}
107 			if (w->ww_ispty)
108 				*p = c;
109 		}
110 	for (w = wwhead.ww_forw; w != &wwhead; w = w->ww_forw)
111 		if (w->ww_pty >= 0 && w->ww_obq > w->ww_obp && !w->ww_stopped) {
112 			n = wwwrite(w, w->ww_obp, w->ww_obq - w->ww_obp);
113 			if ((w->ww_obp += n) == w->ww_obq)
114 				w->ww_obq = w->ww_obp = w->ww_ob;
115 			if (wwinterrupt())
116 				return;
117 			break;
118 		}
119 	goto loop;
120 }
121