118744Sedward /* 233514Sbostic * Copyright (c) 1983 Regents of the University of California. 333514Sbostic * All rights reserved. 433514Sbostic * 5*42835Sbostic * %sccs.include.redist.c% 618744Sedward */ 718744Sedward 833514Sbostic #ifndef lint 9*42835Sbostic static char sccsid[] = "@(#)wwiomux.c 3.24 (Berkeley) 06/02/90"; 1033514Sbostic #endif /* not lint */ 1133514Sbostic 1213923Sedward #include "ww.h" 1315872Sedward #include <sys/time.h> 1424958Sedward #include <sys/types.h> 1542834Sedward #ifdef POSIX_TTY 1642834Sedward #include <sys/ioctl.h> 1742834Sedward #endif 1833751Sedward #include <fcntl.h> 1913923Sedward 2015872Sedward /* 2116124Sedward * Multiple window output handler. 2216124Sedward * The idea is to copy window outputs to the terminal, via the 2335342Sedward * display package. We try to give wwcurwin highest priority. 2435342Sedward * The only return conditions are when there is keyboard input 2535342Sedward * and when a child process dies, which are serviced by signal 2631443Sedward * catchers (wwrint() and wwchild()). 2716124Sedward * When there's nothing to do, we sleep in a select(). 2816124Sedward * This can be done better with interrupt driven io. But that's 2916124Sedward * not supported on ptys, yet. 3016124Sedward * The history of this routine is interesting. 3115872Sedward */ 3215872Sedward wwiomux() 3313923Sedward { 3415872Sedward register struct ww *w; 3524958Sedward fd_set imask; 3616124Sedward register n; 3715872Sedward register char *p; 3815872Sedward char c; 3933751Sedward struct timeval tv; 4036800Sedward char noblock = 0; 4113923Sedward 4231443Sedward for (;;) { 4316124Sedward if (wwinterrupt()) { 4431443Sedward wwclrintr(); 4516124Sedward return; 4616124Sedward } 4716124Sedward 4831443Sedward FD_ZERO(&imask); 4916313Sedward for (w = wwhead.ww_forw; w != &wwhead; w = w->ww_forw) { 5031443Sedward if (w->ww_pty < 0) 5116313Sedward continue; 5231443Sedward if (w->ww_obq < w->ww_obe) 5331443Sedward FD_SET(w->ww_pty, &imask); 5431443Sedward if (w->ww_obq > w->ww_obp && !w->ww_stopped) 5531443Sedward noblock = 1; 5631443Sedward } 5731443Sedward 5831443Sedward if (!noblock) { 5931443Sedward if (wwcurwin != 0) 6031443Sedward wwcurtowin(wwcurwin); 6131443Sedward wwupdate(); 6231443Sedward wwflush(); 6338497Sedward (void) setjmp(wwjmpbuf); 6431443Sedward wwsetjmp = 1; 6531443Sedward if (wwinterrupt()) { 6631443Sedward wwsetjmp = 0; 6731443Sedward wwclrintr(); 6831443Sedward return; 6916313Sedward } 7033751Sedward /* 7133751Sedward * Defensive code. If somebody else (for example, 7233751Sedward * wall) clears the ASYNC flag on us, we will block 7333751Sedward * forever. So we need a finite timeout and set 7433751Sedward * the flag again. Anything more clever will probably 7533751Sedward * need even more system calls. (This is a bug 7633751Sedward * in the kernel.) 7733751Sedward * I don't like this one bit. 7833751Sedward */ 7938497Sedward (void) fcntl(0, F_SETFL, wwnewtty.ww_fflags); 8033751Sedward tv.tv_sec = 30; 8136800Sedward tv.tv_usec = 0; 8236800Sedward } else { 8333751Sedward tv.tv_sec = 0; 8436800Sedward tv.tv_usec = 10000; 8536800Sedward } 8631443Sedward wwnselect++; 8733751Sedward n = select(wwdtablesize, &imask, (fd_set *)0, (fd_set *)0, &tv); 8831443Sedward wwsetjmp = 0; 8936800Sedward noblock = 0; 9031443Sedward 9131443Sedward if (n < 0) 9231443Sedward wwnselecte++; 9331443Sedward else if (n == 0) 9431443Sedward wwnselectz++; 9531443Sedward else 9631443Sedward for (w = wwhead.ww_forw; w != &wwhead; w = w->ww_forw) { 9731443Sedward if (w->ww_pty < 0 || 9831443Sedward !FD_ISSET(w->ww_pty, &imask)) 9931443Sedward continue; 10031443Sedward wwnwread++; 10131443Sedward p = w->ww_obq; 10231443Sedward if (w->ww_ispty) { 10331443Sedward if (p == w->ww_ob) { 10431443Sedward w->ww_obp++; 10531443Sedward w->ww_obq++; 10631443Sedward } else 10731443Sedward p--; 10831443Sedward c = *p; 10931443Sedward } 11031443Sedward n = read(w->ww_pty, p, w->ww_obe - p); 11131443Sedward if (n < 0) { 11231443Sedward wwnwreade++; 11331443Sedward (void) close(w->ww_pty); 11431443Sedward w->ww_pty = -1; 11531443Sedward } else if (n == 0) { 11631443Sedward wwnwreadz++; 11731443Sedward (void) close(w->ww_pty); 11831443Sedward w->ww_pty = -1; 11931443Sedward } else if (!w->ww_ispty) { 12031443Sedward wwnwreadd++; 12131443Sedward wwnwreadc += n; 12231443Sedward w->ww_obq += n; 12331443Sedward } else if (*p == TIOCPKT_DATA) { 12431443Sedward n--; 12531443Sedward wwnwreadd++; 12631443Sedward wwnwreadc += n; 12731443Sedward w->ww_obq += n; 12831443Sedward } else { 12931443Sedward wwnwreadp++; 13031443Sedward if (*p & TIOCPKT_STOP) 13131443Sedward w->ww_stopped = 1; 13231443Sedward if (*p & TIOCPKT_START) 13331443Sedward w->ww_stopped = 0; 13431443Sedward if (*p & TIOCPKT_FLUSHWRITE) { 13531443Sedward w->ww_stopped = 0; 13631443Sedward w->ww_obq = w->ww_obp = 13731443Sedward w->ww_ob; 13831443Sedward } 13931443Sedward } 14031443Sedward if (w->ww_ispty) 14131443Sedward *p = c; 14231443Sedward } 14335342Sedward /* 14435342Sedward * Try the current window first, if there is output 14535342Sedward * then process it and go back to the top to try again. 14635342Sedward * This can lead to starvation of the other windows, 14735342Sedward * but presumably that what we want. 14835342Sedward * Update will eventually happen when output from wwcurwin 14935342Sedward * dies down. 15035342Sedward */ 15135342Sedward if ((w = wwcurwin) != 0 && w->ww_pty >= 0 && 15235342Sedward w->ww_obq > w->ww_obp && !w->ww_stopped) { 15335342Sedward n = wwwrite(w, w->ww_obp, w->ww_obq - w->ww_obp); 15435342Sedward if ((w->ww_obp += n) == w->ww_obq) 15535342Sedward w->ww_obq = w->ww_obp = w->ww_ob; 15636800Sedward noblock = 1; 15735342Sedward continue; 15835342Sedward } 15931443Sedward for (w = wwhead.ww_forw; w != &wwhead; w = w->ww_forw) 16031443Sedward if (w->ww_pty >= 0 && w->ww_obq > w->ww_obp && 16131443Sedward !w->ww_stopped) { 16231443Sedward n = wwwrite(w, w->ww_obp, 16331443Sedward w->ww_obq - w->ww_obp); 16431443Sedward if ((w->ww_obp += n) == w->ww_obq) 16516313Sedward w->ww_obq = w->ww_obp = w->ww_ob; 16635342Sedward if (wwinterrupt()) 16735342Sedward break; 16816313Sedward } 16931443Sedward } 17013923Sedward } 171