commit-mailutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[SCM] GNU Mailutils branch, master, updated. mu-1-2-90-separate-argp-cfg


From: Sergey Poznyakoff
Subject: [SCM] GNU Mailutils branch, master, updated. mu-1-2-90-separate-argp-cfg-326-gb9aaf72
Date: Thu, 20 Aug 2009 20:40:00 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU Mailutils".

http://git.savannah.gnu.org/cgit/mailutils.git/commit/?id=b9aaf724c6428fb4e0d01950d4d7113671e048e5

The branch, master has been updated
       via  b9aaf724c6428fb4e0d01950d4d7113671e048e5 (commit)
       via  811b38863c06207ab3012c586176a113c1f8def1 (commit)
      from  1c0ee63834fc729e6ed49fcfa6965d8a7cc88f87 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit b9aaf724c6428fb4e0d01950d4d7113671e048e5
Author: Sergey Poznyakoff <address@hidden>
Date:   Thu Aug 20 23:39:45 2009 +0300

    Movemail: allow to copy mailbox ownership when run as root.
    
    * movemail/movemail.c: Implement new configuration keyword
    "mailbox-ownership" (and the --owner command line option).
    * doc/texinfo/programs.texi: Document new movemail features.
    (Ownership): New subsection stub.
    * NEWS: Update

commit 811b38863c06207ab3012c586176a113c1f8def1
Author: Sergey Poznyakoff <address@hidden>
Date:   Thu Aug 20 23:34:47 2009 +0300

    Fix in configure.ac
    
    * configure.ac: Use PATH_MAILDIR (without leading underscore).

-----------------------------------------------------------------------

Summary of changes:
 NEWS                      |    6 +-
 configure.ac              |    2 +-
 doc/texinfo/programs.texi |  119 +++++----------
 movemail/movemail.c       |  369 ++++++++++++++++++++++++++++++++++++++-------
 4 files changed, 361 insertions(+), 135 deletions(-)

diff --git a/NEWS b/NEWS
index ed4a90e..43b4403 100644
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,4 @@
-GNU mailutils NEWS -- history of user-visible changes. 2009-08-14
+GNU mailutils NEWS -- history of user-visible changes. 2009-08-20
 Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 
 2008, 2009 Free Software Foundation, Inc.
 See the end of file for copying conditions.
