home *** CD-ROM | disk | FTP | other *** search
- /* $Header: lock.c,v 2.2 90/05/03 10:13:56 chip Exp $
- *
- * Mailbox locking.
- * Local hacks for mailbox access should be grafted here.
- *
- * $Log: lock.c,v $
- * Revision 2.2 90/05/03 10:13:56 chip
- * Really unlock file descriptors in fd_unlock(). (!)
- *
- * Revision 2.1 89/06/09 12:25:30 network
- * Update RCS revisions.
- *
- * Revision 1.6 89/06/09 12:23:52 network
- * Baseline for 2.0 release.
- *
- */
-
- #include "deliver.h"
-
- /*
- * Validate the locking configuration.
- */
-
- #if (defined(ML_FCNTL) + defined(ML_LOCKF) + defined(ML_LOCKING)) > 1
- lose! "Only one of ML_FCNTL, ML_LOCKF and ML_LOCKING may be defined.";
- #endif
-
- /*
- * Support for the lockf() system call.
- */
-
- #ifdef ML_LOCKF
- #include <unistd.h>
- #define SIMPLE_LOCK "lockf"
- #define LOCKFD(fd, size) lockf(fd, F_LOCK, size)
- #define UNLOCKFD(fd, size) lockf(fd, F_ULOCK, size)
- #endif /* ML_LOCKF */
-
- /*
- * Setup for the locking() system call.
- */
-
- #ifdef ML_LOCKING
- #include <sys/locking.h>
- #define SIMPLE_LOCK "locking"
- #define LOCKFD(fd, size) locking(fd, LK_LOCK, size)
- #define UNLOCKFD(fd, size) locking(fd, LK_UNLCK, size)
- #endif
-
- /*
- * Local functions.
- */
-
- #ifdef ML_DOTLOCK
- static char *dotlock_name();
- #endif
- #ifdef ML_DOTMLK
- static char *dotmlk_name();
- #endif
-
- /*----------------------------------------------------------------------
- * Lock a mailbox by name.
- *
- * This code looks quite hairy with all the ifdefs. In fact, the only
- * somewhat strange thing here is that neither, either, or both of
- * ML_DOTLOCK and ML_DOTMLK may be defined, and we have to allow for it.
- */
-
- int
- name_lock(name)
- char *name;
- {
- #ifdef ML_DOTLOCK
- char *dotlock;
- #endif
- #ifdef ML_DOTMLK
- char *dotmlk;
- #endif
-
- #ifdef ML_DOTLOCK
- if ((dotlock = dotlock_name(name)) == NULL
- || create_lockfile(dotlock) < 0)
- return -1;
- #endif /* ML_DOTLOCK */
-
- #ifdef ML_DOTMLK
- if ((dotmlk = dotmlk_name(name)) == NULL
- || create_lockfile(dotmlk) < 0)
- {
- #ifdef ML_DOTLOCK
- (void) remove_lockfile(dotlock); /* don't leave me hanging */
- #endif
- return -1;
- }
- #endif /* ML_DOTMLK */
-
- return 0;
- }
-
- /*----------------------------------------------------------------------
- * Unlock a mailbox by name.
- */
-
- int
- name_unlock(name)
- char *name;
- {
- int ret = 0;
-
- #ifdef ML_DOTLOCK
- char *dotlock;
- #endif
- #ifdef ML_DOTMLK
- char *dotmlk;
- #endif
-
- #ifdef ML_DOTLOCK
- if ((dotlock = dotlock_name(name)) == NULL
- || remove_lockfile(dotlock) < 0)
- ret = -1;
- #endif /* ML_DOTLOCK */
-
- #ifdef ML_DOTMLK
- if ((dotmlk = dotmlk_name(name)) == NULL
- || remove_lockfile(dotmlk) < 0)
- ret = -1;
- #endif /* ML_DOTMLK */
-
- return ret;
- }
-
- /*----------------------------------------------------------------------
- * Lock a file descriptor.
- */
-
- int
- fd_lock(fd)
- int fd;
- {
- #ifdef ML_FCNTL
- struct flock fl;
-
- fl.l_type = F_WRLCK;
- fl.l_whence = 0;
- fl.l_start = 0L;
- fl.l_len = 0L;
-
- if (fcntl(fd, F_SETLKW, &fl) == -1)
- {
- syserr("can't lock with fcntl()");
- return -1;
- }
-
- if (verbose)
- message("locked mailbox with fcntl()\n");
- #endif /* ML_FCNTL */
-
- #ifdef SIMPLE_LOCK
- long pos;
-
- if ((pos = lseek(fd, 0L, 0)) == -1)
- {
- syserr("can't seek in mailbox");
- return -1;
- }
- if (LOCKFD(fd, 0L) == -1)
- {
- syserr("can't lock with %s()", SIMPLE_LOCK);
- return -1;
- }
- if (lseek(fd, pos, 0) == -1)
- {
- syserr("can't seek in mailbox");
- return -1;
- }
-
- if (verbose)
- message("locked mailbox with %s()\n", SIMPLE_LOCK);
- #endif /* SIMPLE_LOCK */
-
- /* Default: success */
- return 0;
- }
-
- /*----------------------------------------------------------------------
- * Unlock a file descriptor.
- */
-
- int
- fd_unlock(fd)
- int fd;
- {
- #ifdef ML_FCNTL
- struct flock fl;
-
- fl.l_type = F_UNLCK;
- fl.l_whence = 0;
- fl.l_start = 0L;
- fl.l_len = 0L;
-
- if (fcntl(fd, F_SETLKW, &fl) == -1)
- {
- syserr("can't unlock with fcntl()");
- return -1;
- }
-
- if (verbose)
- message("unlocked mailbox with fcntl()\n");
- #endif /* ML_FCNTL */
-
- #ifdef SIMPLE_LOCK
- long pos;
-
- if ((pos = lseek(fd, 0L, 0)) == -1)
- {
- syserr("can't seek in mailbox");
- return -1;
- }
- if (UNLOCKFD(fd, 0L) == -1)
- {
- syserr("can't unlock with %s()", SIMPLE_LOCK);
- return -1;
- }
- if (lseek(fd, pos, 0) == -1)
- {
- syserr("can't seek in mailbox");
- return -1;
- }
-
- if (verbose)
- message("unlocked mailbox with %s()\n", SIMPLE_LOCK);
- #endif /* SIMPLE_LOCK */
-
- /* Default: success */
- return 0;
- }
-
- /*----------------------------------------------------------------------
- * Return the name of the appropriate ".lock" file for a mailbox.
- */
-
- #ifdef ML_DOTLOCK
-
- static char *
- dotlock_name(name)
- char *name;
- {
- static char *lname = NULL;
- static int lsize = 0;
- char *p;
- int n, i;
-
- n = strlen(name);
- if (lsize < n + 8)
- {
- if (lname)
- free(lname);
- lsize = n + 32;
- lname = zalloc(lsize);
- }
-
- (void) strcpy(lname, name);
-
- /*
- * We want as much of `basename.lock' as will fit in a string
- * MAX_NAMESIZE long.
- */
- for (i = 0, p = basename(lname); (i < MAX_NAMESIZE - 5) && (*p); ++i)
- ++p;
- (void) strcpy(p, ".lock");
-
- return lname;
- }
-
- #endif /* ML_DOTLOCK */
-
- /*----------------------------------------------------------------------
- * Return the name of the appropriate ".mlk" file for a mailbox.
- */
-
- #ifdef ML_DOTMLK
-
- static char *
- dotmlk_name(name)
- char *name;
- {
- static char lname[MAX_NAMESIZE + 16];
- char *p, *d;
- int i;
-
- /*
- * To explain the below: If we ass_u_me that MAX_NAMESIZE is 14,
- * then this code is like `printf(lname, "/tmp/%.10s.mlk", ...)'.
- * In other words, we want as much of `basename.mlk' as will fit
- * in a string MAX_NAMESIZE long.
- */
- d = lname;
- for (p = "/tmp/"; *p; )
- *d++ = *p++;
- for (i = 0, p = basename(name); (i < MAX_NAMESIZE - 4) && (*p); ++i)
- *d++ = *p++;
- (void) strcpy(d, ".mlk");
-
- return lname;
- }
-
- #endif /* ML_DOTMLK */
-
- /*----------------------------------------------------------------------
- * Create a lockfile.
- */
-
- int
- create_lockfile(name)
- char *name;
- {
- #ifndef O_CREAT
- char *othername, *p;
- #endif
- int fd, tries;
-
- #ifndef O_CREAT
- othername = zalloc(strlen(name) + 20); /* fudge (???) */
- (void) strcpy(othername, name);
- (void) sprintf(basename(othername), ".dl.%d", getpid());
- if ((fd = creat(othername, 0)) == -1)
- {
- syserr("can't create %s", othername);
- return -1;
- }
- (void) close(fd);
- if (verbose)
- message("created pre-lockfile %s\n", name);
- #endif
-
- for (tries = 0; tries < 10; ++tries)
- {
- if (tries)
- snooze(3);
-
- #ifdef O_CREAT
-
- if ((fd = open(name, O_RDWR|O_CREAT|O_EXCL, 0)) >= 0)
- {
- (void) close(fd);
- if (verbose)
- message("created lockfile %s\n", name);
- return 0;
- }
-
- #else /* not O_CREAT */
-
- if (link(othername, name) == 0)
- {
- if (unlink(othername) == -1)
- syserr("can't remove %s", othername);
- free(othername);
- if (verbose)
- message("created lockfile %s\n", name);
- return 0;
- }
-
- #endif /* not O_CREAT */
-
- if (verbose && (tries == 0))
- message("Waiting to create %s\n", name);
- }
-
- syserr("can't create lockfile %s", name);
- return -1;
- }
-
- /*----------------------------------------------------------------------
- * Remove a lockfile.
- */
-
- int
- remove_lockfile(name)
- char *name;
- {
- if (unlink(name) == -1)
- {
- syserr("can't remove lockfile %s", name);
- return -1;
- }
-
- if (verbose)
- message("removed lockfile %s\n", name);
-
- return 0;
- }
-