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