Fixes in wordsplit. Use wordsplit instead of vartab in movemail.
Eventually this will lead to vartab fading out until it is removed in some point in the future. Wordsplit provides a much better variable substitution mechanism. * include/mailutils/wordsplit.h (mu_wordsplit) <ws_getvar>: Change signature. <ws_closure>: New member. (MU_WRDSF_CLOSURE): New flag. * libmailutils/string/wordsplit.c (mu_wordsplit_init): Initialize ws_closure to NULL, unless MU_WRDSF_CLOSURE is set. Do not modify ws_wordn if MU_WRDSF_DOOFFS is set. (wsnode_remove): Clear _WSNF_JOIN on the previous node if the node being deleted is the last one in chain. (expvar): Pass ws_closure as 3rd argument to ws_getvar. Insert a NULL node if the variable is not defined. * movemail/movemail.c: Use wordsplit instead of vartab. Note a side effect: the "source:*" and "dest:*" variables are now written as "source_*" and "dest_*", correspondingly. (movemail_getvar_closure): New structure. (DCL_VTX): Remove macro and its uses. (get_url_part, movemail_getvar): New functions. (set_program_id): Rewrite using wordsplit.
Showing
3 changed files
with
96 additions
and
51 deletions
... | @@ -35,8 +35,9 @@ struct mu_wordsplit | ... | @@ -35,8 +35,9 @@ struct mu_wordsplit |
35 | __attribute__ ((__format__ (__printf__, 1, 2))); | 35 | __attribute__ ((__format__ (__printf__, 1, 2))); |
36 | 36 | ||
37 | const char **ws_env; | 37 | const char **ws_env; |
38 | char *(*ws_getvar) (const char *, size_t); | 38 | const char *(*ws_getvar) (const char *, size_t, void *); |
39 | 39 | void *ws_closure; | |
40 | |||
40 | const char *ws_input; | 41 | const char *ws_input; |
41 | size_t ws_len; | 42 | size_t ws_len; |
42 | size_t ws_endp; | 43 | size_t ws_endp; |
... | @@ -103,6 +104,9 @@ struct mu_wordsplit | ... | @@ -103,6 +104,9 @@ struct mu_wordsplit |
103 | /* Handle C escapes */ | 104 | /* Handle C escapes */ |
104 | #define MU_WRDSF_CESCAPES 0x1000000 | 105 | #define MU_WRDSF_CESCAPES 0x1000000 |
105 | 106 | ||
107 | /* ws_closure is set */ | ||
108 | #define MU_WRDSF_CLOSURE 0x2000000 | ||
109 | |||
106 | #define MU_WRDSF_DEFFLAGS \ | 110 | #define MU_WRDSF_DEFFLAGS \ |
107 | (MU_WRDSF_NOVAR | MU_WRDSF_NOCMD | \ | 111 | (MU_WRDSF_NOVAR | MU_WRDSF_NOCMD | \ |
108 | MU_WRDSF_QUOTE | MU_WRDSF_SQUEEZE_DELIMS | MU_WRDSF_CESCAPES) | 112 | MU_WRDSF_QUOTE | MU_WRDSF_SQUEEZE_DELIMS | MU_WRDSF_CESCAPES) |
... | ... |
... | @@ -151,9 +151,10 @@ mu_wordsplit_init (struct mu_wordsplit *wsp, const char *input, size_t len, | ... | @@ -151,9 +151,10 @@ mu_wordsplit_init (struct mu_wordsplit *wsp, const char *input, size_t len, |
151 | wsp->ws_wordc = 0; | 151 | wsp->ws_wordc = 0; |
152 | wsp->ws_wordn = 0; | 152 | wsp->ws_wordn = 0; |
153 | } | 153 | } |
154 | if (wsp->ws_flags & MU_WRDSF_DOOFFS) | ||
155 | wsp->ws_wordn += wsp->ws_offs; | ||
156 | 154 | ||
155 | if (!(wsp->ws_flags & MU_WRDSF_CLOSURE)) | ||
156 | wsp->ws_closure = NULL; | ||
157 | |||
157 | wsp->ws_endp = 0; | 158 | wsp->ws_endp = 0; |
158 | wsp->ws_errno = 0; | 159 | wsp->ws_errno = 0; |
159 | wsp->ws_head = wsp->ws_tail = NULL; | 160 | wsp->ws_head = wsp->ws_tail = NULL; |
... | @@ -311,7 +312,11 @@ wsnode_remove (struct mu_wordsplit *wsp, struct mu_wordsplit_node *node) | ... | @@ -311,7 +312,11 @@ wsnode_remove (struct mu_wordsplit *wsp, struct mu_wordsplit_node *node) |
311 | 312 | ||
312 | p = node->prev; | 313 | p = node->prev; |
313 | if (p) | 314 | if (p) |
314 | p->next = node->next; | 315 | { |
316 | p->next = node->next; | ||
317 | if (!node->next) | ||
318 | p->flags &= ~_WSNF_JOIN; | ||
319 | } | ||
315 | else | 320 | else |
316 | wsp->ws_head = node->next; | 321 | wsp->ws_head = node->next; |
317 | 322 | ||
... | @@ -666,7 +671,7 @@ expvar (struct mu_wordsplit *wsp, const char *str, size_t len, | ... | @@ -666,7 +671,7 @@ expvar (struct mu_wordsplit *wsp, const char *str, size_t len, |
666 | { | 671 | { |
667 | size_t i = 0; | 672 | size_t i = 0; |
668 | const char *defstr = NULL; | 673 | const char *defstr = NULL; |
669 | char *value; | 674 | const char *value; |
670 | const char *vptr; | 675 | const char *vptr; |
671 | struct mu_wordsplit_node *newnode; | 676 | struct mu_wordsplit_node *newnode; |
672 | const char *start = str - 1; | 677 | const char *start = str - 1; |
... | @@ -738,7 +743,7 @@ expvar (struct mu_wordsplit *wsp, const char *str, size_t len, | ... | @@ -738,7 +743,7 @@ expvar (struct mu_wordsplit *wsp, const char *str, size_t len, |
738 | return _wsplt_nomem (wsp); | 743 | return _wsplt_nomem (wsp); |
739 | } | 744 | } |
740 | else if (wsp->ws_flags & MU_WRDSF_GETVAR) | 745 | else if (wsp->ws_flags & MU_WRDSF_GETVAR) |
741 | value = wsp->ws_getvar (str, i); | 746 | value = wsp->ws_getvar (str, i, wsp->ws_closure); |
742 | else if (wsp->ws_flags & MU_WRDSF_UNDEF) | 747 | else if (wsp->ws_flags & MU_WRDSF_UNDEF) |
743 | { | 748 | { |
744 | wsp->ws_errno = MU_WRDSE_UNDEF; | 749 | wsp->ws_errno = MU_WRDSE_UNDEF; |
... | @@ -822,6 +827,14 @@ expvar (struct mu_wordsplit *wsp, const char *str, size_t len, | ... | @@ -822,6 +827,14 @@ expvar (struct mu_wordsplit *wsp, const char *str, size_t len, |
822 | memcpy (newnode->v.word, start, size); | 827 | memcpy (newnode->v.word, start, size); |
823 | newnode->v.word[size] = 0; | 828 | newnode->v.word[size] = 0; |
824 | } | 829 | } |
830 | else | ||
831 | { | ||
832 | if (wsnode_new (wsp, &newnode)) | ||
833 | return 1; | ||
834 | wsnode_insert (wsp, newnode, *ptail, 0); | ||
835 | *ptail = newnode; | ||
836 | newnode->flags = _WSNF_NULL; | ||
837 | } | ||
825 | return 0; | 838 | return 0; |
826 | } | 839 | } |
827 | 840 | ||
... | ... |
... | @@ -650,70 +650,98 @@ _compare_uidls (const void *item, const void *value) | ... | @@ -650,70 +650,98 @@ _compare_uidls (const void *item, const void *value) |
650 | 650 | ||
651 | return strcmp (a->uidl, b->uidl); | 651 | return strcmp (a->uidl, b->uidl); |
652 | } | 652 | } |
653 | |||
654 | struct movemail_getvar_closure | ||
655 | { | ||
656 | const char *source_name; | ||
657 | const char *dest_name; | ||
658 | mu_url_t source_url; | ||
659 | mu_url_t dest_url; | ||
660 | }; | ||
653 | 661 | ||
654 | #define __cat2__(a,b) a ## b | 662 | #define SEQ(s, n, l) \ |
655 | #define DCL_VTX(what) \ | 663 | (((l) == (sizeof(s) - 1)) && memcmp (s, n, l) == 0) |
656 | static int \ | ||
657 | __cat2__(_vtx_,what) (const char *name, void *data, char **p) \ | ||
658 | { \ | ||
659 | mu_url_t url = data; \ | ||
660 | int rc = __cat2__(mu_url_aget_,what) (url, p); \ | ||
661 | if (rc == MU_ERR_NOENT) \ | ||
662 | { \ | ||
663 | *p = strdup (""); \ | ||
664 | return 0; \ | ||
665 | } \ | ||
666 | return rc; \ | ||
667 | } | ||
668 | 664 | ||
669 | DCL_VTX (host) | 665 | static const char * |
670 | DCL_VTX (user) | 666 | get_url_part (mu_url_t url, const char *name, size_t nlen) |
671 | DCL_VTX (path) | 667 | { |
668 | int rc = MU_ERR_NOENT; | ||
669 | const char *s; | ||
670 | |||
671 | if (!url) | ||
672 | return NULL; | ||
673 | if (SEQ ("user", name, nlen)) | ||
674 | rc = mu_url_sget_user (url, &s); | ||
675 | else if (SEQ ("host", name, nlen)) | ||
676 | rc = mu_url_sget_host (url, &s); | ||
677 | else if (SEQ ("port", name, nlen)) | ||
678 | rc = mu_url_sget_portstr (url, &s); | ||
679 | else if (SEQ ("path", name, nlen)) | ||
680 | rc = mu_url_sget_path (url, &s); | ||
681 | |||
682 | if (rc) | ||
683 | return NULL; | ||
684 | return s; | ||
685 | } | ||
686 | |||
687 | static const char * | ||
688 | movemail_getvar (const char *name, size_t nlen, void *data) | ||
689 | { | ||
690 | struct movemail_getvar_closure *pc = data; | ||
691 | |||
692 | if (SEQ ("progname", name, nlen)) | ||
693 | return mu_program_name; | ||
694 | if (SEQ ("source", name, nlen)) | ||
695 | return pc->source_name; | ||
696 | if (SEQ ("dest", name, nlen)) | ||
697 | return pc->dest_name; | ||
698 | |||
699 | if (nlen > 7 && memcmp ("source_", name, 7) == 0) | ||
700 | return get_url_part (pc->source_url, name + 7, nlen - 7); | ||
701 | if (nlen > 5 && memcmp ("dest_", name, 5) == 0) | ||
702 | return get_url_part (pc->dest_url, name + 5, nlen - 5); | ||
703 | |||
704 | return NULL; | ||
705 | } | ||
672 | 706 | ||
673 | static void | 707 | static void |
674 | set_program_id (const char *source_name, const char *dest_name) | 708 | set_program_id (const char *source_name, const char *dest_name) |
675 | { | 709 | { |
676 | int rc; | 710 | int rc; |
677 | mu_vartab_t vtab; | 711 | struct mu_wordsplit ws; |
678 | char *id; | 712 | struct movemail_getvar_closure clos; |
679 | mu_url_t url; | 713 | |
680 | 714 | clos.source_name = source_name; | |
681 | mu_vartab_create (&vtab); | 715 | clos.dest_name = dest_name; |
682 | mu_vartab_define (vtab, "progname", mu_program_name, 1); | 716 | rc = mu_mailbox_get_url (source, &clos.source_url); |
683 | mu_vartab_define (vtab, "source", source_name, 1); | ||
684 | rc = mu_mailbox_get_url (source, &url); | ||
685 | if (rc) | 717 | if (rc) |
686 | mu_diag_output (MU_DIAG_INFO, | 718 | mu_diag_output (MU_DIAG_INFO, |
687 | _("cannot obtain source mailbox URL: %s"), | 719 | _("cannot obtain source mailbox URL: %s"), |
688 | mu_strerror (rc)); | 720 | mu_strerror (rc)); |
689 | else | 721 | rc = mu_mailbox_get_url (dest, &clos.dest_url); |
690 | { | ||
691 | mu_vartab_define_exp (vtab, "source:user", _vtx_user, NULL, url); | ||
692 | mu_vartab_define_exp (vtab, "source:host", _vtx_host, NULL, url); | ||
693 | mu_vartab_define_exp (vtab, "source:path", _vtx_path, NULL, url); | ||
694 | } | ||
695 | |||
696 | mu_vartab_define (vtab, "dest", dest_name, 1); | ||
697 | rc = mu_mailbox_get_url (dest, &url); | ||
698 | if (rc) | 722 | if (rc) |
699 | mu_diag_output (MU_DIAG_INFO, | 723 | mu_diag_output (MU_DIAG_INFO, |
700 | _("cannot obtain destination mailbox URL: %s"), | 724 | _("cannot obtain destination mailbox URL: %s"), |
701 | mu_strerror (rc)); | 725 | mu_strerror (rc)); |
702 | else | 726 | |
727 | ws.ws_getvar = movemail_getvar; | ||
728 | ws.ws_closure = &clos; | ||
729 | if (mu_wordsplit (program_id_option, &ws, | ||
730 | MU_WRDSF_NOSPLIT | MU_WRDSF_NOCMD | | ||
731 | MU_WRDSF_GETVAR | MU_WRDSF_CLOSURE)) | ||
703 | { | 732 | { |
704 | mu_vartab_define_exp (vtab, "dest:user", _vtx_user, NULL, url); | 733 | mu_error (_("cannot expand line `%s': %s"), program_id_option, |
705 | mu_vartab_define_exp (vtab, "dest:host", _vtx_host, NULL, url); | 734 | mu_wordsplit_strerror (&ws)); |
706 | mu_vartab_define_exp (vtab, "dest:path", _vtx_path, NULL, url); | 735 | return; |
707 | } | 736 | } |
708 | 737 | ||
709 | rc = mu_vartab_expand (vtab, program_id_option, &id); | ||
710 | mu_vartab_destroy (&vtab); | ||
711 | /* mu_asprintf (&id, "%s: %s", mu_program_name, s); | ||
712 | free (s);*/ | ||
713 | /* FIXME: Don't use mu_set_program_name here, because it | 738 | /* FIXME: Don't use mu_set_program_name here, because it |
714 | plays wise with its argument. We need a mu_set_diag_prefix | 739 | plays wise with its argument. We need a mu_set_diag_prefix |
715 | function. */ | 740 | function. */ |
716 | mu_program_name = id; | 741 | mu_program_name = ws.ws_wordv[0]; |
742 | ws.ws_wordv[0] = NULL; | ||
743 | ws.ws_wordc = 0; | ||
744 | mu_wordsplit_free (&ws); | ||
717 | } | 745 | } |
718 | 746 | ||
719 | int | 747 | int |
... | ... |
-
Please register or sign in to post a comment