Commit ad938c5a ad938c5af5952cfbe1cb9782999a674eb5ceddbb by Sergey Poznyakoff

Simplify mu_cfg_tree_reduce.

This function used to handle include/program statements, which
is useless now, as these are expanded by mu_cfg_tree_postprocess.

* include/mailutils/cfg.h (mu_cfg_tree_reduce): Change signature.
(mu_format_config_tree): Change signature.
(mu_config_clone_root_container): New proto.
(mu_config_register_section): Rename to mu_config_root_register_section.
mu_config_container_register_section. All uses changed.
(mu_config_root_register_section): New proto.

* libmailutils/cfg/driver.c (prog_parser)
(_cb_include): Remove unnecessary code.
(mu_build_container): Simplify. All uses updated.
(mu_cfg_tree_reduce): Simplify invocation. All uses updated.

* libmu_argp/muinit.c (mu_app_init): Re-implement --config-help support.

* sieve/sieve.c (sieve_cfg_param): Fix docstring for "debug".
* sieve/tests/testsuite.at (MUT_SIEVE_DEFAULT_OPTIONS): New variable.
(MUT_SIEVE_CMDLINE): Include MUT_SIEVE_DEFAULT_OPTIONS.
(MUT_SIEVE_COMPILE): Pass MUT_SIEVE_DEFAULT_OPTIONS to sieve.
1 parent 4dda9b21
......@@ -211,6 +211,8 @@ struct mu_cfg_cidr
int mu_config_create_container (struct mu_cfg_cont **pcont,
enum mu_cfg_cont_type type);
int mu_config_clone_container (struct mu_cfg_cont *cont);
struct mu_cfg_cont *mu_config_clone_root_container (void);
void mu_config_destroy_container (struct mu_cfg_cont **pcont);
int mu_cfg_section_add_container (struct mu_cfg_section *sect,
......@@ -231,11 +233,19 @@ int mu_cfg_scan_tree (mu_cfg_tree_t *tree, struct mu_cfg_section *sections,
int mu_cfg_find_section (struct mu_cfg_section *root_sec,
const char *path, struct mu_cfg_section **retval);
int mu_config_register_section (const char *parent_path,
const char *ident,
const char *label,
mu_cfg_section_fp parser,
struct mu_cfg_param *param);
int mu_config_container_register_section (struct mu_cfg_cont **proot,
const char *parent_path,
const char *ident,
const char *label,
mu_cfg_section_fp parser,
struct mu_cfg_param *param,
struct mu_cfg_section **psection);
int mu_config_root_register_section (const char *parent_path,
const char *ident,
const char *label,
mu_cfg_section_fp parser,
struct mu_cfg_param *param);
int mu_config_register_plain_section (const char *parent_path,
const char *ident,
struct mu_cfg_param *params);
......@@ -274,11 +284,12 @@ void mu_cfg_format_node (mu_stream_t stream, const mu_cfg_node_t *node,
int flags);
void mu_cfg_format_container (mu_stream_t stream, struct mu_cfg_cont *cont);
void mu_format_config_tree (mu_stream_t stream, const char *progname,
struct mu_cfg_param *progparam, int flags);
int mu_cfg_tree_reduce (mu_cfg_tree_t *parse_tree, const char *progname,
void mu_format_config_tree (mu_stream_t stream,
struct mu_cfg_param *progparam);
int mu_cfg_tree_reduce (mu_cfg_tree_t *parse_tree,
struct mu_cfg_parse_hints *hints,
struct mu_cfg_param *progparam,
int flags, void *target_ptr);
void *target_ptr);
int mu_cfg_assert_value_type (mu_config_value_t *val, int type);
int mu_cfg_string_value_cb (mu_config_value_t *val,
int (*fun) (const char *, void *),
......
......@@ -340,13 +340,13 @@ mu_config_clone_container (struct mu_cfg_cont *cont)
int
_mu_config_register_section (struct mu_cfg_cont **proot,
const char *parent_path,
const char *ident,
const char *label,
mu_cfg_section_fp parser,
struct mu_cfg_param *param,
struct mu_cfg_section **psection)
mu_config_container_register_section (struct mu_cfg_cont **proot,
const char *parent_path,
const char *ident,
const char *label,
mu_cfg_section_fp parser,
struct mu_cfg_param *param,
struct mu_cfg_section **psection)
{
int rc;
struct mu_cfg_section *root_section;
......@@ -420,172 +420,54 @@ _mu_config_register_section (struct mu_cfg_cont **proot,
}
int
mu_config_register_section (const char *parent_path,
const char *ident,
const char *label,
mu_cfg_section_fp parser,
struct mu_cfg_param *param)
mu_config_root_register_section (const char *parent_path,
const char *ident,
const char *label,
mu_cfg_section_fp parser,
struct mu_cfg_param *param)
{
return _mu_config_register_section (&root_container,
parent_path,
ident, label,
parser, param, NULL);
return mu_config_container_register_section (&root_container,
parent_path,
ident, label,
parser, param, NULL);
}
int
mu_config_register_plain_section (const char *parent_path, const char *ident,
struct mu_cfg_param *params)
{
return mu_config_register_section (parent_path, ident, NULL, NULL, params);
}
static int
prog_parser (enum mu_cfg_section_stage stage,
const mu_cfg_node_t *node,
const char *label, void **section_data,
void *call_data,
mu_cfg_tree_t *tree)
{
if (stage == mu_cfg_section_start)
{
return node->label->type == MU_CFG_STRING
&& strcmp (node->label->v.string, label);
}
return 0;
}
struct include_data
{
const char *progname;
struct mu_cfg_param *progparam;
int flags;
void *target;
};
static int
_cb_include (void *data, mu_config_value_t *val)
{
int ret = 0;
struct stat sb;
const char *dirname;
struct include_data *idp = data;
char *tmp = NULL;
if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
return 1;
dirname = val->v.string;
if (dirname[0] != '/')
{
dirname = tmp = mu_make_file_name (SYSCONFDIR, dirname);
if (!dirname)
{
mu_error ("%s", mu_strerror (errno));
return 1;
}
}
if (stat (dirname, &sb) == 0)
{
if (S_ISDIR (sb.st_mode))
{
char *file = mu_make_file_name (dirname, idp->progname);
ret = mu_get_config (file, idp->progname, idp->progparam,
idp->flags & ~MU_PARSE_CONFIG_GLOBAL,
idp->target);
}
else
ret = mu_get_config (dirname, idp->progname, idp->progparam,
idp->flags, idp->target);
}
else if (errno == ENOENT)
{
mu_error (_("include file or directory does not exist"));
ret = 1;
}
else
{
mu_error (_("cannot stat include file or directory: %s"),
mu_strerror (errno));
ret = 1;
}
free (tmp);
return ret;
return mu_config_root_register_section (parent_path, ident, NULL, NULL,
params);
}
struct mu_cfg_cont *
mu_build_container (const char *progname, struct include_data *idp)
mu_config_clone_root_container (void)
{
struct mu_cfg_cont *cont = root_container;
mu_config_clone_container (cont);
if (idp->flags & MU_PARSE_CONFIG_PLAIN)
{
struct mu_cfg_param mu_include_param[] = {
{ "include", mu_cfg_callback, NULL, 0, _cb_include,
N_("Include contents of the given file. If a directory is given, "
"include contents of the file <file>/<program>, where "
"<program> is the name of the program. This latter form is "
"allowed only in the site-wide configuration file."),
N_("file-or-directory") },
{ NULL }
};
mu_include_param[0].data = idp;
_mu_config_register_section (&cont, NULL, NULL, NULL,
(void*) progname, mu_include_param, NULL);
if (idp->flags & MU_PARSE_CONFIG_GLOBAL)
{
mu_iterator_t iter;
struct mu_cfg_section *prog_sect;
struct mu_cfg_cont *old_root = root_container;
static struct mu_cfg_param empty_param = { NULL };
_mu_config_register_section (&cont, NULL, "program", progname,
prog_parser,
idp->progparam ?
idp->progparam : &empty_param,
&prog_sect);
if (old_root->v.section.children)
{
if (!prog_sect->children)
mu_list_create (&prog_sect->children);
mu_list_get_iterator (old_root->v.section.children, &iter);
for (mu_iterator_first (iter); !mu_iterator_is_done (iter);
mu_iterator_next (iter))
{
struct mu_cfg_cont *c;
mu_iterator_current (iter, (void**)&c);
mu_list_append (prog_sect->children, c);
}
mu_iterator_destroy (&iter);
}
}
else if (idp->progparam)
_mu_config_register_section (&cont, NULL, NULL, NULL, NULL,
idp->progparam, NULL);
}
else if (idp->progparam)
_mu_config_register_section (&cont, NULL, NULL, NULL, NULL,
idp->progparam, NULL);
return cont;
}
static struct mu_cfg_cont *
mu_build_container (struct mu_cfg_param *param)
{
struct mu_cfg_cont *cont = mu_config_clone_root_container ();
mu_config_container_register_section (&cont, NULL, NULL, NULL, NULL,
param, NULL);
return cont;
}
int
mu_cfg_tree_reduce (mu_cfg_tree_t *parse_tree, const char *progname,
struct mu_cfg_param *progparam, int flags,
mu_cfg_tree_reduce (mu_cfg_tree_t *parse_tree,
struct mu_cfg_parse_hints *hints,
struct mu_cfg_param *progparam,
void *target_ptr)
{
int rc = 0;
if (!parse_tree)
return 0;
if (flags & MU_PARSE_CONFIG_DUMP)
if (hints && (hints->flags & MU_PARSE_CONFIG_DUMP))
{
int yes = 1;
mu_stream_t stream;
......@@ -598,18 +480,9 @@ mu_cfg_tree_reduce (mu_cfg_tree_t *parse_tree, const char *progname,
if (root_container)
{
struct include_data idata;
struct mu_cfg_cont *cont;
idata.progname = progname;
idata.progparam = progparam;
idata.flags = flags;
idata.target = target_ptr;
cont = mu_build_container (progname, &idata);
struct mu_cfg_cont *cont = mu_build_container (progparam);
rc = mu_cfg_scan_tree (parse_tree, &cont->v.section, target_ptr,
(void*) progname);
NULL);
mu_config_destroy_container (&cont);
}
......@@ -617,17 +490,9 @@ mu_cfg_tree_reduce (mu_cfg_tree_t *parse_tree, const char *progname,
}
void
mu_format_config_tree (mu_stream_t stream, const char *progname,
struct mu_cfg_param *progparam, int flags)
mu_format_config_tree (mu_stream_t stream, struct mu_cfg_param *progparam)
{
struct include_data idata;
struct mu_cfg_cont *cont;
idata.progname = progname;
idata.progparam = progparam;
idata.flags = flags;
idata.target = NULL;
cont = mu_build_container (progname, &idata);
struct mu_cfg_cont *cont = mu_build_container (progparam);
mu_cfg_format_container (stream, cont);
mu_config_destroy_container (&cont);
}
......
......@@ -390,12 +390,11 @@ mu_get_config (const char *file, const char *progname,
struct mu_cfg_parse_hints hints;
hints.flags = flags | MU_CFG_PARSE_PROGRAM;
hints.program = progname;
hints.program = (char*)progname;
rc = mu_cfg_tree_postprocess (parse_tree, &hints);
if (rc == 0)
rc = mu_cfg_tree_reduce (parse_tree, progname, progparam, flags,
target_ptr);
rc = mu_cfg_tree_reduce (parse_tree, &hints, progparam, target_ptr);
mu_cfg_destroy_tree (&parse_tree);
}
......
......@@ -137,6 +137,16 @@ mu_app_init (struct argp *myargp, const char **capa,
char *comment;
char *canonical_name = get_canonical_name ();
mu_stream_t stream;
struct mu_cfg_cont *cont;
static struct mu_cfg_param dummy_include_param[] = {
{ "include", mu_cfg_string, NULL, 0, NULL,
N_("Include contents of the given file. If a directory is given, "
"include contents of the file <file>/<program>, where "
"<program> is the name of the program. This latter form is "
"allowed only in the site-wide configuration file."),
N_("file-or-directory") },
{ NULL }
};
mu_stdio_stream_create (&stream, MU_STDOUT_FD, 0);
......@@ -156,8 +166,15 @@ mu_app_init (struct argp *myargp, const char **capa,
canonical_name);
mu_cfg_format_docstring (stream, comment, 0);
free (comment);
cont = mu_config_clone_root_container ();
mu_config_container_register_section (&cont, NULL, NULL, NULL, NULL,
dummy_include_param, NULL);
mu_config_container_register_section (&cont, NULL, NULL, NULL, NULL,
cfg_param, NULL);
mu_cfg_format_container (stream, cont);
mu_config_destroy_container (&cont);
mu_format_config_tree (stream, mu_program_name, cfg_param, 0);
mu_stream_destroy (&stream);
exit (0);
}
......@@ -167,14 +184,16 @@ mu_app_init (struct argp *myargp, const char **capa,
{
struct mu_cfg_parse_hints hints = { MU_PARSE_CONFIG_PLAIN };
hints.flags |= MU_CFG_PARSE_PROGRAM;
hints.program = (char*)mu_program_name;
if (mu_cfg_parser_verbose)
hints.flags |= MU_PARSE_CONFIG_VERBOSE;
if (mu_cfg_parser_verbose > 1)
hints.flags |= MU_PARSE_CONFIG_DUMP;
mu_cfg_tree_postprocess (mu_argp_tree, &hints);
mu_cfg_tree_union (&parse_tree, &mu_argp_tree);
rc = mu_cfg_tree_reduce (parse_tree, mu_program_name, cfg_param,
hints.flags, data);
rc = mu_cfg_tree_reduce (parse_tree, &hints, cfg_param, data);
}
if (mu_rcfile_lint)
......
......@@ -79,8 +79,8 @@ mu_libcfg_init (char **cnames)
mu_error (_("unknown configuration group requested `%s'"),
cnames[i]);
else
mu_config_register_section (NULL, cp->name, NULL,
cp->parser, cp->cfgparam);
mu_config_root_register_section (NULL, cp->name, NULL,
cp->parser, cp->cfgparam);
}
}
}
......
......@@ -113,7 +113,6 @@ mutool_acl (int argc, char **argv)
mu_acl_result_t result;
mu_cfg_tree_t *tree = NULL, *temp_tree = NULL;
mu_cfg_node_t *node;
int flags = 0;
if (argp_parse (&acl_argp, argc, argv, ARGP_IN_ORDER, &index, NULL))
return 1;
......@@ -148,8 +147,7 @@ mutool_acl (int argc, char **argv)
mu_cfg_tree_create (&temp_tree);
mu_cfg_tree_add_node (temp_tree, node);
rc = mu_cfg_tree_reduce (temp_tree, mu_program_name, acl_cfg_param,
flags, NULL);
rc = mu_cfg_tree_reduce (temp_tree, NULL, acl_cfg_param, NULL);
if (rc)
return 1;
if (!acl)
......
......@@ -293,8 +293,8 @@ static struct mu_cfg_param sieve_cfg_param[] = {
N_("Debug flags. Argument consists of one or more of the following "
"flags:\n"
" g - main parser traces\n"
" T - mailutils traces (MU_DEBUG_TRACE0-MU_DEBUG_TRACE1)\n"
" P - network protocols (MU_DEBUG_PROT)\n"
" T - mailutils traces (sieve.trace9)\n"
" P - network protocols (sieve.prot)\n"
" t - sieve trace (MU_SIEVE_DEBUG_TRACE)\n"
" i - sieve instructions trace (MU_SIEVE_DEBUG_INSTR).") },
{ "verbose", mu_cfg_bool, &verbose, 0, NULL,
......@@ -467,7 +467,7 @@ main (int argc, char *argv[])
if (mu_app_init (&argp, sieve_argp_capa, sieve_cfg_param,
argc, argv, ARGP_IN_ORDER, NULL, NULL))
exit (EX_USAGE);
if (!script)
{
mu_error (_("script must be specified"));
......
......@@ -28,6 +28,12 @@ AT_CLEANUP
])
dnl ------------------------------------------------------------
m4_define([MUT_SIEVE_DEFAULT_OPTIONS],[dnl
--no-site-config dnl
--no-user-config dnl
])
dnl ------------------------------------------------------------
dnl MUT_SIEVE_OPTIONS -- additional command line options for Sieve
m4_define([MUT_SIEVE_OPTIONS])
......@@ -38,10 +44,9 @@ m4_define([MUT_SIEVE_MAILBOX],[sieve.mbox])
dnl ------------------------------------------------------------
m4_define([MUT_SIEVE_CMDLINE],[dnl
--verbose dnl
MUT_SIEVE_DEFAULT_OPTIONS dnl
--line-info=no dnl
--no-program-name dnl
--no-site-config dnl
--no-user-config dnl
-M sendmail:$abs_top_builddir/examples/mta dnl
--email foobar@nonexistent.net])
......@@ -53,7 +58,7 @@ dnl
m4_define([MUT_SIEVE_COMPILE],[
AT_DATA([prog],[$1
])
AT_CHECK([sieve MUT_SIEVE_OPTIONS -c prog],m4_shift($@))])
AT_CHECK([sieve MUT_SIEVE_DEFAULT_OPTIONS MUT_SIEVE_OPTIONS -c prog],m4_shift($@))])
dnl ------------------------------------------------------------
dnl MUT_SIEVE_RUN(SCRIPT, MBOX, [ADD-TEST = `'],
......