@@ -27,6 +27,10 @@ exists in the destination mailbox.
 The `--verbose' command line option enables outputting additional
 information.
 
+The `--owner' command line option (and the corresponding
+`mailbox-ownership' configuration file statement) copy mailbox
+ownership, if the utility is run with root privileges.
+
 * Mail
 
 ** The -f option
diff --git a/configure.ac b/configure.ac
index 0258618..f852b92 100644
--- a/configure.ac
+++ b/configure.ac
@@ -335,7 +335,7 @@ AH_BOTTOM(
 #ifdef MU_CONF_MAILDIR
 # define MU_PATH_MAILDIR MU_CONF_MAILDIR
 #else
-# define MU_PATH_MAILDIR _PATH_MAILDIR "/"
+# define MU_PATH_MAILDIR PATH_MAILDIR "/"
 #endif])
 
 use_dbm=no
diff --git a/doc/texinfo/programs.texi b/doc/texinfo/programs.texi
index 4135911..5cf7ef2 100644
--- a/doc/texinfo/programs.texi
+++ b/doc/texinfo/programs.texi
@@ -4371,13 +4371,15 @@ description of @code{Rmail} interface.
 
 Mailutils version of @command{movemail} is completely
 backward-compatible with its Emacs predecessor, so it should run
-flawlessly with older versions of Emacs. Emacs version 21.4, which is
-being developed at the time of this writing, will contain improved
address@hidden interface for work with mailutils @command{movemail}.
+flawlessly with older versions of Emacs. Emacs versions
+starting from 22.1 contain improved @code{Rmail} interface and
+are able to take advantage of all new features mailutils
address@hidden provides.
 
 @menu
 * Movemail Configuration::
 * Movemail Options::     Description of the Available Options
+* Ownership::            Setting Destination Mailbox Ownership
 * Summary::              Short Movemail Invocation Summary
 @end menu
 
@@ -4408,6 +4410,31 @@ exists in the destination mailbox.
 Set verbosity level.
 @end deffn
 
address@hidden {Movemail Config} mailbox-ownership @var{method-list}
+Define list of methods for setting ownership of the destination
+mailbox.  The @var{method-list} argument can contain the following
+elements:
+
address@hidden
address@hidden @asis
address@hidden copy-id
+Copy owner UID and GID from the source mailbox. This method works only
+with local mailboxes, i.e.: @samp{mbox} (UNIX mailbox), @samp{maildir}
+and @samp{mh}.
+
address@hidden copy-name
+Get owner name from the source mailbox URL and obtain UID and GID for
+this user using mailutils authorization methods.
+
address@hidden address@hidden:@var{gid}]
+Set supplied @var{uid} and @var{gid}. If @var{gid} is not supplied,
+it is read from the @file{/etc/passwd} record for this UID.
+
address@hidden address@hidden
+Make destination mailbox owned by @var{user}.
address@hidden table
address@hidden deffn
+
 @multitable @columnfractions 0.3 0.6
 @headitem Statement @tab Reference
 @item debug         @tab @xref{Debug Statement}.
@@ -4439,58 +4466,13 @@ If the remote server supports @acronym{TLS} encryption, 
use
 @option{--tls} to instruct @command{movemail} to initiate encrypted
 connection.
 
-Quite a few options control how @command{movemail} handles mail
-locking (a way of preventing simultaneous access to the source
-mailbox). By default, before accessing mailbox @var{file},
address@hidden will first see if the file named
address@hidden@var{file}.lock} (so called @dfn{lock file}) exists. If so, it
-will assume that the mailbox is being used by another program and will
-sleep one second. If @address@hidden file disappears after this
-wait period, the program will proceed. Otherwise, it will repeat this
-action ten times. If after ten wait periods the lock file does not
-disappear, @command{movemail} gives up and exits.
-
-If the lock file does not exist, @command{movemail} will create it,
-thereby indicating to other programs that the mailbox is being used,
-and will proceed to copying messages to the destination file. When
-finished, @command{movemail} closes the mailbox and removes the lock
-file.
-
-Several options control this behavior. To change the default sleep period
-use @option{--lock-retry-timeout}. Its argument is the timeout value
-in seconds.
-
-To change number of retries, use @option{--lock-retry-count}. For
-example, setting @code{rmail-movemail-flags} to
-
address@hidden
---lock-retry-timeout=2 --lock-retry-count=5
address@hidden smallexample
-
address@hidden
-instructs @command{movemail} to make five attempts to acquire the lock
-file, with two-second intervals between the attempts.
-
-You may also force @command{movemail} to remove the lock file if it is
-older than a given amount of time (a so called @dfn{stale lock
-file}). To do so, use the following option:
-
address@hidden
address@hidden
address@hidden smallexample
-
-The @option{--lock-expire-timeout} sets the number of seconds after
-which a lock file is considered stale.
address@hidden Ownership
address@hidden Setting Destination Mailbox Ownership
address@hidden
 
-There are special programs that can be used to lock and unlock
-mailboxes. A common example of such programs is @command{dotlock}. If
-you wish to use such @dfn{external locking program} instead of the
-default mailutils locking mechanism, use option
address@hidden Argument to this option specifies the full
-name of the external program to use.
 
 @node Summary
address@hidden Summary of Movemail Usage
address@hidden Movemail Usage Summary
 
 @smallexample
 movemail address@hidden @var{inbox} @var{destfile} address@hidden
@@ -4500,7 +4482,7 @@ The first argument, @var{inbox}, is the @acronym{url} 
(@pxref{URL}) of
 the source mailbox. The second argument, @var{destfile}, traditionally
 means destination file, i.e. the UNIX mailbox to copy messages
 to. However, mailutils @command{movemail} extends the meaning of this
-parameter. You may actually specify any valid @acronym{url} as
+parameter. You may actually specify any valid @acronym{URL} as
 @var{destfile} address@hidden does not use this
 feature}. Finally, optional third argument is a traditional way of
 specifying user passwords for remote (@acronym{POP} or @acronym{IMAP})
@@ -4521,30 +4503,6 @@ Preserve the source mailbox
 @itemx --reverse
 Reverse the sorting order
 
address@hidden address@hidden
-Use given @var{program} as the external locker program.
-
address@hidden address@hidden
-Set number of seconds after which the lock expires
-
address@hidden address@hidden
-Set locker flags. @var{flags} is composed of the following letters:
address@hidden -- use external locker program @command{dotlock},
address@hidden -- retry 10 times if acquiring of the lock failed (see also
address@hidden below), @samp{T} -- remove stale locks
-after 10 minutes (see also @option{--lock-expire-timeout},
-and @samp{P} -- write process @acronym{PID} to the lock file.
-
address@hidden address@hidden
-Set the maximum number of times to retry acquiring the lockfile
-
address@hidden address@hidden
-Set timeout for acquiring the lockfile
-
address@hidden -m @var{url}
address@hidden --mail-spool @var{URL}
-Use specified URL as a mailspool directory
-
 @item address@hidden
 Enable (default) or disable TLS support
 
@@ -4552,6 +4510,13 @@ Enable (default) or disable TLS support
 @item --uidl
 Use UIDLs to avoid downloading the same message twice.
 
address@hidden -P @var{method-list}
address@hidden address@hidden
+Define list of methods for setting ownership of the destination
+mailbox. @xref{mailbox-ownership-methods}, for a description of
address@hidden This option is useful only when running
address@hidden as root.
+
 @item -v
 @item --verbose
 Increase verbosity level.
diff --git a/movemail/movemail.c b/movemail/movemail.c
index bacfd40..99dc5b0 100644
--- a/movemail/movemail.c
+++ b/movemail/movemail.c
@@ -24,6 +24,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <sys/stat.h>
+#include <pwd.h>
 #include <grp.h>
 #include <unistd.h>
 #include <mailutils/mailutils.h>
@@ -39,30 +40,74 @@ static char args_doc[] = N_("inbox-url destfile 
[POP-password]");
 #define OPT_EMACS 256
 
 static struct argp_option options[] = {
-  { "preserve", 'p', NULL, 0, N_("Preserve the source mailbox"), 0 },
+  { "preserve", 'p', NULL, 0, N_("Preserve the source mailbox") },
   { "keep-messages", 0, NULL, OPTION_ALIAS, NULL },
-  { "reverse",  'r', NULL, 0, N_("Reverse the sorting order"), 0 },
+  { "reverse",  'r', NULL, 0, N_("Reverse the sorting order") },
   { "emacs", OPT_EMACS, NULL, 0,
-    N_("Output information used by Emacs rmail interface"), 0 },
-  { "copy-permissions", 'P', NULL, 0,
-    N_("Copy original mailbox permissions and ownership when applicable"),
-    0 },
+    N_("Output information used by Emacs rmail interface") },
   { "uidl", 'u', NULL, 0,
-    N_("Use UIDLs to avoid downloading the same message twice"),
-    0 },
+    N_("Use UIDLs to avoid downloading the same message twice") },
   { "verbose", 'v', NULL, 0,
-    N_("Increase verbosity level"),
-    0 },
+    N_("Increase verbosity level") },
+  { "owner", 'P', N_("MODELIST"), 0,
+    N_("Control mailbox ownership") },
   { NULL,      0, NULL, 0, NULL, 0 }
 };
 
 static int reverse_order;
 static int preserve_mail; 
 static int emacs_mode;
-static int copy_meta;
 static int uidl_option;
 static int verbose_option;
 
+enum set_ownership_mode
+  {
+    copy_owner_id,
+    copy_owner_name,
+    set_owner_id,
+    set_owner_name
+  };
+#define SET_OWNERSHIP_MAX 4
+
+struct user_id
+{
+  uid_t uid;
+  gid_t gid;
+};
+
+struct set_ownership_method
+{
+  enum set_ownership_mode mode;
+  union
+  {
+    char *name;
+    struct user_id id;
+  } owner;
+};
+
+static struct set_ownership_method so_methods[SET_OWNERSHIP_MAX];
+static int so_method_num;
+
+struct set_ownership_method *
+get_next_so_method ()
+{
+  if (so_method_num == MU_ARRAY_SIZE (so_methods))
+    {
+      mu_error (_("ownership method table overflow"));
+      exit (1);
+    }
+  return so_methods + so_method_num++;
+}
+
+mu_kwd_t method_kwd[] = {
+  { "copy-id", copy_owner_id }, 
+  { "copy-name", copy_owner_name },
+  { "set-name", set_owner_name },
+  { "user", set_owner_name },
+  { "set-id", set_owner_id },
+  { NULL }
+};
+
 static error_t
 parse_opt (int key, char *arg, struct argp_state *state)
 {
@@ -79,7 +124,7 @@ parse_opt (int key, char *arg, struct argp_state *state)
       break;
 
     case 'P':
-      copy_meta = 1;
+      mu_argp_node_list_new (&lst, "mailbox-ownership", arg);
       break;
 
     case 'u':
@@ -93,7 +138,7 @@ parse_opt (int key, char *arg, struct argp_state *state)
     case OPT_EMACS:
       mu_argp_node_list_new (&lst, "emacs", "yes");
       break;
-      
+
     case ARGP_KEY_INIT:
       mu_argp_node_list_init (&lst);
       break;
@@ -118,6 +163,130 @@ static struct argp argp = {
 };
 
 
+static int
+_cb_mailbox_ownership (mu_debug_t debug, const char *str)
+{
+  if (strcmp (str, "clear") == 0)
+    so_method_num = 0;
+  else
+    {
+      int code;
+      char *p;
+      size_t len = strcspn (str, "=");
+      struct set_ownership_method *meth;
+         
+      if (mu_kwd_xlat_name_len (method_kwd, str, len, &code))
+       {
+         mu_cfg_format_error (debug, MU_DEBUG_ERROR, 
+                              _("Invalid ownership method: %s"),
+                              str);
+         return 1;
+       }
+      
+      meth = get_next_so_method ();
+      meth->mode = code;
+      switch (meth->mode)
+       {
+       case copy_owner_id:
+       case copy_owner_name:
+         break;
+         
+       case set_owner_id:
+         if (!str[len])
+           {
+             mu_cfg_format_error (debug, MU_DEBUG_ERROR, 
+                                  _("Ownership method %s requires value"),
+                                  str);
+             return 1;
+           }
+         str += len + 1;
+         meth->owner.id.uid = strtoul (str, &p, 0);
+         if (*p)
+           {
+             if (*p == ':')
+               {
+                 str = p + 1;
+                 meth->owner.id.gid = strtoul (str, &p, 0);
+                 if (*p)
+                   {
+                     mu_cfg_format_error (debug, MU_DEBUG_ERROR, 
+                                          _("expected gid number, but found 
%s"),
+                                          str);
+                     return 1;
+                   }
+               }
+             else
+               {
+                 mu_cfg_format_error (debug, MU_DEBUG_ERROR, 
+                                      _("expected uid number, but found %s"),
+                                      str);
+                 return 1;
+               }
+           }
+         else
+           meth->owner.id.gid = (gid_t) -1;
+         break;
+         
+       case set_owner_name:
+         if (!str[len])
+           {
+             mu_cfg_format_error (debug, MU_DEBUG_ERROR, 
+                                  _("Ownership method %s requires value"),
+                                  str);
+             return 1;
+           }
+         meth->owner.name = mu_strdup (str + len + 1);
+       }
+    }
+  return 0;
+}
+
+static int
+cb_mailbox_ownership (mu_debug_t debug, void *data, mu_config_value_t *val)
+{
+  int i;
+  
+  if (val->type == MU_CFG_STRING)
+    {
+      const char *str = val->v.string;
+      if (!strchr (str, ','))
+       return _cb_mailbox_ownership (debug, str);
+      else
+       {
+         int argc;
+         char **argv;
+
+         if (mu_argcv_get_np (str, strlen (str), ",", NULL, 0,
+                              &argc, &argv, NULL))
+           {
+             mu_cfg_format_error (debug, MU_DEBUG_ERROR, 
+                                  _("cannot parse %s"),
+                                  str);
+             return 1;
+           }
+
+         for (i = 0; i < argc; i++)
+           if (_cb_mailbox_ownership (debug, argv[i]))
+             return 1;
+
+         mu_argcv_free (argc, argv);
+         return 0;
+       }
+    }
+               
+  if (mu_cfg_assert_value_type (val, MU_CFG_LIST, debug))
+    return 1;
+
+  for (i = 0; i < val->v.arg.c; i++)
+    {
+      if (mu_cfg_assert_value_type (&val->v.arg.v[i], MU_CFG_STRING, debug))
+       return 1;
+      if (_cb_mailbox_ownership (debug, val->v.arg.v[i].v.string))
+       return 1;
+    }
+  return 0;
+}
+
 struct mu_cfg_param movemail_cfg_param[] = {
   { "preserve", mu_cfg_bool, &preserve_mail, 0, NULL,
     N_("Do not remove messages from the source mailbox.") },
@@ -128,7 +297,16 @@ struct mu_cfg_param movemail_cfg_param[] = {
   { "uidl", mu_cfg_bool, &uidl_option, 0, NULL,
     N_("Use UIDLs to avoid downloading the same message twice.") },
   { "verbose", mu_cfg_int, &verbose_option, 0, NULL,
-    N_("Increase verbosity level.") },
+    N_("Set verbosity level.") },
+  { "mailbox-ownership", mu_cfg_callback, NULL, 0,
+    cb_mailbox_ownership,
+    N_("Define a list of methods for setting mailbox ownership. Valid "
+       "methods are:\n"
+       " copy-id          get owner UID and GID from the source mailbox\n"
+       " copy-name        get owner name from the source mailbox URL\n"
+       " set-id=UID[:GID] set supplied UID and GID\n"
+       " set-name=USER    make destination mailbox owned by USER"),
+    N_("methods: list") },
   { NULL }
 };
 
@@ -300,29 +478,18 @@ close_mailboxes (void)
   mu_mailbox_close (dest);
   mu_mailbox_close (source);
 }  
-
-static void
-set_permissions (mu_mailbox_t mbox)
+
+static int
+get_mbox_owner_id (mu_mailbox_t mbox, mu_url_t url, struct user_id *id)
 {
-  mu_url_t url = NULL;
   const char *s;
-  int rc;
-  uid_t uid;
-  gid_t gid;
-  
-  if (getuid () != 0)
-    {
-      mu_error (_("must be root to use --copy-permissions"));
-      exit (1);
-    }
-  mu_mailbox_get_url (mbox, &url);
-  rc = mu_url_sget_scheme  (url, &s);
+  int rc = mu_url_sget_scheme  (url, &s);
   if (rc)
     die (mbox, _("Cannot get scheme"), rc);
-  if (strcmp (s, "/") == 0
-      || strcmp (s, "mbox") == 0
-      || strcmp (s, "mh") == 0
-      || strcmp (s, "maildir") == 0)
+  if ((strcmp (s, "/") == 0
+       || strcmp (s, "mbox") == 0
+       || strcmp (s, "mh") == 0
+       || strcmp (s, "maildir") == 0))
     {
       struct stat st;
       
@@ -335,33 +502,124 @@ set_permissions (mu_mailbox_t mbox)
                    mu_strerror (errno));
          exit (1);
        }
-      uid = st.st_uid;
-      gid = st.st_gid;
+      id->uid = st.st_uid;
+      id->gid = st.st_gid;
+      return 0;
     }
-  else
+  else if (verbose_option)
+    mu_diag_output (MU_DIAG_WARNING,
+                   _("ignoring copy-name: not a local mailbox"));
+  return 1;
+}
+
+static int
+get_user_id (const char *name, struct user_id *id)
+{
+  struct mu_auth_data *auth = mu_get_auth_by_name (name);
+  
+  if (!auth)
     {
-      struct mu_auth_data *auth;
-      
-      rc = mu_url_sget_user (url, &s);
-      if (rc)
-       die (mbox, _("Cannot get user"), rc);
-      
-      auth = mu_get_auth_by_name (s);
-      if (!auth)
-       {
-         mu_error (_("No such user: %s"), s);
-         exit (1);
-       }
-      else
+      if (verbose_option)
+       mu_diag_output (MU_DIAG_WARNING, _("no such user: %s"), name);
+      return 1;
+    }
+
+  id->uid = auth->uid;
+  id->gid = auth->gid;
+  mu_auth_data_free (auth);
+  return 0;
+}  
+
+static int
+get_mbox_owner_name (mu_mailbox_t mbox, mu_url_t url, struct user_id *id)
+{
+  const char *s;
+  int rc = mu_url_sget_user (url, &s);
+  if (rc)
+    /* FIXME */
+    die (mbox, _("Cannot get mailbox owner name"), rc);
+
+  return get_user_id (s, id);
+}
+
+static int
+guess_mbox_owner (mu_mailbox_t mbox, struct user_id *id)
+{
+  mu_url_t url = NULL;
+  int rc;
+  struct set_ownership_method *meth;
+  
+  rc = mu_mailbox_get_url (mbox, &url);
+  if (rc)
+    die (mbox, _("Cannot get url"), rc);
+
+  rc = 1;
+  for (meth = so_methods; rc == 1 && meth < so_methods + so_method_num; meth++)
+    {
+      switch (meth->mode)
        {
-         uid = auth->uid;
-         gid = auth->gid;
+       case copy_owner_id:
+         rc = get_mbox_owner_id (mbox, url, id);
+         break;
+         
+       case copy_owner_name:
+         rc = get_mbox_owner_name (mbox, url, id);
+         break;
+         
+       case set_owner_id:
+         id->uid = meth->owner.id.uid;
+         rc = 0;
+         if (meth->owner.id.gid == (gid_t)-1)
+           {
+             struct passwd *pw = getpwuid (id->uid);
+             if (pw)
+               id->gid = pw->pw_gid;
+             else
+               {
+                 if (verbose_option)
+                   mu_diag_output (MU_DIAG_WARNING,
+                                   _("no user with uid %lu found"),
+                                   (unsigned long) id->uid);
+                 rc = 1;
+               }
+           }
+         break;
+         
+       case set_owner_name:
+         rc = get_user_id (meth->owner.name, id);
+         break;
        }
-      mu_auth_data_free (auth);
     }
+  
+  return rc;
+}
 
-  if (mu_switch_to_privs (uid, gid, NULL))
-    exit (1);
+static void
+switch_owner (mu_mailbox_t mbox)
+{
+  struct user_id user_id;
+
+  if (so_method_num == 0)
+    return;
+
+  if (getuid ())
+    {
+      if (verbose_option)
+       mu_diag_output (MU_DIAG_WARNING,
+                       _("ignoring mailbox-ownership statement"));
+      return;
+    }
+  
+  if (guess_mbox_owner (mbox, &user_id) == 0)
+    {
+      if (mu_switch_to_privs (user_id.uid, user_id.gid, NULL))
+       exit (1);
+    }
+  else
+    {
+      mu_error (_("no suitable method for setting mailbox ownership"));
+      exit (1);
+    }
 }
 
 static int
@@ -443,8 +701,7 @@ main (int argc, char **argv)
   else
     open_mailbox (&source, source_name, flags, argv[2]);
 
-  if (copy_meta) 
-    set_permissions (source);
+  switch_owner (source);
   
   open_mailbox (&dest, dest_name, MU_STREAM_RDWR | MU_STREAM_CREAT, NULL);
 


hooks/post-receive
-- 
GNU Mailutils




reply via email to

[Prev in Thread] Current Thread [Next in Thread]