1 /* 2 * Copyright (c) 1983, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Edward Wang at The University of California, Berkeley. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 */ 36 37 #ifndef lint 38 static char sccsid[] = "@(#)wwiomux.c 8.1 (Berkeley) 6/6/93"; 39 static char rcsid[] = 40 "$FreeBSD: src/usr.bin/window/wwiomux.c,v 1.1.1.1.14.1 2001/05/17 09:45:01 obrien Exp $"; 41 #endif /* not lint */ 42 43 #include "ww.h" 44 #include <sys/time.h> 45 #include <sys/types.h> 46 #if !defined(OLD_TTY) && !defined(TIOCPKT_DATA) 47 #include <sys/ioctl.h> 48 #endif 49 #include <fcntl.h> 50 51 /* 52 * Multiple window output handler. 53 * The idea is to copy window outputs to the terminal, via the 54 * display package. We try to give wwcurwin highest priority. 55 * The only return conditions are when there is keyboard input 56 * and when a child process dies, which are serviced by signal 57 * catchers (wwrint() and wwchild()). 58 * When there's nothing to do, we sleep in a select(). 59 * This can be done better with interrupt driven io. But that's 60 * not supported on ptys, yet. 61 * The history of this routine is interesting. 62 */ 63 wwiomux() 64 { 65 register struct ww *w; 66 fd_set imask; 67 register n; 68 register char *p; 69 char c; 70 struct timeval tv; 71 char noblock = 0; 72 73 for (;;) { 74 if (wwinterrupt()) { 75 wwclrintr(); 76 return; 77 } 78 79 FD_ZERO(&imask); 80 n = -1; 81 for (w = wwhead.ww_forw; w != &wwhead; w = w->ww_forw) { 82 if (w->ww_pty < 0) 83 continue; 84 if (w->ww_obq < w->ww_obe) { 85 if (w->ww_pty > n) 86 n = w->ww_pty; 87 FD_SET(w->ww_pty, &imask); 88 } 89 if (w->ww_obq > w->ww_obp && !w->ww_stopped) 90 noblock = 1; 91 } 92 93 if (!noblock) { 94 if (wwcurwin != 0) 95 wwcurtowin(wwcurwin); 96 wwupdate(); 97 wwflush(); 98 (void) setjmp(wwjmpbuf); 99 wwsetjmp = 1; 100 if (wwinterrupt()) { 101 wwsetjmp = 0; 102 wwclrintr(); 103 return; 104 } 105 /* 106 * Defensive code. If somebody else (for example, 107 * wall) clears the ASYNC flag on us, we will block 108 * forever. So we need a finite timeout and set 109 * the flag again. Anything more clever will probably 110 * need even more system calls. (This is a bug 111 * in the kernel.) 112 * I don't like this one bit. 113 */ 114 (void) fcntl(0, F_SETFL, wwnewtty.ww_fflags); 115 tv.tv_sec = 30; 116 tv.tv_usec = 0; 117 } else { 118 tv.tv_sec = 0; 119 tv.tv_usec = 10000; 120 } 121 wwnselect++; 122 n = select(n + 1, &imask, (fd_set *)0, (fd_set *)0, &tv); 123 wwsetjmp = 0; 124 noblock = 0; 125 126 if (n < 0) 127 wwnselecte++; 128 else if (n == 0) 129 wwnselectz++; 130 else 131 for (w = wwhead.ww_forw; w != &wwhead; w = w->ww_forw) { 132 if (w->ww_pty < 0 || 133 !FD_ISSET(w->ww_pty, &imask)) 134 continue; 135 wwnwread++; 136 p = w->ww_obq; 137 if (w->ww_ispty) { 138 if (p == w->ww_ob) { 139 w->ww_obp++; 140 w->ww_obq++; 141 } else 142 p--; 143 c = *p; 144 } 145 n = read(w->ww_pty, p, w->ww_obe - p); 146 if (n < 0) { 147 wwnwreade++; 148 (void) close(w->ww_pty); 149 w->ww_pty = -1; 150 } else if (n == 0) { 151 wwnwreadz++; 152 (void) close(w->ww_pty); 153 w->ww_pty = -1; 154 } else if (!w->ww_ispty) { 155 wwnwreadd++; 156 wwnwreadc += n; 157 w->ww_obq += n; 158 } else if (*p == TIOCPKT_DATA) { 159 n--; 160 wwnwreadd++; 161 wwnwreadc += n; 162 w->ww_obq += n; 163 } else { 164 wwnwreadp++; 165 if (*p & TIOCPKT_STOP) 166 w->ww_stopped = 1; 167 if (*p & TIOCPKT_START) 168 w->ww_stopped = 0; 169 if (*p & TIOCPKT_FLUSHWRITE) { 170 w->ww_stopped = 0; 171 w->ww_obq = w->ww_obp = 172 w->ww_ob; 173 } 174 } 175 if (w->ww_ispty) 176 *p = c; 177 } 178 /* 179 * Try the current window first, if there is output 180 * then process it and go back to the top to try again. 181 * This can lead to starvation of the other windows, 182 * but presumably that what we want. 183 * Update will eventually happen when output from wwcurwin 184 * dies down. 185 */ 186 if ((w = wwcurwin) != 0 && w->ww_pty >= 0 && 187 w->ww_obq > w->ww_obp && !w->ww_stopped) { 188 n = wwwrite(w, w->ww_obp, w->ww_obq - w->ww_obp); 189 if ((w->ww_obp += n) == w->ww_obq) 190 w->ww_obq = w->ww_obp = w->ww_ob; 191 noblock = 1; 192 continue; 193 } 194 for (w = wwhead.ww_forw; w != &wwhead; w = w->ww_forw) 195 if (w->ww_pty >= 0 && w->ww_obq > w->ww_obp && 196 !w->ww_stopped) { 197 n = wwwrite(w, w->ww_obp, 198 w->ww_obq - w->ww_obp); 199 if ((w->ww_obp += n) == w->ww_obq) 200 w->ww_obq = w->ww_obp = w->ww_ob; 201 if (wwinterrupt()) 202 break; 203 } 204 } 205 } 206