summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS29
-rw-r--r--doc/texinfo/mu-mh.texi53
-rw-r--r--libproto/imap/mbox.c7
-rw-r--r--mh/inc.c225
-rw-r--r--mh/tests/.gitignore1
-rw-r--r--mh/tests/Makefile.am7
-rw-r--r--mh/tests/ali.at2
-rw-r--r--mh/tests/lu.c31
8 files changed, 281 insertions, 74 deletions
diff --git a/NEWS b/NEWS
index 02291b47a..1da261c2c 100644
--- a/NEWS
+++ b/NEWS
@@ -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;
}
diff --git a/mh/inc.c b/mh/inc.c
index 790d5cf15..ca87066a8 100644
--- a/mh/inc.c
+++ b/mh/inc.c
@@ -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;
+}

Return to:

Send suggestions and report system problems to the System administrator.