Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.2 9/18/84; site sdcc3.UUCP Path: utzoo!watmath!clyde!bonnie!akgua!sdcsvax!sdcc3!muller From: muller@sdcc3.UUCP (Keith Muller) Newsgroups: net.sources Subject: load control system (8 of 8) Message-ID: <2683@sdcc3.UUCP> Date: Tue, 12-Feb-85 14:07:54 EST Article-I.D.: sdcc3.2683 Posted: Tue Feb 12 14:07:54 1985 Date-Received: Thu, 14-Feb-85 01:27:02 EST Organization: U.C. San Diego, Academic Computer Center Lines: 491 This is part 8 (last one!) of the load control system. Part 1 must be unpacked before any other part. Keith Muller ucbvax!sdcsvax!muller # This is a shell archive. Remove anything before this line, # then unpack it by saving it in a file and typing "sh file". # # Wrapped by sdcc3!muller on Sat Feb 9 13:58:45 PST 1985 # Contents: server/setup.c echo x - server/setup.c sed 's/^@//' > "server/setup.c" <<'@//E*O*F server/setup.c//' /*------------------------------------------------------------------------- * setup.c - server * * routines needed to start up the server. *------------------------------------------------------------------------- */ /* $Log$ */ #include "../h/common.h" #include "../h/server.h" #include#include #include #include #include #include #include #include #include #include #include #include #include /*------------------------------------------------------------------------- * doargs * * check the command line arguement list and set up the global parameters. * * Note that both -X value and -Xvalue format for any flag X is accepted *------------------------------------------------------------------------- */ doargs(argc, argv) int argc; char **argv; { register int i; register char *ptr; int lasti; int badarg; #ifdef sun extern long loadlevel; #else extern double loadlevel; #endif sun extern u_long mqtime; extern struct itimerval startalrm; extern long atol(); extern int atoi(); extern double atof(); badarg = 0; for (i = 1; i < argc; i++){ if (argv[i][0] != '-'){ fprintf(stderr,"bad arg: %s\n", argv[i]); badarg = 1; break; } lasti = i; /* * set ptr to point at start of flags VALUE. * if strlen > 2 must be -Xvalue format * otherwise set ptr to point at next argv */ if (strlen(argv[i]) > 2) ptr = &(argv[i][2]); else if ((i+1) < argc) ptr = argv[++i]; else{ fprintf(stderr,"bad arg: %s\n", argv[i]); badarg = 1; break; } switch(argv[lasti][1]){ case 'L': /* * load level to queue at */ #ifdef sun if ((loadlevel = (long)(atof(ptr)*256)) <= 0){ fprintf(stderr,"bad loadlevel: %ld\n",atof(ptr)); #else if ((loadlevel = atof(ptr)) <= 0){ fprintf(stderr,"bad loadlevel: %lf\n",loadlevel); #endif badarg = 1; } break; case 'T': /* * timer cycle time for load checks */ if ((startalrm.it_value.tv_sec = atol(ptr))<1){ fprintf(stderr,"bad alarmtime: %ld\n",atol(ptr)); badarg = 1; } break; default: fprintf(stderr,"unknown arg: %s\n",argv[lasti]); badarg = 1; break; } if (badarg == 1) break; } if (badarg == 1){ fprintf(stderr,"Useage: %s [-L load] [-T alarm]\n",argv[0]); exit(1); } } /*-------------------------------------------------------------------------- * setup * * a collection of code need at startup to set up the server. such as * checking to make sure only one server runs, detatch server from control * terminal etc *-------------------------------------------------------------------------- */ setup() { register int i; int lockfile; int temp; char line[20]; static struct nlist avenrun[] = { {"_avenrun"}, {""}}; extern int alrmmask; extern long loadaddr; extern int descsize; extern int kmem; extern int errno; extern int errorcount; extern FILE *errfile; extern FILE *fopen(); extern int getpid(); extern int onalrm(); extern int getpid(); extern int setpriority(); extern char *sprintf(); if (getuid() != 0){ fprintf(stderr, "must run as root\n"); exit(1); } /* * see if the spool dir where the client sockets are bound exsists */ if (access(SPOOLDIR, F_OK) == -1){ fprintf(stderr,"No directory: %s\n", SPOOLDIR); exit(1); } /* * see if the spool dir where the server sockets are bound exsists */ if (access(SERVERDIR, F_OK) == -1){ fprintf(stderr,"No directory: %s\n", SERVERDIR); exit(1); } /* * detach from foreground */ if (fork() != 0) exit(0); /* * close down all open descriptors * so the server is no longer attached to any tty */ descsize = getdtablesize(); for (i = 0; i < descsize; i++) (void)close(i); (void)open("/dev/null",O_RDONLY); (void)open("/dev/null", O_WRONLY); (void)open("/dev/null", O_WRONLY); /* * do an ioctl to /dev/tty to detach server from ttys */ if ((i = open("/dev/tty", O_RDWR)) > 0){ (void)ioctl(i, TIOCNOTTY, (char *)0); (void)close(i); } /* * set umask to remove all others permissions */ (void)umask(027); /* * open the error logging file */ errfile = fopen(ERRORPATH,"a+"); if (errfile < 0) exit(1); /* * check lockfile for other servers already running uses advisory * locking */ lockfile = open (LOCK, O_WRONLY|O_CREAT, 0640); if (lockfile < 0){ errlog("cannot create lockfile"); exit(1); } if (flock(lockfile, LOCK_EX|LOCK_NB) < 0){ if (errno == EWOULDBLOCK) exit(0); errlog("cannot lock lockfile"); exit(1); } /* * write the pid of this server in the lock file in case you * need to blow the server away. (not currently used). */ i = getpid(); (void)ftruncate(lockfile, 0); (void)sprintf(line, "%d\n", i); temp = strlen(line); if (write(lockfile, line, temp) != temp) errlog("cannot write server pid"); /* * mark the logfile that a new server is starting */ (void)fprintf(errfile,"server pid: %d ",i); errno = 0; errlog("started at"); errorcount = 0; /* * lower the server priority so that under heavy load the server * can get the machine cycles when it needs them. The server * uses very small amounts of cpu, so this is not going to impact * the system. */ if (setpriority(0, i, PRIO) < 0 ) errlog("cannot lower priority"); /* * open kmem where the load average will be read from */ if ((kmem = open("/dev/kmem", O_RDONLY)) < 0){ errlog("cannot open kmem"); cleanup(); } /* * get the address in this vmunix where the load average is * loacated in the kernel data space */ nlist("/vmunix", avenrun); if (avenrun[0].n_value == 0){ errlog("cannot find _avenrun"); cleanup(); } loadaddr = (long)avenrun[0].n_value; /* * bind the signal handlers now */ (void)signal(SIGALRM, onalrm); /* * mask used to block off sigalrm when the data structures * are being changed and must not service a timer interrupt * to check the load average */ alrmmask = 1 << (SIGALRM - 1); } /*--------------------------------------------------------------------------- * scanspool * * when the server is restarted it could be right after an older server * just terminated and left a lot of jobs queued up. since the queue is * kept in memory for speed, no record exsists anymore about the queued * clients. Since all the client sockets are bound in the same spool * directory simply search the directory for a client socket and send it * a POLLCMD. the client will respond to the POLLCMD by resubmitting its * work request datagram. The addqueue routine rebuilds the queue by time * so the queue will be in the proper order. Any dead cleints whose bound * sockets are still in the spool will be removed (the bound sockets). *--------------------------------------------------------------------------- */ scanspool() { register int i; int numfds; int readfds; u_long pid; int cnprlen; int clprlen; int tag; int msgmask; struct direct *dp; struct stat statbuf; DIR *dirp; extern struct timeval polltime; extern int msgsock; extern int descsize; extern long atol(); /* * open a directory for scanning */ if ((dirp = opendir(SPOOLDIR)) == NULL){ errlog("cannot open spool directory"); cleanup(); } /* * cd to the directory, this allows short names for binding and * has a place to look for core dumps if they might occur */ if (chdir(SPOOLDIR) == -1){ errlog("cannot cd to spool"); cleanup(); } /* * clprlen is length of the prefix of client socket. * cnprlen is length of prefix of control program socket. * needed to extract the uid */ clprlen = strlen(CLIENTPRE); cnprlen = strlen(CNTRLPRE); msgmask = 1 << msgsock; for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)){ /* * if not a possable client, go to next entry */ if (dp->d_ino == 0) continue; if (strncmp(CLIENTPRE, dp->d_name, clprlen) == 0) tag = 1; else if (strncmp(CNTRLPRE, dp->d_name, cnprlen) == 0) tag = 0; else continue; if (stat(dp->d_name, &statbuf) != 0){ errlog("stat on spool file failed"); continue; } /* * file has client or cntrol like name but is not a socket, * remove as could cause problems later */ if ((statbuf.st_mode & S_IFSOCK) == 0){ (void)unlink(dp->d_name); continue; } if (tag == 0){ /* * send a message to waiting control program. outcntrl * will remove if this is an old socket. */ pid = (u_long)atol(dp->d_name + cnprlen); (void)outcntrl(pid, POLLCMD); continue; } /* * is a client socket must force a resubmit of the job. If it * is an old socket outmsg will remove. */ pid = (u_long)atol(dp->d_name + clprlen); /* * throw a couple of POLLCMDS at the client to see if * he is still alive. If the system is loaded could take * a while to swap back in so give him time. */ for (i = 0; i < MAXPOLLS; i++){ if (outmsg(pid, POLLCMD) != 0) break; readfds = msgmask; numfds = select(descsize,&readfds,(int*)0,(int*)0,&polltime); if ((numfds < 0) && (errno != EINTR)){ errlog("select error in scanspool"); cleanup(); } /* * time in select expired and no answer from client * try again */ if (numfds <= 0){ continue; } /* * got a datagram, figure it out */ msgdis(); } } } /*------------------------------------------------------------------------- * crsock * * create all the sockets used by the server *------------------------------------------------------------------------- */ crsock() { int len; struct sockaddr_un name; extern int msgsock; extern int cntrlsock; extern char *strcpy(); /* * create the msgsocket where queue requests appear */ name.sun_family = AF_UNIX; msgsock = socket(AF_UNIX, SOCK_DGRAM, 0); if (msgsock < 0){ errlog("cannot create msgsock"); cleanup(); } /* * remove any entry in the file system for this name else the bind * will fail. We are sure from the locking that this is ok to do. */ (void)unlink(MSGPATH); (void)strcpy(name.sun_path, MSGPATH); len = strlen(name.sun_path) + sizeof(name.sun_family) + 1; if (bind(msgsock, &name, len) < 0){ errlog("cannot bind msgsock"); cleanup(); } /* * create the control socket for high priority control commands */ cntrlsock = socket(AF_UNIX, SOCK_DGRAM, 0); if (cntrlsock < 0){ errlog("cannot create cntrlsock"); cleanup(); } (void)unlink(CNTRLPATH); (void)strcpy(name.sun_path, CNTRLPATH); len = strlen(name.sun_path) + sizeof(name.sun_family) + 1; if (bind(cntrlsock, &name, len) < 0){ errlog("cannot bind cntrlsock"); cleanup(); } } @//E*O*F server/setup.c// chmod u=r,g=r,o=r server/setup.c echo Inspecting for damage in transit... temp=/tmp/shar$$; dtemp=/tmp/.shar$$ trap "rm -f $temp $dtemp; exit" 0 1 2 3 15 cat > $temp <<\!!! 461 1512 10759 setup.c !!! wc server/setup.c | sed 's=[^ ]*/==' | diff -b $temp - >$dtemp if [ -s $dtemp ] then echo "Ouch [diff of wc output]:" ; cat $dtemp else echo "No problems found." fi exit 0