summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2017-06-20 00:39:18 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2017-06-20 00:39:18 +0300
commit455554b8b04054e1db41b72426f7ee9d8579acf5 (patch)
tree8b6ff512af954dcf4c6cc1525b58b11e35788d1d
parent1ddc81a18a3f1491494ff7ec3a21e1bbcabf265a (diff)
downloadmailutils-455554b8b04054e1db41b72426f7ee9d8579acf5.tar.gz
mailutils-455554b8b04054e1db41b72426f7ee9d8579acf5.tar.bz2
API for formatting message sets on output
* libmailutils/msgset/print.c (mu_msgset_formats): New global. (mu_stream_msgset_format): New function. * include/mailutils/msgset.h (mu_msgset_format): New struct. (mu_msgset_fmt_imap, mu_msgset_fmt_mh): New defines. (MU_MSGSET_IGNORE_TRANSERR): New flag (mu_msgset_copy, mu_msgset_translate): New protos. (mu_stream_msgset_format, mu_msgset_imap_print): New protos. (mu_msgset_print): Deprecate. * libmailutils/imapio/sendmsgset.c: Use mu_msgset_imap_print instead of mu_msgset_print. * mu/libexec/imap.c: Likewise. * libmailutils/msgset/Makefile.am: Add copy.c * libmailutils/msgset/add.c (mu_msgset_add_range): Translate if message set mode doesn't match the requested one. * libmailutils/msgset/sub.c (mu_msgset_sub_range): Likewise. * libmailutils/msgset/trans.c (_mu_msgset_translate_pair): Act according to the mode argument. (mu_msgset_translate): New function. * libmailutils/tests/msgset.c: New option -mh * mh/mh_sequence.c (write_sequence): Rewrite. * testsuite/msgset.c: Optionally translate uids to msgnums and vice-versa.
-rw-r--r--include/mailutils/msgset.h41
-rw-r--r--include/mailutils/sys/msgset.h1
-rw-r--r--libmailutils/imapio/sendmsgset.c2
-rw-r--r--libmailutils/msgset/Makefile.am1
-rw-r--r--libmailutils/msgset/add.c6
-rw-r--r--libmailutils/msgset/print.c55
-rw-r--r--libmailutils/msgset/sub.c6
-rw-r--r--libmailutils/msgset/trans.c75
-rw-r--r--libmailutils/tests/msgset.c8
-rw-r--r--mh/inc.c4
-rw-r--r--mh/mh_msgset.c1
-rw-r--r--mh/mh_sequence.c87
-rw-r--r--mu/libexec/imap.c2
-rw-r--r--testsuite/msgset.c20
14 files changed, 212 insertions, 97 deletions
diff --git a/include/mailutils/msgset.h b/include/mailutils/msgset.h
index 8f3b6e1bf..cad1532ae 100644
--- a/include/mailutils/msgset.h
+++ b/include/mailutils/msgset.h
@@ -30,6 +30,25 @@ struct mu_msgrange
size_t msg_end;
};
+struct mu_msgset_format
+{
+ char *range; /* range separator (e.g., ":" for IMAP, "-" for MH) */
+ char *delim; /* delimiter (e.g., "," for IMAP, " " for MH) */
+ char *last; /* last message marker (e.g., "*" for IMAP, "last" for MH) */
+ char *empty; /* empty list representation ( "NIL", for IMAP, NULL for MH */
+};
+
+enum
+ {
+ MU_MSGSET_FMT_IMAP,
+ MU_MSGSET_FMT_MH
+ };
+
+extern struct mu_msgset_format const mu_msgset_formats[];
+typedef struct mu_msgset_format const *mu_msgset_format_t;
+#define mu_msgset_fmt_imap (&mu_msgset_formats[MU_MSGSET_FMT_IMAP])
+#define mu_msgset_fmt_mh (&mu_msgset_formats[MU_MSGSET_FMT_MH])
+
/* Message numbers start with 1. MU_MSGNO_LAST denotes the last
message. */
#define MU_MSGNO_LAST 0
@@ -37,9 +56,15 @@ struct mu_msgrange
#define MU_MSGSET_NUM 0 /* Message set operates on sequence numbers */
#define MU_MSGSET_UID 1 /* Message set operates on UIDs */
+#define MU_MSGSET_IGNORE_TRANSERR 0x10
+
#define MU_MSGSET_MODE_MASK 0x0f
int mu_msgset_create (mu_msgset_t *pmsgset, mu_mailbox_t mbox, int mode);
+
+int mu_msgset_copy (mu_msgset_t src, mu_msgset_t dst);
+int mu_msgset_translate (mu_msgset_t *dst, mu_msgset_t src, int flags);
+
int mu_msgset_get_list (mu_msgset_t msgset, mu_list_t *plist);
int mu_msgset_get_iterator (mu_msgset_t msgset, mu_iterator_t *pitr);
@@ -54,9 +79,21 @@ int mu_msgset_clear (mu_msgset_t set);
void mu_msgset_free (mu_msgset_t set);
void mu_msgset_destroy (mu_msgset_t *set);
-int mu_msgset_parse_imap (mu_msgset_t set, int mode, const char *s, char **end);
+int mu_msgset_parse_imap (mu_msgset_t set, int mode, const char *s,
+ char **end);
+
+int mu_stream_msgset_format (mu_stream_t str,
+ struct mu_msgset_format const *fmt,
+ mu_msgset_t mset);
+int mu_msgset_print (mu_stream_t str, mu_msgset_t msgset)
+ MU_DEPRECATED;
+
+static inline int
+mu_msgset_imap_print (mu_stream_t str, mu_msgset_t mset)
+{
+ return mu_stream_msgset_format (str, mu_msgset_fmt_imap, mset);
+}
-int mu_msgset_print (mu_stream_t str, mu_msgset_t msgset);
int mu_msgset_locate (mu_msgset_t msgset, size_t n,
struct mu_msgrange const **prange);
diff --git a/include/mailutils/sys/msgset.h b/include/mailutils/sys/msgset.h
index 8bb12091e..2392ff1e9 100644
--- a/include/mailutils/sys/msgset.h
+++ b/include/mailutils/sys/msgset.h
@@ -27,6 +27,7 @@ struct _mu_msgset
mu_list_t list; /* List of mu_msgrange structures */
mu_mailbox_t mbox; /* Associated mailbox */
int flags; /* Message set flags */
+ size_t format; /* Format index */
};
int _mu_msgset_translate_pair (mu_msgset_t mset, int mode,
diff --git a/libmailutils/imapio/sendmsgset.c b/libmailutils/imapio/sendmsgset.c
index 7310c956a..9ed85ce65 100644
--- a/libmailutils/imapio/sendmsgset.c
+++ b/libmailutils/imapio/sendmsgset.c
@@ -25,5 +25,5 @@
int
mu_imapio_send_msgset (mu_imapio_t io, mu_msgset_t msgset)
{
- return mu_msgset_print (io->_imap_stream, msgset);
+ return mu_msgset_imap_print (io->_imap_stream, msgset);
}
diff --git a/libmailutils/msgset/Makefile.am b/libmailutils/msgset/Makefile.am
index 1dd608ad5..806d5d38b 100644
--- a/libmailutils/msgset/Makefile.am
+++ b/libmailutils/msgset/Makefile.am
@@ -22,6 +22,7 @@ libmsgset_la_SOURCES = \
addset.c\
aggr.c\
clear.c\
+ copy.c\
create.c\
count.c\
getitr.c\
diff --git a/libmailutils/msgset/add.c b/libmailutils/msgset/add.c
index 3e11f5ab4..f16f73450 100644
--- a/libmailutils/msgset/add.c
+++ b/libmailutils/msgset/add.c
@@ -41,12 +41,16 @@ mu_msgset_add_range (mu_msgset_t mset, size_t beg, size_t end, int mode)
return ENOMEM;
range->msg_beg = beg;
range->msg_end = end;
- rc = _mu_msgset_translate_range (mset, mode, range);
+ if (mode != _MU_MSGSET_MODE (mset->flags))
+ {
+ rc = _mu_msgset_translate_range (mset, _MU_MSGSET_MODE (mset->flags),
+ range);
if (rc)
{
free (range);
return rc;
}
+ }
rc = mu_list_append (mset->list, range);
if (rc)
free (range);
diff --git a/libmailutils/msgset/print.c b/libmailutils/msgset/print.c
index 108c70099..7c3816b6a 100644
--- a/libmailutils/msgset/print.c
+++ b/libmailutils/msgset/print.c
@@ -24,10 +24,26 @@
#include <mailutils/msgset.h>
#include <mailutils/sys/msgset.h>
+struct mu_msgset_format const mu_msgset_formats[] = {
+ [MU_MSGSET_FMT_IMAP] = {
+ .delim = ",",
+ .range = ":",
+ .last = "*",
+ .empty = "NIL"
+ },
+ [MU_MSGSET_FMT_MH] = {
+ .delim = " ",
+ .range = "-",
+ .last = "last"
+ }
+};
+
+
struct print_env
{
mu_stream_t stream;
int cont;
+ struct mu_msgset_format const *fmt;
};
static int
@@ -39,36 +55,59 @@ _msgrange_printer (void *item, void *data)
if (env->cont)
{
- rc = mu_stream_write (env->stream, ",", 1, NULL);
+ rc = mu_stream_printf (env->stream, "%s", env->fmt->delim);
if (rc)
return rc;
}
else
env->cont = 1;
+
if (range->msg_beg == range->msg_end)
rc = mu_stream_printf (env->stream, "%lu", (unsigned long) range->msg_beg);
else if (range->msg_end == 0)
- rc = mu_stream_printf (env->stream, "%lu:*",
- (unsigned long) range->msg_beg);
+ rc = mu_stream_printf (env->stream, "%lu%s%s",
+ (unsigned long) range->msg_beg,
+ env->fmt->range,
+ env->fmt->last);
+ else if (range->msg_end == range->msg_beg + 1)
+ rc = mu_stream_printf (env->stream, "%lu%s%lu",
+ (unsigned long) range->msg_beg,
+ env->fmt->delim,
+ (unsigned long) range->msg_end);
else
- rc = mu_stream_printf (env->stream, "%lu:%lu",
+ rc = mu_stream_printf (env->stream, "%lu%s%lu",
(unsigned long) range->msg_beg,
+ env->fmt->range,
(unsigned long) range->msg_end);
return rc;
}
int
-mu_msgset_print (mu_stream_t str, mu_msgset_t mset)
+mu_stream_msgset_format (mu_stream_t str, struct mu_msgset_format const *fmt,
+ mu_msgset_t mset)
{
struct print_env env;
int rc;
+ env.stream = str;
+ env.cont = 0;
+ env.fmt = fmt;
+
if (mu_list_is_empty (mset->list))
- return mu_stream_printf (str, "%s", "nil");
+ {
+ if (env.fmt->empty)
+ return mu_stream_printf (str, "%s", env.fmt->empty);
+ return 0;
+ }
rc = mu_msgset_aggregate (mset);
if (rc)
return rc;
- env.stream = str;
- env.cont = 0;
return mu_list_foreach (mset->list, _msgrange_printer, &env);
}
+
+int
+mu_msgset_print (mu_stream_t str, mu_msgset_t mset)
+{
+ return mu_stream_msgset_format (str, mu_msgset_fmt_imap, mset);
+}
+
diff --git a/libmailutils/msgset/sub.c b/libmailutils/msgset/sub.c
index efd578eed..af2bc60e6 100644
--- a/libmailutils/msgset/sub.c
+++ b/libmailutils/msgset/sub.c
@@ -129,11 +129,15 @@ mu_msgset_sub_range (mu_msgset_t mset, size_t beg, size_t end, int mode)
beg = t;
}
- rc = _mu_msgset_translate_pair (mset, mode, &beg, &end);
+ if (mode != _MU_MSGSET_MODE (mset->flags))
+ {
+ rc = _mu_msgset_translate_pair (mset, _MU_MSGSET_MODE (mset->flags),
+ &beg, &end);
if (rc == MU_ERR_NOENT)
return 0;
else if (rc)
return rc;
+ }
rc = mu_msgset_aggregate (mset);
if (rc)
diff --git a/libmailutils/msgset/trans.c b/libmailutils/msgset/trans.c
index 66cf8f651..b4e44fa7e 100644
--- a/libmailutils/msgset/trans.c
+++ b/libmailutils/msgset/trans.c
@@ -27,14 +27,14 @@ int
_mu_msgset_translate_pair (mu_msgset_t mset, int mode,
size_t *pbeg, size_t *pend)
{
- if (mode != _MU_MSGSET_MODE (mset->flags) && mset->mbox)
+ if (mset->mbox)
{
int cmd, rc;
size_t n = 1;
size_t beg = *pbeg;
size_t end = *pend;
- switch (_MU_MSGSET_MODE (mset->flags))
+ switch (mode)
{
case MU_MSGSET_NUM:
cmd = MU_MAILBOX_UID_TO_MSGNO;
@@ -97,3 +97,74 @@ _mu_msgset_translate_range (mu_msgset_t mset, int mode, struct mu_msgrange *r)
return _mu_msgset_translate_pair (mset, mode, &r->msg_beg, &r->msg_end);
}
+struct trans_closure
+{
+ mu_msgset_t mset;
+ int flags;
+};
+
+static int
+trans_range (void *item, void *data)
+{
+ struct mu_msgrange const *range = item;
+ struct trans_closure *clos = data;
+ struct mu_msgrange *copy;
+ int rc;
+
+ copy = malloc (sizeof *copy);
+ if (!copy)
+ return errno;
+ *copy = *range;
+ rc = _mu_msgset_translate_range (clos->mset, _MU_MSGSET_MODE (clos->flags),
+ copy);
+ switch (rc)
+ {
+ case 0:
+ rc = mu_list_append (clos->mset->list, copy);
+ break;
+
+ case MU_ERR_NOENT:
+ if (clos->flags & MU_MSGSET_IGNORE_TRANSERR)
+ rc = 0;
+ /* fallthrough */
+
+ default:
+ free (copy);
+ }
+
+ return rc;
+}
+
+int
+mu_msgset_translate (mu_msgset_t *dst, mu_msgset_t src, int flags)
+{
+ int rc;
+ mu_msgset_t tmp;
+
+ rc = mu_msgset_create (&tmp, src->mbox, src->flags);
+ if (rc)
+ return rc;
+
+ tmp->format = src->format;
+
+ if (_MU_MSGSET_MODE (flags) == src->flags)
+ {
+ rc = mu_msgset_copy (src, tmp);
+ }
+ else
+ {
+ struct trans_closure tc;
+ tc.mset = tmp;
+ tc.flags = flags;
+ rc = mu_list_foreach (src->list, trans_range, &tc);
+ }
+
+ if (rc)
+ mu_msgset_destroy (&tmp);
+ else
+ *dst = tmp;
+
+ return rc;
+}
+
+
diff --git a/libmailutils/tests/msgset.c b/libmailutils/tests/msgset.c
index 6d6a06dc9..c9aa53182 100644
--- a/libmailutils/tests/msgset.c
+++ b/libmailutils/tests/msgset.c
@@ -18,6 +18,8 @@
#include <stdlib.h>
#include <mailutils/mailutils.h>
+mu_msgset_format_t format = mu_msgset_fmt_imap;
+
static void
parse_msgrange (char *arg, struct mu_msgrange *range)
{
@@ -76,7 +78,7 @@ parse_msgset (const char *arg)
static void
print_all (mu_msgset_t msgset)
{
- MU_ASSERT (mu_msgset_print (mu_strout, msgset));
+ MU_ASSERT (mu_stream_msgset_format (mu_strout, format, msgset));
mu_printf ("\n");
}
@@ -111,13 +113,15 @@ main (int argc, char **argv)
if (strcmp (arg, "-h") == 0 || strcmp (arg, "-help") == 0)
{
- mu_printf ("usage: %s [-msgset=SET] [-add=X[:Y]] [-del=X[:Y]] "
+ mu_printf ("usage: %s [-mh] [-msgset=SET] [-add=X[:Y]] [-del=X[:Y]] "
"[-addset=SET] [-delset=SET] [-first] [-last] ...\n",
mu_program_name);
return 0;
}
else if (strncmp (arg, "-msgset=", 8) == 0)
msgset_string = arg + 8;
+ else if (strcmp (arg, "-mh") == 0)
+ format = mu_msgset_fmt_mh;
else
break;
}
diff --git a/mh/inc.c b/mh/inc.c
index 8f3981bcd..9ae0abde4 100644
--- a/mh/inc.c
+++ b/mh/inc.c
@@ -440,9 +440,7 @@ main (int argc, char **argv)
mu_msgset_create (&unseen, NULL, MU_MSGSET_NUM);
mu_msgset_add_range (unseen, lastseen, incdat.lastmsg, MU_MSGSET_NUM);
- mh_seq_add (incdat.output,
- unseen_seq,
- unseen, 0);
+ mh_seq_add (incdat.output, unseen_seq, unseen, 0);
mu_msgset_free (unseen);
}
diff --git a/mh/mh_msgset.c b/mh/mh_msgset.c
index 3b961d5c7..5b372cc63 100644
--- a/mh/mh_msgset.c
+++ b/mh/mh_msgset.c
@@ -119,6 +119,7 @@ msgset_parser_init (struct msgset_parser *parser, mu_mailbox_t mbox,
mu_diag_funcall (MU_DIAG_ERROR, "mu_msgset_create", NULL, rc);
exit (1);
}
+
parser->argc = argc;
parser->argv = argv;
parser->curp = "";
diff --git a/mh/mh_sequence.c b/mh/mh_sequence.c
index 5ae37c621..50c6ca248 100644
--- a/mh/mh_sequence.c
+++ b/mh/mh_sequence.c
@@ -47,6 +47,8 @@ mh_seq_read (mu_mailbox_t mbox, const char *name, int flags)
static void
write_sequence (mu_mailbox_t mbox, const char *name, char *value, int private)
{
+ if (value && value[0] == 0)
+ value = NULL;
if (private)
{
char *p = private_sequence_name (name);
@@ -63,96 +65,35 @@ delete_sequence (mu_mailbox_t mbox, const char *name, int private)
write_sequence (mbox, name, NULL, private);
}
-struct format_closure
-{
- mu_stream_t stream;
- mu_mailbox_t mailbox;
- int delim;
-};
-
-static int
-format_sequence (void *item, void *data)
-{
- struct mu_msgrange *r = item;
- struct format_closure *clos = data;
- int rc;
- size_t beg, end;
-
- if (clos->mailbox)
- {
- rc = mu_mailbox_translate (clos->mailbox,
- MU_MAILBOX_MSGNO_TO_UID,
- r->msg_beg, &beg);
- if (rc)
- return rc;
- }
- else
- beg = r->msg_beg;
- if (clos->delim)
- mu_stream_write (clos->stream, " ", 1, NULL);
- if (r->msg_beg == r->msg_end)
- rc = mu_stream_printf (clos->stream, "%lu", (unsigned long) beg);
- else
- {
- if (clos->mailbox)
- {
- rc = mu_mailbox_translate (clos->mailbox,
- MU_MAILBOX_MSGNO_TO_UID,
- r->msg_end, &end);
- if (rc)
- return rc;
- }
- else
- end = r->msg_end;
- if (beg + 1 == end)
- rc = mu_stream_printf (clos->stream, "%lu %lu",
- (unsigned long) beg,
- (unsigned long) end);
- else
- rc = mu_stream_printf (clos->stream, "%lu-%lu",
- (unsigned long) beg,
- (unsigned long) end);
- }
- clos->delim = 1;
- return rc;
-}
-
static void
save_sequence (mu_mailbox_t mbox, const char *name, mu_msgset_t mset,
int flags)
{
- mu_list_t list;
-
- mu_msgset_get_list (mset, &list);
- if (mu_list_is_empty (list))
- write_sequence (mset->mbox, name, NULL, flags & SEQ_PRIVATE);
- else
- {
- struct format_closure clos;
int rc;
+ mu_stream_t mstr;
+ mu_msgset_t outset;
mu_transport_t trans[2];
- rc = mu_memory_stream_create (&clos.stream, MU_STREAM_RDWR);
+ rc = mu_msgset_translate (&outset, mset,
+ MU_MSGSET_UID|MU_MSGSET_IGNORE_TRANSERR);
if (rc)
{
- mu_diag_funcall (MU_DIAG_ERROR, "mu_memory_stream_create", NULL, rc);
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_msgset_translate", NULL, rc);
exit (1);
}
- clos.mailbox = mset->mbox;
- clos.delim = 0;
- rc = mu_list_foreach (list, format_sequence, &clos);
+ rc = mu_memory_stream_create (&mstr, MU_STREAM_RDWR);
if (rc)
{
- mu_diag_funcall (MU_DIAG_ERROR, "mu_list_foreach", NULL, rc);
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_memory_stream_create", NULL, rc);
exit (1);
}
- mu_stream_write (clos.stream, "", 1, NULL);
- mu_stream_ioctl (clos.stream, MU_IOCTL_TRANSPORT, MU_IOCTL_OP_GET,
- trans);
+ mu_stream_msgset_format (mstr, mu_msgset_fmt_mh, outset);
+ mu_stream_write (mstr, "", 1, NULL);
+ mu_stream_ioctl (mstr, MU_IOCTL_TRANSPORT, MU_IOCTL_OP_GET, trans);
write_sequence (mbox, name, (char*)trans[0], flags & SEQ_PRIVATE);
- mu_stream_unref (clos.stream);
- }
+ mu_stream_unref (mstr);
+ mu_msgset_free (outset);
}
void
diff --git a/mu/libexec/imap.c b/mu/libexec/imap.c
index a56af8c77..37d494a7a 100644
--- a/mu/libexec/imap.c
+++ b/mu/libexec/imap.c
@@ -1100,7 +1100,7 @@ com_search (int argc, char **argv)
return 0;
}
mu_printf ("%lu matches:", (unsigned long) count);
- mu_msgset_print (mu_strout, mset);
+ mu_msgset_imap_print (mu_strout, mset);
mu_printf ("\n");
mu_msgset_free (mset);
diff --git a/testsuite/msgset.c b/testsuite/msgset.c
index 18a62a244..215c3d585 100644
--- a/testsuite/msgset.c
+++ b/testsuite/msgset.c
@@ -79,13 +79,16 @@ main (int argc, char **argv)
{
int i;
char *msgset_string = NULL;
- mu_msgset_t msgset;
+ mu_msgset_t msgset, outset;
int create_mode = MU_MSGSET_NUM;
int parse_mode = MU_MSGSET_NUM;
+ int output_mode = MU_MSGSET_NUM;
+ int output_flags = 0;
+ mu_msgset_format_t format = mu_msgset_fmt_imap;
mu_mailbox_t mbox = NULL;
mu_set_program_name (argv[0]);
- mu_registrar_record (mu_mbox_record);
+ mu_register_local_mbox_formats ();
for (i = 1; i < argc; i++)
{
char *arg = argv[i];
@@ -114,6 +117,14 @@ main (int argc, char **argv)
MU_ASSERT (mu_mailbox_create (&mbox, arg + 9));
MU_ASSERT (mu_mailbox_open (mbox, MU_STREAM_READ));
}
+ else if (strcmp (arg, "-mh") == 0)
+ format = mu_msgset_fmt_mh;
+ else if (strcmp (arg, "-printuid") == 0)
+ output_mode = MU_MSGSET_UID;
+ else if (strcmp (arg, "-printnum") == 0)
+ output_mode = MU_MSGSET_NUM;
+ else if (strcmp (arg, "-ignore-error") == 0)
+ output_flags = MU_MSGSET_IGNORE_TRANSERR;
else
break;
}
@@ -230,8 +241,11 @@ main (int argc, char **argv)
return 1;
}
}
- MU_ASSERT (mu_msgset_print (mu_strout, msgset));
+
+ MU_ASSERT (mu_msgset_translate (&outset, msgset, output_mode|output_flags));
+ MU_ASSERT (mu_stream_msgset_format (mu_strout, format, outset));
mu_printf ("\n");
+ mu_msgset_free (outset);
mu_msgset_free (msgset);
return 0;

Return to:

Send suggestions and report system problems to the System administrator.