load control (2 of 8)

Keith Muller muller at sdcc3.UUCP
Tue Feb 12 05:45:50 AEST 1985


This is a shar file of the second part of eight shar files for the load control
system as described in net.unix-wizards.
NOTE: 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:44:50 PST 1985
# Contents:  client/Makefile client/main.c scripts/addldd scripts/makedirs
#	scripts/qaddldd scripts/rmldd scripts/saddldd
 
echo x - client/Makefile
sed 's/^@//' > "client/Makefile" <<'@//E*O*F client/Makefile//'
#
# Makefile for batch client
#

CFLAGS= -O

HDR=	../h/common.h ../h/client.h

SRC=	main.c

DEST1=	/bin
TARG1=	binclient
TARG1Q=	qbinclient
DEST2=	/usr/bin
TARG2=	usrbinclient
TARG2Q=	qusrbinclient
DEST3=	/usr/local
TARG3=	usrlocclient
TARG3Q=	qusrlocclient
DEST4=	/usr/ucb
TARG4=	usrucbclient
TARG4Q=	qusrucbclient
DEST5=	/usr/games
TARG5=	gamesclient
TARG5Q=	qgamesclient
DEST6=	/usr/new
TARG6=	usrnewclient
TARG6Q=	qusrnewclient
#
#the spec macros have the name of the program
#SPEC1=	test
#DESTSPEC1= /tmp

all:	$(TARG1) $(TARG1Q) $(TARG2) $(TARG2Q) $(TARG3) $(TARG3Q) $(TARG4) \
	$(TARG4Q) $(TARG5) $(TARG5Q) $(TARG6) $(TARG6Q)

clean:
	rm -f core *client 

lint:
	lint -abchx  main.c

install: $(DEST1)/.client $(DEST1)/.qclient \
	 $(DEST2)/.client $(DEST2)/.qclient \
	 $(DEST3)/.client $(DEST3)/.qclient \
	 $(DEST4)/.client $(DEST4)/.qclient \
	 $(DEST5)/.client $(DEST5)/.qclient
#	 $(DEST5)/.client $(DEST5)/.qclient \
#	 $(DEST6)/.client $(DEST6)/.qclient 
####################################################################
#	 Have the two commented lines replace the last line of the
#	 dependency list if your machine has /usr/new.
#
#        The following line is a sample for $(SPEC1) which would
#	 have to be added into the install dependency for each
#	 SPEC defined.
#        $(DESTSPEC1)/.$(SPEC1)client
####################################################################

####################################################################
# $(SPEC1) is a sample of a special client for controlling
# a single binary (like pi)
# NOARGV should be the full path name of where the real binary is
# is store (usually a .code directory)
####################################################################

$(SPEC1)client: main.c $(HDR)
	cc $(CFLAGS) -DNOARGV=\"$(DESTSPEC1)/.code/$(SPEC1)\" main.c -o $(SPEC1)client

$(DESTSPEC1)/.$(SPEC1)client: $(SPEC1)client
	install -c -m 4711 -o root $(SPEC1)client $(DESTSPEC1)/.$(SPEC1)client

####################################################################

$(TARG1): main.c $(HDR)
	cc $(CFLAGS) -DCODEPATH=\"$(DEST1)/.code/\" main.c -o $(TARG1)

$(TARG1Q): main.c $(HDR)
	cc $(CFLAGS) -DCODEPATH=\"$(DEST1)/.code/\" -DQUIET main.c -o $(TARG1Q)

$(TARG2): main.c $(HDR)
	cc $(CFLAGS) -DCODEPATH=\"$(DEST2)/.code/\" main.c -o $(TARG2)

$(TARG2Q): main.c $(HDR)
	cc $(CFLAGS) -DCODEPATH=\"$(DEST2)/.code/\" -DQUIET main.c -o $(TARG2Q)

$(TARG3): main.c $(HDR)
	cc $(CFLAGS) -DCODEPATH=\"$(DEST3)/.code/\" main.c -o $(TARG3)

