commit 62f0ccb0d60fd8abcc865a95d55c4888296f2ebc
parent 1b6377f437237bd7bbad948b91143d3eaa919384
Author: Jaromil <jaromil@dyne.org>
Date:   Wed, 12 Sep 2012 13:36:06 +0200
updated ignore list and mutt source
Diffstat:
2 files changed, 787 insertions(+), 0 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -1,6 +1,8 @@
 *~
 *.o
 *.zwc
+*.gmo
+.deps
 dotlock
 fetchaddr
 fetchdate
@@ -21,3 +23,30 @@ src/mairix/fromcheck.c
 src/mairix/fromcheck.h
 src/mairix/nvpscan.c
 src/mairix/nvpscan.h
+src/mutt-1.5.21/Makefile
+src/mutt-1.5.21/config.h
+src/mutt-1.5.21/config.log
+src/mutt-1.5.21/config.status
+src/mutt-1.5.21/contrib/Makefile
+src/mutt-1.5.21/doc/Makefile
+src/mutt-1.5.21/flea
+src/mutt-1.5.21/hcachever.sh
+src/mutt-1.5.21/hcversion.h
+src/mutt-1.5.21/imap/Makefile
+src/mutt-1.5.21/imap/libimap.a
+src/mutt-1.5.21/intl/Makefile
+src/mutt-1.5.21/keymap_defs.h
+src/mutt-1.5.21/m4/Makefile
+src/mutt-1.5.21/make.log
+src/mutt-1.5.21/mutt_dotlock
+src/mutt-1.5.21/mutt_md5
+src/mutt-1.5.21/muttbug.sh
+src/mutt-1.5.21/patchlist.c
+src/mutt-1.5.21/pgpewrap
+src/mutt-1.5.21/pgpring
+src/mutt-1.5.21/po/Makefile
+src/mutt-1.5.21/po/Makefile.in
+src/mutt-1.5.21/po/POTFILES
+src/mutt-1.5.21/reldate.h
+src/mutt-1.5.21/smime_keys
+src/mutt-1.5.21/stamp-h1
diff --git a/src/mutt-1.5.21/mutt_dotlock.c b/src/mutt-1.5.21/mutt_dotlock.c
@@ -0,0 +1,758 @@
+/*
+ * Copyright (C) 1996-2000 Michael R. Elkins <me@mutt.org>
+ * Copyright (C) 1998-2001,2007 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 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.
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.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 <limits.h>
+#endif
+
+#include "dotlock.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 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
+#   define SETEGID setegid
+#  else
+#   define SETEGID setgid
+#  endif
+#  ifndef S_ISLNK
+#   define S_ISLNK(x) (((x) & S_IFMT) == S_IFLNK ? 1 : 0)
+#  endif
+
+# 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;
+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_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);
+static void END_PRIVILEGED (void);
+
+/* These functions work on the current directory.
+ * Invoke dotlock_prepare () before and check their
+ * return value.
+ */
+
+static int dotlock_try (void);
+static int dotlock_unlock (const char *);
+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)
+{
+  int i;
+  char *p;
+  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__ */
+    return DL_EX_ERROR;
+  if ((p = strchr (Hostname, '.')))
+    *p = '\0';
+
+
+  /* parse the command line options. */
+  DotlockFlags = 0;
+  
+  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;
+
+      /* 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]);
+    }
+  }
+
+  if (optind == argc || Retry < 0)
+    usage (argv[0]);
+
+  return dotlock_dispatch (argv[optind], -1);
+}
+
+
+/* 
+ * Determine our effective group ID, and drop 
+ * privileges.
+ * 
+ * Return value:
+ * 
+ *  0 - everything went fine
+ * -1 - we couldn't drop privileges.
+ * 
+ */
+
+
+static int
+dotlock_init_privs (void)
+{
+
+# ifdef USE_SETGID
+  
+  UserGid = getgid ();
+  MailGid = getegid ();
+
+  if (SETEGID (UserGid) != 0)
+    return -1;
+
+# endif
+
+  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];
+
+  /* If dotlock_prepare () succeeds [return value == 0],
+   * realpath contains the basename of f, and we have
+   * successfully changed our working directory to
+   * `dirname $f`.  Additionally, f has been opened for
+   * reading to verify that the user has at least read
+   * permissions on that file.
+   * 
+   * For a more detailed explanation of all this, see the
+   * lengthy comment below.
+   */
+
+  if (dotlock_prepare (realpath, sizeof (realpath), f, fd) != 0)
+    return DL_EX_ERROR;
+
+  /* Actually perform the locking operation. */
+
+  if (DotlockFlags & DL_FL_TRY)
+    return dotlock_try ();
+  else if (DotlockFlags & DL_FL_UNLOCK)
+    return dotlock_unlock (realpath);
+  else if (DotlockFlags & DL_FL_UNLINK)
+    return dotlock_unlink (realpath);
+  else /* lock */
+    return dotlock_lock (realpath);
+}
+
+  
+/*
+ * Get privileges 
+ * 
+ * This function re-acquires the privileges we may have
+ * if the user told us to do so by giving the "-p"
+ * command line option.
+ * 
+ * BEGIN_PRIVILEGES () won't return if an error occurs.
+ * 
+ */
+
+static void
+BEGIN_PRIVILEGED (void)
+{
+#ifdef USE_SETGID
+  if (DotlockFlags & DL_FL_USEPRIV)
+  {
+    if (SETEGID (MailGid) != 0)
+    {
+      /* perror ("setegid"); */
+      exit (DL_EX_ERROR);
+    }
+  }
+#endif
+}
+
+/*
+ * Drop privileges
+ * 
+ * This function drops the group privileges we may have.
+ * 
+ * END_PRIVILEGED () won't return if an error occurs.
+ *
+ */
+
+static void
+END_PRIVILEGED (void)
+{
+#ifdef USE_SETGID
+  if (DotlockFlags & DL_FL_USEPRIV)
+  {
+    if (SETEGID (UserGid) != 0)
+    {
+      /* perror ("setegid"); */
+      exit (DL_EX_ERROR);
+    }
+  }
+#endif
+}
+
+#ifdef DL_STANDALONE
+
+/*
+ * Usage information.
+ * 
+ * This function doesn't return.
+ * 
+ */
+
+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);
+
+  fputs ("\noptions:"
+	"\n  -t\t\ttry"
+	"\n  -f\t\tforce"
+	"\n  -u\t\tunlock"
+	"\n  -d\t\tunlink"
+	"\n  -p\t\tprivileged"
+#ifndef USE_SETGID
+	" (ignored)"
+#endif
+	"\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.
+ * 
+ * Some simple-minded access (2) checking isn't sufficient
+ * here: The problem is that the user may give us a
+ * deeply nested path to a file which has the same name
+ * as the file he wants to lock, but different
+ * permissions, say, e.g.
+ * /tmp/lots/of/subdirs/var/spool/mail/root.
+ * 
+ * He may then try to replace /tmp/lots/of/subdirs by a
+ * symbolic link to / after we have invoked access () to
+ * check the file's permissions.  The lockfile we'd
+ * create or remove would then actually be
+ * /var/spool/mail/root.
+ * 
+ * To avoid this attack, we proceed as follows:
+ * 
+ * - First, follow symbolic links a la
+ *   dotlock_deference_symlink ().
+ * 
+ * - get the result's dirname.
+ * 
+ * - chdir to this directory.  If you can't, bail out.
+ * 
+ * - try to open the file in question, only using its
+ *   basename.  If you can't, bail out.
+ * 
+ * - fstat that file and compare the result to a
+ *   subsequent lstat (only using the basename).  If
+ *   the comparison fails, bail out.
+ * 
+ * dotlock_prepare () is invoked from main () directly
+ * after the command line parsing has been done.
+ *
+ * Return values:
+ * 
+ * 0 - Evereything's fine.  The program's new current
+ *     directory is the contains the file to be locked.
+ *     The string pointed to by bn contains the name of
+ *     the file to be locked.
+ * 
+ * -1 - Something failed. Don't continue.
+ * 
+ * tlr, Jul 15 1998
+ */
+
+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.
+   * play safe.
+   */
+
+  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))
+  {
+    /* something's fishy */
+    return -1;
+  }
+  
+  return 0;
+}
+
+static int
+dotlock_prepare (char *bn, size_t l, const char *f, int _fd)
+{
+  struct stat fsb, lsb;
+  char realpath[_POSIX_PATH_MAX];
+  char *basename, *dirname;
+  char *p;
+  int fd;
+  int r;
+  
+  if (dotlock_deference_symlink (realpath, sizeof (realpath), f) == -1)
+    return -1;
+  
+  if ((p = strrchr (realpath, '/')))
+  {
+    *p = '\0';
+    basename = p + 1;
+    dirname = realpath;
+  }
+  else
+  {
+    basename = realpath;
+    dirname = ".";
+  }
+
+  if (strlen (basename) + 1 > l)
+    return -1;
+  
+  strfcpy (bn, basename, l);
+  
+  if (chdir (dirname) == -1)
+    return -1;
+
+  if (_fd != -1)
+    fd = _fd;
+  else if ((fd = open (basename, O_RDONLY)) == -1)
+    return -1;
+  
+  r = fstat (fd, &fsb);
+  
+  if (_fd == -1)
+    close (fd);
+  
+  if (r == -1)
+    return -1;
+  
+  if (lstat (basename, &lsb) == -1)
+    return -1;
+
+  if (dotlock_check_stats (&fsb, &lsb) == -1)
+    return -1;
+
+  return 0;
+}
+
+/*
+ * Expand a symbolic link.
+ * 
+ * This function expects newpath to have space for
+ * at least _POSIX_PATH_MAX characters.
+ *
+ */
+
+static void 
+dotlock_expand_link (char *newpath, const char *path, const char *link)
+{
+  const char *lb = NULL;
+  size_t len;
+
+  /* link is full path */
+  if (*link == '/')
+  {
+    strfcpy (newpath, link, _POSIX_PATH_MAX);
+    return;
+  }
+
+  if ((lb = strrchr (path, '/')) == NULL)
+  {
+    /* no path in link */
+    strfcpy (newpath, link, _POSIX_PATH_MAX);
+    return;
+  }
+
+  len = lb - path + 1;
+  memcpy (newpath, path, len);
+  strfcpy (newpath + len, link, _POSIX_PATH_MAX - len);
+}
+
+
+/*
+ * Deference a chain of symbolic links
+ * 
+ * The final path is written to d.
+ *
+ */
+
+static int
+dotlock_deference_symlink (char *d, size_t l, const char *path)
+{
+  struct stat sb;
+  char realpath[_POSIX_PATH_MAX];
+  const char *pathptr = path;
+  int count = 0;
+  
+  while (count++ < MAXLINKS)
+  {
+    if (lstat (pathptr, &sb) == -1)
+    {
+      /* perror (pathptr); */
+      return -1;
+    }
+    
+    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)) == -1)
+      {
+	/* perror (pathptr); */
+	return -1;
+      }
+      
+      linkfile[len] = '\0';
+      dotlock_expand_link (linkpath, pathptr, linkfile);
+      strfcpy (realpath, linkpath, sizeof (realpath));
+      pathptr = realpath;
+    }
+    else
+      break;
+  }
+
+  strfcpy (d, pathptr, l);
+  return 0;
+}
+
+/*
+ * Dotlock a file.
+ * 
+ * realpath is assumed _not_ to be an absolute path to
+ * the file we are about to lock.  Invoke
+ * dotlock_prepare () before using this function!
+ * 
+ */
+
+#define HARDMAXATTEMPTS 10
+
+static int
+dotlock_lock (const char *realpath)
+{
+  char lockfile[_POSIX_PATH_MAX + LONG_STRING];
+  char nfslockfile[_POSIX_PATH_MAX + LONG_STRING];
+  size_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);
+
+  
+  BEGIN_PRIVILEGED ();
+
+  unlink (nfslockfile);
+
+  while ((fd = open (nfslockfile, O_WRONLY | O_EXCL | O_CREAT, 0)) < 0)
+  {
+    END_PRIVILEGED ();
+
+  
+    if (errno != EAGAIN)
+    {
+      /* perror ("cannot open NFS lock file"); */
+      return DL_EX_ERROR;
+    }
+
+    
+    BEGIN_PRIVILEGED ();
+  }
+
+  END_PRIVILEGED ();
+
+  
+  close (fd);
+  
+  while (hard_count++ < HARDMAXATTEMPTS)
+  {
+
+    BEGIN_PRIVILEGED ();
+    link (nfslockfile, lockfile);
+    END_PRIVILEGED ();
+
+    if (stat (nfslockfile, &sb) != 0)
+    {
+      /* perror ("stat"); */
+      return DL_EX_ERROR;
+    }
+
+    if (sb.st_nlink == 2)
+      break;
+
+    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 ();
+
+	count = 0;
+	continue;
+      }
+      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);
+    } while (time (NULL) == t);
+  }
+
+  BEGIN_PRIVILEGED ();
+  unlink (nfslockfile);
+  END_PRIVILEGED ();
+
+  return DL_EX_OK;
+}
+
+
+/*
+ * Unlock a file. 
+ * 
+ * The same comment as for dotlock_lock () applies here.
+ * 
+ */
+
+static int
+dotlock_unlock (const char *realpath)
+{
+  char lockfile[_POSIX_PATH_MAX + LONG_STRING];
+  int i;
+
+  snprintf (lockfile, sizeof (lockfile), "%s.lock",
+	   realpath);
+  
+  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)
+{
+  struct stat lsb;
+  int i = -1;
+
+  if (dotlock_lock (realpath) != DL_EX_OK)
+    return DL_EX_ERROR;
+
+  if ((i = lstat (realpath, &lsb)) == 0 && lsb.st_size == 0)
+    unlink (realpath);
+
+  dotlock_unlock (realpath);
+
+  return (i == 0) ?  DL_EX_OK : DL_EX_ERROR;
+}
+
+
+/*
+ * Check if a file can be locked at all.
+ * 
+ * The same comment as for dotlock_lock () applies here.
+ * 
+ */
+
+static int
+dotlock_try (void)
+{
+#ifdef USE_SETGID
+  struct stat sb;
+#endif
+
+  if (access (".", W_OK) == 0)
+    return DL_EX_OK;
+
+#ifdef USE_SETGID
+  if (stat (".", &sb) == 0)
+  {
+    if ((sb.st_mode & S_IWGRP) == S_IWGRP && sb.st_gid == MailGid)
+      return DL_EX_NEED_PRIVS;
+  }
+#endif
+
+  return DL_EX_IMPOSSIBLE;
+}