Commit 1b2350e5 1b2350e50f3f39fbc40811da4b942a71fd1dab8d by Sergey Poznyakoff

* include/mailutils/cfg.h (mu_cfg_section): New type.

(struct mu_cfg_param.offset): New member
(mu_offsetof): New define
(mu_cfg_section_fp): Change signature
(struct mu_cfg_section.label,target): New members.
(struct mu_cfg_section.data): Remove.
(struct mu_cfg_section.children): New member, instead of
param and subsec which are removed.
(mu_cfg_scan_tree): Change signature.
(mu_config_register_section): Change signature.
(mu_parse_config): Change signature.
(mu_parse_config_tree): Rename to mu_cfg_tree_reduce.
(mu_get_config): New proto.

* include/mailutils/libcfg.h (mu_parse_config_files): Change
prototype.

* dotlock/dotlock.c, imap4d/imap4d.c, lib/tcpwrap.h,
libargp/muinit.c, libcfg/auth.c, libcfg/common.c, libcfg/gsasl.c,
libcfg/init.c, libcfg/ldap.c, libcfg/pam.c, libcfg/radius.c,
libcfg/sieve.c, libcfg/sql.c, libcfg/tls.c, libcfg/virtdomain.c,
maidag/maidag.c, mail.local/main.c, mail.remote/mail.remote.c,
mailbox/cfg_format.c, mailbox/cfg_parser.y, mimeview/mimeview.c,
movemail/movemail.c, pop3d/pop3d.c, readmsg/readmsg.c,
sieve/sieve.c: Reflect changes to the cfg framework.

* mailbox/Makefile.am (libmailutils_la_SOURCES): Add cfg_driver.c.
* mailbox/cfg_driver.c: New file.
* mailbox/cfg_lexer.c: Move driver part into a separate file.