$(TARG3Q): main.c $(HDR)
	cc $(CFLAGS) -DCODEPATH=\"$(DEST3)/.code/\" -DQUIET main.c -o $(TARG3Q)

$(TARG4): main.c $(HDR)
	cc $(CFLAGS) -DCODEPATH=\"$(DEST4)/.code/\" main.c -o $(TARG4)

$(TARG4Q): main.c $(HDR)
	cc $(CFLAGS) -DCODEPATH=\"$(DEST4)/.code/\" -DQUIET main.c -o $(TARG4Q)

$(TARG5): main.c $(HDR)
	cc $(CFLAGS) -DCODEPATH=\"$(DEST5)/.code/\" main.c -o $(TARG5)

$(TARG5Q): main.c $(HDR)
	cc $(CFLAGS) -DCODEPATH=\"$(DEST5)/.code/\" -DQUIET main.c -o $(TARG5Q)

$(TARG6): main.c $(HDR)
	cc $(CFLAGS) -DCODEPATH=\"$(DEST6)/.code/\" main.c -o $(TARG6)

$(TARG6Q): main.c $(HDR)
	cc $(CFLAGS) -DCODEPATH=\"$(DEST6)/.code/\" -DQUIET main.c -o $(TARG6Q)

$(DEST1)/.client: $(TARG1)
	install -c -m 4711 -o root $(TARG1) $(DEST1)/.client

$(DEST1)/.qclient: $(TARG1Q)
	install -c -m 4711 -o root $(TARG1Q) $(DEST1)/.qclient

$(DEST2)/.client: $(TARG2)
	install -c -m 4711 -o root $(TARG2) $(DEST2)/.client

$(DEST2)/.qclient: $(TARG2Q)
	install -c -m 4711 -o root $(TARG2Q) $(DEST2)/.qclient

$(DEST3)/.client: $(TARG3)
	install -c -m 4711 -o root $(TARG3) $(DEST3)/.client

$(DEST3)/.qclient: $(TARG3Q)
	install -c -m 4711 -o root $(TARG3Q) $(DEST3)/.qclient

$(DEST4)/.client: $(TARG4)
	install -c -m 4711 -o root $(TARG4) $(DEST4)/.client

$(DEST4)/.qclient: $(TARG4Q)
	install -c -m 4711 -o root $(TARG4Q) $(DEST4)/.qclient

$(DEST5)/.client: $(TARG5)
	install -c -m 4711 -o root $(TARG5) $(DEST5)/.client

$(DEST5)/.qclient: $(TARG5Q)
	install -c -m 4711 -o root $(TARG5Q) $(DEST5)/.qclient

$(DEST6)/.client: $(TARG6)
	install -c -m 4711 -o root $(TARG6) $(DEST6)/.client

$(DEST6)/.qclient: $(TARG6Q)
	install -c -m 4711 -o root $(TARG6Q) $(DEST6)/.qclient

####################################################################
# tmpclient is used for testing the ldc system with a /tmp/.code
# directory. This is not normally used.
####################################################################

tmpclient: main.c $(HDR)
	cc $(CFLAGS) -DCODEPATH=\"/tmp/.code/\" main.c -o tmpclient
	install -c -m 4711 -o root tmpclient /tmp/.client
@//E*O*F client/Makefile//
chmod u=r,g=r,o=r client/Makefile
 
echo x - client/main.c
sed 's/^@//' > "client/main.c" <<'@//E*O*F client/main.c//'

