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/mailutils.h>
20
21 mu_msgset_format_t format = mu_msgset_fmt_imap;
22
23 static void
parse_msgrange(char const * arg,struct mu_msgrange * range)24 parse_msgrange (char const *arg, struct mu_msgrange *range)
25 {
26 size_t msgnum;
27 char *p;
28
29 errno = 0;
30 msgnum = strtoul (arg, &p, 10);
31 range->msg_beg = msgnum;
32 if (*p == ':')
33 {
34 if (*++p == '*')
35 msgnum = 0;
36 else
37 {
38 msgnum = strtoul (p, &p, 10);
39 if (*p)
40 {
41 mu_error ("error in message range near %s", p);
42 exit (1);
43 }
44 }
45 }
46 else if (*p == '*')
47 msgnum = 0;
48 else if (*p)
49 {
50 mu_error ("error in message range near %s", p);
51 exit (1);
52 }
53
54 range->msg_end = msgnum;
55 }
56
57 mu_msgset_t
parse_msgset(const char * arg)58 parse_msgset (const char *arg)
59 {
60 int rc;
61 mu_msgset_t msgset;
62 char *end;
63
64 MU_ASSERT (mu_msgset_create (&msgset, NULL, MU_MSGSET_NUM));
65 if (arg)
66 {
67 rc = mu_msgset_parse_imap (msgset, MU_MSGSET_NUM, arg, &end);
68 if (rc)
69 {
70 mu_error ("mu_msgset_parse_imap: %s near %s",
71 mu_strerror (rc), end);
72 exit (1);
73 }
74 }
75 return msgset;
76 }
77
78 static void
print_all(mu_msgset_t msgset)79 print_all (mu_msgset_t msgset)
80 {
81 MU_ASSERT (mu_stream_msgset_format (mu_strout, format, msgset));
82 mu_printf ("\n");
83 }
84
85 static void
print_first(mu_msgset_t msgset)86 print_first (mu_msgset_t msgset)
87 {
88 size_t n;
89 MU_ASSERT (mu_msgset_first (msgset, &n));
90 printf ("%zu\n", n);
91 }
92
93 static void
print_last(mu_msgset_t msgset)94 print_last (mu_msgset_t msgset)
95 {
96 size_t n;
97 MU_ASSERT (mu_msgset_last (msgset, &n));
98 printf ("%zu\n", n);
99 }
100
101 static void
cli_msgset(struct mu_parseopt * po,struct mu_option * opt,char const * arg)102 cli_msgset (struct mu_parseopt *po, struct mu_option *opt, char const *arg)
103 {
104 mu_msgset_t *msgset = opt->opt_ptr;
105 if (*msgset)
106 {
107 mu_parseopt_error (po, "message set already defined");
108 exit (po->po_exit_error);
109 }
110 *msgset = parse_msgset (arg);
111 }
112
113 static void
cli_mh(struct mu_parseopt * po,struct mu_option * opt,char const * arg)114 cli_mh (struct mu_parseopt *po, struct mu_option *opt, char const *arg)
115 {
116 format = mu_msgset_fmt_mh;
117 }
118
119 static mu_msgset_t
get_msgset(struct mu_option * opt)120 get_msgset (struct mu_option *opt)
121 {
122 mu_msgset_t *msgset = opt->opt_ptr;
123 if (!*msgset)
124 {
125 *msgset = parse_msgset (NULL);
126 }
127 return *msgset;
128 }
129
130 static void
cli_add(struct mu_parseopt * po,struct mu_option * opt,char const * arg)131 cli_add (struct mu_parseopt *po, struct mu_option *opt, char const *arg)
132 {
133 struct mu_msgrange range;
134 parse_msgrange (arg, &range);
135 MU_ASSERT (mu_msgset_add_range (get_msgset (opt), range.msg_beg,
136 range.msg_end, MU_MSGSET_NUM));
137 }
138
139 static void
cli_sub(struct mu_parseopt * po,struct mu_option * opt,char const * arg)140 cli_sub (struct mu_parseopt *po, struct mu_option *opt, char const *arg)
141 {
142 struct mu_msgrange range;
143 parse_msgrange (arg, &range);
144 MU_ASSERT (mu_msgset_sub_range (get_msgset (opt), range.msg_beg,
145 range.msg_end, MU_MSGSET_NUM));
146 }
147
148 static void
cli_addset(struct mu_parseopt * po,struct mu_option * opt,char const * arg)149 cli_addset (struct mu_parseopt *po, struct mu_option *opt, char const *arg)
150 {
151 mu_msgset_t tset = parse_msgset (arg);
152 MU_ASSERT (mu_msgset_add (get_msgset (opt), tset));
153 mu_msgset_free (tset);
154 }
155
156 static void
cli_subset(struct mu_parseopt * po,struct mu_option * opt,char const * arg)157 cli_subset (struct mu_parseopt *po, struct mu_option *opt, char const *arg)
158 {
159 mu_msgset_t tset = parse_msgset (arg);
160 MU_ASSERT (mu_msgset_sub (get_msgset (opt), tset));
161 mu_msgset_free (tset);
162 }
163
164 static void
cli_first(struct mu_parseopt * po,struct mu_option * opt,char const * arg)165 cli_first (struct mu_parseopt *po, struct mu_option *opt, char const *arg)
166 {
167 void (**print) (mu_msgset_t) = opt->opt_ptr;
168 *print = print_first;
169 }
170
171 static void
cli_last(struct mu_parseopt * po,struct mu_option * opt,char const * arg)172 cli_last (struct mu_parseopt *po, struct mu_option *opt, char const *arg)
173 {
174 void (**print) (mu_msgset_t) = opt->opt_ptr;
175 *print = print_last;
176 }
177
178 int
main(int argc,char ** argv)179 main (int argc, char **argv)
180 {
181 mu_msgset_t msgset = NULL;
182 void (*print) (mu_msgset_t) = print_all;
183
184 struct mu_option options[] = {
185 { "mh", 0, NULL, MU_OPTION_DEFAULT,
186 "use MH message set format for output", mu_c_incr, NULL, cli_mh },
187 { "msgset", 0, "SET", MU_OPTION_DEFAULT,
188 "define message set", mu_c_string, &msgset, cli_msgset },
189 { "add", 0, "X[:Y]", MU_OPTION_DEFAULT,
190 "add range to message set", mu_c_string, &msgset, cli_add },
191 { "sub", 0, "X[:Y]", MU_OPTION_DEFAULT,
192 "subtract range from message set", mu_c_string, &msgset, cli_sub },
193 { "addset", 0, "SET", MU_OPTION_DEFAULT,
194 "add message set to message set", mu_c_string, &msgset, cli_addset },
195 { "subset", 0, "SET", MU_OPTION_DEFAULT,
196 "subtract message set from message set", mu_c_string, &msgset,
197 cli_subset },
198 { "first", 0, NULL, MU_OPTION_DEFAULT,
199 "print only first element from the resulting set",
200 mu_c_string, &print, cli_first },
201 { "last", 0, NULL, MU_OPTION_DEFAULT,
202 "print only last element from the resulting set",
203 mu_c_string, &print, cli_last },
204 MU_OPTION_END
205 };
206
207 mu_set_program_name (argv[0]);
208 mu_cli_simple (argc, argv,
209 MU_CLI_OPTION_OPTIONS, options,
210 MU_CLI_OPTION_SINGLE_DASH,
211 MU_CLI_OPTION_PROG_DOC, "message set parser test utility",
212 MU_CLI_OPTION_END);
213
214 if (!msgset)
215 {
216 mu_error ("nothing to do; try %s -help for assistance", mu_program_name);
217 exit (1);
218 }
219
220 print (msgset);
221 mu_msgset_free (msgset);
222
223 return 0;
224 }
225
226
227
228
229