Commit b9aaf724 b9aaf724c6428fb4e0d01950d4d7113671e048e5 by Sergey Poznyakoff

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
1 parent 811b3886
1 GNU mailutils NEWS -- history of user-visible changes. 2009-08-14 1 GNU mailutils NEWS -- history of user-visible changes. 2009-08-20
2 Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2 Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007,
3 2008, 2009 Free Software Foundation, Inc. 3 2008, 2009 Free Software Foundation, Inc.
4 See the end of file for copying conditions. 4 See the end of file for copying conditions.
...@@ -27,6 +27,10 @@ exists in the destination mailbox. ...@@ -27,6 +27,10 @@ exists in the destination mailbox.
27 The `--verbose' command line option enables outputting additional 27 The `--verbose' command line option enables outputting additional
28 information. 28 information.
29 29
30 The `--owner' command line option (and the corresponding
31 `mailbox-ownership' configuration file statement) copy mailbox
32 ownership, if the utility is run with root privileges.
33
30 * Mail 34 * Mail
31 35
32 ** The -f option 36 ** The -f option
......
...@@ -4371,13 +4371,15 @@ description of @code{Rmail} interface. ...@@ -4371,13 +4371,15 @@ description of @code{Rmail} interface.
4371 4371
4372 Mailutils version of @command{movemail} is completely 4372 Mailutils version of @command{movemail} is completely
4373 backward-compatible with its Emacs predecessor, so it should run 4373 backward-compatible with its Emacs predecessor, so it should run
4374 flawlessly with older versions of Emacs. Emacs version 21.4, which is 4374 flawlessly with older versions of Emacs. Emacs versions
4375 being developed at the time of this writing, will contain improved 4375 starting from 22.1 contain improved @code{Rmail} interface and
4376 @code{Rmail} interface for work with mailutils @command{movemail}. 4376 are able to take advantage of all new features mailutils
4377 @command{movemail} provides.
4377 4378
4378 @menu 4379 @menu
4379 * Movemail Configuration:: 4380 * Movemail Configuration::
4380 * Movemail Options:: Description of the Available Options 4381 * Movemail Options:: Description of the Available Options
4382 * Ownership:: Setting Destination Mailbox Ownership
4381 * Summary:: Short Movemail Invocation Summary 4383 * Summary:: Short Movemail Invocation Summary
4382 @end menu 4384 @end menu
4383 4385
...@@ -4408,6 +4410,31 @@ exists in the destination mailbox. ...@@ -4408,6 +4410,31 @@ exists in the destination mailbox.
4408 Set verbosity level. 4410 Set verbosity level.
4409 @end deffn 4411 @end deffn
4410 4412
4413 @deffn {Movemail Config} mailbox-ownership @var{method-list}
4414 Define list of methods for setting ownership of the destination
4415 mailbox. The @var{method-list} argument can contain the following
4416 elements:
4417
4418 @anchor{mailbox-ownership-methods}
4419 @table @asis
4420 @item copy-id
4421 Copy owner UID and GID from the source mailbox. This method works only
4422 with local mailboxes, i.e.: @samp{mbox} (UNIX mailbox), @samp{maildir}
4423 and @samp{mh}.
4424
4425 @item copy-name
4426 Get owner name from the source mailbox URL and obtain UID and GID for
4427 this user using mailutils authorization methods.
4428
4429 @item set-id=@var{uid}[:@var{gid}]
4430 Set supplied @var{uid} and @var{gid}. If @var{gid} is not supplied,
4431 it is read from the @file{/etc/passwd} record for this UID.
4432
4433 @item set-name=@var{user}
4434 Make destination mailbox owned by @var{user}.
4435 @end table
4436 @end deffn
4437
4411 @multitable @columnfractions 0.3 0.6 4438 @multitable @columnfractions 0.3 0.6
4412 @headitem Statement @tab Reference 4439 @headitem Statement @tab Reference
4413 @item debug @tab @xref{Debug Statement}. 4440 @item debug @tab @xref{Debug Statement}.
...@@ -4439,58 +4466,13 @@ If the remote server supports @acronym{TLS} encryption, use ...@@ -4439,58 +4466,13 @@ If the remote server supports @acronym{TLS} encryption, use
4439 @option{--tls} to instruct @command{movemail} to initiate encrypted 4466 @option{--tls} to instruct @command{movemail} to initiate encrypted
4440 connection. 4467 connection.
4441 4468
4442 Quite a few options control how @command{movemail} handles mail 4469 @node Ownership
4443 locking (a way of preventing simultaneous access to the source 4470 @subsection Setting Destination Mailbox Ownership
4444 mailbox). By default, before accessing mailbox @var{file}, 4471 @UNREVISED
4445 @command{movemail} will first see if the file named
4446 @file{@var{file}.lock} (so called @dfn{lock file}) exists. If so, it
4447 will assume that the mailbox is being used by another program and will
4448 sleep one second. If @file{@var{file}.lock} file disappears after this
4449 wait period, the program will proceed. Otherwise, it will repeat this
4450 action ten times. If after ten wait periods the lock file does not
4451 disappear, @command{movemail} gives up and exits.
4452
4453 If the lock file does not exist, @command{movemail} will create it,
4454 thereby indicating to other programs that the mailbox is being used,
4455 and will proceed to copying messages to the destination file. When
4456 finished, @command{movemail} closes the mailbox and removes the lock
4457 file.
4458
4459 Several options control this behavior. To change the default sleep period
4460 use @option{--lock-retry-timeout}. Its argument is the timeout value
4461 in seconds.
4462
4463 To change number of retries, use @option{--lock-retry-count}. For
4464 example, setting @code{rmail-movemail-flags} to
4465
4466 @smallexample
4467 --lock-retry-timeout=2 --lock-retry-count=5
4468 @end smallexample
4469
4470 @noindent
4471 instructs @command{movemail} to make five attempts to acquire the lock
4472 file, with two-second intervals between the attempts.
4473
4474 You may also force @command{movemail} to remove the lock file if it is
4475 older than a given amount of time (a so called @dfn{stale lock
4476 file}). To do so, use the following option:
4477
4478 @smallexample
4479 --lock-expire-timeout=@var{seconds}
4480 @end smallexample
4481
4482 The @option{--lock-expire-timeout} sets the number of seconds after
4483 which a lock file is considered stale.
4484 4472
4485 There are special programs that can be used to lock and unlock
4486 mailboxes. A common example of such programs is @command{dotlock}. If
4487 you wish to use such @dfn{external locking program} instead of the
4488 default mailutils locking mechanism, use option
4489 @option{--external-locker}. Argument to this option specifies the full
4490 name of the external program to use.
4491 4473
4492 @node Summary 4474 @node Summary
4493 @subsection Summary of Movemail Usage 4475 @subsection Movemail Usage Summary
4494 4476
4495 @smallexample 4477 @smallexample
4496 movemail [@var{option}...] @var{inbox} @var{destfile} [@var{remote-password}] 4478 movemail [@var{option}...] @var{inbox} @var{destfile} [@var{remote-password}]
...@@ -4500,7 +4482,7 @@ The first argument, @var{inbox}, is the @acronym{url} (@pxref{URL}) of ...@@ -4500,7 +4482,7 @@ The first argument, @var{inbox}, is the @acronym{url} (@pxref{URL}) of
4500 the source mailbox. The second argument, @var{destfile}, traditionally 4482 the source mailbox. The second argument, @var{destfile}, traditionally
4501 means destination file, i.e. the UNIX mailbox to copy messages 4483 means destination file, i.e. the UNIX mailbox to copy messages
4502 to. However, mailutils @command{movemail} extends the meaning of this 4484 to. However, mailutils @command{movemail} extends the meaning of this
4503 parameter. You may actually specify any valid @acronym{url} as 4485 parameter. You may actually specify any valid @acronym{URL} as
4504 @var{destfile} parameter.@footnote{Rmail does not use this 4486 @var{destfile} parameter.@footnote{Rmail does not use this
4505 feature}. Finally, optional third argument is a traditional way of 4487 feature}. Finally, optional third argument is a traditional way of
4506 specifying user passwords for remote (@acronym{POP} or @acronym{IMAP}) 4488 specifying user passwords for remote (@acronym{POP} or @acronym{IMAP})
...@@ -4521,30 +4503,6 @@ Preserve the source mailbox ...@@ -4521,30 +4503,6 @@ Preserve the source mailbox
4521 @itemx --reverse 4503 @itemx --reverse
4522 Reverse the sorting order 4504 Reverse the sorting order
4523 4505
4524 @item --external-locker=@var{program}
4525 Use given @var{program} as the external locker program.
4526
4527 @item --lock-expire-timeout=@var{seconds}
4528 Set number of seconds after which the lock expires
4529
4530 @item --lock-flags=@var{flags}
4531 Set locker flags. @var{flags} is composed of the following letters:
4532 @samp{E} -- use external locker program @command{dotlock},
4533 @samp{R} -- retry 10 times if acquiring of the lock failed (see also
4534 @option{--lock-retry-count} below), @samp{T} -- remove stale locks
4535 after 10 minutes (see also @option{--lock-expire-timeout},
4536 and @samp{P} -- write process @acronym{PID} to the lock file.
4537
4538 @item --lock-retry-count=@var{number}
4539 Set the maximum number of times to retry acquiring the lockfile
4540
4541 @item --lock-retry-timeout=@var{seconds}
4542 Set timeout for acquiring the lockfile
4543
4544 @item -m @var{url}
4545 @itemx --mail-spool @var{URL}
4546 Use specified URL as a mailspool directory
4547
4548 @item --tls[=@var{bool}] 4506 @item --tls[=@var{bool}]
4549 Enable (default) or disable TLS support 4507 Enable (default) or disable TLS support
4550 4508
...@@ -4552,6 +4510,13 @@ Enable (default) or disable TLS support ...@@ -4552,6 +4510,13 @@ Enable (default) or disable TLS support
4552 @item --uidl 4510 @item --uidl
4553 Use UIDLs to avoid downloading the same message twice. 4511 Use UIDLs to avoid downloading the same message twice.
4554 4512
4513 @item -P @var{method-list}
4514 @itemx --owner=@var{method-list}
4515 Define list of methods for setting ownership of the destination
4516 mailbox. @xref{mailbox-ownership-methods}, for a description of
4517 @var{method-list}. This option is useful only when running
4518 @command{movemail} as root.
4519
4555 @item -v 4520 @item -v
4556 @item --verbose 4521 @item --verbose
4557 Increase verbosity level. 4522 Increase verbosity level.
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
24 #include <stdlib.h> 24 #include <stdlib.h>
25 #include <string.h> 25 #include <string.h>
26 #include <sys/stat.h> 26 #include <sys/stat.h>
27 #include <pwd.h>
27 #include <grp.h> 28 #include <grp.h>
28 #include <unistd.h> 29 #include <unistd.h>
29 #include <mailutils/mailutils.h> 30 #include <mailutils/mailutils.h>
...@@ -39,30 +40,74 @@ static char args_doc[] = N_("inbox-url destfile [POP-password]"); ...@@ -39,30 +40,74 @@ static char args_doc[] = N_("inbox-url destfile [POP-password]");
39 #define OPT_EMACS 256 40 #define OPT_EMACS 256
40 41
41 static struct argp_option options[] = { 42 static struct argp_option options[] = {
42 { "preserve", 'p', NULL, 0, N_("Preserve the source mailbox"), 0 }, 43 { "preserve", 'p', NULL, 0, N_("Preserve the source mailbox") },
43 { "keep-messages", 0, NULL, OPTION_ALIAS, NULL }, 44 { "keep-messages", 0, NULL, OPTION_ALIAS, NULL },
44 { "reverse", 'r', NULL, 0, N_("Reverse the sorting order"), 0 }, 45 { "reverse", 'r', NULL, 0, N_("Reverse the sorting order") },
45 { "emacs", OPT_EMACS, NULL, 0, 46 { "emacs", OPT_EMACS, NULL, 0,
46 N_("Output information used by Emacs rmail interface"), 0 }, 47 N_("Output information used by Emacs rmail interface") },
47 { "copy-permissions", 'P', NULL, 0,
48 N_("Copy original mailbox permissions and ownership when applicable"),
49 0 },
50 { "uidl", 'u', NULL, 0, 48 { "uidl", 'u', NULL, 0,
51 N_("Use UIDLs to avoid downloading the same message twice"), 49 N_("Use UIDLs to avoid downloading the same message twice") },
52 0 },
53 { "verbose", 'v', NULL, 0, 50 { "verbose", 'v', NULL, 0,
54 N_("Increase verbosity level"), 51 N_("Increase verbosity level") },
55 0 }, 52 { "owner", 'P', N_("MODELIST"), 0,
53 N_("Control mailbox ownership") },
56 { NULL, 0, NULL, 0, NULL, 0 } 54 { NULL, 0, NULL, 0, NULL, 0 }
57 }; 55 };
58 56
59 static int reverse_order; 57 static int reverse_order;
60 static int preserve_mail; 58 static int preserve_mail;
61 static int emacs_mode; 59 static int emacs_mode;
62 static int copy_meta;
63 static int uidl_option; 60 static int uidl_option;
64 static int verbose_option; 61 static int verbose_option;
65 62
63 enum set_ownership_mode
64 {
65 copy_owner_id,
66 copy_owner_name,
67 set_owner_id,
68 set_owner_name
69 };
70 #define SET_OWNERSHIP_MAX 4
71
72 struct user_id
73 {
74 uid_t uid;
75 gid_t gid;
76 };
77
78 struct set_ownership_method
79 {
80 enum set_ownership_mode mode;
81 union
82 {
83 char *name;
84 struct user_id id;
85 } owner;
86 };
87
88 static struct set_ownership_method so_methods[SET_OWNERSHIP_MAX];
89 static int so_method_num;
90
91 struct set_ownership_method *
92 get_next_so_method ()
93 {
94 if (so_method_num == MU_ARRAY_SIZE (so_methods))
95 {
96 mu_error (_("ownership method table overflow"));
97 exit (1);
98 }
99 return so_methods + so_method_num++;
100 }
101
102 mu_kwd_t method_kwd[] = {
103 { "copy-id", copy_owner_id },
104 { "copy-name", copy_owner_name },
105 { "set-name", set_owner_name },
106 { "user", set_owner_name },
107 { "set-id", set_owner_id },
108 { NULL }
109 };
110
66 static error_t 111 static error_t
67 parse_opt (int key, char *arg, struct argp_state *state) 112 parse_opt (int key, char *arg, struct argp_state *state)
68 { 113 {
...@@ -79,7 +124,7 @@ parse_opt (int key, char *arg, struct argp_state *state) ...@@ -79,7 +124,7 @@ parse_opt (int key, char *arg, struct argp_state *state)
79 break; 124 break;
80 125
81 case 'P': 126 case 'P':
82 copy_meta = 1; 127 mu_argp_node_list_new (&lst, "mailbox-ownership", arg);
83 break; 128 break;
84 129
85 case 'u': 130 case 'u':
...@@ -118,6 +163,130 @@ static struct argp argp = { ...@@ -118,6 +163,130 @@ static struct argp argp = {
118 }; 163 };
119 164
120 165
166 static int
167 _cb_mailbox_ownership (mu_debug_t debug, const char *str)
168 {
169 if (strcmp (str, "clear") == 0)
170 so_method_num = 0;
171 else
172 {
173 int code;
174 char *p;
175 size_t len = strcspn (str, "=");
176 struct set_ownership_method *meth;
177
178 if (mu_kwd_xlat_name_len (method_kwd, str, len, &code))
179 {
180 mu_cfg_format_error (debug, MU_DEBUG_ERROR,
181 _("Invalid ownership method: %s"),
182 str);
183 return 1;
184 }
185
186 meth = get_next_so_method ();
187 meth->mode = code;
188 switch (meth->mode)
189 {
190 case copy_owner_id:
191 case copy_owner_name:
192 break;
193
194 case set_owner_id:
195 if (!str[len])
196 {
197 mu_cfg_format_error (debug, MU_DEBUG_ERROR,
198 _("Ownership method %s requires value"),
199 str);
200 return 1;
201 }
202 str += len + 1;
203 meth->owner.id.uid = strtoul (str, &p, 0);
204 if (*p)
205 {
206 if (*p == ':')
207 {
208 str = p + 1;
209 meth->owner.id.gid = strtoul (str, &p, 0);
210 if (*p)
211 {
212 mu_cfg_format_error (debug, MU_DEBUG_ERROR,
213 _("expected gid number, but found %s"),
214 str);
215 return 1;
216 }
217 }
218 else
219 {
220 mu_cfg_format_error (debug, MU_DEBUG_ERROR,
221 _("expected uid number, but found %s"),
222 str);
223 return 1;
224 }
225 }
226 else
227 meth->owner.id.gid = (gid_t) -1;
228 break;
229
230 case set_owner_name:
231 if (!str[len])
232 {
233 mu_cfg_format_error (debug, MU_DEBUG_ERROR,
234 _("Ownership method %s requires value"),
235 str);
236 return 1;
237 }
238 meth->owner.name = mu_strdup (str + len + 1);
239 }
240 }
241 return 0;
242 }
243
244 static int
245 cb_mailbox_ownership (mu_debug_t debug, void *data, mu_config_value_t *val)
246 {
247 int i;
248
249 if (val->type == MU_CFG_STRING)
250 {
251 const char *str = val->v.string;
252 if (!strchr (str, ','))
253 return _cb_mailbox_ownership (debug, str);
254 else
255 {
256 int argc;
257 char **argv;
258
259 if (mu_argcv_get_np (str, strlen (str), ",", NULL, 0,
260 &argc, &argv, NULL))
261 {
262 mu_cfg_format_error (debug, MU_DEBUG_ERROR,
263 _("cannot parse %s"),
264 str);
265 return 1;
266 }
267
268 for (i = 0; i < argc; i++)
269 if (_cb_mailbox_ownership (debug, argv[i]))
270 return 1;
271
272 mu_argcv_free (argc, argv);
273 return 0;
274 }
275 }
276
277 if (mu_cfg_assert_value_type (val, MU_CFG_LIST, debug))
278 return 1;
279
280 for (i = 0; i < val->v.arg.c; i++)
281 {
282 if (mu_cfg_assert_value_type (&val->v.arg.v[i], MU_CFG_STRING, debug))
283 return 1;
284 if (_cb_mailbox_ownership (debug, val->v.arg.v[i].v.string))
285 return 1;
286 }
287 return 0;
288 }
289
121 struct mu_cfg_param movemail_cfg_param[] = { 290 struct mu_cfg_param movemail_cfg_param[] = {
122 { "preserve", mu_cfg_bool, &preserve_mail, 0, NULL, 291 { "preserve", mu_cfg_bool, &preserve_mail, 0, NULL,
123 N_("Do not remove messages from the source mailbox.") }, 292 N_("Do not remove messages from the source mailbox.") },
...@@ -128,7 +297,16 @@ struct mu_cfg_param movemail_cfg_param[] = { ...@@ -128,7 +297,16 @@ struct mu_cfg_param movemail_cfg_param[] = {
128 { "uidl", mu_cfg_bool, &uidl_option, 0, NULL, 297 { "uidl", mu_cfg_bool, &uidl_option, 0, NULL,
129 N_("Use UIDLs to avoid downloading the same message twice.") }, 298 N_("Use UIDLs to avoid downloading the same message twice.") },
130 { "verbose", mu_cfg_int, &verbose_option, 0, NULL, 299 { "verbose", mu_cfg_int, &verbose_option, 0, NULL,
131 N_("Increase verbosity level.") }, 300 N_("Set verbosity level.") },
301 { "mailbox-ownership", mu_cfg_callback, NULL, 0,
302 cb_mailbox_ownership,
303 N_("Define a list of methods for setting mailbox ownership. Valid "
304 "methods are:\n"
305 " copy-id get owner UID and GID from the source mailbox\n"
306 " copy-name get owner name from the source mailbox URL\n"
307 " set-id=UID[:GID] set supplied UID and GID\n"
308 " set-name=USER make destination mailbox owned by USER"),
309 N_("methods: list") },
132 { NULL } 310 { NULL }
133 }; 311 };
134 312
...@@ -301,28 +479,17 @@ close_mailboxes (void) ...@@ -301,28 +479,17 @@ close_mailboxes (void)
301 mu_mailbox_close (source); 479 mu_mailbox_close (source);
302 } 480 }
303 481
304 static void 482 static int
305 set_permissions (mu_mailbox_t mbox) 483 get_mbox_owner_id (mu_mailbox_t mbox, mu_url_t url, struct user_id *id)
306 { 484 {
307 mu_url_t url = NULL;
308 const char *s; 485 const char *s;
309 int rc; 486 int rc = mu_url_sget_scheme (url, &s);
310 uid_t uid;
311 gid_t gid;
312
313 if (getuid () != 0)
314 {
315 mu_error (_("must be root to use --copy-permissions"));
316 exit (1);
317 }
318 mu_mailbox_get_url (mbox, &url);
319 rc = mu_url_sget_scheme (url, &s);
320 if (rc) 487 if (rc)
321 die (mbox, _("Cannot get scheme"), rc); 488 die (mbox, _("Cannot get scheme"), rc);
322 if (strcmp (s, "/") == 0 489 if ((strcmp (s, "/") == 0
323 || strcmp (s, "mbox") == 0 490 || strcmp (s, "mbox") == 0
324 || strcmp (s, "mh") == 0 491 || strcmp (s, "mh") == 0
325 || strcmp (s, "maildir") == 0) 492 || strcmp (s, "maildir") == 0))
326 { 493 {
327 struct stat st; 494 struct stat st;
328 495
...@@ -335,33 +502,124 @@ set_permissions (mu_mailbox_t mbox) ...@@ -335,33 +502,124 @@ set_permissions (mu_mailbox_t mbox)
335 mu_strerror (errno)); 502 mu_strerror (errno));
336 exit (1); 503 exit (1);
337 } 504 }
338 uid = st.st_uid; 505 id->uid = st.st_uid;
339 gid = st.st_gid; 506 id->gid = st.st_gid;
507 return 0;
340 } 508 }
341 else 509 else if (verbose_option)
342 { 510 mu_diag_output (MU_DIAG_WARNING,
343 struct mu_auth_data *auth; 511 _("ignoring copy-name: not a local mailbox"));
512 return 1;
513 }
344 514
345 rc = mu_url_sget_user (url, &s); 515 static int
346 if (rc) 516 get_user_id (const char *name, struct user_id *id)
347 die (mbox, _("Cannot get user"), rc); 517 {
518 struct mu_auth_data *auth = mu_get_auth_by_name (name);
348 519
349 auth = mu_get_auth_by_name (s);
350 if (!auth) 520 if (!auth)
351 { 521 {
352 mu_error (_("No such user: %s"), s); 522 if (verbose_option)
353 exit (1); 523 mu_diag_output (MU_DIAG_WARNING, _("no such user: %s"), name);
524 return 1;
354 } 525 }
526
527 id->uid = auth->uid;
528 id->gid = auth->gid;
529 mu_auth_data_free (auth);
530 return 0;
531 }
532
533 static int
534 get_mbox_owner_name (mu_mailbox_t mbox, mu_url_t url, struct user_id *id)
535 {
536 const char *s;
537 int rc = mu_url_sget_user (url, &s);
538 if (rc)
539 /* FIXME */
540 die (mbox, _("Cannot get mailbox owner name"), rc);
541
542 return get_user_id (s, id);
543 }
544
545 static int
546 guess_mbox_owner (mu_mailbox_t mbox, struct user_id *id)
547 {
548 mu_url_t url = NULL;
549 int rc;
550 struct set_ownership_method *meth;
551
552 rc = mu_mailbox_get_url (mbox, &url);
553 if (rc)
554 die (mbox, _("Cannot get url"), rc);
555
556 rc = 1;
557 for (meth = so_methods; rc == 1 && meth < so_methods + so_method_num; meth++)
558 {
559 switch (meth->mode)
560 {
561 case copy_owner_id:
562 rc = get_mbox_owner_id (mbox, url, id);
563 break;
564
565 case copy_owner_name:
566 rc = get_mbox_owner_name (mbox, url, id);
567 break;
568
569 case set_owner_id:
570 id->uid = meth->owner.id.uid;
571 rc = 0;
572 if (meth->owner.id.gid == (gid_t)-1)
573 {
574 struct passwd *pw = getpwuid (id->uid);
575 if (pw)
576 id->gid = pw->pw_gid;
355 else 577 else
356 { 578 {
357 uid = auth->uid; 579 if (verbose_option)
358 gid = auth->gid; 580 mu_diag_output (MU_DIAG_WARNING,
581 _("no user with uid %lu found"),
582 (unsigned long) id->uid);
583 rc = 1;
584 }
585 }
586 break;
587
588 case set_owner_name:
589 rc = get_user_id (meth->owner.name, id);
590 break;
359 } 591 }
360 mu_auth_data_free (auth);
361 } 592 }
362 593
363 if (mu_switch_to_privs (uid, gid, NULL)) 594 return rc;
595 }
596
597 static void
598 switch_owner (mu_mailbox_t mbox)
599 {
600 struct user_id user_id;
601
602 if (so_method_num == 0)
603 return;
604
605 if (getuid ())
606 {
607 if (verbose_option)
608 mu_diag_output (MU_DIAG_WARNING,
609 _("ignoring mailbox-ownership statement"));
610 return;
611 }
612
613 if (guess_mbox_owner (mbox, &user_id) == 0)
614 {
615 if (mu_switch_to_privs (user_id.uid, user_id.gid, NULL))
364 exit (1); 616 exit (1);
617 }
618 else
619 {
620 mu_error (_("no suitable method for setting mailbox ownership"));
621 exit (1);
622 }
365 } 623 }
366 624
367 static int 625 static int
...@@ -443,8 +701,7 @@ main (int argc, char **argv) ...@@ -443,8 +701,7 @@ main (int argc, char **argv)
443 else 701 else
444 open_mailbox (&source, source_name, flags, argv[2]); 702 open_mailbox (&source, source_name, flags, argv[2]);
445 703
446 if (copy_meta) 704 switch_owner (source);
447 set_permissions (source);
448 705
449 open_mailbox (&dest, dest_name, MU_STREAM_RDWR | MU_STREAM_CREAT, NULL); 706 open_mailbox (&dest, dest_name, MU_STREAM_RDWR | MU_STREAM_CREAT, NULL);
450 707
......