Commit c66e1b8d c66e1b8de8fd661a34f03734cbb0a559324c3075 by Sergey Poznyakoff

Remove all uses of vartab, replacing them with wordsplit.

* libmailutils/string/wordsplit.c (mu_wordsplit_init): Call
mu_wordsplit_free_words to reclaim the memory.
(mu_wordsplit_free_words): New function.
(mu_wordsplit_free): Use mu_wordsplit_free_words.

* imap4d/imap4d.c (imap4d_session_setup0): Use wordsplit instead of
vartab.
* imap4d/imap4d.h: Don't include vartab.h.
* imap4d/preauth.c (do_preauth_ident): Use mu_str_stripws instead of
the static trimcrlf, which is removed.
(do_preauth_program): Use wordsplit instead of
vartab and mu_prog_stream_create instead of popen.
* libmailutils/mailbox/mbx_default.c: Include nls.h
Don't include vartab.h
(mu_construct_user_mailbox_url): Use wordsplit instead of
vartab.
* libmailutils/server/acl.c (expand_arg): Use wordsplit instead of
vartab.
* libmu_auth/ldap.c (_mu_ldap_search):L Likewise.
* libmu_auth/radius.c (_expand_query): Likewise.
* libmu_auth/sql.c (mu_sql_expand_query): Likewise.
* libproto/mailer/prog.c (_expand_sender, _expand_rcpt): Rewrite.
(url_to_argv): : Use wordsplit instead of
vartab.

