summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2008-02-04 15:02:23 +0000
committerSergey Poznyakoff <gray@gnu.org.ua>2008-02-04 15:02:23 +0000
commitc3aab4628802557768ed0f1f4caef401cdc052d8 (patch)
treedbe284eee8dc0680f7ee35a3776ef260a625ab2f
parent46e86fe1d88d50e4731c98a87fe92fb5e8d73e62 (diff)
downloadmailutils-c3aab4628802557768ed0f1f4caef401cdc052d8.tar.gz
mailutils-c3aab4628802557768ed0f1f4caef401cdc052d8.tar.bz2
* NEWS: Update.
* examples/header.c: New command `itr'. (main): Empty input repeats the recent command. * include/mailutils/header.h (mu_header_get_iterator): New function. * libproto/include/header0.h (struct _mu_header): New member itr. * mailbox/Makefile.am (libmailutils_la_SOURCES): Add hdritr.c * mailbox/hdritr.c: New file. * mailbox/header.c (mu_header_remove): Bugfix. Invalidate the header after removal.
-rw-r--r--ChangeLog13
-rw-r--r--NEWS20
-rw-r--r--examples/header.c91
-rw-r--r--include/mailutils/header.h2
-rw-r--r--libproto/include/header0.h6
-rw-r--r--mailbox/Makefile.am1
-rw-r--r--mailbox/hdritr.c159
-rw-r--r--mailbox/header.c1
8 files changed, 280 insertions, 13 deletions
diff --git a/ChangeLog b/ChangeLog
index 717398ac4..69307af87 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2008-02-04 Sergey Poznyakoff <gray@gnu.org.ua>
+
+ * NEWS: Update.
+ * examples/header.c: New command `itr'.
+ (main): Empty input repeats the recent command.
+ * include/mailutils/header.h (mu_header_get_iterator): New
+ function.
+ * libproto/include/header0.h (struct _mu_header): New member itr.
+ * mailbox/Makefile.am (libmailutils_la_SOURCES): Add hdritr.c
+ * mailbox/hdritr.c: New file.
+ * mailbox/header.c (mu_header_remove): Bugfix. Invalidate the
+ header after removal.
+
2008-01-31 Sergey Poznyakoff <gray@gnu.org.ua>
* auth/radius.c (_expand_query): Fix typo.
diff --git a/NEWS b/NEWS
index 6246d8be2..d0ec7a5b8 100644
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,4 @@
-GNU mailutils NEWS -- history of user-visible changes. 2008-01-12
+GNU mailutils NEWS -- history of user-visible changes. 2008-02-04
Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
See the end of file for copying conditions.
@@ -143,6 +143,24 @@ approach is recommended to use instead of mu_error_set_print:
mu_diag_get_debug (&debug);
mu_debug_set_print (debug, new_printer, NULL);
+** Header iteration
+
+New function `mu_header_get_iterator' returns an iterator for this
+header object. Thus, the following code loops over all headers:
+
+ mu_iterator_t itr;
+ mu_header_get_iterator (header, &itr);
+ for (mu_iterator_first (itr); !mu_iterator_is_done (itr);
+ mu_iterator_next (itr))
+ {
+ const char *hdr, *val;
+ mu_iterator_current_kv (itr,
+ (const void**)&hdr,
+ (void**)&val));
+ /* Do something with hdr and val */
+ }
+ mu_iterator_destroy (&itr);
+
** Global debugging and verbosity settings.
These settings provide default values for mu_debug_t objects created
diff --git a/examples/header.c b/examples/header.c
index 76d6b7fe1..bd2939181 100644
--- a/examples/header.c
+++ b/examples/header.c
@@ -27,6 +27,7 @@
char *file;
mu_header_t header;
+mu_iterator_t iterator;
char *ps[] = { "> ", ". " };
int interactive;
@@ -132,6 +133,7 @@ cmd_free (int argc, char **argv)
{
if (check_args (argv[0], argc, 1, 1))
return;
+ mu_iterator_destroy (&iterator);
mu_header_destroy (&header, NULL);
}
@@ -285,7 +287,55 @@ cmd_write (int argc, char **argv)
break;
}
}
-
+
+void
+cmd_iterate (int argc, char **argv)
+{
+ if (check_args (argv[0], argc, 1, 2))
+ return;
+ if (argc == 1)
+ {
+ mu_iterator_t itr;
+ MU_ASSERT (mu_header_get_iterator (header, &itr));
+ for (mu_iterator_first (itr); !mu_iterator_is_done (itr);
+ mu_iterator_next (itr))
+ {
+ const char *hdr, *val;
+ MU_ASSERT (mu_iterator_current_kv (itr,
+ (const void**)&hdr,
+ (void**)&val));
+ printf ("%s: %s\n", hdr, val);
+ }
+ mu_iterator_destroy (&itr);
+ }
+ else
+ {
+ const char *hdr, *val;
+
+ if (!iterator)
+ MU_ASSERT (mu_header_get_iterator (header, &iterator));
+
+ if (strcmp (argv[1], "first") == 0 || strcmp (argv[1], "1") == 0)
+ mu_iterator_first (iterator);
+ else if (strcmp (argv[1], "next") == 0 || strcmp (argv[1], "n") == 0)
+ {
+ mu_iterator_next (iterator);
+ if (mu_iterator_is_done (iterator))
+ {
+ printf ("Past end of headers. Use `itr first'.\n");
+ return;
+ }
+ }
+
+ MU_ASSERT (mu_iterator_current_kv (iterator,
+ (const void **)&hdr,
+ (void**)&val));
+ printf ("%s: %s\n", hdr, val);
+ }
+}
+
+
+
struct cmdtab
{
char *name;
@@ -303,6 +353,7 @@ static struct cmdtab cmdtab[] = {
{ "print", cmd_print, "NAME [N]",
"find and print the Nth (by default, 1st) instance of header named NAME" },
{ "dump", cmd_dump, NULL, "dump all headers on screen" },
+ { "itr", cmd_iterate, "[first|1|next|n]", "iterate over headers" },
{ "remove", cmd_remove, "NAME [N]",
"remove the Nth (by default, 1st) instance of header named NAME" },
{ "insert", cmd_insert, "NAME VALUE [REF [NUM] [before|after] [replace]]",
@@ -392,11 +443,27 @@ cmd_help (int argc, char **argv)
}
int
+docmd (int argc, char **argv)
+{
+ struct cmdtab *cmd = find_cmd (argv[0]);
+ if (!cmd)
+ {
+ mu_error ("%u: unknown command %s", line_num, argv[0]);
+ return 1;
+ }
+ else
+ cmd->fun (argc, argv);
+ return 0;
+}
+
+int
main (int argc, char **argv)
{
int c;
char buf[512];
-
+ char **prevv;
+ int prevc = 0;
+
interactive = isatty (0);
while ((c = getopt (argc, argv, "f:h")) != EOF)
{
@@ -434,7 +501,6 @@ main (int argc, char **argv)
{
int c;
char **v;
- struct cmdtab *cmd;
int status;
line_num++;
@@ -446,17 +512,20 @@ main (int argc, char **argv)
continue;
}
- cmd = find_cmd (v[0]);
- if (!cmd)
+ if (c == 0)
{
- mu_error ("%u: unknown command %s",
- line_num, v[0]);
+ if (prevc)
+ docmd (prevc, prevv);
+ else
+ mu_argcv_free (c, v);
}
else
- cmd->fun (c, v);
-
- mu_argcv_free (c, v);
-
+ {
+ docmd (c, v);
+ mu_argcv_free (prevc, prevv);
+ prevc = c;
+ prevv = v;
+ }
}
exit (0);
}
diff --git a/include/mailutils/header.h b/include/mailutils/header.h
index 58bf8f261..29e004a19 100644
--- a/include/mailutils/header.h
+++ b/include/mailutils/header.h
@@ -154,6 +154,8 @@ extern int mu_header_set_stream (mu_header_t, mu_stream_t, void *);
extern int mu_header_size (mu_header_t, size_t *);
extern int mu_header_lines (mu_header_t, size_t *);
+extern int mu_header_get_iterator (mu_header_t, mu_iterator_t *);
+
extern int mu_header_set_fill (mu_header_t,
int (*_fill) (mu_header_t, char *, size_t, mu_off_t, size_t *), void *owner);
diff --git a/libproto/include/header0.h b/libproto/include/header0.h
index 76b8bcf34..31e1b1e48 100644
--- a/libproto/include/header0.h
+++ b/libproto/include/header0.h
@@ -25,6 +25,7 @@
#include <mailutils/header.h>
#include <mailutils/assoc.h>
+#include <mailutils/iterator.h>
#include <sys/types.h>
#ifdef __cplusplus
@@ -67,7 +68,10 @@ struct _mu_header
/* Stream. */
mu_stream_t stream;
size_t strpos;
-
+
+ /* Iterators */
+ mu_iterator_t itr;
+
/* Methods */
int (*_fill) (mu_header_t, char *, size_t, mu_off_t, size_t *);
};
diff --git a/mailbox/Makefile.am b/mailbox/Makefile.am
index 9fdf7b57c..c309bb238 100644
--- a/mailbox/Makefile.am
+++ b/mailbox/Makefile.am
@@ -65,6 +65,7 @@ libmailutils_la_SOURCES = \
folder.c\
gdebug.c\
gocs.c\
+ hdritr.c\
header.c\
iterator.c\
ipsrv.c\
diff --git a/mailbox/hdritr.c b/mailbox/hdritr.c
new file mode 100644
index 000000000..7bd6780a3
--- /dev/null
+++ b/mailbox/hdritr.c
@@ -0,0 +1,159 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 2008 Free Software Foundation, Inc.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 3 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General
+ Public License along with this library; if not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301 USA */
+
+/* Mail header iterators. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+
+#include <header0.h>
+#include <mailutils/errno.h>
+
+struct header_iterator
+{
+ mu_header_t header;
+ size_t index;
+};
+
+static int
+hdr_first (void *owner)
+{
+ struct header_iterator *itr = owner;
+ itr->index = 1;
+ return 0;
+}
+
+static int
+hdr_next (void *owner)
+{
+ struct header_iterator *itr = owner;
+ itr->index++;
+ return 0;
+}
+
+static int
+hdr_getitem (void *owner, void **pret, const void **pkey)
+{
+ struct header_iterator *itr = owner;
+ int rc;
+ size_t count;
+
+ rc = mu_header_get_field_count (itr->header, &count);
+ if (rc)
+ return rc;
+ if (itr->index > count)
+ return MU_ERR_NOENT;
+
+ rc = mu_header_sget_field_name (itr->header, itr->index,
+ (const char**) pkey);
+ if (rc == 0)
+ {
+ if (pkey)
+ rc = mu_header_sget_field_value (itr->header, itr->index,
+ (const char**) pret);
+ }
+ return rc;
+}
+
+static int
+hdr_finished_p (void *owner)
+{
+ struct header_iterator *itr = owner;
+ size_t count;
+
+ if (mu_header_get_field_count (itr->header, &count))
+ return 1;
+ return itr->index > count;
+}
+
+static int
+hdr_destroy (mu_iterator_t iterator, void *data)
+{
+ struct header_iterator *itr = data;
+ mu_iterator_detach (&itr->header->itr, iterator);
+ free (data);
+ return 0;
+}
+
+static int
+hdr_curitem_p (void *owner, void *item)
+{
+ void *ptr;
+
+ if (hdr_getitem (owner, &ptr, NULL))
+ return 0;
+ return ptr == item;
+}
+
+static int
+hdr_data_dup (void **ptr, void *owner)
+{
+ *ptr = malloc (sizeof (struct header_iterator));
+ if (*ptr == NULL)
+ return ENOMEM;
+ memcpy (*ptr, owner, sizeof (struct header_iterator));
+ return 0;
+}
+
+int
+mu_header_get_iterator (mu_header_t hdr, mu_iterator_t *piterator)
+{
+ mu_iterator_t iterator;
+ int status;
+ struct header_iterator *itr;
+
+ if (!hdr)
+ return EINVAL;
+
+ itr = calloc (1, sizeof *itr);
+ if (!itr)
+ return ENOMEM;
+ itr->header = hdr;
+ itr->index = 1;
+
+ status = mu_iterator_create (&iterator, itr);
+ if (status)
+ {
+ free (itr);
+ return status;
+ }
+
+ mu_iterator_set_first (iterator, hdr_first);
+ mu_iterator_set_next (iterator, hdr_next);
+ mu_iterator_set_getitem (iterator, hdr_getitem);
+ mu_iterator_set_finished_p (iterator, hdr_finished_p);
+ mu_iterator_set_curitem_p (iterator, hdr_curitem_p);
+ mu_iterator_set_destroy (iterator, hdr_destroy);
+ mu_iterator_set_dup (iterator, hdr_data_dup);
+
+ mu_iterator_attach (&hdr->itr, iterator);
+
+ *piterator = iterator;
+ return 0;
+}
+
+
+
+
+
+
+
+
diff --git a/mailbox/header.c b/mailbox/header.c
index a5c1083ac..f423d1317 100644
--- a/mailbox/header.c
+++ b/mailbox/header.c
@@ -579,6 +579,7 @@ mu_header_remove (mu_header_t header, const char *fn, int n)
return MU_ERR_NOENT;
mu_hdrent_remove (header, ent);
+ HEADER_SET_MODIFIED (header);
free (ent);
return 0;
}

Return to:

Send suggestions and report system problems to the System administrator.