Now parsing options with argp instead of getopts.
Showing
2 changed files
with
155 additions
and
125 deletions
1 | #CFLAGS = -Wall -pedantic -g -DTESTING | 1 | #CFLAGS = -Wall -pedantic -g -DTESTING |
2 | AUTOMAKE_OPTIONS = ../lib/ansi2knr | 2 | AUTOMAKE_OPTIONS = ../lib/ansi2knr |
3 | INCLUDES = -I${top_srcdir}/include -I${top_srcdir}/lib | 3 | INCLUDES = -I${top_srcdir}/include -I${top_srcdir}/lib @ARGPINCS@ |
4 | YLWRAP = $(SHELL) $(srcdir)/ylwrap | 4 | YLWRAP = $(SHELL) $(srcdir)/ylwrap |
5 | YFLAGS = -d | 5 | YFLAGS = -d |
6 | 6 | ||
... | @@ -54,7 +54,7 @@ HDR = \ | ... | @@ -54,7 +54,7 @@ HDR = \ |
54 | util.h | 54 | util.h |
55 | 55 | ||
56 | sieve_DEPENDENCIES = ../mailbox/libmailbox.la | 56 | sieve_DEPENDENCIES = ../mailbox/libmailbox.la |
57 | sieve_LDADD = ../mailbox/libmailbox.la ../lib/libmailutils.a | 57 | sieve_LDADD = @ARGPLIBS@ ../mailbox/libmailbox.la ../lib/libmailutils.a |
58 | sieve_SOURCES = \ | 58 | sieve_SOURCES = \ |
59 | sieve.c \ | 59 | sieve.c \ |
60 | ${SRC} $(HDR) | 60 | ${SRC} $(HDR) | ... | ... |
1 | /* | 1 | /* |
2 | 2 | ||
3 | sieve interpreter | 3 | sieve script interpreter. |
4 | 4 | ||
5 | */ | 5 | */ |
6 | 6 | ||
... | @@ -10,11 +10,13 @@ sieve interpreter | ... | @@ -10,11 +10,13 @@ sieve interpreter |
10 | 10 | ||
11 | #include <assert.h> | 11 | #include <assert.h> |
12 | #include <errno.h> | 12 | #include <errno.h> |
13 | #include <stdarg.h> | ||
13 | #include <stdio.h> | 14 | #include <stdio.h> |
14 | #include <stdlib.h> | 15 | #include <stdlib.h> |
15 | #include <string.h> | 16 | #include <string.h> |
16 | #include <unistd.h> | 17 | #include <unistd.h> |
17 | #include <stdarg.h> | 18 | |
19 | #include <argp.h> | ||
18 | 20 | ||
19 | #include "sieve.h" | 21 | #include "sieve.h" |
20 | 22 | ||
... | @@ -23,26 +25,133 @@ sieve interpreter | ... | @@ -23,26 +25,133 @@ sieve interpreter |
23 | 25 | ||
24 | void mutil_register_all_mbox_formats(void); | 26 | void mutil_register_all_mbox_formats(void); |
25 | 27 | ||
26 | const char USAGE[] = | 28 | const char *argp_program_version = "sieve (" PACKAGE ") " VERSION; |
27 | "usage: sieve [-hnkvc] [-d <TPthq>] [-f mbox] [-t tickets] script\n"; | 29 | const char *argp_program_bug_address = "<bug-mailutils@gnu.org>"; |
28 | 30 | ||
29 | const char HELP[] = | 31 | static char doc[] = |
30 | " -h print this helpful message and exit.\n" | 32 | "GNU sieve -- a mail filtering tool\n" |
31 | " -n no execute, just print actions.\n" | 33 | "\v" |
32 | " -k keep on going if execution fails on a message.\n" | 34 | "Debug flags:\n" |
33 | " -v print actions executed on a message.\n" | 35 | " T - mailutil traces (MU_DEBUG_TRACE)\n" |
34 | " -c compile script and exit.\n" | 36 | " P - network protocols (MU_DEBUG_PROT)\n" |
35 | " -f the mbox to sieve, defaults to the users spool file.\n" | 37 | " t - sieve trace (SV_DEBUG_TRACE)\n" |
36 | " -t a ticket file to use for authentication to mailboxes.\n" | 38 | " h - sieve header filling (SV_DEBUG_HDR_FILL)\n" |
37 | " -d debug flags, each turns on a different set of messages:\n" | 39 | " q - sieve message queries (SV_DEBUG_MSG_QUERY)\n" |
38 | " T - mailutil traces\n" | ||
39 | " P - network protocols\n" | ||
40 | " t - sieve trace\n" | ||
41 | " h - sieve header parseing\n" | ||
42 | " q - sieve message queries\n" | ||
43 | " -m a mailer URL (default is \"sendmail:\")\n" | ||
44 | ; | 40 | ; |
45 | 41 | ||
42 | static struct argp_option options[] = { | ||
43 | {"no-actions", 'n', 0, 0, | ||
44 | "No actions executed, just print what would be done", 0}, | ||
45 | |||
46 | {"keep-going", 'k', 0, 0, | ||
47 | "Keep on going if execution fails on a message", 0}, | ||
48 | |||
49 | {"compile-only", 'c', 0, 0, | ||
50 | "Compile script and exit", 0}, | ||
51 | |||
52 | {"mbox-url", 'f', "MBOX", 0, | ||
53 | "Mailbox to sieve (defaults to user's mail spool)", 0}, | ||
54 | |||
55 | {"ticket", 't', "TICKET", 0, | ||
56 | "Ticket file for mailbox authentication", 0}, | ||
57 | |||
58 | {"mailer-url", 'm', "MAILER", 0, | ||
59 | "Mailer URL (defaults to \"sendmail:\")", 0}, | ||
60 | |||
61 | {"debug", 'd', "FLAGS", OPTION_ARG_OPTIONAL, | ||
62 | "Debug flags (defaults to \"TPt\")", 0}, | ||
63 | |||
64 | {0} | ||
65 | }; | ||
66 | |||
67 | struct options | ||
68 | { | ||
69 | int no_actions; | ||
70 | int keep_going; | ||
71 | int compile_only; | ||
72 | char *mbox; | ||
73 | char *tickets; | ||
74 | int debug_level; | ||
75 | char *mailer; | ||
76 | char *script; | ||
77 | }; | ||
78 | |||
79 | static error_t | ||
80 | parser (int key, char *arg, struct argp_state *state) | ||
81 | { | ||
82 | struct options *opts = state->input; | ||
83 | |||
84 | switch (key) | ||
85 | { | ||
86 | case ARGP_KEY_INIT: | ||
87 | opts->mailer = "sendmail:"; | ||
88 | break; | ||
89 | case 'n': | ||
90 | opts->no_actions = SV_FLAG_NO_ACTIONS; | ||
91 | break; | ||
92 | case 'k': | ||
93 | opts->keep_going = 1; | ||
94 | break; | ||
95 | case 'c': | ||
96 | opts->compile_only = 1; | ||
97 | break; | ||
98 | case 'f': | ||
99 | opts->mbox = arg; | ||
100 | break; | ||
101 | case 't': | ||
102 | opts->tickets = arg; | ||
103 | break; | ||
104 | case 'd': | ||
105 | for (; *arg; arg++) | ||
106 | { | ||
107 | switch (*arg) | ||
108 | { | ||
109 | case 'T': | ||
110 | opts->debug_level |= MU_DEBUG_TRACE; | ||
111 | break; | ||
112 | case 'P': | ||
113 | opts->debug_level |= MU_DEBUG_PROT; | ||
114 | break; | ||
115 | case 't': | ||
116 | opts->debug_level |= SV_DEBUG_TRACE; | ||
117 | break; | ||
118 | case 'h': | ||
119 | opts->debug_level |= SV_DEBUG_HDR_FILL; | ||
120 | break; | ||
121 | case 'q': | ||
122 | opts->debug_level |= SV_DEBUG_MSG_QUERY; | ||
123 | break; | ||
124 | default: | ||
125 | argp_error (state, "%c is not a valid debug flag", *arg); | ||
126 | break; | ||
127 | } | ||
128 | } | ||
129 | break; | ||
130 | |||
131 | case ARGP_KEY_ARG: | ||
132 | if (opts->script) | ||
133 | argp_error (state, "only one SCRIPT can be specified"); | ||
134 | opts->script = arg; | ||
135 | break; | ||
136 | |||
137 | case ARGP_KEY_NO_ARGS: | ||
138 | argp_error (state, "SCRIPT must be specified"); | ||
139 | break; | ||
140 | |||
141 | default: | ||
142 | return ARGP_ERR_UNKNOWN; | ||
143 | } | ||
144 | |||
145 | return 0; | ||
146 | } | ||
147 | |||
148 | static struct argp argp = { | ||
149 | options, | ||
150 | parser, | ||
151 | "SCRIPT", | ||
152 | doc | ||
153 | }; | ||
154 | |||
46 | static void | 155 | static void |
47 | parse_error (const char *script, int lineno, const char *errmsg) | 156 | parse_error (const char *script, int lineno, const char *errmsg) |
48 | { | 157 | { |
... | @@ -98,88 +207,17 @@ main (int argc, char *argv[]) | ... | @@ -98,88 +207,17 @@ main (int argc, char *argv[]) |
98 | mailer_t mailer = 0; | 207 | mailer_t mailer = 0; |
99 | mailbox_t mbox = 0; | 208 | mailbox_t mbox = 0; |
100 | 209 | ||
210 | struct options opts; | ||
211 | |||
101 | size_t count = 0; | 212 | size_t count = 0; |
102 | int msgno = 0; | 213 | int msgno = 0; |
103 | 214 | ||
104 | int rc = 0; | 215 | int rc = 0; |
105 | 216 | ||
106 | int opt_no_actions = 0; | 217 | argp_parse (&argp, argc, argv, ARGP_IN_ORDER, NULL, &opts); |
107 | int opt_keep_going = 0; | ||
108 | int opt_compile_only = 0; | ||
109 | char *opt_mbox = 0; | ||
110 | char *opt_tickets = 0; | ||
111 | int opt_debug_level = 0; | ||
112 | char *opt_mailer = "sendmail:"; | ||
113 | char *opt_script = 0; | ||
114 | |||
115 | int opt; | ||
116 | 218 | ||
117 | mutil_register_all_mbox_formats (); | 219 | mutil_register_all_mbox_formats (); |
118 | 220 | ||
119 | while ((opt = getopt (argc, argv, "hnkcf:t:d:")) != -1) | ||
120 | { | ||
121 | switch (opt) | ||
122 | { | ||
123 | case 'h': | ||
124 | printf ("%s\n", USAGE); | ||
125 | printf ("%s", HELP); | ||
126 | return 0; | ||
127 | case 'n': | ||
128 | opt_no_actions = SV_FLAG_NO_ACTIONS; | ||
129 | break; | ||
130 | case 'k': | ||
131 | opt_keep_going = 1; | ||
132 | break; | ||
133 | case 'c': | ||
134 | opt_compile_only = 1; | ||
135 | break; | ||
136 | case 'f': | ||
137 | opt_mbox = optarg; | ||
138 | break; | ||
139 | case 't': | ||
140 | opt_tickets = optarg; | ||
141 | break; | ||
142 | case 'd': | ||
143 | for (; *optarg; optarg++) | ||
144 | { | ||
145 | switch (*optarg) | ||
146 | { | ||
147 | case 'T': | ||
148 | opt_debug_level |= MU_DEBUG_TRACE; | ||
149 | break; | ||
150 | case 'P': | ||
151 | opt_debug_level |= MU_DEBUG_PROT; | ||
152 | break; | ||
153 | case 't': | ||
154 | opt_debug_level |= SV_DEBUG_TRACE; | ||
155 | break; | ||
156 | case 'h': | ||
157 | opt_debug_level |= SV_DEBUG_HDR_FILL; | ||
158 | break; | ||
159 | case 'q': | ||
160 | opt_debug_level |= SV_DEBUG_MSG_QUERY; | ||
161 | break; | ||
162 | default: | ||
163 | fprintf (stderr, "unknown debug flag %c\n", *optarg); | ||
164 | fprintf (stderr, "%s", USAGE); | ||
165 | return 1; | ||
166 | } | ||
167 | } | ||
168 | break; | ||
169 | default: | ||
170 | fprintf (stderr, "%s", USAGE); | ||
171 | return 1; | ||
172 | } | ||
173 | } | ||
174 | |||
175 | if (!argv[optind]) | ||
176 | { | ||
177 | fprintf (stderr, "%s", USAGE); | ||
178 | return 1; | ||
179 | } | ||
180 | |||
181 | opt_script = argv[optind]; | ||
182 | |||
183 | /* Sieve interpreter setup. */ | 221 | /* Sieve interpreter setup. */ |
184 | rc = sv_interp_alloc (&interp, parse_error, execute_error, action_log); | 222 | rc = sv_interp_alloc (&interp, parse_error, execute_error, action_log); |
185 | 223 | ||
... | @@ -189,7 +227,7 @@ main (int argc, char *argv[]) | ... | @@ -189,7 +227,7 @@ main (int argc, char *argv[]) |
189 | goto cleanup; | 227 | goto cleanup; |
190 | } | 228 | } |
191 | 229 | ||
192 | rc = sv_script_parse (&script, interp, opt_script); | 230 | rc = sv_script_parse (&script, interp, opts.script); |
193 | 231 | ||
194 | if (rc) | 232 | if (rc) |
195 | { | 233 | { |
... | @@ -197,21 +235,21 @@ main (int argc, char *argv[]) | ... | @@ -197,21 +235,21 @@ main (int argc, char *argv[]) |
197 | parse_error() was already called to report it. */ | 235 | parse_error() was already called to report it. */ |
198 | if (rc != SV_EPARSE) | 236 | if (rc != SV_EPARSE) |
199 | fprintf (stderr, "parsing %s failed: %s\n", | 237 | fprintf (stderr, "parsing %s failed: %s\n", |
200 | opt_script, sv_strerror (rc)); | 238 | opts.script, sv_strerror (rc)); |
201 | goto cleanup; | 239 | goto cleanup; |
202 | } | 240 | } |
203 | 241 | ||
204 | /* We can finish if its only a compilation check. */ | 242 | /* We can finish if its only a compilation check. */ |
205 | if (opt_compile_only) | 243 | if (opts.compile_only) |
206 | goto cleanup; | 244 | goto cleanup; |
207 | 245 | ||
208 | /* Create a ticket, if we can. */ | 246 | /* Create a ticket, if we can. */ |
209 | if (opt_tickets) | 247 | if (opts.tickets) |
210 | { | 248 | { |
211 | if ((rc = wicket_create (&wicket, opt_tickets)) != 0) | 249 | if ((rc = wicket_create (&wicket, opts.tickets)) != 0) |
212 | { | 250 | { |
213 | fprintf (stderr, "wicket create <%s> failed: %s\n", | 251 | fprintf (stderr, "wicket create <%s> failed: %s\n", |
214 | opt_tickets, strerror (rc)); | 252 | opts.tickets, strerror (rc)); |
215 | goto cleanup; | 253 | goto cleanup; |
216 | } | 254 | } |
217 | if ((rc = wicket_get_ticket (wicket, &ticket, 0, 0)) != 0) | 255 | if ((rc = wicket_get_ticket (wicket, &ticket, 0, 0)) != 0) |
... | @@ -222,14 +260,14 @@ main (int argc, char *argv[]) | ... | @@ -222,14 +260,14 @@ main (int argc, char *argv[]) |
222 | } | 260 | } |
223 | 261 | ||
224 | /* Create a debug object, if needed. */ | 262 | /* Create a debug object, if needed. */ |
225 | if (opt_debug_level) | 263 | if (opts.debug_level) |
226 | { | 264 | { |
227 | if ((rc = mu_debug_create (&debug, interp))) | 265 | if ((rc = mu_debug_create (&debug, interp))) |
228 | { | 266 | { |
229 | fprintf (stderr, "mu_debug_create failed: %s\n", strerror (rc)); | 267 | fprintf (stderr, "mu_debug_create failed: %s\n", strerror (rc)); |
230 | goto cleanup; | 268 | goto cleanup; |
231 | } | 269 | } |
232 | if ((rc = mu_debug_set_level (debug, opt_debug_level))) | 270 | if ((rc = mu_debug_set_level (debug, opts.debug_level))) |
233 | { | 271 | { |
234 | fprintf (stderr, "mu_debug_set_level failed: %s\n", strerror (rc)); | 272 | fprintf (stderr, "mu_debug_set_level failed: %s\n", strerror (rc)); |
235 | goto cleanup; | 273 | goto cleanup; |
... | @@ -242,10 +280,10 @@ main (int argc, char *argv[]) | ... | @@ -242,10 +280,10 @@ main (int argc, char *argv[]) |
242 | } | 280 | } |
243 | 281 | ||
244 | /* Create a mailer. */ | 282 | /* Create a mailer. */ |
245 | if ((rc = mailer_create(&mailer, opt_mailer))) | 283 | if ((rc = mailer_create(&mailer, opts.mailer))) |
246 | { | 284 | { |
247 | fprintf (stderr, "mailer create <%s> failed: %s\n", | 285 | fprintf (stderr, "mailer create <%s> failed: %s\n", |
248 | opt_mailer, strerror (rc)); | 286 | opts.mailer, strerror (rc)); |
249 | goto cleanup; | 287 | goto cleanup; |
250 | } | 288 | } |
251 | if (debug && (rc = mailer_set_debug (mailer, debug))) | 289 | if (debug && (rc = mailer_set_debug (mailer, debug))) |
... | @@ -255,10 +293,10 @@ main (int argc, char *argv[]) | ... | @@ -255,10 +293,10 @@ main (int argc, char *argv[]) |
255 | } | 293 | } |
256 | 294 | ||
257 | /* Create, give a ticket to, and open the mailbox. */ | 295 | /* Create, give a ticket to, and open the mailbox. */ |
258 | if ((rc = mailbox_create_default (&mbox, opt_mbox)) != 0) | 296 | if ((rc = mailbox_create_default (&mbox, opts.mbox)) != 0) |
259 | { | 297 | { |
260 | fprintf (stderr, "mailbox create <%s> failed: %s\n", | 298 | fprintf (stderr, "mailbox create <%s> failed: %s\n", |
261 | opt_mbox ? opt_mbox : "default", strerror (rc)); | 299 | opts.mbox ? opts.mbox : "default", strerror (rc)); |
262 | goto cleanup; | 300 | goto cleanup; |
263 | } | 301 | } |
264 | 302 | ||
... | @@ -294,7 +332,7 @@ main (int argc, char *argv[]) | ... | @@ -294,7 +332,7 @@ main (int argc, char *argv[]) |
294 | } | 332 | } |
295 | 333 | ||
296 | /* Open the mailbox read-only if we aren't going to modify it. */ | 334 | /* Open the mailbox read-only if we aren't going to modify it. */ |
297 | if (opt_no_actions) | 335 | if (opts.no_actions) |
298 | rc = mailbox_open (mbox, MU_STREAM_READ); | 336 | rc = mailbox_open (mbox, MU_STREAM_READ); |
299 | else | 337 | else |
300 | rc = mailbox_open (mbox, MU_STREAM_RDWR); | 338 | rc = mailbox_open (mbox, MU_STREAM_RDWR); |
... | @@ -302,7 +340,7 @@ main (int argc, char *argv[]) | ... | @@ -302,7 +340,7 @@ main (int argc, char *argv[]) |
302 | if (rc != 0) | 340 | if (rc != 0) |
303 | { | 341 | { |
304 | fprintf (stderr, "open on %s failed: %s\n", | 342 | fprintf (stderr, "open on %s failed: %s\n", |
305 | opt_mbox ? opt_mbox : "default", strerror (rc)); | 343 | opts.mbox ? opts.mbox : "default", strerror (rc)); |
306 | goto cleanup; | 344 | goto cleanup; |
307 | } | 345 | } |
308 | 346 | ||
... | @@ -312,18 +350,10 @@ main (int argc, char *argv[]) | ... | @@ -312,18 +350,10 @@ main (int argc, char *argv[]) |
312 | if (rc != 0) | 350 | if (rc != 0) |
313 | { | 351 | { |
314 | fprintf (stderr, "message count on %s failed: %s\n", | 352 | fprintf (stderr, "message count on %s failed: %s\n", |
315 | opt_mbox ? opt_mbox : "default", strerror (rc)); | 353 | opts.mbox ? opts.mbox : "default", strerror (rc)); |
316 | goto cleanup; | 354 | goto cleanup; |
317 | } | 355 | } |
318 | 356 | ||
319 | /* | ||
320 | if (opt_verbose) | ||
321 | { | ||
322 | fprintf (stderr, "mbox %s has %d messages...\n", | ||
323 | ic.opt_mbox, count); | ||
324 | } | ||
325 | */ | ||
326 | |||
327 | for (msgno = 1; msgno <= count; ++msgno) | 357 | for (msgno = 1; msgno <= count; ++msgno) |
328 | { | 358 | { |
329 | message_t msg = 0; | 359 | message_t msg = 0; |
... | @@ -331,18 +361,18 @@ main (int argc, char *argv[]) | ... | @@ -331,18 +361,18 @@ main (int argc, char *argv[]) |
331 | if ((rc = mailbox_get_message (mbox, msgno, &msg)) != 0) | 361 | if ((rc = mailbox_get_message (mbox, msgno, &msg)) != 0) |
332 | { | 362 | { |
333 | fprintf (stderr, "get message on %s (msg %d) failed: %s\n", | 363 | fprintf (stderr, "get message on %s (msg %d) failed: %s\n", |
334 | opt_mbox ? opt_mbox : "default", msgno, strerror (rc)); | 364 | opts.mbox ? opts.mbox : "default", msgno, strerror (rc)); |
335 | goto cleanup; | 365 | goto cleanup; |
336 | } | 366 | } |
337 | 367 | ||
338 | rc = sv_script_execute (script, msg, ticket, debug, mailer, opt_no_actions); | 368 | rc = sv_script_execute (script, msg, ticket, debug, mailer, opts.no_actions); |
339 | 369 | ||
340 | if (rc) | 370 | if (rc) |
341 | { | 371 | { |
342 | fprintf (stderr, "execution of %s on %s (msg %d) failed: %s\n", | 372 | fprintf (stderr, "execution of %s on %s (msg %d) failed: %s\n", |
343 | opt_script, opt_mbox ? opt_mbox : "default", msgno, | 373 | opts.script, opts.mbox ? opts.mbox : "default", msgno, |
344 | sv_strerror (rc)); | 374 | sv_strerror (rc)); |
345 | if (opt_keep_going) | 375 | if (opts.keep_going) |
346 | rc = 0; | 376 | rc = 0; |
347 | else | 377 | else |
348 | goto cleanup; | 378 | goto cleanup; |
... | @@ -350,7 +380,7 @@ main (int argc, char *argv[]) | ... | @@ -350,7 +380,7 @@ main (int argc, char *argv[]) |
350 | } | 380 | } |
351 | 381 | ||
352 | cleanup: | 382 | cleanup: |
353 | if (mbox && !opt_no_actions && !opt_compile_only) | 383 | if (mbox && !opts.no_actions && !opts.compile_only) |
354 | { | 384 | { |
355 | int e; | 385 | int e; |
356 | 386 | ||
... | @@ -360,7 +390,7 @@ cleanup: | ... | @@ -360,7 +390,7 @@ cleanup: |
360 | on a later message. */ | 390 | on a later message. */ |
361 | if ((e = mailbox_expunge (mbox)) != 0) | 391 | if ((e = mailbox_expunge (mbox)) != 0) |
362 | fprintf (stderr, "expunge on %s failed: %s\n", | 392 | fprintf (stderr, "expunge on %s failed: %s\n", |
363 | opt_mbox ? opt_mbox : "default", strerror (e)); | 393 | opts.mbox ? opts.mbox : "default", strerror (e)); |
364 | 394 | ||
365 | if(e && !rc) | 395 | if(e && !rc) |
366 | rc = e; | 396 | rc = e; | ... | ... |
-
Please register or sign in to post a comment