mutt_*mktemp--
[apps/madmutt.git] / dotlock.c
index eb799d5..abf92f0 100644 (file)
--- a/dotlock.c
+++ b/dotlock.c
@@ -1,67 +1,27 @@
 /*
+ * Copyright notice from original mutt:
  * Copyright (C) 1996-2000 Michael R. Elkins <me@mutt.org>
  * Copyright (C) 1998-2000 Thomas Roessler <roessler@does-not-exist.org>
- * 
- *     This program is free software; you can redistribute it and/or modify
- *     it under the terms of the GNU General Public License as published by
- *     the Free Software Foundation; either version 2 of the License, or
- *     (at your option) any later version.
- * 
- *     This program is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- * 
- *     You should have received a copy of the GNU General Public License
- *     along with this program; if not, write to the Free Software
- *     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
- */ 
-
-/*
- * This module either be compiled into Mutt, or it can be
- * built as a separate program. For building it
- * separately, define the DL_STANDALONE preprocessor
- * macro.
+ *
+ * This file is part of mutt-ng, see http://www.muttng.org/.
+ * It's licensed under the GNU General Public License,
+ * please see the file GPL in the top level source directory.
  */
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
+#include <lib-lib/lib-lib.h>
 
-#include <unistd.h>
-#include <dirent.h>
-#include <sys/file.h>
-#include <sys/stat.h>
 #include <sys/utsname.h>
-#include <errno.h>
-#include <time.h>
-#include <fcntl.h>
-#include <limits.h>
-
-#ifndef _POSIX_PATH_MAX
-#include <posix1_lim.h>
-#endif
-
 #include "dotlock.h"
-#include "config.h"
 
 #ifdef HAVE_GETOPT_H
 #include <getopt.h>
 #endif
 
-#ifdef DL_STANDALONE
-# include "reldate.h"
-#endif
-
-#define MAXLINKS 1024 /* maximum link depth */
-
-#ifdef DL_STANDALONE
+#define MAXLINKS 1024           /* maximum link depth */
 
 # define LONG_STRING 1024
 # define MAXLOCKATTEMPT 5
 
-# define strfcpy(A,B,C) strncpy (A,B,C), *(A+(C)-1)=0
-
 # ifdef USE_SETGID
 
 #  ifdef HAVE_SETEGID
 
 # endif
 
-# ifndef HAVE_SNPRINTF
-extern int snprintf (char *, size_t, const char *, ...);
-# endif
-
-#else  /* DL_STANDALONE */
-
-# ifdef USE_SETGID
-#   error Do not try to compile dotlock as a mutt module when requiring egid switching!
-# endif
-
-# include "mutt.h"
-# include "mx.h"
-
-#endif /* DL_STANDALONE */
-
 static int DotlockFlags;
 static int Retry = MAXLOCKATTEMPT;
 
-#ifdef DL_STANDALONE
 static char *Hostname;
-#endif
 
 #ifdef USE_SETGID
 static gid_t UserGid;
@@ -103,14 +46,12 @@ static gid_t MailGid;
 #endif
 
 static int dotlock_deference_symlink (char *, size_t, const char *);
-static int dotlock_prepare (char *, size_t, const char *, int fd);
+static int dotlock_prepare (char *, ssize_t, const char *, int fd);
 static int dotlock_check_stats (struct stat *, struct stat *);
 static int dotlock_dispatch (const char *, int fd);
 
-#ifdef DL_STANDALONE
 static int dotlock_init_privs (void);
 static void usage (const char *);
-#endif
 
 static void dotlock_expand_link (char *, const char *, const char *);
 static void BEGIN_PRIVILEGED (void);
@@ -127,8 +68,6 @@ static int dotlock_unlink (const char *);
 static int dotlock_lock (const char *);
 
 
-#ifdef DL_STANDALONE
-
 #define check_flags(a) if (a & DL_FL_ACTIONS) usage (argv[0])
 
 int main (int argc, char **argv)
@@ -138,15 +77,15 @@ int main (int argc, char **argv)
   struct utsname utsname;
 
   /* first, drop privileges */
