Assume POSIX 1003.1-1988 or later for unistd.h.
[bpt/emacs.git] / lib-src / movemail.c
index 4cf97cb..adc5dd9 100644 (file)
@@ -1,7 +1,7 @@
 /* movemail foo bar -- move file foo to file bar,
    locking file foo the way /bin/mail respects.
 
-Copyright (C) 1986, 1992-1994, 1996, 1999, 2001-2011
+Copyright (C) 1986, 1992-1994, 1996, 1999, 2001-2012
   Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -22,7 +22,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 /* Important notice: defining MAIL_USE_FLOCK or MAIL_USE_LOCKF *will
    cause loss of mail* if you do it on a system that does not normally
-   use flock as its way of interlocking access to inbox files.  The
+   use flock/lockf as its way of interlocking access to inbox files.  The
    setting of MAIL_USE_FLOCK and MAIL_USE_LOCKF *must agree* with the
    system's own conventions.  It is not a choice that is up to you.
 
@@ -65,12 +65,8 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <getopt.h>
 #include <unistd.h>
-#ifdef HAVE_FCNTL_H
 #include <fcntl.h>
-#endif
-#ifdef HAVE_STRING_H
 #include <string.h>
-#endif
 #include "syswait.h"
 #ifdef MAIL_USE_POP
 #include "pop.h"
@@ -100,17 +96,15 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <fcntl.h>
 #endif /* WINDOWSNT */
 
-#ifndef F_OK
-#define F_OK 0
-#define X_OK 1
-#define W_OK 2
-#define R_OK 4
-#endif
-
 #ifdef WINDOWSNT
 #include <sys/locking.h>
 #endif
 
+/* If your system uses the `flock' or `lockf' system call for mail locking,
+   define MAIL_USE_SYSTEM_LOCK.  If your system type should always define
+   MAIL_USE_LOCKF or MAIL_USE_FLOCK but configure does not do this,
+   please make a bug report.  */
+
 #ifdef MAIL_USE_LOCKF
 #define MAIL_USE_SYSTEM_LOCK
 #endif
@@ -135,16 +129,10 @@ static char *mail_spool_name (char *);
 #endif
 #endif
 
-#ifndef HAVE_STRERROR
-char *strerror (int);
-#endif
-
-static void fatal (const char *s1, const char *s2, const char *s3) NO_RETURN;
+static _Noreturn void fatal (const char *s1, const char *s2, const char *s3);
 static void error (const char *s1, const char *s2, const char *s3);
-static void pfatal_with_name (char *name) NO_RETURN;
-static void pfatal_and_delete (char *name) NO_RETURN;
-static char *concat (const char *s1, const char *s2, const char *s3);
-static long *xmalloc (unsigned int size);
+static _Noreturn void pfatal_with_name (char *name);
+static _Noreturn void pfatal_and_delete (char *name);
 #ifdef MAIL_USE_POP
 static int popmail (char *mailbox, char *outfile, int preserve, char *password, int reverse_order);
 static int pop_retr (popserver server, int msgno, FILE *arg);
@@ -153,6 +141,21 @@ static int mbx_delimit_begin (FILE *mbf);
 static int mbx_delimit_end (FILE *mbf);
 #endif
 
+#if (defined MAIL_USE_MAILLOCK                                         \
+     || (!defined DISABLE_DIRECT_ACCESS && !defined MAIL_USE_MMDF      \
+        && !defined MAIL_USE_SYSTEM_LOCK))
+/* Like malloc but get fatal error if memory is exhausted.  */
+
+static void *
+xmalloc (size_t size)
+{
+  void *result = malloc (size);
+  if (!result)
+    fatal ("virtual memory exhausted", 0, 0);
+  return result;
+}
+#endif
+
 /* Nonzero means this is name of a lock file to delete on fatal error.  */
 static char *delete_lockname;
 
@@ -168,8 +171,9 @@ main (int argc, char **argv)
 #ifndef MAIL_USE_SYSTEM_LOCK
   struct stat st;
   int tem;
-  char *lockname, *p;
+  char *lockname;
   char *tempname;
+  size_t inname_len, inname_dirlen;
   int desc;
 #endif /* not MAIL_USE_SYSTEM_LOCK */
 
@@ -184,8 +188,8 @@ main (int argc, char **argv)
 # define ARGSTR "p"
 #endif /* MAIL_USE_POP */
 
-  uid_t real_gid = getgid();
-  uid_t priv_gid = getegid();
+  uid_t real_gid = getgid ();
+  uid_t priv_gid = getegid ();
 
 #ifdef WINDOWSNT
   /* Ensure all file i/o is in binary mode. */
