Commit f49d4057 f49d4057c49022a646c8dbe2d203e8c374bb7427 by Sergey Poznyakoff

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.
1 parent 5dd9e9c1
......@@ -35,8 +35,9 @@ struct mu_wordsplit
__attribute__ ((__format__ (__printf__, 1, 2)));
const char **ws_env;
char *(*ws_getvar) (const char *, size_t);
const char *(*ws_getvar) (const char *, size_t, void *);
void *ws_closure;
const char *ws_input;
size_t ws_len;
size_t ws_endp;
......@@ -103,6 +104,9 @@ struct mu_wordsplit
/* Handle C escapes */
#define MU_WRDSF_CESCAPES 0x1000000
/* ws_closure is set */
#define MU_WRDSF_CLOSURE 0x2000000
#define MU_WRDSF_DEFFLAGS \
(MU_WRDSF_NOVAR | MU_WRDSF_NOCMD | \
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,
wsp->ws_wordc = 0;
wsp->ws_wordn = 0;
}
if (wsp->ws_flags & MU_WRDSF_DOOFFS)
wsp->ws_wordn += wsp->ws_offs;
if (!(wsp->ws_flags & MU_WRDSF_CLOSURE))
wsp->ws_closure = NULL;
wsp->ws_endp = 0;
wsp->ws_errno = 0;
wsp->ws_head = wsp->ws_tail = NULL;
......@@ -311,7 +312,11 @@ wsnode_remove (struct mu_wordsplit *wsp, struct mu_wordsplit_node *node)
p = node->prev;
if (p)
p->next = node->next;
{
p->next = node->next;
if (!node->next)
p->flags &= ~_WSNF_JOIN;
}
else
wsp->ws_head = node->next;
......@@ -666,7 +671,7 @@ expvar (struct mu_wordsplit *wsp, const char *str, size_t len,
{
size_t i = 0;
const char *defstr = NULL;
char *value;
const char *value;
const char *vptr;
struct mu_wordsplit_node *newnode;
const char *start = str - 1;
......@@ -738,7 +743,7 @@ expvar (struct mu_wordsplit *wsp, const char *str, size_t len,
return _wsplt_nomem (wsp);
}
else if (wsp->ws_flags & MU_WRDSF_GETVAR)
value = wsp->ws_getvar (str, i);
value = wsp->ws_getvar (str, i, wsp->ws_closure);
else if (wsp->ws_flags & MU_WRDSF_UNDEF)
{
wsp->ws_errno = MU_WRDSE_UNDEF;
......@@ -822,6 +827,14 @@ expvar (struct mu_wordsplit *wsp, const char *str, size_t len,
memcpy (newnode->v.word, start, size);
newnode->v.word[size] = 0;
}
else
{
if (wsnode_new (wsp, &newnode))
return 1;
wsnode_insert (wsp, newnode, *ptail, 0);
*ptail = newnode;
newnode->flags = _WSNF_NULL;
}
return 0;
}
......
......@@ -650,70 +650,98 @@ _compare_uidls (const void *item, const void *value)
return strcmp (a->uidl, b->uidl);
}
struct movemail_getvar_closure
{
const char *source_name;
const char *dest_name;
mu_url_t source_url;
mu_url_t dest_url;
};
#define __cat2__(a,b) a ## b
#define DCL_VTX(what) \
static int \
__cat2__(_vtx_,what) (const char *name, void *data, char **p) \
{ \
mu_url_t url = data; \
int rc = __cat2__(mu_url_aget_,what) (url, p); \
if (rc == MU_ERR_NOENT) \
{ \
*p = strdup (""); \
return 0; \
} \
return rc; \
}
#define SEQ(s, n, l) \
(((l) == (sizeof(s) - 1)) && memcmp (s, n, l) == 0)
DCL_VTX (host)
DCL_VTX (user)
DCL_VTX (path)
static const char *
get_url_part (mu_url_t url, const char *name, size_t nlen)
{
int rc = MU_ERR_NOENT;
const char *s;
if (!url)
return NULL;
if (SEQ ("user", name, nlen))
rc = mu_url_sget_user (url, &s);
else if (SEQ ("host", name, nlen))
rc = mu_url_sget_host (url, &s);
else if (SEQ ("port", name, nlen))
rc = mu_url_sget_portstr (url, &s);
else if (SEQ ("path", name, nlen))
rc = mu_url_sget_path (url, &s);
if (rc)
return NULL;
return s;
}
static const char *
movemail_getvar (const char *name, size_t nlen, void *data)
{
struct movemail_getvar_closure *pc = data;
if (SEQ ("progname", name, nlen))
return mu_program_name;
if (SEQ ("source", name, nlen))
return pc->source_name;
if (SEQ ("dest", name, nlen))
return pc->dest_name;
if (nlen > 7 && memcmp ("source_", name, 7) == 0)
return get_url_part (pc->source_url, name + 7, nlen - 7);
if (nlen > 5 && memcmp ("dest_", name, 5) == 0)
return get_url_part (pc->dest_url, name + 5, nlen - 5);
return NULL;
}
static void
set_program_id (const char *source_name, const char *dest_name)
{
int rc;
mu_vartab_t vtab;
char *id;
mu_url_t url;
mu_vartab_create (&vtab);
mu_vartab_define (vtab, "progname", mu_program_name, 1);
mu_vartab_define (vtab, "source", source_name, 1);
rc = mu_mailbox_get_url (source, &url);
struct mu_wordsplit ws;
struct movemail_getvar_closure clos;
clos.source_name = source_name;
clos.dest_name = dest_name;
rc = mu_mailbox_get_url (source, &clos.source_url);
if (rc)
mu_diag_output (MU_DIAG_INFO,
_("cannot obtain source mailbox URL: %s"),
mu_strerror (rc));
else
{
mu_vartab_define_exp (vtab, "source:user", _vtx_user, NULL, url);
mu_vartab_define_exp (vtab, "source:host", _vtx_host, NULL, url);
mu_vartab_define_exp (vtab, "source:path", _vtx_path, NULL, url);
}
mu_vartab_define (vtab, "dest", dest_name, 1);
rc = mu_mailbox_get_url (dest, &url);
rc = mu_mailbox_get_url (dest, &clos.dest_url);
if (rc)
mu_diag_output (MU_DIAG_INFO,
_("cannot obtain destination mailbox URL: %s"),
mu_strerror (rc));
else
ws.ws_getvar = movemail_getvar;
ws.ws_closure = &clos;
if (mu_wordsplit (program_id_option, &ws,
MU_WRDSF_NOSPLIT | MU_WRDSF_NOCMD |
MU_WRDSF_GETVAR | MU_WRDSF_CLOSURE))
{
mu_vartab_define_exp (vtab, "dest:user", _vtx_user, NULL, url);
mu_vartab_define_exp (vtab, "dest:host", _vtx_host, NULL, url);
mu_vartab_define_exp (vtab, "dest:path", _vtx_path, NULL, url);
mu_error (_("cannot expand line `%s': %s"), program_id_option,
mu_wordsplit_strerror (&ws));
return;
}
rc = mu_vartab_expand (vtab, program_id_option, &id);
mu_vartab_destroy (&vtab);
/* mu_asprintf (&id, "%s: %s", mu_program_name, s);
free (s);*/
/* FIXME: Don't use mu_set_program_name here, because it
plays wise with its argument. We need a mu_set_diag_prefix
function. */
mu_program_name = id;
mu_program_name = ws.ws_wordv[0];
ws.ws_wordv[0] = NULL;
ws.ws_wordc = 0;
mu_wordsplit_free (&ws);
}
int
......