Commit dc62b399 dc62b3998f0fe8ce0f131e269b130831093264fb by Sergey Poznyakoff

Improve configuration file handling.

* include/mailutils/cfg.h (mu_cfg_parse_hints):
Rename site_rcfile to site_file, custom_rcfile to custom_file.
Remove append_tree and data fields.
(MU_PARSE_CONFIG_GLOBAL,MU_CFG_PARSE_PROGRAM): Remove.
(MU_PARSE_CONFIG_VERBOSE): Rename to MU_CF_VERBOSE.
(MU_PARSE_CONFIG_DUMP): Rename to MU_CF_DUMP.
(MU_CFG_FMT_LOCUS): Rename to MU_CF_FMT_LOCUS.
(MU_CFG_FMT_VALUE_ONLY): Rename to MU_CF_FMT_VALUE_ONLY.
(MU_CFG_FMT_PARAM_PATH): Rename to MU_CF_FMT_PARAM_PATH.

(MU_CFG_COMPATIBILITY,MU_CFG_DEPRECATED): Remove.
(mu_parse_config, mu_get_config): Remove deprecated functions.

* libmailutils/cli/cli.c (mu_general_help_text): New global.
(app_data): New struct.
(init_options): Construct configuration option group depending on
which configuration files are in use.
(mu_cli_ext): Don't use per-user configuration files for servers.
Pass pointer to app_data structure as po.po_data
(mu_cli): Set MU_CFHINT_PER_USER_FILE flag by default.

* mail/testsuite/lib/mail.exp: Rewrite invocation of the mu_init command.
* include/mailutils/cli.h (mu_cli_setup) <server>: New field.

* comsat/comsat.c (cli): Mark as server.
(main): Bugfix: pass pointer to server to mu_cli.
* imap4d/imap4d.c (cli): Mark as server.
* pop3d/pop3d.c: Likewise.

* comsat/tests/testsuite.at: Use the --no-site-config
option.
* imap4d/tests/testsuite.at: Likewise.

* libmailutils/cfg/driver.c: Update.
* libmailutils/cfg/format.c: Update.
* libmailutils/cfg/lexer.l: Update.
* libmailutils/cfg/parser.y: Update.
* mu/acl.c: Update.

* pop3d/testsuite/lib/pop3d.exp: Likewise.

* mu/mu.c: Don't read configuration files.
* mu/query.c: Fix args_doc

