[alt.sources] Setlock - uucp style lock tool for setting/clearing locks

pda@Dixie.Com (Paul D. Anderson) (03/23/91)

Setlock is a program that can be used by shell scripts to set
and clear System V uucp-style lock files (located in
/usr/spool/locks).

Setlock always reads the lock file, testing to see if the
process indicated  in the lock file is still active, before
performing any indicated action. 

Setlock  exits such that an exit code of '0' always means
"action completed successfully".  Failure exit codes from
setlock are not symmetrical.  Each exit code carries a  specific
meaning corresponding to the action given by a specific switch. 

I would appreciate any feedback regarding portability and 
enhancements.  I hope you find this as useful as I have found
it already, here.

-paul

Submitted-by: pda@Dixie.Com
Archive-name: setlock/part01

---- Cut Here and feed the following to sh ----
#!/bin/sh
# This is setlock, a shell archive (shar 3.43)
# made 03/23/1991 11:28 UTC by pda@Dixie.Com
# Source directory /usr/local/tools/setlock
#
# existing files will NOT be overwritten unless -c is specified
#
# This shar contains:
# length  mode       name
# ------ ---------- ------------------------------------------
#   5692 -r--rw---- setlock.c
#    740 -r--r--r-- makefile
#   1928 -r--r--r-- README
#   4924 -r--r--r-- setlock.1
#   4866 -r--rw---- dotest
#   3521 -rwxrwx--- Hourly
#    614 -rwxrw---- gettyclear
#    778 -r-xrwx--- log
#
# ============= setlock.c ==============
if test -f 'setlock.c' -a X"$1" != X"-c"; then
	echo 'x - skipping setlock.c (File already exists)'
