]> diplodocus.org Git - nmh/blobdiff - sbr/lock_file.c
Fix invalid pointer arithmetic.
[nmh] / sbr / lock_file.c
index 7280464f48435f1936b5dba14d3bd76340969abf..2c8b1c7531ae9ea286de318e1bd52c88d119c894 100644 (file)
@@ -1,8 +1,4 @@
-
-/*
- * lock.c -- routines to lock/unlock files
- *
- * $Id$
+/* lock_file.c -- routines to lock/unlock files
  *
  * This code is Copyright (c) 2002, by the authors of nmh.  See the
  * COPYRIGHT file in the root directory of the nmh distribution for
  
 #include <h/mh.h>
 #include <h/signals.h>
+#include <h/utils.h>
+#include <h/mts.h>
+#include "lock_file.h"
+#include "m_mktemp.h"
 
-#ifdef TIME_WITH_SYS_TIME
+#ifdef HAVE_SYS_TIME_H
 # include <sys/time.h>
-# include <time.h>
-#else
-# ifdef TM_IN_SYS_TIME
-#  include <sys/time.h>
-# else
-#  include <time.h>
-# endif
-#endif
-
-#ifdef HAVE_ERRNO_H
-# include <errno.h>
-#endif
-
-#ifdef MMDFONLY
-# include <mmdfonly.h>
-# include <lockonly.h>
-#endif /* MMDFONLY */
-
-#ifdef HAVE_FCNTL_H
-# include <fcntl.h>
-#else
-# include <sys/file.h>
 #endif
-
-#if defined(LOCKF_LOCKING) || defined(FLOCK_LOCKING)
+#include <time.h>
+#include <fcntl.h>
+#ifdef HAVE_FLOCK
 # include <sys/file.h>
 #endif
 
-#include <signal.h>
-
 #if defined(HAVE_LIBLOCKFILE)
-#include <lockfile.h>
+# include <lockfile.h>
 #endif
 
-extern int errno;
-
 #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];
@@ -77,6 +45,11 @@ struct lockinfo {
 #endif
 };
 
+/*
+ * Number of tries to retry locking
+ */
+#define LOCK_RETRIES 60
+
 /*
  * Amount of time to wait before
  * updating ctime of lock file.
@@ -98,113 +71,122 @@ struct lock {
     struct lock *l_next;
 };
 
+enum locktype { FCNTL_LOCKING, FLOCK_LOCKING, LOCKF_LOCKING, DOT_LOCKING };
+
+/* Our saved lock types. */
+static enum locktype datalocktype, spoollocktype;
+
 /* top of list containing all open locks */
 static struct lock *l_top = NULL;
-#endif /* DOT_LOCKING */
 
-/*
- * static prototypes
- */
-#ifdef KERNEL_LOCKING
-static int lkopen_kernel (char *, int, mode_t);
-#endif
+static int lkopen(const char *, int, mode_t, enum locktype, int *);
+static int str2accbits(const char *);
 
-#ifdef DOT_LOCKING
-static int lkopen_dot (char *, int, mode_t);
-static int lockit (struct lockinfo *);
-static void lockname (char *, struct lockinfo *, int);
+static int lkopen_fcntl (const char *, int, mode_t, int *);
+#ifdef HAVE_LOCKF
+static int lkopen_lockf (const char *, int, mode_t, int *);
+#endif /* HAVE_LOCKF */
+#ifdef HAVE_FLOCK
+static int lkopen_flock (const char *, int, mode_t, int *);
+#endif /* HAVE_FLOCK */
+
+static enum locktype init_locktype(const char *) PURE;
+
+static int lkopen_dot (const char *, int, mode_t, int *);
+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 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
-lkopen (char *file, int access, mode_t mode)
+lkopendata(const char *file, int access, mode_t mode, int *failed_to_lock)
 {
-#ifdef KERNEL_LOCKING
-    return lkopen_kernel(file, access, mode);
-#endif
+    static bool deja_vu;
 
-#ifdef DOT_LOCKING
-    return lkopen_dot(file, access, mode);
-#endif
+    if (!deja_vu) {
+        char *dl;
+
+        deja_vu = true;
+       if ((dl = context_find("datalocking"))) {
+           datalocktype = init_locktype(dl);
+       } else {
+           /* We default to fcntl locking for data files */
+           datalocktype = FCNTL_LOCKING;
+       }
+    }
+
+    return lkopen(file, access, mode, datalocktype, failed_to_lock);
 }
 
 
 /*
- * 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, int *failed_to_lock)
 {
-#ifdef FCNTL_LOCKING
-    struct flock buf;
-#endif
+    static bool deja_vu;
 
-#ifdef DOT_LOCKING
-    struct lockinfo lkinfo;
-#endif
+    if (!deja_vu) {
+       deja_vu = true;
+        spoollocktype = init_locktype(spoollocking);
+    }
 
-    if (fd == -1)
-       return 0;
+    return lkopen(file, access, mode, spoollocktype, failed_to_lock);
+}
 
-#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, int *failed_to_lock)
+{
+    FILE *fp;
+    int oflags = str2accbits(mode);
+    int fd;
 
-#ifdef DOT_LOCKING
-    lockname (file, &lkinfo, 0);       /* get name of lock file */
-#if !defined(HAVE_LIBLOCKFILE)
-    unlink (lkinfo.curlock);           /* remove lock file      */
-#else
-    lockfile_remove(lkinfo.curlock);
-#endif /* HAVE_LIBLOCKFILE */
-    timerOFF (fd);                     /* turn off lock timer   */
-#endif /* DOT_LOCKING */
+    if (oflags == -1) {
+       errno = EINVAL;
+       return NULL;
+    }
 
