]> diplodocus.org Git - nmh/blobdiff - sbr/lock_file.c
mhstore(1) now obeys its -noverbose switch.
[nmh] / sbr / lock_file.c
index 9771543ce91f2a691033c2f177ad70a945d25607..1a562f9b987d61333f7367bb50fd1aee851cbfa7 100644 (file)
@@ -2,63 +2,67 @@
 /*
  * lock.c -- routines to lock/unlock files
  *
 /*
  * lock.c -- routines to lock/unlock files
  *
- * $Id$
+ * This code is Copyright (c) 2002, by the authors of nmh.  See the
+ * COPYRIGHT file in the root directory of the nmh distribution for
+ * complete copyright information.
  */
 
  */
 
+/* Modified by Ruud de Rooij to support Miquel van Smoorenburg's liblockfile
+ *
+ * Since liblockfile locking shares most of its code with dot locking, it
+ * is enabled by defining both DOT_LOCKING and HAVE_LIBLOCKFILE.
+ *
+ * Ruud de Rooij <ruud@debian.org>  Sun, 28 Mar 1999 15:34:03 +0200
+ */
 #include <h/mh.h>
 #include <h/signals.h>
 #include <h/mh.h>
 #include <h/signals.h>
+#include <h/utils.h>
+#include <h/mts.h>
 
 
-#ifdef HAVE_ERRNO_H
-# include <errno.h>
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
 #endif
 #endif
-
-#ifdef MMDFONLY
-# include <mmdfonly.h>
-# include <lockonly.h>
-#endif /* MMDFONLY */
-
-#ifdef HAVE_FCNTL_H
-# include <fcntl.h>
-#else
+#include <time.h>
+#include <fcntl.h>
+#ifdef HAVE_FLOCK
 # include <sys/file.h>
 #endif
 
 # include <sys/file.h>
 #endif
 
-#if defined(LOCKF_LOCKING) || defined(FLOCK_LOCKING)
-# include <sys/file.h>
+#if defined(HAVE_LIBLOCKFILE)
+# include <lockfile.h>
 #endif
 
 #endif
 
-#include <signal.h>
-
-extern int errno;
-
 #ifdef LOCKDIR
 char *lockdir = LOCKDIR;
 #endif
 
 #ifdef LOCKDIR
 char *lockdir = LOCKDIR;
 #endif
 
-/* Are we using any kernel locking? */
-#if defined (FLOCK_LOCKING) || defined(LOCKF_LOCKING) || defined(FCNTL_LOCKING)
-# define KERNEL_LOCKING
-#endif
-
-#ifdef DOT_LOCKING
-
 /* struct for getting name of lock file to create */
 struct lockinfo {
     char curlock[BUFSIZ];
 /* struct for getting name of lock file to create */
 struct lockinfo {
     char curlock[BUFSIZ];
+#if !defined(HAVE_LIBLOCKFILE)
     char tmplock[BUFSIZ];
     char tmplock[BUFSIZ];
+#endif
 };
 
 };
 
+/*
+ * Number of tries to retry locking
+ */
+#define LOCK_RETRIES 5
+
 /*
  * Amount of time to wait before
  * updating ctime of lock file.
  */
 #define        NSECS 20
 
 /*
  * Amount of time to wait before
  * updating ctime of lock file.
  */
 #define        NSECS 20
 
+#if !defined(HAVE_LIBLOCKFILE)
 /*
  * How old does a lock file need to be
  * before we remove it.
  */
 #define RSECS 180
 /*
  * How old does a lock file need to be
  * before we remove it.
  */
 #define RSECS 180