else
echo 'x - extracting setlock.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'setlock.c' &&
X
/* Setlock - test for a lock file and set up a lock.
X	Copyright 1991 Paul D. Anderson, All Rights Reserved Worldwide
X
X	License Agreement:
X	You may use this program for any legal purpose, but you may
X	not sell it.  You may not pretend that you wrote it.
X
*/
X
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <errno.h>
X
X
usage()
{
X	static char *utext[] = {
X
X	"setlock -l lockname -p lockpid [ -f | -s | -r | -t | -R ] [-v]",
#ifndef SHORTHELP
X	"  -l lockname	... name of the lockfile ",
X	"  -p lockpid	... pid to write to lockfile (and to test for)",
X	"  -f		... freshen lock file - touch it with current pid again",
X	"  -s		... set the lock",
X	"  -r		... remove the lock, only if it matches lockpid",
X	"  -R		... remove the lock, iff the lock is invalid,",
X	"			even if it doesn't match lockpid",
X	"  -t		... test to see if the lock is valid",
X	"  -v		... say the exit code to stdout",
X	"",
X	"exit codes:",
X	"  0	... action performed OK",
X	"  1	... unable to set lock (current lockfile valid)",
X	"  2	... did not remove lock (pid passed doesn't match lockfile)",
X	"  3	... unable to freshen lock file, file does not exist",
X	"  4	... unable to freshen lock file, file found but process is dead",
X	"  5	... unable to freshen lock file, lock file not owned by you",
X	"  6	... lock is not valid, process is gone.",
X	"  7	... lock file does not exist",
X	"  8	... pid specified on command line is not active",
X	"  9	... unable to remove lock file not owned by you, still active",
X	"  50	... unable to perform action, other error occurred",
X	"",
X	"  100	... program exited due to error"
#else
X	""
#endif
X	};
X
X	int i;
X
X	for (i=0; i<sizeof utext/sizeof (char *); ++i) 
X		puts(utext[i]);
}
X
#ifndef LCKPATH
#define LCKPATH "/usr/spool/locks"
#endif
X
static char sccsid[] = { "@(#) setlock.c 1.5 91/03/19  20:43:23" };
X
extern int errno;
X
int vflg = 0;
X
main(ac,av)
int ac;
char *av[];
{
X	int c, lockpid, pid=0, fflg=0,sflg=0,rflg=0,tflg=0,errflg=0;
X	int Rflg=0;
X	char *cp, *lockname=0, buf[128], path[128];
X	extern char *optarg;
X
X	while ((c=getopt(ac,av,"l:p:ftsrvR"))!= -1) {
X	switch (c) {
X	case 'l':	lockname=optarg;		break;
X	case 'p':	pid=atoi(optarg);		break;
X	case 'f':	++fflg;					break;
X	case 't':	++tflg;					break;
X	case 's':	++sflg;					break;
X	case 'r':	++rflg;					break;
X	case 'R':	++Rflg;					break;
X	case 'v':	++vflg;					break;
X	case '?':	errflg++;	break;
X	}}
X
X	if (
X		(errflg || Rflg+tflg+fflg+sflg+rflg > 1 || !lockname)
X		|| ( !(Rflg || tflg ) && !pid )
X		|| ( ( Rflg || tflg ) && pid ) 
X	) {
X		usage();
X		die(100);
X	}
X
X	/* make sure the given pid is for real */
X	if ( pid && ! testpid(pid) ) die(8);
X
X	/* if there is a slash in the lockname, then assume a path
X	has been specified, as this dude may want a lock in a directory
X	other than /usr/spool/locks... */
X
X	if (strchr(lockname,'/')) { strcpy(path,lockname); }
X	else sprintf(path,"%s/%s",LCKPATH, lockname);
X
X	/* test for a valid lockfile */
X	if (tflg) {
X		switch (lockpid=valid(path)) {
X		case -1:	die(7);		/* lock file not found */
X		case 0:		die(6);		/* lock found, lock inactive */
X		default:	die(0);		/* process is still active */
X		}
X	}
X
X	/* remove the lock file */
X	if (rflg || Rflg ) {
X		switch(lockpid=valid(path)) {
X		case -1:	die(0);		/* lock file not there, so exit ok */
X		case 0:					/* lock there, but inactive, so rm it */
X				unlink(path);
X				die(0);
X		default:
X				/* lock is there and active */
X				if (Rflg) die(9);
X				/* rflg - rmove the lock iff its ours.  */
X				if ( rflg && pid == lockpid ) {
X					unlink(path);
X					die(0);
X				} else {
X					die(2);	/* pid in lock file doesn't match our pid */
X				}
X		}
X	}
X
X	/* set a lock file */
X	if (sflg) {
X		switch(lockpid=valid(path)) {
X		case -1:	/* lock file not found */
X		case 0:		/* lock found but process dead */
X				if (set(path,pid)) die(0);		/* write the lock file */
X				else die(50);
X		default:
X				die(1);		/* lock is valid, can't set one */
X		}
X	}
X
X	/* freshen the lock file */
X	if (fflg) { 
X		switch(lockpid=valid(path)) {
X		case -1:	/* lock file not found */
X				die(3);
X		case 0:		/* lock found but process dead */
X				die(4);
X		default:	/* lock is valid, can't set one */
X				if ( lockpid != pid ) die(5);		/* not owned by me */
X				else if ( freshen(path,pid) ) die(0);
X				else die(50);
X		}
X	}
X
X	die(100);
}
X
/* returns -1 if lock file is not found.
X		0 if there is a lock file, but process is dead and
X		'pid' of process if process is still active */
X
valid(path)
char *path;
{
X	FILE *fp;
X	char buf[20];
X	int pid, rc, saveerrno;
X
X	/* try to get the lock pid - if we can't open the file, then
X	presume the lock is invalid.  So return a 1 to say that the
X	process is dead.  (a non-readable lock file is incorrectly
X	formed and we needn't try any further error recovery) */
X
X	if ( access(path,0) ) return -1;
X	if ( (fp=fopen(path,"r")) == (FILE *)0 ) return -1;
X
X	fgets(buf,sizeof buf,fp);
X	fclose(fp);
X
X	return testpid(atoi(buf));
}
X
testpid(pid)
{
X	int rc;
X
X	rc = kill(pid,0);
X
X	/* we should return 1 if the process is active */
X	switch(rc) {
X	case 0:		/* it's our process and must be alive, so return ok */
X			return pid;
X	default:	/* it's someone else's process or doesn't exist... */
X		switch(errno) {
X		case ESRCH:	/* process doesn't exist */
X			return 0;	
X		default:	/* something else happened, but process is alive */
X			return pid;
X		}
X	}
}
X
set(path,pid)
char *path;
{
X	FILE *fp;
X
X	if ( (fp=fopen(path,"w")) == (FILE *) 0) return 0;
X
X	fprintf(fp,"%10ld\n",(long)pid);
X	fclose(fp);
X	return 1;
}
X
freshen(path,pid)
char *path;
{
X	FILE *fp;
X
X	if ( (fp=fopen(path,"r+")) == (FILE *) 0) return 0;
X
X	fprintf(fp,"%10ld\n",(long)pid);
X	fclose(fp);
X	return 1;
}
X
die(code)
{
X	if (vflg) printf("%d\n",code);
X	exit(code);
}
SHAR_EOF
chmod 0460 setlock.c ||
echo 'restore of setlock.c failed'
Wc_c="`wc -c < 'setlock.c'`"
test 5692 -eq "$Wc_c" ||
	echo 'setlock.c: original size 5692, current size' "$Wc_c"
