diff options
-rw-r--r-- | NEWS | 29 | ||||
-rw-r--r-- | doc/texinfo/mu-mh.texi | 53 | ||||
-rw-r--r-- | libproto/imap/mbox.c | 7 | ||||
-rw-r--r-- | mh/inc.c | 225 | ||||
-rw-r--r-- | mh/tests/.gitignore | 1 | ||||
-rw-r--r-- | mh/tests/Makefile.am | 7 | ||||
-rw-r--r-- | mh/tests/ali.at | 2 | ||||
-rw-r--r-- | mh/tests/lu.c | 31 |
8 files changed, 281 insertions, 74 deletions
@@ -1,4 +1,4 @@ -GNU mailutils NEWS -- history of user-visible changes. 2012-04-29 +GNU mailutils NEWS -- history of user-visible changes. 2012-05-31 Copyright (C) 2002-2012 Free Software Foundation, Inc. See the end of file for copying conditions. @@ -126,6 +126,33 @@ input folders of type IMAP or IMAPS. A sample usage is: Note the `-truncate' option. +** MH: multiple sources + +The `inc' command is able to incorporate messages from several +source mailboxes. These are specified via multiple `-file' +options, e.g.: + + inc -truncate \ + -file 'imaps://imap.gmail.com;moveto=archived' \ + -file pops://mail.gnu.org \ + -file /var/mail/root + +Additional parameters can be used in URLs supplied with the `-file' +option: + + moveto=FOLDER + Moves incorporated messages into FOLDER. This is similar to the + `--moveto' option, but applies only to that particular mailbox. + See the example above. + + nomoveto + Disables the previous `--moveto' option. + + truncate[=BOOL] + Controls source mailbox truncation. If BOOL is not given or is + "yes", the mailbox will be truncated after successful processing. + If BOOL is "no", the source mailbox will not be truncated. + ** mailutils-config is deprecated. Use `mu cflags' and `mu ldflags' instead. The mailutils-config is diff --git a/doc/texinfo/mu-mh.texi b/doc/texinfo/mu-mh.texi index e16cffc71..415e3e464 100644 --- a/doc/texinfo/mu-mh.texi +++ b/doc/texinfo/mu-mh.texi @@ -249,6 +249,59 @@ Understands @option{--build} option. This command is not provided. Use @option{fmtcheck} instead. +@item inc +@itemize @bullet +@item The @option{--moveto} option. +The @option{--moveto} option instructs @command{inc} to move +messages into another folder after incorporating them. This option +has effect only if the @option{--truncate} option has also been +specified and the underlying mailbox supports the @samp{move} +operation. Currently only @samp{imap} and @samp{imaps} mailboxes +support it. For example, the following command moves incorporated +messages into the @samp{archive} folder: + +@example +inc --file imaps://imap.gmail.com --moveto=archive +@end example + +The @samp{moveto} URL parameter can be used instead of this option, +e.g.: + +@example +inc --file 'imaps://imap.gmail.com;moveto=archive' +@end example + +@item Multiple sources +Mailutils @command{inc} is able to incorporate messages from several +source mailboxes. These are specified via multiple @option{-file} +options, e.g.: + +@example +inc -truncate \ + -file 'imaps://imap.gmail.com;moveto=archived' \ + -file pops://mail.gnu.org \ + -file /var/mail/root +@end example + +@item URL parameters +The following additional parameters can be used in the mailbox +URLs supplied with the @option{-file} option: + +@table @option +@item moveto=@var{folder} +Moves incorporated messages into another folder. This was discussed +above. + +@item nomoveto +Disables the previous @option{--moveto} option. + +@item truncate[=@var{bool}] +Controls source mailbox truncation. If @var{bool} is not given or it is +@samp{yes}, the mailbox will be truncated after successful processing. +If @var{bool} is @samp{no}, the source mailbox will not be truncated. +@end table +@end itemize + @item mhl The @samp{ignores} keyword can be used in variable list. In that diff --git a/libproto/imap/mbox.c b/libproto/imap/mbox.c index a7fd302c6..538c04be6 100644 --- a/libproto/imap/mbox.c +++ b/libproto/imap/mbox.c @@ -269,9 +269,12 @@ _imap_env_date (mu_envelope_t env, char *buf, size_t len, statbuf); rc = mu_c_streamftime (str, MU_DATETIME_FROM, &imsg->env->date, &imsg->env->tz); + if (rc == 0) + rc = mu_stream_write (str, "", 1, NULL); mu_stream_destroy (&str); - if (pnwrite) - *pnwrite = statbuf[MU_STREAM_STAT_OUT]; + if (rc == 0 && pnwrite) + /* Do not count terminating null character */ + *pnwrite = statbuf[MU_STREAM_STAT_OUT] - 1; } return rc; } @@ -68,7 +68,7 @@ struct mh_option mh_option[] = { static char *format_str = mh_list_format; static int width = 80; -static char *input_file; +static mu_list_t input_file_list; static char *audit_file; static FILE *audit_fp; static int changecur = -1; @@ -80,6 +80,8 @@ static const char *move_to_mailbox; static error_t opt_handler (int key, char *arg, struct argp_state *state) { + int rc; + switch (key) { case ARGP_KEY_FINI: @@ -116,11 +118,26 @@ opt_handler (int key, char *arg, struct argp_state *state) break; case ARG_FILE: - input_file = arg; + if (!input_file_list) + { + rc = mu_list_create (&input_file_list); + if (rc) + { + mu_diag_funcall (MU_DIAG_ERROR, + "mu_list_create", "&input_file_list", rc); + exit (1); + } + } + rc = mu_list_append (input_file_list, arg); + if (rc) + { + mu_diag_funcall (MU_DIAG_ERROR, "mu_list_append", arg, rc); + exit (1); + } break; case ARG_TRUNCATE: - truncate_source = is_true(arg); + truncate_source = is_true (arg); break; case ARG_NOTRUNCATE: @@ -165,33 +182,42 @@ list_message (mh_format_t *format, mu_mailbox_t mbox, size_t msgno, free (buf); } -int -main (int argc, char **argv) +struct incdat { - mu_mailbox_t input = NULL; - mu_mailbox_t output = NULL; - size_t total, n; + mu_mailbox_t output; size_t lastmsg; - int f_truncate = 0; - int f_changecur = 0; mh_format_t format; - int rc; - - /* Native Language Support */ - MU_APP_INIT_NLS (); - - mh_argp_init (); - mh_argp_parse (&argc, &argv, 0, options, mh_option, args_doc, doc, - opt_handler, NULL, NULL); - /* Inc sets missing cur to 1 */ - mh_mailbox_cur_default = 1; +}; - if (!quiet && mh_format_parse (format_str, &format)) +static int +getparam (mu_url_t url, const char *param, const char **sval) +{ + int rc = mu_url_sget_param (url, param, sval); + switch (rc) { - mu_error (_("Bad format string")); + case 0: + case MU_ERR_NOENT: + break; + + default: + mu_diag_funcall (MU_DIAG_ERROR, "mu_url_sget_param", param, rc); exit (1); } + return rc; +} +static int +incmbx (void *item, void *data) +{ + char *input_file = item; + struct incdat *dp = data; + mu_mailbox_t input = NULL; + size_t total, n; + int rc; + int f_truncate = truncate_source; + const char *f_move_to_mailbox = move_to_mailbox, *sval; + mu_url_t url; + /* Select and open input mailbox */ if (input_file == NULL) { @@ -201,8 +227,6 @@ main (int argc, char **argv) mu_strerror (rc)); exit (1); } - f_truncate = 1; - f_changecur = 1; } else if ((rc = mu_mailbox_create_default (&input, input_file)) != 0) { @@ -210,14 +234,14 @@ main (int argc, char **argv) input_file, mu_strerror (rc)); exit (1); } - + if ((rc = mu_mailbox_open (input, MU_STREAM_RDWR)) != 0) { mu_url_t url; mu_mailbox_get_url (input, &url); mu_error (_("cannot open mailbox %s: %s"), mu_url_to_string (url), - mu_strerror (errno)); + mu_strerror (rc)); exit (1); } @@ -227,24 +251,29 @@ main (int argc, char **argv) exit (1); } - output = mh_open_folder (append_folder, MU_STREAM_RDWR|MU_STREAM_CREAT); - if ((rc = mu_mailbox_messages_count (output, &lastmsg)) != 0) + if ((rc = mu_mailbox_get_url (input, &url)) != 0) { - mu_error (_("cannot read output mailbox: %s"), - mu_strerror (errno)); + mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_get_url", input_file, rc); exit (1); } - - /* Fixup options */ - if (truncate_source == -1) - truncate_source = f_truncate; - if (changecur == -1) - changecur = f_changecur; + if (getparam (url, "truncate", &sval) == 0) + { + if (!sval) + f_truncate = 1; + else + f_truncate = is_true (sval); + } + + if (getparam (url, "nomoveto", NULL) == 0) + f_move_to_mailbox = NULL; + else + getparam (url, "nomoveto", &f_move_to_mailbox); + /* Open audit file, if specified */ if (audit_file) audit_fp = mh_audit_open (audit_file, input); - + for (n = 1; n <= total; n++) { mu_message_t imsg; @@ -256,27 +285,28 @@ main (int argc, char **argv) continue; } - if ((rc = mu_mailbox_append_message (output, imsg)) != 0) + if ((rc = mu_mailbox_append_message (dp->output, imsg)) != 0) { mu_error (_("%lu: error appending message: %s"), (unsigned long) n, mu_strerror (rc)); continue; } - + if (n == 1 && changecur) { mu_message_t msg = NULL; size_t cur; - mu_mailbox_get_message (output, lastmsg + 1, &msg); + mu_mailbox_get_message (dp->output, dp->lastmsg + 1, &msg); mh_message_number (msg, &cur); - mh_mailbox_set_cur (output, cur); + mh_mailbox_set_cur (dp->output, cur); } - + + ++dp->lastmsg; if (!quiet) - list_message (&format, output, lastmsg + n, width); + list_message (&dp->format, dp->output, dp->lastmsg, width); - if (truncate_source) + if (f_truncate) { mu_attribute_t attr; mu_message_get_attribute (imsg, &attr); @@ -284,50 +314,105 @@ main (int argc, char **argv) } } - if (truncate_source && move_to_mailbox) + if (total && f_truncate) { - mu_msgset_t msgset; - - rc = mu_msgset_create (&msgset, input, MU_MSGSET_NUM); - if (rc) - mu_diag_funcall (MU_DIAG_ERROR, "mu_msgset_create", NULL, rc); - else + if (f_move_to_mailbox) { - rc = mu_msgset_add_range (msgset, 1, total, MU_MSGSET_NUM); + mu_msgset_t msgset; + + rc = mu_msgset_create (&msgset, input, MU_MSGSET_NUM); if (rc) - mu_diag_funcall (MU_DIAG_ERROR, "mu_msgset_add_range", NULL, rc); + mu_diag_funcall (MU_DIAG_ERROR, "mu_msgset_create", NULL, rc); else { - rc = mu_mailbox_msgset_copy (input, msgset, move_to_mailbox, - MU_MAILBOX_COPY_CREAT); + rc = mu_msgset_add_range (msgset, 1, total, MU_MSGSET_NUM); if (rc) + mu_diag_funcall (MU_DIAG_ERROR, "mu_msgset_add_range", + NULL, rc); + else { - mu_error (_("failed to move messages to %s: %s"), - move_to_mailbox, mu_strerror (rc)); - truncate_source = 0; + rc = mu_mailbox_msgset_copy (input, msgset, move_to_mailbox, + MU_MAILBOX_COPY_CREAT); + if (rc) + { + mu_error (_("failed to move messages to %s: %s"), + move_to_mailbox, mu_strerror (rc)); + f_truncate = 0; + } } + mu_msgset_destroy (&msgset); } - mu_msgset_destroy (&msgset); } + mu_mailbox_expunge (input); } - if (!changecur) + if (audit_fp) { - mu_property_t prop = mh_mailbox_get_property (output); - mu_property_invalidate (prop); + mh_audit_close (audit_fp); + audit_fp = NULL; } - mh_global_save_state (); - mu_mailbox_close (output); - mu_mailbox_destroy (&output); - - if (truncate_source) - mu_mailbox_expunge (input); mu_mailbox_close (input); mu_mailbox_destroy (&input); - if (audit_fp) - mh_audit_close (audit_fp); + return 0; +} + +int +main (int argc, char **argv) +{ + struct incdat incdat; + int rc; + int f_truncate = 0; + int f_changecur = 0; + + /* Native Language Support */ + MU_APP_INIT_NLS (); + + mh_argp_init (); + mh_argp_parse (&argc, &argv, 0, options, mh_option, args_doc, doc, + opt_handler, NULL, NULL); + /* Inc sets missing cur to 1 */ + mh_mailbox_cur_default = 1; + + memset (&incdat, 0, sizeof (incdat)); + if (!quiet && mh_format_parse (format_str, &incdat.format)) + { + mu_error (_("Bad format string")); + exit (1); + } + + incdat.output = mh_open_folder (append_folder, + MU_STREAM_RDWR|MU_STREAM_CREAT); + if ((rc = mu_mailbox_messages_count (incdat.output, &incdat.lastmsg)) != 0) + { + mu_error (_("cannot read output mailbox: %s"), + mu_strerror (errno)); + exit (1); + } + + /* Fixup options */ + if (!input_file_list) + f_truncate = f_changecur = 1; + if (truncate_source == -1) + truncate_source = f_truncate; + if (changecur == -1) + changecur = f_changecur; + + if (!input_file_list) + incmbx (NULL, &incdat); + else + mu_list_foreach (input_file_list, incmbx, &incdat); + + if (!changecur) + { + mu_property_t prop = mh_mailbox_get_property (incdat.output); + mu_property_invalidate (prop); + } + mh_global_save_state (); + + mu_mailbox_close (incdat.output); + mu_mailbox_destroy (&incdat.output); return 0; } diff --git a/mh/tests/.gitignore b/mh/tests/.gitignore index 33e4e9a57..cea5b74a8 100644 --- a/mh/tests/.gitignore +++ b/mh/tests/.gitignore @@ -1,5 +1,6 @@ atconfig atlocal +lu package.m4 status.mf testsuite diff --git a/mh/tests/Makefile.am b/mh/tests/Makefile.am index c2e991ed3..227adbfec 100644 --- a/mh/tests/Makefile.am +++ b/mh/tests/Makefile.am @@ -34,6 +34,13 @@ $(srcdir)/package.m4: $(top_srcdir)/configure.ac # +## -------------------------- ## +## Non-installable programs ## +## -------------------------- ## + +INCLUDES = @MU_LIB_COMMON_INCLUDES@ +noinst_PROGRAMS = lu + ## ------------ ## ## Test suite. ## ## ------------ ## diff --git a/mh/tests/ali.at b/mh/tests/ali.at index 487a6807a..98cd4771a 100644 --- a/mh/tests/ali.at +++ b/mh/tests/ali.at @@ -98,7 +98,7 @@ ali -list -a ./mh_aliases korzen [expout]) MH_CHECK([ali: everybody],[ali06 ali-everybody],[ -cat /etc/passwd | awk -F : '/^#/ { next } $3>200 { print $1 }' > expout +lu 200 > expout test -s expout || AT_SKIP_TEST AT_DATA([mh_aliases],[ everybody: * diff --git a/mh/tests/lu.c b/mh/tests/lu.c new file mode 100644 index 000000000..c438f9d8a --- /dev/null +++ b/mh/tests/lu.c @@ -0,0 +1,31 @@ +/* This file is part of GNU Mailutils test suite. + Copyright (C) 2012 Free Software Foundation, Inc. + + This file is free software; as a special exception the author gives + unlimited permission to copy and/or distribute it, with or without + modifications. + + This file is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY, to the extent permitted by law; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +*/ +#include <sys/types.h> +#include <pwd.h> +#include <stdio.h> +#include <stdlib.h> + +/* List all user names. With a single numeric argument, list users with UID + greater than that argument. */ +int +main (int argc, char **argv) +{ + struct passwd *pw; + int minuid = 0; + + if (argc == 2) + minuid = atoi (argv[1]); + while ((pw = getpwent ())) + if (pw->pw_uid > minuid) + printf ("%s\n", pw->pw_name); + return 0; +} |