Commit ad3cc340 ad3cc340266af4e1d768e6d3e59594f78cd6f940 by Sergey Poznyakoff

Complement f160ca75

* include/mailutils/wordsplit.h (MU_WRDSX_WORD)
(MU_WRDSX_QUOTE): New constants.
(mu_wordsplit_getwords): Rename to mu_wordsplit_get_words.
* libmailutils/string/wordsplit.c (mu_wordsplit_getwords): Rename
to mu_wordsplit_get_words.

* libmailutils/base/userprivs.c (mu_switch_to_privs): Fix
memory overrun when retrieving the current pointer.

* examples/header.c (main): Use mu_wordsplit_get_words
* imap4d/preauth.c (preauth_getvar): Rewrite according to
the new API.
* libmailutils/imapio/create.c (mu_imapio_create): Use MU_WRDSX_
constants to address ws_escape.
* libmailutils/imapio/qstring.c: Likewise.
* libmailutils/mailbox/mbx_default.c: Minor fix.
* libmailutils/server/acl.c (acl_getvar): Rewrite according to
the new API.
* libmailutils/tests/wsp.c: Minor fix.
* libmailutils/url/create.c (_mu_url_create_internal): Bugfix: alloc
url->path.
* libmu_sieve/extensions/list.c (retrieve_next_header): Use
mu_wordsplit_get_words
* libproto/mailer/prog.c (prog_getvar): Rewrite according to
the new API.
* libproto/mailer/smtp_gsasl.c (get_implemented_mechs): Remove
unneeded assignment to ws.ws_wordv.
* mh/folder.c: Use mu_wordsplit_get_words.
* mh/mhn.c: Likewise.
* movemail/movemail.c (movemail_getvar): Rewrite according to
the new API.
1 parent f160ca75
...@@ -558,7 +558,7 @@ main (int argc, char **argv) ...@@ -558,7 +558,7 @@ main (int argc, char **argv)
558 int c; 558 int c;
559 char buf[512]; 559 char buf[512];
560 char **prevv = NULL; 560 char **prevv = NULL;
561 int prevc = 0; 561 size_t prevc = 0;
562 562
563 interactive = isatty (0); 563 interactive = isatty (0);
564 while ((c = getopt (argc, argv, "f:h")) != EOF) 564 while ((c = getopt (argc, argv, "f:h")) != EOF)
...@@ -615,10 +615,7 @@ main (int argc, char **argv) ...@@ -615,10 +615,7 @@ main (int argc, char **argv)
615 { 615 {
616 docmd (ws.ws_wordc, ws.ws_wordv); 616 docmd (ws.ws_wordc, ws.ws_wordv);
617 mu_argcv_free (prevc, prevv); 617 mu_argcv_free (prevc, prevv);
618 prevc = ws.ws_wordc; 618 mu_wordsplit_get_words (&ws, &prevc, &prevv);
619 prevv = ws.ws_wordv;
620 ws.ws_wordc = 0;
621 ws.ws_wordv = NULL;
622 } 619 }
623 mu_wordsplit_free (&ws); 620 mu_wordsplit_free (&ws);
624 } 621 }
......
...@@ -395,26 +395,41 @@ struct preauth_closure ...@@ -395,26 +395,41 @@ struct preauth_closure
395 struct sockaddr_in *s_clt, *s_srv; 395 struct sockaddr_in *s_clt, *s_srv;
396 }; 396 };
397 397
398 static const char * 398 static int
399 preauth_getvar (const char *name, size_t nlen, void *data) 399 preauth_getvar (char **ret, const char *name, size_t nlen, void *data)
400 { 400 {
401 struct preauth_closure *clos = data; 401 struct preauth_closure *clos = data;
402 const char *s = NULL;
402 403
404 if (SEQ ("client_address", name, nlen))
405 {
403 if (clos->s_clt && clos->s_clt->sin_family == AF_INET) 406 if (clos->s_clt && clos->s_clt->sin_family == AF_INET)
407 s = inet_ntoa (clos->s_clt->sin_addr);
408 }
409 else if (SEQ ("client_port", name, nlen))
404 { 410 {
405 if (SEQ ("client_address", name, nlen)) 411 if (clos->s_clt && clos->s_clt->sin_family == AF_INET)
406 return inet_ntoa (clos->s_clt->sin_addr); 412 s = mu_umaxtostr (0, ntohs (clos->s_clt->sin_port));
407 if (SEQ ("client_prot", name, nlen))
408 return mu_umaxtostr (0, ntohs (clos->s_clt->sin_port));
409 } 413 }
414 else if (SEQ ("server_address", name, nlen))
415 {
410 if (clos->s_srv && clos->s_srv->sin_family == AF_INET) 416 if (clos->s_srv && clos->s_srv->sin_family == AF_INET)
417 s = inet_ntoa (clos->s_srv->sin_addr);
418 }
419 else if (SEQ ("server_port", name, nlen))
411 { 420 {
412 if (SEQ ("server_address", name, nlen)) 421 if (clos->s_srv && clos->s_srv->sin_family == AF_INET)
413 return inet_ntoa (clos->s_srv->sin_addr); 422 s = mu_umaxtostr (0, ntohs (clos->s_srv->sin_port));
414 if (SEQ ("server_port", name, nlen))
415 return mu_umaxtostr (0, ntohs (clos->s_srv->sin_port));
416 } 423 }
417 return NULL; 424
425 if (s)
426 {
427 *ret = strdup (s);
428 if (!*ret)
429 return MU_WRDSE_NOSPACE;
430 return MU_WRDSE_OK;
431 }
432 return MU_WRDSE_UNDEF;
418 } 433 }
419 434
420 /* External (program) preauth */ 435 /* External (program) preauth */
......
...@@ -70,9 +70,9 @@ struct mu_wordsplit ...@@ -70,9 +70,9 @@ struct mu_wordsplit
70 int (*ws_getvar) (char **ret, const char *var, size_t len, void *clos); 70 int (*ws_getvar) (char **ret, const char *var, size_t len, void *clos);
71 /* [Input] (MU_WRDSF_GETVAR, !MU_WRDSF_NOVAR) Looks up 71 /* [Input] (MU_WRDSF_GETVAR, !MU_WRDSF_NOVAR) Looks up
72 the name VAR (LEN bytes long) in the table of 72 the name VAR (LEN bytes long) in the table of
73 variables and if found returns in memory 73 variables and, if found returns the value of
74 location pointed to by RET the value of that 74 that variable in memory location pointed to
75 variable. Returns WRDSE_OK (0) on success, 75 by RET . Returns WRDSE_OK (0) on success,
76 and an error code (see WRDSE_* defines below) 76 and an error code (see WRDSE_* defines below)
77 on error. User-specific errors can be returned 77 on error. User-specific errors can be returned
78 by storing the error diagnostic string in RET 78 by storing the error diagnostic string in RET
...@@ -213,6 +213,10 @@ struct mu_wordsplit ...@@ -213,6 +213,10 @@ struct mu_wordsplit
213 #define MU_WRDSO_OESC MU_WRDSO_OESC_WORD 213 #define MU_WRDSO_OESC MU_WRDSO_OESC_WORD
214 #define MU_WRDSO_XESC MU_WRDSO_XESC_WORD 214 #define MU_WRDSO_XESC MU_WRDSO_XESC_WORD
215 215
216 /* Indices into ws_escape */
217 #define MU_WRDSX_WORD 0
218 #define MU_WRDSX_QUOTE 1
219
216 /* Set escape option F in WS for words (Q==0) or quoted strings (Q==1) */ 220 /* Set escape option F in WS for words (Q==0) or quoted strings (Q==1) */
217 #define MU_WRDSO_ESC_SET(ws,q,f) ((ws)->ws_options |= ((f) << 4*(q))) 221 #define MU_WRDSO_ESC_SET(ws,q,f) ((ws)->ws_options |= ((f) << 4*(q)))
218 /* Test WS for escape option F for words (Q==0) or quoted strings (Q==1) */ 222 /* Test WS for escape option F for words (Q==0) or quoted strings (Q==1) */
...@@ -235,7 +239,8 @@ int mu_wordsplit_len (const char *s, size_t len, mu_wordsplit_t *ws, int flags); ...@@ -235,7 +239,8 @@ int mu_wordsplit_len (const char *s, size_t len, mu_wordsplit_t *ws, int flags);
235 void mu_wordsplit_free (mu_wordsplit_t *ws); 239 void mu_wordsplit_free (mu_wordsplit_t *ws);
236 void mu_wordsplit_free_words (mu_wordsplit_t *ws); 240 void mu_wordsplit_free_words (mu_wordsplit_t *ws);
237 void mu_wordsplit_free_envbuf (mu_wordsplit_t *ws); 241 void mu_wordsplit_free_envbuf (mu_wordsplit_t *ws);
238 void mu_wordsplit_getwords (mu_wordsplit_t *ws, int *wordc, char ***wordv); 242
243 int mu_wordsplit_get_words (mu_wordsplit_t *ws, size_t *wordc, char ***wordv);
239 244
240 int mu_wordsplit_c_unquote_char (int c); 245 int mu_wordsplit_c_unquote_char (int c);
241 int mu_wordsplit_c_quote_char (int c); 246 int mu_wordsplit_c_quote_char (int c);
......
...@@ -180,7 +180,7 @@ mu_switch_to_privs (uid_t uid, gid_t gid, mu_list_t retain_groups) ...@@ -180,7 +180,7 @@ mu_switch_to_privs (uid_t uid, gid_t gid, mu_list_t retain_groups)
180 /* Create a list of supplementary groups */ 180 /* Create a list of supplementary groups */
181 mu_list_count (retain_groups, &size); 181 mu_list_count (retain_groups, &size);
182 size++; 182 size++;
183 emptygidset = malloc (size * sizeof emptygidset[0]); 183 emptygidset = calloc (size, sizeof emptygidset[0]);
184 if (!emptygidset) 184 if (!emptygidset)
185 return ENOMEM; 185 return ENOMEM;
186 emptygidset[0] = gid ? gid : getegid (); 186 emptygidset[0] = gid ? gid : getegid ();
...@@ -189,8 +189,11 @@ mu_switch_to_privs (uid_t uid, gid_t gid, mu_list_t retain_groups) ...@@ -189,8 +189,11 @@ mu_switch_to_privs (uid_t uid, gid_t gid, mu_list_t retain_groups)
189 { 189 {
190 for (mu_iterator_first (itr); 190 for (mu_iterator_first (itr);
191 !mu_iterator_is_done (itr); mu_iterator_next (itr)) 191 !mu_iterator_is_done (itr); mu_iterator_next (itr))
192 mu_iterator_current (itr, 192 {
193 (void **)(emptygidset + j++)); 193 void *p;
194 mu_iterator_current (itr, &p);
195 emptygidset[j++] = (gid_t) (intptr_t) p;
196 }
194 mu_iterator_destroy (&itr); 197 mu_iterator_destroy (&itr);
195 } 198 }
196 rc = mu_set_user_privileges (uid, emptygidset, j); 199 rc = mu_set_user_privileges (uid, emptygidset, j);
......
...@@ -29,8 +29,8 @@ mu_imapio_create (mu_imapio_t *iop, mu_stream_t str, int server) ...@@ -29,8 +29,8 @@ mu_imapio_create (mu_imapio_t *iop, mu_stream_t str, int server)
29 io->_imap_stream = str; 29 io->_imap_stream = str;
30 mu_stream_ref (str); 30 mu_stream_ref (str);
31 io->_imap_ws.ws_delim = " \t()[]"; 31 io->_imap_ws.ws_delim = " \t()[]";
32 io->_imap_ws.ws_escape[0] = NULL; 32 io->_imap_ws.ws_escape[MU_WRDSX_WORD] = NULL;
33 io->_imap_ws.ws_escape[1] = "\\\\\"\""; 33 io->_imap_ws.ws_escape[MU_WRDSX_QUOTE] = "\\\\\"\"";
34 MU_WRDSO_ESC_SET (&io->_imap_ws, 0, MU_WRDSO_BSKEEP); 34 MU_WRDSO_ESC_SET (&io->_imap_ws, 0, MU_WRDSO_BSKEEP);
35 MU_WRDSO_ESC_SET (&io->_imap_ws, 1, MU_WRDSO_BSKEEP); 35 MU_WRDSO_ESC_SET (&io->_imap_ws, 1, MU_WRDSO_BSKEEP);
36 io->_imap_ws_flags = MU_WRDSF_DELIM | 36 io->_imap_ws_flags = MU_WRDSF_DELIM |
......
...@@ -66,7 +66,8 @@ mu_imapio_send_qstring_unfold (struct _mu_imapio *io, const char *buffer, ...@@ -66,7 +66,8 @@ mu_imapio_send_qstring_unfold (struct _mu_imapio *io, const char *buffer,
66 else 66 else
67 mu_imapio_send_literal_string (io, buffer); 67 mu_imapio_send_literal_string (io, buffer);
68 } 68 }
69 else if (buffer[len = strcspn (buffer, io->_imap_ws.ws_escape)]) 69 else if (io->_imap_ws.ws_escape[MU_WRDSX_QUOTE]
70 && buffer[len = strcspn (buffer, io->_imap_ws.ws_escape[MU_WRDSX_QUOTE])])
70 { 71 {
71 int rc; 72 int rc;
72 73
...@@ -82,7 +83,7 @@ mu_imapio_send_qstring_unfold (struct _mu_imapio *io, const char *buffer, ...@@ -82,7 +83,7 @@ mu_imapio_send_qstring_unfold (struct _mu_imapio *io, const char *buffer,
82 mu_stream_write (io->_imap_stream, "\\", 1, NULL); 83 mu_stream_write (io->_imap_stream, "\\", 1, NULL);
83 mu_stream_write (io->_imap_stream, buffer, 1, NULL); 84 mu_stream_write (io->_imap_stream, buffer, 1, NULL);
84 buffer++; 85 buffer++;
85 len = strcspn (buffer, io->_imap_ws.ws_escape); 86 len = strcspn (buffer, io->_imap_ws.ws_escape[MU_WRDSX_QUOTE]);
86 } 87 }
87 else 88 else
88 break; 89 break;
......
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
39 #include <mailutils/folder.h> 39 #include <mailutils/folder.h>
40 #include <mailutils/auth.h> 40 #include <mailutils/auth.h>
41 #include <mailutils/wordsplit.h> 41 #include <mailutils/wordsplit.h>
42 #include <mailutils/io.h>
42 43
43 #include <mailutils/sys/mailbox.h> 44 #include <mailutils/sys/mailbox.h>
44 45
......
...@@ -71,7 +71,6 @@ struct run_closure ...@@ -71,7 +71,6 @@ struct run_closure
71 char **env; 71 char **env;
72 char ipstr[40]; 72 char ipstr[40];
73 char *addrstr; 73 char *addrstr;
74 char *numbuf;
75 mu_acl_result_t *result; 74 mu_acl_result_t *result;
76 }; 75 };
77 76
...@@ -305,57 +304,54 @@ _acl_match (struct _mu_acl_entry *ent, struct run_closure *rp) ...@@ -305,57 +304,54 @@ _acl_match (struct _mu_acl_entry *ent, struct run_closure *rp)
305 #define SEQ(s, n, l) \ 304 #define SEQ(s, n, l) \
306 (((l) == (sizeof(s) - 1)) && memcmp (s, n, l) == 0) 305 (((l) == (sizeof(s) - 1)) && memcmp (s, n, l) == 0)
307 306
308 static const char * 307 static int
309 acl_getvar (const char *name, size_t nlen, void *data) 308 acl_getvar (char **ret, const char *name, size_t nlen, void *data)
310 { 309 {
311 struct run_closure *rp = data; 310 struct run_closure *rp = data;
312 311
313 if (SEQ ("family", name, nlen)) 312 if (SEQ ("aclno", name, nlen))
313 {
314 if (mu_asprintf (ret, "%u", rp->idx))
315 return MU_WRDSE_NOSPACE;
316 return MU_WRDSE_OK;
317 }
318 else if (SEQ ("address", name, nlen))
314 { 319 {
320 if (mu_cidr_format (&rp->addr, MU_CIDR_FMT_ADDRONLY, ret))
321 return MU_WRDSE_NOSPACE;
322 return MU_WRDSE_OK;
323 }
324 else if (SEQ ("family", name, nlen))
325 {
326 char *s;
327
315 switch (rp->addr.family) 328 switch (rp->addr.family)
316 { 329 {
317 case AF_INET: 330 case AF_INET:
318 return "AF_INET"; 331 s = "AF_INET";
332 break;
319 333
320 #ifdef MAILUTILS_IPV6 334 #ifdef MAILUTILS_IPV6
321 case AF_INET6: 335 case AF_INET6:
322 return "AF_INET6"; 336 s = "AF_INET6";
337 break;
323 #endif 338 #endif
324 339
325 case AF_UNIX: 340 case AF_UNIX:
326 return "AF_UNIX"; 341 s = "AF_UNIX";
342 break;
327 343
328 default: 344 default:
329 return NULL; 345 return MU_WRDSE_UNDEF;
330 }
331 } 346 }
332 347
333 if (SEQ ("aclno", name, nlen)) 348 *ret = strdup (s);
334 { 349 if (!*ret)
335 if (!rp->numbuf && mu_asprintf (&rp->numbuf, "%u", rp->idx)) 350 return MU_WRDSE_NOSPACE;
336 return NULL; 351 return MU_WRDSE_OK;
337 return rp->numbuf;
338 }
339
340 if (SEQ ("address", name, nlen))
341 {
342 if (!rp->addrstr)
343 mu_cidr_format (&rp->addr, MU_CIDR_FMT_ADDRONLY, &rp->addrstr);
344 return rp->addrstr;
345 } 352 }
346 353
347 #if 0 354 return MU_WRDSE_UNDEF;
348 /* FIXME?: */
349 if (SEQ ("port", name, nlen))
350 {
351 if (!rp->portbuf &&
352 mu_asprintf (&rp->portbuf, "%hu", ntohs (s_in->sin_port)))
353 return NULL;
354 return rp->portbuf;
355 }
356 #endif
357
358 return NULL;
359 } 355 }
360 356
361 static int 357 static int
...@@ -577,9 +573,7 @@ mu_acl_check_sockaddr (mu_acl_t acl, const struct sockaddr *sa, int salen, ...@@ -577,9 +573,7 @@ mu_acl_check_sockaddr (mu_acl_t acl, const struct sockaddr *sa, int salen,
577 r.result = pres; 573 r.result = pres;
578 r.env = acl->envv; 574 r.env = acl->envv;
579 *r.result = mu_acl_result_undefined; 575 *r.result = mu_acl_result_undefined;
580 r.numbuf = NULL;
581 mu_list_foreach (acl->aclist, _run_entry, &r); 576 mu_list_foreach (acl->aclist, _run_entry, &r);
582 free (r.numbuf);
583 free (r.addrstr); 577 free (r.addrstr);
584 return 0; 578 return 0;
585 } 579 }
......
...@@ -2282,16 +2282,21 @@ mu_wordsplit_free (struct mu_wordsplit *ws) ...@@ -2282,16 +2282,21 @@ mu_wordsplit_free (struct mu_wordsplit *ws)
2282 mu_wordsplit_free_envbuf (ws); 2282 mu_wordsplit_free_envbuf (ws);
2283 } 2283 }
2284 2284
2285 void 2285 int
2286 mu_wordsplit_getwords (struct mu_wordsplit *ws, int *wordc, char ***wordv) 2286 mu_wordsplit_get_words (struct mu_wordsplit *ws, size_t *wordc, char ***wordv)
2287 { 2287 {
2288 char **p = realloc (ws->ws_wordv, 2288 char **p = realloc (ws->ws_wordv,
2289 (ws->ws_wordc + 1) * sizeof (ws->ws_wordv[0])); 2289 (ws->ws_wordc + 1) * sizeof (ws->ws_wordv[0]));
2290 *wordv = p ? p : ws->ws_wordv; 2290 if (!p)
2291 return -1;
2292 *wordv = p;
2291 *wordc = ws->ws_wordc; 2293 *wordc = ws->ws_wordc;
2294
2292 ws->ws_wordv = NULL; 2295 ws->ws_wordv = NULL;
2293 ws->ws_wordc = 0; 2296 ws->ws_wordc = 0;
2294 ws->ws_wordn = 0; 2297 ws->ws_wordn = 0;
2298
2299 return 0;
2295 } 2300 }
2296 2301
2297 const char *_mu_wordsplit_errstr[] = { 2302 const char *_mu_wordsplit_errstr[] = {
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
27 #include <mailutils/errno.h> 27 #include <mailutils/errno.h>
28 #include <mailutils/error.h> 28 #include <mailutils/error.h>
29 #include <mailutils/cstr.h> 29 #include <mailutils/cstr.h>
30 #include <mailutils/io.h>
30 31
31 extern char **environ; 32 extern char **environ;
32 33
...@@ -199,13 +200,11 @@ wsp_runcmd (char **ret, const char *str, size_t len, char **argv, void *closure) ...@@ -199,13 +200,11 @@ wsp_runcmd (char **ret, const char *str, size_t len, char **argv, void *closure)
199 memcpy (cmd, str, len); 200 memcpy (cmd, str, len);
200 cmd[len] = 0; 201 cmd[len] = 0;
201 202
202 fp = popen(cmd, "r"); 203 fp = popen (cmd, "r");
203 if (!fp) 204 if (!fp)
204 { 205 {
205 size_t size = 0;
206 ret = NULL; 206 ret = NULL;
207 if (mu_asprintf (ret, &size, "can't run %s: %s", 207 if (mu_asprintf (ret, "can't run %s: %s", cmd, mu_strerror (errno)))
208 cmd, strerror (errno)))
209 return MU_WRDSE_NOSPACE; 208 return MU_WRDSE_NOSPACE;
210 else 209 else
211 return MU_WRDSE_USERERR; 210 return MU_WRDSE_USERERR;
......
...@@ -416,7 +416,12 @@ _mu_url_create_internal (struct mu_url_ctx *ctx, mu_url_t hint) ...@@ -416,7 +416,12 @@ _mu_url_create_internal (struct mu_url_ctx *ctx, mu_url_t hint)
416 ctx->flags &= ~MU_URL_PARSE_HEXCODE; 416 ctx->flags &= ~MU_URL_PARSE_HEXCODE;
417 if (mu_wordsplit (ctx->input + 1, &ws, MU_WRDSF_DEFFLAGS)) 417 if (mu_wordsplit (ctx->input + 1, &ws, MU_WRDSF_DEFFLAGS))
418 return errno; 418 return errno;
419 url->path = ws.ws_wordv[0]; 419 url->path = strdup (ws.ws_wordv[0]);
420 if (!url->path)
421 {
422 mu_wordsplit_free (&ws);
423 return ENOMEM;
424 }
420 url->flags |= MU_URL_PATH; 425 url->flags |= MU_URL_PATH;
421 426
422 url->qargc = ws.ws_wordc - 1; 427 url->qargc = ws.ws_wordc - 1;
......
...@@ -81,12 +81,9 @@ retrieve_next_header (struct header_closure *hc, char *name, char **pval) ...@@ -81,12 +81,9 @@ retrieve_next_header (struct header_closure *hc, char *name, char **pval)
81 mu_wordsplit_free (&ws); 81 mu_wordsplit_free (&ws);
82 return 1; 82 return 1;
83 } 83 }
84 hc->valv = ws.ws_wordv; 84 mu_wordsplit_get_words (&ws, &hc->valc, &hc->valv);
85 hc->valc = ws.ws_wordc;
86 hc->vali = 0;
87 ws.ws_wordv = NULL;
88 ws.ws_wordc = 0;
89 mu_wordsplit_free (&ws); 85 mu_wordsplit_free (&ws);
86 hc->vali = 0;
90 *pval = hc->valv[hc->vali++]; 87 *pval = hc->valv[hc->vali++];
91 return 0; 88 return 0;
92 } 89 }
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
33 #include <mailutils/observer.h> 33 #include <mailutils/observer.h>
34 #include <mailutils/progmailer.h> 34 #include <mailutils/progmailer.h>
35 #include <mailutils/wordsplit.h> 35 #include <mailutils/wordsplit.h>
36 #include <mailutils/io.h>
36 37
37 #include <mailutils/sys/url.h> 38 #include <mailutils/sys/url.h>
38 #include <mailutils/sys/mailer.h> 39 #include <mailutils/sys/mailer.h>
...@@ -143,18 +144,30 @@ struct prog_exp ...@@ -143,18 +144,30 @@ struct prog_exp
143 { 144 {
144 mu_message_t msg; 145 mu_message_t msg;
145 mu_address_t sender_addr; 146 mu_address_t sender_addr;
146 char *sender_str;
147 mu_address_t rcpt_addr; 147 mu_address_t rcpt_addr;
148 char *rcpt_str;
149 }; 148 };
150 149
151 static const char * 150 static int
152 _expand_sender (struct prog_exp *pe) 151 _expand_err (char **ret, const char *prefix, int status)
153 { 152 {
154 if (!pe->sender_str && 153 if (mu_asprintf (ret, "%s: %s", prefix, mu_strerror (status)))
155 mu_address_aget_email (pe->sender_addr, 1, &pe->sender_str)) 154 return MU_WRDSE_NOSPACE;
156 return NULL; 155 return MU_WRDSE_USERERR;
157 return pe->sender_str; 156 }
157
158 static int
159 _expand_sender (struct prog_exp *pe, char **ret)
160 {
161 int status = mu_address_aget_email (pe->sender_addr, 1, ret);
162 switch (status)
163 {
164 case 0:
165 return MU_WRDSE_OK;
166
167 case ENOMEM:
168 return MU_WRDSE_NOSPACE;
169 }
170 return _expand_err (ret, "getting email", status);
158 } 171 }
159 172
160 static int 173 static int
...@@ -203,13 +216,10 @@ message_read_rcpt (mu_message_t msg, mu_address_t *paddr) ...@@ -203,13 +216,10 @@ message_read_rcpt (mu_message_t msg, mu_address_t *paddr)
203 return 0; 216 return 0;
204 } 217 }
205 218
206 static const char * 219 static int
207 _expand_rcpt (struct prog_exp *pe) 220 _expand_rcpt (struct prog_exp *pe, char **ret)
208 { 221 {
209 int status; 222 int status;
210
211 if (!pe->rcpt_str)
212 {
213 size_t i, count = 0; 223 size_t i, count = 0;
214 size_t len = 0; 224 size_t len = 0;
215 char *str; 225 char *str;
...@@ -223,7 +233,7 @@ _expand_rcpt (struct prog_exp *pe) ...@@ -223,7 +233,7 @@ _expand_rcpt (struct prog_exp *pe)
223 if (status) 233 if (status)
224 { 234 {
225 mu_address_destroy (&tmp_addr); 235 mu_address_destroy (&tmp_addr);
226 return NULL; 236 return _expand_err (ret, "reading recipients", status);
227 } 237 }
228 addr = tmp_addr; 238 addr = tmp_addr;
229 } 239 }
...@@ -237,7 +247,7 @@ _expand_rcpt (struct prog_exp *pe) ...@@ -237,7 +247,7 @@ _expand_rcpt (struct prog_exp *pe)
237 if ((status = mu_address_sget_email (addr, i, &email)) != 0) 247 if ((status = mu_address_sget_email (addr, i, &email)) != 0)
238 { 248 {
239 mu_address_destroy (&tmp_addr); 249 mu_address_destroy (&tmp_addr);
240 return NULL; 250 return _expand_err (ret, "reading email", status);
241 } 251 }
242 len += strlen (email); 252 len += strlen (email);
243 } 253 }
...@@ -246,9 +256,9 @@ _expand_rcpt (struct prog_exp *pe) ...@@ -246,9 +256,9 @@ _expand_rcpt (struct prog_exp *pe)
246 if (!str) 256 if (!str)
247 { 257 {
248 mu_address_destroy (&tmp_addr); 258 mu_address_destroy (&tmp_addr);
249 return NULL; 259 return MU_WRDSE_NOSPACE;
250 } 260 }
251 pe->rcpt_str = str; 261 *ret = str;
252 262
253 for (i = 1; i <= count; i++) 263 for (i = 1; i <= count; i++)
254 { 264 {
...@@ -262,23 +272,23 @@ _expand_rcpt (struct prog_exp *pe) ...@@ -262,23 +272,23 @@ _expand_rcpt (struct prog_exp *pe)
262 } 272 }
263 *str = 0; 273 *str = 0;
264 mu_address_destroy (&tmp_addr); 274 mu_address_destroy (&tmp_addr);
265 } 275
266 return pe->rcpt_str; 276 return MU_WRDSE_OK;
267 } 277 }
268 278
269 #define SEQ(s, n, l) \ 279 #define SEQ(s, n, l) \
270 (((l) == (sizeof(s) - 1)) && memcmp (s, n, l) == 0) 280 (((l) == (sizeof(s) - 1)) && memcmp (s, n, l) == 0)
271 281
272 static const char * 282 static int
273 prog_getvar (const char *name, size_t nlen, void *data) 283 prog_getvar (char **ret, const char *name, size_t nlen, void *data)
274 { 284 {
275 struct prog_exp *pe = data; 285 struct prog_exp *pe = data;
276 286
277 if (SEQ ("sender", name, nlen)) 287 if (SEQ ("sender", name, nlen))
278 return _expand_sender (pe); 288 return _expand_sender (pe, ret);
279 if (SEQ ("rcpt", name, nlen)) 289 if (SEQ ("rcpt", name, nlen))
280 return _expand_rcpt (pe); 290 return _expand_rcpt (pe, ret);
281 return NULL; 291 return MU_WRDSE_UNDEF;
282 } 292 }
283 293
284 static int 294 static int
...@@ -298,7 +308,6 @@ url_to_argv (mu_url_t url, mu_message_t msg, ...@@ -298,7 +308,6 @@ url_to_argv (mu_url_t url, mu_message_t msg,
298 pe.msg = msg; 308 pe.msg = msg;
299 pe.rcpt_addr = to; 309 pe.rcpt_addr = to;
300 pe.sender_addr = from; 310 pe.sender_addr = from;
301 pe.sender_str = pe.rcpt_str = NULL;
302 311
303 ws.ws_getvar = prog_getvar; 312 ws.ws_getvar = prog_getvar;
304 ws.ws_closure = &pe; 313 ws.ws_closure = &pe;
...@@ -341,8 +350,6 @@ url_to_argv (mu_url_t url, mu_message_t msg, ...@@ -341,8 +350,6 @@ url_to_argv (mu_url_t url, mu_message_t msg,
341 } 350 }
342 argv[i+1] = NULL; 351 argv[i+1] = NULL;
343 mu_wordsplit_free (&ws); 352 mu_wordsplit_free (&ws);
344 free (pe.sender_str);
345 free (pe.rcpt_str);
346 353
347 *pargc = argc; 354 *pargc = argc;
348 *pargv = argv; 355 *pargv = argv;
......
...@@ -69,7 +69,6 @@ get_implemented_mechs (Gsasl *ctx, mu_list_t *plist) ...@@ -69,7 +69,6 @@ get_implemented_mechs (Gsasl *ctx, mu_list_t *plist)
69 mu_list_append (supp, ws.ws_wordv[i]); 69 mu_list_append (supp, ws.ws_wordv[i]);
70 } 70 }
71 ws.ws_wordc = 0; 71 ws.ws_wordc = 0;
72 ws.ws_wordv = NULL;
73 mu_wordsplit_free (&ws); 72 mu_wordsplit_free (&ws);
74 } 73 }
75 free (listmech); 74 free (listmech);
......
...@@ -518,7 +518,7 @@ action_list () ...@@ -518,7 +518,7 @@ action_list ()
518 /* Push & pop */ 518 /* Push & pop */
519 519
520 static void 520 static void
521 get_stack (int *pc, char ***pv) 521 get_stack (size_t *pc, char ***pv)
522 { 522 {
523 struct mu_wordsplit ws; 523 struct mu_wordsplit ws;
524 const char *stack = mh_global_context_get ("Folder-Stack", NULL); 524 const char *stack = mh_global_context_get ("Folder-Stack", NULL);
...@@ -535,10 +535,7 @@ get_stack (int *pc, char ***pv) ...@@ -535,10 +535,7 @@ get_stack (int *pc, char ***pv)
535 } 535 }
536 else 536 else
537 { 537 {
538 *pc = ws.ws_wordc; 538 mu_wordsplit_get_words (&ws, pc, pv);
539 *pv = ws.ws_wordv;
540 ws.ws_wordc = 0;
541 ws.ws_wordv = NULL;
542 mu_wordsplit_free (&ws); 539 mu_wordsplit_free (&ws);
543 } 540 }
544 } 541 }
...@@ -559,9 +556,9 @@ set_stack (int c, char **v) ...@@ -559,9 +556,9 @@ set_stack (int c, char **v)
559 } 556 }
560 557
561 static void 558 static void
562 push_val (int *pc, char ***pv, const char *val) 559 push_val (size_t *pc, char ***pv, const char *val)
563 { 560 {
564 int c = *pc; 561 size_t c = *pc;
565 char **v = *pv; 562 char **v = *pv;
566 563
567 c++; 564 c++;
...@@ -581,10 +578,10 @@ push_val (int *pc, char ***pv, const char *val) ...@@ -581,10 +578,10 @@ push_val (int *pc, char ***pv, const char *val)
581 } 578 }
582 579
583 static char * 580 static char *
584 pop_val (int *pc, char ***pv) 581 pop_val (size_t *pc, char ***pv)
585 { 582 {
586 char *val; 583 char *val;
587 int c; 584 size_t c;
588 char **v; 585 char **v;
589 586
590 if (*pc == 0) 587 if (*pc == 0)
...@@ -603,7 +600,7 @@ pop_val (int *pc, char ***pv) ...@@ -603,7 +600,7 @@ pop_val (int *pc, char ***pv)
603 static int 600 static int
604 action_push () 601 action_push ()
605 { 602 {
606 int c; 603 size_t c;
607 char **v; 604 char **v;
608 605
609 get_stack (&c, &v); 606 get_stack (&c, &v);
...@@ -628,7 +625,7 @@ action_push () ...@@ -628,7 +625,7 @@ action_push ()
628 static int 625 static int
629 action_pop () 626 action_pop ()
630 { 627 {
631 int c; 628 size_t c;
632 char **v; 629 char **v;
633 630
634 get_stack (&c, &v); 631 get_stack (&c, &v);
......
...@@ -199,7 +199,7 @@ split_content (const char *content, char **type, char **subtype) ...@@ -199,7 +199,7 @@ split_content (const char *content, char **type, char **subtype)
199 } 199 }
200 200
201 static void 201 static void
202 split_args (const char *argstr, size_t len, int *pargc, char ***pargv) 202 split_args (const char *argstr, size_t len, size_t *pargc, char ***pargv)
203 { 203 {
204 struct mu_wordsplit ws; 204 struct mu_wordsplit ws;
205 205
...@@ -215,10 +215,7 @@ split_args (const char *argstr, size_t len, int *pargc, char ***pargv) ...@@ -215,10 +215,7 @@ split_args (const char *argstr, size_t len, int *pargc, char ***pargv)
215 } 215 }
216 else 216 else
217 { 217 {
218 *pargc = ws.ws_wordc; 218 mu_wordsplit_get_words (&ws, pargc, pargv);
219 *pargv = ws.ws_wordv;
220 ws.ws_wordc = 0;
221 ws.ws_wordv = NULL;
222 mu_wordsplit_free (&ws); 219 mu_wordsplit_free (&ws);
223 } 220 }
224 } 221 }
...@@ -631,7 +628,7 @@ mhn_compose_command (char *typestr, char *typeargs, int *flags, char *file) ...@@ -631,7 +628,7 @@ mhn_compose_command (char *typestr, char *typeargs, int *flags, char *file)
631 { 628 {
632 const char *p, *str; 629 const char *p, *str;
633 char *type, *subtype, **typeargv = NULL; 630 char *type, *subtype, **typeargv = NULL;
634 int typeargc = 0; 631 size_t typeargc = 0;
635 mu_opool_t pool; 632 mu_opool_t pool;
636 633
637 split_content (typestr, &type, &subtype); 634 split_content (typestr, &type, &subtype);
...@@ -662,7 +659,7 @@ mhn_compose_command (char *typestr, char *typeargs, int *flags, char *file) ...@@ -662,7 +659,7 @@ mhn_compose_command (char *typestr, char *typeargs, int *flags, char *file)
662 /* additional arguments */ 659 /* additional arguments */
663 if (typeargs) 660 if (typeargs)
664 { 661 {
665 int i; 662 size_t i;
666 663
667 if (!typeargv) 664 if (!typeargv)
668 split_args (typeargs, strlen (typeargs), 665 split_args (typeargs, strlen (typeargs),
...@@ -741,7 +738,7 @@ check_type (const char *typeargs, const char *typeval) ...@@ -741,7 +738,7 @@ check_type (const char *typeargs, const char *typeval)
741 738
742 if (typeargs) 739 if (typeargs)
743 { 740 {
744 int i, argc; 741 size_t i, argc;
745 char **argv; 742 char **argv;
746 743
747 split_args (typeargs, strlen (typeargs), &argc, &argv); 744 split_args (typeargs, strlen (typeargs), &argc, &argv);
...@@ -769,7 +766,7 @@ mhn_show_command (mu_message_t msg, msg_part_t part, int *flags, ...@@ -769,7 +766,7 @@ mhn_show_command (mu_message_t msg, msg_part_t part, int *flags,
769 mu_opool_t pool; 766 mu_opool_t pool;
770 mu_header_t hdr; 767 mu_header_t hdr;
771 char *temp_cmd = NULL; 768 char *temp_cmd = NULL;
772 int typeargc = 0; 769 size_t typeargc = 0;
773 char **typeargv = NULL; 770 char **typeargv = NULL;
774 771
775 mu_message_get_header (msg, &hdr); 772 mu_message_get_header (msg, &hdr);
...@@ -1084,7 +1081,7 @@ _message_is_external_body (mu_message_t msg, char ***env) ...@@ -1084,7 +1081,7 @@ _message_is_external_body (mu_message_t msg, char ***env)
1084 rc = subtype && strcmp (subtype, "external-body") == 0; 1081 rc = subtype && strcmp (subtype, "external-body") == 0;
1085 if (rc && env) 1082 if (rc && env)
1086 { 1083 {
1087 int c; 1084 size_t c;
1088 split_args (argstr, strlen (argstr), &c, env); 1085 split_args (argstr, strlen (argstr), &c, env);
1089 } 1086 }
1090 1087
...@@ -2753,7 +2750,7 @@ parse_header_directive (const char *val, char **encoding, char **charset, ...@@ -2753,7 +2750,7 @@ parse_header_directive (const char *val, char **encoding, char **charset,
2753 p = strchr (val, '>'); 2750 p = strchr (val, '>');
2754 if (p) 2751 if (p)
2755 { 2752 {
2756 int i, argc; 2753 size_t i, argc;
2757 char **argv; 2754 char **argv;
2758 2755
2759 *subject = mu_strdup (p + 1); 2756 *subject = mu_strdup (p + 1);
...@@ -2819,7 +2816,7 @@ mhn_header (mu_message_t msg, mu_message_t omsg) ...@@ -2819,7 +2816,7 @@ mhn_header (mu_message_t msg, mu_message_t omsg)
2819 _get_content_encoding (parthdr, &encoding); 2816 _get_content_encoding (parthdr, &encoding);
2820 if (typeargs) 2817 if (typeargs)
2821 { 2818 {
2822 int i, argc; 2819 size_t i, argc;
2823 char **argv; 2820 char **argv;
2824 2821
2825 split_args (typeargs, strlen (typeargs), &argc, &argv); 2822 split_args (typeargs, strlen (typeargs), &argc, &argv);
......
...@@ -757,46 +757,66 @@ struct movemail_getvar_closure ...@@ -757,46 +757,66 @@ struct movemail_getvar_closure
757 #define SEQ(s, n, l) \ 757 #define SEQ(s, n, l) \
758 (((l) == (sizeof(s) - 1)) && memcmp (s, n, l) == 0) 758 (((l) == (sizeof(s) - 1)) && memcmp (s, n, l) == 0)
759 759
760 static const char * 760 static int
761 get_url_part (mu_url_t url, const char *name, size_t nlen) 761 get_url_part (mu_url_t url, const char *name, size_t nlen, char **ret)
762 { 762 {
763 int rc = MU_ERR_NOENT; 763 int rc;
764 const char *s;
765 764
766 if (!url) 765 if (!url)
767 return NULL; 766 return MU_WRDSE_UNDEF;
768 if (SEQ ("user", name, nlen)) 767 if (SEQ ("user", name, nlen))
769 rc = mu_url_sget_user (url, &s); 768 rc = mu_url_aget_user (url, ret);
770 else if (SEQ ("host", name, nlen)) 769 else if (SEQ ("host", name, nlen))
771 rc = mu_url_sget_host (url, &s); 770 rc = mu_url_aget_host (url, ret);
772 else if (SEQ ("port", name, nlen)) 771 else if (SEQ ("port", name, nlen))
773 rc = mu_url_sget_portstr (url, &s); 772 rc = mu_url_aget_portstr (url, ret);
774 else if (SEQ ("path", name, nlen)) 773 else if (SEQ ("path", name, nlen))
775 rc = mu_url_sget_path (url, &s); 774 rc = mu_url_aget_path (url, ret);
775 else
776 return MU_WRDSE_UNDEF;
776 777
777 if (rc) 778 switch (rc)
778 return NULL; 779 {
779 return s; 780 case 0:
781 break;
782
783 case MU_ERR_NOENT:
784 return MU_WRDSE_UNDEF;
785
786 default:
787 if (mu_asprintf (ret, "%s", mu_strerror (rc)))
788 return MU_WRDSE_NOSPACE;
789 return MU_WRDSE_USERERR;
790 }
791
792 return MU_WRDSE_OK;
780 } 793 }
781 794
782 static const char * 795 static int
783 movemail_getvar (const char *name, size_t nlen, void *data) 796 movemail_getvar (char **ret, const char *name, size_t nlen, void *data)
784 { 797 {
785 struct movemail_getvar_closure *pc = data; 798 struct movemail_getvar_closure *pc = data;
786 799 const char *s;
787 if (SEQ ("progname", name, nlen))
788 return mu_program_name;
789 if (SEQ ("source", name, nlen))
790 return pc->source_name;
791 if (SEQ ("dest", name, nlen))
792 return pc->dest_name;
793 800
794 if (nlen > 7 && memcmp ("source_", name, 7) == 0) 801 if (nlen > 7 && memcmp ("source_", name, 7) == 0)
795 return get_url_part (pc->source_url, name + 7, nlen - 7); 802 return get_url_part (pc->source_url, name + 7, nlen - 7, ret);
803
796 if (nlen > 5 && memcmp ("dest_", name, 5) == 0) 804 if (nlen > 5 && memcmp ("dest_", name, 5) == 0)
797 return get_url_part (pc->dest_url, name + 5, nlen - 5); 805 return get_url_part (pc->dest_url, name + 5, nlen - 5, ret);
806
807 if (SEQ ("progname", name, nlen))
808 s = mu_program_name;
809 else if (SEQ ("source", name, nlen))
810 s = pc->source_name;
811 else if (SEQ ("dest", name, nlen))
812 s = pc->dest_name;
813 else
814 return MU_WRDSE_UNDEF;
798 815
799 return NULL; 816 *ret = strdup (s);
817 if (!*ret)
818 return MU_WRDSE_NOSPACE;
819 return MU_WRDSE_OK;
800 } 820 }
801 821
802 static void 822 static void
...@@ -834,7 +854,6 @@ set_program_id (const char *source_name, const char *dest_name) ...@@ -834,7 +854,6 @@ set_program_id (const char *source_name, const char *dest_name)
834 plays wise with its argument. We need a mu_set_diag_prefix 854 plays wise with its argument. We need a mu_set_diag_prefix
835 function. */ 855 function. */
836 mu_program_name = ws.ws_wordv[0]; 856 mu_program_name = ws.ws_wordv[0];
837 ws.ws_wordv[0] = NULL;
838 ws.ws_wordc = 0; 857 ws.ws_wordc = 0;
839 mu_wordsplit_free (&ws); 858 mu_wordsplit_free (&ws);
840 mu_stdstream_strerr_setup (MU_STRERR_STDERR); 859 mu_stdstream_strerr_setup (MU_STRERR_STDERR);
......