home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 200-299 / ff220.lzh / DNet / dnet / dnet.c < prev    next >
C/C++ Source or Header  |  1989-06-04  |  8KB  |  334 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:\n");
  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.     char local_dir[MAXPATHLEN];
  67.     struct passwd pw_info;
  68.     extern void RcvInt();
  69.  
  70.     if (getenv("DNETDIR")) {
  71.     strcpy(local_dir, getenv("DNETDIR"));
  72.     if (chdir(local_dir)) {
  73.         fprintf(stderr, "Unable to chdir to DNETDIR: %s\n", local_dir);
  74.         exit(1);
  75.     }
  76.     freopen("DNET.LOG", "w", stderr);
  77.     } else {
  78.     pw_info = *getpwuid(getuid());
  79.     strcpy(local_dir, pw_info.pw_dir);
  80.     strcat(local_dir, "/.dnet");
  81.     if (chdir(local_dir)) {
  82.         mkdir(local_dir, 0700);
  83.         if (chdir(local_dir)) {
  84.         fprintf(stderr, "Unable to create dir %s\n", local_dir);
  85.         exit(1);
  86.         }
  87.     }
  88.     freopen("DNET.LOG", "w", stderr);
  89.     }
  90.     fprintf(stderr, "DNet startup\n");
  91.     fprintf(stderr, "Log file placed in %s\n", local_dir);
  92.     fflush(stderr);
  93.  
  94.     signal(SIGINT, SIG_IGN);
  95.     signal(SIGPIPE, SIG_IGN);
  96.     signal(SIGQUIT, SIG_IGN);
  97.     signal(SIGCHLD, handle_child);
  98.     signal(SIGHUP, loganddie);
  99.  
  100.     bzero(Pkts,sizeof(Pkts));
  101.     setlistenport("");
  102.  
  103.     {
  104.     register short i;
  105.     for (i = 1; i < ac; ++i) {
  106.         register char *ptr = av[i];
  107.         if (*ptr != '-') {
  108.         DDebug = 1;
  109.         fprintf(stderr, "Debug mode on\n");
  110.         continue;
  111.         }
  112.         switch(*ptr) {
  113.         case 'B':
  114.         USecPerByte = atoi(ptr+1) / 10;     /*  bytes per second */
  115.         USecPerByte = 1000000 / USecPerByte;
  116.         fprintf(stderr, "Assuming about %ld uS/byte for timeout calc\n",
  117.             USecPerByte
  118.         );
  119.         break;
  120.         default:
  121.         fprintf(stderr, "Unknown option: %c\n", *ptr);
  122.         printf("Unknown option: %c\n", *ptr);
  123.         exit(1);
  124.         }
  125.     }
  126.     }
  127.  
  128.     NewList(&TxList);
  129.  
  130.     Fdperm[0] = 1;
  131.     Fdstate[0] = RcvInt;
  132.     FD_SET(0, &Fdread);
  133.     FD_SET(0, &Fdexcept);
  134.  
  135.     fprintf(stderr, "DNET RUNNING, Listenfd=%ld\n", DNet_fd);
  136.     NetOpen();          /* initialize network and interrupt driven read */
  137.     TimerOpen();        /* initialize timers                            */
  138.  
  139.     do_netreset();
  140.     do_restart();
  141.  
  142.     notdone = 1;
  143.     while (notdone) {
  144.     /*
  145.      *    MAIN LOOP.  select() on all the file descriptors.  Set the
  146.      *    timeout to infinity (NULL) normally.  However, if there is
  147.      *    a pending read or write timeout, set the select timeout
  148.      *    to 2 seconds in case they timeout before we call select().
  149.      *    (i.e. a timing window).  OR, if we are in the middle of a
  150.      *    read, don't use descriptor 0 and timeout according to
  151.      *    the expected read length, then set the descriptor as ready.
  152.      */
  153.  
  154.     fd_set fd_rd;
  155.     fd_set fd_wr;
  156.     fd_set fd_ex;
  157.     struct timeval tv, *ptv;
  158.     int err;
  159.  
  160.     fd_rd = Fdread;
  161.     fd_wr = Fdwrite;
  162.     fd_ex = Fdexcept;
  163.  
  164.     tv.tv_sec = 0;        /* normally wait forever for an event */
  165.     tv.tv_usec= 0;
  166.     ptv = NULL;
  167.     if ((Rto_act || Wto_act)) {     /* unless timeout pending */
  168.         ptv = &tv;
  169.         tv.tv_sec = 2;
  170.     }
  171.  
  172.     /*   ... or expecting data (don't just wait for one byte).
  173.      *
  174.      *   This is an attempt to reduce the CPU usage for the process.
  175.      *   If we are expecting data over the serial line, then don't
  176.      *   return from the select() even if data is available, but
  177.      *   wait for the timeout period indicated before reading the
  178.      *   data.  Don't wait more than 64 byte times or we may loose
  179.      *   some data (the silo's are only so big.. like 128 bytes).
  180.      *
  181.      *   Currently, USecPerByte is not set properly (set for 9600 baud)
  182.      */
  183.  
  184.     if (RExpect) {
  185.         ptv = &tv;
  186.         tv.tv_usec= USecPerByte * ((RExpect < 64) ? RExpect : 64);
  187.         tv.tv_sec = 0;
  188.         FD_CLR(0, &fd_rd);
  189.     }
  190.     err = select(FD_SETSIZE, &fd_rd, &fd_wr, &fd_ex, ptv);
  191.     if (RExpect) {
  192.         FD_SET(0, &fd_rd);   /* pretend data ready */
  193.     }
  194.     if (DDebug)
  195.         fprintf(stderr, "SERR %ld %ld %08lx %08lx\n",
  196.         err, errno, RExpect, ptv
  197.         );
  198.  
  199.     if (RTimedout) {
  200.         RTimedout = 0;
  201.         do_rto();
  202.         mark = 0;
  203.     }
  204.     if (WTimedout) {
  205.         WTimedout = 0;
  206.         do_wto();
  207.     }
  208.     if (err < 0) {
  209.         if (errno == EBADF) {
  210.         perror("select");
  211.         dneterror(NULL);
  212.         }
  213.     } else {
  214.         register short i;
  215.         register short j;
  216.         register long mask;
  217.  
  218.         for (i = 0; i < FD_SETSIZE/NFDBITS; ++i) {
  219.         if (mask = fd_ex.fds_bits[i]) {
  220.             for (j = i * NFDBITS; mask; (mask >>= 1),(++j)) {
  221.             if (mask & 1)
  222.                 (*Fdstate[j])(2,j);
  223.             }
  224.         }
  225.         if (mask = fd_wr.fds_bits[i]) {
  226.             for (j = i * NFDBITS; mask; (mask >>= 1),(++j)) {
  227.             if (mask & 1)
  228.                 (*Fdstate[j])(1,j);
  229.             }
  230.         }
  231.         if (mask = fd_rd.fds_bits[i]) {
  232.             for (j = i * NFDBITS; mask; (mask >>= 1),(++j)) {
  233.             if (mask & 1)
  234.                 (*Fdstate[j])(0,j);
  235.             }
  236.         }
  237.         }
  238.     }
  239.     if (RcvData != mark)
  240.         mark = do_rnet();
  241.     do_wupdate();
  242.     do_wnet();
  243.     }
  244.     dneterror(NULL);
  245. }
  246.  
  247. void
  248. nop()
  249. {
  250. }
  251.  
  252. do_netreset()
  253. {
  254.     register short i;
  255.     register CHAN *ch;
  256.     for (i = 0; i < FD_SETSIZE; ++i) {
  257.     if (!Fdperm[i])
  258.         Fdstate[i] = nop;
  259.     }
  260.     for (i = 0, ch = Chan; i < MAXCHAN; ++i, ++ch) {
  261.     switch(ch->state) {
  262.     case CHAN_OPEN:
  263.     case CHAN_LOPEN:    /*  pending on network        */
  264.     case CHAN_CLOSE:
  265.         if (ch->fd >= 0) {
  266.         FD_CLR(ch->fd, &Fdread);
  267.         FD_CLR(ch->fd, &Fdexcept);
  268.         Fdstate[ch->fd] = nop;
  269.         close(ch->fd);
  270.         ch->fd = -1;
  271.         ch->state = CHAN_FREE;
  272.         ch->flags = 0;
  273.         --NumCon;
  274.         }
  275.         ClearChan(&TxList, i, 1);
  276.         break;
  277.     }
  278.     }
  279.     RPStart = 0;
  280.     WPStart = 0;
  281.     WPUsed  = 0;
  282.     RState  = 0;
  283.     RChan = 0;
  284.     WChan = 0;
  285. }
  286.  
  287. do_restart()
  288. {
  289.     static ubyte buf[3] = { SYNC, PKCMD_RESTART, (SYNC<<1)^PKCMD_RESTART };
  290.     Restart = 1;
  291.     NetWrite(buf, sizeof(buf), 1);
  292.     WTimeout(WTIME);
  293. }
  294.  
  295. setlistenport(remotehost)
  296. char *remotehost;
  297. {
  298.     static struct sockaddr sa[2];
  299.     int s;
  300.     extern void do_localopen();
  301.  
  302.     if (DNet_fd >= 0) {
  303.     unlink(sa[0].sa_data);
  304.     Fdstate[DNet_fd] = nop;
  305.     Fdperm[DNet_fd] = 0;
  306.     FD_CLR(DNet_fd, &Fdread);
  307.     FD_CLR(DNet_fd, &Fdexcept);
  308.     close(DNet_fd);
  309.     }
  310.     setenv("DNETHOST=", remotehost);
  311.     sprintf(sa[0].sa_data, "DNET.%s", remotehost);
  312.     unlink(sa[0].sa_data);
  313.     sa[0].sa_family = AF_UNIX;
  314.  
  315.     s = socket(PF_UNIX, SOCK_STREAM, 0);
  316.     fcntl(s, F_SETOWN, getpid());
  317.     fcntl(s, F_SETFL,  FNDELAY);
  318.     if (bind(s, &sa[0], SASIZE(sa[0])) < 0) {
  319.     perror("bind");
  320.     exit(1);
  321.     }
  322.     if (listen(s, 5) < 0) {
  323.     unlink(sa[0].sa_data);
  324.     perror("listen");
  325.     exit(1);
  326.     }
  327.     DNet_fd = s;
  328.     Fdstate[DNet_fd] = do_localopen;
  329.     Fdperm[DNet_fd] = 1;
  330.     FD_SET(DNet_fd, &Fdread);
  331.     FD_SET(DNet_fd, &Fdexcept);
  332. }
  333.  
  334.