home *** CD-ROM | disk | FTP | other *** search
- /* $Header: lock.c,v 1.2 88/08/30 16:13:14 network Exp $
- *
- * Mailbox locking.
- * Local hacks for mailbox access should be grafted here.
- *
- * $Log: lock.c,v $
- * Revision 1.2 88/08/30 16:13:14 network
- * Portability fixes from Ronald Karr <tron@uts.amdahl.com>.
- *
- * Revision 1.1 88/06/06 09:38:48 chip
- * Initial revision
- *
- */
-
- #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/types.h>
- #include <sys/locking.h>
- #define SIMPLE_LOCK "locking"
- #define LOCKFD(fd, size) locking(fd, LK_LOCK, size)
- #define UNLOCKFD(fd, size) locking(fd, LK_UNLOCK, 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
- lock_name(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
- unlock_name(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
- lock_fd(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
- unlock_fd(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 (LOCKFD(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;
- {
- int tries, fd;
-
- for (tries = 0; tries < 10; ++tries)
- {
- if (tries)
- snooze(3);
-
- 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;
- }
-
- if (verbose && (tries == 0))
- {
- message("Waiting to create %s (try #%d)\n",
- name, tries + 1);
- }
- }
-
- 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;
- }
-