summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2010-05-20 16:29:36 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2010-05-20 16:29:36 +0300
commit7cbbb4012d63c86e8e0726a5634bdd880ffe34b3 (patch)
treef9c710a2226189f70c810aa25958bcba61a6d1ef
parent7d8bee8e82f7f1bad91371caf511f6eadf13b2f9 (diff)
downloadmailutils-7cbbb4012d63c86e8e0726a5634bdd880ffe34b3.tar.gz
mailutils-7cbbb4012d63c86e8e0726a5634bdd880ffe34b3.tar.bz2
Movemail improved.
* movemail/movemail.c: New options: --ignore-errors and --program-id. (_compare_msgno): Remove now unneded static. (main): Handle --ignore-errors and --program-id settings. Optimize the main loop for the case when --uidls is given. Return 1 on errors. * doc/texinfo/programs.texi: Document new features.
-rw-r--r--doc/texinfo/programs.texi60
-rw-r--r--movemail/movemail.c176
2 files changed, 194 insertions, 42 deletions
diff --git a/doc/texinfo/programs.texi b/doc/texinfo/programs.texi
index 118f44bed..fe50c7fea 100644
--- a/doc/texinfo/programs.texi
+++ b/doc/texinfo/programs.texi
@@ -4369,7 +4369,7 @@ intended as a replacement for @command{movemail} from GNU Emacs. The
module. @xref{Rmail,,,emacs,Reading Mail with Rmail}, for detailed
description of @code{Rmail} interface.
-Mailutils version of @command{movemail} is completely
+Mailutils version of @command{movemail} is fully
backward-compatible with its Emacs predecessor, so it should run
flawlessly with older versions of Emacs. Emacs versions
starting from 22.1 contain improved @code{Rmail} interface and
@@ -4401,6 +4401,57 @@ If @var{bool} is @samp{true}, reverse message sorting order.
If @var{bool} is @samp{true}, output information used by Emacs rmail interface.
@end deffn
+@deffn {Movemail Config} ignore-erros @var{bool}
+Continue moving messages after errors. By default,
+@command{mailfromd} exits immediately if it cannot copy a message.
+@end deffn
+
+@deffn {Movemail Config} program-id @var{fmt}
+Set program identifier, i.e. a string which will prefix all
+diagnostic messages issued by the program. By default, program
+name is used.
+
+The @var{fmt} is a format string that may contain references to the
+following macro variables (@FIXME-pxref{macro-variables}):
+
+@table @code
+@item progname
+The program name.
+
+@item source
+URL of the source mailbox.
+
+@item source:user
+User part of the source mailbox URL.
+
+@item source:host
+Host part of the source mailbox URL.
+
+@item source:path
+Path part of the source mailbox URL.
+
+@item dest
+URL of the destination mailbox
+
+@item dest:user
+User part of the destination mailbox URL.
+
+@item dest:host
+Host part of the destination mailbox URL.
+
+@item dest:path
+Path part of the destination mailbox URL.
+@end table
+
+Setting @code{program-id} may be necessary if several @code{movemail}
+instances are run simultaneously (e.g. invoked from a script) to
+discern between the instances. For example:
+
+@smallexample
+program-id "$@{progname@}: $@{source@} => $@{dest@}"
+@end smallexample
+@end deffn
+
@deffn {Movemail Config} uidl @var{bool}
Avoid copying the message if a message with the same UIDL already
exists in the destination mailbox.
@@ -4494,11 +4545,18 @@ Following is the summary of available command line options:
@item --emacs
Output information used by Emacs rmail interface
+@item --ignore-errors
+Continue moving messages after an error occurs.
+
@item -p
@itemx --preserve
@itemx --keep-messages
Preserve the source mailbox
+@item --program-id=@var{fmt}
+Set program identifier for diagnostic purposes. See @ref{Movemail
+Configuration,program-id}, for a detailed discussion of this feature.
+
@item -r
@itemx --reverse
Reverse the sorting order
diff --git a/movemail/movemail.c b/movemail/movemail.c
index a38517355..3c910930c 100644
--- a/movemail/movemail.c
+++ b/movemail/movemail.c
@@ -37,13 +37,17 @@ const char *program_version = "movemail (" PACKAGE_STRING ")";
static char doc[] = N_("GNU movemail -- move messages across mailboxes.");
static char args_doc[] = N_("inbox-url destfile [POP-password]");
-#define OPT_EMACS 256
+enum {
+ EMACS_OPTION=256,
+ IGNORE_ERRORS_OPTION,
+ PROGRAM_ID_OPTION
+};
static struct argp_option options[] = {
{ "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") },
- { "emacs", OPT_EMACS, NULL, 0,
+ { "emacs", EMACS_OPTION, NULL, 0,
N_("output information used by Emacs rmail interface") },
{ "uidl", 'u', NULL, 0,
N_("use UIDLs to avoid downloading the same message twice") },
@@ -51,6 +55,10 @@ static struct argp_option options[] = {
N_("increase verbosity level") },
{ "owner", 'P', N_("MODELIST"), 0,
N_("control mailbox ownership") },
+ { "ignore-errors", IGNORE_ERRORS_OPTION, NULL, 0,
+ N_("try to continue after errors") },
+ { "program-id", PROGRAM_ID_OPTION, N_("FMT"), 0,
+ N_("set program identifier for diagnostics (default: program name)") },
{ NULL, 0, NULL, 0, NULL, 0 }
};
@@ -59,6 +67,8 @@ static int preserve_mail;
static int emacs_mode;
static int uidl_option;
static int verbose_option;
+static int ignore_errors;
+static char *program_id_option;
enum set_ownership_mode
{
@@ -135,10 +145,18 @@ parse_opt (int key, char *arg, struct argp_state *state)
verbose_option++;
break;
- case OPT_EMACS:
+ case EMACS_OPTION:
mu_argp_node_list_new (lst, "emacs", "yes");
break;
+ case IGNORE_ERRORS_OPTION:
+ mu_argp_node_list_new (lst, "ignore-errors", "yes");
+ break;
+
+ case PROGRAM_ID_OPTION:
+ mu_argp_node_list_new (lst, "program-id", arg);
+ break;
+
case ARGP_KEY_INIT:
mu_argp_node_list_init (&lst);
break;
@@ -298,6 +316,10 @@ struct mu_cfg_param movemail_cfg_param[] = {
N_("Use UIDLs to avoid downloading the same message twice.") },
{ "verbose", mu_cfg_int, &verbose_option, 0, NULL,
N_("Set verbosity level.") },
+ { "ignore-errors", mu_cfg_bool, &ignore_errors, 0, NULL,
+ N_("Continue after an error.") },
+ { "program-id", mu_cfg_string, &program_id_option, 0, NULL,
+ N_("Set program identifier string (default: program name)") },
{ "mailbox-ownership", mu_cfg_callback, NULL, 0,
cb_mailbox_ownership,
N_("Define a list of methods for setting mailbox ownership. Valid "
@@ -633,26 +655,70 @@ _compare_uidls (const void *item, const void *value)
return strcmp (a->uidl, b->uidl);
}
-static int
-_compare_msgno (const void *item, const void *value)
-{
- const struct mu_uidl *a = item;
- const struct mu_uidl *b = value;
-
- if (a->msgno < b->msgno)
- return -1;
- if (a->msgno > b->msgno)
- return 1;
- return 0;
+#define __cat2__(a,b) a ## b
+#define DCL_VTX(what) \
+static int \
+ __cat2__(_vtx_,what) (const char *name, void *data, char **p) \
+{ \
+ mu_url_t url = data; \
+ int rc = __cat2__(mu_url_aget_,what) (url, p); \
+ if (rc == MU_ERR_NOENT) \
+ { \
+ *p = strdup (""); \
+ return 0; \
+ } \
+ return rc; \
}
-static int
-msgno_in_list (mu_list_t list, size_t num)
+DCL_VTX (host)
+DCL_VTX (user)
+DCL_VTX (path)
+
+static void
+set_program_id (const char *source_name, const char *dest_name)
{
- struct mu_uidl t;
- t.msgno = num;
- return mu_list_locate (list, &t, NULL) == 0;
-}
+ int rc;
+ mu_vartab_t vtab;
+ char *id;
+ mu_url_t url;
+
+ mu_vartab_create (&vtab);
+ mu_vartab_define (vtab, "progname", mu_program_name, 1);
+ mu_vartab_define (vtab, "source", source_name, 1);
+ rc = mu_mailbox_get_url (source, &url);
+ if (rc)
+ mu_diag_output (MU_DIAG_INFO,
+ _("cannot obtain source mailbox URL: %s"),
+ mu_strerror (rc));
+ else
+ {
+ mu_vartab_define_exp (vtab, "source:user", _vtx_user, NULL, url);
+ mu_vartab_define_exp (vtab, "source:host", _vtx_host, NULL, url);
+ mu_vartab_define_exp (vtab, "source:path", _vtx_path, NULL, url);
+ }
+
+ mu_vartab_define (vtab, "dest", dest_name, 1);
+ rc = mu_mailbox_get_url (dest, &url);
+ if (rc)
+ mu_diag_output (MU_DIAG_INFO,
+ _("cannot obtain destination mailbox URL: %s"),
+ mu_strerror (rc));
+ else
+ {
+ mu_vartab_define_exp (vtab, "dest:user", _vtx_user, NULL, url);
+ mu_vartab_define_exp (vtab, "dest:host", _vtx_host, NULL, url);
+ mu_vartab_define_exp (vtab, "dest:path", _vtx_path, NULL, url);
+ }
+
+ rc = mu_vartab_expand (vtab, program_id_option, &id);
+ mu_vartab_destroy (&vtab);
+ /* asprintf (&id, "%s: %s", mu_program_name, s);
+ free (s);*/
+ /* FIXME: Don't use mu_set_program_name here, because it
+ plays wise with its argument. We need a mu_set_diag_prefix
+ function. */
+ mu_program_name = id;
+}
int
main (int argc, char **argv)
@@ -660,6 +726,7 @@ main (int argc, char **argv)
int index;
size_t i, total;
int rc = 0;
+ int errs = 0;
char *source_name, *dest_name;
int flags;
mu_list_t src_uidl_list = NULL;
@@ -707,6 +774,9 @@ main (int argc, char **argv)
open_mailbox (&dest, dest_name, MU_STREAM_RDWR | MU_STREAM_CREAT, NULL);
+ if (program_id_option)
+ set_program_id (source_name, dest_name);
+
rc = mu_mailbox_messages_count (source, &total);
if (rc)
{
@@ -745,43 +815,67 @@ main (int argc, char **argv)
}
mu_iterator_destroy (&itr);
mu_list_destroy (&dst_uidl_list);
- mu_list_set_comparator (src_uidl_list, _compare_msgno);
+ mu_list_set_comparator (src_uidl_list, NULL);
}
-
- if (reverse_order)
+
+ /* FIXME: Implementing a mailbox iterator would allow to merge the three
+ branches of this conditional. */
+ if (src_uidl_list)
+ {
+ mu_iterator_t itr;
+
+ rc = mu_list_get_iterator (src_uidl_list, &itr);
+ if (rc)
+ {
+ mu_error(_("cannot get iterator: %s"), mu_strerror (rc));
+ exit (1);
+ }
+ rc = mu_iterator_ctl (itr, mu_itrctl_set_direction, &reverse_order);
+ if (rc)
+ {
+ mu_error(_("cannot set iteration direction: %s"), mu_strerror (rc));
+ exit (1);
+ }
+ for (mu_iterator_first (itr); !mu_iterator_is_done (itr);
+ mu_iterator_next (itr))
+ {
+ struct mu_uidl *uidl;
+
+ mu_iterator_current (itr, (void **)&uidl);
+ rc = move_message (source, dest, uidl->msgno);
+ if (rc == 0)
+ msg_count++;
+ else if (!ignore_errors)
+ break;
+ else
+ errs = 1;
+ }
+ mu_iterator_destroy (&itr);
+ }
+ else if (reverse_order)
{
for (i = total; i > 0; i--)
{
- if (src_uidl_list && !msgno_in_list (src_uidl_list, i))
- {
- if (verbose_option > 1)
- mu_diag_output (MU_DIAG_INFO, _("ignoring message %lu"),
- (unsigned long) i);
- continue;
- }
rc = move_message (source, dest, i);
if (rc == 0)
msg_count++;
- else
+ else if (!ignore_errors)
break;
+ else
+ errs = 1;
}
}
else
{
for (i = 1; i <= total; i++)
{
- if (src_uidl_list && !msgno_in_list (src_uidl_list, i))
- {
- if (verbose_option > 1)
- mu_diag_output (MU_DIAG_INFO, _("ignoring message %lu"),
- (unsigned long) i);
- continue;
- }
rc = move_message (source, dest, i);
if (rc == 0)
msg_count++;
- else
+ else if (!ignore_errors)
break;
+ else
+ errs = 1;
}
}
@@ -791,7 +885,7 @@ main (int argc, char **argv)
(unsigned long) msg_count);
if (rc)
- return rc;
+ return !!rc;
mu_mailbox_sync (dest);
rc = mu_mailbox_close (dest);
@@ -804,5 +898,5 @@ main (int argc, char **argv)
mu_mailbox_close (source);
mu_mailbox_destroy (&source);
- return rc;
+ return !(rc == 0 && errs == 0);
}

Return to:

Send suggestions and report system problems to the System administrator.