flock command for XENIX
Richard Greenall
richard at berner.uucp
Fri Jul 21 02:46:49 AEST 1989
I was in need of an equivilent to the BSD flock command under XENIX 2.3.2, so
I wrote one. It comes in handy in shell scripts.
So without further adieu, here it is.
#! /bin/sh
# This is a shell archive. Remove anything before this line, then feed it
# into a shell via "sh file" or similar. To overwrite existing files,
# type "sh file -c".
# The tool that generated this appeared in the comp.sources.unix newsgroup;
# send mail to comp-sources-unix at uunet.uu.net if you want that tool.
# If this archive is complete, you will see the following message at the end:
# "End of shell archive."
# Contents: flock.c
# Wrapped by richard at berner on Thu Jul 20 12:43:42 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'flock.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'flock.c'\"
else
echo shar: Extracting \"'flock.c'\" \(4361 characters\)
sed "s/^X//" >'flock.c' <<'END_OF_FILE'
X/* flock.
X
X This program is a close equivilent to the 4.3 bsd flock command for
X locking files from the command line. The only differences between this
X flock command and the bsd flock command is that only 1 file name
X may appear on the command line instead of multiple file names.
X
X This program is in the public domain and may be used and
X distributed as long as this message is not removed from the source.
X
X This program was written under SCO XENIX 2.3.2 (386) but should
X run under any SYSTEM V machine with little change. I have tried
X to stay away from anything XENIX specific, but who knows?
X
X Richard Greenall
X berner!richard
X*/
X
X#include <stdio.h>
X#include <stdlib.h>
X#include <errno.h>
X#include <fcntl.h>
X#include <signal.h>
X#include <values.h>
X#include <getopt.h>
X#include <prototypes.h>
X
Xint child, parent, fildes;
X
Xvoid (*deffunc1)();
Xvoid (*deffunc2)();
X
Xvoid childdone( void );
Xvoid killchild( void );
Xvoid closefile( void );
X
Xint main(argc,argv)
Xint argc;
Xchar *argv[];
X{
X int c,shared,exclusive,nonblocking,errflag;
X int status;
X
X struct flock flock;
X
X /* initialize all data to zero at begining */
X
X c = shared = exclusive = nonblocking = errflag = 0;
X parent = getpid();
X
X /* get options. Options to the program are s, e, & n without
X any parameters. The options s & e are mutually exclusive */
X
X while( (c = getopt(argc,argv,"sen")) != EOF)
X switch( (char) c ) {
X case 's' : shared++; break;
X case 'e' : exclusive++; break;
X case 'n' : nonblocking++; break;
X case '?' : errflag++; break;
X }
X
X /* check for errors from options and report if any */
X
X if(errflag || (shared && exclusive) || argc != optind+1 ) {
X fprintf(stderr,"Usage : %s [ -sen ] filename\n",argv[0]);
X exit(1);
X }
X
X /* if neither shared or exclusive flag set, default to exclusive mode */
X if(!shared && !exclusive) exclusive++;
X
X /* use this signal to let the parent know when everything has gone
X ok, and that it may exit */
X
X signal(SIGUSR1,childdone);
X
X switch(child = fork()) {
X case -1:
X perror(argv[0]);
X exit(1);
X case 0:
X /* ignore break key presses */
X
X signal(SIGINT,SIG_IGN);
X
X /* open the file for read only if shared access requested, read and
X write if exclusive */
X
X fildes = open(argv[optind], (shared) ? O_RDONLY : O_RDWR);
X if(fildes == -1) {
X perror(argv[0]);
X exit(1);
X }
X
X /* set flags to lock the entire file */
X
X flock.l_whence = 0;
X flock.l_start = flock.l_len = 0L;
X
X /* type of lock */
X if(shared) flock.l_type = F_RDLCK;
X if(exclusive) flock.l_type = F_WRLCK;
X
X /* use fcntl to lock the file. If the type of lock is
X blocking, and we get an error, report it. If the
X type of lock is nonblocking and we get an error, it
X could be that another process has the file
X locked, so just report is silently by exiting
X with status 1 */
X
X if(fcntl(fildes,(nonblocking) ? F_SETLK : F_SETLKW, &flock)== -1)
X if(nonblocking) {
X if(errno == EAGAIN) {
X fprintf(stderr, "%s: Operation would block\n",argv[0]);
X exit(2);
X }
X else {
X perror(argv[0]);
X exit(1);
X }
X } else {
X perror(argv[0]);
X exit(1);
X }
X
X /* let the parent know that everything has gone ok, and it
X can exit */
X
X kill(parent,SIGUSR1);
X
X /* set up to sleep forever */
X
X signal(SIGTERM,closefile);
X
X /* close all streams so that the shell will not expect any
X more output */
X
X fclose(stdin);
X fclose(stdout);
X fclose(stderr);
X
X /* sleep forever till killed */
X
X for ( ; ; ) sleep(MAXINT);
X
X default:
X /* kill the child if any signals are received while waiting */
X deffunc1 = signal(SIGINT,killchild);
X deffunc2 = signal(SIGHUP,killchild);
X
X /* if this wait returns, there must have been an error becuase
X an ok exit would call the function childdone() */
X
X wait(&status);
X signal(SIGINT,deffunc1);
X signal(SIGHUP,deffunc2);
X
X /* now exit with the same status code as the child (high order
X 8 bits */
X exit( (status >> 8) );
X }
X /* NOTREACHED */
X}
X
X
Xvoid childdone() {
X /* child has finished so exit printing out its pid number so that
X it may be killed later by the user */
X printf("%d\n",child);
X exit(0);
X}
X
X
Xvoid killchild() {
X /* a Break was hit, so kill the child so that the lock won't be left */
X kill(child,SIGTERM);
X exit(1);
X}
X
X
Xvoid closefile() {
X close(fildes);
X exit(0);
X}
END_OF_FILE
echo shar: NEWLINE appended to \"'flock.c'\"
if test 4362 -ne `wc -c <'flock.c'`; then
echo shar: \"'flock.c'\" unpacked with wrong size!
fi
# end of 'flock.c'
fi
echo shar: End of shell archive.
exit 0
More information about the Alt.sources
mailing list