home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Photo CD Demo 1
/
Demo.bin
/
inetray
/
comm.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-07-03
|
12KB
|
473 lines
/*======================================================================
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);
}
}