diff lib-src/movemail.c @ 16897:523d5c54a3f5

Include maillock.h (conditionally). Remove a redundant inclusion of <stdio.h>. (MAIL_USE_MAILLOCK): New macro, conditionally defined. (main): Add variable spool_name. Support the usage of maillock and mailunlock to lock and unlock mailboxes. (mail_spool_name): New function.
author Richard M. Stallman <rms@gnu.org>
date Mon, 20 Jan 1997 07:30:40 +0000
parents ed13d19dbce5
children d878e23bbfa6
line wrap: on
line diff
--- a/lib-src/movemail.c	Mon Jan 20 02:22:25 1997 +0000
+++ b/lib-src/movemail.c	Mon Jan 20 07:30:40 1997 +0000
@@ -121,6 +121,17 @@
 extern int lk_open (), lk_close ();
 #endif
 
+#if !defined (MAIL_USE_SYSTEM_LOCK) && !defined (MAIL_USE_MMDF) && \
+	defined (HAVE_LIBMAIL) && defined (HAVE_MAILLOCK_H)
+#include <maillock.h>
+/* We can't use maillock unless we know what directory system mail
+   files appear in. */
+#ifdef MAILDIR
+#define MAIL_USE_MAILLOCK
+static char *mail_spool_name ();
+#endif
+#endif
+
 /* Cancel substitutions made by config.h for Emacs.  */
 #undef open
 #undef read
@@ -166,12 +177,16 @@
   int desc;
 #endif /* not MAIL_USE_SYSTEM_LOCK */
 
+#ifdef MAIL_USE_MAILLOCK
+  char *spool_name;
+#endif
+
   delete_lockname = 0;
 
   if (argc < 3)
     {
       fprintf (stderr, "Usage: movemail inbox destfile [POP-password]\n");
-      exit(1);
+      exit (1);
     }
 
   inname = argv[1];
@@ -223,80 +238,89 @@
 
 #ifndef MAIL_USE_MMDF
 #ifndef MAIL_USE_SYSTEM_LOCK
-  /* Use a lock file named after our first argument with .lock appended:
-     If it exists, the mail file is locked.  */
-  /* Note: this locking mechanism is *required* by the mailer
-     (on systems which use it) to prevent loss of mail.
-
-     On systems that use a lock file, extracting the mail without locking
-     WILL occasionally cause loss of mail due to timing errors!
+#ifdef MAIL_USE_MAILLOCK
+  spool_name = mail_spool_name (inname);
+  if (! spool_name)
+#endif
+    {
+      /* Use a lock file named after our first argument with .lock appended:
+	 If it exists, the mail file is locked.  */
+      /* Note: this locking mechanism is *required* by the mailer
+	 (on systems which use it) to prevent loss of mail.
 
-     So, if creation of the lock file fails
-     due to access permission on the mail spool directory,
-     you simply MUST change the permission
-     and/or make movemail a setgid program
-     so it can create lock files properly.
-
-     You might also wish to verify that your system is one
-     which uses lock files for this purpose.  Some systems use other methods.
+	 On systems that use a lock file, extracting the mail without locking
+	 WILL occasionally cause loss of mail due to timing errors!
 
-     If your system uses the `flock' system call for mail locking,
-     define MAIL_USE_SYSTEM_LOCK in config.h or the s-*.h file
-     and recompile movemail.  If the s- file for your system
-     should define MAIL_USE_SYSTEM_LOCK but does not, send a bug report
-     to bug-gnu-emacs@prep.ai.mit.edu so we can fix it.  */
+	 So, if creation of the lock file fails
+	 due to access permission on the mail spool directory,
+	 you simply MUST change the permission
+	 and/or make movemail a setgid program
+	 so it can create lock files properly.
 