* testsuite/lib/mailutils.exp (mu_init): Change option handling.
Set --no-config option by default.
1 parent b4c787e6
......@@ -194,11 +194,11 @@ struct mu_cfg_param comsat_cfg_param[] = {
static char const *alt_args[] = { N_("--test MBOX-URL MSG-QID"), NULL };
static struct mu_cli_setup cli = {
options,
comsat_cfg_param,
N_("GNU comsatd -- notify users about incoming mail"),
"",
alt_args,
.optv = options,
.cfg =comsat_cfg_param,
.prog_doc = N_("GNU comsatd -- notify users about incoming mail"),
.prog_alt_args = alt_args,
.server = 1
};
static char *capa[] = {
......@@ -568,7 +568,7 @@ main (int argc, char **argv)
save_argv = argv;
mu_cli (argc, argv, &cli, capa, NULL, &argc, &argv);
mu_cli (argc, argv, &cli, capa, server, &argc, &argv);
if (test_mode)
{
......
......@@ -22,7 +22,7 @@ m4_pushdef([BIFF_MBOX],[`pwd`/mailbox])
dnl ------------------------------------------------------------
dnl comsatcmd
m4_pushdef([comsatcmd],[comsatd --no-site --no-user --file ./biff.rc dnl
m4_pushdef([comsatcmd],[comsatd --no-site-config --file ./biff.rc dnl
--set logging.syslog=no --test])
dnl ------------------------------------------------------------
......
......@@ -449,9 +449,10 @@ static struct mu_cfg_param imap4d_cfg_param[] = {
};
struct mu_cli_setup cli = {
options,
imap4d_cfg_param,
N_("GNU imap4d -- the IMAP4D daemon.")
.optv = options,
.cfg = imap4d_cfg_param,
.prog_doc = N_("GNU imap4d -- the IMAP4D daemon."),
.server = 1
};
int
......@@ -659,7 +660,7 @@ get_client_address (int fd, struct sockaddr_in *pcs)
}
static int
set_strerr_flt ()
set_strerr_flt (void)
{
mu_stream_t flt, trans[2];
int rc;
......@@ -700,7 +701,7 @@ set_strerr_flt ()
}
static void
clr_strerr_flt ()
clr_strerr_flt (void)
{
mu_stream_t flt, trans[2];
int rc;
......
......@@ -20,7 +20,6 @@ m4_define([IMAP4D_HOMEDIR])
m4_define([IMAP4D_DEFAULT_OPTIONS],[dnl
--no-site-config dnl
--no-user-config dnl
--test dnl
--set logging.syslog=0 dnl
--set logging.severity=notice dnl
......
......@@ -76,13 +76,39 @@ struct mu_cfg_node
struct mu_cfg_parse_hints
{
int flags;
char *site_rcfile;
char *custom_rcfile;
char *site_file;
char *custom_file;
char *program;
struct mu_cfg_tree *append_tree;
void *data;
};
/* Bit constants for the flags field of struct mu_cfg_parse_hints */
/* Parse site-wide configuration file hints.site_file */
#define MU_CFHINT_SITE_FILE 0x0001
/* Parse custom configuration file hints.custom_file */
#define MU_CFHINT_CUSTOM_FILE 0x0002
/* The hints.program field is set. The "program PROGNAME" section
will be processed, if PROGNAME is the same as hints.program.
If include statement is used with the directory name DIR as its
argument, the file DIR/PROGNAME will be looked up and read in,
if it exists. */
#define MU_CFHINT_PROGRAM 0x0004
/* If MU_CFHINT_PROGRAM is set, look for the file ~/.PROGNAME after parsing
site-wide configuration */
#define MU_CFHINT_PER_USER_FILE 0x0008
/* Verbosely log files being processed */
#define MU_CF_VERBOSE 0x0010
/* Dump the pare tree on stderr */
#define MU_CF_DUMP 0x0020
/* Format location of the statement */
#define MU_CF_FMT_LOCUS 0x0100
/* Print only value */
#define MU_CF_FMT_VALUE_ONLY 0x0200
/* Print full parameter path */
#define MU_CF_FMT_PARAM_PATH 0x0400
struct mu_cfg_tree
{
mu_list_t nodes; /* a list of mu_cfg_node_t */
......@@ -140,9 +166,6 @@ struct mu_cfg_param
const char *argname;
};
#define MU_TARGET_REF(f) &f, 0
#define MU_TARGET_OFF(s,f) NULL, mu_offsetof(s,f)
enum mu_cfg_section_stage
{
mu_cfg_section_start,
......@@ -230,28 +253,6 @@ int mu_config_register_plain_section (const char *parent_path,
const char *ident,
struct mu_cfg_param *params);
#define MU_PARSE_CONFIG_GLOBAL 0x001
#define MU_PARSE_CONFIG_VERBOSE 0x002
#define MU_PARSE_CONFIG_DUMP 0x004
#define MU_PARSE_CONFIG_PLAIN 0x008
#define MU_CFG_PARSE_SITE_RCFILE 0x010
#define MU_CFG_PARSE_CUSTOM_RCFILE 0x020
#define MU_CFG_PARSE_PROGRAM 0x040
#define MU_CFG_FMT_LOCUS 0x080
#define MU_CFG_FMT_VALUE_ONLY 0x100
#define MU_CFG_FMT_PARAM_PATH 0x200
#define MU_PARSE_CONFIG_LINT 0x400
#define MU_CFG_APPEND_TREE 0x800
#ifdef MU_CFG_COMPATIBILITY
# define MU_CFG_DEPRECATED
#else
# define MU_CFG_DEPRECATED MU_DEPRECATED
#endif
int mu_parse_config (const char *file, const char *progname,
struct mu_cfg_param *progparam, int flags,
void *target_ptr) MU_CFG_DEPRECATED;
extern int mu_cfg_parser_verbose;
extern size_t mu_cfg_error_count;
......@@ -279,10 +280,6 @@ int mu_cfg_parse_file (mu_cfg_tree_t **return_tree, const char *file,
int flags);
int mu_get_config (const char *file, const char *progname,
struct mu_cfg_param *progparam, int flags,
void *target_ptr) MU_CFG_DEPRECATED;
int mu_cfg_tree_create (struct mu_cfg_tree **ptree);
mu_cfg_node_t *mu_cfg_tree_create_node (struct mu_cfg_tree *tree,
enum mu_cfg_node_type type,
......
......@@ -50,11 +50,14 @@ struct mu_cli_setup
int ex_usage; /* If not 0, exit code on usage errors */
int ex_config; /* If not 0, exit code on configuration
errors */
int inorder;
int inorder:1; /* Don't permute options and arguments */
int server:1; /* This is a server: don't read per-user
configuration files */
void (*prog_doc_hook) (mu_stream_t);
};
extern const char mu_version_copyright[];
extern const char mu_general_help_text[];
void mu_version_hook (struct mu_parseopt *po, mu_stream_t stream);
void mu_cli (int argc, char **argv, struct mu_cli_setup *setup,
......
......@@ -27,7 +27,6 @@
#include <ctype.h>
#include <mailutils/argcv.h>
#include <mailutils/nls.h>
#define MU_CFG_COMPATIBILITY /* This source uses deprecated cfg interfaces */
#include <mailutils/cfg.h>
#include <mailutils/errno.h>
#include <mailutils/error.h>
......@@ -466,14 +465,14 @@ mu_cfg_tree_reduce (mu_cfg_tree_t *parse_tree,
struct mu_cfg_cont *cont;
if (!parse_tree)
return 0;
if (hints && (hints->flags & MU_PARSE_CONFIG_DUMP))
if (hints && (hints->flags & MU_CF_DUMP))
{
int yes = 1;
mu_stream_t stream;
mu_stdio_stream_create (&stream, MU_STDERR_FD, 0);
mu_stream_ioctl (stream, MU_IOCTL_FD, MU_IOCTL_FD_SET_BORROW, &yes);
mu_cfg_format_parse_tree (stream, parse_tree, MU_CFG_FMT_LOCUS);
mu_cfg_format_parse_tree (stream, parse_tree, MU_CF_FMT_LOCUS);
mu_stream_destroy (&stream);
}
......@@ -492,29 +491,6 @@ mu_format_config_tree (mu_stream_t stream, struct mu_cfg_param *progparam)
mu_config_destroy_container (&cont);
}
int
mu_parse_config (const char *file, const char *progname,
struct mu_cfg_param *progparam, int flags,
void *target_ptr)
{
int rc;
char *full_name = mu_tilde_expansion (file, MU_HIERARCHY_DELIMITER, NULL);
if (full_name)
{
if (access (full_name, R_OK) == 0)
{
rc = mu_get_config (full_name, progname, progparam, flags,
target_ptr);
}
else
rc = ENOENT;
free (full_name);
}
else
rc = ENOMEM;
return rc;
}
static const char *
_first_value_ptr (mu_config_value_t *val)
{
......
......@@ -152,7 +152,7 @@ format_node (const mu_cfg_node_t *node, void *data)
{
struct tree_print *tp = data;
if ((tp->flags & MU_CFG_FMT_LOCUS) && node->locus.mu_file)
if ((tp->flags & MU_CF_FMT_LOCUS) && node->locus.mu_file)
mu_stream_printf (tp->stream, "# %lu \"%s\"\n",
(unsigned long) node->locus.mu_line,
node->locus.mu_file);
......@@ -165,7 +165,7 @@ format_node (const mu_cfg_node_t *node, void *data)
break;
case mu_cfg_node_statement:
if (tp->flags & MU_CFG_FMT_PARAM_PATH)
if (tp->flags & MU_CF_FMT_PARAM_PATH)
return MU_CFG_ITER_OK;
else
{
......@@ -181,9 +181,9 @@ format_node (const mu_cfg_node_t *node, void *data)
break;
case mu_cfg_node_param:
if (tp->flags & MU_CFG_FMT_VALUE_ONLY)
if (tp->flags & MU_CF_FMT_VALUE_ONLY)
format_value (tp, node->label);
else if (tp->flags & MU_CFG_FMT_PARAM_PATH)
else if (tp->flags & MU_CF_FMT_PARAM_PATH)
{
format_path (tp, node, ':');
mu_stream_write (tp->stream, " ", 1, NULL);
......@@ -209,7 +209,7 @@ static int
format_node_end (const mu_cfg_node_t *node, void *data)
{
struct tree_print *tp = data;
if (!(tp->flags & MU_CFG_FMT_PARAM_PATH))
if (!(tp->flags & MU_CF_FMT_PARAM_PATH))
{
tp->level--;
format_level (tp->stream, tp->level);
......@@ -242,7 +242,7 @@ mu_cfg_format_node (mu_stream_t stream, const mu_cfg_node_t *node, int flags)
struct tree_print t;
if (node->type == mu_cfg_node_statement)
flags &= ~MU_CFG_FMT_VALUE_ONLY;
flags &= ~MU_CF_FMT_VALUE_ONLY;
t.flags = flags;
t.level = 0;
t.stream = stream;
......
......@@ -330,14 +330,14 @@ mu_cfg_parse_file (mu_cfg_tree_t **return_tree, const char *file, int flags)
int rc;
char *full_name = mu_tilde_expansion (file, MU_HIERARCHY_DELIMITER, NULL);
if (flags & MU_PARSE_CONFIG_VERBOSE)
if (flags & MU_CF_VERBOSE)
mu_diag_output (MU_DIAG_INFO, _("opening configuration file %s"),
full_name);
if (stat (full_name, &st))
{
if (errno != ENOENT)
mu_error (_("cannot stat `%s': %s"), full_name, mu_strerror (errno));
else if (flags & MU_PARSE_CONFIG_VERBOSE)
else if (flags & MU_CF_VERBOSE)
mu_diag_output (MU_DIAG_INFO, _("configuration file %s doesn't exist"),
full_name);
free (full_name);
......@@ -345,7 +345,7 @@ mu_cfg_parse_file (mu_cfg_tree_t **return_tree, const char *file, int flags)
}
else if (!S_ISREG (st.st_mode))
{
if (flags & MU_PARSE_CONFIG_VERBOSE)
if (flags & MU_CF_VERBOSE)
mu_diag_output (MU_DIAG_INFO, _("%s: not a regular file"), full_name);
free (full_name);
return ENOENT;
......@@ -360,7 +360,7 @@ mu_cfg_parse_file (mu_cfg_tree_t **return_tree, const char *file, int flags)
return errno;
}
if (flags & MU_PARSE_CONFIG_VERBOSE)
if (flags & MU_CF_VERBOSE)
mu_diag_output (MU_DIAG_INFO, _("parsing file `%s'"), full_name);
mu_cfg_set_lex_debug ();
......@@ -379,37 +379,13 @@ mu_cfg_parse_file (mu_cfg_tree_t **return_tree, const char *file, int flags)
yyrestart (fp);
rc = mu_cfg_parse (return_tree);
fclose (fp);
if (flags & MU_PARSE_CONFIG_VERBOSE)
if (flags & MU_CF_VERBOSE)
mu_diag_output (MU_DIAG_INFO, _("finished parsing file `%s'"),
mu_cfg_locus.mu_file);
return rc == 0 ? 0 : MU_ERR_FAILURE;
}
/* FIXME: Deprecated interface */
int
mu_get_config (const char *file, const char *progname,
struct mu_cfg_param *progparam, int flags, void *target_ptr)
{
mu_cfg_tree_t *parse_tree;
int rc = mu_cfg_parse_file (&parse_tree, file, flags);
if (rc == 0)
{
struct mu_cfg_parse_hints hints;
hints.flags = flags | MU_CFG_PARSE_PROGRAM;
hints.program = (char*)progname;
rc = mu_cfg_tree_postprocess (parse_tree, &hints);
if (rc == 0)
rc = mu_cfg_tree_reduce (parse_tree, &hints, progparam, target_ptr);
mu_cfg_destroy_tree (&parse_tree);
}
return rc == 0 ? 0 : MU_ERR_FAILURE;
}
mu_opool_t
mu_cfg_lexer_pool ()
{
......
......@@ -501,8 +501,7 @@ do_include (const char *name, struct mu_cfg_parse_hints *hints,
if (S_ISDIR (sb.st_mode))
{
if ((hints->flags & (MU_PARSE_CONFIG_GLOBAL|MU_CFG_PARSE_PROGRAM)) ==
(MU_PARSE_CONFIG_GLOBAL|MU_CFG_PARSE_PROGRAM))
if (hints->flags & MU_CFHINT_PROGRAM)
{
char *file = mu_make_file_name (name, hints->program);
rc = mu_cfg_parse_file (&tree, file, hints->flags);
......@@ -515,7 +514,7 @@ do_include (const char *name, struct mu_cfg_parse_hints *hints,
if (rc == 0 && tree)
{
struct mu_cfg_parse_hints xhints = *hints;
xhints.flags &= ~MU_PARSE_CONFIG_GLOBAL;
xhints.flags &= ~MU_CFHINT_PROGRAM;
mu_cfg_tree_postprocess (tree, &xhints);
}
}
......@@ -538,8 +537,7 @@ do_include (const char *name, struct mu_cfg_parse_hints *hints,
}
int
mu_cfg_tree_postprocess (mu_cfg_tree_t *tree,
struct mu_cfg_parse_hints *hints)
mu_cfg_tree_postprocess (mu_cfg_tree_t *tree, struct mu_cfg_parse_hints *hints)
{
int rc;
mu_iterator_t itr;
......@@ -558,13 +556,12 @@ mu_cfg_tree_postprocess (mu_cfg_tree_t *tree,
if (node->type == mu_cfg_node_statement)
{
if ((hints->flags & MU_PARSE_CONFIG_GLOBAL) &&
if ((hints->flags & MU_CFHINT_PROGRAM) &&
strcmp (node->tag, "program") == 0)
{
if (node->label->type == MU_CFG_STRING)
{
if ((hints->flags & MU_CFG_PARSE_PROGRAM)
&& strcmp (node->label->v.string, hints->program) == 0)
if (strcmp (node->label->v.string, hints->program) == 0)
{
/* Reset the parent node */
mu_list_foreach (node->nodes, _node_set_parent,
......@@ -1527,10 +1524,11 @@ mu_cfg_parse_config (mu_cfg_tree_t **ptree, struct mu_cfg_parse_hints *hints)
{
int rc = 0;
mu_cfg_tree_t *tree = NULL, *tmp;
struct mu_cfg_parse_hints xhints;
if ((hints->flags & MU_CFG_PARSE_SITE_RCFILE) && hints->site_rcfile)
if ((hints->flags & MU_CFHINT_SITE_FILE) && hints->site_file)
{
rc = mu_cfg_parse_file (&tmp, hints->site_rcfile, hints->flags);
rc = mu_cfg_parse_file (&tmp, hints->site_file, hints->flags);
if (rc == ENOMEM)
{
......@@ -1539,14 +1537,16 @@ mu_cfg_parse_config (mu_cfg_tree_t **ptree, struct mu_cfg_parse_hints *hints)
}
else if (rc == 0)
{
struct mu_cfg_parse_hints xhints = *hints;
xhints.flags |= MU_PARSE_CONFIG_GLOBAL;
mu_cfg_tree_postprocess (tmp, &xhints);
mu_cfg_tree_postprocess (tmp, hints);
mu_cfg_tree_union (&tree, &tmp);
}
}
if ((hints->flags & MU_CFG_PARSE_PROGRAM) && hints->program)
xhints = *hints;
xhints.flags &= ~MU_CFHINT_PROGRAM;
if ((hints->flags & MU_CFHINT_PER_USER_FILE)
&& (hints->flags & MU_CFHINT_PROGRAM))
{
size_t size = 3 + strlen (hints->program) + 1;
char *file_name = malloc (size);
......@@ -1555,7 +1555,7 @@ mu_cfg_parse_config (mu_cfg_tree_t **ptree, struct mu_cfg_parse_hints *hints)
strcpy (file_name, "~/.");
strcat (file_name, hints->program);
rc = mu_cfg_parse_file (&tmp, file_name, hints->flags);
rc = mu_cfg_parse_file (&tmp, file_name, xhints.flags);
if (rc == ENOMEM)
{
mu_error ("%s", mu_strerror (rc));
......@@ -1564,7 +1564,7 @@ mu_cfg_parse_config (mu_cfg_tree_t **ptree, struct mu_cfg_parse_hints *hints)
}
else if (rc == 0)
{
mu_cfg_tree_postprocess (tmp, hints);
mu_cfg_tree_postprocess (tmp, &xhints);
mu_cfg_tree_union (&tree, &tmp);
}
else if (rc == ENOENT)
......@@ -1573,26 +1573,23 @@ mu_cfg_parse_config (mu_cfg_tree_t **ptree, struct mu_cfg_parse_hints *hints)
}
}
if ((hints->flags & MU_CFG_PARSE_CUSTOM_RCFILE) && hints->custom_rcfile)
if ((hints->flags & MU_CFHINT_CUSTOM_FILE) && hints->custom_file)
{
rc = mu_cfg_parse_file (&tmp, hints->custom_rcfile, hints->flags);
rc = mu_cfg_parse_file (&tmp, hints->custom_file, xhints.flags);
if (rc)
{
mu_error (_("errors parsing file %s: %s"), hints->custom_rcfile,
mu_error (_("errors parsing file %s: %s"), hints->custom_file,
mu_strerror (rc));
mu_cfg_destroy_tree (&tree);
return rc;
}
else
{
mu_cfg_tree_postprocess (tmp, hints);
mu_cfg_tree_postprocess (tmp, &xhints);
mu_cfg_tree_union (&tree, &tmp);
}
}
if (hints->flags & MU_CFG_APPEND_TREE)
mu_cfg_tree_union (&tree, &hints->append_tree);
*ptree = tree;
return rc;
}
......
......@@ -76,23 +76,29 @@ There is NO WARRANTY, to the extent permitted by law.\n\
"));
}
static char gnu_general_help_url[] =
const char mu_general_help_text[] =
N_("General help using GNU software: <http://www.gnu.org/gethelp/>");
struct app_data
{
struct mu_cli_setup *setup;
struct mu_cfg_parse_hints *hints;
struct mu_cfg_tree *append_tree;
int lint;
};
static void
extra_help_hook (struct mu_parseopt *po, mu_stream_t stream)
{
struct mu_cfg_parse_hints *hints = po->po_data;
struct mu_cli_setup *setup = hints->data;
mu_stream_printf (stream, "%s\n", _(setup->prog_extra_doc));
struct app_data *dp = po->po_data;
mu_stream_printf (stream, "%s\n", gettext (dp->setup->prog_extra_doc));
}
static void
prog_doc_hook (struct mu_parseopt *po, mu_stream_t stream)
{
struct mu_cfg_parse_hints *hints = po->po_data;
struct mu_cli_setup *setup = hints->data;
setup->prog_doc_hook (stream);
struct app_data *dp = po->po_data;
dp->setup->prog_doc_hook (stream);
}
static void
......@@ -100,87 +106,108 @@ change_progname (struct mu_parseopt *po, struct mu_option *opt,
char const *arg)
{
po->po_prog_name = mu_strdup (arg);
free (mu_program_name);
mu_program_name = mu_strdup (arg);
}
static void
no_user_config (struct mu_parseopt *po, struct mu_option *opt,
char const *arg)
{
struct mu_cfg_parse_hints *hints = po->po_data;
hints->flags &= ~MU_CFG_PARSE_PROGRAM;
struct app_data *dp = po->po_data;
dp->hints->flags &= ~MU_CFHINT_PER_USER_FILE;
}
static void
no_site_config (struct mu_parseopt *po, struct mu_option *opt,
char const *arg)
{
struct mu_cfg_parse_hints *hints = po->po_data;
hints->flags &= ~MU_CFG_PARSE_SITE_RCFILE;
struct app_data *dp = po->po_data;
dp->hints->flags &= ~MU_CFHINT_SITE_FILE;
}
static void
no_config (struct mu_parseopt *po, struct mu_option *opt, char const *arg)
{
struct app_data *dp = po->po_data;
dp->hints->flags &= ~(MU_CFHINT_SITE_FILE|MU_CFHINT_PER_USER_FILE);
}
static void
config_file (struct mu_parseopt *po, struct mu_option *opt,
char const *arg)
{
struct mu_cfg_parse_hints *hints = po->po_data;
hints->flags |= MU_CFG_PARSE_CUSTOM_RCFILE;
hints->custom_rcfile = mu_strdup (arg);
struct app_data *dp = po->po_data;
dp->hints->flags = (dp->hints->flags
& ~(MU_CFHINT_SITE_FILE|MU_CFHINT_PROGRAM))
| MU_CFHINT_CUSTOM_FILE;
dp->hints->custom_file = mu_strdup (arg);
}
static void
config_verbose (struct mu_parseopt *po, struct mu_option *opt,
char const *arg)
{
struct mu_cfg_parse_hints *hints = po->po_data;
if (hints->flags & MU_PARSE_CONFIG_VERBOSE)
hints->flags |= MU_PARSE_CONFIG_DUMP;
struct app_data *dp = po->po_data;
if (dp->hints->flags & MU_CF_VERBOSE)
dp->hints->flags |= MU_CF_DUMP;
else
hints->flags |= MU_PARSE_CONFIG_VERBOSE;
dp->hints->flags |= MU_CF_VERBOSE;
}
static void
config_lint (struct mu_parseopt *po, struct mu_option *opt,
char const *arg)
{
struct mu_cfg_parse_hints *hints = po->po_data;
hints->flags |= MU_PARSE_CONFIG_VERBOSE|MU_PARSE_CONFIG_LINT;
struct app_data *dp = po->po_data;
dp->lint = 1;
dp->hints->flags |= MU_CF_VERBOSE;
}
static void
param_set (struct mu_parseopt *po, struct mu_option *opt, char const *arg)
{
struct mu_cfg_parse_hints *hints = po->po_data;
struct app_data *dp = po->po_data;
mu_cfg_node_t *node;
int rc = mu_cfg_create_subtree (arg, &node);
if (rc)
mu_parseopt_error (po, "%s: cannot create node: %s",
arg, mu_strerror (rc));
if (!(hints->flags & MU_CFG_APPEND_TREE))
if (!dp->append_tree)
{
mu_cfg_tree_create (&hints->append_tree);
hints->flags |= MU_CFG_APPEND_TREE;
mu_cfg_tree_create (&dp->append_tree);
}
mu_cfg_tree_add_node (hints->append_tree, node);
mu_cfg_tree_add_node (dp->append_tree, node);
}
struct mu_option mu_common_options[] = {
MU_OPTION_GROUP(N_("Common options")),
/* MU_OPTION_GROUP(N_("Common options")),*/
{ "program-name", 0, N_("NAME"), MU_OPTION_IMMEDIATE|MU_OPTION_HIDDEN,
N_("set program name"),
mu_c_string, NULL, change_progname },
MU_OPTION_END
};
{ "no-user-config", 0, NULL, MU_OPTION_IMMEDIATE,
N_("do not load user configuration file"),
mu_c_string, NULL, no_user_config },
{ "no-user-rcfile", 0, NULL, MU_OPTION_ALIAS },
struct mu_option mu_config_option_header =
MU_OPTION_GROUP (N_("Configuration handling"));
struct mu_option mu_site_config_options[] = {
{ "no-site-config", 0, NULL, MU_OPTION_IMMEDIATE,
N_("do not load site-wide configuration file"),
mu_c_string, NULL, no_site_config },
{ "no-site-rcfile", 0, NULL, MU_OPTION_ALIAS },
MU_OPTION_END
};
struct mu_option mu_no_config_option = {
"no-config", 0, NULL, MU_OPTION_IMMEDIATE,
N_("do not load site and user configuration files"),
mu_c_string, NULL, no_config
};
struct mu_option mu_config_options[] = {
{ "config-file", 0, N_("FILE"), MU_OPTION_IMMEDIATE,
N_("load this configuration file"),
N_("load this configuration file; implies --no-config"),
mu_c_string, NULL, config_file },
{ "rcfile", 0, NULL, MU_OPTION_ALIAS },
......@@ -201,6 +228,14 @@ struct mu_option mu_common_options[] = {
MU_OPTION_END
};
struct mu_option mu_user_config_options[] = {
{ "no-user-config", 0, NULL, MU_OPTION_IMMEDIATE,
N_("do not load user configuration file"),
mu_c_string, NULL, no_user_config },
{ "no-user-rcfile", 0, NULL, MU_OPTION_ALIAS },
MU_OPTION_END
};
static void
show_comp_defaults (struct mu_parseopt *po, struct mu_option *opt,
char const *unused)
......@@ -213,7 +248,7 @@ static void
show_config_help (struct mu_parseopt *po, struct mu_option *opt,
char const *unused)
{
struct mu_cfg_parse_hints *hints = po->po_data;
struct app_data *dp = po->po_data;
char *comment;
mu_stream_t stream;
......@@ -253,11 +288,10 @@ show_config_help (struct mu_parseopt *po, struct mu_option *opt,
cont = mu_config_clone_root_container ();
mu_config_container_register_section (&cont, NULL, NULL, NULL, NULL,
dummy_include_param, NULL);
if (hints->data)
if (dp->setup)
{
struct mu_cli_setup *setup = hints->data;
mu_config_container_register_section (&cont, NULL, NULL, NULL, NULL,
setup->cfg, NULL);
dp->setup->cfg, NULL);
}
mu_cfg_format_container (stream, cont);
......@@ -267,11 +301,15 @@ show_config_help (struct mu_parseopt *po, struct mu_option *opt,
exit (0);
}
struct mu_option mu_extra_help_options[] = {
static struct mu_option mu_extra_help_options[] = {
MU_OPTION_GROUP (N_("Informational options")),
{ "show-config-options", 0, NULL, MU_OPTION_IMMEDIATE,
N_("show compilation options"),
mu_c_string, NULL, show_comp_defaults },
MU_OPTION_END
};
static struct mu_option mu_config_help_options[] = {
{ "config-help", 0, NULL, MU_OPTION_IMMEDIATE,
N_("show configuration file summary"),
mu_c_string, NULL, show_config_help },
......@@ -288,9 +326,38 @@ add_opt_group (void *item, void *data)
return 0;
}
#define CONFIG_ENABLED \
(MU_CFHINT_SITE_FILE | MU_CFHINT_CUSTOM_FILE | MU_CFHINT_PER_USER_FILE)
static void
opool_add_option (mu_opool_t pool, struct mu_option *opt)
{
mu_opool_append (pool, opt, sizeof *opt);
}
static void
opool_add_options (mu_opool_t pool, struct mu_option *opt)
{
while (!MU_OPTION_IS_END (opt))
{
opool_add_option (pool, opt);
opt++;
}
}
static struct mu_option *
opool_end_option (mu_opool_t pool)
{
struct mu_option end = MU_OPTION_END;
opool_add_option (pool, &end);
return mu_opool_finish (pool, NULL);
}
/* Build the list of option groups and configuration sections */
static struct mu_option **
init_options (char **capa, struct mu_cli_setup *setup,
init_options (mu_opool_t pool,
char **capa, struct mu_cli_setup *setup,
struct mu_cfg_parse_hints const *hints,
mu_list_t *ret_comlist)
{
size_t i, s;
......@@ -316,7 +383,40 @@ init_options (char **capa, struct mu_cli_setup *setup,
*ret_comlist = comlist;
mu_list_append (oplist, mu_common_options);
/* Construct configuration option section */
if (hints->flags & CONFIG_ENABLED)
{
opool_add_option (pool, &mu_config_option_header);
opool_add_options (pool, mu_config_options);
if (hints->flags & MU_CFHINT_SITE_FILE)
{
opool_add_options (pool, mu_site_config_options);
if (hints->flags & MU_CFHINT_PER_USER_FILE)
{
opool_add_options (pool, mu_user_config_options);
opool_add_option (pool, &mu_no_config_option);
}
else
{
struct mu_option opt = mu_no_config_option;
opt.opt_flags = MU_OPTION_ALIAS;
opool_add_option (pool, &opt);
}
}
else if (hints->flags & MU_CFHINT_PER_USER_FILE)
{
struct mu_option opt = mu_no_config_option;
opool_add_options (pool, mu_user_config_options);
opt.opt_flags = MU_OPTION_ALIAS;
opool_add_option (pool, &opt);
}
mu_list_append (oplist, opool_end_option (pool));
}
mu_list_append (oplist, mu_extra_help_options);
if (hints->flags & CONFIG_ENABLED)
mu_list_append (oplist, mu_config_help_options);
mu_list_count (oplist, &s);
......@@ -367,6 +467,8 @@ mu_cli_ext (int argc, char **argv,
char const *dfl_args[DFLARGC];
char **args = NULL;
size_t argcnt;
struct app_data appd;
mu_opool_t pool;
/* Set up defaults */
if (setup->ex_usage == 0)
......@@ -375,10 +477,11 @@ mu_cli_ext (int argc, char **argv,
setup->ex_config = EX_CONFIG;
hints = *cfhint;
hints.data = setup;
if (setup->server)
hints.flags &= ~MU_CFHINT_PER_USER_FILE;
/* Set program name */
if (hints.flags & MU_CFG_PARSE_PROGRAM)
if (hints.flags & MU_CFHINT_PROGRAM)
{
if (!mu_log_tag)
mu_log_tag = (char*)hints.program;
......@@ -389,7 +492,7 @@ mu_cli_ext (int argc, char **argv,
if (!mu_log_tag)
mu_log_tag = (char*)mu_program_name;
hints.program = (char*) mu_program_name;
hints.flags |= MU_CFG_PARSE_PROGRAM;
hints.flags |= MU_CFHINT_PROGRAM;
}
/* Initialize standard streams */
......@@ -478,12 +581,17 @@ mu_cli_ext (int argc, char **argv,
if (flags & MU_PARSEOPT_NEGATION)
po.po_negation = pohint->po_negation;
po.po_data = &hints;
appd.setup = setup;
appd.hints = &hints;
appd.append_tree = NULL;
appd.lint = 0;
po.po_data = &appd;
flags |= MU_PARSEOPT_DATA;
po.po_exit_error = setup->ex_usage;
optv = init_options (capa, setup, &com_list);
mu_opool_create (&pool, MU_OPOOL_ENOMEMABRT);
optv = init_options (pool, capa, setup, &hints, &com_list);
if (mu_parseopt (&po, argc, argv, optv, flags))
exit (po.po_exit_error);
......@@ -502,6 +610,9 @@ mu_cli_ext (int argc, char **argv,
if (mu_cfg_parse_config (&parse_tree, &hints))
exit (setup->ex_config);
if (appd.append_tree)
mu_cfg_tree_union (&parse_tree, &appd.append_tree);
if (mu_cfg_tree_reduce (parse_tree, &hints, setup->cfg, data))
exit (setup->ex_config);
......@@ -513,15 +624,14 @@ mu_cli_ext (int argc, char **argv,
mu_list_foreach (com_list, run_commit, NULL);
mu_list_destroy (&com_list);
if (hints.flags & MU_PARSE_CONFIG_LINT)
exit (0);
mu_cfg_destroy_tree (&parse_tree);
free (optv);
free (args);
mu_parseopt_free (&po);
mu_opool_destroy (&pool);
if (appd.lint)
exit (0);
}
void
......@@ -543,14 +653,14 @@ mu_cli (int argc, char **argv, struct mu_cli_setup *setup, char **capa,
pohint.po_bug_address = PACKAGE_BUGREPORT;
pohint.po_flags |= MU_PARSEOPT_BUG_ADDRESS;
pohint.po_extra_info = gnu_general_help_url;
pohint.po_extra_info = mu_general_help_text;
pohint.po_flags |= MU_PARSEOPT_EXTRA_INFO;
pohint.po_version_hook = mu_version_hook;
pohint.po_flags |= MU_PARSEOPT_VERSION_HOOK;
cfhint.site_rcfile = mu_site_config_file ();
cfhint.flags = MU_CFG_PARSE_SITE_RCFILE;
cfhint.site_file = mu_site_config_file ();
cfhint.flags = MU_CFHINT_SITE_FILE | MU_CFHINT_PER_USER_FILE;
mu_cli_ext (argc, argv, setup, &pohint, &cfhint, capa, data,
ret_argc, ret_argv);
......
......@@ -18,7 +18,7 @@
source $top_srcdir/testsuite/lib/mailutils.exp
mu_init "--nosum --norc"
mu_init --nosum --norc
#FIXME: this doesn't work with remote testing
set env(MAILRC) $MU_RC_DIR/mail.rc
......
......@@ -58,8 +58,8 @@ mutool_acl (int argc, char **argv)
}
memset (&hints, 0, sizeof (hints));
hints.flags = MU_CFG_PARSE_CUSTOM_RCFILE;
hints.custom_rcfile = input_file_name;
hints.flags = MU_CFHINT_CUSTOM_FILE;
hints.custom_file = input_file_name;
mu_acl_cfg_init ();
if (mu_cfg_parse_config (&tree, &hints))
......
......@@ -43,6 +43,19 @@ int
main (int argc, char **argv)
{
mutool_action_t action;
static struct mu_parseopt pohint = {
.po_flags = MU_PARSEOPT_PACKAGE_NAME
| MU_PARSEOPT_PACKAGE_URL
| MU_PARSEOPT_BUG_ADDRESS
| MU_PARSEOPT_EXTRA_INFO
| MU_PARSEOPT_VERSION_HOOK,
.po_package_name = PACKAGE_NAME,
.po_package_url = PACKAGE_URL,
.po_bug_address = PACKAGE_BUGREPORT,
.po_extra_info = mu_general_help_text,
.po_version_hook = mu_version_hook,
};
struct mu_cfg_parse_hints cfhint = { .flags = 0 };
/* Native Language Support */
MU_APP_INIT_NLS ();
......@@ -51,7 +64,7 @@ main (int argc, char **argv)
/* Register the desired mailbox formats. */
mu_register_all_mbox_formats ();
mu_cli (argc, argv, &cli, capa, NULL, &argc, &argv);
mu_cli_ext (argc, argv, &cli, &pohint, &cfhint, capa, NULL, &argc, &argv);
if (argc < 1)
{
......
......@@ -17,7 +17,7 @@
#include "mu.h"
char query_docstring[] = N_("query configuration values");
static char query_args_doc[] = N_("path [path...]");
static char query_args_doc[] = N_("PATH [PATH...]");
static char *file_name;
int value_option;
......@@ -59,21 +59,21 @@ mutool_query (int argc, char **argv)
return 1;
}
hints.flags = MU_CFG_PARSE_SITE_RCFILE | MU_PARSE_CONFIG_GLOBAL;
hints.site_rcfile = file_name ? file_name : mu_site_config_file ();
hints.flags = MU_CFHINT_SITE_FILE;
hints.site_file = file_name ? file_name : mu_site_config_file ();
if (progname)
{
hints.flags |= MU_CFG_PARSE_PROGRAM;
hints.flags |= MU_CFHINT_PROGRAM;
hints.program = progname;
}
if (verbose_option)
hints.flags |= MU_CFG_FMT_LOCUS;
hints.flags |= MU_CF_FMT_LOCUS;
if (value_option)
hints.flags |= MU_CFG_FMT_VALUE_ONLY;
hints.flags |= MU_CF_FMT_VALUE_ONLY;
if (path_option)
hints.flags |= MU_CFG_FMT_PARAM_PATH;
hints.flags |= MU_CF_FMT_PARAM_PATH;
if (mu_cfg_parse_config (&tree, &hints))
return 1;
......
......@@ -317,9 +317,10 @@ static char *capa[] = {
};
struct mu_cli_setup cli = {
options,
pop3d_cfg_param,
N_("GNU pop3d -- the POP3 daemon."),
.optv = options,
.cfg = pop3d_cfg_param,
.prog_doc = N_("GNU pop3d -- the POP3 daemon."),
.server = 1
};
int
......
......@@ -18,8 +18,7 @@
source $top_srcdir/testsuite/lib/mailutils.exp
mu_init "--rcfile=$objdir/pop3d.rc"
mu_init "--config-file=$objdir/pop3d.rc"
mu_version
if ![mu_check_capability ENABLE_VIRTUAL_DOMAINS] {
clone_output "WARNING: Support for virtual domains not compiled in"
......
......@@ -148,14 +148,25 @@ proc mu_init {args} {
set MU_SPOOL_DIR "$MU_DATA_DIR/spool"
set MU_FOLDER_DIR "$MU_DATA_DIR/folder"
if {[llength $args] == 1 && [lindex $args 0] == "-noflags"} {
set MU_TOOL_FLAGS "--no-site-rcfile --no-user-rcfile"
} else {
set MU_TOOL_FLAGS "--set mailbox.mail-spool=\"'$MU_SPOOL_DIR'\" --no-site-rcfile --no-user-rcfile"
for {set i 0} {$i < [llength $args]} {incr i} {
append MU_TOOL_FLAGS " [lindex $args $i]"
lappend flags "--no-config" "--set mailbox.mail-spool=\"'$MU_SPOOL_DIR'\""
set i 0
for {} {$i < [llength $args]} {incr i} {
switch -- [lindex $args $i] {
-noflags {
unset flags
}
-- {
incr i
break
}
default {
break
}
}
}
lappend flags {*}[lrange $args $i end]
set MU_TOOL_FLAGS [join $flags { }]
}
}
......