* po/POTFILES.in: Add more files.
1 parent 63fec213
...@@ -308,21 +308,34 @@ imap4d_session_setup0 () ...@@ -308,21 +308,34 @@ imap4d_session_setup0 ()
308 308
309 if (modify_homedir) 309 if (modify_homedir)
310 { 310 {
311 int rc;
312 mu_vartab_t vtab;
313 char *expr = mu_tilde_expansion (modify_homedir, "/", real_homedir); 311 char *expr = mu_tilde_expansion (modify_homedir, "/", real_homedir);
314 312 struct mu_wordsplit ws;
315 mu_vartab_create (&vtab); 313 const char *env[3];
316 mu_vartab_define (vtab, "user", auth_data->name, 0); 314
317 mu_vartab_define (vtab, "home", real_homedir, 0); 315 env[0] = "user";
318 rc = mu_vartab_expand (vtab, expr, &imap4d_homedir); 316 env[1] = auth_data->name;
319 mu_vartab_destroy (&vtab); 317 env[2] = "home";
320 free (expr); 318 env[3] = real_homedir;
321 if (rc) 319 env[4] = NULL;
320
321 ws.ws_env = env;
322 if (mu_wordsplit (expr, &ws,
323 MU_WRDSF_NOSPLIT | MU_WRDSF_NOCMD |
324 MU_WRDSF_ENV | MU_WRDSF_ENV_KV))
325 {
326 mu_error (_("cannot expand line `%s': %s"), expr,
327 mu_wordsplit_strerror (&ws));
328 return 1;
329 }
330 else if (ws.ws_wordc == 0)
331 {
332 mu_error (_("expanding %s yields empty string"), expr);
333 return 1;
334 }
335 imap4d_homedir = strdup (ws.ws_wordv[0]);
336 if (!imap4d_homedir)
322 { 337 {
323 free (real_homedir); 338 mu_error ("%s", mu_strerror (errno));
324 mu_diag_funcall (MU_DIAG_ERROR, "mu_vartab_expand",
325 modify_homedir, rc);
326 return 1; 339 return 1;
327 } 340 }
328 } 341 }
......
...@@ -100,7 +100,6 @@ ...@@ -100,7 +100,6 @@
100 #include <mailutils/server.h> 100 #include <mailutils/server.h>
101 #include <mailutils/wordsplit.h> 101 #include <mailutils/wordsplit.h>
102 #include <mailutils/alloc.h> 102 #include <mailutils/alloc.h>
103 #include <mailutils/vartab.h>
104 #include <mailutils/cctype.h> 103 #include <mailutils/cctype.h>
105 #include <mailutils/cstr.h> 104 #include <mailutils/cstr.h>
106 #include <mailutils/io.h> 105 #include <mailutils/io.h>
......
...@@ -61,22 +61,6 @@ ident_extract_username (char *reply) ...@@ -61,22 +61,6 @@ ident_extract_username (char *reply)
61 } 61 }
62 62
63 static int 63 static int
64 trimcrlf (char *buf)
65 {
66 int len = strlen (buf);
67 if (len == 0)
68 return 0;
69 if (buf[len-1] == '\n')
70 {
71 len--;
72 if (buf[len-1] == '\r')
73 len--;
74 buf[len] = 0;
75 }
76 return len;
77 }
78
79 static int
80 is_des_p (const char *name) 64 is_des_p (const char *name)
81 { 65 {
82 int len = strlen (name); 66 int len = strlen (name);
...@@ -369,8 +353,7 @@ do_preauth_ident (struct sockaddr *clt_sa, struct sockaddr *srv_sa) ...@@ -369,8 +353,7 @@ do_preauth_ident (struct sockaddr *clt_sa, struct sockaddr *srv_sa)
369 return NULL; 353 return NULL;
370 } 354 }
371 mu_diag_output (MU_DIAG_INFO, "Got %s", buf); 355 mu_diag_output (MU_DIAG_INFO, "Got %s", buf);
372 trimcrlf (buf); 356 name = ident_extract_username (mu_str_stripws (buf));
373 name = ident_extract_username (buf);
374 if (!name) 357 if (!name)
375 mu_diag_output (MU_DIAG_INFO, 358 mu_diag_output (MU_DIAG_INFO,
376 _("malformed IDENT response: `%s', from %s:%d"), 359 _("malformed IDENT response: `%s', from %s:%d"),
...@@ -405,48 +388,83 @@ do_preauth_ident (struct sockaddr *clt_sa, struct sockaddr *srv_sa) ...@@ -405,48 +388,83 @@ do_preauth_ident (struct sockaddr *clt_sa, struct sockaddr *srv_sa)
405 } 388 }
406 389
407 390
391 #define SEQ(s, n, l) \
392 (((l) == (sizeof(s) - 1)) && memcmp (s, n, l) == 0)
393
394 struct preauth_closure
395 {
396 struct sockaddr_in *s_clt, *s_srv;
397 };
398
399 static const char *
400 preauth_getvar (const char *name, size_t nlen, void *data)
401 {
402 struct preauth_closure *clos = data;
403
404 if (clos->s_clt && clos->s_clt->sin_family == AF_INET)
405 {
406 if (SEQ ("client_address", name, nlen))
407 return inet_ntoa (clos->s_clt->sin_addr);
408 if (SEQ ("client_prot", name, nlen))
409 return mu_umaxtostr (0, ntohs (clos->s_clt->sin_port));
410 }
411 if (clos->s_srv && clos->s_srv->sin_family == AF_INET)
412 {
413 if (SEQ ("server_address", name, nlen))
414 return inet_ntoa (clos->s_srv->sin_addr);
415 if (SEQ ("server_port", name, nlen))
416 return mu_umaxtostr (0, ntohs (clos->s_srv->sin_port));
417 }
418 return NULL;
419 }
420
408 /* External (program) preauth */ 421 /* External (program) preauth */
409 static char * 422 static char *
410 do_preauth_program (struct sockaddr *pcs, struct sockaddr *sa) 423 do_preauth_program (struct sockaddr *pcs, struct sockaddr *sa)
411 { 424 {
412 int rc; 425 int rc;
413 mu_vartab_t vtab; 426 mu_stream_t str;
414 char *cmd;
415 FILE *fp;
416 char *buf = NULL; 427 char *buf = NULL;
417 size_t size = 0; 428 size_t size = 0, n;
418 429 struct mu_wordsplit ws;
419 mu_vartab_create (&vtab); 430 struct preauth_closure clos;
420 if (pcs && pcs->sa_family == AF_INET) 431
432 clos.s_clt = (struct sockaddr_in *) pcs;
433 clos.s_srv = (struct sockaddr_in *) sa;
434
435 ws.ws_getvar = preauth_getvar;
436 ws.ws_closure = &clos;
437 if (mu_wordsplit (preauth_program, &ws,
438 MU_WRDSF_NOSPLIT | MU_WRDSF_NOCMD |
439 MU_WRDSF_GETVAR | MU_WRDSF_CLOSURE))
421 { 440 {
422 struct sockaddr_in *s_in = (struct sockaddr_in *)pcs; 441 mu_error (_("cannot expand line `%s': %s"), preauth_program,
423 mu_vartab_define (vtab, "client_address", inet_ntoa (s_in->sin_addr), 0); 442 mu_wordsplit_strerror (&ws));
424 mu_vartab_define (vtab, "client_port", 443 return NULL;
425 mu_umaxtostr (0, ntohs (s_in->sin_port)), 0);
426 } 444 }
427 if (sa && sa->sa_family == AF_INET) 445 else if (ws.ws_wordc == 0)
428 { 446 {
429 struct sockaddr_in *s_in = (struct sockaddr_in *) sa; 447 mu_wordsplit_free (&ws);
430 mu_vartab_define (vtab, "server_address", inet_ntoa (s_in->sin_addr), 0); 448 mu_error (_("`%s' expands to an empty line"), preauth_program);
431 mu_vartab_define (vtab, "server_port", 449 return NULL;
432 mu_umaxtostr (0, ntohs (s_in->sin_port)), 0);
433 } 450 }
434 rc = mu_vartab_expand (vtab, preauth_program, &cmd);
435 mu_vartab_destroy (&vtab);
436 if (rc)
437 return NULL;
438 451
439 fp = popen (cmd, "r"); 452 rc = mu_prog_stream_create (&str, ws.ws_wordv[0], MU_STREAM_READ);
440 free (cmd); 453 mu_wordsplit_free (&ws);
441 rc = getline (&buf, &size, fp); 454 if (rc)
442 pclose (fp);
443 if (rc > 0)
444 { 455 {
445 if (trimcrlf (buf) == 0) 456 mu_error (_("cannot open input pipe from %s"), preauth_program);
446 { 457 return NULL;
447 free (buf); 458 }
448 return NULL; 459 rc = mu_stream_getline (str, &buf, &size, &n);
449 } 460 mu_stream_destroy (&str);
461 if (rc)
462 {
463 mu_error (_("read from `%s' failed"), preauth_program);
464 }
465 else
466 {
467 mu_rtrim_cset (buf, "\r\n");
450 return buf; 468 return buf;
451 } 469 }
452 return NULL; 470 return NULL;
......
...@@ -29,15 +29,16 @@ ...@@ -29,15 +29,16 @@
29 29
30 #include <confpaths.h> 30 #include <confpaths.h>
31 31
32 #include <mailutils/nls.h>
32 #include <mailutils/mailbox.h> 33 #include <mailutils/mailbox.h>
33 #include <mailutils/util.h> 34 #include <mailutils/util.h>
34 #include <mailutils/debug.h> 35 #include <mailutils/debug.h>
35 #include <mailutils/error.h> 36 #include <mailutils/error.h>
36 #include <mailutils/errno.h> 37 #include <mailutils/errno.h>
37 #include <mailutils/mu_auth.h> 38 #include <mailutils/mu_auth.h>
38 #include <mailutils/vartab.h>
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 42
42 #include <mailutils/sys/mailbox.h> 43 #include <mailutils/sys/mailbox.h>
43 44
...@@ -137,12 +138,30 @@ mu_construct_user_mailbox_url (char **pout, const char *name) ...@@ -137,12 +138,30 @@ mu_construct_user_mailbox_url (char **pout, const char *name)
137 { 138 {
138 int rc; 139 int rc;
139 const char *pat = mu_mailbox_url (); 140 const char *pat = mu_mailbox_url ();
140 mu_vartab_t vtab; 141 const char *env[3];
142 struct mu_wordsplit ws;
143
144 env[0] = "user";
145 env[1] = (char*) name;
146 env[3] = NULL;
147 ws.ws_env = env;
148 if (mu_wordsplit (pat, &ws,
149 MU_WRDSF_NOSPLIT | MU_WRDSF_NOCMD |
150 MU_WRDSF_ENV | MU_WRDSF_ENV_KV))
151 {
152 mu_error (_("cannot expand line `%s': %s"), pat,
153 mu_wordsplit_strerror (&ws));
154 return errno;
155 }
141 156
142 mu_vartab_create (&vtab); 157 if (ws.ws_wordc == 0)
143 mu_vartab_define (vtab, "user", name, 1); 158 /* FIXME: a special return code maybe? */
144 rc = mu_vartab_expand (vtab, pat, pout); 159 *pout = strdup ("");
145 mu_vartab_destroy (&vtab); 160 else
161 *pout = strdup (ws.ws_wordv[0]);
162 mu_wordsplit_free (&ws);
163 if (!*pout)
164 return ENOMEM;
146 return rc; 165 return rc;
147 } 166 }
148 167
......
...@@ -36,7 +36,6 @@ ...@@ -36,7 +36,6 @@
36 #include <mailutils/error.h> 36 #include <mailutils/error.h>
37 #include <mailutils/errno.h> 37 #include <mailutils/errno.h>
38 #include <mailutils/kwd.h> 38 #include <mailutils/kwd.h>
39 #include <mailutils/vartab.h>
40 #include <mailutils/io.h> 39 #include <mailutils/io.h>
41 40
42 struct _mu_acl_entry 41 struct _mu_acl_entry
...@@ -500,18 +499,12 @@ struct run_closure ...@@ -500,18 +499,12 @@ struct run_closure
500 unsigned idx; 499 unsigned idx;
501 mu_debug_t debug; 500 mu_debug_t debug;
502 struct sockaddr *sa; 501 struct sockaddr *sa;
502 char *numbuf;
503 char *portbuf;
503 int salen; 504 int salen;
504 mu_acl_result_t *result; 505 mu_acl_result_t *result;
505 }; 506 };
506 507
507 static int
508 _expand_aclno (const char *name, void *data, char **p)
509 {
510 struct run_closure *rp = data;
511 /*FIXME: memory leak*/
512 return mu_asprintf (p, "%u", rp->idx);
513 }
514
515 #if defined (HAVE_SYSCONF) && defined (_SC_OPEN_MAX) 508 #if defined (HAVE_SYSCONF) && defined (_SC_OPEN_MAX)
516 # define getmaxfd() sysconf (_SC_OPEN_MAX) 509 # define getmaxfd() sysconf (_SC_OPEN_MAX)
517 #elif defined (HAVE_GETDTABLESIZE) 510 #elif defined (HAVE_GETDTABLESIZE)
...@@ -520,52 +513,103 @@ _expand_aclno (const char *name, void *data, char **p) ...@@ -520,52 +513,103 @@ _expand_aclno (const char *name, void *data, char **p)
520 # define getmaxfd() 64 513 # define getmaxfd() 64
521 #endif 514 #endif
522 515
523 static int 516 #define SEQ(s, n, l) \
524 expand_arg (const char *cmdline, struct run_closure *rp, char **s) 517 (((l) == (sizeof(s) - 1)) && memcmp (s, n, l) == 0)
518
519 static const char *
520 acl_getvar (const char *name, size_t nlen, void *data)
525 { 521 {
526 int rc; 522 struct run_closure *rp = data;
527 mu_vartab_t vtab; 523
528 524 if (SEQ ("aclno", name, nlen))
529 MU_DEBUG1 (rp->debug, MU_DEBUG_TRACE0, "Expanding \"%s\" => ", cmdline); 525 {
526 if (!rp->numbuf && mu_asprintf (&rp->numbuf, "%u", rp->idx))
527 return NULL;
528 return rp->numbuf;
529 }
530 530
531 mu_vartab_create (&vtab);
532 mu_vartab_define_exp (vtab, "aclno", _expand_aclno, NULL, rp);
533 switch (rp->sa->sa_family) 531 switch (rp->sa->sa_family)
534 { 532 {
535 case AF_INET: 533 case AF_INET:
536 { 534 {
537 struct sockaddr_in *s_in = (struct sockaddr_in *)rp->sa; 535 struct sockaddr_in *s_in = (struct sockaddr_in *)rp->sa;
538 struct in_addr addr = s_in->sin_addr; 536
539 char *p; 537 if (SEQ ("address", name, nlen))
538 {
539 struct in_addr addr = s_in->sin_addr;
540 addr.s_addr = htonl (addr.s_addr);
541 return inet_ntoa (addr);
542 }
543
544 if (SEQ ("port", name, nlen))
545 {
546 if (!rp->portbuf &&
547 mu_asprintf (&rp->portbuf, "%hu", ntohs (s_in->sin_port)))
548 return NULL;
549 return rp->portbuf;
550 }
551 break;
540 552
541 mu_vartab_define (vtab, "family", "AF_INET", 1); 553 case AF_UNIX:
542 addr.s_addr = htonl (addr.s_addr); 554 if (SEQ ("address", name, nlen))
543 mu_vartab_define (vtab, "address", inet_ntoa (addr), 0);
544 if (mu_asprintf (&p, "%hu", ntohs (s_in->sin_port)) == 0)
545 { 555 {
546 mu_vartab_define (vtab, "port", p, 0); 556 struct sockaddr_un *s_un = (struct sockaddr_un *)rp->sa;
547 free (p); 557 if (rp->salen == sizeof (s_un->sun_family))
558 return NULL;
559 else
560 return s_un->sun_path;
548 } 561 }
549 } 562 }
550 break; 563 break;
551 564 }
565 return NULL;
566 }
567
568 static int
569 expand_arg (const char *cmdline, struct run_closure *rp, char **s)
570 {
571 int rc;
572 struct mu_wordsplit ws;
573 const char *env[3];
574
575 MU_DEBUG1 (rp->debug, MU_DEBUG_TRACE0, "Expanding \"%s\" => ", cmdline);
576 env[0] = "family";
577 switch (rp->sa->sa_family)
578 {
579 case AF_INET:
580 env[1] = "AF_INET";
581 break;
582
552 case AF_UNIX: 583 case AF_UNIX:
553 { 584 env[1] = "AF_UNIX";
554 struct sockaddr_un *s_un = (struct sockaddr_un *)rp->sa;
555
556 mu_vartab_define (vtab, "family", "AF_UNIX", 1);
557 mu_vartab_define (vtab, "address", s_un->sun_path, 1);
558 }
559 break; 585 break;
560 } 586 }
561 587 env[2] = NULL;
562 rc = mu_vartab_expand (vtab, cmdline, s); 588 ws.ws_env = env;
563 mu_vartab_destroy (&vtab); 589 ws.ws_getvar = acl_getvar;
590 ws.ws_closure = rp;
591 rc = mu_wordsplit (cmdline, &ws,
592 MU_WRDSF_NOSPLIT | MU_WRDSF_NOCMD |
593 MU_WRDSF_ENV | MU_WRDSF_ENV_KV |
594 MU_WRDSF_GETVAR | MU_WRDSF_CLOSURE);
564 595
565 if (rc == 0) 596 if (rc == 0)
566 MU_DEBUG1 (rp->debug, MU_DEBUG_TRACE0, "\"%s\". ", *s); 597 {
598 *s = strdup (ws.ws_wordv[0]);
599 mu_wordsplit_free (&ws);
600 if (!*s)
601 {
602 MU_DEBUG (rp->debug, MU_DEBUG_TRACE0, "failed: not enough memory. ");
603 return ENOMEM;
604 }
605 MU_DEBUG1 (rp->debug, MU_DEBUG_TRACE0, "\"%s\". ", *s);
606 }
567 else 607 else
568 MU_DEBUG (rp->debug, MU_DEBUG_TRACE0, "failed. "); 608 {
609 MU_DEBUG1 (rp->debug, MU_DEBUG_TRACE0, "failed: %s",
610 mu_wordsplit_strerror (&ws));
611 rc = errno;
612 }
569 return rc; 613 return rc;
570 } 614 }
571 615
...@@ -744,7 +788,10 @@ mu_acl_check_sockaddr (mu_acl_t acl, const struct sockaddr *sa, int salen, ...@@ -744,7 +788,10 @@ mu_acl_check_sockaddr (mu_acl_t acl, const struct sockaddr *sa, int salen,
744 r.debug = acl->debug; 788 r.debug = acl->debug;
745 r.result = pres; 789 r.result = pres;
746 *r.result = mu_acl_result_undefined; 790 *r.result = mu_acl_result_undefined;
791 r.numbuf = r.portbuf = NULL;
747 mu_list_do (acl->aclist, _run_entry, &r); 792 mu_list_do (acl->aclist, _run_entry, &r);
793 free (r.numbuf);
794 free (r.portbuf);
748 free (r.sa); 795 free (r.sa);
749 return 0; 796 return 0;
750 } 797 }
......
...@@ -143,7 +143,7 @@ mu_wordsplit_init (struct mu_wordsplit *wsp, const char *input, size_t len, ...@@ -143,7 +143,7 @@ mu_wordsplit_init (struct mu_wordsplit *wsp, const char *input, size_t len,
143 if (wsp->ws_flags & MU_WRDSF_REUSE) 143 if (wsp->ws_flags & MU_WRDSF_REUSE)
144 { 144 {
145 if (!(wsp->ws_flags & MU_WRDSF_APPEND)) 145 if (!(wsp->ws_flags & MU_WRDSF_APPEND))
146 wsp->ws_wordc = 0; 146 mu_wordsplit_free_words (wsp);
147 } 147 }
148 else 148 else
149 { 149 {
...@@ -1427,7 +1427,7 @@ mu_wordsplit (const char *command, struct mu_wordsplit *ws, int flags) ...@@ -1427,7 +1427,7 @@ mu_wordsplit (const char *command, struct mu_wordsplit *ws, int flags)
1427 } 1427 }
1428 1428
1429 void 1429 void
1430 mu_wordsplit_free (struct mu_wordsplit *ws) 1430 mu_wordsplit_free_words (struct mu_wordsplit *ws)
1431 { 1431 {
1432 size_t i; 1432 size_t i;
1433 1433
...@@ -1435,8 +1435,18 @@ mu_wordsplit_free (struct mu_wordsplit *ws) ...@@ -1435,8 +1435,18 @@ mu_wordsplit_free (struct mu_wordsplit *ws)
1435 { 1435 {
1436 char *p = ws->ws_wordv[ws->ws_offs + i]; 1436 char *p = ws->ws_wordv[ws->ws_offs + i];
1437 if (p) 1437 if (p)
1438 free (p); 1438 {
1439 free (p);
1440 ws->ws_wordv[ws->ws_offs + i] = NULL;
1441 }
1439 } 1442 }
1443 ws->ws_wordc = 0;
1444 }
1445
1446 void
1447 mu_wordsplit_free (struct mu_wordsplit *ws)
1448 {
1449 mu_wordsplit_free_words (ws);
1440 free (ws->ws_wordv); 1450 free (ws->ws_wordv);
1441 ws->ws_wordv = NULL; 1451 ws->ws_wordv = NULL;
1442 } 1452 }
......
...@@ -46,7 +46,6 @@ ...@@ -46,7 +46,6 @@
46 #include "mailutils/md5.h" 46 #include "mailutils/md5.h"
47 #include "mailutils/sha1.h" 47 #include "mailutils/sha1.h"
48 #include "mailutils/ldap.h" 48 #include "mailutils/ldap.h"
49 #include "mailutils/vartab.h"
50 49
51 #include <ldap.h> 50 #include <ldap.h>
52 #include <lber.h> 51 #include <lber.h>
...@@ -504,33 +503,43 @@ _mu_ldap_search (LDAP *ld, const char *filter_pat, const char *key, ...@@ -504,33 +503,43 @@ _mu_ldap_search (LDAP *ld, const char *filter_pat, const char *key,
504 struct mu_auth_data **return_data) 503 struct mu_auth_data **return_data)
505 { 504 {
506 int rc; 505 int rc;
507 char *filter;
508 char **attrs; 506 char **attrs;
509 size_t nattrs; 507 size_t nattrs;
510 LDAPMessage *res, *msg; 508 LDAPMessage *res, *msg;
511 ber_int_t msgid; 509 ber_int_t msgid;
512 mu_vartab_t vtab; 510 const char *env[3];
511 struct mu_wordsplit ws;
513 512
514 rc = _construct_attr_array (&nattrs, &attrs); 513 rc = _construct_attr_array (&nattrs, &attrs);
515 if (rc) 514 if (rc)
516 return rc; 515 return rc;
517 516
518 mu_vartab_create (&vtab); 517 env[0] = "user";
519 mu_vartab_define (vtab, "user", key, 1); 518 env[1] = key;
520 mu_vartab_define (vtab, "u", key, 1); 519 env[3] = NULL;
521 rc = mu_vartab_expand (vtab, filter_pat, &filter); 520
522 mu_vartab_destroy (&vtab); 521 ws.ws_env = env;
523 if (rc) 522 if (mu_wordsplit (filter_pat, &ws,
523 MU_WRDSF_NOSPLIT | MU_WRDSF_NOCMD |
524 MU_WRDSF_ENV | MU_WRDSF_ENV_KV))
525 {
526 mu_error (_("cannot expand line `%s': %s"), filter_pat,
527 mu_wordsplit_strerror (&ws));
528 return MU_ERR_FAILURE;
529 }
530 else if (ws.ws_wordc == 0)
524 { 531 {
532 mu_error (_("expanding %s yields empty string"), filter_pat);
533 mu_wordsplit_free (&ws);
525 mu_argcv_free (nattrs, attrs); 534 mu_argcv_free (nattrs, attrs);
526 return ENOMEM; 535 return MU_ERR_FAILURE;
527 } 536 }
528 537
529 rc = ldap_search_ext (ld, ldap_param.base, LDAP_SCOPE_SUBTREE, 538 rc = ldap_search_ext (ld, ldap_param.base, LDAP_SCOPE_SUBTREE,
530 filter, attrs, 0, 539 ws.ws_wordv[0], attrs, 0,
531 NULL, NULL, NULL, -1, &msgid); 540 NULL, NULL, NULL, -1, &msgid);
541 mu_wordsplit_free (&ws);
532 mu_argcv_free (nattrs, attrs); 542 mu_argcv_free (nattrs, attrs);
533 free (filter);
534 543
535 if (rc != LDAP_SUCCESS) 544 if (rc != LDAP_SUCCESS)
536 { 545 {
......
...@@ -40,7 +40,6 @@ ...@@ -40,7 +40,6 @@
40 #include <mailutils/error.h> 40 #include <mailutils/error.h>
41 #include <mailutils/errno.h> 41 #include <mailutils/errno.h>
42 #include <mailutils/nls.h> 42 #include <mailutils/nls.h>
43 #include <mailutils/vartab.h>
44 #include <mailutils/io.h> 43 #include <mailutils/io.h>
45 #include <mailutils/cctype.h> 44 #include <mailutils/cctype.h>
46 45
...@@ -245,41 +244,38 @@ mu_radius_module_init (enum mu_gocs_op op, void *data) ...@@ -245,41 +244,38 @@ mu_radius_module_init (enum mu_gocs_op op, void *data)
245 static char * 244 static char *
246 _expand_query (const char *query, const char *ustr, const char *passwd) 245 _expand_query (const char *query, const char *ustr, const char *passwd)
247 { 246 {
248 int rc; 247 struct mu_wordsplit ws;
249 mu_vartab_t vtab; 248 const char *env[2 * 2 + 1];
250 char *str, *ret; 249 char *ret;
251 250
252 if (!query) 251 env[0] = "user";
253 return NULL; 252 env[1] = (char*) ustr;
254 253 env[2] = "passwd";
255 mu_vartab_create (&vtab); 254 env[3] = (char*) passwd;
256 if (ustr) 255 env[4] = NULL;
257 { 256
258 mu_vartab_define (vtab, "user", ustr, 1); 257 ws.ws_env = env;
259 mu_vartab_define (vtab, "u", ustr, 1); 258 if (mu_wordsplit (query, &ws,
260 } 259 MU_WRDSF_NOSPLIT | MU_WRDSF_NOCMD |
261 260 MU_WRDSF_ENV | MU_WRDSF_ENV_KV))
262 if (passwd)
263 { 261 {
264 mu_vartab_define (vtab, "passwd", passwd, 1); 262 mu_error (_("cannot expand line `%s': %s"), query,
265 mu_vartab_define (vtab, "p", passwd, 1); 263 mu_wordsplit_strerror (&ws));
264 return NULL;
266 } 265 }
267 266 else if (ws.ws_wordc == 0)
268 rc = mu_vartab_expand (vtab, query, &str);
269 if (rc == 0)
270 { 267 {
271 ret = grad_emalloc (strlen (str) + 1); 268 mu_error (_("expanding %s yields empty string"), query);
272 strcpy (ret, str); 269 mu_wordsplit_free (&ws);
273 free (str); 270 return NULL;
274 } 271 }
275 else 272
276 ret = NULL; 273 ret = grad_emalloc (strlen (ws.ws_wordv[0]) + 1);
277 274 strcpy (ret, ws.ws_wordv[0]);
278 mu_vartab_destroy (&vtab); 275 mu_wordsplit_free (&ws);
279 return ret; 276 return ret;
280 } 277 }
281 278
282
283 279
284 static grad_avp_t * 280 static grad_avp_t *
285 create_request (grad_avp_t *template, const char *ustr, const char *passwd) 281 create_request (grad_avp_t *template, const char *ustr, const char *passwd)
......
...@@ -49,7 +49,6 @@ ...@@ -49,7 +49,6 @@
49 #include <mailutils/nls.h> 49 #include <mailutils/nls.h>
50 #include <mailutils/util.h> 50 #include <mailutils/util.h>
51 #include <mailutils/sql.h> 51 #include <mailutils/sql.h>
52 #include <mailutils/vartab.h>
53 #include <mailutils/cstr.h> 52 #include <mailutils/cstr.h>
54 #include "sql.h" 53 #include "sql.h"
55 54
...@@ -91,20 +90,34 @@ mu_sql_expand_query (const char *query, const char *ustr) ...@@ -91,20 +90,34 @@ mu_sql_expand_query (const char *query, const char *ustr)
91 int rc; 90 int rc;
92 char *res; 91 char *res;
93 char *esc_ustr; 92 char *esc_ustr;
94 mu_vartab_t vtab; 93 struct mu_wordsplit ws;
95 94 const char *env[2 + 1];
95
96 if (!query) 96 if (!query)
97 return NULL; 97 return NULL;
98 98
99 esc_ustr = sql_escape_string (ustr); 99 esc_ustr = sql_escape_string (ustr);
100 mu_vartab_create (&vtab); 100 env[0] = "user";
101 mu_vartab_define (vtab, "user", ustr, 1); 101 env[1] = (char*) ustr;
102 mu_vartab_define (vtab, "u", ustr, 1); 102 env[2] = NULL;
103 rc = mu_vartab_expand (vtab, query, &res); 103
104 if (rc) 104 ws.ws_env = env;
105 res = NULL; 105 if (mu_wordsplit (query, &ws,
106 mu_vartab_destroy (&vtab); 106 MU_WRDSF_NOSPLIT | MU_WRDSF_NOCMD |
107 107 MU_WRDSF_ENV | MU_WRDSF_ENV_KV))
108 {
109 mu_error (_("cannot expand line `%s': %s"), query,
110 mu_wordsplit_strerror (&ws));
111 return NULL;
112 }
113 else if (ws.ws_wordc == 0)
114 {
115 mu_error (_("expanding %s yields empty string"), query);
116 mu_wordsplit_free (&ws);
117 return NULL;
118 }
119 res = strdup (ws.ws_wordv[0]);
120 mu_wordsplit_free (&ws);
108 free (esc_ustr); 121 free (esc_ustr);
109 return res; 122 return res;
110 } 123 }
......
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
32 #include <mailutils/message.h> 32 #include <mailutils/message.h>
33 #include <mailutils/observer.h> 33 #include <mailutils/observer.h>
34 #include <mailutils/progmailer.h> 34 #include <mailutils/progmailer.h>
35 #include <mailutils/vartab.h> 35 #include <mailutils/wordsplit.h>
36 36
37 #include <mailutils/sys/url.h> 37 #include <mailutils/sys/url.h>
38 #include <mailutils/sys/mailer.h> 38 #include <mailutils/sys/mailer.h>
...@@ -140,26 +140,24 @@ prog_close (mu_mailer_t mailer) ...@@ -140,26 +140,24 @@ prog_close (mu_mailer_t mailer)
140 return mu_progmailer_close (mailer->data); 140 return mu_progmailer_close (mailer->data);
141 } 141 }
142 142
143 static int 143 struct prog_exp
144 _expand_sender (const char *name, void *data, char **p)
145 {
146 mu_address_t addr = data;
147 char *email;
148 int status = mu_address_aget_email (addr, 1, &email);
149
150 if (status != 0)
151 return status;
152 *p = email;
153 return 0;
154 }
155
156 struct ex_rcpt
157 { 144 {
158 mu_message_t msg; 145 mu_message_t msg;
159 mu_address_t addr; 146 mu_address_t sender_addr;
160 char *string; 147 char *sender_str;
148 mu_address_t rcpt_addr;
149 char *rcpt_str;
161 }; 150 };
162 151
152 static const char *
153 _expand_sender (struct prog_exp *pe)
154 {
155 if (!pe->sender_str &&
156 mu_address_aget_email (pe->sender_addr, 1, &pe->sender_str))
157 return NULL;
158 return pe->sender_str;
159 }
160
163 static int 161 static int
164 address_add (mu_address_t *paddr, const char *value) 162 address_add (mu_address_t *paddr, const char *value)
165 { 163 {
...@@ -206,28 +204,27 @@ message_read_rcpt (mu_message_t msg, mu_address_t *paddr) ...@@ -206,28 +204,27 @@ message_read_rcpt (mu_message_t msg, mu_address_t *paddr)
206 return 0; 204 return 0;
207 } 205 }
208 206
209 static int 207 static const char *
210 _expand_rcpt (const char *name, void *data, char **p) 208 _expand_rcpt (struct prog_exp *pe)
211 { 209 {
212 struct ex_rcpt *exrcpt = data;
213 int status; 210 int status;
214 211
215 if (!exrcpt->string) 212 if (!pe->rcpt_str)
216 { 213 {
217 size_t i, count = 0; 214 size_t i, count = 0;
218 size_t len = 0; 215 size_t len = 0;
219 char *str; 216 char *str;
220 mu_address_t tmp_addr = NULL, addr; 217 mu_address_t tmp_addr = NULL, addr;
221 218
222 if (exrcpt->addr) 219 if (pe->rcpt_addr)
223 addr = exrcpt->addr; 220 addr = pe->rcpt_addr;
224 else 221 else
225 { 222 {
226 status = message_read_rcpt (exrcpt->msg, &tmp_addr); 223 status = message_read_rcpt (pe->msg, &tmp_addr);
227 if (status) 224 if (status)
228 { 225 {
229 mu_address_destroy (&tmp_addr); 226 mu_address_destroy (&tmp_addr);
230 return status; 227 return NULL;
231 } 228 }
232 addr = tmp_addr; 229 addr = tmp_addr;
233 } 230 }
...@@ -241,7 +238,7 @@ _expand_rcpt (const char *name, void *data, char **p) ...@@ -241,7 +238,7 @@ _expand_rcpt (const char *name, void *data, char **p)
241 if ((status = mu_address_sget_email (addr, i, &email)) != 0) 238 if ((status = mu_address_sget_email (addr, i, &email)) != 0)
242 { 239 {
243 mu_address_destroy (&tmp_addr); 240 mu_address_destroy (&tmp_addr);
244 return status; 241 return NULL;
245 } 242 }
246 len += strlen (email); 243 len += strlen (email);
247 } 244 }
...@@ -250,9 +247,9 @@ _expand_rcpt (const char *name, void *data, char **p) ...@@ -250,9 +247,9 @@ _expand_rcpt (const char *name, void *data, char **p)
250 if (!str) 247 if (!str)
251 { 248 {
252 mu_address_destroy (&tmp_addr); 249 mu_address_destroy (&tmp_addr);
253 return ENOMEM; 250 return NULL;
254 } 251 }
255 exrcpt->string = str; 252 pe->rcpt_str = str;
256 253
257 for (i = 1; i <= count; i++) 254 for (i = 1; i <= count; i++)
258 { 255 {
...@@ -267,14 +264,22 @@ _expand_rcpt (const char *name, void *data, char **p) ...@@ -267,14 +264,22 @@ _expand_rcpt (const char *name, void *data, char **p)
267 *str = 0; 264 *str = 0;
268 mu_address_destroy (&tmp_addr); 265 mu_address_destroy (&tmp_addr);
269 } 266 }
270 *p = exrcpt->string; 267 return pe->rcpt_str;
271 return 0;
272 } 268 }
273 269
274 void 270 #define SEQ(s, n, l) \
275 _free_rcpt (void *data, char *value) 271 (((l) == (sizeof(s) - 1)) && memcmp (s, n, l) == 0)
272
273 static const char *
274 prog_getvar (const char *name, size_t nlen, void *data)
276 { 275 {
277 free (value); 276 struct prog_exp *pe = data;
277
278 if (SEQ ("sender", name, nlen))
279 return _expand_sender (pe);
280 if (SEQ ("rcpt", name, nlen))
281 return _expand_rcpt (pe);
282 return NULL;
278 } 283 }
279 284
280 static int 285 static int
...@@ -283,41 +288,58 @@ url_to_argv (mu_url_t url, mu_message_t msg, ...@@ -283,41 +288,58 @@ url_to_argv (mu_url_t url, mu_message_t msg,
283 int *pargc, char ***pargv) 288 int *pargc, char ***pargv)
284 { 289 {
285 int rc; 290 int rc;
286 mu_vartab_t vtab; 291 struct prog_exp pe;
287 struct ex_rcpt ex_rcpt;
288 char **query; 292 char **query;
289 size_t i; 293 size_t i;
290 size_t argc; 294 size_t argc;
291 char **argv; 295 char **argv;
296 struct mu_wordsplit ws;
297 int wsflags;
292 298
293 ex_rcpt.msg = msg; 299 pe.msg = msg;
294 ex_rcpt.addr = to; 300 pe.rcpt_addr = to;
295 ex_rcpt.string = NULL; 301 pe.sender_addr = from;
296 mu_vartab_create (&vtab); 302 pe.sender_str = pe.rcpt_str = NULL;
297 mu_vartab_define_exp (vtab, "sender", _expand_sender, NULL, from); 303
298 mu_vartab_define_exp (vtab, "rcpt", _expand_rcpt, _free_rcpt, &ex_rcpt); 304 ws.ws_getvar = prog_getvar;
305 ws.ws_closure = &pe;
306 wsflags = MU_WRDSF_NOSPLIT | MU_WRDSF_NOCMD |
307 MU_WRDSF_GETVAR | MU_WRDSF_CLOSURE;
299 308
300 rc = mu_url_sget_query (url, &argc, &query); 309 rc = mu_url_sget_query (url, &argc, &query);
301 if (rc) 310 if (rc)
302 return rc; 311 return rc;
303 312
304 argv = calloc (argc + 1, sizeof (argv[0])); 313 argv = calloc (argc + 2, sizeof (argv[0]));
305 if (!argv) 314 if (!argv)
306 return ENOMEM; 315 return ENOMEM;
307 316
317 rc = mu_url_aget_path (url, &argv[0]);
318 if (rc)
319 {
320 free (argv);
321 return rc;
322 }
323
308 for (i = 0; i < argc; i++) 324 for (i = 0; i < argc; i++)
309 { 325 {
310 if ((rc = mu_vartab_expand (vtab, query[i], &argv[i]))) 326 if (mu_wordsplit (query[i], &ws, wsflags))
311 { 327 {
312 mu_argcv_free (i, argv); 328 mu_argcv_free (i, argv);
313 mu_vartab_destroy (&vtab); 329 mu_wordsplit_free (&ws);
314 return rc; 330 return errno;
315 } 331 }
332 if (ws.ws_wordc == 0)
333 argv[i+1] = strdup ("");
334 else
335 argv[i+1] = strdup (ws.ws_wordv[0]);
336 wsflags |= MU_WRDSF_REUSE;
316 } 337 }
317 argv[i] = NULL; 338 argv[i+1] = NULL;
339 mu_wordsplit_free (&ws);
340 free (pe.sender_str);
341 free (pe.rcpt_str);
318 342
319 mu_vartab_destroy (&vtab);
320
321 *pargc = argc; 343 *pargc = argc;
322 *pargv = argv; 344 *pargv = argv;
323 return 0; 345 return 0;
......
...@@ -140,6 +140,7 @@ libmailutils/server/ipsrv.c ...@@ -140,6 +140,7 @@ libmailutils/server/ipsrv.c
140 libmailutils/server/msrv.c 140 libmailutils/server/msrv.c
141 141
142 libmailutils/mailbox/message.c 142 libmailutils/mailbox/message.c
143 libmailutils/mailbox/mbx_default.c
143 libmailutils/mailer/mailer.c 144 libmailutils/mailer/mailer.c
144 libmailutils/mailer/smtp.c 145 libmailutils/mailer/smtp.c
145 libmailutils/mailer/smtp_gsasl.c 146 libmailutils/mailer/smtp_gsasl.c
......