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