fi
# ============= makefile ==============
if test -f 'makefile' -a X"$1" != X"-c"; then
	echo 'x - skipping makefile (File already exists)'
else
echo 'x - extracting makefile (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'makefile' &&
X
# Makefile for setlock
# @(#) makefile 1.3
X
# Set where section 1 man pages go
MAN1DIR=/usr/local/man/man1
# Set where the binary goes
BINDIR=/usr/local/bin
#
CFLAGS=	-O -DLCKPATH=\"/usr/spool/locks\"
X
# If using shared libs on ISC SysV, then c_s *must* be at the end of the line.
LIBS= -lc_s
X
all: setlock
X
setlock:	setlock.c
X	cc -o setlock $(CFLAGS) setlock.c $(LIBS)
X
clean:
X	rm setlock
X
strip:
X	strip setlock
X	mcs -d setlock
X
install:
X	cp setlock $(BINDIR)
X	cd $(BINDIR); chmod 555 setlock; chown bin setlock; chgrp sys setlock
X	cp setlock.1 $(MAN1DIR)
X	cd $(MAN1DIR); chmod 444 setlock.1; chown bin setlock.1; chgrp sys setlock.1
X
shar:
X	shar -c -a -nsetlock -osetlock setlock.c makefile README setlock.1 dotest Hourly gettyclear log
SHAR_EOF
chmod 0444 makefile ||
echo 'restore of makefile failed'
Wc_c="`wc -c < 'makefile'`"
test 740 -eq "$Wc_c" ||
	echo 'makefile: original size 740, current size' "$Wc_c"
fi
# ============= README ==============
if test -f 'README' -a X"$1" != X"-c"; then
	echo 'x - skipping README (File already exists)'
