Commit 1cbd9527 1cbd9527dcb568e2facb3da3ee3daeaf1021560e by Sam Roberts

Now parsing options with argp instead of getopts.

1 parent 9247183d
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;
......