home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.bin / window / wwiomux.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-18  |  5.8 KB  |  200 lines

  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, 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    3.26 (Berkeley) 8/12/90";
  39. #endif /* not lint */
  40.  
  41. #include "ww.h"
  42. #include <sys/time.h>
  43. #include <sys/types.h>
  44. #if !defined(OLD_TTY) && !defined(TIOCPKT_DATA)
  45. #include <sys/ioctl.h>
  46. #endif
  47. #include <fcntl.h>
  48.  
  49. /*
  50.  * Multiple window output handler.
  51.  * The idea is to copy window outputs to the terminal, via the
  52.  * display package.  We try to give wwcurwin highest priority.
  53.  * The only return conditions are when there is keyboard input
  54.  * and when a child process dies, which are serviced by signal
  55.  * catchers (wwrint() and wwchild()).
  56.  * When there's nothing to do, we sleep in a select().
  57.  * This can be done better with interrupt driven io.  But that's
  58.  * not supported on ptys, yet.
  59.  * The history of this routine is interesting.
  60.  */
  61. wwiomux()
  62. {
  63.     register struct ww *w;
  64.     fd_set imask;
  65.     register n;
  66.     register char *p;
  67.     char c;
  68.     struct timeval tv;
  69.     char noblock = 0;
  70.  
  71.     for (;;) {
  72.         if (wwinterrupt()) {
  73.             wwclrintr();
  74.             return;
  75.         }
  76.  
  77.         FD_ZERO(&imask);
  78.         for (w = wwhead.ww_forw; w != &wwhead; w = w->ww_forw) {
  79.             if (w->ww_pty < 0)
  80.                 continue;
  81.             if (w->ww_obq < w->ww_obe)
  82.                 FD_SET(w->ww_pty, &imask);
  83.             if (w->ww_obq > w->ww_obp && !w->ww_stopped)
  84.                 noblock = 1;
  85.         }
  86.  
  87.         if (!noblock) {
  88.             if (wwcurwin != 0)
  89.                 wwcurtowin(wwcurwin);
  90.             wwupdate();
  91.             wwflush();
  92.             (void) setjmp(wwjmpbuf);
  93.             wwsetjmp = 1;
  94.             if (wwinterrupt()) {
  95.                 wwsetjmp = 0;
  96.                 wwclrintr();
  97.                 return;
  98.             }
  99.             /*
  100.              * Defensive code.  If somebody else (for example,
  101.              * wall) clears the ASYNC flag on us, we will block
  102.              * forever.  So we need a finite timeout and set
  103.              * the flag again.  Anything more clever will probably
  104.              * need even more system calls.  (This is a bug
  105.              * in the kernel.)
  106.              * I don't like this one bit.
  107.              */
  108.             (void) fcntl(0, F_SETFL, wwnewtty.ww_fflags);
  109.             tv.tv_sec = 30;
  110.             tv.tv_usec = 0;
  111.         } else {
  112.             tv.tv_sec = 0;
  113.             tv.tv_usec = 10000;
  114.         }
  115.         wwnselect++;
  116.         n = select(wwdtablesize, &imask, (fd_set *)0, (fd_set *)0, &tv);
  117.         wwsetjmp = 0;
  118.         noblock = 0;
  119.  
  120.         if (n < 0)
  121.             wwnselecte++;
  122.         else if (n == 0)
  123.             wwnselectz++;
  124.         else
  125.             for (w = wwhead.ww_forw; w != &wwhead; w = w->ww_forw) {
  126.                 if (w->ww_pty < 0 ||
  127.                     !FD_ISSET(w->ww_pty, &imask))
  128.                     continue;
  129.                 wwnwread++;
  130.                 p = w->ww_obq;
  131.                 if (w->ww_ispty) {
  132.                     if (p == w->ww_ob) {
  133.                         w->ww_obp++;
  134.                         w->ww_obq++;
  135.                     } else
  136.                         p--;
  137.                     c = *p;
  138.                 }
  139.                 n = read(w->ww_pty, p, w->ww_obe - p);
  140.                 if (n < 0) {
  141.                     wwnwreade++;
  142.                     (void) close(w->ww_pty);
  143.                     w->ww_pty = -1;
  144.                 } else if (n == 0) {
  145.                     wwnwreadz++;
  146.                     (void) close(w->ww_pty);
  147.                     w->ww_pty = -1;
  148.                 } else if (!w->ww_ispty) {
  149.                     wwnwreadd++;
  150.                     wwnwreadc += n;
  151.                     w->ww_obq += n;
  152.                 } else if (*p == TIOCPKT_DATA) {
  153.                     n--;
  154.                     wwnwreadd++;
  155.                     wwnwreadc += n;
  156.                     w->ww_obq += n;
  157.                 } else {
  158.                     wwnwreadp++;
  159.                     if (*p & TIOCPKT_STOP)
  160.                         w->ww_stopped = 1;
  161.                     if (*p & TIOCPKT_START)
  162.                         w->ww_stopped = 0;
  163.                     if (*p & TIOCPKT_FLUSHWRITE) {
  164.                         w->ww_stopped = 0;
  165.                         w->ww_obq = w->ww_obp =
  166.                             w->ww_ob;
  167.                     }
  168.                 }
  169.                 if (w->ww_ispty)
  170.                     *p = c;
  171.             }
  172.         /*
  173.          * Try the current window first, if there is output
  174.          * then process it and go back to the top to try again.
  175.          * This can lead to starvation of the other windows,
  176.          * but presumably that what we want.
  177.          * Update will eventually happen when output from wwcurwin
  178.          * dies down.
  179.          */
  180.         if ((w = wwcurwin) != 0 && w->ww_pty >= 0 &&
  181.             w->ww_obq > w->ww_obp && !w->ww_stopped) {
  182.             n = wwwrite(w, w->ww_obp, w->ww_obq - w->ww_obp);
  183.             if ((w->ww_obp += n) == w->ww_obq)
  184.                 w->ww_obq = w->ww_obp = w->ww_ob;
  185.             noblock = 1;
  186.             continue;
  187.         }
  188.         for (w = wwhead.ww_forw; w != &wwhead; w = w->ww_forw)
  189.             if (w->ww_pty >= 0 && w->ww_obq > w->ww_obp &&
  190.                 !w->ww_stopped) {
  191.                 n = wwwrite(w, w->ww_obp,
  192.                     w->ww_obq - w->ww_obp);
  193.                 if ((w->ww_obp += n) == w->ww_obq)
  194.                     w->ww_obq = w->ww_obp = w->ww_ob;
  195.                 if (wwinterrupt())
  196.                     break;
  197.             }
  198.     }
  199. }
  200.