]> code.delx.au - gnu-emacs/blobdiff - lib-src/movemail.c
Merge from emacs-24; up to 2012-04-25T15:23:19Z!sdl.web@gmail.com
[gnu-emacs] / lib-src / movemail.c
index 5fcc6de17a63b750fda4407f09d59c325c77c5bf..9d19df32814688c4dac8da033c71e98362e13fdd 100644 (file)
@@ -1,7 +1,8 @@
 /* movemail foo bar -- move file foo to file bar,
    locking file foo the way /bin/mail respects.
-   Copyright (C) 1986, 1992, 1993, 1994, 1996, 1999, 2001, 2002, 2003, 2004,
-                 2005, 2006, 2007, 2008, 2009, 2010, 2011  Free Software Foundation, Inc.
+
+Copyright (C) 1986, 1992-1994, 1996, 1999, 2001-2012
+  Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -63,12 +64,11 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <time.h>
 
 #include <getopt.h>
-#ifdef HAVE_UNISTD_H
 #include <unistd.h>
-#endif
 #ifdef HAVE_FCNTL_H
 #include <fcntl.h>
 #endif
+#include <string.h>
 #include "syswait.h"
 #ifdef MAIL_USE_POP
 #include "pop.h"
@@ -78,13 +78,6 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #undef access
 #endif /* MSDOS */
 
-#ifndef DIRECTORY_SEP
-#define DIRECTORY_SEP '/'
-#endif
-#ifndef IS_DIRECTORY_SEP
-#define IS_DIRECTORY_SEP(_c_) ((_c_) == DIRECTORY_SEP)
-#endif
-
 #ifdef WINDOWSNT
 #include "ntlib.h"
 #undef access
@@ -136,53 +129,46 @@ extern int lk_open (), lk_close ();
    files appear in. */
 #ifdef MAILDIR
 #define MAIL_USE_MAILLOCK
-static char *mail_spool_name ();
+static char *mail_spool_name (char *);
 #endif
 #endif
 
-#ifndef errno
-extern int errno;
-#endif
-char *strerror ();
-#ifdef HAVE_INDEX
-extern char *index __P ((const char *, int));
-#endif
-#ifdef HAVE_RINDEX
-extern char *rindex __P((const char *, int));
+#ifndef HAVE_STRERROR
+char *strerror (int);
 #endif
 
-void fatal ();
-void error ();
-void pfatal_with_name ();
-void pfatal_and_delete ();
-char *concat ();
-long *xmalloc ();
-int popmail ();
-int pop_retr ();
-int mbx_write ();
-int mbx_delimit_begin ();
-int mbx_delimit_end ();
+static void fatal (const char *s1, const char *s2, const char *s3) NO_RETURN;
+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);
+#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);
+static int mbx_write (char *line, int len, FILE *mbf);
+static int mbx_delimit_begin (FILE *mbf);
+static int mbx_delimit_end (FILE *mbf);
+#endif
 
 /* Nonzero means this is name of a lock file to delete on fatal error.  */
-char *delete_lockname;
+static char *delete_lockname;
 
 int
-main (argc, argv)
-     int argc;
-     char **argv;
+main (int argc, char **argv)
 {
   char *inname, *outname;
   int indesc, outdesc;
-  int nread;
-  int status;
+  ssize_t nread;
+  int wait_status;
   int c, preserve_mail = 0;
 
 #ifndef MAIL_USE_SYSTEM_LOCK
   struct stat st;
-  long now;
   int tem;
-  char *lockname, *p;
+  char *lockname;
   char *tempname;
+  size_t inname_dirlen;
   int desc;
 #endif /* not MAIL_USE_SYSTEM_LOCK */
 
@@ -197,8 +183,8 @@ main (argc, 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. */
@@ -271,9 +257,22 @@ main (argc, argv)
 #ifndef MAIL_USE_SYSTEM_LOCK
 #ifdef MAIL_USE_MAILLOCK
   spool_name = mail_spool_name (inname);
-  if (! spool_name)
+  if (spool_name)
+    {
+#ifdef lint
+      lockname = 0;
+#endif
+    }
+  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
@@ -298,27 +297,38 @@ main (argc, argv)
         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);
+      for (inname_dirlen = strlen (inname);
+          inname_dirlen && !IS_DIRECTORY_SEP (inname[inname_dirlen - 1]);
+          inname_dirlen--)
+       continue;
+      tempname = (char *) 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);
 
@@ -341,7 +351,7 @@ main (argc, argv)
             by time differences between machines.  */
          if (stat (lockname, &st) >= 0)
            {
-             now = time (0);
+             time_t now = time (0);
              if (st.st_ctime < now - 300)
                unlink (lockname);
            }
@@ -357,7 +367,10 @@ main (argc, argv)
       int lockcount = 0;
       int status = 0;
 #if defined (MAIL_USE_MAILLOCK) && defined (HAVE_TOUCHLOCK)
