home *** CD-ROM | disk | FTP | other *** search
- /*======================================================================
- C O M M . C
- doc: Thu Mar 5 12:32:02 1992
- dlm: Fri Jul 3 15:02:47 1992
- (c) 1992 ant@julia
- uE-Info: 262 17 T 0 0 72 2 2 8 ofnI
- ======================================================================*/
-
- #include <stdio.h>
- #include <signal.h>
- #include </usr/include/netdb.h> /* prefer system over rpc/netdb.h */
- #include <errno.h>
- #include <sys/time.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <sys/param.h>
- #include <rpc/rpc.h>
- #include <arpa/inet.h>
- #include <netinet/in.h>
- #include "inetray.h"
- #include "inetray.start.h"
- #include "rcfile.h"
- #include "common.h"
- #include "utils.h"
- #include "config.h"
- #ifdef AUX_QUIRK
- #include "aux_quirk.h"
- #endif
-
- hInfo *hosts = NULL; /* list of hosts */
- int sfdmax = 0; /* max fd for ressocks */
- int nRunning = 0; /* number of workers running */
-
- static int sock; /* listening socket */
-
- extern int errno; /* to restart syscalls */
- extern int key; /* session key */
-
- void shutDown() /* shut down operation */
- {
- int i,res;
- void killAll(),flushAll(),waitAll(),terminateAll(),closeAll();
-
- for (i=1; i<=32; i++) /* ignore all signals */
- signal(i,SIG_IGN);
- fprintf(stderr,"\nShutting down...");
- killAll(); /* kill workers */
- flushAll(); /* flush result sockets */
- waitAll(); /* wait for workers */
- terminateAll(); /* terminate servers */
- closeAll(); /* close sockets */
- putc('\n',stderr);
- exit(0);
- }
-
- void abort1(host) /* this one is broken */
- hInfo *host;
- {
- fprintf(stderr,"\tWarning: Lost connection with %s (check SYSLOG)\n",
- host->name);
- host->broken = TRUE; /* this host crashed */
- close(host->sock);
- if (--nRunning == 0) { /* still servers running? */
- fprintf(stderr,"We're alone now...");
- shutDown();
- }
- }
-
- void IRbroadcast(fNum,inP,in) /* bcast INIT or TERMINATE */
- u_long fNum; char *in; xdrproc_t inP;
- {
- int i,res,exists,uid,nSvcs;
- char *addr;
-
- exists = getHost(TRUE,&addr,&nSvcs,&uid); /* hosts */
- while (exists) {
- if (fNum == INIT)
- ((iPrm *)in)->uid = uid;
- for (i=0; i<nSvcs; i++) {
- res = sendrpc(addr,INETRAY+i,IRV1,fNum,
- inP,in,xdr_void,NULL);
- if ((res != 0) &&
- ((fNum != TERMINATE) || (res != RPC_PROGNOTREGISTERED))) {
- fprintf(stderr,
- "\nWarning: sendrpc(%s,%d): ",
- addr,fNum);
- clnt_perrno(res);
- }
- }
- exists = getHost(FALSE,&addr,&nSvcs,&uid);
- }
-
- exists = getNet(TRUE,&addr,&nSvcs,&uid); /* nets */
- while (exists) {
- if (fNum == INIT)
- ((iPrm *)in)->uid = uid;
- for (i=0; i<nSvcs; i++) {
- res = clnt_dirbcast(addr,INETRAY+i,IRV1,fNum,
- inP,in,xdr_void,NULL,NULL);
- if (res != 0) {
- fprintf(stderr,
- "\nWarning: clnt_dirbcast(%s,%d): ",
- addr,fNum);
- clnt_perrno(res);
- }
- }
- exists = getNet(FALSE,&addr,&nSvcs,&uid);
- }
-
- getLocal(&addr,&nSvcs,&uid); /* LAN */
- if (fNum == INIT)
- ((iPrm *)in)->uid = uid;
- for (i=0; i<nSvcs; i++) {
- res = clnt_broadcast(INETRAY+i,IRV1,fNum,
- inP,in,xdr_void,NULL,NULL);
- if (res != 0) {
- fprintf(stderr,
- "\nWarning: clnt_broadcast(%d): ",fNum);
- clnt_perrno(res);
- }
- }
- }
-
- void IRSbroadcast() /* bcast START */
- {
- int res,exists;
- char *addr;
- sPrm p;
-
- exists = getHost(TRUE,&addr,&p.nSvcs,&p.uid); /* hosts */
- while (exists) {
- if (p.nSvcs > 0) {
- res = sendrpc(addr,STARTER,IRSV1,START,
- xdr_sPrm,&p,xdr_void,NULL);
- if ((res != 0) && (res != RPC_PROGNOTREGISTERED)) {
- fprintf(stderr,
- "\nWarning: sendrpc(%s,START): ",addr);
- clnt_perrno(res);
- }
- }
- exists = getHost(FALSE,&addr,&p.nSvcs,&p.uid);
- }
-
- exists = getNet(TRUE,&addr,&p.nSvcs,&p.uid); /* nets */
- while (exists) {
- if (p.nSvcs > 0) {
- res = clnt_dirbcast(addr,STARTER,IRSV1,START,
- xdr_sPrm,&p,xdr_void,NULL,NULL);
- if (res != 0) {
- fprintf(stderr,
- "\nWarning: clnt_dirbcast(%s,START): ",addr);
- clnt_perrno(res);
- }
- }
- exists = getNet(FALSE,&addr,&p.nSvcs,&p.uid);
- }
-
- getLocal(&addr,&p.nSvcs,&p.uid); /* LAN */
- if (p.nSvcs > 0) {
- res = clnt_broadcast(STARTER,IRSV1,START,
- xdr_sPrm,&p,xdr_void,NULL,NULL);
- if (res != 0) {
- fprintf(stderr,"\nWarning: clnt_broadcast(START): ");
- clnt_perrno(res);
- }
- }
- }
-
- static readit(fdp,buf,nbyte) /* xdr aux routine */
- char *fdp,*buf; int nbyte;
- {
- int nread,fd;
-
- fd = *(int *)fdp;
- reStartRead:
- nread = read(fd,buf,nbyte);
- if (nread < 0) {
- if (errno == EINTR) {
- goto reStartRead;
- }
- perror("read");
- }
- if (nread == 0) nread = -1;
- return nread;
- }
-
- static void getAnswers() /* wait for answers */
- {
- int aLen,res;
- hInfo *new,*old;
- fd_set sockSet;
- char buf[64],*cp;
- struct hostent *host;
- struct servent *s;
- struct sockaddr_in addr;
- struct timeval tout,noDefault;
-
- tout.tv_sec = rTimeout; /* timeout */
- tout.tv_usec = 0;
- noDefault.tv_sec = noDefault.tv_usec = -1; /* use supplied val */
- do {
- do {
- restartSelect:
- FD_ZERO(&sockSet); /* select() on socket */
- FD_SET(sock,&sockSet);
- res = select(sock+1,&sockSet,NULL,NULL,&tout);
- if (res < 0) {
- if (errno == EINTR) goto restartSelect;
- perror("select");
- exit(1);
- }
- } while ((res == 0) && (nRunning < minWorkers));
- if (res == 0) break; /* done */
-
- new = (hInfo *)malloc(sizeof(hInfo)); /* alloc node */
- if (new == NULL) {
- fprintf(stderr,"malloc() failed\n");
- exit(1);
- }
-
- aLen = sizeof(addr); /* accept result */
- new->sock = accept(sock,&addr,&aLen);
- if (new->sock < 0) {
- perror("accept");
- exit(1);
- }
- sprintf(buf,"<%s>",inet_ntoa(addr.sin_addr));
- fprintf(stderr,"\n %-18.17s",buf);
- if (new->sock > sfdmax) sfdmax = new->sock;
-
- xdrrec_create(&(new->xdrs),0,0, /* make xdr_stuff */
- (char *)&(new->sock),readit,NULL);
- new->xdrs.x_op = XDR_DECODE;
- if (!xdrrec_skiprecord(&(new->xdrs))) { /* read next record*/
- fprintf(stderr,"xdrrec_skiprecord() failed\n");
- exit(1);
- }
- if (!xdr_int(&(new->xdrs),&(new->wid))) {/* read info */
- fprintf(stderr,"xdr_int() failed\n");
- exit(1);
- }
- if (!xdr_int(&(new->xdrs),&(new->pid))) {
- fprintf(stderr,"xdr_int() failed\n");
- exit(1);
- }
- cp = new->rUser;
- if (!xdr_string(&(new->xdrs),&cp,32)) {
- fprintf(stderr,"xdr_string() failed\n");
- exit(1);
- }
- cp = new->rwd;
- if (!xdr_string(&(new->xdrs),&cp,MAXPATHLEN)) {
- fprintf(stderr,"xdr_string() failed\n");
- exit(1);
- }
-
- host = gethostbyaddr(&addr.sin_addr, /* create client */
- sizeof(addr.sin_addr),AF_INET);
- if (host == NULL) {
- perror("gethostbyaddr");
- exit(1);
- }
- strncpy(new->name,host->h_name,MAXHOSTNAMELEN);
- bcopy((char *)&addr.sin_addr,
- (char *)&new->addr,
- sizeof(addr.sin_addr));
- new->clnt = clnt_create(new->name,
- INETRAY+new->wid,IRV1,"udp");
- new->done = 0;
- if (new->clnt == NULL) {
- fprintf(stderr,"Warning: clnt_create(%s)",new->name);
- clnt_pcreateerror("");
- new->done = -1;
- } else if (!clnt_control(new->clnt,CLSET_TIMEOUT,&noDefault)) {
- fprintf(stderr,"clnt_control() failed\n");
- exit(1);
- }
-
- new->next = hosts; /* link it in list */
- hosts = new;
-
- if (!doThis(new->name) || /* drop it */
- (nRunning == maxWorkers)) {
- new->done = -1; /* sentinel */
- fprintf(stderr,"(%s[%d] ignored)",
- new->name,new->pid);
- } else if (new->done == 0) {
- new->broken = FALSE;
- nRunning++; /* found one */
- sprintf(buf,"%s[%d]",new->name,new->pid);
- fprintf(stderr,"%-20.19s%-10.9s%s",
- buf,new->rUser,new->rwd);
- }
- } FOREVER;
-
- for (old = NULL, new = hosts; /* drop from list */
- new != NULL;
- new = new->next) {
- if (new->done == 0) {
- old = new;
- continue;
- }
- res = clnt_call(new->clnt,TERMINATE,
- xdr_int,&key,
- xdr_void,NULL,
- now);
- if (res != 5) {
- fprintf(stderr,"clnt_call(%s)",new->name);
- clnt_perrno(res);
- exit(1);
- }
- if (old == NULL) { /* drop from list */
- hosts = new->next;
- } else {
- old->next = new->next;
- }
- }
- }
-
- int registerSvc(hName,cLine,cwd) /* register servers */
- char *hName,*cLine,*cwd; /* params for INIT */
- {
- int i;
- iPrm param;
- struct sockaddr_in addr;
-
- param.rName = hName; /* compose parameters */
- param.cmdLine = cLine;
- stripHome(geteuid(),cwd);
- param.cwd = cwd;
- param.key = key;
- param.rPort = portNumber;
-
- /* listen on socket */
- if ((sock = socket(PF_INET,SOCK_STREAM,0)) < 0) {
- perror("socket");
- exit(1);
- }
- addr.sin_family = AF_INET;
- addr.sin_port = htons(portNumber);
- addr.sin_addr.s_addr = INADDR_ANY;
- if (bind(sock,&addr,sizeof(addr)) < 0) {
- perror("bind");
- exit(1);
- }
- if (listen(sock,5) < 0) {
- perror("listen");
- exit(1);
- }
-
- fprintf(stderr,"start");
- IRSbroadcast(); /* start servers */
- fprintf(stderr,", delay");
- sleep(STARTDELAY); /* allow startup */
- fprintf(stderr,", init");
- IRbroadcast(INIT,xdr_iPrm,¶m); /* start all workers */
- fprintf(stderr,"]");
- getAnswers(); /* wait for replys */
- close(sock);
- }
-
- void closeAll() /* close all sockets */
- {
- hInfo *host;
-
- for (host = hosts; host != NULL; host = host->next) {
- if (host->broken) continue;
- xdr_destroy(&(host->xdrs));
- clnt_destroy(host->clnt);
- close(host->sock);
- }
- }
-
- void flushAll() /* flush all sockets */
- {
- hInfo *host;
- fd_set sockSet;
- char buf[1024];
- int res;
- struct timeval tout;
-
- tout.tv_sec = FLUSHTIMEOUT;
- tout.tv_usec = 0;
- do {
- restartSelect:
- FD_ZERO(&sockSet);
- for (host = hosts; host != NULL; host = host->next)
- if (!host->broken)
- FD_SET(host->sock,&sockSet);
- res = select(sfdmax+1,&sockSet,NULL,NULL,&tout);
- if (res < 0) {
- if (errno == EINTR) goto restartSelect;
- perror("select");
- exit(1);
- }
- if (res == 0) return; /* done */
- for (host = hosts; host != NULL; host = host->next) {
- if (host->broken) continue;
- if (FD_ISSET(host->sock,&sockSet)) {
- if (read(host->sock,buf,1024) < 0) {
- perror("read");
- exit(1);
- }
- }
- }
- } FOREVER;
- }
-
- void killAll() /* kill all servers */
- {
- hInfo *host;
- int *res;
-
- for (host = hosts; host != NULL; host = host->next) {
- if (host->broken) continue;
- res = kill_1(&key,host->clnt);
- if (res == (int *)NULL) {
- fprintf(stderr,"kill(): ");
- abort1(host);
- }
- }
- }
-
- void waitAll() /* wait on all clients */
- {
- hInfo *host;
- int *res;
-
- for (host = hosts; host != NULL; host = host->next) {
- if (host->broken) continue;
- res = wait_1(&key,host->clnt);
- if (res == (int *)NULL) {
- fprintf(stderr,"wait(): ");
- abort1(host);
- }
- }
- }
-
- void terminateAll() /* terminate all svcs */
- {
- hInfo *host;
- fd_set sockSet;
- int res,n,time=0;
-
- IRbroadcast(TERMINATE,xdr_int,&key); /* terminate all */
- sleep(1); time++;
-
- while (time < TERMTIMEOUT) {
- restartSelect:
- FD_ZERO(&sockSet);
- for (n=0,host=hosts; host!=NULL; host=host->next) {
- if (host->broken) continue;
- FD_SET(host->sock,&sockSet);
- n++;
- }
- res = select(sfdmax+1,&sockSet,NULL,NULL,&now);
- if (res < 0) {
- if (errno == EINTR) goto restartSelect;
- perror("select");
- exit(1);
- }
- if (n == res) return; /* done */
- for (host = hosts; host != NULL; host = host->next)
- host->broken = FD_ISSET(host->sock,&sockSet);
- sleep(1); time++;
- }
- fprintf(stderr,"Warning: The following servers did not terminate:\n");
- for (host = hosts; host != NULL; host = host->next) {
- if (!FD_ISSET(host->sock,&sockSet))
- fprintf(stderr,"\t%s[%d]\n",host->name,host->pid);
- }
- }
-