Commit 66f7ed95 66f7ed9562cce859f20166f9cf0c38a018a83dbe by Sergey Poznyakoff

Provide a way to discern between erroneous return and user-induced break conditi…

…on in foreach iterator functions

* libmailutils/diag/errors (MU_ERR_USER0-MU_ERR_USER7): New error constants.
Reserved for user's purposes, such as breaking from foreach iterators.
* libmaildutils/list/foreach.c (mu_list_foreach): Treat NULL list as a list
of 0 elements.
* libmailutils/list/foreachdir.c (mu_list_foreach_dir): Likewise.
* imap4d/imap4d.h (imap4d_auth_result): Remap constants to MU_ERR_USER[0-2]
* libmu_sieve/prog.c (mu_i_sv_lint_command): Use mu_list_locate with
the default comparator.
* mh/mh_list.c (_comp_name): Rewrite to match the definition of
mu_list_comparator_t
(mhl_format_run): Set _comp_name as comparator for the
env.printed_fields list.
(header_is_printed): Use mu_list_locate.

* imap4d/authenticate.c: Use MU_ERR_USER0-MU_ERR_USER7 to indicate
normal break condition in foreach iterators.
* imap4d/imap4d.c: Likewise.
* imap4d/namespace.c: Likewise.
* libmailutils/auth/auth.c: Likewise.
* libmailutils/cfg/driver.c: Likewise.
* libmailutils/cfg/parser.y: Likewise.
* libmailutils/server/acl.c: Likewise.
* libmailutils/server/msrv.c: Likewise.
* libmu_sieve/conf.c: Likewise.
* libmu_sieve/load.c: Likewise.
* libmu_sieve/sieve.l: Likewise.
* libmu_sieve/strexp.c: Likewise.
* libproto/imap/mbox.c: Likewise.
* libproto/imap/search.c: Likewise.
* mh/mh_format.c: Likewise.
* mh/send.c: Likewise.
* mh/sortm.c: Likewise.
* mimeview/mimetypes.y: Likewise.
* movemail/movemail.c: Likewise.
1 parent da63ec15
......@@ -96,7 +96,7 @@ imap4d_authenticate (struct imap4d_session *session,
{
char *auth_type;
struct imap4d_auth adata;
enum imap4d_auth_result res;
int res;
if (imap4d_tokbuf_argc (tok) != 3)
return io_completion_response (command, RESP_BAD, "Invalid arguments");
......@@ -136,6 +136,10 @@ imap4d_authenticate (struct imap4d_session *session,
case imap4d_auth_fail:
adata.response = RESP_NO;
break;
default:
adata.response = RESP_NO;
mu_error ("%s", mu_strerror (res));
}
return io_completion_response (command, adata.response,
"%s authentication failed", auth_type);
......
......@@ -340,11 +340,11 @@ check_user_groups (void *item, void *data)
return 0;
if (gp->gr_gid == auth_data->gid)
return MU_ERR_EXISTS;
return MU_ERR_USER0;
for (p = gp->gr_mem; *p; p++)
if (strcmp (*p, auth_data->name) == 0)
return MU_ERR_EXISTS;
return MU_ERR_USER0;
return 0;
}
......@@ -353,7 +353,7 @@ static int
imap_check_group_list (mu_list_t l)
{
int rc = mu_list_foreach (l, check_user_groups, NULL);
if (rc == MU_ERR_EXISTS)
if (rc == MU_ERR_USER0)
return 0;
else if (rc == 0)
return MU_ERR_NOENT;
......
......@@ -467,10 +467,10 @@ struct imap4d_auth
enum imap4d_auth_result
{
imap4d_auth_nosup,
imap4d_auth_ok,
imap4d_auth_resp,
imap4d_auth_fail
imap4d_auth_nosup = 0,
imap4d_auth_ok = MU_ERR_USER0,
imap4d_auth_resp = MU_ERR_USER1,
imap4d_auth_fail = MU_ERR_USER2
};
typedef enum imap4d_auth_result
......
......@@ -83,8 +83,18 @@ namespace_enumerate (int id, nsfp_t f, void *closure)
nsc.id = id;
nsc.fun = f;
nsc.closure = closure;
return namespace[id] == 0 ? 0 :
mu_list_foreach (namespace[id], _enum_fun, &nsc);
if (namespace[id])
{
int rc = mu_list_foreach (namespace[id], _enum_fun, &nsc);
if (rc == MU_ERR_USER0)
return 1;
else if (rc != 0)
{
mu_diag_funcall (MU_DIAG_ERROR, "mu_list_foreach", NULL, rc);
return 0;
}
}
return 0;
}
static int
......@@ -149,7 +159,7 @@ check_namespace (void *closure, int ns, char *path, int delim)
{
p->ns = ns;
p->exact = len == p->namelen;
return 1;
return MU_ERR_USER0;
}
return 0;
}
......
......@@ -123,7 +123,7 @@ try_auth (void *item, void *data)
if (authenticate (cb->authority) == 0)
{
cb->status = 0;
return 1;
return MU_ERR_USER0;
}
return 0;
}
......
......@@ -165,7 +165,13 @@ dup_container (struct mu_cfg_cont **pcont)
newcont->v.section.offset = oldcont->v.section.offset;
newcont->v.section.docstring = oldcont->v.section.docstring;
newcont->v.section.children = NULL;
mu_list_foreach (oldcont->v.section.children, _dup_cont_action, &dd);
rc = mu_list_foreach (oldcont->v.section.children, _dup_cont_action, &dd);
if (rc)
{
mu_diag_funcall (MU_DIAG_ERROR, "_dup_cont_action",
oldcont->v.section.ident, rc);
abort ();
}
break;
case mu_cfg_cont_param:
......@@ -325,8 +331,7 @@ mu_config_clone_container (struct mu_cfg_cont *cont)
switch (cont->type)
{
case mu_cfg_cont_section:
mu_list_foreach (cont->v.section.children, _clone_action, NULL);
break;
return mu_list_foreach (cont->v.section.children, _clone_action, NULL);
case mu_cfg_cont_param:
break;
......@@ -590,7 +595,6 @@ struct mapping_closure
{
mu_assoc_t assoc;
char *err_term;
int err;
};
static int
......@@ -600,6 +604,7 @@ parse_mapping (void *item, void *data)
char *str = item;
size_t len;
char *key, *val;
int rc;
len = strcspn (str, "=");
if (str[len] == 0)
......@@ -613,11 +618,9 @@ parse_mapping (void *item, void *data)
val = mu_strdup (str + len + 1);
if (!val)
return ENOMEM;
clos->err = mu_assoc_install (clos->assoc, key, val);
rc = mu_assoc_install (clos->assoc, key, val);
free (key);
if (clos->err)
return 1;
return 0;
return rc;
}
int
......@@ -655,10 +658,15 @@ mu_cfg_field_map (struct mu_config_value const *val, mu_assoc_t *passoc,
if (rc)
{
if (err_term)
*err_term = clos.err_term;
if (rc == MU_ERR_PARSE)
{
if (err_term)
*err_term = clos.err_term;
else
free (clos.err_term);
}
else
free (clos.err_term);
mu_error ("%s:%d: %s", __FILE__, __LINE__, mu_strerror (rc));
mu_assoc_destroy (&clos.assoc);
}
else
......
......@@ -565,7 +565,7 @@ mu_cfg_tree_postprocess (mu_cfg_tree_t *tree, struct mu_cfg_parse_hints *hints)
{
/* Reset the parent node */
mu_list_foreach (node->nodes, _node_set_parent,
node->parent);
node->parent);
/* Move all nodes from this block to the topmost
level */
mu_iterator_ctl (itr, mu_itrctl_insert_list,
......@@ -619,6 +619,7 @@ _mu_cfg_preorder_recursive (void *item, void *cbdata)
{
mu_cfg_node_t *node = item;
struct mu_cfg_iter_closure *clos = cbdata;
int rc;
switch (node->type)
{
......@@ -629,22 +630,24 @@ _mu_cfg_preorder_recursive (void *item, void *cbdata)
switch (clos->beg (node, clos->data))
{
case MU_CFG_ITER_OK:
if (mu_cfg_preorder (node->nodes, clos))
return 1;
rc = mu_cfg_preorder (node->nodes, clos);
if (rc)
return rc;
if (clos->end && clos->end (node, clos->data) == MU_CFG_ITER_STOP)
return 1;
return MU_ERR_USER0;
break;
case MU_CFG_ITER_SKIP:
break;
case MU_CFG_ITER_STOP:
return 1;
return MU_ERR_USER0;
}
break;
case mu_cfg_node_param:
return clos->beg (node, clos->data) == MU_CFG_ITER_STOP;
if (clos->beg (node, clos->data) == MU_CFG_ITER_STOP)
return MU_ERR_USER0;
}
return 0;
}
......@@ -1035,6 +1038,7 @@ mu_cfg_scan_tree (mu_cfg_tree_t *tree, struct mu_cfg_section *sections,
struct mu_cfg_iter_closure clos;
int save_mode = 0, mode;
struct mu_locus save_locus = { NULL, };
int rc;
dat.tree = tree;
dat.list = NULL;
......@@ -1055,9 +1059,10 @@ mu_cfg_scan_tree (mu_cfg_tree_t *tree, struct mu_cfg_section *sections,
clos.beg = _scan_tree_helper;
clos.end = _scan_tree_end_helper;
clos.data = &dat;
mu_cfg_preorder (tree->nodes, &clos);
rc = mu_cfg_preorder (tree->nodes, &clos);
pop_section (&dat);
if (rc && rc != MU_ERR_USER0)
dat.error++;
mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
MU_IOCTL_LOGSTREAM_SET_MODE, &save_mode);
mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
......@@ -1448,11 +1453,13 @@ mu_cfg_find_node (mu_cfg_tree_t *tree, const char *path, mu_cfg_node_t **pval)
clos.data = &data;
rc = mu_cfg_preorder (tree->nodes, &clos);
destroy_value (data.label);
if (rc)
if (rc == MU_ERR_USER0)
{
*pval = (mu_cfg_node_t *) data.node;
return 0;
}
else
mu_diag_funcall (MU_DIAG_ERR, "mu_cfg_preorder", NULL, rc);
}
return MU_ERR_NOENT;
}
......
......@@ -129,3 +129,14 @@ MU_ERR_FORMAT _("Error in format string")
MU_ERR_REMOVE_SOURCE _("Failed to remove source file")
MU_ERR_REMOVE_DEST _("Failed to remove destination file")
MU_ERR_RESTORE_META _("Failed to restore ownership or mode")
# User-defined errors are meant to be returned by foreach iterator
# callbacks when they need to break iterations.
MU_ERR_USER0 _("User-defined error 0")
MU_ERR_USER1 _("User-defined error 1")
MU_ERR_USER2 _("User-defined error 2")
MU_ERR_USER3 _("User-defined error 3")
MU_ERR_USER4 _("User-defined error 4")
MU_ERR_USER5 _("User-defined error 5")
MU_ERR_USER6 _("User-defined error 6")
MU_ERR_USER7 _("User-defined error 7")
......
......@@ -29,7 +29,9 @@ mu_list_foreach (mu_list_t list, mu_list_action_t action, void *cbdata)
mu_iterator_t itr;
int status = 0;
if (list == NULL || action == NULL)
if (list == NULL)
return 0;
if (action == NULL)
return EINVAL;
status = mu_list_get_iterator (list, &itr);
if (status)
......
......@@ -30,7 +30,9 @@ mu_list_foreach_dir (mu_list_t list, int dir,
mu_iterator_t itr;
int status = 0;
if (list == NULL || action == NULL)
if (list == NULL)
return 0;
if (action == NULL)
return EINVAL;
status = mu_list_get_iterator (list, &itr);
if (status)
......
......@@ -483,12 +483,12 @@ _run_entry (void *item, void *data)
{
case mu_acl_accept:
*rp->result = mu_acl_result_accept;
status = 1;
status = MU_ERR_USER0;
break;
case mu_acl_deny:
*rp->result = mu_acl_result_deny;
status = 1;
status = MU_ERR_USER0;
break;
case mu_acl_log:
......@@ -523,12 +523,12 @@ _run_entry (void *item, void *data)
{
case 0:
*rp->result = mu_acl_result_accept;
status = 1;
status = MU_ERR_USER0;
break;
case 1:
*rp->result = mu_acl_result_deny;
status = 1;
status = MU_ERR_USER0;
}
}
}
......@@ -573,9 +573,11 @@ mu_acl_check_sockaddr (mu_acl_t acl, const struct sockaddr *sa, int salen,
r.result = pres;
r.env = acl->envv;
*r.result = mu_acl_result_undefined;
mu_list_foreach (acl->aclist, _run_entry, &r);
rc = mu_list_foreach (acl->aclist, _run_entry, &r);
free (r.addrstr);
return 0;
if (rc == MU_ERR_USER0)
rc = 0;
return rc;
}
int
......
......@@ -216,7 +216,7 @@ m_server_cleanup (void *item, void *data)
mu_diag_output (MU_DIAG_ERR,
"process %lu terminated (cause unknown)",
(unsigned long) datp->pid);
return 1;
return MU_ERR_USER0;
}
return 0;
}
......
......@@ -50,9 +50,11 @@ _path_append (void *item, void *data)
{
mu_list_t *plist = data;
char *p;
int rc;
if (!*plist)
{
int rc = mu_list_create (plist);
rc = mu_list_create (plist);
if (rc)
{
mu_error (_("cannot create list: %s"), mu_strerror (rc));
......@@ -62,8 +64,15 @@ _path_append (void *item, void *data)
}
p = strdup (item);
if (!p)
return ENOMEM;
return mu_list_append (*plist, p);
rc = errno;
else
rc = mu_list_append (*plist, p);
if (rc)
{
mu_error (_("can't add directory to path: %s"), mu_strerror (rc));
exit (1);
}
return 0;
}
static int
......@@ -223,7 +232,8 @@ sieve_commit (void *ptr)
{
if (sieve_settings.clearflags & MU_SIEVE_CLEAR_INCLUDE_PATH)
mu_list_destroy (&mu_sieve_include_path);
mu_list_foreach (sieve_settings.include_path, _path_append, &mu_sieve_include_path);
mu_list_foreach (sieve_settings.include_path, _path_append,
&mu_sieve_include_path);
if (sieve_settings.clearflags & MU_SIEVE_CLEAR_LIBRARY_PATH)
{
mu_list_destroy (&mu_sieve_library_path);
......@@ -231,7 +241,8 @@ sieve_commit (void *ptr)
}
mu_list_foreach (sieve_settings.library_path_prefix, _path_append,
&mu_sieve_library_path_prefix);
mu_list_foreach (sieve_settings.library_path, _path_append, &mu_sieve_library_path);
mu_list_foreach (sieve_settings.library_path, _path_append,
&mu_sieve_library_path);
mu_list_destroy (&sieve_settings.library_path);
mu_list_destroy (&sieve_settings.library_path_prefix);
mu_list_destroy (&sieve_settings.include_path);
......
......@@ -34,7 +34,7 @@ typedef int (*sieve_module_init_t) (mu_sieve_machine_t mach);
static int _add_load_dir (void *, void *);
static int
sieve_init_load_path ()
sieve_init_load_path (void)
{
static int inited = 0;
......@@ -42,11 +42,14 @@ sieve_init_load_path ()
{
if (lt_dlinit ())
return 1;
mu_list_foreach (mu_sieve_library_path_prefix, _add_load_dir, NULL);
if (mu_list_foreach (mu_sieve_library_path_prefix, _add_load_dir, NULL))
return 1;
#ifdef MU_SIEVE_MODDIR
_add_load_dir (MU_SIEVE_MODDIR, NULL);
if (_add_load_dir (MU_SIEVE_MODDIR, NULL))
return 1;
#endif
mu_list_foreach (mu_sieve_library_path, _add_load_dir, NULL);
if (mu_list_foreach (mu_sieve_library_path, _add_load_dir, NULL))
return 1;
inited = 1;
}
return 0;
......@@ -122,7 +125,13 @@ mu_sieve_unload_ext (void *data)
static int
_add_load_dir (void *item, void *unused)
{
return lt_dladdsearchdir (item);
if (lt_dladdsearchdir (item))
{
mu_error (_("can't add dynamic library search directory: %s"),
lt_dlerror ());
return MU_ERR_FAILURE;
}
return 0;
}
int
......
......@@ -86,12 +86,6 @@ find_tag (mu_sieve_tag_group_t *taglist, char *tagname,
return NULL;
}
static int
_compare_ptr (void *item, void *data)
{
return item == data;
}
struct check_arg
{
struct mu_sieve_machine *mach;
......@@ -125,7 +119,7 @@ _run_checker (void *item, void *data)
mach->tagcount = 0;
mach->identifier = NULL;
return rc;
return rc ? MU_ERR_USER0 : 0;
}
void
......@@ -223,7 +217,7 @@ mu_i_sv_lint_command (struct mu_sieve_machine *mach,
err = 1;
break;
}
if (mu_list_foreach (chk_list, _compare_ptr, cf) == 0)
if (mu_list_locate (chk_list, cf, NULL) == MU_ERR_NOENT)
{
rc = mu_list_append (chk_list, cf);
if (rc)
......
......@@ -388,7 +388,7 @@ _try_include (void *item, void *data)
if (access (name, R_OK) == 0)
{
*(char**) data = name;
return 1;
return MU_ERR_USER0;
}
free (name);
return 0;
......
......@@ -200,11 +200,16 @@ string_split (struct stringbuf *buf)
static int
string_assemble (struct stringbuf *buf)
{
struct segm_stat st;
int rc;
struct segm_stat st;
st.len = 0;
st.end = 0;
mu_list_foreach (buf->seglist, update_len, &st);
rc = mu_list_foreach (buf->seglist, update_len, &st);
if (rc)
longjmp (buf->errbuf, rc);
if (st.end == buf->length - 1)
return MU_ERR_CANCELED;
......@@ -212,7 +217,14 @@ string_assemble (struct stringbuf *buf)
if (!buf->expansion)
longjmp (buf->errbuf, ENOMEM);
buf->endptr = buf->expansion;
mu_list_foreach (buf->seglist, append_segm, buf);
rc = mu_list_foreach (buf->seglist, append_segm, buf);
if (rc)
{
free (buf->expansion);
buf->expansion = NULL;
longjmp (buf->errbuf, rc);
}
*buf->endptr = 0;
return 0;
......
......@@ -1119,9 +1119,11 @@ sum_lines (void *item, void *data)
struct mu_bodystructure *bs = item;
size_t *pn = data;
size_t n;
if (_compute_lines (bs, &n))
return 1;
int rc;
rc = _compute_lines (bs, &n);
if (rc)
return rc;
*pn += n;
return 0;
}
......@@ -1146,7 +1148,7 @@ _compute_lines (struct mu_bodystructure *bs, size_t *pcount)
*pcount = 0;
return mu_list_foreach (bs->v.multipart.body_parts, sum_lines, pcount);
}
return 1;
return MU_ERR_USER0;
}
static int
......
......@@ -45,7 +45,7 @@ add_msgno (void *item, void *data)
mu_debug (MU_DEBCAT_MAILBOX, MU_DEBUG_ERROR,
(_("unexpected list element in untagged response from SEARCH")));
scp->retcode = MU_ERR_BADREPLY;
return 1;
return MU_ERR_USER0;
}
if (!scp->msgset)
......@@ -70,7 +70,7 @@ add_msgno (void *item, void *data)
(_("not a number in untagged response from SEARCH: %s"),
elt->v.string));
scp->retcode = MU_ERR_BADREPLY;
return 1;
return MU_ERR_USER0;
}
rc = mu_msgset_add_range (scp->msgset, num, num, MU_MSGSET_NUM);
......@@ -79,7 +79,7 @@ add_msgno (void *item, void *data)
mu_debug (MU_DEBCAT_MAILBOX, MU_DEBUG_ERROR,
("mu_msgset_add_range: %s", mu_strerror (rc)));
scp->retcode = rc;
return 1;
return MU_ERR_USER0;
}
return 0;
}
......
......@@ -447,7 +447,7 @@ addr_cmp (void *item, void *data)
continue;
rc = mu_address_contains_email (b, str);
}
return rc;
return rc ? MU_ERR_USER0 : 0;
}
static int
......
......@@ -466,15 +466,15 @@ static void goto_offset (struct eval_env *env, int count);
static void print (struct eval_env *env, char *str, int nloff);
static int
_comp_name (void *item, void *date)
_comp_name (void const *item, void const *date)
{
return mu_c_strcasecmp (item, date) == 0;
return mu_c_strcasecmp (item, date);
}
int
header_is_printed (struct eval_env *env, const char *name)
{
return mu_list_foreach (env->printed_fields, _comp_name, (void*) name) == 1;
return mu_list_locate (env->printed_fields, (void*) name, NULL) == 0;
}
int
......@@ -842,6 +842,7 @@ mhl_format_run (mu_list_t fmt,
env.bvar[B_NEWLINE] = 1;
mu_list_create (&env.printed_fields);
mu_list_set_comparator (env.printed_fields, _comp_name);
env.ivar[I_WIDTH] = width;
env.ivar[I_LENGTH] = length;
env.bvar[B_CLEARSCREEN] = flags & MHL_CLEARSCREEN;
......
......@@ -221,7 +221,7 @@ elt_fixup (void *item, void *data)
exit (1);
elt->msg = mh_file_to_message (NULL, elt->file_name);
if (!elt->msg)
return 1;
return MU_ERR_USER0;
return 0;
}
......@@ -633,7 +633,7 @@ _action_send (void *item, void *data)
mailer = open_mailer ();
if (!mailer)
return 1;
return MU_ERR_FAILURE;
WATCH ((_("Sending message %s"), elt->file_name));
if (split_message)
......@@ -650,7 +650,7 @@ _action_send (void *item, void *data)
if (rc)
{
mu_error(_("cannot send message: %s"), mu_strerror (rc));
return 1;
return MU_ERR_FAILURE;
}
WATCH ((_("Destroying the mailer")));
......
......@@ -286,7 +286,7 @@ compare_action (void *item, void *data)
free (a);
free (b);
return dp->r; /* go on until the difference is found */
return dp->r ? MU_ERR_USER0 : 0; /* go on until the difference is found */
}
static int
......
......@@ -693,7 +693,7 @@ evaluate (void *item, void *data)
if (eval_rule (p->node))
{
*ptype = p->type;
return 1;
return MU_ERR_USER0;
}
return 0;
}
......
......@@ -218,7 +218,7 @@ set_onerror_action (void *item, void *data)
if (mu_kwd_xlat_name (onerror_kw, str, &flag))
{
mu_error (_("unknown keyword: %s"), str);
return 1;
return MU_ERR_FAILURE;
}
if (clr)
onerror_flags &= ~flag;
......