else
echo 'x - extracting README (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'README' &&
X
Mon Mar 18 18:22:27 EST 1991
@(#) README 1.2 
X
To build setlock, define in the makefile in what directory your
lock files are located and type make.  
X
When done, test setlock using the 'dotest' script.  It will
attempt to put setlock through all of its paces creating locks
in  /usr/spool/locks, in the local directory and in a remote
directory. It'll even try to create a lock file in /usr/lib (so
don't be root when you run it!).  If it succeeds, then setlock
will probably  work ok on your system, although I could have
made the test probably 3 times larger for a complete test. 
X
Dotest will report 'passed' or 'FAILED' on your screen.  It's
up to you to figure out why the test failed.  I've put some
diagnostic printouts in to help in the trace.
X
I have enclosed 3 scripts that we use here on our system that
give an example of how I use setlock to enhance news processing,
recover gettys on the dialin ports and share a common log file.
X
'Hourly' runs various jobs for news processing, including
compress and news' expire(8).  By running those programs in
sequential fashion we don't become IO  or Memory bound.   The
script is run every 15 minutes by crontab, but to do so without
having 10 copies running simultaneously, I had to use a lock
indicating the script was already running (since many jobs run 
longer than 15 minutes). The first thing Hourly always does is
to set a number of flags to indicate that specific processing is
needed. Hourly then checks (via setlock) to see if it is already
running.  If so, it exits.  If not, the lockfile is set and
Hourly does its processing.   
X
The 'gettyclear' script resets ports on our machine.  Gettyclear
uses the '-R' option of setlock to remove a lock file that
doesn't belong to the process iff the process associated with
that lock file is dead. 
X
The 'log' script allows us to write to a common logfile with 
vi, by setting a lock to solve concurrency problems.
SHAR_EOF
chmod 0444 README ||
echo 'restore of README failed'
Wc_c="`wc -c < 'README'`"
test 1928 -eq "$Wc_c" ||
	echo 'README: original size 1928, current size' "$Wc_c"
fi
# ============= setlock.1 ==============
if test -f 'setlock.1' -a X"$1" != X"-c"; then
	echo 'x - skipping setlock.1 (File already exists)'
else
echo 'x - extracting setlock.1 (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'setlock.1' &&
.TH SETLOCK 1 "21 March 1991" "Version 1.4"
.SH NAME
.B setlock 
- test, set and clear System V UUCP lock files
.SH SYNOPSIS
.B setlock
-l lockname -p lockpid [ -f | -s | -r ] [-v]
.LP
.B setlock
-l lockname [ -t | -R ] [-v]
.SH DESCRIPTION
.I Setlock
is a program that can be used by shell scripts to set
and clear System V uucp-style lock files (located in /usr/spool/locks).  
.LP
.I Setlock 
always reads the lock file, testing to see if the process indicated 
in the lock file is still active, before performing any indicated action.
.LP
.I Setlock 
exits such that an exit code of '0' always means "action
completed successfully".  Failure exit codes from setlock are
not symmetrical.  Each exit code carries a  specific meaning
corresponding to the action given by a specific switch. 
X
.SH OPTIONS
.LP
The -l  switch is required under all circumstances:
.TP
-l lockname	... name of the lockfile 
.IP
If 'lockname' is a just a file name, then setlock will create the
lockfile in /usr/spool/locks.  If 'lockname' has a path element
in it, the lock file will be created where specified.  ie:
.nf
X				-l ./mylock
.fi
.IP
will create a lock file 'mylock' in the current directory.
.TP
-p lockpid ... pid to write to lockfile (and to test for)
.IP
This should be the process id of the invoking process.  A 
good way to do this is to use the '$$' variable of the shell
process.  ie:
.nf
X				-p $$
.fi
.IP
The remaining switches specify actions to take in regards to
the specified lock file.
.TP
-s ... set the lock
.IP
Create the lock file specified.  The name given for the lock
file is checked for existance.  If it currently exists, then
the file is read for the PID and the system is checked to see
if the process number in the lock file is still running.  If
so, setlock exits with error.  If not, then setlock creates
a lock file and exits with good status.
.TP
-r ... remove the lock, only if it matches lockpid
.IP
Try to remove the lock file specified.  The lock file is
checked to make sure the pid in the file is the same as
that specified on the command line.  If the pids don't match, setlock
exits with an error.  If the pid is correct, the lock file
is removed.
.TP
-f ... freshen lock file - touch it with current pid again
.IP
The lock file is checked to make sure the pid in the file is the
same as that specified on the command line.  If so, then the
lock data is written to the file again (the file is updated),
so that the modification date becomes current.  If the pid is
incorrect, setlock exits with error.
.TP
-R ... remove the lock, iff the lock is invalid
.IP
Remove a lock, even if it is not owned by you, but only if the
process specified in the lock file is dead.  If the process is
still running, setlock exits with error.
.TP
-t ... test to see if the lock is valid
.IP
Test a lock file to see if it is valid and the process specified
by the lock file is still running.  Exits with error if the lock
file does not exist or the process is dead.
.TP
-v ... say the exit code to stdout
.IP
Write the exit code on stdout.  Useful for debugging.
.LP
.SH EXIT CODES
.LP
.TP
0
Action performed OK.
.TP
1
Unable to set lock (current lockfile valid).
.TP
2
Did not remove lock (pid passed doesn't match lockfile).
.TP
3
Unable to freshen lock file, file does not exist.
.TP
4
Unable to freshen lock file, file found but process is dead.
.TP
5
Unable to freshen lock file, lock file not owned by you.
.TP
6
Lock is not valid, process is gone.
.TP
7
Lock file does not exist.
.TP
8
Pid specified on command line is not active.
.TP
9
Unable to remove lock file not owned by you, still active.
.TP
50
Unable to perform action, other error occurred.
.TP
100
Program exited due to error.
.SH FILES
.LP
Only the file given in the -l switch.
.SH "SEE ALSO"
.LP
uucico(1), cu(1), tip(1), pcomm(1)
.LP
.SH AUTHOR
.LP
Copyright 1991 Paul D. Anderson, All Rights Reserved Worldwide.
.LP
paul@Dixie.Com, Dixie Communications, (404) 578-9547 (noon-10PM).
PO Box 670386, Marietta, GA 30066. 
.LP
@(#) setlock.1 1.4 91/03/23  06:19:11
.SH LICENSE AGREEMENT
.LP
You may use this program for any legal purpose, but you may
not sell it.  You may not pretend that you wrote it.
.SH DEFICIENCIES / BUGS
.LP
Maybe setlock should report some kind of unique status when a file
(or any component of the path) is not accessible.  This particularly
applicable when removing a lock: setlock just returns good status:
"lock does not exist".
.LP
When setlock is given a pid, it tests to make sure that the
pid specified is at least active on the system before continuing,
but it does not make sure the pid is owned by the program invoker.
I could probably test the result code if I wanted tighter code,
but I'm not worried enough that using '$$' will cause any great
problem.
.LP
.SH FUTURE SHOCK
I suppose setlock could be tightened up and made a setuid program,
for environments that don't have world writeable lock directories.
SHAR_EOF
chmod 0444 setlock.1 ||
echo 'restore of setlock.1 failed'
Wc_c="`wc -c < 'setlock.1'`"
test 4924 -eq "$Wc_c" ||
	echo 'setlock.1: original size 4924, current size' "$Wc_c"
fi
# ============= dotest ==============
if test -f 'dotest' -a X"$1" != X"-c"; then
	echo 'x - skipping dotest (File already exists)'
else
echo 'x - extracting dotest (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'dotest' &&
:
# A script to see if setlock is *really* working OK.
# (well, it gets things going, anyway)
# "@(#) dotest 1.1"
X
# define UULOCK to test locks in /usr/spool/locks
UULOCK="LCK..setlock"
# lock dir - trailing slash IS significant
LOCKDIR="/usr/spool/locks/"
X
# define HERE to test local directory locks
HERE="./a.lock.$$"
X
# define THERE to test a lock in a remote directory
THERE="/usr/tmp/a.lock.$$"
X
# define ILLEGAL to test illegal lock creation
ILLEGAL="/usr/lib/a.lock.$$"
X
sl() {
X	echo "./setlock $*  -->\c"
X	./setlock $*
X	rc=$?
X	echo "$rc  \c"
X	return $rc
}
X
# failure flag
F=0
X
for LOCK in $UULOCK $HERE $THERE
do
X	echo "\nChecking using lockfile: $LOCK"
X
X	if [ "$LOCK" = "$UULOCK" ] ; then L="$LOCKDIR"; else L=""; fi
X
X	trap "" 0 1 2 3 15
X	if [ -f "${L}$LOCK" ] ; then echo "$LOCK exists. Aborted. "; exit 1; fi
X	trap "rm -f ${L}$LOCK" 0 1 2 3 15
X
X	# create the lock then try to create it again
X	if sl -s -p $$ -l $LOCK ; then echo "passed"; else echo "FAILED"; F=1; fi
X	if [ ! -f "${L}$LOCK" ] ; then echo "CREATE FAILED"; F=1; fi
X	if sl -s -p $$ -l $LOCK ; then echo "FAILED"; F=1; else echo "passed" ; fi
X	# remove it then remove it again
X	if sl -r -p $$ -l $LOCK ; then echo "passed"; else echo "FAILED"; F=1; fi
X	if [ -f "${L}$LOCK" ] ; then echo "REMOVE FAILED"; F=1; fi
X	if sl -r -p $$ -l $LOCK ; then echo "passed"; else echo "FAILED"; F=1; fi
X	# set the lock then remove it as a 'foreign' lock
X	if sl -s -p $$ -l $LOCK ; then echo "passed"; else echo "FAILED"; F=1; fi
X	if sl -R -l $LOCK ; then echo "FAILED"; F=1; else echo "passed" ; fi
X	if [ ! -f "${L}$LOCK" ] ; then echo "REMOVE SUCCEEDED - SHOULDN'T HAVE"; F=1; fi
X	# lock had better be there, so freshen it
X	if sl -f -p $$ -l $LOCK ; then echo "passed"; else echo "FAILED"; F=1; fi
X	# now test to see if it is there
X	if sl -t -l $LOCK ; then echo "passed"; else echo "FAILED"; F=1; fi
X	# remove it and make sure it's not there
X	if sl -r -p $$ -l $LOCK ; then echo "passed"; else echo "FAILED"; F=1; fi
X	if sl -t -l $LOCK ; then echo "FAILED"; F=1; else echo "passed"; fi
X
X	# create the lock with a pid that we know exists, but is not ours
X	# then try to create a lock over it
X	if sl -s -p 1 -l $LOCK ; then echo "passed"; else echo "FAILED"; F=1; fi
X	if sl -s -p $$ -l $LOCK ; then echo "FAILED"; F=1; else echo "passed"; fi
X	# now try to remove a lock that is not ours and make sure it still exists
X	if sl -r -p $$ -l $LOCK ; then echo "FAILED"; F=1; else echo "passed"; fi
X	if sl -t -l $LOCK ; then echo "passed"; else echo "FAILED"; F=1; fi
X	# try to remove it as a foreign lock file
X	if sl -R -l $LOCK ; then echo "FAILED"; F=1; else echo "passed" ; fi
X	if [ ! -f "${L}$LOCK" ] ; then echo "REMOVE SUCCEEDED - SHOULDN'T HAVE"; F=1; fi
X	# make sure we can remove the original lock file
X	if sl -r -p 1 -l $LOCK ; then echo "passed"; else echo "FAILED"; F=1; fi
X	if sl -t -l $LOCK ; then echo "FAILED"; F=1; else echo "passed"; fi
X	if [ -f "${L}$LOCK" ] ; then echo "REMOVE FAILED - SHOULDN'T HAVE"; F=1; fi
X
X	# if we've passed tests so far, then test all all the other
X	# exit codes (3,4,5,6,8,50)
X
X	if [ "$F" -ne 0 ] ; then
X		echo "Too many failures, testing stopped"
X		exit 1
X	fi
X
X	# freshen a non-existant log file
X	if sl -f -p $$ -l $LOCK ; then echo "FAILED"; F=1; else echo "passed"; fi
X	if [ -f "${L}$LOCK" ] ; then echo "CREATED LOCK - SHOULDN'T HAVE"; F=1; fi
X
X	# create a lock file for a process that must be dead
X	echo "     40000" > "${L}$LOCK"
X	# then try to freshen it
X	if sl -f -p $$ -l $LOCK ; then echo "FAILED"; F=1; else echo "passed"; fi
X	# since we know its a dead process, then try a foreign removal
X	if sl -R -l $LOCK ; then echo "passed"; else echo "FAILED"; F=1; fi
X	rm -f "${L}$LOCK"
X
X	# create a lock for an active process and then freshen it with our
X	# process
X	if sl -s -p 1 -l $LOCK ; then echo "passed"; else echo "FAILED"; F=1; fi
X	if sl -f -p $$ -l $LOCK ; then echo "FAILED"; F=1; else echo "passed"; fi
X	if sl -r -p 1 -l $LOCK ; then echo "passed"; else echo "FAILED"; F=1; fi
X
X	# test an invalid lock
X	echo "     40000" > "${L}$LOCK"
X	if sl -t -l $LOCK ; then echo "FAILED"; F=1; else echo "passed"; fi
X	rm -f "${L}$LOCK"
X
X	# test for an illegal invocation pid
X	if sl -s -p 40000 -l $LOCK ; then echo "FAILED"; F=1; else echo "passed"; fi
X	rm -f "${L}$LOCK"
X
done
X
if [ "$F" -ne 0 ] ; then
X	echo "Too many tests failed. exiting."
X	exit 1
fi
X
trap "" 0 1 2 3 15
X
if [ -n "$ILLEGAL" ] ; then
X
X	LOCK="$ILLEGAL"
X	L=""
X
X	echo "\nTesting for illegal access lock creation"
X	# only test for creating a lock where it is not allowed, since
X	# we have pretty much wrung out functionality.
X	if sl -s -p $$ -l $LOCK ; then echo "FAILED"; F=1; else echo "passed" ; fi
X	if sl -r -p $$ -l $LOCK ; then echo "passed"; else echo "FAILED"; F=1; fi
fi
X
if [ "$F" -eq 0 ] ; then
X	echo "\nCongratulations, it appears that setlock works on your system!"
X	exit 0
fi
X
exit 1
X
SHAR_EOF
chmod 0460 dotest ||
echo 'restore of dotest failed'
Wc_c="`wc -c < 'dotest'`"
test 4866 -eq "$Wc_c" ||
	echo 'dotest: original size 4866, current size' "$Wc_c"
fi
# ============= Hourly ==============
if test -f 'Hourly' -a X"$1" != X"-c"; then
	echo 'x - skipping Hourly (File already exists)'
else
echo 'x - extracting Hourly (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'Hourly' &&
:
set -x
LIBD=/usr/local/news/bin
X
# %Z% %M% %I% %E% %Q% %U%
X
# News stuff to do every hour.  But we will do it in sequence, so
# that we don't get 4 copies of compress running concurrently.
# It is important to run this script at exactly 0, 15, 30 and 45 minutes.
X
# This script will run every 15 minutes, but we'll make
# sure that some things only occur hourly.  
X
# To do this, we will test the date and time, setting some files
# in the bin dir as flags, showing that we should do certain
# functions.  We need to do it this way, because there may be
# occassions where this script will not exit for several hours
# and we would miss the window for performing certain functions...
# As such, we will just set a flag and perform the functions later.
X
# Set 'flags' here to direct processing...
X
MINUTE=`date +%M`
HOUR=`date +%H`
X
STATUS="$LIBD/.status"		# here is where status is written
X
FLUSH="$LIBD/.flush"		# flush all batch queues when present
UUNET="$LIBD/.uunet"		# do the sendbatch for uunet when present
REGULAR="$LIBD/.regular" 	# do regular batching when present
CLEANUP="$LIBD/.cleanup"	# run expire
ARCHIVE="$LIBD/.archive"	# archive files
X
if [ $MINUTE = "00" ] ; then
X	case $HOUR in
X	02|06|09|14|18|23)
X			touch $ARCHIVE;;	# archive data
X	07)	
X			touch $CLEANUP;;	# run expire and free disk
X	10)
X			touch $FLUSH;;		# flush all batch queues
X	22)
X			touch $UUNET;;		# batch up uunet news
X	*)
X	esac
X
X	# Start batching every hour
X	touch $REGULAR
fi
X
# Now see if we are already running, and if so, then exit
# because there is no further processing we can do.  Otherwise, set
# a lock file and begin processing.
X
LCKDIR=/usr/spool/locks
LOCK=LCK..newshour
LOCKPRG=/usr/local/bin/setlock
X
if  $LOCKPRG -s -p $$ -l $LOCK  ; then
X	: # we set the lock, now do the rest of the processing
else
X	#echo "Already running"
X	exit 0
fi
X
trap "rm -f $LCKDIR/$LOCK $STATUS" 0 1 2 3 15
X
status() {
X	echo "$*" > $STATUS
}
X
# flush all articles at 10 each morning by using default -a0
# by setting a minimum before queing, we can ensure full batches...
X
if [ -f $FLUSH ] ; then
X	rm -f $FLUSH
X	for system in kd4nc nanovx wa4mei slammer ke4zv
X	do
X		status "Flushing batch que for $system"
X		$LIBD/Sendbatch -c -f10000 -m12000000 -s250000 $system
X	done
X	status
fi
X
# post stuff to uunet only once a day, just before we get our feed from them
X
if [ -f $UUNET ] ; then
X	rm -f $UUNET
X	status "Preparing batch for uunet"
X	$LIBD/Sendbatch -c -m2000000 -f2000 uunet
X	status
fi
X
X
# always cleanup before unbatching...
if [ -f $CLEANUP ] ; then
X	rm -f $CLEANUP
X	status "Running nightly cleanup"
X	$LIBD/Nightly
X	status
fi
X
X
# ALWAYS unbatch
status "Unbatching"
rnews -U
status
X
X
# Archive away any articles
X
if [ -f $ARCHIVE ] ; then
X	rm -f $ARCHIVE
X	status "Archiving news articles"
X	$LIBD/Archive2
X	status
fi
X
# Feed news to other sites
# leave the day and evening hours free for our use
# -f = MIN Blocks on spool
# -m = max bytes allowed for site
# -s = batch size
# -a = min Articles in batch file for site before batching
#
X
if [ -f $REGULAR ] ; then
X	rm -f $REGULAR
X
X	# Emory is our primary feed. I want them to get anything posted here asap.
X	status "Preparing batch for emory"
X	$LIBD/Sendbatch -c -f2500 -m4000000 emory
X
X	# do the Dynafeed sends
X	for system in arg toolz
X	do
X		status "Preparing batch for $system"
X		$LIBD/dofeeds $system
X	done
X	status
X
X	for system in kd4nc nanovx wa4mei slammer ke4zv
X	do
X		status "Preparing batch for $system"
X		$LIBD/Sendbatch -c -a150 -f10000 -m12000000 -s250000 $system
X	done
X	status
fi
X
SHAR_EOF
chmod 0770 Hourly ||
echo 'restore of Hourly failed'
Wc_c="`wc -c < 'Hourly'`"
test 3521 -eq "$Wc_c" ||
	echo 'Hourly: original size 3521, current size' "$Wc_c"
