load control (5 of 8)
Keith Muller
muller at sdcc3.UUCP
Tue Feb 12 18:17:11 AEST 1985
This is part 5 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:54:09 PST 1985
# Contents: control/ldccmdtab.c control/ldcmain.c control/ldqmain.c
# control/ldrmmain.c control/list.c
echo x - control/ldccmdtab.c
sed 's/^@//' > "control/ldccmdtab.c" <<'@//E*O*F control/ldccmdtab.c//'
/*---------------------------------------------------------------------------
* commandtab.c - control
*
* tables of commands that the load program will call
*
*---------------------------------------------------------------------------
*/
/* $Log$ */
#include "../h/control.h"
char aborhelp[] = "terminate the server (disable load control)";
char delhelp[] = "remove specified jobs (by pid or user) from the queue";
char errhelp[] = "print the contents of the error logging file";
char helphelp[] = "get help on any command";
char listhelp[] = "list all the jobs queued for a specified user";
char loadhelp[] = "change the load level above which jobs are queued";
char longhelp[] = "list all queued jobs";
char movehelp[] = "move a processes position in the queue";
char purghelp[] = "remove ALL the jobs from the queue (the jobs terminate)";
char quithelp[] = "exit the control program";
char runhelp[] = "run specified jobs (by pid or user) from the queue";
char sizehelp[] = "change the maximium number of jobs that can be queued";
char statushelp[] = "print the current settings of changeable parameters";
char timerhelp[] = "change the number of seconds between load average checks";
char waithelp[] = "change the maximium time (seconds) a job can be queued";
/*
* import the functions
*/
extern int abortserv(), delete(), errprint(), help(), list(), loadlimit(), longlist();
extern int move(), purge(), quit(), run(), sizeset(), status(), timerset(), waitset();
/*
* the command table
* the privledge column restrict certain commands to root (root only
* as other changes could cause the server to be aborted with no
* way to restart!
*/
struct cmd cmdtab[] = {
/* command helpmessage routine privledge */
{ "abort", aborhelp, abortserv, RESTRICT },
{ "delete", delhelp, delete, NORESTRICT },
{ "errors", errhelp, errprint, NORESTRICT },
{ "help", helphelp, help, NORESTRICT },
{ "list", listhelp, list, NORESTRICT },
{ "loadlimit", loadhelp, loadlimit, RESTRICT },
{ "longlist", longhelp, longlist, NORESTRICT },
{ "move", movehelp, move, RESTRICT },
{ "purge", purghelp, purge, RESTRICT },
{ "quit", quithelp, quit, NORESTRICT },
{ "run", runhelp, run, RESTRICT },
{ "sizeset", sizehelp, sizeset, RESTRICT },
{ "status", statushelp, status, NORESTRICT },
{ "timerset", timerhelp, timerset, RESTRICT },
{ "waitset", waithelp, waitset, RESTRICT },
{ "?", helphelp, help, NORESTRICT },
{ 0 },
};
int NCMDS = sizeof (cmdtab) / sizeof (cmdtab[0]);
@//E*O*F control/ldccmdtab.c//
chmod u=r,g=r,o=r control/ldccmdtab.c
echo x - control/ldcmain.c
sed 's/^@//' > "control/ldcmain.c" <<'@//E*O*F control/ldcmain.c//'
/*-------------------------------------------------------------------------
* main.c - control/ldc
*
* the ldc program is used to send commands to the server that can
* alter the servers execution or display the servers current state
*
* Author: Keith Muller
* University Of California, San Diego
* Academic Computer Center C - 010
* La Jolla, Ca 92093
* ucbvax!sdcsvax!sdcc3!muller
* (619) 452-6090
*-------------------------------------------------------------------------
*/
/* $Log$ */
#include "../h/common.h"
#include "../h/control.h"
#include <sys/uio.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/time.h>
#include <stdio.h>
#include <setjmp.h>
#include <errno.h>
int fromatty; /* set to 1 if interactive, 0 otherwise */
char cmdline[256]; /* buffer for the command */
char *margv[64]; /* args in interactive mode */
int margc; /* count of args */
jmp_buf toplevel; /* jmp_buf used if a command is aborted premature */
/*-------------------------------------------------------------------------
* main
*
*-------------------------------------------------------------------------
*/
main(argc, argv)
int argc;
char *argv[];
{
register struct cmd *c;
extern int uid;
extern int isatty();
extern char *gets();
extern struct cmd *getcmd();
/*
* set up the necessary overhead
*/
setup();
/*
* could be a single line command
*/
if (--argc > 0) {
if ((c = getcmd(*++argv)) == 0)
quit();
if ((c->c_priv == RESTRICT) && (uid != 0)){
printf("?Privileged command\n");
quit();
}
/*
* run the entry from the command table
*/
(*c->c_handler)(argc, argv);
/*
* clean up
*/
quit();
}
/*
* see if the program is attached to a tty
*/
fromatty = isatty(fileno(stdin));
/*
* on an interrupt return to this point!
*/
(void)setjmp(toplevel);
for (;;) {
if (fromatty){
printf("\nldc> ");
(void)fflush(stdout);
}
/*
* wait for io either on the tty or a status message
* from the server is read.
*/
if (iowait() == 0)
continue;
if (gets(cmdline) == NULL)
break;
if (cmdline[0] == '\0')
continue;
/*
* transform into a argv argc array
*/
makeargv();
/*
* valid command?
*/
if ((c = getcmd(margv[0])) == 0)
continue;
if ((c->c_priv == RESTRICT) && (uid != 0)) {
printf("?Privileged command\n");
continue;
}
/*
* run the command from the command table
*/
(*c->c_handler)(margc, margv);
}
quit();
}
/*-------------------------------------------------------------------------
* onint
*
* when an interrupt occurs jump here!
*-------------------------------------------------------------------------
*/
onint()
{
extern FILE *out;
/*
* if fromtty == 0 standard input is not a tty, so exit
*/
if (fromatty == 0)
quit();
/*
* if list or status command was interrupted, close off the
* open file
*/
if (out != NULL)
(void)fclose(out);
/*
* interactive so continue
*/
putchar('\n');
longjmp(toplevel, 1);
}
/*-------------------------------------------------------------------------
* quit
*
*-------------------------------------------------------------------------
*/
quit()
{
extern int sock;
extern char path[];
(void)close(sock);
(void)unlink(path);
exit(0);
}
/*-------------------------------------------------------------------------
* getcmd
*
* find closest fit for the command typed in
*-------------------------------------------------------------------------
*/
struct cmd *
getcmd(comname)
char *comname;
{
register char *p;
register char *q;
register struct cmd *c;
register struct cmd *found;
int nmatches;
int longest;
extern struct cmd cmdtab[];
longest = 0;
nmatches = 0;
found = (struct cmd *)0;
for (c = cmdtab; (p = c->c_name) != (char *)0; c++) {
for (q = comname; *q == *p++; q++){
/*
* exact match?
*/
if (*q == '\0')
return(c);
}
/*
* name is a prefix
*/
if (*q == '\0') {
if (q - comname > longest) {
longest = q - comname;
nmatches = 1;
found = c;
} else if ((q - comname) == longest)
nmatches++;
}
}
/*
* More than one match found
*/
if (nmatches > 1){
printf("?Ambiguous command\n");
return((struct cmd *)0);
}
/*
* No match found in table
*/
if (found == (struct cmd *)0)
printf("?Invalid command\n");
return(found);
}
/*-------------------------------------------------------------------------
* makeargv
*
* Slice a string up into argc/argv.
*-------------------------------------------------------------------------
*/
makeargv()
{
register char *cp;
register char **argp = margv;
margc = 0;
for (cp = cmdline; *cp != '\0'; ) {
/*
* skip over the blanks
*/
while (*cp == ' ')
cp++;
if (*cp == '\0')
break;
*argp++ = cp;
margc = margc + 1;
while ((*cp != '\0') && (*cp != ' '))
cp++;
if (*cp == '\0')
break;
*cp++ = '\0';
}
*argp++ = (char *)0;
}
/*-------------------------------------------------------------------------
* Help command.
*
*-------------------------------------------------------------------------
*/
help(argc, argv)
int argc;
char *argv[];
{
register struct cmd *c;
register int i;
register int j;
register int w;
char *arg;
int columns;
int width = 0;
int lines;
int len;
extern int NCMDS;
if (argc == 1) {
printf("Commands may be abbreviated. Commands are:\n");
for (c = cmdtab; c < &(cmdtab[NCMDS-1]); c++) {
len = strlen(c->c_name);
if (len > width)
width = len;
}
width = (width + 8) &~ 7;
columns = 80 / width;
if (columns == 0)
columns = 1;
lines = (NCMDS + columns - 1) / columns;
for (i = 0; i < lines; i++) {
for (j = 0; j < columns; j++) {
c = cmdtab + j * lines + i;
printf("%s", c->c_name);
if (c + lines >= &(cmdtab[NCMDS-1])) {
printf("\n");
break;
}
w = strlen(c->c_name);
while (w < width) {
w = (w + 8) &~ 7;
putchar('\t');
}
}
}
return;
}
while (--argc > 0) {
arg = *++argv;
if ((c = getcmd(arg)) == (struct cmd *)0)
continue;
printf("%-*s\t%s\n", 10, c->c_name, c->c_help);
}
}
/*-------------------------------------------------------------------------
* iowait
*
* wait for io on either stdin or a status message from server.
*-------------------------------------------------------------------------
*/
iowait()
{
int readfds;
int numfds;
char msg;
int fromlen = 0;
extern int errno;
extern int descsize;
extern int sockmask;
extern int stdinmask;
extern int sock;
for(;;){
readfds = sockmask | stdinmask;
numfds = select(descsize,&readfds,(int *)0,(int *)0,(struct timeval *)0);
if ((numfds < 0) && (errno != EINTR)){
perror("select failed");
quit();
}
if (numfds <= 0)
continue;
if (readfds & stdinmask)
return(1);
if (recvfrom(sock,&msg,sizeof(msg),0,(struct sockaddr *)0,&fromlen)<=0){
perror("Failed message from server");
quit();
}
switch(msg){
case POLLCMD:
printf("A new server just started\n");
break;
default:
printf("Unexpected message from server\n");
break;
}
return(0);
}
}
@//E*O*F control/ldcmain.c//
chmod u=r,g=r,o=r control/ldcmain.c
echo x - control/ldqmain.c
sed 's/^@//' > "control/ldqmain.c" <<'@//E*O*F control/ldqmain.c//'
/*-------------------------------------------------------------------------
* ldqmain.c - control/ldq
*
* the ldq program is used to print the contents of the load queue.
* The same function is also part of the ldc command.
*
* Author: Keith Muller
* University Of California, San Diego
* Academic Computer Center C - 010
* La Jolla, Ca 92093
* ucbvax!sdcsvax!sdcc3!muller
* (619) 452-6090
*-------------------------------------------------------------------------
*/
/* $Log$ */
#include "../h/control.h"
#include <stdio.h>
/*-------------------------------------------------------------------------
* main
*
*-------------------------------------------------------------------------
*/
main(argc, argv)
int argc;
char *argv[];
{
if (argc > 2){
printf("usage: ldq [-a] [user]\n");
exit(1);
}
/*
* set up the necessary overhead
*/
setup();
/*
* call the correct list version (same as in ldc).
*/
if ((argc == 2) && (strcmp(argv[1],"-a") == 0)){
/*
* decrement the argc count to get rid of the -a flag.
*/
argc = 1;
longlist(argc,argv);
}else{
/*
* must be a short list call
*/
list(argc,argv);
}
/*
* clean up the sockets
*/
quit();
}
/*-------------------------------------------------------------------------
* onint
*
* when an interrupt occurs jump here!
*-------------------------------------------------------------------------
*/
onint()
{
printf("\n....interrupted\n");
quit();
}
/*-------------------------------------------------------------------------
* quit
*
*-------------------------------------------------------------------------
*/
quit()
{
extern int sock;
extern char path[];
(void)close(sock);
(void)unlink(path);
exit(0);
}
@//E*O*F control/ldqmain.c//
chmod u=r,g=r,o=r control/ldqmain.c
echo x - control/ldrmmain.c
sed 's/^@//' > "control/ldrmmain.c" <<'@//E*O*F control/ldrmmain.c//'
/*-------------------------------------------------------------------------
* ldrmmain.c - control/ldrm
*
* the ldrm program is used to delete jobs from the load queue.
* The same function is also part of the ldc command.
*
* Author: Keith Muller
* University Of California, San Diego
* Academic Computer Center C - 010
* La Jolla, Ca 92093
* ucbvax!sdcsvax!sdcc3!muller
* (619) 452-6090
*-------------------------------------------------------------------------
*/
/* $Log$ */
#include "../h/control.h"
#include <stdio.h>
/*-------------------------------------------------------------------------
* main
*
*-------------------------------------------------------------------------
*/
main(argc, argv)
int argc;
char *argv[];
{
if (argc < 2){
printf("useage: ldrm [pids] [-u users]\n");
exit(1);
}
if (strncmp(argv[1], "-u", 2) == 0){
/*
* remove all jobs by user (-u option)
*/
if (argc < 3){
printf("No user name.\n");
printf("Usage: ldrm [pids] [-u users]\n");
return;
}
}
/*
* set up the necessary overhead
*/
setup();
/*
* call the delete routine
*/
delete(argc, argv);
/*
* clean up the sockets
*/
quit();
}
/*-------------------------------------------------------------------------
* onint
*
* when an interrupt occurs jump here!
*-------------------------------------------------------------------------
*/
onint()
{
printf("\n....interrupted\n");
quit();
}
/*-------------------------------------------------------------------------
* quit
*
*-------------------------------------------------------------------------
*/
quit()
{
extern int sock;
extern char path[];
(void)close(sock);
(void)unlink(path);
exit(0);
}
@//E*O*F control/ldrmmain.c//
chmod u=r,g=r,o=r control/ldrmmain.c
echo x - control/list.c
sed 's/^@//' > "control/list.c" <<'@//E*O*F control/list.c//'
/*-----------------------------------------------------------------------
* list.c - control program
*
* this file contains the commands: longlist and list which are common
* to both ldc and ldq.
*-----------------------------------------------------------------------
*/
/* $Log$ */
#include "../h/common.h"
#include "../h/control.h"
#include <sys/time.h>
#include <stdio.h>
#include <pwd.h>
struct hashbuck names[HASHMOD];
/*----------------------------------------------------------------------------
* getuname
*
* keep a local hash table of recently requested uids. Speeds up the list
* commands when repeatively invoked by ldc. This is done because looking
* up passwd entries are expensive. So expensive that it SHOULD NEVER be
* done by the server. The server NEVER SHOULD look up passwd entries. This
* routine helps unhashed (generic 4.2) passwd files greatly. It is even
* worthwhile on newer dbm passwd file.
*-----------------------------------------------------------------------------
*/
static char *
getuname(huid)
register int huid;
{
register struct hashbuck *hashptr;
register struct passwd *pwd;
extern struct passwd *getpwuid();
extern char *strncpy();
/*
* hash and find the address of the bucket
*/
hashptr = &(names[huid % HASHMOD]);
/*
* if this is the user return the name
*/
if ((hashptr->buckuid == huid) && (hashptr->buckname[0] != '\0'))
return(hashptr->buckname);
/*
* not the same user (or empty) so update this bucket.
* collisions should be rare if the hashtable is of reasonable
* size reletive to the size of the passwd file.
*/
if ((pwd = getpwuid(huid)) != (struct passwd *)NULL){
hashptr->buckuid = huid;
(void)strncpy(hashptr->buckname, pwd->pw_name, PNAMSIZ);
return(hashptr->buckname);
}
/*
* bad uid, skip it
*/
return((char *)0);
}
/*----------------------------------------------------------------------------
* longlist
*
* tell the server to update the list of queued jobs in the list file. When
* the server says the list is updated, show ALL the queued jobs to the user
*-----------------------------------------------------------------------------
*/
longlist(argc, argv)
int argc;
char **argv;
{
int juid;
u_long jpid;
u_long jtime;
int pos;
int qcount;
char *jname;
char jcom[COMLEN];
struct timezone zone;
struct timeval now;
extern FILE *out;
extern int gettimeofday();
extern int fclose();
FILE *fopen();
extern struct request job;
if (argc != 1){
printf("Usage: longlist\n");
return;
}
job.type = LISTCMD;
/*
* only try to print the list if the server says all is ok!
*/
if (sendcntrl() < 0)
return;
if ((out = fopen(LISTFILE, "r")) == NULL){
printf("cannot open listfile file\n");
return;
}
/*
* first entry in the queue is the qcount. if it is zero just say so
*/
if (fscanf(out,"%d",&qcount) != 1){
printf("No queue info available\n");
(void)fclose(out);
out = NULL;
return;
}
if (qcount < 1){
printf("Queue empty\n");
(void)fclose(out);
out = NULL;
return;
}
/*
* at least one job is in the queue.
*/
printf(" rank\t pid\t user\t time(sec) commands\n");
printf("-------------------------------------------------------\n");
pos = 1;
(void)gettimeofday(&now, &zone);
while(fscanf(out,"%d %ld %ld %[^\n]",&juid,&jpid,&jtime,jcom) == 4){
printf(" %3d\t",pos++);
printf(" %5u\t",jpid);
if ((jname = getuname(juid)) != (char *)0)
printf(" %-8.8s",jname);
else
printf(" %-8.8d",juid);
printf(" %5ld",now.tv_sec - (long)jtime);
printf(" %s\n",jcom);
}
/*
* if eof is not set, file has an error
*/
if (feof(out) == 0)
printf("Error in list file\n");
(void)fclose(out);
out = NULL;
}
/*----------------------------------------------------------------------------
* list
*
* tell the server to update the list of queued jobs in the list file. When
* the server says the list is updated, show ONLY this users jobs.
*-----------------------------------------------------------------------------
*/
list(argc, argv)
int argc;
char **argv;
{
int juid;
int cmpuid;
u_long jpid;
u_long jtime;
int pos;
int qcount;
char *jname;
char jcom[COMLEN];
int found;
struct passwd *pwd;
struct timezone zone;
struct timeval now;
extern int uid;
extern FILE *out;
extern struct passwd *getpwnam();
extern int gettimeofday();
extern int fclose();
FILE *fopen();
extern struct request job;
if (argc > 2){
printf("Usage: list [user]\n");
return;
}
if (argc == 2){
/*
* if a user is specified, look him up in the passwd file
*/
if ((pwd = getpwnam(argv[1])) == (struct passwd *)NULL){
printf("No such user: %s\n", argv[1]);
(void)endpwent();
return;
}
cmpuid = pwd->pw_uid;
jname = pwd->pw_name;
(void)endpwent();
}else{
/*
* no user specified, use the current users uid
*/
cmpuid = uid;
if ((jname = getuname(uid)) == (char *)0){
printf("Cannot find you in the passwd file\n");
return;
}
}
job.type = LISTCMD;
/*
* only try to print the list if the server says all is ok!
*/
if (sendcntrl() < 0)
return;
if ((out = fopen(LISTFILE, "r")) == NULL){
printf("cannot open listfile file\n");
return;
}
/*
* first entry in the queue is the qcount. if it is zero just say so
*/
if (fscanf(out,"%d",&qcount) != 1){
printf("No queue info available\n");
(void)fclose(out);
out = NULL;
return;
}
if (qcount < 1){
printf("Queue empty\n");
(void)fclose(out);
out = NULL;
return;
}
/*
* at least one job is in the queue. Look for a job owned by the
* specific user.
*/
found = 0;
pos = 0;
while(fscanf(out,"%d %ld %ld %[^\n]",&juid,&jpid,&jtime,jcom) == 4){
pos++;
if (cmpuid == juid){
/*
* found a job owned by the user
*/
found = 1;
break;
}
}
if (found == 0){
/*
* no jobs found, either an error or no jobs for that user
* is in the queue.
*/
if (feof(out) == 0){
printf("Error in list file\n");
}else{
printf("No jobs in queue for: %s\n", jname);
}
(void)fclose(out);
out = NULL;
return;
}
(void)gettimeofday(&now, &zone);
printf(" rank\t pid\t user\t time(sec) commands\n");
printf("-------------------------------------------------------\n");
printf(" %3d\t %5u\t %-8.8s",pos++, jpid, jname);
printf(" %5ld",now.tv_sec - (long)jtime);
printf(" %s\n",jcom);
while(fscanf(out,"%d %ld %ld %[^\n]",&juid,&jpid,&jtime,jcom) == 4){
/*
* only print this users jobs
*/
if (cmpuid != juid){
pos++;
continue;
}
printf(" %3d\t %5u\t %-8.8s",pos++, jpid, jname);
printf(" %5ld",now.tv_sec - (long)jtime);
printf(" %s\n",jcom);
}
if (feof(out) == 0)
printf("Error in list file\n");
(void)fclose(out);
out = NULL;
}
@//E*O*F control/list.c//
chmod u=r,g=r,o=r control/list.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 <<\!!!
66 365 2506 ldccmdtab.c
373 968 7150 ldcmain.c
88 195 1754 ldqmain.c
87 185 1736 ldrmmain.c
297 910 6776 list.c
911 2623 19922 total
!!!
wc control/ldccmdtab.c control/ldcmain.c control/ldqmain.c control/ldrmmain.c control/list.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