-    return (close (fd));
-}
+    if ((fd = lkopendata(file, oflags, 0666, failed_to_lock)) == -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 *
-lkfopen (char *file, char *mode)
+lkfopenspool(const char *file, const char *mode)
 {
-    int fd, access;
     FILE *fp;
+    int oflags = str2accbits(mode);
+    int failed_to_lock = 0;
+    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, &failed_to_lock)) == -1)
        return NULL;
 
     if ((fp = fdopen (fd, mode)) == NULL) {
@@ -217,142 +199,283 @@ 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
-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);
+
+    if (datalocktype == DOT_LOCKING)
+       lkclose_dot(fd, name);
+
+    return rc;
+}
+
+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;
+}
+
+
+/*
+ * Convert fopen() mode argument to open() bits
+ */
+
+static int
+str2accbits(const char *mode)
+{
+    if (strcmp (mode, "r") == 0)
+       return O_RDONLY;
+    if (strcmp (mode, "r+") == 0)
+       return O_RDWR;
+    if (strcmp (mode, "w") == 0)
+       return O_WRONLY | O_CREAT | O_TRUNC;
+    if (strcmp (mode, "w+") == 0)
+       return O_RDWR | O_CREAT | O_TRUNC;
+    if (strcmp (mode, "a") == 0)
+       return O_WRONLY | O_CREAT | O_APPEND;
+    if (strcmp (mode, "a+") == 0)
+       return O_RDWR | O_CREAT | O_APPEND;
+
+    errno = EINVAL;
+    return -1;
+}
+
+/*
+ * Internal routine to switch between different locking types.
+ */
+
+static int
+lkopen (const char *file, int access, mode_t mode, enum locktype ltype,
+        int *failed_to_lock)
+{
+    switch (ltype) {
+
+    case FCNTL_LOCKING:
+       return lkopen_fcntl(file, access, mode, failed_to_lock);
+
+    case DOT_LOCKING:
+       return lkopen_dot(file, access, mode, failed_to_lock);
+
+#ifdef HAVE_FLOCK
+    case FLOCK_LOCKING:
+       return lkopen_flock(file, access, mode, failed_to_lock);
+#endif /* HAVE_FLOCK */
+
+#ifdef HAVE_LOCKF
+    case LOCKF_LOCKING:
+       return lkopen_lockf(file, access, mode, failed_to_lock);
+#endif /* HAVE_FLOCK */
+
+    default:
+       adios(NULL, "Internal locking error: unsupported lock type used!");
+    }
+
+    return -1;
+}
 
-#ifdef LOCKF_LOCKING
-    /* make sure we unlock the whole thing */
-    fseek (fp, 0L, SEEK_SET);
-    lockf (fileno(fp), F_ULOCK, 0L);
-#endif
 
-#ifdef DOT_LOCKING
+/*
+ * 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)
-    unlink (lkinfo.curlock);           /* remove lock file      */
+    (void) m_unlink (lkinfo.curlock);  /* remove lock file      */
 #else
     lockfile_remove(lkinfo.curlock);
 #endif /* HAVE_LIBLOCKFILE */