/*--------------------------------------------------------------------------
 * main.c - client
 *
 * Front end program that communicates with the ldd server. This front
 * end replaces the program to be controlled. The controlled binary is
 * hidden in a directory that is only accessable through group privledges.
 * Only one client executable is needed for each protected binary directory.
 * The real name of the program to be executed is extracted from argv[0]
 * unless NOARGV is defined. When defined, NOARGV has the name of the program
 * to be exec'ed wired in. The NOARGV option is necessary for programs like
 * pi and px which use argv[0] to pass data to them (YUCK!!!) when they are
 * called from pix. Usually all the front ends can just be links (hard or soft)
 * to the same code file.
 * The QUIET option allows suppression of the client status messages (this
 * is good for nroff). The ONETIME option exempts all child processes from
 * being queued once the parent process has passed through load control
 * once. (Good for queueing individual passes of a compiler, make, etc).
 * If for any reason the server is dead or not responding, this program will
 * simply exec the proper code file. This allows the load control system to
 * be quickly disabled by killing off the ldd server program. 
 * The front end checks every QUEUETIME seconds to see if the server is
 * still running and has this process queued up. If this poll fails the
 * control program is exec'ed. This protects against the system locking up due
 * to server death. The system WILL NOT be overloaded from a rash of executing
 * jobs as each job will expire relative to the time it was queued (which will
 * be spread out over time).
 *
 * 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/client.h"
#include <sys/uio.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/time.h>
#include <stdio.h>
#include <signal.h>
#include <errno.h>

int queued = 0;				 /* 1 if queued */
int msgsock = -1;			 /* desciptor of socket */
int len = 0;				 /* used to store address len */
char *ptr;				 /* ptr for pulling apart argv[0] */
char clientpath[255];			 /* buffer for socket name */
char binary[255];			 /* buffer for real binary's path */
struct request job;			 /* datagram for the server */
struct sockaddr_un name;		 /* socket address of server */
struct timeval polltime = {WAITTIME, 0}; /* waitime to check server */
extern int onint();			 /* interrupt handler */

/*-----------------------------------------------------------------------
 * main
 *
 *-----------------------------------------------------------------------
 */