fi
# ============= gettyclear ==============
if test -f 'gettyclear' -a X"$1" != X"-c"; then
	echo 'x - skipping gettyclear (File already exists)'
else
echo 'x - extracting gettyclear (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'gettyclear' &&
X
X
# script to periodically kill the getty on the dialin ports, resetting modems
X
LCKDIR="/usr/spool/locks"
TMP="/usr/tmp/gc.$$"
X
SETLOCK=/usr/local/bin/setlock
X
trap "rm -f $TMP" 0 1 2 3 15
X
for d in 01 04 05 06 07
do
X	ps -ef >$TMP &
X
X	$SETLOCK -R -l LCK..ttya$d
X	$SETLOCK -R -l LCK..ttyA$d
X
X	wait
X
X	if [ -f "$LCKDIR/LCK..ttya$d" -o -f "$LCKDIR/LCK..ttyA$d" ] ; then
X		: # if the lockfile still exists, then do nothing
X	else
X		pid=`grep [u]utty < $TMP | egrep 'tty[aA]'$d | awk ' { print $2 } '`
X		if [ -n "$pid" ] ; then 
X			kill -9 $pid
X		fi
X		chmod 666 /dev/ttya$d /dev/ttyA$d
X		stty sane </dev/ttya$d
X	fi
done
SHAR_EOF
chmod 0760 gettyclear ||
echo 'restore of gettyclear failed'
Wc_c="`wc -c < 'gettyclear'`"
test 614 -eq "$Wc_c" ||
	echo 'gettyclear: original size 614, current size' "$Wc_c"