+#endif /* HAVE_LIBLOCKFILE */
 
 /* struct for recording and updating locks */
 struct lock {
 
 /* struct for recording and updating locks */
 struct lock {
@@ -67,109 +71,125 @@ struct lock {
     struct lock *l_next;
 };
 
     struct lock *l_next;
 };
 
-/* top of list containing all open locks */
-static struct lock *l_top = NULL;
-#endif /* DOT_LOCKING */
+enum locktype { FCNTL_LOCKING, FLOCK_LOCKING, LOCKF_LOCKING, DOT_LOCKING };
 
 /*
 
 /*
- * static prototypes
+ * Flags to indicate whether we've initialized the lock types, and
+ * our saved lock types
  */
  */
-#ifdef KERNEL_LOCKING
-static int lkopen_kernel (char *, int, mode_t);
-#endif
+static int datalockinit = 0;
+static int spoollockinit = 0;
+static enum locktype datalocktype, spoollocktype;
 
 
-#ifdef DOT_LOCKING
-static int lkopen_dot (char *, int, mode_t);
-static int lockit (struct lockinfo *);
-static void lockname (char *, struct lockinfo *, int);
+
+/* top of list containing all open locks */
+static struct lock *l_top = NULL;
+
+static int lkopen(const char *, int, mode_t, enum locktype);
+static int str2accbits(const char *);
+
+static int lkopen_fcntl (const char *, int, mode_t);
+#ifdef HAVE_LOCKF
+static int lkopen_lockf (const char *, int, mode_t);
+#endif /* HAVE_LOCKF */
+#ifdef HAVE_FLOCK
+static int lkopen_flock (const char *, int, mode_t);
+#endif /* HAVE_FLOCK */
+
+static enum locktype init_locktype(const char *);
+
+static int lkopen_dot (const char *, int, mode_t);
+static void lkclose_dot (int, const char *);
+static void lockname (const char *, struct lockinfo *, int);
 static void timerON (char *, int);
 static void timerOFF (int);
 static void timerON (char *, int);
 static void timerOFF (int);
-static RETSIGTYPE alrmser (int);
-#endif
+static void alrmser (int);
 
 
+#if !defined(HAVE_LIBLOCKFILE)
+static int lockit (struct lockinfo *);
+#endif
 
 /*
 
 /*
- * Base routine to open and lock a file,
- * and return a file descriptor.
+ * Base functions: determine the data type used to lock files and
+ * call the underlying function.
  */
 
 int
  */
 
 int
-lkopen (char *file, int access, mode_t mode)
+lkopendata(const char *file, int access, mode_t mode)
 {
 {
-#ifdef KERNEL_LOCKING
-    return lkopen_kernel(file, access, mode);
-#endif
+    if (! datalockinit) {
+       char *cp = context_find("datalocking");
 
 
-#ifdef DOT_LOCKING
-    return lkopen_dot(file, access, mode);
-#endif
+       if (cp) {
+           datalocktype = init_locktype(cp);
+       } else {
+           /* We default to fcntl locking for data files */
+           datalocktype = FCNTL_LOCKING;
+       }
+
+       datalockinit = 1;
+    }
+
+    return lkopen(file, access, mode, datalocktype);
 }
 
 
 /*
 }
 
 
 /*
- * Base routine to close and unlock a file,
- * given a file descriptor.
+ * Locking using the spool locking algorithm
  */
 
  */
 
-int
-lkclose (int fd, char *file)
+int lkopenspool(const char *file, int access, mode_t mode)
 {
 {
-#ifdef FCNTL_LOCKING
-    struct flock buf;
-#endif
+    if (! spoollockinit) {
+       spoollocktype = init_locktype(spoollocking);
 
 
-#ifdef DOT_LOCKING
-    struct lockinfo lkinfo;
-#endif
+       spoollockinit = 1;
+    }
 
 
-    if (fd == -1)
-       return 0;
+    return lkopen(file, access, mode, spoollocktype);
+}
 
 
-#ifdef FCNTL_LOCKING
-    buf.l_type   = F_UNLCK;
-    buf.l_whence = SEEK_SET;
-    buf.l_start  = 0;
-    buf.l_len    = 0;
-    fcntl(fd, F_SETLK, &buf);
-#endif
 
 
-#ifdef FLOCK_LOCKING
-    flock (fd, LOCK_UN);
-#endif
+/*
+ * Versions of lkopen that return a FILE *
+ */
 
 
-#ifdef LOCKF_LOCKING
-    /* make sure we unlock the whole thing */
-    lseek (fd, (off_t) 0, SEEK_SET);
-    lockf (fd, F_ULOCK, 0L);
-#endif 
+FILE *
+lkfopendata(const char *file, const char *mode)
+{
+    FILE *fp;
+    int oflags = str2accbits(mode);
+    int fd;
 
 
-#ifdef DOT_LOCKING
-    lockname (file, &lkinfo, 0);       /* get name of lock file */
-    unlink (lkinfo.curlock);           /* remove lock file      */
-    timerOFF (fd);                     /* turn off lock timer   */
-#endif
+    if (oflags == -1) {
+       errno = EINVAL;
+       return NULL;
+    }
 
 
-    return (close (fd));
-}
+    if ((fd = lkopendata(file, oflags, 0666)) == -1)
+       return NULL;
 
 
+    if ((fp = fdopen (fd, mode)) == NULL) {
+       close (fd);
+       return NULL;
+    }
 
 
-/*
- * Base routine to open and lock a file,
- * and return a FILE pointer
- */
+    return fp;
+}
 
 FILE *
 
 FILE *
-lkfopen (char *file, char *mode)
+lkfopenspool(const char *file, const char *mode)
 {
 {
-    int fd, access;
     FILE *fp;
     FILE *fp;
+    int oflags = str2accbits(mode);
+    int fd;
 
 
-    if (strcmp (mode, "r") == 0)
-       access = O_RDONLY;
-    else
-       access = O_RDWR;
+    if (oflags == -1) {
+       errno = EINVAL;
+       return NULL;
+    }
 
 
-    if ((fd = lkopen (file, access, 0)) == -1)
+    if ((fd = lkopenspool(file, oflags, 0666)) == -1)
        return NULL;
 
     if ((fp = fdopen (fd, mode)) == NULL) {
        return NULL;
 
     if ((fp = fdopen (fd, mode)) == NULL) {
@@ -182,138 +202,280 @@ lkfopen (char *file, char *mode)
 
 
 /*
 
 
 /*
- * Base routine to close and unlock a file,
- * given a FILE pointer
+ * Corresponding close functions.
+ *
+ * A note here: All of the kernel locking functions terminate the lock
+ * when the descriptor is closed, so why write the code to explicitly
+ * unlock the file?  We only need to do this in the dot-locking case.
  */
 
 int
  */
 
 int
-lkfclose (FILE *fp, char *file)
+lkclosedata(int fd, const char *name)
 {
 {
-#ifdef FCNTL_LOCKING
-    struct flock buf;
-#endif
+    int rc = close(fd);
 
 
-#ifdef DOT_LOCKING
-    struct lockinfo lkinfo;
-#endif
+    if (datalocktype == DOT_LOCKING)
+       lkclose_dot(fd, name);
 
 
-    if (fp == NULL)
-       return 0;
+    return rc;
+}
 
 
-#ifdef FCNTL_LOCKING
-    buf.l_type   = F_UNLCK;
-    buf.l_whence = SEEK_SET;
-    buf.l_start  = 0;
-    buf.l_len    = 0;
-    fcntl(fileno(fp), F_SETLK, &buf);
-#endif
+int
+lkfclosedata(FILE *f, const char *name)
+{
+    int fd, rc;
 
 
-#ifdef FLOCK_LOCKING
-    flock (fileno(fp), LOCK_UN);
-#endif
+    if (f == NULL)
+       return 0;
+    
+    fd = fileno(f);
+    rc = fclose(f);
 
 
-#ifdef LOCKF_LOCKING
-    /* make sure we unlock the whole thing */
-    fseek (fp, 0L, SEEK_SET);
-    lockf (fileno(fp), F_ULOCK, 0L);
-#endif
+    if (datalocktype == DOT_LOCKING)
+       lkclose_dot(fd, name);
 
 
-#ifdef DOT_LOCKING
-    lockname (file, &lkinfo, 0);       /* get name of lock file */
-    unlink (lkinfo.curlock);           /* remove lock file      */
-    timerOFF (fileno(fp));             /* turn off lock timer   */
-#endif
+    return rc;
+}
 
 
-    return (fclose (fp));
+int
+lkclosespool(int fd, const char *name)
+{
+    int rc = close(fd);
+
+    if (spoollocktype == DOT_LOCKING)
+       lkclose_dot(fd, name);
+
+    return rc;
 }
 
 }
 
+int
+lkfclosespool(FILE *f, const char *name)
+{
+    int fd, rc;
+
+    if (f == NULL)
+       return 0;
+    
+    fd = fileno(f);
+    rc = fclose(f);
+
+    if (spoollocktype == DOT_LOCKING)
+       lkclose_dot(fd, name);
+
+    return rc;
+}
 
 
-#ifdef KERNEL_LOCKING
 
 /*
 
 /*
- * open and lock a file, using kernel locking
+ * Convert fopen() mode argument to open() bits
  */
 
 static int
  */
 
 static int
-lkopen_kernel (char *file, int access, mode_t mode)
+str2accbits(const char *mode)
 {
 {
-    int fd, i, j;
+    if (strcmp (mode, "r") == 0)
+       return O_RDONLY;
+    else if (strcmp (mode, "r+") == 0)
+       return O_RDWR;
+    else if (strcmp (mode, "w") == 0)
+       return O_WRONLY | O_CREAT | O_TRUNC;
+    else if (strcmp (mode, "w+") == 0)
+       return O_RDWR | O_CREAT | O_TRUNC;
+    else if (strcmp (mode, "a") == 0)
+       return O_WRONLY | O_CREAT | O_APPEND;
+    else if (strcmp (mode, "a+") == 0)
+       return O_RDWR | O_CREAT | O_APPEND;
+    else {
+       errno = EINVAL;
+       return -1;
+    }
+}
 
 
-# ifdef FCNTL_LOCKING
-    struct flock buf;
-# endif /* FCNTL_LOCKING */
+/*
+ * Internal routine to switch between different locking types.
+ */
+
+static int
+lkopen (const char *file, int access, mode_t mode, enum locktype ltype)
+{
+    switch (ltype) {
 
 
-    for (i = 0; i < 5; i++) {
+    case FCNTL_LOCKING:
+       return lkopen_fcntl(file, access, mode);
 
 
-# if defined(LOCKF_LOCKING) || defined(FCNTL_LOCKING)
-       /* remember the original mode */
-       j = access;
+    case DOT_LOCKING:
+       return lkopen_dot(file, access, mode);
 
 
-       /* make sure we open at the beginning */
-       access &= ~O_APPEND;
+#ifdef HAVE_FLOCK
+    case FLOCK_LOCKING:
+       return lkopen_flock(file, access, mode);
+#endif /* HAVE_FLOCK */
 
 
-       /*
-        * We MUST have write permission or
-        * lockf/fcntl() won't work
-        */
-       if ((access & 03) == O_RDONLY) {
-           access &= ~O_RDONLY;
-           access |= O_RDWR;
-       }
-# endif /* LOCKF_LOCKING || FCNTL_LOCKING */
+#ifdef HAVE_LOCKF
+    case LOCKF_LOCKING:
+       return lkopen_lockf(file, access, mode);
+#endif /* HAVE_FLOCK */
 
 
-       if ((fd = open (file, access | O_NDELAY, mode)) == -1)
+    default:
+       adios(NULL, "Internal locking error: unsupported lock type used!");
+    }
+
+    return -1;
+}
+
+
+/*
+ * Routine to clean up the dot locking file
+ */
+
+static void
+lkclose_dot (int fd, const char *file)
+{
+    struct lockinfo lkinfo;
+
+    lockname (file, &lkinfo, 0);       /* get name of lock file */
+#if !defined(HAVE_LIBLOCKFILE)
+    (void) m_unlink (lkinfo.curlock);  /* remove lock file      */
+#else
+    lockfile_remove(lkinfo.curlock);
+#endif /* HAVE_LIBLOCKFILE */
+    timerOFF (fd);                     /* turn off lock timer   */
+}
+
+
+/*
+ * Open and lock a file, using fcntl locking
+ */
+
+static int
+lkopen_fcntl(const char *file, int access, mode_t mode)
+{
+    int fd, i, saved_errno;
+    struct flock flk;
+
+    /*
+     * The assumption here is that if you open the file for writing, you
+     * need an exclusive lock.
+     */
+
+    for (i = 0; i < LOCK_RETRIES; i++) {
+       if ((fd = open(file, access, mode)) == -1)
            return -1;
 
            return -1;
 
-# ifdef FCNTL_LOCKING
-       buf.l_type   = F_WRLCK;
-       buf.l_whence = SEEK_SET;
-       buf.l_start  = 0;
-       buf.l_len    = 0;
-       if (fcntl (fd, F_SETLK, &buf) != -1)
-           return fd;
-# endif
+       flk.l_start = 0;
+       flk.l_len = 0;
+       flk.l_type = (access & O_ACCMODE) == O_RDONLY ? F_RDLCK : F_WRLCK;
+       flk.l_whence = SEEK_SET;
 
 
-# ifdef FLOCK_LOCKING
-       if (flock (fd, LOCK_EX | LOCK_NB) != -1)
+       if (fcntl(fd, F_SETLK, &flk) != -1)
            return fd;
            return fd;
-# endif
 
 
-# ifdef LOCKF_LOCKING
-       if (lockf (fd, F_TLOCK, 0L) != -1) {
-           /* see if we should be at the end */
-           if (j & O_APPEND)
-               lseek (fd, (off_t) 0, SEEK_END);
+       saved_errno = errno;
+       close(fd);
+       sleep(1);
+    }
+
+    errno = saved_errno;
+    return -1;
+}
+
+
+#ifdef HAVE_FLOCK
+/*
+ * Open and lock a file, using flock locking
+ */
+
+static int
+lkopen_flock(const char *file, int access, mode_t mode)
+{
+    int fd, i, saved_errno, locktype;
+
+    /*
+     * The assumption here is that if you open the file for writing, you
+     * need an exclusive lock.
+     */
+
+    locktype = (((access & O_ACCMODE) == O_RDONLY) ? LOCK_SH : LOCK_EX) |
+                                                       LOCK_NB;
+
+    for (i = 0; i < LOCK_RETRIES; i++) {
+       if ((fd = open(file, access, mode)) == -1)
+           return -1;
+
+       if (flock(fd, locktype) != -1)
            return fd;
            return fd;
-       }
-# endif
 
 
-       j = errno;
-       close (fd);
-       sleep (5);
+       saved_errno = errno;
+       close(fd);
+       sleep(1);
     }
 
     }
 
-    close (fd);
-    errno = j;
+    errno = saved_errno;
     return -1;
 }
     return -1;
 }
+#endif /* HAVE_FLOCK */
+
+/*
+ * Open and lock a file, using lockf locking
+ */
+
+static int
+lkopen_lockf(const char *file, int access, mode_t mode)
+{
+    int fd, i, saved_errno, saved_access;
+
+    /*
+     * Two notes:
+     *
+     * Because lockf locks start from the current offset, mask off O_APPEND
+     * and seek to the end of the file later if it was requested.
+     *
+     * lockf locks require write access to the file, so always add it
+     * even if it wasn't requested.
+     */
+
+    saved_access = access;
+
+    access &= ~O_APPEND;
+
+    if ((access & O_ACCMODE) == O_RDONLY) {
+       access &= ~O_RDONLY;
+       access |= O_RDWR;
+    }
+
+    for (i = 0; i < LOCK_RETRIES; i++) {
+       if ((fd = open(file, access, mode)) == -1)
+           return -1;
 
 
-#endif /* KERNEL_LOCKING */
+       if (lockf(fd, F_TLOCK, 0) != -1) {
+           /*
+            * Seek to end if requested
+            */
+           if (saved_access & O_APPEND) {
+               lseek(fd, 0, SEEK_END);
+           }
+           return fd;
+       }
 
 
+       saved_errno = errno;
+       close(fd);
+       sleep(1);
+    }
+
+    errno = saved_errno;
+    return -1;
+}
 
 
-#ifdef DOT_LOCKING
 
 /*
  * open and lock a file, using dot locking
  */
 
 static int
 
 /*
  * open and lock a file, using dot locking
  */
 
 static int
-lkopen_dot (char *file, int access, mode_t mode)
+lkopen_dot (const char *file, int access, mode_t mode)
 {
 {
-    int i, fd;
-    time_t curtime;
+    int fd;
     struct lockinfo lkinfo;
     struct lockinfo lkinfo;
-    struct stat st;
 
     /* open the file */
     if ((fd = open (file, access, mode)) == -1)
 
     /* open the file */
     if ((fd = open (file, access, mode)) == -1)
@@ -325,35 +487,53 @@ lkopen_dot (char *file, int access, mode_t mode)
      */
     lockname (file, &lkinfo, 1);
 
      */
     lockname (file, &lkinfo, 1);
 
-    for (i = 0;;) {
-       /* attempt to create lock file */
-       if (lockit (&lkinfo) == 0) {
-           /* if successful, turn on timer and return */
-           timerON (lkinfo.curlock, fd);
-           return fd;
-       } else {
-           /*
-            * Abort locking, if we fail to lock after 5 attempts
-            * and are never able to stat the lock file.
-            */
-           if (stat (lkinfo.curlock, &st) == -1) {
-               if (i++ > 5)
-                   return -1;
-               sleep (5);
+#if !defined(HAVE_LIBLOCKFILE)
+    {
+       int i;
+       for (i = 0;;) {
+           /* attempt to create lock file */
+           if (lockit (&lkinfo) == 0) {
+               /* if successful, turn on timer and return */
+               timerON (lkinfo.curlock, fd);
+               return fd;
            } else {
            } else {
-               i = 0;
-               time (&curtime);
-
-               /* check for stale lockfile, else sleep */
-               if (curtime > st.st_ctime + RSECS)
-                   unlink (lkinfo.curlock);
-               else
+               /*
+                * Abort locking, if we fail to lock after 5 attempts
+                * and are never able to stat the lock file.
+                */
+               struct stat st;
+               if (stat (lkinfo.curlock, &st) == -1) {
+                   if (i++ > 5)
+                       return -1;
                    sleep (5);
                    sleep (5);
+               } else {
+                   time_t curtime;
+                   i = 0;
+                   time (&curtime);
+                   
+                   /* check for stale lockfile, else sleep */
+                   if (curtime > st.st_ctime + RSECS)
+                       (void) m_unlink (lkinfo.curlock);
+                   else
+                       sleep (5);
+               }
+               lockname (file, &lkinfo, 1);
            }
        }
     }
            }
        }
     }
+#else
+    if (lockfile_create(lkinfo.curlock, 5, 0) == L_SUCCESS) {
+        timerON(lkinfo.curlock, fd);
+        return fd;
+    }
+    else {
+        close(fd);
+        return -1;
+    }
+#endif /* HAVE_LIBLOCKFILE */
 }
 
 }
 
+#if !defined(HAVE_LIBLOCKFILE)
 /*
  * Routine that actually tries to create
  * the lock file.
 /*
  * Routine that actually tries to create
  * the lock file.
@@ -363,18 +543,18 @@ static int
 lockit (struct lockinfo *li)
 {
     int fd;
 lockit (struct lockinfo *li)
 {
     int fd;
-    char *curlock, *tmplock;
+    char *curlock, *tmpfile;
 
 #if 0
     char buffer[128];
 #endif
 
     curlock = li->curlock;
 
 #if 0
     char buffer[128];
 #endif
 
     curlock = li->curlock;
-    tmplock = li->tmplock;
 
 
-    /* create the temporary lock file */
-    if ((fd = creat(tmplock, 0600)) == -1)
+    if ((tmpfile = m_mktemp(li->tmplock, &fd, NULL)) == NULL) {
+        advise(NULL, "unable to create temporary file in %s", get_temp_dir());
        return -1;
        return -1;
+    }
 
 #if 0
     /* write our process id into lock file */
 
 #if 0
     /* write our process id into lock file */
@@ -388,21 +568,23 @@ lockit (struct lockinfo *li)
      * Now try to create the real lock file
      * by linking to the temporary file.
      */
      * Now try to create the real lock file
      * by linking to the temporary file.
      */
-    fd = link(tmplock, curlock);
-    unlink(tmplock);
+    fd = link(tmpfile, curlock);
+    (void) m_unlink(tmpfile);
 
     return (fd == -1 ? -1 : 0);
 }
 
     return (fd == -1 ? -1 : 0);
 }
+#endif /* HAVE_LIBLOCKFILE */
 
 /*
  * Get name of lock file, and temporary lock file
  */
 
 static void
 
 /*
  * Get name of lock file, and temporary lock file
  */
 
 static void
-lockname (char *file, struct lockinfo *li, int isnewlock)
+lockname (const char *file, struct lockinfo *li, int isnewlock)
 {
     int bplen, tmplen;
 {
     int bplen, tmplen;
-    char *bp, *cp;
+    char *bp;
+    const char *cp;
 
 #if 0
     struct stat st;
 
 #if 0
     struct stat st;
@@ -420,7 +602,7 @@ lockname (char *file, struct lockinfo *li, int isnewlock)
     bplen += tmplen;
 #else
     if (cp != file) {
     bplen += tmplen;
 #else
     if (cp != file) {
-       snprintf (bp, sizeof(li->curlock), "%.*s", cp - file, file);
+       snprintf (bp, sizeof(li->curlock), "%.*s", (int)(cp - file), file);
        tmplen = strlen (bp);
        bp    += tmplen;
        bplen += tmplen;
        tmplen = strlen (bp);
        bp    += tmplen;
        bplen += tmplen;
@@ -442,6 +624,7 @@ lockname (char *file, struct lockinfo *li, int isnewlock)
 
     snprintf (bp, sizeof(li->curlock) - bplen, "%s.lock", cp);
 
 
     snprintf (bp, sizeof(li->curlock) - bplen, "%s.lock", cp);
 
+#if !defined(HAVE_LIBLOCKFILE)
     /*
      * If this is for a new lock, create a name for
      * the temporary lock file for lockit()
     /*
      * If this is for a new lock, create a name for
      * the temporary lock file for lockit()
@@ -451,15 +634,9 @@ lockname (char *file, struct lockinfo *li, int isnewlock)
            strncpy (li->tmplock, ",LCK.XXXXXX", sizeof(li->tmplock));
        else
            snprintf (li->tmplock, sizeof(li->tmplock), "%.*s,LCK.XXXXXX",
            strncpy (li->tmplock, ",LCK.XXXXXX", sizeof(li->tmplock));
        else
            snprintf (li->tmplock, sizeof(li->tmplock), "%.*s,LCK.XXXXXX",
-                    cp - li->curlock, li->curlock);
-#ifdef HAVE_MKSTEMP
-       mkstemp (li->tmplock);
-#else
-       mktemp (li->tmplock);
-#endif
-
-       unlink (li->tmplock);   /* remove any stray */
+                    (int)(cp - li->curlock), li->curlock);
     }
     }
+#endif
 }
 
 
 }
 
 
@@ -474,15 +651,11 @@ timerON (char *curlock, int fd)
     struct lock *lp;
     size_t len;
 
     struct lock *lp;
     size_t len;
 
-    if (!(lp = (struct lock *) malloc (sizeof(*lp))))
-       return;
+    lp = (struct lock *) mh_xmalloc (sizeof(*lp));
 
     len = strlen(curlock) + 1;
     lp->l_fd = fd;
 
     len = strlen(curlock) + 1;
     lp->l_fd = fd;
-    if (!(lp->l_lock = malloc (len))) {
-       free ((char *) lp);
-       return;
-    }
+    lp->l_lock = mh_xmalloc (len);
     memcpy (lp->l_lock, curlock, len);
     lp->l_next = l_top;
 
     memcpy (lp->l_lock, curlock, len);
     lp->l_next = l_top;
 
@@ -535,26 +708,58 @@ timerOFF (int fd)
  * lockfiles, so another command doesn't remove them.
  */
 
  * lockfiles, so another command doesn't remove them.
  */
 
-static RETSIGTYPE
+static void
 alrmser (int sig)
 {
 alrmser (int sig)
 {
-    int j;
     char *lockfile;
     struct lock *lp;
     char *lockfile;
     struct lock *lp;
-
-#ifndef        RELIABLE_SIGNALS
-    SIGNAL (SIGALRM, alrmser);
-#endif
+    NMH_UNUSED (sig);
 
     /* update the ctime of all the lock files */
     for (lp = l_top; lp; lp = lp->l_next) {
        lockfile = lp->l_lock;
 
     /* update the ctime of all the lock files */
     for (lp = l_top; lp; lp = lp->l_next) {
        lockfile = lp->l_lock;
-       if (*lockfile && (j = creat (lockfile, 0600)) != -1)
-           close (j);
+#if !defined(HAVE_LIBLOCKFILE)
+       {
+           int j;
+           if (*lockfile && (j = creat (lockfile, 0600)) != -1)
+               close (j);
+       }
+#else
+    lockfile_touch(lockfile);
+#endif
     }
 
     /* restart the alarm */
     alarm (NSECS);
 }
 
     }
 
     /* restart the alarm */
     alarm (NSECS);
 }
 
-#endif /* DOT_LOCKING */
+
+/*
+ * Return a locking algorithm based on the string name
+ */
+
+static enum locktype
+init_locktype(const char *lockname)
+{
+    if (strcasecmp(lockname, "fcntl") == 0) {
+       return FCNTL_LOCKING;
+    } else if (strcasecmp(lockname, "lockf") == 0) {
+#ifdef HAVE_LOCKF
+       return LOCKF_LOCKING;
+#else /* ! HAVE_LOCKF */
+       adios(NULL, "lockf not supported on this system");
+#endif /* HAVE_LOCKF */
+    } else if (strcasecmp(lockname, "flock") == 0) {
+#ifdef HAVE_FLOCK
+       return FLOCK_LOCKING;
+#else /* ! HAVE_FLOCK */
+       adios(NULL, "flock not supported on this system");
+#endif /* HAVE_FLOCK */
+    } else if (strcasecmp(lockname, "dot") == 0) {
+       return DOT_LOCKING;
+    } else {
+       adios(NULL, "Unknown lock type: \"%s\"", lockname);
+       /* NOTREACHED */
+       return 0;
+    }
+}