main(argc, argv, envp)
int argc;
char **argv, **envp;
{
	register int i;			/* general counter */
	int msgmask;			/* mask for select */
	int readfds;			/* mask for desc to select on */
	int numfds;			/* number of desc select ret */
	int egid;			/* effective group id */
	int rgid;			/* real group id */
	int uid;			/* real user id */
	int pollcount;			/* number of polls to server */
	int descsize;			/* size of desc table */
	int sigmask;			/* signal mask before block */
	char msg;			/* answer from server */
	struct timeval now;		/* time (secs) value */
	struct timezone zone;		/* timezone value (unused) */
	int fromlen = 0;
#ifndef QUIET
	int announce;			/* limits "queued" messages */
	char *eptr;
	extern char *getenv();
	extern int strcmp();
#endif QUIET
	extern char *strcpy();
	extern char *strncpy();
	extern char *strcat();
	extern int getpid();
	extern int getegid();
	extern int getgid();
	extern int getuid();
	extern int sigblock();
	extern int sigsetmask();
	extern int errno;
	extern char *sprintf();
	extern char *rindex();

	/*
	 * the client front end runs ONLY setuid to root. so get real user
	 * and both effective and real gids.
	 */
	egid = getegid();
	rgid = getgid();
	uid = getuid();

	/*
	 * set the users real and effective uid (no limits on root). also set
	 * the group id to LDDGID so a socket can be bound in the spool
	 * directory and a datagram can be sent to the server. (the spool
	 * directory MUST BE in group LDDGID and mode 0730 only!
	 * NO OTHER PRIVLEDGES AT ALL!!!!!)
	 */
	(void)setregid(rgid, LDDGID);
	(void)setreuid(uid, uid);

	/*
	 * If NOARGV is defined, then this is a special client which
	 * will only exec a SINGLE program. This is to get around things
	 * like pi which can use argv[0] to pass data. Otherwise we must
	 * find the base name of the requested program. Since argv[0]
	 * can be a long ugly path name, ugly looking code is needed
	 * to strip off the path.
	 */
#ifdef NOARGV
	/*
	 * NOARGV is set in the makefile to have the FULL path of where the
	 * real binary lives: for example /usr/bin/.code/yuck
	 */
	(void)strcpy(binary, NOARGV);
	if ((ptr = rindex(binary, '/')) == (char *)0)
		ptr = binary;
	else
		ptr++;
#else
	/*
	 * must pull the path out of the argv[0]
	 */
	if ((ptr = rindex(argv[0], '/')) == (char *)0)
		ptr = argv[0];
	else
		ptr++;
	(void)sprintf(binary, "%s%s", CODEPATH, ptr);
#endif
	/*
	 * If ONETIME is defined, then all child processes of this job are
	 * EXEMPT from being queued. This is useful for things like pi which
	 * can be called both by a user and from pix.
	 * This works because if the effective gid of the process
	 * is the group LDDGID this process must be a decendent of a process
	 * that has already passed through the load control system. This
	 * mechanism will work only if this program is setuid and IS NOT
	 * setgid.
	 *
	 * root is always exempt!
	 *
	 * NOTE: ptr will be used later to build up the command line buffer
	 * in the datagram request packet sent to the server.
	 */

#ifdef ONETIME
	if ((egid == LDDGID) || (uid == 0))
		run(argv, envp);
#else
	if (uid == 0)
		run(argv, envp);
#endif ONETIME

	/*
	 * create the socket and the datagram. if anything fails
	 * just run. cannot afford to have this process HANG!
	 */
	msgsock = socket(AF_UNIX, SOCK_DGRAM, 0);
	if (msgsock < 0)
		run(argv, envp);

	/*
	 * bind the handler to clean up
	 */
	(void)signal(SIGINT, onint);
	(void)signal(SIGHUP, onint);
	(void)signal(SIGQUIT, onint);
	(void)signal(SIGTERM, onint);

	/*
	 * make the datagram up
	 */
	job.pid = (u_long)getpid();
	(void)sprintf(clientpath,"%s/%s%u",SPOOLDIR,CLIENTPRE,job.pid);
	(void)strcpy(name.sun_path, clientpath);
	name.sun_family = AF_UNIX;
	len = strlen(name.sun_path) + 1 + sizeof(name.sun_family);

	/*
	 * block off interrupt and control z until we get datagram
	 * sent
	 */
	sigmask = sigblock((1<<(SIGINT-1)) | (1<<(SIGTSTP-1)) | (1<<(SIGHUP-1)) |
			   (1<<(SIGQUIT-1)) | (1<<(SIGTERM-1)));

	/*
	 * bind the socket, if it fails just run
	 */
	(void)unlink(name.sun_path);

	if (bind(msgsock, &name, len) < 0){
		(void)sigsetmask(sigmask);
		run(argv, envp);
	}

	/*
	 * build up the command line that will be displayed in the
	 * when the user interrogates the queue. This helps in identifying
	 * which job is which.
	 */
	(void)strncpy(job.com, ptr, COMLEN - 1);
	i = 1;
	len = strlen(job.com) + 1;
	while((i < argc) && ((len = len + strlen(argv[i]) + 1) <= COMLEN)){
		(void)strcat(job.com, " ");
		(void)strcat(job.com, argv[i]);
		i++;
	}

	/*
	 * put the path name of the servers datagram in the sockaddr struct
	 */
	(void)strcpy(name.sun_path, MSGPATH);
	len = strlen(name.sun_path) + 1 + sizeof(name.sun_family);

	/*
	 * time stamp the datagram, and place my pid in it (identfies the name
	 * of this clients bound socket
	 */
	if (gettimeofday(&now, &zone) < 0)
		run(argv, envp);
	job.time = now.tv_sec;
	job.type = QCMD;
	job.uid = (u_long)uid;

	/*
	 * send the request to the server
	 */
	if (sendto(msgsock, &job, sizeof(struct request), 0, &name, len) < 0){
		(void)sigsetmask(sigmask);
		run(argv, envp);
	}

	descsize = getdtablesize();
	msgmask = 1 << msgsock;
	pollcount = 0;

	/*
	 * unblock the signals
	 */
	 (void)sigsetmask(sigmask);

#ifndef QUIET
	/*
	 * set announce to 0 to get at least one status message
	 * if user has ENVNAME = quiet in his environment, no messages!
	 */
	if (((eptr=getenv(ENVNAME))==(char *)0)||(strcmp(eptr,"quiet")!=0))
		announce = 0;
	else
		announce = -1;
#endif QUIET

	/*
	 * wait for the word from the server!
	 */
	for(;;){
		readfds = msgmask;
		numfds = select(descsize,&readfds,(int *)0,(int *)0,&polltime);

		/*
		 * if there is a screwup here just run
		 */
		if (((numfds<0)&&(errno!=EINTR))||((numfds<=0)&&(pollcount>MAXPOLLS))){
#ifndef QUIET
			if (announce == 1)
				fprintf(stderr,"running\n");
#endif QUIET
			run(argv, envp);
		}
		
		/*
		 * we waitied polltime seconds and no word from the server
		 * so send the datagram again in case the system lost it
		 * OR else we got a garbage answer!
		 */
		if ((numfds<=0)||(recvfrom(msgsock,&msg,sizeof(msg),0,(struct sockaddr *)0,&fromlen)<=0)){
			pollcount++;
			/*
			 * oh server where are you?
			 */
			if (sendto(msgsock,&job,sizeof(struct request),0,&name,len)<0){
#ifndef QUIET
				if (announce == 1)
					fprintf(stderr,"running\n");
#endif QUIET
				run(argv, envp);
			}else{
				/*
				 * the datagram was sent so switch to WAITTIME
				 * for an answer. WAITTIME is much shorter
				 * than QUEUETIME as we want to be queued.
				 */
				polltime.tv_sec = WAITTIME;
				continue;
			}
		}

		/*
		 * we got the word see what to do
		 */
		switch(msg){
			case RUNCMD:
				/*
				 * we can run
				 */
#ifndef QUIET
			 	if (announce == 1)
					fprintf(stderr,"running\n");
#endif QUIET
				run(argv, envp);
				break;
			case STOPCMD:
				/*
				 * bye bye
				 */
#ifndef QUIET
			 	if (announce == 1)
					fprintf(stderr,"stopped\n");
#endif QUIET
				(void)close(msgsock);
				(void)unlink(clientpath);
				exit(1);
			case QCMD:
				/*
				 * we have been queued 
				 * switch to QUEUETIME so to check later
				 * that the server is still around (so we
				 * don't wait forever!
				 * Switch to POLLCMD so that the server knows
				 * we have been in the queue at least once.
				 */
				polltime.tv_sec = QUEUETIME;
				queued = 1;
				pollcount = 0;
				job.type = POLLCMD;
#ifndef QUIET
				/*
				 * tell user he is being queued
				 */
				if (announce == 0){
					fprintf(stderr,"Queued, waiting to run....");
					announce = 1;
				}
#endif QUIET
				break;
			case FULLQUEUE:
				/*
				 * The queue is full, this job cannot be
				 * accepted. This prevents the system
				 * from running out of slots in the
				 * process table.
				 */
			 	fprintf(stderr,"Cannot run, the system is overloaded. Try again later.\n");
				(void)close(msgsock);
				(void)unlink(clientpath);
				exit(1);
			case POLLCMD:
				/*
				 * server wants the data again
				 * The only way we can get this is from
				 * a new server during startup.
				 * So reset the datagram to a QCMD.
				 * (fall through to default below),
				 */
				job.type = QCMD;
			default:
				/*
				 * or got garbage
				 */
				if (sendto(msgsock,&job,sizeof(struct request),0,&name,len)<0){
#ifndef QUIET
			 		if (announce == 1)
						fprintf(stderr,"running\n");
#endif QUIET
					run(argv, envp);
				}

				/*
				 * switch back to WAITTIME to be a pest until
				 * we get queued
				 */
				polltime.tv_sec = WAITTIME;
				queued = 0;
				pollcount = 0;
				break;
		}
	}
}

