Commit c3aab462 c3aab4628802557768ed0f1f4caef401cdc052d8 by Sergey Poznyakoff

* 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.
1 parent 46e86fe1
1 2008-02-04 Sergey Poznyakoff <gray@gnu.org.ua>
2
3 * NEWS: Update.
4 * examples/header.c: New command `itr'.
5 (main): Empty input repeats the recent command.
6 * include/mailutils/header.h (mu_header_get_iterator): New
7 function.
8 * libproto/include/header0.h (struct _mu_header): New member itr.
9 * mailbox/Makefile.am (libmailutils_la_SOURCES): Add hdritr.c
10 * mailbox/hdritr.c: New file.
11 * mailbox/header.c (mu_header_remove): Bugfix. Invalidate the
12 header after removal.
13
1 2008-01-31 Sergey Poznyakoff <gray@gnu.org.ua> 14 2008-01-31 Sergey Poznyakoff <gray@gnu.org.ua>
2 15
3 * auth/radius.c (_expand_query): Fix typo. 16 * auth/radius.c (_expand_query): Fix typo.
......
1 GNU mailutils NEWS -- history of user-visible changes. 2008-01-12 1 GNU mailutils NEWS -- history of user-visible changes. 2008-02-04
2 Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. 2 Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
3 See the end of file for copying conditions. 3 See the end of file for copying conditions.
4 4
...@@ -143,6 +143,24 @@ approach is recommended to use instead of mu_error_set_print: ...@@ -143,6 +143,24 @@ approach is recommended to use instead of mu_error_set_print:
143 mu_diag_get_debug (&debug); 143 mu_diag_get_debug (&debug);
144 mu_debug_set_print (debug, new_printer, NULL); 144 mu_debug_set_print (debug, new_printer, NULL);
145 145
146 ** Header iteration
147
148 New function `mu_header_get_iterator' returns an iterator for this
149 header object. Thus, the following code loops over all headers:
150
151 mu_iterator_t itr;
152 mu_header_get_iterator (header, &itr);
153 for (mu_iterator_first (itr); !mu_iterator_is_done (itr);
154 mu_iterator_next (itr))
155 {
156 const char *hdr, *val;
157 mu_iterator_current_kv (itr,
158 (const void**)&hdr,
159 (void**)&val));
160 /* Do something with hdr and val */
161 }
162 mu_iterator_destroy (&itr);
163
146 ** Global debugging and verbosity settings. 164 ** Global debugging and verbosity settings.
147 165
148 These settings provide default values for mu_debug_t objects created 166 These settings provide default values for mu_debug_t objects created
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
27 27
28 char *file; 28 char *file;
29 mu_header_t header; 29 mu_header_t header;
30 mu_iterator_t iterator;
30 31
31 char *ps[] = { "> ", ". " }; 32 char *ps[] = { "> ", ". " };
32 int interactive; 33 int interactive;
...@@ -132,6 +133,7 @@ cmd_free (int argc, char **argv) ...@@ -132,6 +133,7 @@ cmd_free (int argc, char **argv)
132 { 133 {
133 if (check_args (argv[0], argc, 1, 1)) 134 if (check_args (argv[0], argc, 1, 1))
134 return; 135 return;
136 mu_iterator_destroy (&iterator);
135 mu_header_destroy (&header, NULL); 137 mu_header_destroy (&header, NULL);
136 } 138 }
137 139
...@@ -285,7 +287,55 @@ cmd_write (int argc, char **argv) ...@@ -285,7 +287,55 @@ cmd_write (int argc, char **argv)
285 break; 287 break;
286 } 288 }
287 } 289 }
288 290
291 void
292 cmd_iterate (int argc, char **argv)
293 {
294 if (check_args (argv[0], argc, 1, 2))
295 return;
296 if (argc == 1)
297 {
298 mu_iterator_t itr;
299 MU_ASSERT (mu_header_get_iterator (header, &itr));
300 for (mu_iterator_first (itr); !mu_iterator_is_done (itr);
301 mu_iterator_next (itr))
302 {
303 const char *hdr, *val;
304 MU_ASSERT (mu_iterator_current_kv (itr,
305 (const void**)&hdr,
306 (void**)&val));
307 printf ("%s: %s\n", hdr, val);
308 }
309 mu_iterator_destroy (&itr);
310 }
311 else
312 {
313 const char *hdr, *val;
314
315 if (!iterator)
316 MU_ASSERT (mu_header_get_iterator (header, &iterator));
317
318 if (strcmp (argv[1], "first") == 0 || strcmp (argv[1], "1") == 0)
319 mu_iterator_first (iterator);
320 else if (strcmp (argv[1], "next") == 0 || strcmp (argv[1], "n") == 0)
321 {
322 mu_iterator_next (iterator);
323 if (mu_iterator_is_done (iterator))
324 {
325 printf ("Past end of headers. Use `itr first'.\n");
326 return;
327 }
328 }
329
330 MU_ASSERT (mu_iterator_current_kv (iterator,
331 (const void **)&hdr,
332 (void**)&val));
333 printf ("%s: %s\n", hdr, val);
334 }
335 }
336
337
338
289 struct cmdtab 339 struct cmdtab
290 { 340 {
291 char *name; 341 char *name;
...@@ -303,6 +353,7 @@ static struct cmdtab cmdtab[] = { ...@@ -303,6 +353,7 @@ static struct cmdtab cmdtab[] = {
303 { "print", cmd_print, "NAME [N]", 353 { "print", cmd_print, "NAME [N]",
304 "find and print the Nth (by default, 1st) instance of header named NAME" }, 354 "find and print the Nth (by default, 1st) instance of header named NAME" },
305 { "dump", cmd_dump, NULL, "dump all headers on screen" }, 355 { "dump", cmd_dump, NULL, "dump all headers on screen" },
356 { "itr", cmd_iterate, "[first|1|next|n]", "iterate over headers" },
306 { "remove", cmd_remove, "NAME [N]", 357 { "remove", cmd_remove, "NAME [N]",
307 "remove the Nth (by default, 1st) instance of header named NAME" }, 358 "remove the Nth (by default, 1st) instance of header named NAME" },
308 { "insert", cmd_insert, "NAME VALUE [REF [NUM] [before|after] [replace]]", 359 { "insert", cmd_insert, "NAME VALUE [REF [NUM] [before|after] [replace]]",
...@@ -392,11 +443,27 @@ cmd_help (int argc, char **argv) ...@@ -392,11 +443,27 @@ cmd_help (int argc, char **argv)
392 } 443 }
393 444
394 int 445 int
446 docmd (int argc, char **argv)
447 {
448 struct cmdtab *cmd = find_cmd (argv[0]);
449 if (!cmd)
450 {
451 mu_error ("%u: unknown command %s", line_num, argv[0]);
452 return 1;
453 }
454 else
455 cmd->fun (argc, argv);
456 return 0;
457 }
458
459 int
395 main (int argc, char **argv) 460 main (int argc, char **argv)
396 { 461 {
397 int c; 462 int c;
398 char buf[512]; 463 char buf[512];
399 464 char **prevv;
465 int prevc = 0;
466
400 interactive = isatty (0); 467 interactive = isatty (0);
401 while ((c = getopt (argc, argv, "f:h")) != EOF) 468 while ((c = getopt (argc, argv, "f:h")) != EOF)
402 { 469 {
...@@ -434,7 +501,6 @@ main (int argc, char **argv) ...@@ -434,7 +501,6 @@ main (int argc, char **argv)
434 { 501 {
435 int c; 502 int c;
436 char **v; 503 char **v;
437 struct cmdtab *cmd;
438 int status; 504 int status;
439 505
440 line_num++; 506 line_num++;
...@@ -446,17 +512,20 @@ main (int argc, char **argv) ...@@ -446,17 +512,20 @@ main (int argc, char **argv)
446 continue; 512 continue;
447 } 513 }
448 514
449 cmd = find_cmd (v[0]); 515 if (c == 0)
450 if (!cmd)
451 { 516 {
452 mu_error ("%u: unknown command %s", 517 if (prevc)
453 line_num, v[0]); 518 docmd (prevc, prevv);
519 else
520 mu_argcv_free (c, v);
454 } 521 }
455 else 522 else
456 cmd->fun (c, v); 523 {
457 524 docmd (c, v);
458 mu_argcv_free (c, v); 525 mu_argcv_free (prevc, prevv);
459 526 prevc = c;
527 prevv = v;
528 }
460 } 529 }
461 exit (0); 530 exit (0);
462 } 531 }
......
...@@ -154,6 +154,8 @@ extern int mu_header_set_stream (mu_header_t, mu_stream_t, void *); ...@@ -154,6 +154,8 @@ extern int mu_header_set_stream (mu_header_t, mu_stream_t, void *);
154 extern int mu_header_size (mu_header_t, size_t *); 154 extern int mu_header_size (mu_header_t, size_t *);
155 extern int mu_header_lines (mu_header_t, size_t *); 155 extern int mu_header_lines (mu_header_t, size_t *);
156 156
157 extern int mu_header_get_iterator (mu_header_t, mu_iterator_t *);
158
157 159
158 extern int mu_header_set_fill (mu_header_t, 160 extern int mu_header_set_fill (mu_header_t,
159 int (*_fill) (mu_header_t, char *, size_t, mu_off_t, size_t *), void *owner); 161 int (*_fill) (mu_header_t, char *, size_t, mu_off_t, size_t *), void *owner);
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
25 25
26 #include <mailutils/header.h> 26 #include <mailutils/header.h>
27 #include <mailutils/assoc.h> 27 #include <mailutils/assoc.h>
28 #include <mailutils/iterator.h>
28 #include <sys/types.h> 29 #include <sys/types.h>
29 30
30 #ifdef __cplusplus 31 #ifdef __cplusplus
...@@ -67,7 +68,10 @@ struct _mu_header ...@@ -67,7 +68,10 @@ struct _mu_header
67 /* Stream. */ 68 /* Stream. */
68 mu_stream_t stream; 69 mu_stream_t stream;
69 size_t strpos; 70 size_t strpos;
70 71
72 /* Iterators */
73 mu_iterator_t itr;
74
71 /* Methods */ 75 /* Methods */
72 int (*_fill) (mu_header_t, char *, size_t, mu_off_t, size_t *); 76 int (*_fill) (mu_header_t, char *, size_t, mu_off_t, size_t *);
73 }; 77 };
......
...@@ -65,6 +65,7 @@ libmailutils_la_SOURCES = \ ...@@ -65,6 +65,7 @@ libmailutils_la_SOURCES = \
65 folder.c\ 65 folder.c\
66 gdebug.c\ 66 gdebug.c\
67 gocs.c\ 67 gocs.c\
68 hdritr.c\
68 header.c\ 69 header.c\
69 iterator.c\ 70 iterator.c\
70 ipsrv.c\ 71 ipsrv.c\
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2008 Free Software Foundation, Inc.
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 3 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General
15 Public License along with this library; if not, write to the
16 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301 USA */
18
19 /* Mail header iterators. */
20
21 #ifdef HAVE_CONFIG_H
22 # include <config.h>
23 #endif
24 #include <stdlib.h>
25 #include <string.h>
26
27 #include <header0.h>
28 #include <mailutils/errno.h>
29
30 struct header_iterator
31 {
32 mu_header_t header;
33 size_t index;
34 };
35
36 static int
37 hdr_first (void *owner)
38 {
39 struct header_iterator *itr = owner;
40 itr->index = 1;
41 return 0;
42 }
43
44 static int
45 hdr_next (void *owner)
46 {
47 struct header_iterator *itr = owner;
48 itr->index++;
49 return 0;
50 }
51
52 static int
53 hdr_getitem (void *owner, void **pret, const void **pkey)
54 {
55 struct header_iterator *itr = owner;
56 int rc;
57 size_t count;
58
59 rc = mu_header_get_field_count (itr->header, &count);
60 if (rc)
61 return rc;
62 if (itr->index > count)
63 return MU_ERR_NOENT;
64
65 rc = mu_header_sget_field_name (itr->header, itr->index,
66 (const char**) pkey);
67 if (rc == 0)
68 {
69 if (pkey)
70 rc = mu_header_sget_field_value (itr->header, itr->index,
71 (const char**) pret);
72 }
73 return rc;
74 }
75
76 static int
77 hdr_finished_p (void *owner)
78 {
79 struct header_iterator *itr = owner;
80 size_t count;
81
82 if (mu_header_get_field_count (itr->header, &count))
83 return 1;
84 return itr->index > count;
85 }
86
87 static int
88 hdr_destroy (mu_iterator_t iterator, void *data)
89 {
90 struct header_iterator *itr = data;
91 mu_iterator_detach (&itr->header->itr, iterator);
92 free (data);
93 return 0;
94 }
95
96 static int
97 hdr_curitem_p (void *owner, void *item)
98 {
99 void *ptr;
100
101 if (hdr_getitem (owner, &ptr, NULL))
102 return 0;
103 return ptr == item;
104 }
105
106 static int
107 hdr_data_dup (void **ptr, void *owner)
108 {
109 *ptr = malloc (sizeof (struct header_iterator));
110 if (*ptr == NULL)
111 return ENOMEM;
112 memcpy (*ptr, owner, sizeof (struct header_iterator));
113 return 0;
114 }
115
116 int
117 mu_header_get_iterator (mu_header_t hdr, mu_iterator_t *piterator)
118 {
119 mu_iterator_t iterator;
120 int status;
121 struct header_iterator *itr;
122
123 if (!hdr)
124 return EINVAL;
125
126 itr = calloc (1, sizeof *itr);
127 if (!itr)
128 return ENOMEM;
129 itr->header = hdr;
130 itr->index = 1;
131
132 status = mu_iterator_create (&iterator, itr);
133 if (status)
134 {
135 free (itr);
136 return status;
137 }
138
139 mu_iterator_set_first (iterator, hdr_first);
140 mu_iterator_set_next (iterator, hdr_next);
141 mu_iterator_set_getitem (iterator, hdr_getitem);
142 mu_iterator_set_finished_p (iterator, hdr_finished_p);
143 mu_iterator_set_curitem_p (iterator, hdr_curitem_p);
144 mu_iterator_set_destroy (iterator, hdr_destroy);
145 mu_iterator_set_dup (iterator, hdr_data_dup);
146
147 mu_iterator_attach (&hdr->itr, iterator);
148
149 *piterator = iterator;
150 return 0;
151 }
152
153
154
155
156
157
158
159
...@@ -579,6 +579,7 @@ mu_header_remove (mu_header_t header, const char *fn, int n) ...@@ -579,6 +579,7 @@ mu_header_remove (mu_header_t header, const char *fn, int n)
579 return MU_ERR_NOENT; 579 return MU_ERR_NOENT;
580 580
581 mu_hdrent_remove (header, ent); 581 mu_hdrent_remove (header, ent);
582 HEADER_SET_MODIFIED (header);
582 free (ent); 583 free (ent);
583 return 0; 584 return 0;
584 } 585 }
......