home *** CD-ROM | disk | FTP | other *** search
/ Photo CD Demo 1 / Demo.bin / inetray / comm.c < prev    next >
C/C++ Source or Header  |  1992-07-03  |  12KB  |  473 lines

  1. /*======================================================================
  2.                     C O M M . C 
  3.                     doc: Thu Mar  5 12:32:02 1992
  4.                     dlm: Fri Jul  3 15:02:47 1992
  5.                     (c) 1992 ant@julia
  6.                     uE-Info: 262 17 T 0 0 72 2 2 8 ofnI
  7. ======================================================================*/
  8.  
  9. #include    <stdio.h>
  10. #include    <signal.h>
  11. #include    </usr/include/netdb.h>    /* prefer system over rpc/netdb.h */
  12. #include    <errno.h>
  13. #include    <sys/time.h>
  14. #include    <sys/types.h>
  15. #include    <sys/socket.h>
  16. #include    <sys/param.h>
  17. #include    <rpc/rpc.h>
  18. #include    <arpa/inet.h>
  19. #include    <netinet/in.h>
  20. #include    "inetray.h"
  21. #include    "inetray.start.h"
  22. #include    "rcfile.h"
  23. #include    "common.h"
  24. #include    "utils.h"
  25. #include    "config.h"
  26. #ifdef AUX_QUIRK
  27. #include    "aux_quirk.h"
  28. #endif
  29.  
  30. hInfo        *hosts = NULL;        /* list of hosts */
  31. int        sfdmax = 0;        /* max fd for ressocks */
  32. int        nRunning = 0;        /* number of workers running */
  33.  
  34. static int    sock;            /* listening socket */
  35.  
  36. extern int    errno;            /* to restart syscalls */
  37. extern int    key;            /* session key */
  38.  
  39. void shutDown()                /* shut down operation */
  40. {
  41.     int i,res;
  42.     void killAll(),flushAll(),waitAll(),terminateAll(),closeAll();
  43.  
  44.     for (i=1; i<=32; i++)            /* ignore all signals */
  45.         signal(i,SIG_IGN);
  46.     fprintf(stderr,"\nShutting down..."); 
  47.     killAll();                /* kill workers */
  48.     flushAll();                /* flush result sockets */
  49.     waitAll();                /* wait for workers */
  50.     terminateAll();                /* terminate servers */
  51.     closeAll();                /* close sockets */
  52.     putc('\n',stderr); 
  53.     exit(0);
  54. }
  55.  
  56. void abort1(host)            /* this one is broken */
  57. hInfo *host;
  58. {
  59.     fprintf(stderr,"\tWarning: Lost connection with %s (check SYSLOG)\n",
  60.                     host->name);
  61.     host->broken = TRUE;        /* this host crashed */
  62.     close(host->sock);
  63.     if (--nRunning == 0) {        /* still servers running? */
  64.             fprintf(stderr,"We're alone now...");
  65.             shutDown();
  66.     }
  67. }
  68.  
  69. void IRbroadcast(fNum,inP,in)        /* bcast INIT or TERMINATE */
  70. u_long fNum; char *in; xdrproc_t inP;
  71. {
  72.     int     i,res,exists,uid,nSvcs;
  73.     char    *addr;
  74.  
  75.     exists = getHost(TRUE,&addr,&nSvcs,&uid);    /* hosts */
  76.     while (exists) {
  77.         if (fNum == INIT)
  78.             ((iPrm *)in)->uid = uid;
  79.         for (i=0; i<nSvcs; i++) {
  80.             res = sendrpc(addr,INETRAY+i,IRV1,fNum,
  81.                     inP,in,xdr_void,NULL);
  82.             if ((res != 0) &&
  83.                 ((fNum != TERMINATE) || (res != RPC_PROGNOTREGISTERED))) {
  84.                 fprintf(stderr,
  85.                     "\nWarning: sendrpc(%s,%d): ",
  86.                     addr,fNum);
  87.                 clnt_perrno(res);
  88.             }
  89.         }
  90.         exists = getHost(FALSE,&addr,&nSvcs,&uid);
  91.     }
  92.  
  93.     exists = getNet(TRUE,&addr,&nSvcs,&uid);    /* nets */
  94.     while (exists) {
  95.         if (fNum == INIT)
  96.             ((iPrm *)in)->uid = uid;
  97.         for (i=0; i<nSvcs; i++) {
  98.             res = clnt_dirbcast(addr,INETRAY+i,IRV1,fNum,
  99.                         inP,in,xdr_void,NULL,NULL);
  100.             if (res != 0) {
  101.                 fprintf(stderr,
  102.                     "\nWarning: clnt_dirbcast(%s,%d): ",
  103.                     addr,fNum);
  104.                 clnt_perrno(res);
  105.             }
  106.         }
  107.         exists = getNet(FALSE,&addr,&nSvcs,&uid);
  108.     }
  109.  
  110.     getLocal(&addr,&nSvcs,&uid);            /* LAN */
  111.         if (fNum == INIT)
  112.                 ((iPrm *)in)->uid = uid;
  113.         for (i=0; i<nSvcs; i++) {
  114.             res = clnt_broadcast(INETRAY+i,IRV1,fNum,
  115.                                     inP,in,xdr_void,NULL,NULL);
  116.             if (res != 0) {
  117.                     fprintf(stderr,
  118.                             "\nWarning: clnt_broadcast(%d): ",fNum);
  119.                     clnt_perrno(res);
  120.         }
  121.     }
  122. }
  123.  
  124. void IRSbroadcast()                    /* bcast START */
  125. {
  126.     int     res,exists;
  127.     char    *addr;
  128.     sPrm    p;
  129.  
  130.     exists = getHost(TRUE,&addr,&p.nSvcs,&p.uid);    /* hosts */
  131.     while (exists) {
  132.         if (p.nSvcs > 0) {
  133.                     res = sendrpc(addr,STARTER,IRSV1,START,
  134.                                     xdr_sPrm,&p,xdr_void,NULL);
  135.                     if ((res != 0) && (res != RPC_PROGNOTREGISTERED)) {
  136.                             fprintf(stderr,
  137.                                     "\nWarning: sendrpc(%s,START): ",addr);
  138.                             clnt_perrno(res);
  139.             }
  140.         }
  141.         exists = getHost(FALSE,&addr,&p.nSvcs,&p.uid);
  142.     }
  143.  
  144.     exists = getNet(TRUE,&addr,&p.nSvcs,&p.uid);    /* nets */
  145.     while (exists) {
  146.         if (p.nSvcs > 0) {
  147.                     res = clnt_dirbcast(addr,STARTER,IRSV1,START,
  148.                                             xdr_sPrm,&p,xdr_void,NULL,NULL);
  149.                     if (res != 0) {
  150.                             fprintf(stderr,
  151.                                     "\nWarning: clnt_dirbcast(%s,START): ",addr);
  152.                             clnt_perrno(res);
  153.             }
  154.         }
  155.         exists = getNet(FALSE,&addr,&p.nSvcs,&p.uid);
  156.     }
  157.  
  158.     getLocal(&addr,&p.nSvcs,&p.uid);        /* LAN */
  159.     if (p.nSvcs > 0) {
  160.             res = clnt_broadcast(STARTER,IRSV1,START,
  161.                                     xdr_sPrm,&p,xdr_void,NULL,NULL);
  162.             if (res != 0) {
  163.                     fprintf(stderr,"\nWarning: clnt_broadcast(START): ");
  164.                     clnt_perrno(res);
  165.         }
  166.     }
  167. }
  168.  
  169. static readit(fdp,buf,nbyte)            /* xdr aux routine */
  170. char *fdp,*buf; int nbyte;
  171. {
  172.     int nread,fd;
  173.  
  174.     fd = *(int *)fdp;
  175. reStartRead:
  176.     nread = read(fd,buf,nbyte);
  177.     if (nread < 0) {
  178.         if (errno == EINTR) {
  179.             goto reStartRead;
  180.         }
  181.         perror("read");
  182.     }
  183.     if (nread == 0) nread = -1;
  184.     return nread;
  185. }
  186.  
  187. static void getAnswers()                /* wait for answers */
  188. {
  189.     int    aLen,res;
  190.     hInfo    *new,*old;
  191.     fd_set    sockSet;
  192.     char    buf[64],*cp;
  193.     struct hostent         *host;
  194.     struct servent         *s;
  195.     struct sockaddr_in    addr;
  196.     struct timeval        tout,noDefault;
  197.  
  198.     tout.tv_sec = rTimeout;                /* timeout */
  199.     tout.tv_usec = 0;
  200.     noDefault.tv_sec = noDefault.tv_usec = -1;    /* use supplied val */
  201.     do {
  202.             do {
  203.         restartSelect:
  204.                 FD_ZERO(&sockSet);        /* select() on socket */
  205.                 FD_SET(sock,&sockSet);
  206.                     res = select(sock+1,&sockSet,NULL,NULL,&tout);
  207.                     if (res < 0) {
  208.                        if (errno == EINTR) goto restartSelect;
  209.                             perror("select");
  210.                             exit(1);
  211.             }
  212.         } while ((res == 0) && (nRunning < minWorkers));
  213.         if (res == 0) break;            /* done */
  214.         
  215.         new = (hInfo *)malloc(sizeof(hInfo));     /* alloc node */
  216.         if (new == NULL) {
  217.             fprintf(stderr,"malloc() failed\n");
  218.             exit(1);
  219.         }
  220.  
  221.                aLen = sizeof(addr);            /* accept result */
  222.         new->sock = accept(sock,&addr,&aLen);
  223.         if (new->sock < 0) {
  224.             perror("accept");
  225.             exit(1);
  226.         }
  227.         sprintf(buf,"<%s>",inet_ntoa(addr.sin_addr));
  228.         fprintf(stderr,"\n  %-18.17s",buf);
  229.         if (new->sock > sfdmax) sfdmax = new->sock;
  230.  
  231.         xdrrec_create(&(new->xdrs),0,0,        /* make xdr_stuff */
  232.                 (char *)&(new->sock),readit,NULL);
  233.         new->xdrs.x_op = XDR_DECODE;
  234.             if (!xdrrec_skiprecord(&(new->xdrs))) {    /* read next record*/
  235.                     fprintf(stderr,"xdrrec_skiprecord() failed\n");
  236.                     exit(1);
  237.         }
  238.                 if (!xdr_int(&(new->xdrs),&(new->wid))) {/* read info */
  239.             fprintf(stderr,"xdr_int() failed\n");
  240.             exit(1);
  241.         }
  242.                 if (!xdr_int(&(new->xdrs),&(new->pid))) {
  243.             fprintf(stderr,"xdr_int() failed\n");
  244.             exit(1);
  245.         }
  246.         cp = new->rUser;
  247.                 if (!xdr_string(&(new->xdrs),&cp,32)) {
  248.             fprintf(stderr,"xdr_string() failed\n");
  249.             exit(1);
  250.         }
  251.         cp = new->rwd;
  252.                 if (!xdr_string(&(new->xdrs),&cp,MAXPATHLEN)) {
  253.             fprintf(stderr,"xdr_string() failed\n");
  254.             exit(1);
  255.         }
  256.         
  257.         host = gethostbyaddr(&addr.sin_addr,    /* create client */
  258.             sizeof(addr.sin_addr),AF_INET);
  259.         if (host == NULL) {
  260.             perror("gethostbyaddr");
  261.             exit(1);
  262.         }
  263.         strncpy(new->name,host->h_name,MAXHOSTNAMELEN);
  264.         bcopy((char *)&addr.sin_addr,
  265.             (char *)&new->addr,
  266.             sizeof(addr.sin_addr));
  267.         new->clnt = clnt_create(new->name,
  268.                 INETRAY+new->wid,IRV1,"udp");
  269.         new->done = 0;
  270.         if (new->clnt == NULL) {
  271.             fprintf(stderr,"Warning: clnt_create(%s)",new->name);
  272.             clnt_pcreateerror("");
  273.             new->done = -1;
  274.         } else if (!clnt_control(new->clnt,CLSET_TIMEOUT,&noDefault)) {
  275.             fprintf(stderr,"clnt_control() failed\n");
  276.             exit(1);
  277.         }
  278.  
  279.         new->next = hosts;            /* link it in list */
  280.         hosts = new;
  281.  
  282.         if (!doThis(new->name) ||        /* drop it */
  283.                 (nRunning == maxWorkers)) {        
  284.             new->done = -1;            /* sentinel */
  285.             fprintf(stderr,"(%s[%d] ignored)",
  286.                 new->name,new->pid);
  287.         } else if (new->done == 0) {
  288.             new->broken = FALSE;
  289.             nRunning++;            /* found one */
  290.             sprintf(buf,"%s[%d]",new->name,new->pid);
  291.             fprintf(stderr,"%-20.19s%-10.9s%s",
  292.                     buf,new->rUser,new->rwd);
  293.         }
  294.     } FOREVER;
  295.  
  296.     for (old = NULL, new = hosts;            /* drop from list */
  297.          new != NULL;
  298.          new = new->next) {
  299.         if (new->done == 0) {
  300.             old = new;
  301.             continue;
  302.         }
  303.         res = clnt_call(new->clnt,TERMINATE,
  304.                     xdr_int,&key,
  305.                     xdr_void,NULL,
  306.                     now); 
  307.         if (res != 5) {
  308.             fprintf(stderr,"clnt_call(%s)",new->name);
  309.             clnt_perrno(res);
  310.             exit(1);
  311.         }
  312.         if (old == NULL) {            /* drop from list */
  313.             hosts = new->next;
  314.         } else {
  315.             old->next = new->next;
  316.         }
  317.     }
  318. }
  319.  
  320. int registerSvc(hName,cLine,cwd)    /* register servers */
  321. char *hName,*cLine,*cwd;        /* params for INIT */
  322. {
  323.     int    i;
  324.     iPrm    param;
  325.     struct sockaddr_in    addr;
  326.  
  327.     param.rName = hName;        /* compose parameters */
  328.     param.cmdLine = cLine;
  329.     stripHome(geteuid(),cwd);
  330.     param.cwd = cwd;
  331.     param.key = key;
  332.     param.rPort = portNumber;
  333.     
  334.     /* listen on socket */
  335.     if ((sock = socket(PF_INET,SOCK_STREAM,0)) < 0) {
  336.         perror("socket");
  337.         exit(1);
  338.     }
  339.     addr.sin_family = AF_INET;
  340.     addr.sin_port = htons(portNumber);
  341.     addr.sin_addr.s_addr = INADDR_ANY;
  342.     if (bind(sock,&addr,sizeof(addr)) < 0) {
  343.         perror("bind");
  344.         exit(1);
  345.     }
  346.     if (listen(sock,5) < 0) {
  347.         perror("listen");
  348.         exit(1);
  349.     }
  350.  
  351.     fprintf(stderr,"start"); 
  352.     IRSbroadcast();                /* start servers */
  353.     fprintf(stderr,", delay"); 
  354.     sleep(STARTDELAY);            /* allow startup */
  355.     fprintf(stderr,", init"); 
  356.     IRbroadcast(INIT,xdr_iPrm,¶m);    /* start all workers */
  357.     fprintf(stderr,"]"); 
  358.     getAnswers();                /* wait for replys */
  359.     close(sock);
  360. }
  361.  
  362. void closeAll()                /* close all sockets */
  363. {
  364.     hInfo     *host;
  365.     
  366.     for (host = hosts; host != NULL; host = host->next) {
  367.         if (host->broken) continue;
  368.         xdr_destroy(&(host->xdrs));
  369.         clnt_destroy(host->clnt);
  370.         close(host->sock);
  371.     }
  372. }
  373.  
  374. void flushAll()                /* flush all sockets */
  375. {
  376.     hInfo     *host;
  377.     fd_set     sockSet;
  378.     char    buf[1024];
  379.     int    res;
  380.     struct timeval tout;
  381.  
  382.     tout.tv_sec = FLUSHTIMEOUT;
  383.     tout.tv_usec = 0;
  384.     do {
  385.     restartSelect:
  386.             FD_ZERO(&sockSet);
  387.         for (host = hosts; host != NULL; host = host->next)
  388.             if (!host->broken)
  389.                 FD_SET(host->sock,&sockSet);
  390.             res = select(sfdmax+1,&sockSet,NULL,NULL,&tout);
  391.                if (res < 0) {
  392.                    if (errno == EINTR) goto restartSelect;
  393.                     perror("select");
  394.             exit(1);
  395.         }
  396.         if (res == 0) return;    /* done */
  397.         for (host = hosts; host != NULL; host = host->next) {
  398.             if (host->broken) continue;
  399.             if (FD_ISSET(host->sock,&sockSet)) {
  400.                 if (read(host->sock,buf,1024) < 0) {
  401.                     perror("read");
  402.                     exit(1);
  403.                 }
  404.             }
  405.         }
  406.         } FOREVER;
  407. }
  408.  
  409. void killAll()                /* kill all servers */
  410. {
  411.     hInfo     *host;
  412.     int    *res;
  413.  
  414.     for (host = hosts; host != NULL; host = host->next) {
  415.         if (host->broken) continue;
  416.         res = kill_1(&key,host->clnt);
  417.         if (res == (int *)NULL) {
  418.             fprintf(stderr,"kill(): ");
  419.             abort1(host);
  420.         }
  421.     }
  422. }
  423.  
  424. void waitAll()                /* wait on all clients */
  425. {
  426.     hInfo     *host;
  427.     int    *res;
  428.  
  429.     for (host = hosts; host != NULL; host = host->next) {
  430.         if (host->broken) continue;
  431.         res = wait_1(&key,host->clnt);
  432.         if (res == (int *)NULL) {
  433.             fprintf(stderr,"wait(): ");
  434.             abort1(host);
  435.         }
  436.     }
  437. }
  438.  
  439. void terminateAll()            /* terminate all svcs */
  440. {
  441.     hInfo     *host;
  442.     fd_set     sockSet;
  443.     int    res,n,time=0;
  444.  
  445.     IRbroadcast(TERMINATE,xdr_int,&key);    /* terminate all */
  446.     sleep(1); time++;
  447.  
  448.     while (time < TERMTIMEOUT) {
  449.     restartSelect:
  450.             FD_ZERO(&sockSet);
  451.             for (n=0,host=hosts; host!=NULL; host=host->next) {
  452.                 if (host->broken) continue;
  453.             FD_SET(host->sock,&sockSet);
  454.             n++;
  455.         }
  456.             res = select(sfdmax+1,&sockSet,NULL,NULL,&now);
  457.                if (res < 0) {
  458.                    if (errno == EINTR) goto restartSelect;
  459.                     perror("select");
  460.             exit(1);
  461.         }
  462.         if (n == res) return;        /* done */
  463.         for (host = hosts; host != NULL; host = host->next)
  464.             host->broken = FD_ISSET(host->sock,&sockSet);
  465.         sleep(1); time++;
  466.         }
  467.         fprintf(stderr,"Warning: The following servers did not terminate:\n");
  468.         for (host = hosts; host != NULL; host = host->next) {
  469.                 if (!FD_ISSET(host->sock,&sockSet)) 
  470.                         fprintf(stderr,"\t%s[%d]\n",host->name,host->pid);
  471.         }
  472. }
  473.