/*-----------------------------------------------------------------------------
 * onint
 *
 * what to do when the user wants out
 *-----------------------------------------------------------------------------
 */
onint()
{

	/*
	 * if we are already queued say goodbye to the server
	 */
	if (queued == 1){
		/*
		 * Send a message to the server we are quitting so the server
		 * can remove us from the queue.
		 */
		job.type = PJOBCMD;
		job.time = job.pid;
		(void)sendto(msgsock,&job,sizeof(struct request),0,&name,len);
	}
	(void)close(msgsock);
	(void)unlink(clientpath);
	exit(0);
}

/*-----------------------------------------------------------------------------
 * run
 *
 * routine that execs the real program after getting the ok 
 *-----------------------------------------------------------------------------
 */

run(argv, envp)
char **argv, **envp;
{
	extern int msgsock;
	extern char binary[];
	extern char clientpath[];

	/*
	 * shut down the socket and remove it from the spool
	 */
	if (msgsock != -1)
		(void)close(msgsock);
	(void)unlink(clientpath);

	/*
	 * all is set try to run!
	 * this works because the directory where the REAL code file is
	 * is mode 0730 and the group MUST BE LDDGID!
	 * and we are now running with an effective gid of LDDGID
	 */
	(void)execve(binary, argv, envp);

	/*
	 * from now on something screwed up! print the error and
	 * hope the user reports it!
	 */
	perror(binary);
	exit(0);
}
@//E*O*F client/main.c//
chmod u=r,g=r,o=r client/main.c
 
