home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (c) 1989,1990,1991 University of Rochester
- * Department of Electrical Engineering
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * at the University of Rochester.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
- /*
- * rsdclnt.c for the 'lb' load balancer
- * -Deke Kassabian, University of Rochester EE Department
- * ( deke@ee.rochester.edu ) (716) 275-3106
- *
- * $Revision: 1.2 $
- * $Author: deke $
- * $Date: 91/03/03 17:52:36 $
- * $Log: rsdclnt.c,v $
- * Revision 1.2 91/03/03 17:52:36 deke
- * changed stats to lstats to avoid name clash: required by change in rstat.h
- *
- */
-
- #include <stdio.h>
- #include <rpc/rpc.h>
- #include <rpcsvc/rstat.h>
- #include "config.h"
-
- main(argc, argv, envp)
- int argc;
- char *argv[];
- char *envp[];
- {
-
- struct statstime lstats;
- FILE *fd,*fopen();
- char *fgets();
- int getstats();
-
- int start, /* where in the argv the command begins */
- ppgrp, /* parent process group */
- command, /* whether there is a command */
- verbose_mode, /* all possible output */
- quiet_mode; /* no output */
-
- char *path=RSH;
-
- char *dir,*pname;
- char *cmd_exec[MAXSHBUF], /* command to execute (local) */
- *rcmd_exec[MAXSHBUF], /* command to execute (remote) */
- dbuf[MAXSHBUF], /* working directory placeholder */
- host[MAXHOST], /* hostname placeholder */
- best_host[MAXHOST], /* hostname placeholder */
- fentry[MAXLINE]; /* file buffer */
-
- float my_sfactor,
- best_sfactor,
- factor, limit, /* file variables */
- load;
-
- pname = *argv; /* Name of this program */
- verbose_mode=0,quiet_mode=0; /* Default is neither */
- best_sfactor=MAXFLOAT; /* Practically infinity! */
- command=1; /* There is a command */
-
- /* Check arguments.
- *
- * if argc=1 then verbose=Y and command=NULL
- * if argc>=2 check for flags:
- * -v=verbose (full output), -q=quiet (don't output machine selection)
- * with no flags, only machine selection will be output
- * The above flags are mutually exclusive. v overrides q
- *
- * Additional arguments are taken to be a command. No sanity checking
- * will be done. When a machine is selected, the command will be sent
- * to that machine as a shell command.
- *
- */
-
- if (argc == 1) {
- command=0; /* no command to execute */
- verbose_mode=1; /* verbose mode */
- }
- else {
- start=1;
- if(!strcmp(argv[1],"-q")){
- quiet_mode=1; /* quiet mode - no output */
- start=2;
- if(argc == 2) exit(0); /* No command, no output! */
- }
- if(!strcmp(argv[1],"-v")){
- verbose_mode=1; /* verbose mode */
- start=2;
- if(argc == 2) command=0; /* No command - verbose */
- }
- }
- if(command){
- for( ; start<argc ; start++){
- strcat(cmd_exec," "); strcat(cmd_exec,argv[start]);
- }
- }
-
-
- if((fd=fopen(CONFIGFILE,"r"))==0){
- fprintf(stderr,"Error opening configuration file\n");
- exit(1);
- }
-
- while((fgets(fentry,MAXLINE,fd))!=NULL){
- sscanf(fentry,"%s %f %f",host,&factor,&limit);
- if(fentry[0]=='#') continue; /*ignore comments*/
-
- if(verbose_mode)
- printf("\nHOST=%s\tFACTOR=%.2f\tLIMIT=%.2f\n",host,factor,limit);
-
- if(getstats(host,&lstats) !=0){
- load=MAXFLOAT; /* skip this one */
- }
- else {
- load=loadavg(&lstats,0);
- }
-
- if( load > limit){
- if(verbose_mode) printf("Host %s is over defined limit\n",host);
- continue;
- }
-
- my_sfactor=100*(load/factor);
-
- if(verbose_mode)
- printf("Load avg=%.3f\tSelection factor=%.3f\n",
- load,my_sfactor);
-
- if(best_sfactor>my_sfactor){
- best_sfactor=my_sfactor;
- strcpy(best_host,host);
- }
- } /*endwhile */
-
- if(verbose_mode)
- printf("Selected host: <%s> factor=<%.3f>\n",best_host,best_sfactor);
-
- if(command){
- sprintf(rcmd_exec,"(cd %s;%s)",getwd(dbuf),cmd_exec);
- if(!quiet_mode){ /* print if not quiet_mode */
- printf("\nrsh %s %s &\n",best_host,rcmd_exec);
- }
- ppgrp = getpgrp(getppid());
- if (fork())
- exit(0);
- if(setpgrp(getpid(), ppgrp))
- perror("stepgrp");
- execle(path,path,best_host,rcmd_exec,(char *)0,envp); exit(0);
- perror("");
- }
- exit(0);
- }
-
- getstats(hostname,lstats)
- char *hostname;
- struct statstime *lstats;
- {
- int c;
- c=rstat(hostname,lstats); /* rstat seems to return: */
- /* 0 on success */
- /* 13 on hostname lookup fail */
- /* 14 on connection timeout */
- /* 15 on "rstat not supported" */
- /* I chose to generate my own error messages. perror() didn't */
- /* give error messages I liked. Switch back to perror if you */
- /* care to. */
-
- switch(c){
- case 0:
- break;
- case 13:
- fprintf(stderr,"rstat error (%d): ",c);
- fprintf(stderr,"host %s is unknown.\n",hostname);
- break;
- case 14:
- fprintf(stderr,"rstat error (%d): ",c);
- fprintf(stderr,"host %s is down or unreachable.\n",hostname);
- break;
- case 15:
- fprintf(stderr,"rstat error (%d): ",c);
- fprintf(stderr,"host %s does not support protocol.\n",hostname);
- break;
- default:
- fprintf(stderr,"rstat error (%d): ",c);
- fprintf(stderr,"unknown error\n");
- break;
- }
- return(c);
- }
-