* examples/Makefile.am (AM_LDFLAGS): Remove libmuaux
* examples/echosrv.c: Remove getopt.h
1 parent 797a5462
2007-12-11 Sergey Poznyakoff <gray@gnu.org.ua>
* include/mailutils/cfg.h (mu_cfg_section): New type.
(struct mu_cfg_param.offset): New member
(mu_offsetof): New define
(mu_cfg_section_fp): Change signature
(struct mu_cfg_section.label,target): New members.
(struct mu_cfg_section.data): Remove.
(struct mu_cfg_section.children): New member, instead of
param and subsec which are removed.
(mu_cfg_scan_tree): Change signature.
(mu_config_register_section): Change signature.
(mu_parse_config): Change signature.
(mu_parse_config_tree): Rename to mu_cfg_tree_reduce.
(mu_get_config): New proto.
* include/mailutils/libcfg.h (mu_parse_config_files): Change
prototype.
* dotlock/dotlock.c, imap4d/imap4d.c, lib/tcpwrap.h,
libargp/muinit.c, libcfg/auth.c, libcfg/common.c, libcfg/gsasl.c,
libcfg/init.c, libcfg/ldap.c, libcfg/pam.c, libcfg/radius.c,
libcfg/sieve.c, libcfg/sql.c, libcfg/tls.c, libcfg/virtdomain.c,
maidag/maidag.c, mail.local/main.c, mail.remote/mail.remote.c,
mailbox/cfg_format.c, mailbox/cfg_parser.y, mimeview/mimeview.c,
movemail/movemail.c, pop3d/pop3d.c, readmsg/readmsg.c,
sieve/sieve.c: Reflect changes to the cfg framework.
* mailbox/Makefile.am (libmailutils_la_SOURCES): Add cfg_driver.c.
* mailbox/cfg_driver.c: New file.
* mailbox/cfg_lexer.c: Move driver part into a separate file.
* examples/Makefile.am (AM_LDFLAGS): Remove libmuaux
* examples/echosrv.c: Remove getopt.h
2007-12-09 Sergey Poznyakoff <gray@gnu.org.ua>
* examples/Makefile.am: add echosrv.c.
......
......@@ -125,11 +125,11 @@ parse_opt (int key, char *arg, struct argp_state *state)
struct mu_cfg_param dotlock_cfg_param[] = {
{ "force", mu_cfg_time, &force, NULL,
{ "force", mu_cfg_time, &force, 0, NULL,
N_("Forcibly break an existing lock older than the specified time.") },
{ "retry", mu_cfg_int, &retries, NULL,
{ "retry", mu_cfg_int, &retries, 0, NULL,
N_("Number of times to retry acquiring the lock.") },
{ "debug", mu_cfg_bool, &debug, NULL,
{ "debug", mu_cfg_bool, &debug, 0, NULL,
N_("Print details of failure reasons to stderr.") },
{ NULL }
};
......
......@@ -54,7 +54,6 @@ mod_LTLIBRARIES = numaddr.la
INCLUDES = @MU_COMMON_INCLUDES@
AM_LDFLAGS = \
../lib/libmuaux.la\
${MU_LIB_MAILUTILS}\
@MU_COMMON_LIBRARIES@
......
......@@ -28,7 +28,6 @@
#include <arpa/inet.h>
#include <signal.h>
#include <sys/wait.h>
#include "getopt.h"
#include <mailutils/mailutils.h>
#include <mailutils/server.h>
......@@ -185,7 +184,8 @@ server_idle (void *server_data)
(unsigned long) pid,
WTERMSIG (status));
else
mu_diag_output (MU_DIAG_ERR, "%lu: terminated (cause unknown)");
mu_diag_output (MU_DIAG_ERR, "%lu: terminated (cause unknown)",
(unsigned long) pid);
}
}
return 0;
......
......@@ -272,33 +272,33 @@ cb_preauth (mu_debug_t debug, void *data, char *arg)
}
static struct mu_cfg_param imap4d_cfg_param[] = {
{ "other-namespace", mu_cfg_callback, NULL, cb_other,
{ "other-namespace", mu_cfg_callback, NULL, 0, cb_other,
N_("Set other users' namespace. Argument is a colon-separated list "
"of directories comprising the namespace.") },
{ "shared-namespace", mu_cfg_callback, NULL, cb_shared,
{ "shared-namespace", mu_cfg_callback, NULL, 0, cb_shared,
N_("Set shared namespace. Argument is a colon-separated list "
"of directories comprising the namespace.") },
{ "login-disabled", mu_cfg_int, &login_disabled, NULL,
{ "login-disabled", mu_cfg_int, &login_disabled, 0, NULL,
N_("Disable LOGIN command.") },
{ "create-home-dir", mu_cfg_bool, &create_home_dir, NULL,
{ "create-home-dir", mu_cfg_bool, &create_home_dir, 0, NULL,
N_("If true, create non-existing user home directories.") },
{ "home-dir-mode", mu_cfg_callback, NULL, cb_mode,
{ "home-dir-mode", mu_cfg_callback, NULL, 0, cb_mode,
N_("File mode for creating user home directories (octal)."),
N_("mode") },
{ "tls-required", mu_cfg_int, &tls_required, NULL,
{ "tls-required", mu_cfg_int, &tls_required, 0, NULL,
N_("Always require STARTTLS before entering authentication phase.") },
{ "preauth", mu_cfg_callback, NULL, cb_preauth,
{ "preauth", mu_cfg_callback, NULL, 0, cb_preauth,
N_("Configure PREAUTH mode. MODE is one of:\n"
" prog:///<full-program-name: string>\n"
" ident[://:<port: string-or-number>]\n"
" stdio"),
N_("MODE") },
{ "preauth-only", mu_cfg_bool, &preauth_only, NULL,
{ "preauth-only", mu_cfg_bool, &preauth_only, 0, NULL,
N_("Use only preauth mode. If unable to setup it, disconnect "
"immediately.") },
{ "ident-keyfile", mu_cfg_string, &ident_keyfile, NULL,
{ "ident-keyfile", mu_cfg_string, &ident_keyfile, 0, NULL,
N_("Name of DES keyfile for decoding ecrypted ident responses.") },
{ "ident-entrypt-only", mu_cfg_bool, &ident_encrypt_only, NULL,
{ "ident-entrypt-only", mu_cfg_bool, &ident_encrypt_only, 0, NULL,
N_("Use only encrypted ident responses.") },
TCP_WRAPPERS_CONFIG
{ NULL }
......
......@@ -118,7 +118,8 @@ enum mu_cfg_param_data_type
mu_cfg_ipv4,
mu_cfg_cidr,
mu_cfg_host,
mu_cfg_callback
mu_cfg_callback,
mu_cfg_section
};
typedef int (*mu_cfg_callback_t) (mu_debug_t, void *, char *);
......@@ -128,11 +129,17 @@ struct mu_cfg_param
const char *ident;
enum mu_cfg_param_data_type type;
void *data;
size_t offset;
mu_cfg_callback_t callback;
const char *docstring;
const char *argname;
};
#define mu_offsetof(s,f) ((size_t)&((s*)0).f)
#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,
......@@ -141,17 +148,18 @@ enum mu_cfg_section_stage
typedef int (*mu_cfg_section_fp) (enum mu_cfg_section_stage stage,
const mu_cfg_node_t *node,
void *section_data,
const char *label,
void **section_data_ptr,
void *call_data,
mu_cfg_tree_t *tree);
struct mu_cfg_section
{
const char *ident;
char *label;
mu_cfg_section_fp parser;
void *data;
mu_list_t /* of mu_cfg_cont/mu_cfg_section */ subsec;
mu_list_t /* of mu_cfg_cont/mu_cfg_param */ param;
void *target;
mu_list_t /* of mu_cfg_cont */ children;
char *docstring;
};
......@@ -187,15 +195,15 @@ int mu_config_clone_container (struct mu_cfg_cont *cont);
void mu_config_destroy_container (struct mu_cfg_cont **pcont);
int mu_cfg_scan_tree (mu_cfg_tree_t *tree, struct mu_cfg_section *sections,
void *call_data);
void *target, void *call_data);
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,
void *data,
struct mu_cfg_param *param);
int mu_config_register_plain_section (const char *parent_path,
const char *ident,
......@@ -206,7 +214,8 @@ int mu_config_register_plain_section (const char *parent_path,
#define MU_PARSE_CONFIG_DUMP 0x4
int mu_parse_config (const char *file, const char *progname,
struct mu_cfg_param *progparam, int flags);
struct mu_cfg_param *progparam, int flags,
void *target_ptr);
int mu_cfg_parse_boolean (const char *str, int *res);
......@@ -218,8 +227,14 @@ void mu_cfg_format_parse_tree (mu_stream_t stream, struct mu_cfg_tree *tree);
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_parse_config_tree (mu_cfg_tree_t *parse_tree, const char *progname,
struct mu_cfg_param *progparam, int flags);
int mu_cfg_tree_reduce (mu_cfg_tree_t *parse_tree, const char *progname,
struct mu_cfg_param *progparam,
int flags, void *target_ptr);
int mu_get_config (const char *file, const char *progname,
struct mu_cfg_param *progparam, int flags,
void *target_ptr);
int mu_cfg_tree_create (struct mu_cfg_tree **ptree);
void mu_cfg_tree_set_debug (struct mu_cfg_tree *tree, mu_debug_t debug);
......
......@@ -49,7 +49,8 @@ extern int mu_register_cfg_capa (const char *name,
mu_cfg_section_fp *parser);
extern void mu_libcfg_init (char **cnames);
extern int mu_parse_config_files (struct mu_cfg_param *param);
extern int mu_parse_config_files (struct mu_cfg_param *param,
void *target_ptr);
#define __mu_common_cat2__(a,b) a ## b
#define __mu_common_cat3__(a,b,c) a ## b ## c
......@@ -57,7 +58,8 @@ extern int mu_parse_config_files (struct mu_cfg_param *param);
int \
__mu_common_cat3__(mu_,capa,_section_parser) \
(enum mu_cfg_section_stage stage, const mu_cfg_node_t *node, \
void *section_data, void *call_data, mu_cfg_tree_t *tree) \
const char *section_label, void **section_data, \
void *call_data, mu_cfg_tree_t *tree) \
{ \
switch (stage) \
{ \
......
......@@ -33,25 +33,27 @@ extern int mu_tcpwrapper_access (int fd);
#ifdef WITH_LIBWRAP
# define TCP_WRAPPERS_CONFIG \
{ "tcp-wrapper-enable", mu_cfg_bool, &mu_tcp_wrapper_enable, NULL, \
{ "tcp-wrapper-enable", mu_cfg_bool, &mu_tcp_wrapper_enable, 0, NULL, \
N_("Enable TCP wrapper access control. Default is \"yes\".") }, \
{ "tcp-wrapper-daemon", mu_cfg_string, &mu_tcp_wrapper_daemon, NULL, \
{ "tcp-wrapper-daemon", mu_cfg_string, &mu_tcp_wrapper_daemon, 0, NULL, \
N_("Set daemon name for TCP wrapper lookups. Default is program name."), \
N_("name") }, \
{ "hosts-allow-table", mu_cfg_callback, NULL, mu_tcp_wrapper_cb_hosts_allow,\
{ "hosts-allow-table", mu_cfg_callback, NULL, 0, \
mu_tcp_wrapper_cb_hosts_allow, \
N_("Use file for positive client address access control " \
"(default: /etc/hosts.allow)."), \
N_("file") }, \
{ "hosts-deny-table", mu_cfg_callback, NULL, mu_tcp_wrapper_cb_hosts_deny, \
{ "hosts-deny-table", mu_cfg_callback, NULL, 0, \
mu_tcp_wrapper_cb_hosts_deny, \
N_("Use file for negative client address access control " \
"(default: /etc/hosts.deny)."), \
N_("file") }, \
{ "hosts-allow-syslog-level", mu_cfg_callback, NULL, \
{ "hosts-allow-syslog-level", mu_cfg_callback, NULL, 0, \
mu_tcp_wrapper_cb_hosts_allow_syslog, \
N_("Log host allows at this syslog level. See logging { facility } for " \
"a description of argument syntax."), \
N_("level") }, \
{ "hosts-allow-deny-level", mu_cfg_callback, NULL, \
{ "hosts-allow-deny-level", mu_cfg_callback, NULL, 0, \
mu_tcp_wrapper_cb_hosts_deny_syslog, \
N_("Log host denies at this syslog level. See logging { facility } for " \
"a description of argument syntax."), \
......
......@@ -77,7 +77,7 @@ mu_app_init (struct argp *myargp, const char **capa,
mu_libcfg_init (excapa);
free (excapa);
mu_parse_config_files (cfg_param);
mu_parse_config_files (cfg_param, data);
if (mu_help_config_mode)
{
......@@ -113,8 +113,8 @@ mu_app_init (struct argp *myargp, const char **capa,
cfgflags |= MU_PARSE_CONFIG_VERBOSE;
if (mu_cfg_parser_verbose > 1)
cfgflags |= MU_PARSE_CONFIG_DUMP;
rc = mu_parse_config_tree (mu_argp_tree, mu_program_name, cfg_param,
cfgflags);
rc = mu_cfg_tree_reduce (mu_argp_tree, mu_program_name, cfg_param,
cfgflags, data);
mu_gocs_flush ();
mu_cfg_destroy_tree (&mu_argp_tree);
......
......@@ -50,12 +50,12 @@ cb_authorization (mu_debug_t err, void *data, char *arg)
}
static struct mu_cfg_param mu_auth_param[] = {
{ "authentication", mu_cfg_callback, NULL, cb_authentication,
{ "authentication", mu_cfg_callback, NULL, 0, cb_authentication,
N_("Set a list of modules for authentication. Modlist is a "
"colon-separated list of module names or a word `clear' to "
"clear the previously set up values."),
N_("modlist") },
{ "authorization", mu_cfg_callback, NULL, cb_authorization,
{ "authorization", mu_cfg_callback, NULL, 0, cb_authorization,
N_("Set a list of modules for authorization. Modlist is a "
"colon-separated list of module names or a word `clear' to "
"clear the previously set up values."),
......@@ -66,7 +66,8 @@ static struct mu_cfg_param mu_auth_param[] = {
int
mu_auth_section_parser
(enum mu_cfg_section_stage stage, const mu_cfg_node_t *node,
void *section_data, void *call_data, mu_cfg_tree_t *tree)
const char *section_label, void **section_data, void *call_data,
mu_cfg_tree_t *tree)
{
switch (stage)
{
......
......@@ -40,10 +40,10 @@ static struct mu_gocs_debug debug_settings;
/* ************************************************************************* */
static struct mu_cfg_param mu_mailbox_param[] = {
{ "mail-spool", mu_cfg_string, &mailbox_settings.mail_spool, NULL,
{ "mail-spool", mu_cfg_string, &mailbox_settings.mail_spool, 0, NULL,
N_("Use specified URL as a mailspool directory."),
N_("url") },
{ "mailbox-type", mu_cfg_string, &mailbox_settings.mailbox_type, NULL,
{ "mailbox-type", mu_cfg_string, &mailbox_settings.mailbox_type, 0, NULL,
N_("Default mailbox type."), N_("protocol") },
{ NULL }
};
......@@ -57,16 +57,18 @@ DCL_CFG_CAPA (mailbox);
static struct mu_cfg_param mu_locking_param[] = {
/* FIXME: Flags are superfluous. */
{ "flags", mu_cfg_string, &locking_settings.lock_flags, NULL,
{ "flags", mu_cfg_string, &locking_settings.lock_flags, 0, NULL,
N_("Default locker flags (E=external, R=retry, T=time, P=pid).") },
{ "retry-timeout", mu_cfg_ulong, &locking_settings.lock_retry_timeout, NULL,
{ "retry-timeout", mu_cfg_ulong, &locking_settings.lock_retry_timeout,
0, NULL,
N_("Set timeout for acquiring the lock.") },
{ "retry-count", mu_cfg_ulong, &locking_settings.lock_retry_count, NULL,
{ "retry-count", mu_cfg_ulong, &locking_settings.lock_retry_count, 0, NULL,
N_("Set the maximum number of times to retry acquiring the lock.") },
{ "expire-timeout", mu_cfg_ulong, &locking_settings.lock_expire_timeout,
NULL,
0, NULL,
N_("Expire locks older than this amount of time.") },
{ "external-locker", mu_cfg_string, &locking_settings.external_locker, NULL,
{ "external-locker", mu_cfg_string, &locking_settings.external_locker,
0, NULL,
N_("Use external locker program."),
N_("prog") },
{ NULL, }
......@@ -80,11 +82,11 @@ DCL_CFG_CAPA (locking);
/* ************************************************************************* */
static struct mu_cfg_param mu_address_param[] = {
{ "email-addr", mu_cfg_string, &address_settings.address, NULL,
{ "email-addr", mu_cfg_string, &address_settings.address, 0, NULL,
N_("Set the current user email address (default is "
"loginname@defaultdomain)."),
N_("email") },
{ "email-domain", mu_cfg_string, &address_settings.domain, NULL,
{ "email-domain", mu_cfg_string, &address_settings.domain, 0, NULL,
N_("Set e-mail domain for unqualified user names (default is this host)"),
N_("domain") },
{ NULL }
......@@ -98,7 +100,7 @@ DCL_CFG_CAPA (address);
/* ************************************************************************* */
static struct mu_cfg_param mu_mailer_param[] = {
{ "url", mu_cfg_string, &mailer_settings.mailer, NULL,
{ "url", mu_cfg_string, &mailer_settings.mailer, 0, NULL,
N_("Use this URL as the default mailer"),
N_("url") },
{ NULL }
......@@ -125,7 +127,7 @@ cb_facility (mu_debug_t debug, void *data, char *arg)
}
static struct mu_cfg_param mu_logging_param[] = {
{ "facility", mu_cfg_callback, NULL, cb_facility,
{ "facility", mu_cfg_callback, NULL, 0, cb_facility,
N_("Set syslog facility. Arg is one of the following: user, daemon, "
"auth, authpriv, mail, cron, local0 through local7 (case-insensitive), "
"or a facility number.") },
......@@ -156,19 +158,19 @@ _cb_daemon_mode (mu_debug_t debug, void *data, char *arg)
}
static struct mu_cfg_param mu_daemon_param[] = {
{ "max-children", mu_cfg_ulong, &daemon_settings.maxchildren, NULL,
{ "max-children", mu_cfg_ulong, &daemon_settings.maxchildren, 0, NULL,
N_("Maximum number of children processes to run simultaneously.") },
{ "mode", mu_cfg_callback, NULL, _cb_daemon_mode,
{ "mode", mu_cfg_callback, NULL, 0, _cb_daemon_mode,
N_("Set daemon mode (either inetd (or interactive) or daemon)."),
N_("mode") },
{ "transcript", mu_cfg_bool, &daemon_settings.transcript, NULL,
{ "transcript", mu_cfg_bool, &daemon_settings.transcript, 0, NULL,
N_("Log the session transcript.") },
{ "pidfile", mu_cfg_string, &daemon_settings.pidfile, NULL,
{ "pidfile", mu_cfg_string, &daemon_settings.pidfile, 0, NULL,
N_("Store PID of the master process in this file."),
N_("file") },
{ "port", mu_cfg_ushort, &daemon_settings.port, NULL,
{ "port", mu_cfg_ushort, &daemon_settings.port, 0, NULL,
N_("Listen on the specified port number.") },
{ "timeout", mu_cfg_ulong, &daemon_settings.timeout, NULL,
{ "timeout", mu_cfg_ulong, &daemon_settings.timeout, 0, NULL,
N_("Set idle timeout.") },
{ NULL }
};
......@@ -176,7 +178,8 @@ static struct mu_cfg_param mu_daemon_param[] = {
int
mu_daemon_section_parser
(enum mu_cfg_section_stage stage, const mu_cfg_node_t *node,
void *section_data, void *call_data, mu_cfg_tree_t *tree)
const char *section_label, void **section_data,
void *call_data, mu_cfg_tree_t *tree)
{
switch (stage)
{
......@@ -209,7 +212,9 @@ cb_debug_level (mu_debug_t debug, void *data, char *arg)
char *pfx;
struct mu_debug_locus locus;
debug_settings.string = arg;
if (debug_settings.string)
free (debug_settings.string);
debug_settings.string = strdup (arg);
if (mu_debug_get_locus (debug, &locus) == 0)
{
p = umaxtostr (locus.line, buf);
......@@ -232,11 +237,11 @@ cb_debug_level (mu_debug_t debug, void *data, char *arg)
}
static struct mu_cfg_param mu_debug_param[] = {
{ "level", mu_cfg_callback, NULL, &cb_debug_level,
{ "level", mu_cfg_callback, NULL, 0, &cb_debug_level,
N_("Set Mailutils debugging level. Argument is a colon-separated list "
"of debugging specifications in the form:\n"
" <object: string>[[:]=<level: number>].") },
{ "line-info", mu_cfg_bool, &debug_settings.line_info, NULL,
{ "line-info", mu_cfg_bool, &debug_settings.line_info, 0, NULL,
N_("Prefix debug messages with Mailutils source locations.") },
{ NULL }
};
......
......@@ -25,7 +25,7 @@
static struct mu_gsasl_module_data gsasl_settings;
static struct mu_cfg_param mu_gsasl_param[] = {
{ "cram-passwd", mu_cfg_string, &gsasl_settings.cram_md5_pwd, NULL,
{ "cram-passwd", mu_cfg_string, &gsasl_settings.cram_md5_pwd, 0, NULL,
N_("Name of GSASL password file."),
N_("file") },
{ NULL }
......
......@@ -78,14 +78,14 @@ mu_libcfg_init (char **cnames)
mu_error (_("Requested unknown configuration group `%s'"),
cnames[i]);
else
mu_config_register_section (NULL, cp->name, cp->parser, NULL,
cp->cfgparam);
mu_config_register_section (NULL, cp->name, NULL,
cp->parser, cp->cfgparam);
}
}
}
int
mu_parse_config_files (struct mu_cfg_param *param)
mu_parse_config_files (struct mu_cfg_param *param, void *target)
{
int flags = 0;
......@@ -96,7 +96,7 @@ mu_parse_config_files (struct mu_cfg_param *param)
if (mu_load_site_rcfile)
mu_parse_config (MU_CONFIG_FILE, mu_program_name, param,
flags | MU_PARSE_CONFIG_GLOBAL);
flags | MU_PARSE_CONFIG_GLOBAL, target);
if (mu_load_user_rcfile && mu_program_name)
{
......@@ -107,14 +107,14 @@ mu_parse_config_files (struct mu_cfg_param *param)
strcpy (file_name, "~/.");
strcat (file_name, mu_program_name);
mu_parse_config (file_name, mu_program_name, param, flags);
mu_parse_config (file_name, mu_program_name, param, flags, target);
free (file_name);
}
}
if (mu_load_rcfile)
mu_parse_config (mu_load_rcfile, mu_program_name, param, flags);
mu_parse_config (mu_load_rcfile, mu_program_name, param, flags, target);
return 0;
}
......
......@@ -37,24 +37,24 @@ cb_field_map (mu_debug_t debug, void *data, char *arg)
}
static struct mu_cfg_param mu_ldap_param[] = {
{ "enable", mu_cfg_bool, &ldap_settings.enable, NULL,
{ "enable", mu_cfg_bool, &ldap_settings.enable, 0, NULL,
N_("Enable LDAP lookups.") },
{ "url", mu_cfg_string, &ldap_settings.url, NULL,
{ "url", mu_cfg_string, &ldap_settings.url, 0, NULL,
N_("Set URL of the LDAP server."),
N_("url") },
{ "base", mu_cfg_string, &ldap_settings.base, NULL,
{ "base", mu_cfg_string, &ldap_settings.base, 0, NULL,
N_("Base DN for LDAP lookups."),
N_("dn") },
{ "binddn", mu_cfg_string, &ldap_settings.binddn, NULL,
{ "binddn", mu_cfg_string, &ldap_settings.binddn, 0, NULL,
N_("DN for accessing LDAP database."),
N_("dn") },
{ "passwd", mu_cfg_string, &ldap_settings.passwd, NULL,
{ "passwd", mu_cfg_string, &ldap_settings.passwd, 0, NULL,
N_("Password for use with binddn.") },
{ "tls", mu_cfg_bool, &ldap_settings.tls, NULL,
{ "tls", mu_cfg_bool, &ldap_settings.tls, 0, NULL,
N_("Use TLS encryption.") },
{ "debug", mu_cfg_int, &ldap_settings.debug, NULL,
{ "debug", mu_cfg_int, &ldap_settings.debug, 0, NULL,
N_("Set LDAP debugging level.") },
{ "field-map", mu_cfg_callback, NULL, cb_field_map,
{ "field-map", mu_cfg_callback, NULL, 0, cb_field_map,
N_("Set a field-map for parsing LDAP replies. The map is a "
"column-separated list of definitions. Each definition has the "
"following form:\n"
......@@ -63,10 +63,10 @@ static struct mu_cfg_param mu_ldap_param[] = {
"gecos, dir, shell, mailbox, quota, and <attr> is the name of "
"the correspondind LDAP attribute."),
N_("map") },
{ "getpwnam", mu_cfg_string, &ldap_settings.getpwnam_filter, NULL,
{ "getpwnam", mu_cfg_string, &ldap_settings.getpwnam_filter, 0, NULL,
N_("LDAP filter to use for getpwnam requests."),
N_("filter") },
{ "getpwuid", mu_cfg_string, &ldap_settings.getpwuid_filter, NULL,
{ "getpwuid", mu_cfg_string, &ldap_settings.getpwuid_filter, 0, NULL,
N_("LDAP filter to use for getpwuid requests."),
N_("filter") },
{ NULL }
......@@ -75,7 +75,8 @@ static struct mu_cfg_param mu_ldap_param[] = {
int
mu_ldap_section_parser
(enum mu_cfg_section_stage stage, const mu_cfg_node_t *node,
void *section_data, void *call_data, mu_cfg_tree_t *tree)
const char *section_label, void **section_data,
void *call_data, mu_cfg_tree_t *tree)
{
switch (stage)
{
......
......@@ -24,7 +24,7 @@
static char *pam_settings;
static struct mu_cfg_param mu_pam_param[] = {
{ "service", mu_cfg_string, &pam_settings, NULL,
{ "service", mu_cfg_string, &pam_settings, 0, NULL,
N_("Set PAM service name."),
N_("name") },
{ NULL }
......
......@@ -25,16 +25,16 @@
static struct mu_radius_module_data radius_settings;
static struct mu_cfg_param mu_radius_param[] = {
{ "auth", mu_cfg_string, &radius_settings.auth_request, NULL,
{ "auth", mu_cfg_string, &radius_settings.auth_request, 0, NULL,
N_("Radius request for authorization."),
N_("request") },
{ "getpwnam", mu_cfg_string, &radius_settings.getpwnam_request, NULL,
{ "getpwnam", mu_cfg_string, &radius_settings.getpwnam_request, 0, NULL,
N_("Radius request for getpwnam."),
N_("request") },
{ "getpwuid", mu_cfg_string, &radius_settings.getpwuid_request, NULL,
{ "getpwuid", mu_cfg_string, &radius_settings.getpwuid_request, 0, NULL,
N_("Radius request for getpwuid."),
N_("request") },
{ "directory", mu_cfg_string, &radius_settings.config_dir, NULL,
{ "directory", mu_cfg_string, &radius_settings.config_dir, 0, NULL,
N_("Set radius configuration directory.") },
{ NULL }
};
......
......@@ -92,15 +92,15 @@ cb_library_path (mu_debug_t debug, void *data, char *arg)
}
static struct mu_cfg_param mu_sieve_param[] = {
{ "clear-library-path", mu_cfg_callback, NULL, cb_clear_library_path,
{ "clear-library-path", mu_cfg_callback, NULL, 0, cb_clear_library_path,
N_("Clear library search path.") },
{ "clear-include-path", mu_cfg_callback, NULL, cb_clear_include_path,
{ "clear-include-path", mu_cfg_callback, NULL, 0, cb_clear_include_path,
N_("Clear include search path.") },
{ "library-path", mu_cfg_callback, NULL, cb_library_path,
{ "library-path", mu_cfg_callback, NULL, 0, cb_library_path,
N_("Add directories to the library search path. Argument is a "
"comma-separated list of directories."),
N_("list") },
{ "include-path", mu_cfg_callback, NULL, cb_include_path,
{ "include-path", mu_cfg_callback, NULL, 0, cb_include_path,
N_("Add directories to the include search path. Argument is a "
"comma-separated list of directories."),
N_("list") },
......
......@@ -50,31 +50,31 @@ cb_field_map (mu_debug_t debug, void *data, char *arg)
}
static struct mu_cfg_param mu_sql_param[] = {
{ "interface", mu_cfg_string, &sql_settings.interface, NULL,
{ "interface", mu_cfg_string, &sql_settings.interface, 0, NULL,
N_("Set SQL interface to use (one of: mysql, odbc, or postgres).") },
{ "getwpnam", mu_cfg_string, &sql_settings.getpwnam_query, NULL,
{ "getwpnam", mu_cfg_string, &sql_settings.getpwnam_query, 0, NULL,
N_("SQL query to use for getpwnam requests."),
N_("query") },
{ "getpwuid", mu_cfg_string, &sql_settings.getpwuid_query, NULL,
{ "getpwuid", mu_cfg_string, &sql_settings.getpwuid_query, 0, NULL,
N_("SQL query to use for getpwuid requests."),
N_("query") },
{ "getpass", mu_cfg_string, &sql_settings.getpass_query, NULL,
{ "getpass", mu_cfg_string, &sql_settings.getpass_query, 0, NULL,
N_("SQL query returning the user's password."),
N_("query") },
{ "host", mu_cfg_string, &sql_settings.host, NULL,
{ "host", mu_cfg_string, &sql_settings.host, 0, NULL,
N_("SQL server host name.") },
{ "user", mu_cfg_string, &sql_settings.user, NULL,
{ "user", mu_cfg_string, &sql_settings.user, 0, NULL,
N_("SQL user name.") },
{ "passwd", mu_cfg_string, &sql_settings.passwd, NULL,
{ "passwd", mu_cfg_string, &sql_settings.passwd, 0, NULL,
N_("Password for the SQL user.") },
{ "port", mu_cfg_int, &sql_settings.port, NULL,
{ "port", mu_cfg_int, &sql_settings.port, 0, NULL,
N_("SQL server port.") },
{ "db", mu_cfg_string, &sql_settings.db, NULL,
{ "db", mu_cfg_string, &sql_settings.db, 0, NULL,
N_("Database name.") },
{ "password-type", mu_cfg_callback, NULL, cb_password_type,
{ "password-type", mu_cfg_callback, NULL, 0, cb_password_type,
N_("Type of password returned by getpass query (one of: plain, hash, "
"scrambled).") },
{ "field-map", mu_cfg_callback, NULL, cb_field_map,
{ "field-map", mu_cfg_callback, NULL, 0, cb_field_map,
N_("Set a field-map for parsing SQL replies. The map is a "
"column-separated list of definitions. Each definition has the "
"following form:\n"
......
......@@ -25,15 +25,15 @@
static struct mu_tls_module_config tls_settings;
static struct mu_cfg_param mu_tls_param[] = {
{ "tls", mu_cfg_bool, &tls_settings.client_enable, NULL,
{ "tls", mu_cfg_bool, &tls_settings.client_enable, 0, NULL,
N_("Enable client TLS encryption.") },
{ "ssl-cert", mu_cfg_string, &tls_settings.ssl_cert, NULL,
{ "ssl-cert", mu_cfg_string, &tls_settings.ssl_cert, 0, NULL,
N_("Specify SSL certificate file."),
N_("file") },
{ "ssl-key", mu_cfg_string, &tls_settings.ssl_key, NULL,
{ "ssl-key", mu_cfg_string, &tls_settings.ssl_key, 0, NULL,
N_("Specify SSL certificate key file."),
N_("file") },
{ "ssl-cafile", mu_cfg_string, &tls_settings.ssl_cafile, NULL,
{ "ssl-cafile", mu_cfg_string, &tls_settings.ssl_cafile, 0, NULL,
N_("Specify trusted CAs file."),
N_("file") },
{ NULL }
......
......@@ -24,7 +24,7 @@
static struct mu_gocs_virtual virtdomain_settings;
static struct mu_cfg_param mu_virtdomain_param[] = {
{ "passwd-dir", mu_cfg_string, &virtdomain_settings, NULL,
{ "passwd-dir", mu_cfg_string, &virtdomain_settings, 0, NULL,
N_("Name of the directory where virtual domain password files are "
"located."),
N_("dir") },
......
......@@ -238,57 +238,57 @@ cb_debug (mu_debug_t debug, void *data, char *arg)
}
struct mu_cfg_param maidag_cfg_param[] = {
{ "exit-multiple-delivery-success", mu_cfg_bool, &multiple_delivery, NULL,
{ "exit-multiple-delivery-success", mu_cfg_bool, &multiple_delivery, 0, NULL,
N_("In case of multiple delivery, exit with code 0 if at least one "
"delivery succeeded.") },
{ "exit-quota-tempfail", mu_cfg_bool, &ex_quota_tempfail, NULL,
{ "exit-quota-tempfail", mu_cfg_bool, &ex_quota_tempfail, 0, NULL,
N_("Indicate temporary failure if the recipient is over his mail quota.")
},
#ifdef USE_DBM
{ "quota-db", mu_cfg_string, &quotadbname, NULL,
{ "quota-db", mu_cfg_string, &quotadbname, 0, NULL,
N_("Name of DBM quota database file."),
N_("file") },
#endif
#ifdef USE_SQL
{ "quota-query", mu_cfg_string, &quota_query, NULL,
{ "quota-query", mu_cfg_string, &quota_query, 0, NULL,
N_("SQL query to retrieve mailbox quota. This is deprecated, use "
"sql { ... } instead."),
N_("query") },
#endif
{ "sieve-filter", mu_cfg_string, &sieve_pattern, NULL,
{ "sieve-filter", mu_cfg_string, &sieve_pattern, 0, NULL,
N_("File name or name pattern for Sieve filter file."),
N_("file-or-pattern") },
{ "message-id-header", mu_cfg_string, &message_id_header, NULL,
{ "message-id-header", mu_cfg_string, &message_id_header, 0, NULL,
N_("When logging Sieve actions, identify messages by the value of "
"this header."),
N_("name") },
#ifdef WITH_GUILE
{ "guile-filter", mu_cfg_string, &progfile_pattern, NULL,
{ "guile-filter", mu_cfg_string, &progfile_pattern, 0, NULL,
N_("File name or name pattern for Guile filter file."),
N_("file-or-pattern") },
#endif
{ "debug", mu_cfg_callback, NULL, cb_debug,
{ "debug", mu_cfg_callback, NULL, 0, cb_debug,
N_("Set maidag debug level. Debug level consists of one or more "
"of the following letters:\n"
" g - guimb stack traces\n"
" t - sieve trace (MU_SIEVE_DEBUG_TRACE)\n"
" i - sieve instructions trace (MU_SIEVE_DEBUG_INSTR)\n"
" l - sieve action logs\n") },
{ "stderr", mu_cfg_bool, &log_to_stderr, NULL,
{ "stderr", mu_cfg_bool, &log_to_stderr, 0, NULL,
N_("Log to stderr instead of syslog.") },
/* LMTP support */
{ "lmtp", mu_cfg_bool, &lmtp_mode, NULL,
{ "lmtp", mu_cfg_bool, &lmtp_mode, 0, NULL,
N_("Run in LMTP mode.") },
{ "group", mu_cfg_string, &lmtp_group, NULL,
{ "group", mu_cfg_string, &lmtp_group, 0, NULL,
N_("In LMTP mode, change to this group after startup.") },
{ "listen", mu_cfg_string, &lmtp_url_string, NULL,
{ "listen", mu_cfg_string, &lmtp_url_string, 0, NULL,
N_("In LMTP mode, listen on the given URL. Valid URLs are:\n"
" tcp://<address: string>:<port: number> (note that port is "
"mandatory)\n"
" file://<socket-file-name>\n"
"or socket://<socket-file-name>"),
N_("url") },
{ "reuse-address", mu_cfg_bool, &reuse_lmtp_address, NULL,
{ "reuse-address", mu_cfg_bool, &reuse_lmtp_address, 0, NULL,
N_("Reuse existing address (LMTP mode). Default is \"yes\".") },
TCP_WRAPPERS_CONFIG
{ NULL }
......
......@@ -255,36 +255,36 @@ cb_debug (mu_debug_t debug, void *data, char *arg)
}
struct mu_cfg_param mail_local_cfg_param[] = {
{ "ex-multiple-delivery-success", mu_cfg_bool, &multiple_delivery, NULL,
{ "ex-multiple-delivery-success", mu_cfg_bool, &multiple_delivery, 0, NULL,
N_("In case of multiple delivery, exit with code 0 if at least one "
"delivery succeeded.") },
{ "ex-quota-tempfail", mu_cfg_bool, &ex_quota_tempfail, NULL,
{ "ex-quota-tempfail", mu_cfg_bool, &ex_quota_tempfail, 0, NULL,
N_("Indicate temporary failure if the recipient is over his mail quota.")
},
#ifdef USE_DBM
{ "quota-db", mu_cfg_string, &quotadbname, NULL,
{ "quota-db", mu_cfg_string, &quotadbname, 0, NULL,
N_("Name of DBM quota database file."),
N_("file") },
#endif
#ifdef USE_SQL
{ "quota-query", mu_cfg_string, &quota_query, NULL,
{ "quota-query", mu_cfg_string, &quota_query, 0, NULL,
N_("SQL query to retrieve mailbox quota. This is deprecated, use "
"sql { ... } instead."),
N_("query") },
#endif
{ "sieve-filter", mu_cfg_string, &sieve_pattern, NULL,
{ "sieve-filter", mu_cfg_string, &sieve_pattern, 0, NULL,
N_("File name or name pattern for Sieve filter file."),
N_("file-or-pattern") },
{ "message-id-header", mu_cfg_string, &message_id_header, NULL,
{ "message-id-header", mu_cfg_string, &message_id_header, 0, NULL,
N_("When logging Sieve actions, identify messages by the value of "
"this header."),
N_("name") },
#ifdef WITH_GUILE
{ "guile-filter", mu_cfg_string, &progfile_pattern, NULL,
{ "guile-filter", mu_cfg_string, &progfile_pattern, 0, NULL,
N_("File name or name pattern for Guile filter file."),
N_("file-or-pattern") },
#endif
{ "debug", mu_cfg_callback, NULL, cb_debug,
{ "debug", mu_cfg_callback, NULL, 0, cb_debug,
N_("Set mail.local debug level. Debug level consists of one or more "
"of the following letters:\n"
" g - guimb stack traces\n"
......
......@@ -136,12 +136,12 @@ static struct argp argp = {
struct mu_cfg_param mail_remote_cfg_param[] = {
{ "from", mu_cfg_string, &optfrom, NULL,
{ "from", mu_cfg_string, &optfrom, 0, NULL,
N_("Set sender email address."),
N_("email") },
{ "read-recipients", mu_cfg_string, &read_recipients, NULL,
{ "read-recipients", mu_cfg_string, &read_recipients, 0, NULL,
N_("Read recipient addresses from the message.") },
{ "debug", mu_cfg_int, &optdebug, NULL,
{ "debug", mu_cfg_int, &optdebug, 0, NULL,
N_("Set debug verbosity level. Level 1 prints envelope commands in "
"the SMTP protocol transaction. Levels 2 and above print the data "
"part of the transaction as well.") },
......
......@@ -50,6 +50,7 @@ libmailutils_la_SOURCES = \
dbgstderr.c\
dbgsyslog.c\
debug.c\
cfg_driver.c\
cfg_format.c\
cfg_lexer.c\
cfg_parser.c\
......
/* cfg_driver.c -- Main driver for Mailutils configuration files
Copyright (C) 2007 Free Software Foundation, Inc.
GNU Mailutils is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3, or (at
your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <ctype.h>
#include <mailutils/argcv.h>
#include <mailutils/nls.h>
#include <mailutils/cfg.h>
#include <mailutils/errno.h>
#include <mailutils/error.h>
#include <mailutils/mutil.h>
#include <mailutils/monitor.h>
#include <mailutils/refcount.h>
#include <mailutils/list.h>
#include <mailutils/iterator.h>
#include <mailutils/stream.h>
#include <mailutils/assoc.h>
static mu_assoc_t section_tab;
static void
alloc_section_tab ()
{
if (!section_tab)
mu_assoc_create (&section_tab, sizeof (struct mu_cfg_cont *),
MU_ASSOC_COPY_KEY);
}
int
mu_create_canned_section (struct mu_cfg_section *section)
{
struct mu_cfg_cont *cont;
alloc_section_tab ();
mu_config_create_container (&cont, mu_cfg_cont_section);
cont->v.section = *section;
return mu_assoc_install (section_tab, cont->v.section.ident, &cont);
}
int
mu_create_canned_param (struct mu_cfg_param *param)
{
struct mu_cfg_cont *cont;
alloc_section_tab ();
mu_config_create_container (&cont, mu_cfg_cont_param);
cont->v.param = *param;
return mu_assoc_install (section_tab, cont->v.param.ident, &cont);
}
struct mu_cfg_cont *
mu_get_canned_container (const char *name)
{
struct mu_cfg_cont **pcont = mu_assoc_ref (section_tab, name);
return pcont ? *pcont : NULL;
}
static struct mu_cfg_cont *root_container;
int
mu_config_create_container (struct mu_cfg_cont **pcont,
enum mu_cfg_cont_type type)
{
struct mu_cfg_cont *cont;
int rc;
cont = calloc (1, sizeof (*cont));
if (!cont)
return ENOMEM;
rc = mu_refcount_create (&cont->refcount);
if (rc)
free (cont);
else
{
cont->type = type;
*pcont = cont;
}
return rc;
}
struct dup_data
{
struct mu_cfg_cont *cont;
};
static int dup_container (struct mu_cfg_cont **pcont);
static int
_dup_cont_action (void *item, void *cbdata)
{
int rc;
struct mu_cfg_cont *cont = item;
struct dup_data *pdd = cbdata;
rc = dup_container (&cont);
if (rc)
return rc;
if (!pdd->cont->v.section.children)
{
int rc = mu_list_create (&pdd->cont->v.section.children);
if (rc)
return rc;
}
return mu_list_append (pdd->cont->v.section.children, cont);
}
static int
dup_container (struct mu_cfg_cont **pcont)
{
int rc;
struct mu_cfg_cont *newcont, *oldcont = *pcont;
struct dup_data dd;
rc = mu_config_create_container (&newcont, oldcont->type);
if (rc)
return rc;
dd.cont = newcont;
switch (oldcont->type)
{
case mu_cfg_cont_section:
newcont->v.section.ident = oldcont->v.section.ident;
newcont->v.section.label = oldcont->v.section.label;
newcont->v.section.parser = oldcont->v.section.parser;
newcont->v.section.target = oldcont->v.section.target;
newcont->v.section.docstring = oldcont->v.section.docstring;
newcont->v.section.children = NULL;
mu_list_do (oldcont->v.section.children, _dup_cont_action, &dd);
break;
case mu_cfg_cont_param:
newcont->v.param = oldcont->v.param;
break;
}
*pcont = newcont;
return 0;
}
static void
destroy_list (mu_list_t *plist)
{
mu_list_t list = *plist;
mu_iterator_t itr = NULL;
if (!list)
return;
mu_list_get_iterator (list, &itr);
for (mu_iterator_first (itr); !mu_iterator_is_done (itr);
mu_iterator_next (itr))
{
struct mu_cfg_cont *cont, *p;
mu_iterator_current (itr, (void**)&cont);
p = cont;
mu_config_destroy_container (&p);
if (!p)
mu_list_remove (list, cont);
}
mu_iterator_destroy (&itr);
if (mu_list_is_empty (list))
mu_list_destroy (plist);
}
void
mu_config_destroy_container (struct mu_cfg_cont **pcont)
{
struct mu_cfg_cont *cont = *pcont;
unsigned refcount = mu_refcount_dec (cont->refcount);
/* printf ("destr %p-%s: %d\n", cont, cont->v.section.ident, refcount); */
switch (cont->type)
{
case mu_cfg_cont_section:
destroy_list (&cont->v.section.children);
break;
case mu_cfg_cont_param:
break;
}
if (refcount == 0)
{
free (cont);
*pcont = 0;
}
}
static int
add_parameters (struct mu_cfg_section *sect, struct mu_cfg_param *param)
{
if (!param)
return 0;
if (!sect->children)
mu_list_create (&sect->children);
for (; param->ident; param++)
{
int rc;
struct mu_cfg_cont *container;
if (param->type == mu_cfg_section)
{
container = mu_get_canned_container (param->ident);
if (!container)
{
mu_error (_("INTERNAL ERROR: Requested unknown canned "
"section %s"),
param->ident);
abort ();
}
mu_config_clone_container (container);
}
else
{
rc = mu_config_create_container (&container, mu_cfg_cont_param);
if (rc)
return rc;
container->v.param = *param;
}
mu_list_append (sect->children, container);
}
return 0;
}
static int
_clone_action (void *item, void *cbdata)
{
struct mu_cfg_cont *cont = item;
return mu_config_clone_container (cont);
}
int
mu_config_clone_container (struct mu_cfg_cont *cont)
{
mu_refcount_inc (cont->refcount);
/* printf("clone %p-%s: %d\n", cont, cont->v.section.ident, n); */
switch (cont->type)
{
case mu_cfg_cont_section:
mu_list_do (cont->v.section.children, _clone_action, NULL);
break;
case mu_cfg_cont_param:
break;
}
return 0;
}
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)
{
int rc;
struct mu_cfg_section *root_section;
struct mu_cfg_section *parent;
if (!*proot)
{
rc = mu_config_create_container (proot, mu_cfg_cont_section);
if (rc)
return rc;
memset (&(*proot)->v.section, 0, sizeof (*proot)->v.section);
}
root_section = &(*proot)->v.section;
if (parent_path)
{
if (mu_cfg_find_section (root_section, parent_path, &parent))
return MU_ERR_NOENT;
}
else
parent = root_section;
if (mu_refcount_value ((*proot)->refcount) > 1)
{
/* It is a clone, do copy-on-write */
rc = dup_container (proot);
if (rc)
return rc;
root_section = &(*proot)->v.section;
if (parent_path)
{
if (mu_cfg_find_section (root_section, parent_path, &parent))
return MU_ERR_NOENT;
}
else
parent = root_section;
}
if (ident)
{
struct mu_cfg_cont *container;
struct mu_cfg_section *s;
if (!parent->children)
mu_list_create (&parent->children);
mu_config_create_container (&container, mu_cfg_cont_section);
mu_list_append (parent->children, container);
s = &container->v.section;
s->ident = strdup (ident);
s->label = label ? strdup (label) : NULL;
s->parser = parser;
s->children = NULL;
add_parameters (s, param);
if (psection)
*psection = s;
}
else
{
add_parameters (parent, param);
/* FIXME: */
if (!parent->parser)
parent->parser = parser;
if (psection)
*psection = parent;
}
return 0;
}
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)
{
return _mu_config_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 strcmp (node->tag_label, label);
return 0;
}
static char *
make_file_name (const char *dir, const char *file)
{
char *tmp;
size_t len = strlen (dir) + 1 + strlen (file);
tmp = malloc (len + 1);
if (!tmp)
{
mu_error ("%s", mu_strerror (errno));
exit (1);
}
strcpy (tmp, dir);
strcat (tmp, "/");
strcat (tmp, file);
return tmp;
}
struct include_data
{
const char *progname;
struct mu_cfg_param *progparam;
int flags;
void *target;
};
static int
_cb_include (mu_debug_t debug, void *data, char *arg)
{
int ret = 0;
struct stat sb;
char *dirname = arg;
struct include_data *idp = data;
char *tmp = NULL;
if (dirname[0] != '/')
dirname = tmp = make_file_name (SYSCONFDIR, dirname);
if (stat (dirname, &sb) == 0)
{
if (S_ISDIR (sb.st_mode))
{
char *file = make_file_name (dirname, idp->progname);
ret = mu_get_config (file, idp->progname, idp->progparam, 0,
idp->target);
}
else
ret = mu_get_config (dirname, idp->progname, idp->progparam,
idp->flags, idp->target);
}
else if (errno == ENOENT)
{
mu_cfg_format_error (debug, MU_DEBUG_ERROR,
_("include file or directory does not exist"));
ret = 1;
}
else
{
mu_cfg_format_error (debug, MU_DEBUG_ERROR,
_("cannot stat include file or directory: %s"),
mu_strerror (errno));
ret = 1;
}
free (tmp);
return ret;
}
struct mu_cfg_cont *
mu_build_container (const char *progname,
struct mu_cfg_param *progparam, int flags, void *target)
{
struct mu_cfg_cont *cont = root_container;
struct include_data idata;
struct mu_cfg_param mu_include_param[] = {
{ "include", mu_cfg_callback, &idata, 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_config_clone_container (cont);
idata.progname = progname;
idata.progparam = progparam;
idata.flags = flags & MU_PARSE_CONFIG_GLOBAL;
idata.target = target;
_mu_config_register_section (&cont, NULL, NULL, NULL,
(void*) progname, mu_include_param, NULL);
if (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 };
if (!progparam)
progparam = &empty_param;
_mu_config_register_section (&cont, NULL, "program", progname,
prog_parser, progparam, &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 (progparam)
_mu_config_register_section (&cont, NULL, NULL, NULL, NULL,
progparam, NULL);
return cont;
}
int
mu_cfg_tree_reduce (mu_cfg_tree_t *parse_tree, const char *progname,
struct mu_cfg_param *progparam, int flags,
void *target_ptr)
{
int rc = 1;
if (root_container)
{
struct mu_cfg_cont *cont = mu_build_container (progname, progparam,
flags, target_ptr);
rc = mu_cfg_scan_tree (parse_tree, &cont->v.section, target_ptr,
(void*) progname);
mu_config_destroy_container (&cont);
}
if (flags & MU_PARSE_CONFIG_DUMP)
{
mu_stream_t stream;
mu_stdio_stream_create (&stream, stderr,
MU_STREAM_NO_CHECK|MU_STREAM_NO_CLOSE);
mu_stream_open (stream);
mu_cfg_format_parse_tree (stream, parse_tree);
mu_stream_destroy (&stream, NULL);
}
return rc;
}
void
mu_format_config_tree (mu_stream_t stream, const char *progname,
struct mu_cfg_param *progparam, int flags)
{
struct mu_cfg_cont *cont = mu_build_container (progname, progparam, flags,
NULL);
mu_cfg_format_container (stream, cont);
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, "/", NULL);
if (full_name)
{
if (access (full_name, R_OK) == 0)
{
rc = mu_get_config (full_name, progname, progparam, flags,
target_ptr);
free (full_name);
}
else
rc = ENOENT;
}
else
rc = ENOMEM;
return rc;
}
......@@ -172,6 +172,8 @@ mu_cfg_data_type_string (enum mu_cfg_param_data_type type)
return N_("host");
case mu_cfg_callback:
return N_("string");
case mu_cfg_section:
return N_("section");
}
return N_("unknown");
}
......@@ -261,19 +263,16 @@ format_section (mu_stream_t stream, struct mu_cfg_section *sect, int level)
if (sect->ident)
{
mu_stream_sequential_write (stream, sect->ident, strlen (sect->ident));
if (sect->data)
if (sect->label)
{
/* FIXME: This is wrong in general. Data is an opaque data
pointer. */
char *s = sect->data;
mu_stream_sequential_write (stream, " ", 1);
mu_stream_sequential_write (stream, s, strlen (s));
mu_stream_sequential_write (stream, sect->label,
strlen (sect->label));
}
mu_stream_sequential_write (stream, " {\n", 3);
c.stream = stream;
c.level = level + 1;
mu_list_do (sect->subsec, _f_helper, &c);
mu_list_do (sect->param, _f_helper, &c);
mu_list_do (sect->children, _f_helper, &c);
format_level (stream, level);
mu_stream_sequential_write (stream, "};\n\n", 4);
}
......@@ -281,8 +280,7 @@ format_section (mu_stream_t stream, struct mu_cfg_section *sect, int level)
{
c.stream = stream;
c.level = level;
mu_list_do (sect->subsec, _f_helper, &c);
mu_list_do (sect->param, _f_helper, &c);
mu_list_do (sect->children, _f_helper, &c);
}
}
......
......@@ -25,17 +25,12 @@
#include <errno.h>
#include <unistd.h>
#include <ctype.h>
#include <mailutils/errno.h>
#include <mailutils/error.h>
#include <mailutils/argcv.h>
#include <mailutils/nls.h>
#include <mailutils/cfg.h>
#include <mailutils/errno.h>
#include <mailutils/error.h>
#include <mailutils/mutil.h>
#include <mailutils/monitor.h>
#include <mailutils/refcount.h>
#include <mailutils/list.h>
#include <mailutils/iterator.h>
#include <mailutils/stream.h>
#include "cfg_parser.h"
......@@ -350,497 +345,9 @@ again:
}
static struct mu_cfg_cont *root_container;
int
mu_config_create_container (struct mu_cfg_cont **pcont,
enum mu_cfg_cont_type type)
{
struct mu_cfg_cont *cont;
int rc;
cont = calloc (1, sizeof (*cont));
if (!cont)
return ENOMEM;
rc = mu_refcount_create (&cont->refcount);
if (rc)
free (cont);
else
{
cont->type = type;
*pcont = cont;
}
return rc;
}
struct dup_data
{
struct mu_cfg_cont *cont;
};
static int dup_container (struct mu_cfg_cont **pcont);
static int
_dup_section_action (void *item, void *cbdata)
{
int rc;
struct mu_cfg_cont *cont = item;
struct dup_data *pdd = cbdata;
rc = dup_container (&cont);
if (rc)
return rc;
if (!pdd->cont->v.section.subsec)
{
int rc = mu_list_create (&pdd->cont->v.section.subsec);
if (rc)
return rc;
}
return mu_list_append (pdd->cont->v.section.subsec, cont);
}
static int
_dup_param_action (void *item, void *cbdata)
{
int rc;
struct mu_cfg_cont *cont = item;
struct dup_data *pdd = cbdata;
rc = dup_container (&cont);
if (rc)
return rc;
if (!pdd->cont->v.section.param)
{
rc = mu_list_create (&pdd->cont->v.section.param);
if (rc)
return rc;
}
return mu_list_append (pdd->cont->v.section.param, cont);
}
static int
dup_container (struct mu_cfg_cont **pcont)
{
int rc;
struct mu_cfg_cont *newcont, *oldcont = *pcont;
struct dup_data dd;
rc = mu_config_create_container (&newcont, oldcont->type);
if (rc)
return rc;
dd.cont = newcont;
switch (oldcont->type)
{
case mu_cfg_cont_section:
newcont->v.section.ident = oldcont->v.section.ident;
newcont->v.section.parser = oldcont->v.section.parser;
newcont->v.section.data = oldcont->v.section.data;
newcont->v.section.docstring = oldcont->v.section.docstring;
newcont->v.section.subsec = NULL;
newcont->v.section.param = NULL;
mu_list_do (oldcont->v.section.subsec, _dup_section_action, &dd);
mu_list_do (oldcont->v.section.param, _dup_param_action, &dd);
break;
case mu_cfg_cont_param:
newcont->v.param = oldcont->v.param;
break;
}
*pcont = newcont;
return 0;
}
static void
destroy_list (mu_list_t *plist)
{
mu_list_t list = *plist;
mu_iterator_t itr = NULL;
if (!list)
return;
mu_list_get_iterator (list, &itr);
for (mu_iterator_first (itr); !mu_iterator_is_done (itr);
mu_iterator_next (itr))
{
struct mu_cfg_cont *cont, *p;
mu_iterator_current (itr, (void**)&cont);
p = cont;
mu_config_destroy_container (&p);
if (!p)
mu_list_remove (list, cont);
}
mu_iterator_destroy (&itr);
if (mu_list_is_empty (list))
mu_list_destroy (plist);
}
void
mu_config_destroy_container (struct mu_cfg_cont **pcont)
{
struct mu_cfg_cont *cont = *pcont;
unsigned refcount = mu_refcount_dec (cont->refcount);
/* printf ("destr %p-%s: %d\n", cont, cont->v.section.ident, refcount); */
switch (cont->type)
{
case mu_cfg_cont_section:
destroy_list (&cont->v.section.subsec);
destroy_list (&cont->v.section.param);
break;
case mu_cfg_cont_param:
break;
}
if (refcount == 0)
{
free (cont);
*pcont = 0;
}
}
static int
add_parameters (struct mu_cfg_section *sect, struct mu_cfg_param *param)
{
if (!param)
return 0;
if (!sect->param)
mu_list_create (&sect->param);
for (; param->ident; param++)
{
int rc;
struct mu_cfg_cont *container;
rc = mu_config_create_container (&container, mu_cfg_cont_param);
if (rc)
return rc;
container->v.param = *param;
mu_list_append (sect->param, container);
}
return 0;
}
static int
_clone_action (void *item, void *cbdata)
{
struct mu_cfg_cont *cont = item;
return mu_config_clone_container (cont);
}
int
mu_config_clone_container (struct mu_cfg_cont *cont)
{
mu_refcount_inc (cont->refcount);
/* printf("clone %p-%s: %d\n", cont, cont->v.section.ident, n); */
switch (cont->type)
{
case mu_cfg_cont_section:
mu_list_do (cont->v.section.subsec, _clone_action, NULL);
mu_list_do (cont->v.section.param, _clone_action, NULL);
break;
case mu_cfg_cont_param:
break;
}
return 0;
}
int
_mu_config_register_section (struct mu_cfg_cont **proot,
const char *parent_path,
const char *ident,
mu_cfg_section_fp parser,
void *data,
struct mu_cfg_param *param,
struct mu_cfg_section **psection)
{
int rc;
struct mu_cfg_section *root_section;
struct mu_cfg_section *parent;
if (!*proot)
{
rc = mu_config_create_container (proot, mu_cfg_cont_section);
if (rc)
return rc;
memset (&(*proot)->v.section, 0, sizeof (*proot)->v.section);
}
root_section = &(*proot)->v.section;
if (parent_path)
{
if (mu_cfg_find_section (root_section, parent_path, &parent))
return MU_ERR_NOENT;
}
else
parent = root_section;
if (mu_refcount_value ((*proot)->refcount) > 1)
{
/* It is a clone, do copy-on-write */
rc = dup_container (proot);
if (rc)
return rc;
root_section = &(*proot)->v.section;
if (parent_path)
{
if (mu_cfg_find_section (root_section, parent_path, &parent))
return MU_ERR_NOENT;
}
else
parent = root_section;
}
if (ident)
{
struct mu_cfg_cont *container;
struct mu_cfg_section *s;
if (!parent->subsec)
mu_list_create (&parent->subsec);
mu_config_create_container (&container, mu_cfg_cont_section);
mu_list_append (parent->subsec, container);
s = &container->v.section;
s->ident = strdup (ident);
s->parser = parser;
s->data = data;
s->subsec = NULL;
s->param = NULL;
add_parameters (s, param);
if (psection)
*psection = s;
}
else
{
add_parameters (parent, param);
if (!parent->parser)
parent->parser = parser;
if (!parent->data)
parent->data = data;
if (psection)
*psection = parent;
}
return 0;
}
int
mu_config_register_section (const char *parent_path,
const char *ident,
mu_cfg_section_fp parser,
void *data,
struct mu_cfg_param *param)
{
return _mu_config_register_section (&root_container,
parent_path,
ident, parser, data, 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,
void *section_data, void *call_data,
mu_cfg_tree_t *tree)
{
if (stage == mu_cfg_section_start)
{
return strcmp (node->tag_label, call_data);
}
return 0;
}
static char *
make_file_name (const char *dir, const char *file)
{
char *tmp;
size_t len = strlen (dir) + 1 + strlen (file);
tmp = malloc (len + 1);
if (!tmp)
{
mu_error ("%s", mu_strerror (errno));
exit (1);
}
strcpy (tmp, dir);
strcat (tmp, "/");
strcat (tmp, file);
return tmp;
}
struct include_data
{
const char *progname;
struct mu_cfg_param *progparam;
int flags;
};
static int _mu_parse_config (const char *file, const char *progname,
struct mu_cfg_param *progparam, int flags);
static int
_cb_include (mu_debug_t debug, void *data, char *arg)
{
int ret = 0;
struct stat sb;
char *dirname = arg;
struct include_data *idp = data;
char *tmp = NULL;
if (dirname[0] != '/')
dirname = tmp = make_file_name (SYSCONFDIR, dirname);
if (stat (dirname, &sb) == 0)
{
if (S_ISDIR (sb.st_mode))
{
char *file = make_file_name (dirname, idp->progname);
ret = _mu_parse_config (file, idp->progname, idp->progparam, 0);
}
else
ret = _mu_parse_config (dirname, idp->progname, idp->progparam,
idp->flags);
}
else if (errno == ENOENT)
{
mu_cfg_format_error (debug, MU_DEBUG_ERROR,
_("include file or directory does not exist"));
ret = 1;
}
else
{
mu_cfg_format_error (debug, MU_DEBUG_ERROR,
_("cannot stat include file or directory: %s"),
mu_strerror (errno));
ret = 1;
}
free (tmp);
return ret;
}
struct mu_cfg_cont *
mu_build_container (const char *progname,
struct mu_cfg_param *progparam, int flags)
{
struct mu_cfg_cont *cont = root_container;
struct include_data idata;
struct mu_cfg_param mu_include_param[] = {
{ "include", mu_cfg_callback, &idata, _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_config_clone_container (cont);
idata.progname = progname;
idata.progparam = progparam;
idata.flags = flags & MU_PARSE_CONFIG_GLOBAL;
_mu_config_register_section (&cont, NULL, NULL, NULL,
(void*) progname, mu_include_param, NULL);
if (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 };
if (!progparam)
progparam = &empty_param;
_mu_config_register_section (&cont, NULL, "program", prog_parser,
(void*) progname,
progparam, &prog_sect);
if (old_root->v.section.subsec)
{
if (!prog_sect->subsec)
mu_list_create (&prog_sect->subsec);
mu_list_get_iterator (old_root->v.section.subsec, &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->subsec, c);
}
mu_iterator_destroy (&iter);
}
if (old_root->v.section.param)
{
if (!prog_sect->param)
mu_list_create (&prog_sect->param);
mu_list_get_iterator (old_root->v.section.param, &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->param, c);
}
mu_iterator_destroy (&iter);
}
}
else if (progparam)
_mu_config_register_section (&cont, NULL, NULL, NULL, NULL,
progparam, NULL);
return cont;
}
int
mu_parse_config_tree (mu_cfg_tree_t *parse_tree, const char *progname,
struct mu_cfg_param *progparam, int flags)
{
int rc = 1;
if (root_container)
{
struct mu_cfg_cont *cont = mu_build_container (progname, progparam,
flags);
rc = mu_cfg_scan_tree (parse_tree, &cont->v.section, (void*) progname);
mu_config_destroy_container (&cont);
}
if (flags & MU_PARSE_CONFIG_DUMP)
{
mu_stream_t stream;
mu_stdio_stream_create (&stream, stderr,
MU_STREAM_NO_CHECK|MU_STREAM_NO_CLOSE);
mu_stream_open (stream);
mu_cfg_format_parse_tree (stream, parse_tree);
mu_stream_destroy (&stream, NULL);
}
return rc;
}
void
mu_format_config_tree (mu_stream_t stream, const char *progname,
struct mu_cfg_param *progparam, int flags)
{
struct mu_cfg_cont *cont = mu_build_container (progname, progparam, flags);
mu_cfg_format_container (stream, cont);
mu_config_destroy_container (&cont);
}
static int
_mu_parse_config (const char *file, const char *progname,
struct mu_cfg_param *progparam, int flags)
mu_get_config (const char *file, const char *progname,
struct mu_cfg_param *progparam, int flags, void *target_ptr)
{
struct lexer_data data;
struct stat st;
......@@ -883,7 +390,8 @@ _mu_parse_config (const char *file, const char *progname,
NULL);
if (rc == 0)
rc = mu_parse_config_tree (parse_tree, progname, progparam, flags);
rc = mu_cfg_tree_reduce (parse_tree, progname, progparam, flags,
target_ptr);
mu_cfg_destroy_tree (&parse_tree);
mu_list_destroy (&data.mpool);
......@@ -896,23 +404,3 @@ _mu_parse_config (const char *file, const char *progname,
return rc;
}
int
mu_parse_config (const char *file, const char *progname,
struct mu_cfg_param *progparam, int flags)
{
int rc;
char *full_name = mu_tilde_expansion (file, "/", NULL);
if (full_name)
{
if (access (full_name, R_OK) == 0)
{
rc = _mu_parse_config (full_name, progname, progparam, flags);
free (full_name);
}
else
rc = ENOENT;
}
else
rc = ENOMEM;
return rc;
}
......
......@@ -497,13 +497,15 @@ struct mu_cfg_section_list
struct scan_tree_data
{
struct mu_cfg_section_list *list;
void *target;
void *call_data;
mu_cfg_tree_t *tree;
int error;
};
static struct mu_cfg_cont *
find_container (mu_list_t list, const char *ident, size_t len)
find_container (mu_list_t list, enum mu_cfg_cont_type type,
const char *ident, size_t len)
{
mu_iterator_t iter;
struct mu_cfg_cont *ret = NULL;
......@@ -518,7 +520,8 @@ find_container (mu_list_t list, const char *ident, size_t len)
struct mu_cfg_cont *cont;
mu_iterator_current (iter, (void**) &cont);
if (strlen (cont->v.ident) == len
if (cont->type == type
&& strlen (cont->v.ident) == len
&& memcmp (cont->v.ident, ident, len) == 0)
{
ret = cont;
......@@ -534,9 +537,11 @@ find_subsection (struct mu_cfg_section *sec, const char *ident, size_t len)
{
if (sec)
{
if (sec->subsec)
if (sec->children)
{
struct mu_cfg_cont *cont = find_container (sec->subsec, ident, len);
struct mu_cfg_cont *cont = find_container (sec->children,
mu_cfg_cont_section,
ident, len);
if (cont)
return &cont->v.section;
}
......@@ -549,9 +554,11 @@ find_param (struct mu_cfg_section *sec, const char *ident, size_t len)
{
if (sec)
{
if (sec->param)
if (sec->children)
{
struct mu_cfg_cont *cont = find_container (sec->param, ident, len);
struct mu_cfg_cont *cont = find_container (sec->children,
mu_cfg_cont_param,
ident, len);
if (cont)
return &cont->v.param;
}
......@@ -842,8 +849,10 @@ parse_bool (struct scan_tree_data *sdata, const mu_cfg_node_t *node, int *res)
static int
parse_param (struct scan_tree_data *sdata, const mu_cfg_node_t *node)
{
void *tgt;
struct mu_cfg_param *param = find_param (sdata->list->sec, node->tag_name,
0);
if (!param)
{
_mu_cfg_perror (sdata->tree->debug, &node->locus,
......@@ -852,6 +861,22 @@ parse_param (struct scan_tree_data *sdata, const mu_cfg_node_t *node)
return 1;
}
if (param->data)
tgt = param->data;
else if (sdata->list->sec->target)
tgt = (char*)sdata->list->sec->target + param->offset;
else if (sdata->target)
tgt = (char*)sdata->target + param->offset;
else if (param->type == mu_cfg_callback)
tgt = NULL;
else
{
_mu_cfg_perror (sdata->tree->debug, &node->locus,
_("INTERNAL ERROR: cannot determine target offset for "
"%s"), param->ident);
abort ();
}
switch (param->type)
{
case mu_cfg_string:
......@@ -865,80 +890,80 @@ parse_param (struct scan_tree_data *sdata, const mu_cfg_node_t *node)
return 1;
}
strcpy (s, node->tag_label);
/* FIXME: free param->data? */
*(char**)param->data = s;
/* FIXME: free tgt? */
*(char**)tgt = s;
break;
}
case mu_cfg_short:
GETSNUM (node->tag_label, short, *(short*)param->data,
GETSNUM (node->tag_label, short, *(short*)tgt,
sdata->tree->debug);
break;
case mu_cfg_ushort:
GETUNUM (node->tag_label, unsigned short, *(unsigned short*)param->data,
GETUNUM (node->tag_label, unsigned short, *(unsigned short*)tgt,
sdata->tree->debug);
break;
case mu_cfg_int:
GETSNUM (node->tag_label, int, *(int*)param->data, sdata->tree->debug);
GETSNUM (node->tag_label, int, *(int*)tgt, sdata->tree->debug);
break;
case mu_cfg_uint:
GETUNUM (node->tag_label, unsigned int, *(unsigned int*)param->data,
GETUNUM (node->tag_label, unsigned int, *(unsigned int*)tgt,
sdata->tree->debug);
break;
case mu_cfg_long:
GETSNUM (node->tag_label, long, *(long*)param->data,
GETSNUM (node->tag_label, long, *(long*)tgt,
sdata->tree->debug);
break;
case mu_cfg_ulong:
GETUNUM (node->tag_label, unsigned long, *(unsigned long*)param->data,
GETUNUM (node->tag_label, unsigned long, *(unsigned long*)tgt,
sdata->tree->debug);
break;
case mu_cfg_size:
GETUNUM (node->tag_label, size_t, *(size_t*)param->data,
GETUNUM (node->tag_label, size_t, *(size_t*)tgt,
sdata->tree->debug);
break;
case mu_cfg_off:
_mu_cfg_perror (sdata->tree->debug, &node->locus,
_("not implemented yet"));
/* GETSNUM(node->tag_label, off_t, *(off_t*)param->data); */
/* GETSNUM(node->tag_label, off_t, *(off_t*)tgt); */
return 1;
case mu_cfg_time:
GETUNUM (node->tag_label, time_t, *(time_t*)param->data,
GETUNUM (node->tag_label, time_t, *(time_t*)tgt,
sdata->tree->debug);
break;
case mu_cfg_bool:
if (parse_bool (sdata, node, (int*) param->data))
if (parse_bool (sdata, node, (int*) tgt))
return 1;
break;
case mu_cfg_ipv4:
if (parse_ipv4 (sdata, node, (struct in_addr *)param->data))
if (parse_ipv4 (sdata, node, (struct in_addr *)tgt))
return 1;
break;
case mu_cfg_cidr:
if (parse_cidr (sdata, node, (mu_cfg_cidr_t *)param->data))
if (parse_cidr (sdata, node, (mu_cfg_cidr_t *)tgt))
return 1;
break;
case mu_cfg_host:
if (parse_host (sdata, node, (struct in_addr *)param->data))
if (parse_host (sdata, node, (struct in_addr *)tgt))
return 1;
break;
case mu_cfg_callback:
mu_debug_set_locus (sdata->tree->debug, node->locus.file,
node->locus.line);
if (param->callback (sdata->tree->debug, param->data, node->tag_label))
if (param->callback (sdata->tree->debug, tgt, node->tag_label))
return 1;
break;
......@@ -972,11 +997,12 @@ _scan_tree_helper (const mu_cfg_node_t *node, void *data)
}
return MU_CFG_ITER_SKIP;
}
if (!sec->subsec && !sec->param)
if (!sec->children)
return MU_CFG_ITER_SKIP;
if (sec->parser &&
sec->parser (mu_cfg_section_start, node,
sec->data, sdata->call_data, sdata->tree))
sec->label, &sec->target,
sdata->call_data, sdata->tree))
{
sdata->error++;
return MU_CFG_ITER_SKIP;
......@@ -1010,7 +1036,8 @@ _scan_tree_end_helper (const mu_cfg_node_t *node, void *data)
sec = pop_section (sdata);
if (sec && sec->parser)
{
if (sec->parser (mu_cfg_section_end, node, sec->data,
if (sec->parser (mu_cfg_section_end, node,
sec->label, &sec->target,
sdata->call_data, sdata->tree))
{
sdata->error++;
......@@ -1023,13 +1050,14 @@ _scan_tree_end_helper (const mu_cfg_node_t *node, void *data)
int
mu_cfg_scan_tree (mu_cfg_tree_t *tree, struct mu_cfg_section *sections,
void *data)
void *target, void *data)
{
struct scan_tree_data dat;
dat.tree = tree;
dat.list = NULL;
dat.error = 0;
dat.call_data = data;
dat.target = target;
if (push_section (&dat, sections))
return 1;
mu_cfg_preorder (tree->node, _scan_tree_helper, _scan_tree_end_helper, &dat);
......
......@@ -166,13 +166,13 @@ cb_metamail (mu_debug_t debug, void *data, char *arg)
}
struct mu_cfg_param mimeview_cfg_param[] = {
{ "debug", mu_cfg_callback, NULL, cb_debug,
{ "debug", mu_cfg_callback, NULL, 0, cb_debug,
N_("Set debug verbosity level."),
N_("flags") },
{ "mimetypes", mu_cfg_string, &mimetypes_config, NULL,
{ "mimetypes", mu_cfg_string, &mimetypes_config, 0, NULL,
N_("Use this mime.types file."),
N_("file") },
{ "metamail", mu_cfg_string, NULL, cb_metamail,
{ "metamail", mu_cfg_string, NULL, 0, cb_metamail,
N_("Use this program to display files."),
N_("prog") },
{ NULL }
......
......@@ -90,11 +90,11 @@ static struct argp argp = {
struct mu_cfg_param movemail_cfg_param[] = {
{ "preserve", mu_cfg_bool, &preserve_mail, NULL,
{ "preserve", mu_cfg_bool, &preserve_mail, 0, NULL,
N_("Do not remove messages from the source mailbox.") },
{ "reverse", mu_cfg_bool, &reverse_order, NULL,
{ "reverse", mu_cfg_bool, &reverse_order, 0, NULL,
N_("Reverse message sorting order.") },
{ "emacs", mu_cfg_bool, &emacs_mode, NULL,
{ "emacs", mu_cfg_bool, &emacs_mode, 0, NULL,
N_("Output information used by Emacs rmail interface.") },
{ NULL }
};
......
......@@ -134,28 +134,28 @@ cb_bulletin_db (mu_debug_t debug, void *data, char *arg)
}
static struct mu_cfg_param pop3d_cfg_param[] = {
{ "undelete", mu_cfg_int, &undelete_on_startup, NULL,
{ "undelete", mu_cfg_int, &undelete_on_startup, 0, NULL,
N_("On startup, clear deletion marks from all the messages.") },
{ "expire", mu_cfg_uint, &expire, NULL,
{ "expire", mu_cfg_uint, &expire, 0, NULL,
N_("Automatically expire read messages after the given number of days."),
N_("days") },
{ "delete-expired", mu_cfg_int, &expire_on_exit, NULL,
{ "delete-expired", mu_cfg_int, &expire_on_exit, 0, NULL,
N_("Delete expired messages upon closing the mailbox.") },
#ifdef WITH_TLS
{ "tls-required", mu_cfg_callback, NULL, cb_tls_required,
{ "tls-required", mu_cfg_callback, NULL, 0, cb_tls_required,
N_("Always require STLS before entering authentication phase.") },
#endif
#ifdef ENABLE_LOGIN_DELAY
{ "login-delay", mu_cfg_time, &login_delay, NULL,
{ "login-delay", mu_cfg_time, &login_delay, 0, NULL,
N_("Set the minimal allowed delay between two successive logins.") },
{ "stat-file", mu_cfg_string, &login_stat_file, NULL,
{ "stat-file", mu_cfg_string, &login_stat_file, 0, NULL,
N_("Set the name of login statistics file (for login-delay).") },
#endif
{ "bulletin-source", mu_cfg_callback, NULL, cb_bulletin_source,
{ "bulletin-source", mu_cfg_callback, NULL, 0, cb_bulletin_source,
N_("Get bulletins from the specified mailbox."),
N_("url") },
#ifdef USE_DBM
{ "bulletin-db", mu_cfg_callback, NULL, cb_bulletin_db,
{ "bulletin-db", mu_cfg_callback, NULL, 0, cb_bulletin_db,
N_("Set the bulletin database file name."),
N_("file") },
#endif
......
......@@ -129,21 +129,21 @@ readmsg_parse_opt (int key, char *arg, struct argp_state *astate)
struct mu_cfg_param readmsg_cfg_param[] = {
{ "debug", mu_cfg_int, &dbug, NULL,
{ "debug", mu_cfg_int, &dbug, 0, NULL,
N_("Set debug verbosity level.") },
{ "header", mu_cfg_bool, &all_header, NULL,
{ "header", mu_cfg_bool, &all_header, 0, NULL,
N_("Display entire headers.") },
{ "weedlist", mu_cfg_string, &weedlist, NULL,
{ "weedlist", mu_cfg_string, &weedlist, 0, NULL,
N_("Display only headers from this list. Argument is a list of header "
"names separated by whitespace or commas."),
N_("list") },
{ "folder", mu_cfg_string, &mailbox_name, NULL,
{ "folder", mu_cfg_string, &mailbox_name, 0, NULL,
N_("Read messages from this folder.") },
{ "no-header", mu_cfg_bool, &no_header, NULL,
{ "no-header", mu_cfg_bool, &no_header, 0, NULL,
N_("Exclude all headers.") },
{ "form-feeds", mu_cfg_bool, &form_feed, NULL,
{ "form-feeds", mu_cfg_bool, &form_feed, 0, NULL,
N_("Output formfeed character between messages.") },
{ "show-all-match", mu_cfg_bool, &show_all, NULL,
{ "show-all-match", mu_cfg_bool, &show_all, 0, NULL,
N_("Print all messages matching pattern, not only the first.") },
{ NULL }
};
......
......@@ -287,15 +287,15 @@ cb_ticket (mu_debug_t debug, void *data, char *arg)
}
static struct mu_cfg_param sieve_cfg_param[] = {
{ "keep-going", mu_cfg_int, &keep_going, NULL,
{ "keep-going", mu_cfg_int, &keep_going, 0, NULL,
N_("Do not abort if execution fails on a message.") },
{ "mbox-url", mu_cfg_string, &mbox_url, NULL,
{ "mbox-url", mu_cfg_string, &mbox_url, 0, NULL,
N_("Mailbox to sieve (defaults to user's mail spool)."),
N_("url") },
{ "ticket", mu_cfg_callback, NULL, cb_ticket,
{ "ticket", mu_cfg_callback, NULL, 0, cb_ticket,
N_("Ticket file for user authentication."),
N_("ticket") },
{ "debug", mu_cfg_callback, NULL, cb_debug,
{ "debug", mu_cfg_callback, NULL, 0, cb_debug,
N_("Debug flags. Argument consists of one or more of the following "
"flags:\n"
" g - main parser traces\n"
......@@ -303,11 +303,11 @@ static struct mu_cfg_param sieve_cfg_param[] = {
" P - network protocols (MU_DEBUG_PROT)\n"
" t - sieve trace (MU_SIEVE_DEBUG_TRACE)\n"
" i - sieve instructions trace (MU_SIEVE_DEBUG_INSTR).") },
{ "verbose", mu_cfg_bool, &verbose, NULL,
{ "verbose", mu_cfg_bool, &verbose, 0, NULL,
N_("Log all executed actions.") },
{ "line-info", mu_cfg_bool, &sieve_print_locus, NULL,
{ "line-info", mu_cfg_bool, &sieve_print_locus, 0, NULL,
N_("Print source locations along with action logs (default).") },
{ "email", mu_cfg_callback, NULL, cb_email,
{ "email", mu_cfg_callback, NULL, 0, cb_email,
N_("Set user email address.") },
{ NULL }
};
......