-    timerOFF (fileno(fp));             /* turn off lock timer   */
-#endif /* DOT_LOCKING */
-
-    return (fclose (fp));
+    timerOFF (fd);                     /* turn off lock timer   */
 }
 
 
-#ifdef KERNEL_LOCKING
-
 /*
- * open and lock a file, using kernel locking
+ * Open and lock a file, using fcntl locking
  */
 
 static int
-lkopen_kernel (char *file, int access, mode_t mode)
+lkopen_fcntl(const char *file, int access, mode_t mode, int *failed_to_lock)
 {
-    int fd, i, j;
+    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;
 
-# ifdef FCNTL_LOCKING
-    struct flock buf;
-# endif /* FCNTL_LOCKING */
+       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;
 
-    for (i = 0; i < 5; i++) {
+       if (fcntl(fd, F_SETLK, &flk) != -1)
+           return fd;
 
-# if defined(LOCKF_LOCKING) || defined(FCNTL_LOCKING)
-       /* remember the original mode */
-       j = access;
+       saved_errno = errno;
+       close(fd);
+       sleep(1);
+    }
 
-       /* make sure we open at the beginning */
-       access &= ~O_APPEND;
+    *failed_to_lock = 1;
+    errno = saved_errno;
+    return -1;
+}
 
-       /*
-        * 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 */
 
-       if ((fd = open (file, access | O_NDELAY, mode)) == -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 *failed_to_lock)
+{
+    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;
 
-# 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)
+       if (flock(fd, locktype) != -1)
            return fd;
-# endif
 
-# ifdef FLOCK_LOCKING
-       if (flock (fd, LOCK_EX | LOCK_NB) != -1)
-           return fd;
-# endif
+       saved_errno = errno;
+       close(fd);
+       sleep(1);
+    }
+
+    *failed_to_lock = 1;
+    errno = saved_errno;
+    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 *failed_to_lock)
+{
+    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;
 
-# 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);
+       if (lockf(fd, F_TLOCK, 0) != -1) {
+           /*
+            * Seek to end if requested
+            */
+           if (saved_access & O_APPEND) {
+               lseek(fd, 0, SEEK_END);
+           }
            return fd;
        }
-# endif
 
-       j = errno;
-       close (fd);
-       sleep (5);
+       saved_errno = errno;
+       close(fd);
+       sleep(1);
     }
 
-    close (fd);
-    errno = j;
+    *failed_to_lock = 1;
+    errno = saved_errno;
     return -1;
 }
 
-#endif /* KERNEL_LOCKING */
-
-
-#ifdef DOT_LOCKING
 
 /*
  * 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 *failed_to_lock)
 {
-    int i, fd;
-    time_t curtime;
+    int fd;
     struct lockinfo lkinfo;
-    struct stat st;
 
     /* open the file */
     if ((fd = open (file, access, mode)) == -1)
@@ -365,42 +488,53 @@ lkopen_dot (char *file, int access, mode_t mode)
     lockname (file, &lkinfo, 1);
 
 #if !defined(HAVE_LIBLOCKFILE)
-    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);
-           } else {
-               i = 0;
-               time (&curtime);
-
-               /* check for stale lockfile, else sleep */
-               if (curtime > st.st_ctime + RSECS)
-                   unlink (lkinfo.curlock);
-               else
-                   sleep (5);
+    {
+       int i;
+       for (i = 0; i < LOCK_RETRIES; ++i) {
+            struct stat st;
+
+           /* attempt to create lock file */
+           if (lockit (&lkinfo) == 0) {
+               /* if successful, turn on timer and return */
+               timerON (lkinfo.curlock, fd);
+               return fd;
            }
+
+            /*
+             * Abort locking, if we fail to lock after 5 attempts
+             * and are never able to stat the lock file.  Or, if
+             * we can stat the lockfile but exceed LOCK_RETRIES
+             * seconds waiting for it (by falling out of the loop).
+             */
+            if (stat (lkinfo.curlock, &st) == -1) {
+                if (i++ > 5) break;
+                sleep (1);
+            } else {
+                time_t curtime;
+                time (&curtime);
+                
+                /* check for stale lockfile, else sleep */
+                if (curtime > st.st_ctime + RSECS)
+                    (void) m_unlink (lkinfo.curlock);
+                else
+                    sleep (1);
+            }
+            lockname (file, &lkinfo, 1);
        }
+
+        close(fd);
+        *failed_to_lock = 1;
+        return -1;
     }
 #else
     if (lockfile_create(lkinfo.curlock, 5, 0) == L_SUCCESS) {
         timerON(lkinfo.curlock, fd);
         return fd;
     }
-    else {
-        close(fd);
-        return -1;
-    }
+
+    close(fd);
+    *failed_to_lock = 1;
+    return -1;
 #endif /* HAVE_LIBLOCKFILE */
 }
 