fi
# ============= log ==============
if test -f 'log' -a X"$1" != X"-c"; then
	echo 'x - skipping log (File already exists)'
else
echo 'x - extracting log (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'log' &&
:
# script to help with team logging
#LOG=/usr1/foo/teamlog
#LOGLOCK=/usr1/foo/LCK..teamlog
X
if [ -z "$LOG" ] ; then
X	echo "You must set the LOG environment variable to set where the"
X	echo "log file is to be located."
X	exit 1;
fi
if [ -z "$LOGLOCK" ] ; then
X	echo "You must set the LOGLOCK environment variable to set where the"
X	echo "lock file is to be located."
X	exit 1;
fi
X
if setlock -s -p $$ -l $LOGLOCK ; then
X	trap "rm -f $LOGLOCK" 0 1 2 3 15
else
X	echo "Log is currently being edited.  Try again later.\n"
X	echo "The log is currently being edited by:"
X	ps -fp `cat $LOGLOCK`
X	exit 1
fi
X
echo "------------------------------------------------------" >>${LOG}
echo "Entry:  `date +'%A, %D, %R %p'`  `id`\n\n" >> ${LOG}
chmod 0660 ${LOG}
vi +\$  ${LOG}
echo "" >>${LOG}
X
SHAR_EOF
chmod 0570 log ||
echo 'restore of log failed'
Wc_c="`wc -c < 'log'`"
test 778 -eq "$Wc_c" ||
	echo 'log: original size 778, current size' "$Wc_c"
fi
exit 0
-- 
* Paul Anderson * Dixie Communications * (404) 578-9547 * pda@dixie.com *