echo x - scripts/addldd
sed 's/^@//' > "scripts/addldd" <<'@//E*O*F scripts/addldd//'
#! /bin/csh -f
#
# script to add file1 through filen located in directory to the processes
# controlled by the ldd system.
#
# THIS IS FOR COMMANDS THAT SHOULD HAVE STATUS ANNOUNCEMENTS

umask 022
if ($#argv < 2) then
	echo "usage: addldd directory file1 file2 .. filen"
else
	echo "cd $1"
	cd $1
	shift
	while($#argv)
		if (-e .client == 0) then
			echo "there is no .client front end. Do a make install."
			break
		else if (-e .code/$1) then
			echo "$1 is already load controlled"
		else if (-e $1) then
			echo "putting $1 under load control"
			echo "mv $1 .code/$1"
			/bin/mv $1 .code/$1
			echo "ln -s .client $1"
			/bin/ln -s .client $1
		else
			echo "$1 does not exsist"
		endif
		shift
	end
endif
@//E*O*F scripts/addldd//
chmod u=rx,g=rx,o=rx scripts/addldd
 
echo x - scripts/makedirs
sed 's/^@//' > "scripts/makedirs" <<'@//E*O*F scripts/makedirs//'
#! /bin/csh -f
# make all the directories needed by the load control system
# NOTE: lddgrp must be defined as the same group id as in h/client.h
#
echo "making the directories for load control"

foreach i (/bin /usr/bin /usr/local /usr/ucb /usr/new /usr/games)
	if (-e $i && -e $i/.code == 0) then
		echo "mkdir $i/.code"
		/bin/mkdir $i/.code
	endif
	if (-e $i/.code) then
		echo "chown root $i/.code"
		/etc/chown root $i/.code
		echo "chgrp lddgrp $i/.code"
		/bin/chgrp lddgrp $i/.code
		echo "chmod 0710 $i/.code"
		/bin/chmod 0710 $i/.code
	endif
end
#
if (-e /usr/spool/ldd == 0) then
	echo "mkdir /usr/spool/ldd"
	/bin/mkdir /usr/spool/ldd
endif
if (-e /usr/spool/ldd/sr == 0) then
	echo "mkdir /usr/spool/ldd/sr"
	/bin/mkdir /usr/spool/ldd/sr
endif
if (-e /usr/spool/ldd/cl == 0) then
	echo "mkdir /usr/spool/ldd/cl"
	/bin/mkdir /usr/spool/ldd/cl
endif
#
# spool/ldd/cl MUST BE GROUP writeable
# all others should NOT be GROUP writeable
#
echo "chown root /usr/spool/ldd"
/etc/chown root /usr/spool/ldd

echo "chgrp lddgrp /usr/spool/ldd"
/bin/chgrp lddgrp /usr/spool/ldd

echo "chmod 0710 /usr/spool/ldd"
/bin/chmod 0710 /usr/spool/ldd

echo "chown root /usr/spool/ldd/cl"
/etc/chown root /usr/spool/ldd/cl

echo "chgrp lddgrp /usr/spool/ldd/cl"
/bin/chgrp lddgrp /usr/spool/ldd/cl

echo "chmod 0730 /usr/spool/ldd/cl"
/bin/chmod 0730 /usr/spool/ldd/cl

echo "chown root /usr/spool/ldd/sr"
/etc/chown root /usr/spool/ldd/sr

echo "chgrp lddgrp /usr/spool/ldd/sr"
/bin/chgrp lddgrp /usr/spool/ldd/sr

echo "chmod 0710 /usr/spool/ldd/sr"
/bin/chmod 0710 /usr/spool/ldd/sr
@//E*O*F scripts/makedirs//
chmod u=rx,g=rx,o=rx scripts/makedirs
 
echo x - scripts/qaddldd
sed 's/^@//' > "scripts/qaddldd" <<'@//E*O*F scripts/qaddldd//'
#! /bin/csh -f
#
# script to add file1 through filen located in directory to the processes
# controlled by the ldd system.
#
# THIS IS FOR COMMANDS THAT *DO* *NOT* HAVE STATUS ANNOUNCEMENTS

umask 022
if ($#argv < 2) then
	echo "usage: qaddldd directory file1 file2 .. filen"
else
	echo "cd $1"
	cd $1
	shift
	while($#argv)
		if (-e .qclient == 0) then
			echo "there is no .qclient front end. Do a make install."
			break
		else if (-e .code/$1) then
			echo "$1 is already load controlled"
		else if (-e $1) then
			echo "putting $1 under load control (quiet mode)"
			echo "mv $1 .code/$1"
			/bin/mv $1 .code/$1
			echo "ln -s .qclient $1"
			/bin/ln -s .qclient $1
		else
			echo "$1 does not exsist"
		endif
		shift
	end
endif
@//E*O*F scripts/qaddldd//
chmod u=rx,g=rx,o=rx scripts/qaddldd
 
echo x - scripts/rmldd
sed 's/^@//' > "scripts/rmldd" <<'@//E*O*F scripts/rmldd//'
#! /bin/csh -f
#
# script to remove process file1 through filen in directory from the
# load control system. 

umask 022
if ($#argv < 2) then
	echo "usage: rmldd directory file1 file2 .. filen"
else
	echo "cd $1"
	cd $1
	shift
	while($#argv)
		if (-e .code/$1) then
			echo "removing $1 from load control"
			echo "rm $1"
			/bin/rm $1
			echo "mv .code/$1 $1"
			/bin/mv .code/$1 $1
		else
			echo "$1 is not load controlled"
		endif
		shift
	end
endif
@//E*O*F scripts/rmldd//
chmod u=rx,g=rx,o=rx scripts/rmldd
 
echo x - scripts/saddldd
sed 's/^@//' > "scripts/saddldd" <<'@//E*O*F scripts/saddldd//'
#! /bin/csh -f
#
# script to add file file1 as a SPECIAL client in directory directory.
#
# THIS IS FOR COMMANDS THAT REQUIRE SPECIAL PRIVATE CLIENTS

umask 022
if ($#argv != 2) then
	echo "usage: saddldd directory file"
else
	echo "cd $1"
	cd $1
	shift
	if (-e .$1client == 0) then
		echo "there is no .$1client front end. Do a make install."
		break
	else if (-e .code/$1) then
		echo "$1 is already load controlled"
	else if (-e $1) then
		echo "putting $1 under load control (special client)"
		echo "mv $1 .code/$1"
		/bin/mv $1 .code/$1
		echo "ln -s .$1client $1"
		/bin/ln -s .$1client $1
	else
		echo "$1 does not exsist"
	endif
endif
@//E*O*F scripts/saddldd//
chmod u=rx,g=rx,o=rx scripts/saddldd
 
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 <<\!!!
     154     491    4545 Makefile
     471    1929   12916 main.c
      32     123     711 addldd
      63     202    1580 makedirs
      32     126     733 qaddldd
      25      76     454 rmldd
      28     113     644 saddldd
     805    3060   21583 total
!!!
wc  client/Makefile client/main.c scripts/addldd scripts/makedirs scripts/qaddldd scripts/rmldd scripts/saddldd | 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