-  lockname = concat (inname, ".lock", "");
-  tempname = (char *) xmalloc (strlen (inname) + strlen ("EXXXXXX") + 1);
-  strcpy (tempname, inname);
-  p = tempname + strlen (tempname);
-  while (p != tempname && !IS_DIRECTORY_SEP (p[-1]))
-    p--;
-  *p = 0;
-  strcpy (p, "EXXXXXX");
-  mktemp (tempname);
-  unlink (tempname);
+	 You might also wish to verify that your system is one
+	 which uses lock files for this purpose.  Some systems use other methods.
+
+	 If your system uses the `flock' system call for mail locking,
+	 define MAIL_USE_SYSTEM_LOCK in config.h or the s-*.h file
+	 and recompile movemail.  If the s- file for your system
+	 should define MAIL_USE_SYSTEM_LOCK but does not, send a bug report
+	 to bug-gnu-emacs@prep.ai.mit.edu so we can fix it.  */
 
-  while (1)
-    {
-      /* Create the lock file, but not under the lock file name.  */
-      /* Give up if cannot do that.  */
-      desc = open (tempname, O_WRONLY | O_CREAT | O_EXCL, 0666);
-      if (desc < 0)
-	{
-	  char *message = (char *) xmalloc (strlen (tempname) + 50);
-	  sprintf (message, "%s--see source file lib-src/movemail.c",
-		   tempname);
-	  pfatal_with_name (message);
-	}
-      close (desc);
-
-      tem = link (tempname, lockname);
+      lockname = concat (inname, ".lock", "");
+      tempname = (char *) xmalloc (strlen (inname) + strlen ("EXXXXXX") + 1);
+      strcpy (tempname, inname);
+      p = tempname + strlen (tempname);
+      while (p != tempname && !IS_DIRECTORY_SEP (p[-1]))
+	p--;
+      *p = 0;
+      strcpy (p, "EXXXXXX");
+      mktemp (tempname);
       unlink (tempname);
-      if (tem >= 0)
-	break;
-      sleep (1);
+
+      while (1)
+	{
+	  /* Create the lock file, but not under the lock file name.  */
+	  /* Give up if cannot do that.  */
+	  desc = open (tempname, O_WRONLY | O_CREAT | O_EXCL, 0666);
+	  if (desc < 0)
+	    {
+	      char *message = (char *) xmalloc (strlen (tempname) + 50);
+	      sprintf (message, "%s--see source file lib-src/movemail.c",
+		       tempname);
+	      pfatal_with_name (message);
+	    }
+	  close (desc);
 
-      /* If lock file is five minutes old, unlock it.
-	 Five minutes should be good enough to cope with crashes
-	 and wedgitude, and long enough to avoid being fooled
-	 by time differences between machines.  */
-      if (stat (lockname, &st) >= 0)
-	{
-	  now = time (0);
-	  if (st.st_ctime < now - 300)
-	    unlink (lockname);
+	  tem = link (tempname, lockname);
+	  unlink (tempname);
+	  if (tem >= 0)
+	    break;
+	  sleep (1);
+
+	  /* If lock file is five minutes old, unlock it.
+	     Five minutes should be good enough to cope with crashes
+	     and wedgitude, and long enough to avoid being fooled
+	     by time differences between machines.  */
+	  if (stat (lockname, &st) >= 0)
+	    {
+	      now = time (0);
+	      if (st.st_ctime < now - 300)
+		unlink (lockname);
+	    }
 	}
+
+      delete_lockname = lockname;
     }
-
-  delete_lockname = lockname;
 #endif /* not MAIL_USE_SYSTEM_LOCK */
 #endif /* not MAIL_USE_MMDF */
 
   if (fork () == 0)
     {
       int lockcount = 0;
-      int status;
+      int status = 0;
+#if defined (MAIL_USE_MAILLOCK) && defined (HAVE_TOUCHLOCK)
+      long touched_lock, now;
+#endif
 
       setuid (getuid ());
 
@@ -329,21 +353,36 @@
     retry_lock:
 
       /* Try to lock it.  */
+#ifdef MAIL_USE_MAILLOCK
+      if (spool_name)
+	{
+	  /* The "0 - " is to make it a negative number if maillock returns
+	     non-zero. */
+	  status = 0 - maillock (spool_name, 1);
+#ifdef HAVE_TOUCHLOCK
+	  touched_lock = time (0);
+#endif
+	  lockcount = 5;
+	}
+      else
+#endif /* MAIL_USE_MAILLOCK */
+	{
 #ifdef MAIL_USE_SYSTEM_LOCK
 #ifdef MAIL_USE_LOCKF
-      status = lockf (indesc, F_LOCK, 0);
+	  status = lockf (indesc, F_LOCK, 0);
 #else /* not MAIL_USE_LOCKF */
 #ifdef XENIX
-      status = locking (indesc, LK_RLCK, 0L);
+	  status = locking (indesc, LK_RLCK, 0L);
 #else
 #ifdef WINDOWSNT
-      status = locking (indesc, LK_RLCK, -1L);
+	  status = locking (indesc, LK_RLCK, -1L);
 #else
-      status = flock (indesc, LOCK_EX);
+	  status = flock (indesc, LOCK_EX);
 #endif
 #endif
 #endif /* not MAIL_USE_LOCKF */
 #endif /* MAIL_USE_SYSTEM_LOCK */
+	}
 
       /* If it fails, retry up to 5 times
 	 for certain failure codes.  */
@@ -385,6 +424,17 @@
 	      }
 	    if (nread < sizeof buf)
 	      break;
+#if defined (MAIL_USE_MAILLOCK) && defined (HAVE_TOUCHLOCK)
+	    if (spool_name)
+	      {
+		now = time (0);
+		if (now - touched_lock > 60)
+		  {
+		    touchlock ();
+		    touched_lock = now;
+		  }
+	      }
+#endif /* MAIL_USE_MAILLOCK */
 	  }
       }
 
@@ -423,6 +473,12 @@
 	creat (inname, 0600);
 #endif /* not MAIL_USE_SYSTEM_LOCK */
 
+#ifdef MAIL_USE_MAILLOCK
+      /* This has to occur in the child, i.e., in the process that
+         acquired the lock! */
+      if (spool_name)
+	mailunlock ();
+#endif
       exit (0);
     }
 
@@ -433,13 +489,57 @@
     exit (WRETCODE (status));
 
 #if !defined (MAIL_USE_MMDF) && !defined (MAIL_USE_SYSTEM_LOCK)
-  unlink (lockname);
+#ifdef MAIL_USE_MAILLOCK
+  if (! spool_name)
+#endif /* MAIL_USE_MAILLOCK */
+    unlink (lockname);
 #endif /* not MAIL_USE_MMDF and not MAIL_USE_SYSTEM_LOCK */
 
 #endif /* ! DISABLE_DIRECT_ACCESS */
 
   return 0;
 }
+
+#ifdef MAIL_USE_MAILLOCK
+/* This function uses stat to confirm that the mail directory is
+   identical to the directory of the input file, rather than just
+   string-comparing the two paths, because one or both of them might
+   be symbolic links pointing to some other directory. */
+static char *
+mail_spool_name (inname)
+     char *inname;
+{
+  struct stat stat1, stat2;
+  char *indir, *fname;
+  int status;
+
+  if (! (fname = rindex (inname, '/')))
+    return NULL;
+
+  fname++;
+
+  if (stat (MAILDIR, &stat1) < 0)
+    return NULL;
+
+  indir = (char *) xmalloc (fname - inname + 1);
+  strncpy (indir, inname, fname - inname);
+  indir[fname-inname] = '\0';
+
+
+  status = stat (indir, &stat2);
+
+  free (indir);
+
+  if (status < 0)
+    return NULL;
+
+  if ((stat1.st_dev == stat2.st_dev) &&
+      (stat1.st_ino == stat2.st_ino))
+    return fname;
+
+  return NULL;
+}
+#endif /* MAIL_USE_MAILLOCK */
 
 /* Print error message and exit.  */
 
@@ -522,7 +622,6 @@
 #undef _WINSOCKAPI_
 #include <winsock.h>
 #endif
-#include <stdio.h>
 #include <pwd.h>
 
 #ifdef USG
@@ -657,7 +756,7 @@
 
 pop_retr (server, msgno, action, arg)
      popserver server;
-     int (*action)();
+     int (*action) ();
 {
   extern char *strerror ();
   char *line;