load control system (8 of 8)
Keith Muller
muller at sdcc3.UUCP
Wed Feb 13 05:07:54 AEST 1985
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 <stdio.h>
#include <sys/time.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/uio.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/dir.h>
#include <sys/resource.h>
#include <nlist.h>
#include <signal.h>
#include <errno.h>
/*-------------------------------------------------------------------------
* 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
More information about the Comp.sources.unix
mailing list