-  
+
   if (dotlock_init_privs () == -1)
     return DL_EX_ERROR;
 
 
   /* determine the system's host name */
-  
+
   uname (&utsname);
-  if (!(Hostname = strdup (utsname.nodename))) /* __MEM_CHECKED__ */
+  if (!(Hostname = strdup (utsname.nodename)))  /* __MEM_CHECKED__ */
     return DL_EX_ERROR;
   if ((p = strchr (Hostname, '.')))
     *p = '\0';
@@ -154,22 +93,37 @@ int main (int argc, char **argv)
 
   /* parse the command line options. */
   DotlockFlags = 0;
-  
-  while ((i = getopt (argc, argv, "dtfupr:")) != EOF)
-  {
-    switch (i)
-    {
+
+  while ((i = getopt (argc, argv, "dtfupr:")) != EOF) {
+    switch (i) {
       /* actions, mutually exclusive */
-      case 't': check_flags (DotlockFlags); DotlockFlags |= DL_FL_TRY; break;
-      case 'd': check_flags (DotlockFlags); DotlockFlags |= DL_FL_UNLINK; break;
-      case 'u': check_flags (DotlockFlags); DotlockFlags |= DL_FL_UNLOCK; break;
+    case 't':
+      check_flags (DotlockFlags);
+      DotlockFlags |= DL_FL_TRY;
+      break;
+    case 'd':
+      check_flags (DotlockFlags);
+      DotlockFlags |= DL_FL_UNLINK;
+      break;
+    case 'u':
+      check_flags (DotlockFlags);
+      DotlockFlags |= DL_FL_UNLOCK;
+      break;
 
       /* other flags */
-      case 'f': DotlockFlags |= DL_FL_FORCE; break;
-      case 'p': DotlockFlags |= DL_FL_USEPRIV; break;
-      case 'r': DotlockFlags |= DL_FL_RETRY; Retry = atoi (optarg); break;
-      
-      default: usage (argv[0]);
+    case 'f':
+      DotlockFlags |= DL_FL_FORCE;
+      break;
+    case 'p':
+      DotlockFlags |= DL_FL_USEPRIV;
+      break;
+    case 'r':
+      DotlockFlags |= DL_FL_RETRY;
+      Retry = atoi (optarg);
+      break;
+
+    default:
+      usage (argv[0]);
     }
   }
 
@@ -192,12 +146,11 @@ int main (int argc, char **argv)
  */
 
 
-static int
-dotlock_init_privs (void)
+static int dotlock_init_privs (void)
 {
 
 # ifdef USE_SETGID
-  
+
   UserGid = getgid ();
   MailGid = getegid ();
 
@@ -208,44 +161,11 @@ dotlock_init_privs (void)
 
   return 0;
 }
-  
-
-#else  /* DL_STANDALONE */
-
-/* 
- * This function is intended to be invoked from within
- * mutt instead of mx.c's invoke_dotlock ().
- */
-
-int dotlock_invoke (const char *path, int fd, int flags, int retry)
-{
-  int currdir;
-  int r;
-
-  DotlockFlags = flags;
-  
-  if ((currdir = open (".", O_RDONLY)) == -1)
-    return DL_EX_ERROR;
-
-  if (!(DotlockFlags & DL_FL_RETRY) || retry)
-    Retry = MAXLOCKATTEMPT;
-  else
-    Retry = 0;
-  
-  r = dotlock_dispatch (path, fd);
-  
-  fchdir (currdir);
-  close (currdir);
-  
-  return r;
-}
-
-#endif  /* DL_STANDALONE */
 
 
 static int dotlock_dispatch (const char *f, int fd)
 {
-  char realpath[_POSIX_PATH_MAX];
+  char frealpath[_POSIX_PATH_MAX];
 
   /* If dotlock_prepare () succeeds [return value == 0],
    * realpath contains the basename of f, and we have
@@ -258,7 +178,7 @@ static int dotlock_dispatch (const char *f, int fd)
    * lengthy comment below.
    */
 
-  if (dotlock_prepare (realpath, sizeof (realpath), f, fd) != 0)
+  if (dotlock_prepare (frealpath, sizeof (frealpath), f, fd) != 0)
     return DL_EX_ERROR;
 
   /* Actually perform the locking operation. */
@@ -266,14 +186,14 @@ static int dotlock_dispatch (const char *f, int fd)
   if (DotlockFlags & DL_FL_TRY)
     return dotlock_try ();
   else if (DotlockFlags & DL_FL_UNLOCK)
-    return dotlock_unlock (realpath);
+    return dotlock_unlock (frealpath);
   else if (DotlockFlags & DL_FL_UNLINK)
-    return dotlock_unlink (realpath);
-  else /* lock */
-    return dotlock_lock (realpath);
+    return dotlock_unlink (frealpath);
+  else                          /* lock */
+    return dotlock_lock (frealpath);
 }
 
-  
+
 /*
  * Get privileges 
  * 
@@ -285,14 +205,11 @@ static int dotlock_dispatch (const char *f, int fd)
  * 
  */
 
-static void
-BEGIN_PRIVILEGED (void)
+static void BEGIN_PRIVILEGED (void)
 {
 #ifdef USE_SETGID
-  if (DotlockFlags & DL_FL_USEPRIV)
-  {
-    if (SETEGID (MailGid) != 0)
-    {
+  if (DotlockFlags & DL_FL_USEPRIV) {
+    if (SETEGID (MailGid) != 0) {
       /* perror ("setegid"); */
       exit (DL_EX_ERROR);
     }
@@ -309,14 +226,11 @@ BEGIN_PRIVILEGED (void)
  *
  */
 
-static void
-END_PRIVILEGED (void)
+static void END_PRIVILEGED (void)
 {
 #ifdef USE_SETGID
-  if (DotlockFlags & DL_FL_USEPRIV)
-  {
-    if (SETEGID (UserGid) != 0)
-    {
+  if (DotlockFlags & DL_FL_USEPRIV) {
+    if (SETEGID (UserGid) != 0) {
       /* perror ("setegid"); */
       exit (DL_EX_ERROR);
     }
@@ -324,8 +238,6 @@ END_PRIVILEGED (void)
 #endif
 }
 
-#ifdef DL_STANDALONE
-
 /*
  * Usage information.
  * 
@@ -333,30 +245,23 @@ END_PRIVILEGED (void)
  * 
  */
 
-static void 
-usage (const char *av0)
+static void usage (const char *av0)
 {
-  fprintf (stderr, "dotlock [Mutt %s (%s)]\n", VERSION, ReleaseDate);
-  fprintf (stderr, "usage: %s [-t|-f|-u|-d] [-p] [-r <retries>] file\n",
-         av0);
+  fprintf (stderr, "dotlock [Madmutt %s]\n", VERSION);
+  fprintf (stderr, "usage: %s [-t|-f|-u|-d] [-p] [-r <retries>] file\n", av0);
 
   fputs ("\noptions:"
-       "\n  -t\t\ttry"
-       "\n  -f\t\tforce"
-       "\n  -u\t\tunlock"
-       "\n  -d\t\tunlink"
-       "\n  -p\t\tprivileged"
+         "\n  -t\t\ttry"
+         "\n  -f\t\tforce"
+         "\n  -u\t\tunlock" "\n  -d\t\tunlink" "\n  -p\t\tprivileged"
 #ifndef USE_SETGID
-       " (ignored)"
+         " (ignored)"
 #endif
-       "\n  -r <retries>\tRetry locking"
-       "\n", stderr);
-  
+         "\n  -r <retries>\tRetry locking" "\n", stderr);
+
   exit (DL_EX_ERROR);
 }
 
-#endif
-
 /*
  * Access checking: Let's avoid to lock other users' mail
  * spool files if we aren't permitted to read them.
@@ -405,8 +310,7 @@ usage (const char *av0)
  * tlr, Jul 15 1998
  */
 
-static int
-dotlock_check_stats (struct stat *fsb, struct stat *lsb)
+static int dotlock_check_stats (struct stat *fsb, struct stat *lsb)
 {
   /* S_ISLNK (fsb->st_mode) should actually be impossible,
    * but we may have mixed up the parameters somewhere.
@@ -415,70 +319,65 @@ dotlock_check_stats (struct stat *fsb, struct stat *lsb)
 
   if (S_ISLNK (lsb->st_mode) || S_ISLNK (fsb->st_mode))
     return -1;
-  
+
   if ((lsb->st_dev != fsb->st_dev) ||
-     (lsb->st_ino != fsb->st_ino) ||
-     (lsb->st_mode != fsb->st_mode) ||
-     (lsb->st_nlink != fsb->st_nlink) ||
-     (lsb->st_uid != fsb->st_uid) ||
-     (lsb->st_gid != fsb->st_gid) ||
-     (lsb->st_rdev != fsb->st_rdev) ||
-     (lsb->st_size != fsb->st_size))
-  {
+      (lsb->st_ino != fsb->st_ino) ||
+      (lsb->st_mode != fsb->st_mode) ||
+      (lsb->st_nlink != fsb->st_nlink) ||
+      (lsb->st_uid != fsb->st_uid) ||
+      (lsb->st_gid != fsb->st_gid) ||
+      (lsb->st_rdev != fsb->st_rdev) || (lsb->st_size != fsb->st_size)) {
     /* something's fishy */
     return -1;
   }
-  
+
   return 0;
 }
 
-static int
-dotlock_prepare (char *bn, size_t l, const char *f, int _fd)
+static int dotlock_prepare (char *bn, ssize_t l, const char *f, int _fd)
 {
   struct stat fsb, lsb;
-  char realpath[_POSIX_PATH_MAX];
-  char *basename, *dirname;
+  char frealpath[_POSIX_PATH_MAX];
+  char *fbasename, *dirname;
   char *p;
   int fd;
   int r;
-  
-  if (dotlock_deference_symlink (realpath, sizeof (realpath), f) == -1)
+
+  if (dotlock_deference_symlink (frealpath, sizeof (frealpath), f) == -1)
     return -1;
-  
-  if ((p = strrchr (realpath, '/')))
-  {
+
+  if ((p = strrchr (frealpath, '/'))) {
     *p = '\0';
-    basename = p + 1;
-    dirname = realpath;
+    fbasename = p + 1;
+    dirname = frealpath;
   }
-  else
-  {
-    basename = realpath;
-    dirname = ".";
+  else {
+    fbasename = frealpath;
+    dirname = m_strdup(".");
   }
 
-  if (strlen (basename) + 1 > l)
+  if (m_strlen(fbasename) + 1 > l)
     return -1;
-  
-  strfcpy (bn, basename, l);
-  
+
+  m_strcpy(bn, l, fbasename);
+
   if (chdir (dirname) == -1)
     return -1;
 
   if (_fd != -1)
     fd = _fd;
-  else if ((fd = open (basename, O_RDONLY)) == -1)
+  else if ((fd = open (fbasename, O_RDONLY)) == -1)
     return -1;
-  
+
   r = fstat (fd, &fsb);
-  
+
   if (_fd == -1)
     close (fd);
-  
+
   if (r == -1)
     return -1;
-  
-  if (lstat (basename, &lsb) == -1)
+
+  if (lstat (fbasename, &lsb) == -1)
     return -1;
 
   if (dotlock_check_stats (&fsb, &lsb) == -1)
@@ -495,29 +394,27 @@ dotlock_prepare (char *bn, size_t l, const char *f, int _fd)
  *
  */
 
-static void 
-dotlock_expand_link (char *newpath, const char *path, const char *link)
+static void
+dotlock_expand_link (char *newpath, const char *path, const char *flink)
 {
   const char *lb = NULL;
   size_t len;
 
   /* link is full path */
-  if (*link == '/')
-  {
-    strfcpy (newpath, link, _POSIX_PATH_MAX);
+  if (*flink == '/') {
+    m_strcpy(newpath, _POSIX_PATH_MAX, flink);
     return;
   }
 
-  if ((lb = strrchr (path, '/')) == NULL)
-  {
+  if ((lb = strrchr (path, '/')) == NULL) {
     /* no path in link */
-    strfcpy (newpath, link, _POSIX_PATH_MAX);
+    m_strcpy(newpath, _POSIX_PATH_MAX, flink);
     return;
   }
 
   len = lb - path + 1;
   memcpy (newpath, path, len);
-  strfcpy (newpath + len, link, _POSIX_PATH_MAX - len);
+  m_strcpy(newpath + len, _POSIX_PATH_MAX - len, flink);
 }
 
 
@@ -528,44 +425,39 @@ dotlock_expand_link (char *newpath, const char *path, const char *link)
  *
  */
 
-static int
-dotlock_deference_symlink (char *d, size_t l, const char *path)
+static int dotlock_deference_symlink (char *d, size_t l, const char *path)
 {
   struct stat sb;
-  char realpath[_POSIX_PATH_MAX];
+  char frealpath[_POSIX_PATH_MAX];
   const char *pathptr = path;
   int count = 0;
-  
-  while (count++ < MAXLINKS)
-  {
-    if (lstat (pathptr, &sb) == -1)
-    {
+
+  while (count++ < MAXLINKS) {
+    if (lstat (pathptr, &sb) == -1) {
       /* perror (pathptr); */
       return -1;
     }
-    
-    if (S_ISLNK (sb.st_mode))
-    {
+
+    if (S_ISLNK (sb.st_mode)) {
       char linkfile[_POSIX_PATH_MAX];
       char linkpath[_POSIX_PATH_MAX];
       int len;
 
-      if ((len = readlink (pathptr, linkfile, sizeof (linkfile))) == -1)
-      {
-       /* perror (pathptr); */
-       return -1;
+      if ((len = readlink (pathptr, linkfile, sizeof (linkfile))) == -1) {
+        /* perror (pathptr); */
+        return -1;
       }
-      
+
       linkfile[len] = '\0';
       dotlock_expand_link (linkpath, pathptr, linkfile);
-      strfcpy (realpath, linkpath, sizeof (realpath));
-      pathptr = realpath;
+      m_strcpy(frealpath, sizeof(frealpath), linkpath);
+      pathptr = frealpath;
     }
     else
       break;
   }
 
-  strfcpy (d, pathptr, l);
+  m_strcpy(d, l, pathptr);
   return 0;
 }
 
@@ -580,56 +472,51 @@ dotlock_deference_symlink (char *d, size_t l, const char *path)
 
 #define HARDMAXATTEMPTS 10
 
-static int
-dotlock_lock (const char *realpath)
+static int dotlock_lock (const char *frealpath)
 {
   char lockfile[_POSIX_PATH_MAX + LONG_STRING];
   char nfslockfile[_POSIX_PATH_MAX + LONG_STRING];
-  size_t prev_size = 0;
+  ssize_t prev_size = 0;
   int fd;
   int count = 0;
   int hard_count = 0;
   struct stat sb;
   time_t t;
-  
+
   snprintf (nfslockfile, sizeof (nfslockfile), "%s.%s.%d",
-          realpath, Hostname, (int) getpid ());
-  snprintf (lockfile, sizeof (lockfile), "%s.lock", realpath);
+            frealpath, Hostname, (int) getpid ());
+  snprintf (lockfile, sizeof (lockfile), "%s.lock", frealpath);
+
 
-  
   BEGIN_PRIVILEGED ();
 
   unlink (nfslockfile);
 
-  while ((fd = open (nfslockfile, O_WRONLY | O_EXCL | O_CREAT, 0)) < 0)
-  {
+  while ((fd = open (nfslockfile, O_WRONLY | O_EXCL | O_CREAT, 0)) < 0) {
     END_PRIVILEGED ();
 
-  
-    if (errno != EAGAIN)
-    {
+
+    if (errno != EAGAIN) {
       /* perror ("cannot open NFS lock file"); */
       return DL_EX_ERROR;
     }
 
-    
+
     BEGIN_PRIVILEGED ();
   }
 
   END_PRIVILEGED ();
 
-  
+
   close (fd);
-  
-  while (hard_count++ < HARDMAXATTEMPTS)
-  {
+
+  while (hard_count++ < HARDMAXATTEMPTS) {
 
     BEGIN_PRIVILEGED ();
     link (nfslockfile, lockfile);
     END_PRIVILEGED ();
 
-    if (stat (nfslockfile, &sb) != 0)
-    {
+    if (stat (nfslockfile, &sb) != 0) {
       /* perror ("stat"); */
       return DL_EX_ERROR;
     }
@@ -640,32 +527,29 @@ dotlock_lock (const char *realpath)
     if (count == 0)
       prev_size = sb.st_size;
 
-    if (prev_size == sb.st_size && ++count > Retry)
-    {
-      if (DotlockFlags & DL_FL_FORCE)
-      {
-       BEGIN_PRIVILEGED ();
-       unlink (lockfile);
-       END_PRIVILEGED ();
+    if (prev_size == sb.st_size && ++count > Retry) {
+      if (DotlockFlags & DL_FL_FORCE) {
+        BEGIN_PRIVILEGED ();
+        unlink (lockfile);
+        END_PRIVILEGED ();
 
-       count = 0;
-       continue;
+        count = 0;
+        continue;
       }
-      else
-      {
-       BEGIN_PRIVILEGED ();
-       unlink (nfslockfile);
-       END_PRIVILEGED ();
-       return DL_EX_EXIST;
+      else {
+        BEGIN_PRIVILEGED ();
+        unlink (nfslockfile);
+        END_PRIVILEGED ();
+        return DL_EX_EXIST;
       }
     }
-    
+
     prev_size = sb.st_size;
-    
+
     /* don't trust sleep (3) as it may be interrupted
      * by users sending signals. 
      */
-    
+
     t = time (NULL);
     do {
       sleep (1);
@@ -687,42 +571,39 @@ dotlock_lock (const char *realpath)
  * 
  */
 
-static int
-dotlock_unlock (const char *realpath)
+static int dotlock_unlock (const char *frealpath)
 {
   char lockfile[_POSIX_PATH_MAX + LONG_STRING];
   int i;
 
-  snprintf (lockfile, sizeof (lockfile), "%s.lock",
-          realpath);
-  
+  snprintf (lockfile, sizeof (lockfile), "%s.lock", frealpath);
+
   BEGIN_PRIVILEGED ();
   i = unlink (lockfile);
   END_PRIVILEGED ();
-  
+
   if (i == -1)
     return DL_EX_ERROR;
-  
+
   return DL_EX_OK;
 }
 
 /* remove an empty file */
 
-static int
-dotlock_unlink (const char *realpath)
+static int dotlock_unlink (const char *frealpath)
 {
   struct stat lsb;
   int i = -1;
 
-  if (dotlock_lock (realpath) != DL_EX_OK)
+  if (dotlock_lock (frealpath) != DL_EX_OK)
     return DL_EX_ERROR;
 
-  if ((i = lstat (realpath, &lsb)) == 0 && lsb.st_size == 0)
-    unlink (realpath);
+  if ((i = lstat (frealpath, &lsb)) == 0 && lsb.st_size == 0)
+    unlink (frealpath);
 
-  dotlock_unlock (realpath);
+  dotlock_unlock (frealpath);
 
-  return (i == 0) ?  DL_EX_OK : DL_EX_ERROR;
+  return (i == 0) ? DL_EX_OK : DL_EX_ERROR;
 }
 
 
@@ -733,8 +614,7 @@ dotlock_unlink (const char *realpath)
  * 
  */
 
-static int
-dotlock_try (void)
+static int dotlock_try (void)
 {
 #ifdef USE_SETGID
   struct stat sb;
@@ -744,8 +624,7 @@ dotlock_try (void)
     return DL_EX_OK;
 
 #ifdef USE_SETGID
-  if (stat (".", &sb) == 0)
-  {
+  if (stat (".", &sb) == 0) {
     if ((sb.st_mode & S_IWGRP) == S_IWGRP && sb.st_gid == MailGid)
       return DL_EX_NEED_PRIVS;
   }