@@ -414,27 +548,18 @@ static int
 lockit (struct lockinfo *li)
 {
     int fd;
-    char *curlock, *tmplock;
+    char *curlock, *tmpfile;
 
 #if 0
     char buffer[128];
 #endif
 
     curlock = li->curlock;
-    tmplock = li->tmplock;
 
-#ifdef HAVE_MKSTEMP
-    if ((fd = mkstemp(tmplock)) == -1)
-       return -1;
-#else
-    if (mktemp(tmplock) == NULL)
+    if ((tmpfile = m_mktemp(li->tmplock, &fd, NULL)) == NULL) {
+        inform("unable to create temporary file in %s", li->tmplock);
        return -1;
-    if (unlink(tmplock) == -1 && errno != ENOENT)
-       return -1;
-    /* create the temporary lock file */
-    if ((fd = creat(tmplock, 0600)) == -1)
-       return -1;
-#endif
+    }
 
 #if 0
     /* write our process id into lock file */
@@ -448,10 +573,10 @@ lockit (struct lockinfo *li)
      * 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 */
 
@@ -460,10 +585,11 @@ lockit (struct lockinfo *li)
  */
 
 static void
-lockname (char *file, struct lockinfo *li, int isnewlock)
+lockname (const char *file, struct lockinfo *li, int isnewlock)
 {
     int bplen, tmplen;
-    char *bp, *cp;
+    char *bp;
+    const char *cp;
 
 #if 0
     struct stat st;
@@ -481,7 +607,7 @@ lockname (char *file, struct lockinfo *li, int isnewlock)
     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;
@@ -503,7 +629,9 @@ lockname (char *file, struct lockinfo *li, int isnewlock)
 
     snprintf (bp, sizeof(li->curlock) - bplen, "%s.lock", cp);
 
-#if !defined(HAVE_LIBLOCKFILE)
+#if defined(HAVE_LIBLOCKFILE)
+    NMH_UNUSED(isnewlock);
+#else
     /*
      * If this is for a new lock, create a name for
      * the temporary lock file for lockit()
@@ -513,7 +641,7 @@ 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",
-                    cp - li->curlock, li->curlock);
+                    (int)(cp - li->curlock), li->curlock);
     }
 #endif
 }
@@ -528,18 +656,10 @@ static void
 timerON (char *curlock, int fd)
 {
     struct lock *lp;
-    size_t len;
 
-    if (!(lp = (struct lock *) malloc (sizeof(*lp))))
-       return;
-
-    len = strlen(curlock) + 1;
+    NEW(lp);
+    lp->l_lock = mh_xstrdup(curlock);
     lp->l_fd = fd;
-    if (!(lp->l_lock = malloc (len))) {
-       free ((char *) lp);
-       return;
-    }
-    memcpy (lp->l_lock, curlock, len);
     lp->l_next = l_top;
 
     if (!l_top) {
@@ -547,7 +667,6 @@ timerON (char *curlock, int fd)
        SIGNAL (SIGALRM, alrmser);
        alarm (NSECS);
     }
-
     l_top = lp;
 }
 
@@ -591,23 +710,22 @@ timerOFF (int fd)
  * lockfiles, so another command doesn't remove them.
  */
 
-static RETSIGTYPE
+static void
 alrmser (int sig)
 {
-    int j;
     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;
 #if !defined(HAVE_LIBLOCKFILE)
-       if (*lockfile && (j = creat (lockfile, 0600)) != -1)
-           close (j);
+       {
+           int j;
+           if (*lockfile && (j = creat (lockfile, 0600)) != -1)
+               close (j);
+       }
 #else
     lockfile_touch(lockfile);
 #endif
@@ -617,4 +735,35 @@ alrmser (int sig)
     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;
+    }
+    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 */
+    }
+    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 */
+    }
+    if (strcasecmp(lockname, "dot") == 0) {
+       return DOT_LOCKING;
+    }
+    adios(NULL, "Unknown lock type: \"%s\"", lockname);
+    /* NOTREACHED */
+    return 0;
+}