-      time_t touched_lock, now;
+      time_t touched_lock;
+# ifdef lint
+      touched_lock = 0;
+# endif
 #endif
 
       if (setuid (getuid ()) < 0 || setregid (-1, real_gid) < 0)
@@ -467,7 +480,7 @@ main (argc, argv)
 #if defined (MAIL_USE_MAILLOCK) && defined (HAVE_TOUCHLOCK)
            if (spool_name)
              {
-               now = time (0);
+               time_t now = time (0);
                if (now - touched_lock > 60)
                  {
                    touchlock ();
@@ -494,7 +507,8 @@ main (argc, argv)
 #ifdef MAIL_USE_SYSTEM_LOCK
       if (! preserve_mail)
        {
-         ftruncate (indesc, 0L);
+         if (ftruncate (indesc, 0L) != 0)
+           pfatal_with_name (inname);
        }
 #endif /* MAIL_USE_SYSTEM_LOCK */
 
@@ -531,11 +545,11 @@ main (argc, argv)
       exit (EXIT_SUCCESS);
     }
 
-  wait (&status);
-  if (!WIFEXITED (status))
+  wait (&wait_status);
+  if (!WIFEXITED (wait_status))
     exit (EXIT_FAILURE);
-  else if (WRETCODE (status) != 0)
-    exit (WRETCODE (status));
+  else if (WRETCODE (wait_status) != 0)
+    exit (WRETCODE (wait_status));
 
 #if !defined (MAIL_USE_MMDF) && !defined (MAIL_USE_SYSTEM_LOCK)
 #ifdef MAIL_USE_MAILLOCK
@@ -555,14 +569,13 @@ main (argc, argv)
    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;
+mail_spool_name (char *inname)
 {
   struct stat stat1, stat2;
   char *indir, *fname;
   int status;
 
-  if (! (fname = rindex (inname, '/')))
+  if (! (fname = strrchr (inname, '/')))
     return NULL;
 
   fname++;
@@ -592,9 +605,8 @@ mail_spool_name (inname)
 \f
 /* Print error message and exit.  */
 
-void
-fatal (s1, s2, s3)
-     char *s1, *s2, *s3;
+static void
+fatal (const char *s1, const char *s2, const char *s3)
 {
   if (delete_lockname)
     unlink (delete_lockname);
@@ -605,9 +617,8 @@ fatal (s1, s2, s3)
 /* Print error message.  `s1' is printf control string, `s2' and `s3'
    are args for it or null. */
 
-void
-error (s1, s2, s3)
-     char *s1, *s2, *s3;
+static void
+error (const char *s1, const char *s2, const char *s3)
 {
   fprintf (stderr, "movemail: ");
   if (s3)
@@ -615,20 +626,18 @@ error (s1, s2, s3)
   else if (s2)
     fprintf (stderr, s1, s2);
   else
-    fprintf (stderr, s1);
+    fprintf (stderr, "%s", s1);
   fprintf (stderr, "\n");
 }
 
-void
-pfatal_with_name (name)
-     char *name;
+static void
+pfatal_with_name (char *name)
 {
   fatal ("%s for %s", strerror (errno), name);
 }
 
-void
-pfatal_and_delete (name)
-     char *name;
+static void
+pfatal_and_delete (char *name)
 {
   char *s = strerror (errno);
   unlink (name);
@@ -637,11 +646,10 @@ pfatal_and_delete (name)
 
 /* Return a newly-allocated string whose contents concatenate those of s1, s2, s3.  */
 
-char *
-concat (s1, s2, s3)
-     char *s1, *s2, *s3;
+static char *
+concat (const char *s1, const char *s2, const char *s3)
 {
-  int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
+  size_t len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
   char *result = (char *) xmalloc (len1 + len2 + len3 + 1);
 
   strcpy (result, s1);
@@ -654,9 +662,8 @@ concat (s1, s2, s3)
 
 /* Like malloc but get fatal error if memory is exhausted.  */
 
-long *
-xmalloc (size)
-     unsigned size;
+static long *
+xmalloc (unsigned int size)
 {
   long *result = (long *) malloc (size);
   if (!result)
@@ -681,14 +688,8 @@ xmalloc (size)
 
 #define NOTOK (-1)
 #define OK 0
-#define DONE 1
-
-char *progname;
-FILE *sfi;
-FILE *sfo;
-char ibuffer[BUFSIZ];
-char obuffer[BUFSIZ];
-char Errmsg[200];              /* POP errors, at least, can exceed
+
+static char Errmsg[200];       /* POP errors, at least, can exceed
                                   the original length of 80.  */
 
 /*
@@ -705,25 +706,20 @@ char Errmsg[200];         /* POP errors, at least, can exceed
  * Return a value suitable for passing to `exit'.
  */
 
-int
-popmail (mailbox, outfile, preserve, password, reverse_order)
-     char *mailbox;
-     char *outfile;
-     int preserve;
-     char *password;
-     int reverse_order;
+static int
+popmail (char *mailbox, char *outfile, int preserve, char *password, int reverse_order)
 {
   int nmsgs, nbytes;
   register int i;
   int mbfi;
   FILE *mbf;
-  char *getenv ();
+  char *getenv (const char *);
   popserver server;
   int start, end, increment;
   char *user, *hostname;
 
   user = mailbox;
-  if ((hostname = index(mailbox, ':')))
+  if ((hostname = strchr (mailbox, ':')))
     *hostname++ = '\0';
 
   server = pop_open (hostname, user, password, POP_NO_GETPASS);
@@ -752,7 +748,18 @@ popmail (mailbox, outfile, preserve, password, reverse_order)
       error ("Error in open: %s, %s", strerror (errno), outfile);
       return EXIT_FAILURE;
     }
-  fchown (mbfi, getuid (), -1);
+
+  if (fchown (mbfi, getuid (), -1) != 0)
+    {
+      int fchown_errno = errno;
+      struct stat st;
+      if (fstat (mbfi, &st) != 0 || st.st_uid != getuid ())
+       {
+         pop_close (server);
+         error ("Error in fchown: %s, %s", strerror (fchown_errno), outfile);
+         return EXIT_FAILURE;
+       }
+    }
 
   if ((mbf = fdopen (mbfi, "wb")) == NULL)
     {
@@ -836,22 +843,18 @@ popmail (mailbox, outfile, preserve, password, reverse_order)
   return EXIT_SUCCESS;
 }
 
-int
-pop_retr (server, msgno, arg)
-     popserver server;
-     int msgno;
-     FILE *arg;
+static int
+pop_retr (popserver server, int msgno, FILE *arg)
 {
-  extern char *strerror ();
   char *line;
   int ret;
 
   if (pop_retrieve_first (server, msgno, &line))
     {
-      char *error = concat ("Error from POP server: ", pop_error, "");
-      strncpy (Errmsg, error, sizeof (Errmsg));
+      char *msg = concat ("Error from POP server: ", pop_error, "");
+      strncpy (Errmsg, msg, sizeof (Errmsg));
       Errmsg[sizeof (Errmsg)-1] = '\0';
-      free(error);
+      free (msg);
       return (NOTOK);
     }
 
@@ -870,30 +873,26 @@ pop_retr (server, msgno, arg)
 
   if (ret)
     {
-      char *error = concat ("Error from POP server: ", pop_error, "");
-      strncpy (Errmsg, error, sizeof (Errmsg));
+      char *msg = concat ("Error from POP server: ", pop_error, "");
+      strncpy (Errmsg, msg, sizeof (Errmsg));
       Errmsg[sizeof (Errmsg)-1] = '\0';
-      free(error);
+      free (msg);
       return (NOTOK);
     }
 
   return (OK);
 }
 
-/* Do this as a macro instead of using strcmp to save on execution time. */
-#define IS_FROM_LINE(a) ((a[0] == 'F') \
-                        && (a[1] == 'r') \
-                        && (a[2] == 'o') \
-                        && (a[3] == 'm') \
-                        && (a[4] == ' '))
-
-int
-mbx_write (line, len, mbf)
-     char *line;
-     int len;
-     FILE *mbf;
+static int
+mbx_write (char *line, int len, FILE *mbf)
 {
 #ifdef MOVEMAIL_QUOTE_POP_FROM_LINES
+  /* Do this as a macro instead of using strcmp to save on execution time. */
+  # define IS_FROM_LINE(a) ((a[0] == 'F')      \
+                           && (a[1] == 'r')    \
+                           && (a[2] == 'o')    \
+                           && (a[3] == 'm')    \
+                           && (a[4] == ' '))
   if (IS_FROM_LINE (line))
     {
       if (fputc ('>', mbf) == EOF)
@@ -914,9 +913,8 @@ mbx_write (line, len, mbf)
   return (OK);
 }
 
-int
-mbx_delimit_begin (mbf)
-     FILE *mbf;
+static int
+mbx_delimit_begin (FILE *mbf)
 {
   time_t now;
   struct tm *ltime;
@@ -932,9 +930,8 @@ mbx_delimit_begin (mbf)
   return (OK);
 }
 
-int
-mbx_delimit_end (mbf)
-     FILE *mbf;
+static int
+mbx_delimit_end (FILE *mbf)
 {
   if (putc ('\n', mbf) == EOF)
     return (NOTOK);
@@ -958,7 +955,5 @@ strerror (errnum)
 
 #endif /* ! HAVE_STRERROR */
 
-/* arch-tag: 1c323112-41fe-4fe5-8de9-494de631f73f
-   (do not change this comment) */
 
 /* movemail.c ends here */