@@ -267,13 +271,6 @@ main (int argc, char **argv)
   else
 #endif
     {
-      #ifndef DIRECTORY_SEP
-       #define DIRECTORY_SEP '/'
-      #endif
-      #ifndef IS_DIRECTORY_SEP
-       #define IS_DIRECTORY_SEP(_c_) ((_c_) == DIRECTORY_SEP)
-      #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
@@ -282,43 +279,50 @@ main (int argc, char **argv)
         On systems that use a lock file, extracting the mail without locking
         WILL occasionally cause loss of mail due to timing errors!
 
-        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, 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.
-
-        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.  */
-
-      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.  */
+
+      inname_len = strlen (inname);
+      lockname = xmalloc (inname_len + sizeof ".lock");
+      strcpy (lockname, inname);
+      strcpy (lockname + inname_len, ".lock");
+      for (inname_dirlen = inname_len;
+          inname_dirlen && !IS_DIRECTORY_SEP (inname[inname_dirlen - 1]);
+          inname_dirlen--)
+       continue;
+      tempname = xmalloc (inname_dirlen + sizeof "EXXXXXX");
 
       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);
+
+         memcpy (tempname, inname, inname_dirlen);
+         strcpy (tempname + inname_dirlen, "EXXXXXX");
+#ifdef HAVE_MKSTEMP
+         desc = mkstemp (tempname);
+#else
+         mktemp (tempname);
+         if (!*tempname)
+           desc = -1;
+         else
+           {
+             unlink (tempname);
+             desc = open (tempname, O_WRONLY | O_CREAT | O_EXCL, 0600);
+           }
+#endif
          if (desc < 0)
            {
-             char *message = (char *) xmalloc (strlen (tempname) + 50);
-             sprintf (message, "creating %s, which would become the lock file",
-                      tempname);
-             pfatal_with_name (message);
+             int mkstemp_errno = errno;
+             error ("error while creating what would become the lock file",
+                    0, 0);
+             errno = mkstemp_errno;
+             pfatal_with_name (tempname);
            }
          close (desc);
 
@@ -538,8 +542,8 @@ main (int argc, char **argv)
   wait (&wait_status);
   if (!WIFEXITED (wait_status))
     exit (EXIT_FAILURE);
-  else if (WRETCODE (wait_status) != 0)
-    exit (WRETCODE (wait_status));
+  else if (WEXITSTATUS (wait_status) != 0)
+    exit (WEXITSTATUS (wait_status));
 
 #if !defined (MAIL_USE_MMDF) && !defined (MAIL_USE_SYSTEM_LOCK)
 #ifdef MAIL_USE_MAILLOCK
@@ -573,8 +577,8 @@ mail_spool_name (char *inname)
   if (stat (MAILDIR, &stat1) < 0)
     return NULL;
 
-  indir = (char *) xmalloc (fname - inname + 1);
-  strncpy (indir, inname, fname - inname);
+  indir = xmalloc (fname - inname + 1);
+  memcpy (indir, inname, fname - inname);
   indir[fname-inname] = '\0';
 
 
@@ -633,33 +637,6 @@ pfatal_and_delete (char *name)
   unlink (name);
   fatal ("%s for %s", s, name);
 }
-
-/* Return a newly-allocated string whose contents concatenate those of s1, s2, s3.  */
-
-static char *
-concat (const char *s1, const char *s2, const char *s3)
-{
-  size_t len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
-  char *result = (char *) xmalloc (len1 + len2 + len3 + 1);
-
-  strcpy (result, s1);
-  strcpy (result + len1, s2);
-  strcpy (result + len1 + len2, s3);
-  *(result + len1 + len2 + len3) = 0;
-
-  return result;
-}
-
-/* Like malloc but get fatal error if memory is exhausted.  */
-
-static long *
-xmalloc (unsigned int size)
-{
-  long *result = (long *) malloc (size);
-  if (!result)
-    fatal ("virtual memory exhausted", 0, 0);
-  return result;
-}
 \f
 /* This is the guts of the interface to the Post Office Protocol.  */
 
@@ -841,10 +818,7 @@ pop_retr (popserver server, int msgno, FILE *arg)
 
   if (pop_retrieve_first (server, msgno, &line))
     {
-      char *msg = concat ("Error from POP server: ", pop_error, "");
-      strncpy (Errmsg, msg, sizeof (Errmsg));
-      Errmsg[sizeof (Errmsg)-1] = '\0';
-      free (msg);
+      snprintf (Errmsg, sizeof Errmsg, "Error from POP server: %s", pop_error);
       return (NOTOK);
     }
 
@@ -863,10 +837,7 @@ pop_retr (popserver server, int msgno, FILE *arg)
 
   if (ret)
     {
-      char *msg = concat ("Error from POP server: ", pop_error, "");
-      strncpy (Errmsg, msg, sizeof (Errmsg));
-      Errmsg[sizeof (Errmsg)-1] = '\0';
-      free (msg);
+      snprintf (Errmsg, sizeof Errmsg, "Error from POP server: %s", pop_error);
       return (NOTOK);
     }
 
@@ -929,21 +900,3 @@ mbx_delimit_end (FILE *mbf)
 }
 
 #endif /* MAIL_USE_POP */
-\f
-#ifndef HAVE_STRERROR
-char *
-strerror (errnum)
-     int errnum;
-{
-  extern char *sys_errlist[];
-  extern int sys_nerr;
-
-  if (errnum >= 0 && errnum < sys_nerr)
-    return sys_errlist[errnum];
-  return (char *) "Unknown error";
-}
-
-#endif /* ! HAVE_STRERROR */
-
-
-/* movemail.c ends here */