Commit de82eae6 de82eae68b917d574ad60a0046f5a2810d4352e6 by Sam Roberts

Now supports a ~/.sieverc file. Mine looks like:

  # ~/.sieverc
  #   Just moves my mail into my local spool.
  -dTt --ticket=~/.tickets
  -f pop://pop.uniserve.com
  ~/.filter.sv
1 parent 99885cb9
...@@ -10,18 +10,23 @@ sieve script interpreter. ...@@ -10,18 +10,23 @@ sieve script interpreter.
10 10
11 #include <assert.h> 11 #include <assert.h>
12 #include <errno.h> 12 #include <errno.h>
13 #include <fcntl.h>
13 #include <stdarg.h> 14 #include <stdarg.h>
14 #include <stdio.h> 15 #include <stdio.h>
15 #include <stdlib.h> 16 #include <stdlib.h>
16 #include <string.h> 17 #include <string.h>
17 #include <unistd.h> 18 #include <unistd.h>
18 19
20 #include <sys/stat.h>
21
22 #include <argcv.h>
19 #include <argp.h> 23 #include <argp.h>
20 24
21 #include "sieve.h" 25 #include "sieve.h"
22 26
23 #include <mailutils/registrar.h>
24 #include <mailutils/mailbox.h> 27 #include <mailutils/mailbox.h>
28 #include <mailutils/mutil.h>
29 #include <mailutils/registrar.h>
25 30
26 void mutil_register_all_mbox_formats(void); 31 void mutil_register_all_mbox_formats(void);
27 32
...@@ -39,6 +44,8 @@ static char doc[] = ...@@ -39,6 +44,8 @@ static char doc[] =
39 " q - sieve message queries (SV_DEBUG_MSG_QUERY)\n" 44 " q - sieve message queries (SV_DEBUG_MSG_QUERY)\n"
40 ; 45 ;
41 46
47 #define D_DEFAULT "TPt"
48
42 static struct argp_option options[] = { 49 static struct argp_option options[] = {
43 {"no-actions", 'n', 0, 0, 50 {"no-actions", 'n', 0, 0,
44 "No actions executed, just print what would be done", 0}, 51 "No actions executed, just print what would be done", 0},
...@@ -59,7 +66,7 @@ static struct argp_option options[] = { ...@@ -59,7 +66,7 @@ static struct argp_option options[] = {
59 "Mailer URL (defaults to \"sendmail:\")", 0}, 66 "Mailer URL (defaults to \"sendmail:\")", 0},
60 67
61 {"debug", 'd', "FLAGS", OPTION_ARG_OPTIONAL, 68 {"debug", 'd', "FLAGS", OPTION_ARG_OPTIONAL,
62 "Debug flags (defaults to \"TPt\")", 0}, 69 "Debug flags (defaults to \"" D_DEFAULT "\")", 0},
63 70
64 {0} 71 {0}
65 }; 72 };
...@@ -74,6 +81,8 @@ struct options ...@@ -74,6 +81,8 @@ struct options
74 int debug_level; 81 int debug_level;
75 char *mailer; 82 char *mailer;
76 char *script; 83 char *script;
84
85 int final; /* final arg pass */
77 }; 86 };
78 87
79 static error_t 88 static error_t
...@@ -84,8 +93,12 @@ parser (int key, char *arg, struct argp_state *state) ...@@ -84,8 +93,12 @@ parser (int key, char *arg, struct argp_state *state)
84 switch (key) 93 switch (key)
85 { 94 {
86 case ARGP_KEY_INIT: 95 case ARGP_KEY_INIT:
87 opts->mailer = "sendmail:"; 96 if (!opts->tickets)
88 opts->debug_level = MU_DEBUG_ERROR; 97 opts->tickets = mu_tilde_expansion ("~/.tickets", "/", NULL);
98 if (!opts->mailer)
99 opts->mailer = strdup ("sendmail:");
100 if(!opts->debug_level)
101 opts->debug_level = MU_DEBUG_ERROR;
89 break; 102 break;
90 case 'n': 103 case 'n':
91 opts->no_actions = SV_FLAG_NO_ACTIONS; 104 opts->no_actions = SV_FLAG_NO_ACTIONS;
...@@ -97,12 +110,21 @@ parser (int key, char *arg, struct argp_state *state) ...@@ -97,12 +110,21 @@ parser (int key, char *arg, struct argp_state *state)
97 opts->compile_only = 1; 110 opts->compile_only = 1;
98 break; 111 break;
99 case 'f': 112 case 'f':
100 opts->mbox = arg; 113 if(opts->mbox)
114 argp_error (state, "only one MBOX can be specified");
115 opts->mbox = strdup(arg);
101 break; 116 break;
102 case 't': 117 case 't':
103 opts->tickets = arg; 118 free (opts->tickets);
119 opts->tickets = mu_tilde_expansion (arg, "/", NULL);
120 break;
121 case 'm':
122 free (opts->mailer);
123 opts->mailer = strdup(arg);
104 break; 124 break;
105 case 'd': 125 case 'd':
126 if(!arg)
127 arg = D_DEFAULT;
106 for (; *arg; arg++) 128 for (; *arg; arg++)
107 { 129 {
108 switch (*arg) 130 switch (*arg)
...@@ -132,12 +154,12 @@ parser (int key, char *arg, struct argp_state *state) ...@@ -132,12 +154,12 @@ parser (int key, char *arg, struct argp_state *state)
132 case ARGP_KEY_ARG: 154 case ARGP_KEY_ARG:
133 if (opts->script) 155 if (opts->script)
134 argp_error (state, "only one SCRIPT can be specified"); 156 argp_error (state, "only one SCRIPT can be specified");
135 opts->script = arg; 157 opts->script = mu_tilde_expansion (arg, "/", NULL);
136 break; 158 break;
137 159
138 case ARGP_KEY_NO_ARGS: 160 case ARGP_KEY_NO_ARGS:
139 argp_error (state, "SCRIPT must be specified"); 161 if (opts->final && !opts->script)
140 break; 162 argp_error (state, "SCRIPT must be specified");
141 163
142 default: 164 default:
143 return ARGP_ERR_UNKNOWN; 165 return ARGP_ERR_UNKNOWN;
...@@ -197,6 +219,72 @@ debug_print (mu_debug_t debug, size_t level, const char *fmt, va_list ap) ...@@ -197,6 +219,72 @@ debug_print (mu_debug_t debug, size_t level, const char *fmt, va_list ap)
197 return 0; 219 return 0;
198 } 220 }
199 221
222 static int
223 dot_parse (int argc, char *argv[], struct options *opts)
224 {
225 int err = 0;
226 char *rcfile = mu_tilde_expansion ("~/.sieverc", "/", NULL);
227 struct stat s;
228 char *cmd = 0;
229 int fd = -1;
230 int ac = 0;
231 char **av = 0;
232
233 if (!rcfile)
234 return ENOMEM;
235
236 /* Chomp argv[0] down to the last path component. */
237 {
238 char* n = argv[0] + strlen(argv[0]);
239 while(n > argv[0] && *n != '/')
240 n--;
241 if(*n == '/')
242 n++;
243 argv[0] = n;
244 }
245
246 fd = open (rcfile, O_RDONLY, 0);
247
248 free (rcfile);
249 rcfile = 0;
250
251 if (fd != -1)
252 {
253 if ((err = fstat (fd, &s)) == -1)
254 return errno;
255
256 if ((cmd = malloc (s.st_size + 1 + strlen (argv[0]) + 1)) == NULL)
257 return ENOMEM;
258
259 strcpy (cmd, argv[0]);
260 strcat (cmd, " ");
261 err = read (fd, &cmd[strlen (argv[0]) + 1], s.st_size);
262
263 close (fd);
264
265 if (err == -1)
266 {
267 free (cmd);
268 return errno;
269 }
270
271 cmd[strlen (argv[0]) + 1 + err] = '\0';
272
273 argcv_get (cmd, "", "#", &ac, &av);
274
275 argp_parse (&argp, ac, av, ARGP_IN_ORDER, NULL, opts);
276
277 argcv_free (ac, av);
278
279 free (cmd);
280 }
281
282 opts->final = 1;
283
284 argp_parse (&argp, argc, argv, ARGP_IN_ORDER, NULL, opts);
285
286 return 0;
287 }
200 int 288 int
201 main (int argc, char *argv[]) 289 main (int argc, char *argv[])
202 { 290 {
...@@ -215,7 +303,12 @@ main (int argc, char *argv[]) ...@@ -215,7 +303,12 @@ main (int argc, char *argv[])
215 303
216 int rc = 0; 304 int rc = 0;
217 305
218 argp_parse (&argp, argc, argv, ARGP_IN_ORDER, NULL, &opts); 306 rc = dot_parse(argc, argv, &opts);
307
308 if(rc) {
309 fprintf (stderr, "arg parsing failed: %s\n", sv_strerror (rc));
310 return 1;
311 }
219 312
220 mutil_register_all_mbox_formats (); 313 mutil_register_all_mbox_formats ();
221 314
......