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