1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2011-2021 Free Software Foundation, Inc.
3
4 GNU Mailutils is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 GNU Mailutils 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
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
16
17 #include <config.h>
18 #include <stdlib.h>
19 #include <mailutils/types.h>
20 #include <mailutils/errno.h>
21 #include <mailutils/list.h>
22 #include <mailutils/msgset.h>
23 #include <mailutils/mailbox.h>
24 #include <mailutils/sys/msgset.h>
25
26 struct action_closure
27 {
28 mu_msgset_msgno_action_t action;
29 void *data;
30 mu_msgset_t msgset;
31 int flags;
32 };
33
34 static int
call_action(struct action_closure * clos,size_t i)35 call_action (struct action_closure *clos, size_t i)
36 {
37 size_t n;
38 int cmd;
39
40 if (_MU_MSGSET_MODE (clos->msgset->flags) != _MU_MSGSET_MODE (clos->flags))
41 {
42 int rc;
43
44 switch (_MU_MSGSET_MODE (clos->flags))
45 {
46 case MU_MSGSET_NUM:
47 cmd = MU_MAILBOX_UID_TO_MSGNO;
48 break;
49
50 case MU_MSGSET_UID:
51 cmd = MU_MAILBOX_MSGNO_TO_UID;
52 break;
53
54 default:
55 return EINVAL;
56 }
57
58 rc = mu_mailbox_translate (clos->msgset->mbox, cmd, i, &n);
59 if (rc == MU_ERR_NOENT)
60 return 0;
61 if (rc)
62 return rc;
63 }
64 else
65 n = i;
66 return clos->action (n, clos->data);
67 }
68
69
70 static int
procrange(void * item,void * data)71 procrange (void *item, void *data)
72 {
73 struct mu_msgrange *mp = item;
74 struct action_closure *clos = data;
75 size_t i;
76 int rc = 0;
77
78 if (clos->flags & MU_MSGSET_FOREACH_BACKWARD)
79 for (i = mp->msg_end; rc == 0 && i >= mp->msg_beg; i--)
80 rc = call_action (clos, i);
81 else
82 for (i = mp->msg_beg; rc == 0 && i <= mp->msg_end; i++)
83 rc = call_action (clos, i);
84 return rc;
85 }
86
87 /* Apply ACTION to each message number or UID from MSGSET. */
88 int
mu_msgset_foreach_num(mu_msgset_t msgset,int flags,mu_msgset_msgno_action_t action,void * data)89 mu_msgset_foreach_num (mu_msgset_t msgset, int flags,
90 mu_msgset_msgno_action_t action,
91 void *data)
92 {
93 int rc;
94 struct action_closure clos;
95
96 rc = mu_msgset_aggregate (msgset);
97 if (rc)
98 return rc;
99 clos.action = action;
100 clos.data = data;
101 clos.flags = flags;
102 clos.msgset = msgset;
103 return mu_list_foreach_dir (msgset->list,
104 !!(flags & MU_MSGSET_FOREACH_BACKWARD),
105 procrange, &clos);
106 }
107