home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d1xx / d145 / dnet.lha / Dnet / unix / dnet / dnet.c < prev    next >
C/C++ Source or Header  |  1988-05-26  |  7KB  |  290 lines

  1.  
  2. /*
  3.  *  DNET.C
  4.  *
  5.  *    DNET (c)Copyright 1988, Matthew Dillon, All Rights Reserved
  6.  *
  7.  *    Handles action on all active file descriptors and dispatches
  8.  *    to the proper function in FILES.C
  9.  *
  10.  */
  11.  
  12. #include "dnet.h"
  13. #include <sys/wait.h>
  14. #include <sys/resource.h>
  15.  
  16. handle_child()
  17. {
  18.     union wait stat;
  19.     struct rusage rus;
  20.     while (wait3(&stat, WNOHANG, &rus) > 0);
  21. }
  22.  
  23. char *
  24. showselect(ptr)
  25. fd_set *ptr;
  26. {
  27.     static char buf[FD_SETSIZE+32];
  28.     short i;
  29.  
  30.     for (i = 0; i < FD_SETSIZE; ++i) {
  31.     buf[i] = (FD_ISSET(i, ptr)) ? '1' : '0';
  32.     }
  33.     buf[i] = 0;
  34.     return(buf);
  35. }
  36.  
  37.  
  38. loganddie()
  39. {
  40.     fflush(stderr);
  41.     fprintf(stderr, "\nHUPSIGNAL\n");
  42.     perror("HUP, last error:");
  43.     fprintf(stderr, "Last select return: ");
  44.     fprintf(stderr, "  %s\n", showselect(&Fdread));
  45.     fprintf(stderr, "  %s\n", showselect(&Fdwrite));
  46.     fprintf(stderr, "  %s\n", showselect(&Fdexcept));
  47.     fprintf(stderr, "RcvData = %ld\n", RcvData);
  48.     fprintf(stderr, "RChan/WChan = %ld/%ld\n", RChan, WChan);
  49.     fprintf(stderr, "RPStart = %ld\n", RPStart);
  50.     fprintf(stderr, "WPStart = %ld\n", WPStart);
  51.     fprintf(stderr, "WPUsed = %ld\n", WPUsed);
  52.     fprintf(stderr, "RState = %ld\n", RState);
  53.     fflush(stderr);
  54.     kill(0, SIGILL);
  55.     exit(1);
  56. }
  57.  
  58. #define SASIZE(sa)    (sizeof(sa)-sizeof((sa).sa_data)+strlen((sa).sa_data))
  59.  
  60. main(ac,av)
  61. char *av[];
  62. {
  63.     long sink_mask, dnet_mask;
  64.     long mark = 0;
  65.     ubyte notdone;
  66.     extern void RcvInt();
  67.  
  68.     if (getenv("DNETDIR"))
  69.     chdir(getenv("DNETDIR"));
  70.     freopen("DNET.LOG", "w", stderr);
  71.     signal(SIGINT, SIG_IGN);
  72.     signal(SIGPIPE, SIG_IGN);
  73.     signal(SIGQUIT, SIG_IGN);
  74.     signal(SIGCHLD, handle_child);
  75.     signal(SIGHUP, loganddie);
  76.  
  77.     bzero(Pkts,sizeof(Pkts));
  78.     setlistenport("");
  79.     if (ac > 1) {
  80.     DDebug = 1;
  81.     fprintf(stderr, "Debugger running\n");
  82.     }
  83.     NewList(&TxList);
  84.  
  85.     Fdperm[0] = 1;
  86.     Fdstate[0] = RcvInt;
  87.     FD_SET(0, &Fdread);
  88.     FD_SET(0, &Fdexcept);
  89.  
  90.     fprintf(stderr, "DNET RUNNING, Listenfd=%ld\n", DNet_fd);
  91.     NetOpen();        /* initialize network and interrupt driven read */
  92.     TimerOpen();    /* initialize timers                */
  93.  
  94.     do_netreset();
  95.     do_restart();
  96.  
  97.     notdone = 1;
  98.     while (notdone) {
  99.     /*
  100.      *    MAIN LOOP.  select() on all the file descriptors.  Set the
  101.      *    timeout to infinity (NULL) normally.  However, if there is
  102.      *    a pending read or write timeout, set the select timeout
  103.      *    to 2 seconds in case they timeout before we call select().
  104.      *    (i.e. a timing window).  OR, if we are in the middle of a
  105.      *    read, don't use descriptor 0 and timeout according to
  106.      *    the expected read length, then set the descriptor as ready.
  107.      */
  108.  
  109.     fd_set fd_rd;
  110.     fd_set fd_wr;
  111.     fd_set fd_ex;
  112.     struct timeval tv, *ptv;
  113.     int err;
  114.  
  115.     fd_rd = Fdread;
  116.     fd_wr = Fdwrite;
  117.     fd_ex = Fdexcept;
  118.  
  119.     tv.tv_sec = 0;        /* normally wait forever for an event */
  120.     tv.tv_usec= 0;
  121.     ptv = NULL;
  122.     if ((Rto_act || Wto_act)) {    /* unless timeout pending */
  123.         ptv = &tv;
  124.         tv.tv_sec = 2;
  125.     } 
  126.  
  127.     /*   ... or expecting data (don't just wait for one byte).
  128.      *
  129.      *   This is an attempt to reduce the CPU usage for the process.
  130.      *   If we are expecting data over the serial line, then don't
  131.      *   return from the select() even if data is available, but 
  132.      *   wait for the timeout period indicated before reading the
  133.      *   data.  Don't wait more than 64 byte times or we may loose
  134.      *   some data (the silo's are only so big.. like 128 bytes).
  135.      *
  136.      *   Currently, USecPerByte is not set properly (set for 9600 baud)
  137.      */
  138.  
  139.     if (RExpect) {
  140.         ptv = &tv;
  141.         tv.tv_usec= USecPerByte * ((RExpect < 64) ? RExpect : 64);
  142.         tv.tv_sec = 0;
  143.         FD_CLR(0, &fd_rd);
  144.     }
  145.     err = select(FD_SETSIZE, &fd_rd, &fd_wr, &fd_ex, ptv);
  146.     if (RExpect) {
  147.         FD_SET(0, &fd_rd);   /* pretend data ready */
  148.     }
  149.     if (DDebug)
  150.         fprintf(stderr, "SERR %ld %ld %08lx %08lx\n",
  151.         err, errno, RExpect, ptv
  152.         ); 
  153.  
  154.     if (RTimedout) {
  155.         RTimedout = 0;
  156.         do_rto();
  157.         mark = 0;
  158.     }
  159.     if (WTimedout) {
  160.         WTimedout = 0;
  161.         do_wto();
  162.     }
  163.     if (err < 0) {
  164.         if (errno == EBADF) {
  165.             perror("select");
  166.                 dneterror(NULL);
  167.         }
  168.         continue;
  169.     }
  170.     {
  171.         register short i;
  172.         register short j;
  173.         register long mask;
  174.  
  175.         for (i = 0; i < FD_SETSIZE/NFDBITS; ++i) {
  176.         if (mask = fd_ex.fds_bits[i]) {
  177.             for (j = i * NFDBITS; mask; (mask >>= 1),(++j)) {
  178.             if (mask & 1)
  179.                 (*Fdstate[j])(2,j);
  180.             }
  181.         }
  182.         if (mask = fd_wr.fds_bits[i]) {
  183.             for (j = i * NFDBITS; mask; (mask >>= 1),(++j)) {
  184.             if (mask & 1)
  185.                 (*Fdstate[j])(1,j);
  186.             }
  187.         }
  188.         if (mask = fd_rd.fds_bits[i]) {
  189.             for (j = i * NFDBITS; mask; (mask >>= 1),(++j)) {
  190.             if (mask & 1)
  191.                 (*Fdstate[j])(0,j);
  192.             }
  193.         }
  194.         }
  195.     }
  196.     if (RcvData != mark) 
  197.         mark = do_rnet();
  198.     do_wnet();
  199.     }
  200.     dneterror(NULL);
  201. }
  202.  
  203. void
  204. nop()
  205. {
  206. }
  207.  
  208. do_netreset()
  209. {
  210.     register short i;
  211.     register CHAN *ch;
  212.     for (i = 0; i < FD_SETSIZE; ++i) {
  213.     if (!Fdperm[i])
  214.         Fdstate[i] = nop;
  215.     }
  216.     for (i = 0, ch = Chan; i < MAXCHAN; ++i, ++ch) {
  217.     switch(ch->state) {
  218.     case CHAN_OPEN:
  219.     case CHAN_LOPEN:    /*  pending on network        */
  220.     case CHAN_CLOSE:
  221.         if (ch->fd >= 0) {
  222.             FD_CLR(ch->fd, &Fdread);
  223.             FD_CLR(ch->fd, &Fdexcept);
  224.             Fdstate[ch->fd] = nop;
  225.             close(ch->fd);
  226.             ch->fd = -1;
  227.             ch->state = CHAN_FREE;
  228.             ch->flags = 0;
  229.             --NumCon;
  230.         }
  231.         ClearChan(&TxList, i, 1);
  232.         break;
  233.     }
  234.     }
  235.     RPStart = 0;
  236.     WPStart = 0;
  237.     WPUsed  = 0;
  238.     RState  = 0;
  239.     RChan = 0;
  240.     WChan = 0;
  241. }
  242.  
  243. do_restart()
  244. {
  245.     static ubyte buf[3] = { SYNC, PKCMD_RESTART, (SYNC<<1)^PKCMD_RESTART };
  246.     Restart = 1;
  247.     NetWrite(buf, sizeof(buf));
  248.     WTimeout(WTIME);
  249. }
  250.  
  251. setlistenport(remotehost)
  252. char *remotehost;
  253. {
  254.     static struct sockaddr sa[2];
  255.     int s;
  256.     extern void do_localopen();
  257.  
  258.     if (DNet_fd >= 0) {
  259.         unlink(sa[0].sa_data);
  260.         Fdstate[DNet_fd] = nop;
  261.         Fdperm[DNet_fd] = 0;
  262.         FD_CLR(DNet_fd, &Fdread);
  263.         FD_CLR(DNet_fd, &Fdexcept);
  264.     close(DNet_fd);
  265.     }
  266.     setenv("DNETHOST=", remotehost);
  267.     sprintf(sa[0].sa_data, "DNET.%s", remotehost);
  268.     unlink(sa[0].sa_data);
  269.     sa[0].sa_family = AF_UNIX;
  270.  
  271.     s = socket(PF_UNIX, SOCK_STREAM, 0);
  272.     fcntl(s, F_SETOWN, getpid());
  273.     fcntl(s, F_SETFL,  FNDELAY);
  274.     if (bind(s, &sa[0], SASIZE(sa[0])) < 0) {
  275.         perror("bind");
  276.         exit(1);
  277.     }
  278.     if (listen(s, 5) < 0) {
  279.         unlink(sa[0].sa_data);
  280.         perror("listen");
  281.     exit(1);
  282.     }
  283.     DNet_fd = s;
  284.     Fdstate[DNet_fd] = do_localopen;
  285.     Fdperm[DNet_fd] = 1;
  286.     FD_SET(DNet_fd, &Fdread);
  287.     FD_SET(DNet_fd, &Fdexcept);
  288. }
  289.  
  290.