summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2007-11-07 22:32:26 +0000
committerSergey Poznyakoff <gray@gnu.org.ua>2007-11-07 22:32:26 +0000
commit6bd4a8b2ed555986e20ad09e11d6a95470a9be71 (patch)
treefd4460349b8bdf053639bcc9db9870ddb7350e18
parent6c26e9b60fc16d4b4afa64f6a2128ada847c7084 (diff)
downloadmailutils-6bd4a8b2ed555986e20ad09e11d6a95470a9be71.tar.gz
mailutils-6bd4a8b2ed555986e20ad09e11d6a95470a9be71.tar.bz2
* include/mailutils/argp.h (mu_argp_set_config_param): New
function. * include/mailutils/cfg.h (mu_cfg_time): New value (struct mu_cfg_section): Rewamp using lists. (enum mu_cfg_cont_type, struct mu_cfg_cont): New types. (mu_config_create_container, mu_config_clone_container) (mu_config_destroy_container): New functions. (mu_parse_config): New function. * include/mailutils/mu_auth.h (mu_authentication_clear_list) (mu_authorization_clear_list): New functions. * mailbox/cfg_lexer.c: Add missing includes (mu_config_create_container, mu_config_clone_container) (mu_config_destroy_container): New functions. (mu_parse_config): New function. (_mu_config_register_section): New function. (mu_config_register_section): New function. (_mu_parse_config): Fully implement system-wide/per-user configuration semantics. (mu_parse_config): Take two more arguments. * mailbox/cfg_parser.h: Remove automatically generated file. * mailbox/cfg_parser.y (find_container): New function (find_subsection,find_param): Rewrite using find_container (parse_param): Implement new data type mu_cfg_time (time_t value). (_scan_tree_helper): Complain about unknown sections only if MU_CONFIG_VERBOSE environment variable is set. * mailbox/mu_argp.c (assign_string): Bugfix. (mu_argp_set_config_param): New function. (mu_argp_parse): Remove eventual `lt-' prefix from program names. * mailbox/mu_auth.c: New options --clear-authorization and --clear-authentication. (mu_authorization_clear_list,mu_authentication_clear_list): New functions. * include/mailutils/refcount.h (struct _mu_refcount): Move ro refcount.c (mu_refcount_inc,mu_refcount_dec): Change return value. (mu_refcount_value): New function. * mailbox/refcount.c (struct _mu_refcount): Moved from refcount.h (mu_refcount_value): New function. (mu_refcount_create,mu_refcount_destroy,mu_refcount_inc) (mu_refcount_dec): Fix monitor usage. (mu_refcount_inc,mu_refcount_dec): Fix return type. * mailbox/Makefile.am (libmailutils_la_SOURCES): Add refcount.c * dotlock/dotlock.c, imap4d/imap4d.c, mail.local/main.c, mail.remote/mail.remote.c, mimeview/mimeview.c, movemail/movemail.c, pop3d/pop3d.c, pop3d/signal.c, readmsg/readmsg.c, sieve/sieve.c: Implement new configuration. * testsuite/lib/mailutils.exp: Set MU_CONFIG_FLAVOR envar to `none' to avoid reading configuration files.
-rw-r--r--ChangeLog54
-rw-r--r--dotlock/dotlock.c28
-rw-r--r--imap4d/imap4d.c2
-rw-r--r--include/mailutils/argp.h3
-rw-r--r--include/mailutils/cfg.h31
-rw-r--r--include/mailutils/mu_auth.h2
-rw-r--r--include/mailutils/refcount.h12
-rw-r--r--mail.local/main.c122
-rw-r--r--mail.remote/mail.remote.c10
-rw-r--r--mailbox/Makefile.am1
-rw-r--r--mailbox/cfg_lexer.c368
-rw-r--r--mailbox/cfg_parser.y70
-rw-r--r--mailbox/mu_argp.c17
-rw-r--r--mailbox/mu_auth.c40
-rw-r--r--mailbox/refcount.c29
-rw-r--r--mimeview/mimeview.c56
-rw-r--r--movemail/movemail.c13
-rw-r--r--pop3d/pop3d.c63
-rw-r--r--pop3d/signal.c1
-rw-r--r--readmsg/readmsg.c13
-rw-r--r--sieve/sieve.c215
-rw-r--r--testsuite/lib/mailutils.exp1
22 files changed, 897 insertions, 254 deletions
diff --git a/ChangeLog b/ChangeLog
index 35251378d..90527e55f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,57 @@
+2007-11-08 Sergey Poznyakoff <gray@gnu.org.ua>
+
+ * include/mailutils/argp.h (mu_argp_set_config_param): New
+ function.
+ * include/mailutils/cfg.h (mu_cfg_time): New value
+ (struct mu_cfg_section): Rewamp using lists.
+ (enum mu_cfg_cont_type, struct mu_cfg_cont): New types.
+ (mu_config_create_container, mu_config_clone_container)
+ (mu_config_destroy_container): New functions.
+ (mu_parse_config): New function.
+ * include/mailutils/mu_auth.h (mu_authentication_clear_list)
+ (mu_authorization_clear_list): New functions.
+ * mailbox/cfg_lexer.c: Add missing includes
+ (mu_config_create_container, mu_config_clone_container)
+ (mu_config_destroy_container): New functions.
+ (mu_parse_config): New function.
+ (_mu_config_register_section): New function.
+ (mu_config_register_section): New function.
+ (_mu_parse_config): Fully implement system-wide/per-user
+ configuration semantics.
+ (mu_parse_config): Take two more arguments.
+ * mailbox/cfg_parser.h: Remove automatically generated file.
+ * mailbox/cfg_parser.y (find_container): New function
+ (find_subsection,find_param): Rewrite using find_container
+ (parse_param): Implement new data type mu_cfg_time (time_t value).
+ (_scan_tree_helper): Complain about unknown sections only if
+ MU_CONFIG_VERBOSE environment variable is set.
+ * mailbox/mu_argp.c (assign_string): Bugfix.
+ (mu_argp_set_config_param): New function.
+ (mu_argp_parse): Remove eventual `lt-' prefix from program names.
+ * mailbox/mu_auth.c: New options --clear-authorization and
+ --clear-authentication.
+ (mu_authorization_clear_list,mu_authentication_clear_list): New
+ functions.
+
+ * include/mailutils/refcount.h (struct _mu_refcount): Move ro
+ refcount.c
+ (mu_refcount_inc,mu_refcount_dec): Change return value.
+ (mu_refcount_value): New function.
+ * mailbox/refcount.c (struct _mu_refcount): Moved from refcount.h
+ (mu_refcount_value): New function.
+ (mu_refcount_create,mu_refcount_destroy,mu_refcount_inc)
+ (mu_refcount_dec): Fix monitor usage.
+ (mu_refcount_inc,mu_refcount_dec): Fix return type.
+
+ * mailbox/Makefile.am (libmailutils_la_SOURCES): Add refcount.c
+ * dotlock/dotlock.c, imap4d/imap4d.c, mail.local/main.c,
+ mail.remote/mail.remote.c, mimeview/mimeview.c,
+ movemail/movemail.c, pop3d/pop3d.c, pop3d/signal.c,
+ readmsg/readmsg.c, sieve/sieve.c: Implement new configuration.
+
+ * testsuite/lib/mailutils.exp: Set MU_CONFIG_FLAVOR envar to
+ `none' to avoid reading configuration files.
+
2007-11-06 Sergey Poznyakoff <gray@gnu.org.ua>
* mailbox/message.c (message_stream_size): Bugfix.
diff --git a/dotlock/dotlock.c b/dotlock/dotlock.c
index ef7941945..e5044a9bd 100644
--- a/dotlock/dotlock.c
+++ b/dotlock/dotlock.c
@@ -70,7 +70,7 @@ static const char *file;
static int unlock;
static int flags;
static int retries;
-static int force;
+static time_t force;
static int debug;
static error_t
@@ -102,9 +102,7 @@ parse_opt (int key, char *arg, struct argp_state *state)
force = atoi (arg);
if (force <= 0)
argp_error (state, _("MINUTES must be greater than 0"));
- force *= 60;
}
- flags |= MU_LOCKER_TIME;
break;
case ARGP_KEY_ARG:
@@ -122,6 +120,21 @@ parse_opt (int key, char *arg, struct argp_state *state)
return 0;
}
+
+struct mu_cfg_param dotlock_cfg_param[] = {
+ { "force", mu_cfg_time, &force },
+ { "retry", mu_cfg_int, &retries },
+ { "debug", mu_cfg_bool, &debug },
+ { NULL }
+};
+
+
+
+const char *dotlock_capa[] = {
+ "license",
+ NULL
+};
+
int
main (int argc, char *argv[])
{
@@ -140,8 +153,15 @@ main (int argc, char *argv[])
mu_argp_init (program_version, NULL);
argp_err_exit_status = MU_DL_EX_ERROR;
- argp_parse (&argp, argc, argv, 0, NULL, NULL);
+ mu_argp_set_config_param (dotlock_cfg_param);
+ mu_argp_parse (&argp, &argc, &argv, 0, dotlock_capa, NULL, NULL);
+ if (force)
+ {
+ force *= 60;
+ flags |= MU_LOCKER_TIME;
+ }
+
if ((err = mu_locker_create (&locker, file, flags)))
{
if (debug)
diff --git a/imap4d/imap4d.c b/imap4d/imap4d.c
index b147ea0fa..713c7b823 100644
--- a/imap4d/imap4d.c
+++ b/imap4d/imap4d.c
@@ -204,7 +204,7 @@ main (int argc, char **argv)
#ifdef WITH_GSASL
mu_gsasl_init_argp ();
#endif
- mu_config_register_plain_section (NULL, NULL, imap4d_cfg_param);
+ mu_argp_set_config_param (imap4d_cfg_param);
mu_argp_parse (&argp, &argc, &argv, 0, imap4d_capa, NULL, &daemon_param);
if (login_disabled)
diff --git a/include/mailutils/argp.h b/include/mailutils/argp.h
index 924c9d220..5ed957cb5 100644
--- a/include/mailutils/argp.h
+++ b/include/mailutils/argp.h
@@ -60,7 +60,8 @@ extern int mu_register_capa (const char *name, struct argp_child *child,
extern void mu_print_options (void);
extern const char *mu_check_option (char *name);
-
+extern void mu_argp_set_config_param (struct mu_cfg_param *);
+
#ifdef __cplusplus
}
#endif
diff --git a/include/mailutils/cfg.h b/include/mailutils/cfg.h
index af412d525..cdba5fb6a 100644
--- a/include/mailutils/cfg.h
+++ b/include/mailutils/cfg.h
@@ -98,6 +98,7 @@ enum mu_cfg_param_data_type
mu_cfg_ulong,
mu_cfg_size,
mu_cfg_off,
+ mu_cfg_time,
mu_cfg_bool,
mu_cfg_ipv4,
mu_cfg_cidr,
@@ -130,8 +131,26 @@ struct mu_cfg_section
const char *ident;
mu_cfg_section_fp parser;
void *data;
- struct mu_cfg_section *subsec;
- struct mu_cfg_param *param;
+ mu_list_t /* of mu_cfg_cont/mu_cfg_section */ subsec;
+ mu_list_t /* of mu_cfg_cont/mu_cfg_param */ param;
+};
+
+enum mu_cfg_cont_type
+ {
+ mu_cfg_cont_section,
+ mu_cfg_cont_param
+ };
+
+struct mu_cfg_cont
+{
+ enum mu_cfg_cont_type type;
+ mu_refcount_t refcount;
+ union
+ {
+ const char *ident;
+ struct mu_cfg_section section;
+ struct mu_cfg_param param;
+ } v;
};
typedef struct mu_cfg_cidr mu_cfg_cidr_t;
@@ -142,6 +161,11 @@ struct mu_cfg_cidr
unsigned long mask;
};
+int mu_config_create_container (struct mu_cfg_cont **pcont,
+ enum mu_cfg_cont_type type);
+int mu_config_clone_container (struct mu_cfg_cont *cont);
+void mu_config_destroy_container (struct mu_cfg_cont **pcont);
+
int mu_cfg_scan_tree (mu_cfg_node_t *node,
struct mu_cfg_section *sections,
void *data, mu_cfg_perror_t perror,
@@ -159,4 +183,7 @@ int mu_config_register_plain_section (const char *parent_path,
const char *ident,
struct mu_cfg_param *params);
+int mu_parse_config (char *file, char *progname,
+ struct mu_cfg_param *progparam, int global);
+
#endif
diff --git a/include/mailutils/mu_auth.h b/include/mailutils/mu_auth.h
index 85ee65305..53690060c 100644
--- a/include/mailutils/mu_auth.h
+++ b/include/mailutils/mu_auth.h
@@ -103,6 +103,8 @@ extern void mu_auth_register_module (struct mu_auth_module *mod);
extern void mu_authorization_add_module_list (const char *modlist);
extern void mu_authentication_add_module_list (const char *modlist);
+extern void mu_authentication_clear_list (void);
+extern void mu_authorization_clear_list (void);
extern void mu_auth_init (void);
extern int mu_auth_data_alloc (struct mu_auth_data **ptr,
diff --git a/include/mailutils/refcount.h b/include/mailutils/refcount.h
index abf040e6d..5df0a6ff8 100644
--- a/include/mailutils/refcount.h
+++ b/include/mailutils/refcount.h
@@ -26,17 +26,11 @@
extern "C" {
#endif
-/* FIXME: Declaration should be hidden in mailutils/sys/refcount.h */
-struct _mu_refcount
-{
- unsigned int ref;
- mu_monitor_t lock;
-};
-
extern int mu_refcount_create (mu_refcount_t *);
extern void mu_refcount_destroy (mu_refcount_t *);
-extern int mu_refcount_inc (mu_refcount_t);
-extern int mu_refcount_dec (mu_refcount_t);
+extern unsigned mu_refcount_value (mu_refcount_t);
+extern unsigned mu_refcount_inc (mu_refcount_t);
+extern unsigned mu_refcount_dec (mu_refcount_t);
#ifdef __cplusplus
}
diff --git a/mail.local/main.c b/mail.local/main.c
index b44f6ad0c..370e8a204 100644
--- a/mail.local/main.c
+++ b/mail.local/main.c
@@ -128,6 +128,52 @@ char *saved_envelope; /* A hack to spare mu_envelope_ calls */
#define D_DEFAULT "9s"
+static void
+set_debug_flags (const mu_cfg_locus_t *locus, const char *arg)
+{
+ for (; *arg; arg++);
+ {
+ switch (*arg)
+ {
+ case 'g':
+#ifdef WITH_GUILE
+ debug_guile = 1;
+#endif
+ break;
+
+ case 't':
+ sieve_debug_flags |= MU_SIEVE_DEBUG_TRACE;
+ break;
+
+ case 'i':
+ sieve_debug_flags |= MU_SIEVE_DEBUG_INSTR;
+ break;
+
+ case 'l':
+ sieve_enable_log = 1;
+ break;
+
+ case 'T':
+ debug_flags |= MU_DEBUG_TRACE;
+ break;
+
+ case 'P':
+ debug_flags |= MU_DEBUG_PROT;
+ break;
+
+ default:
+ if (isdigit (*arg))
+ debug_level = *arg - '0';
+ else if (locus)
+ mu_error (_("%s:%d: %c is not a valid debug flag"),
+ locus->file, locus->line, *arg);
+ else
+ mu_error (_("%c is not a valid debug flag"), *arg);
+ break;
+ }
+ }
+}
+
static error_t
parse_opt (int key, char *arg, struct argp_state *state)
{
@@ -176,47 +222,9 @@ parse_opt (int key, char *arg, struct argp_state *state)
break;
case 'x':
- do
- {
- if (!arg)
- arg = D_DEFAULT;
- switch (*arg)
- {
- case 'g':
-#ifdef WITH_GUILE
- debug_guile = 1;
-#endif
- break;
-
- case 't':
- sieve_debug_flags |= MU_SIEVE_DEBUG_TRACE;
- break;
-
- case 'i':
- sieve_debug_flags |= MU_SIEVE_DEBUG_INSTR;
- break;
-
- case 'l':
- sieve_enable_log = 1;
- break;
-
- case 'T':
- debug_flags |= MU_DEBUG_TRACE;
- break;
-
- case 'P':
- debug_flags |= MU_DEBUG_PROT;
- break;
-
- default:
- if (isdigit (*arg))
- debug_level = *arg - '0';
- else
- argp_error (state, _("%c is not a valid debug flag"), *arg);
- break;
- }
- }
- while (*++arg);
+ if (!arg)
+ arg = D_DEFAULT;
+ set_debug_flags (NULL, arg);
break;
default:
@@ -228,6 +236,34 @@ parse_opt (int key, char *arg, struct argp_state *state)
return 0;
}
+
+static int
+cb_debug (mu_cfg_locus_t *locus, void *data, char *arg)
+{
+ set_debug_flags (locus, arg);
+ return 0;
+}
+
+struct mu_cfg_param mail_local_cfg_param[] = {
+ { "ex-multiple-delivery-success", mu_cfg_bool, &multiple_delivery },
+ { "ex-quota-tempfail", mu_cfg_bool, &ex_quota_tempfail },
+ { "from", mu_cfg_string, &from },
+#ifdef USE_DBM
+ { "quota-db", mu_cfg_string, &quotadbname },
+#endif
+#ifdef USE_SQL
+ { "quota-query", mu_cfg_string, &quota_query },
+#endif
+ { "sieve", mu_cfg_string, &sieve_pattern },
+ { "message-id-header", mu_cfg_string, &message_id_header },
+#ifdef WITH_GUILE
+ { "source", mu_cfg_string, &progfile_pattern },
+#endif
+ { "debug", mu_cfg_callback, NULL, cb_debug },
+ { NULL }
+};
+
+
static int
_mu_debug_printer (mu_debug_t unused, size_t level, const char *fmt,
@@ -246,7 +282,8 @@ _sieve_debug_printer (void *unused, const char *fmt, va_list ap)
static void
_sieve_action_log (void *user_name,
- const mu_sieve_locus_t *locus, size_t msgno, mu_message_t msg,
+ const mu_sieve_locus_t *locus, size_t msgno,
+ mu_message_t msg,
const char *action, const char *fmt, va_list ap)
{
char *text = NULL;
@@ -334,6 +371,7 @@ main (int argc, char *argv[])
mu_argp_init (program_version, NULL);
mu_sieve_argp_init ();
/* Parse command line */
+ mu_argp_set_config_param (mail_local_cfg_param);
mu_argp_parse (&argp, &argc, &argv, 0, argp_capa, &arg_index, NULL);
uid = getuid ();
diff --git a/mail.remote/mail.remote.c b/mail.remote/mail.remote.c
index e06e74d82..7427b29b7 100644
--- a/mail.remote/mail.remote.c
+++ b/mail.remote/mail.remote.c
@@ -119,6 +119,15 @@ static struct argp argp = {
doc,
};
+
+struct mu_cfg_param mail_remote_cfg_param[] = {
+ { "from", mu_cfg_string, &optfrom },
+ { "read-recipients", mu_cfg_string, &read_recipients },
+ { "debug", mu_cfg_int, &optdebug },
+ { NULL}
+};
+
+
static const char *capa[] = {
"auth",
"common",
@@ -162,6 +171,7 @@ main (int argc, char **argv)
MU_AUTH_REGISTER_ALL_MODULES();
mu_argp_init (program_version, NULL);
+ mu_argp_set_config_param (mail_remote_cfg_param);
mu_argp_parse (&argp, &argc, &argv, 0, capa, &optind, NULL);
if (optfrom)
diff --git a/mailbox/Makefile.am b/mailbox/Makefile.am
index 3f4bc6ed2..6c52d9ef7 100644
--- a/mailbox/Makefile.am
+++ b/mailbox/Makefile.am
@@ -84,6 +84,7 @@ parse822.c \
parsedate.c \
property.c \
registrar.c \
+refcount.c \
rfc2047.c \
socket_stream.c \
stream.c \
diff --git a/mailbox/cfg_lexer.c b/mailbox/cfg_lexer.c
index ea073adfe..56ba7bcb2 100644
--- a/mailbox/cfg_lexer.c
+++ b/mailbox/cfg_lexer.c
@@ -29,6 +29,10 @@
#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>
#define obstack_chunk_alloc malloc
#define obstack_chunk_free free
@@ -226,25 +230,231 @@ again:
return MU_CFG_STRING_TOKEN;
}
-static struct mu_cfg_section *root_section;
+
+static struct mu_cfg_cont *root_container;
int
-mu_config_register_section (const char *parent_path,
- const char *ident,
- mu_cfg_section_fp parser,
- void *data,
- struct mu_cfg_param *param)
+mu_config_create_container (struct mu_cfg_cont **pcont,
+ enum mu_cfg_cont_type type)
{
- struct mu_cfg_section *parent;
- size_t size = 0;
+ struct mu_cfg_cont *cont;
+ int rc;
+
+ cont = malloc (sizeof (*cont));
+ if (!cont)
+ return ENOMEM;
+ rc = mu_refcount_create (&cont->refcount);
+ if (rc)
+ free (cont);
+ else
+ {
+ cont->type = type;
+ *pcont = cont;
+ }
+ return rc;
+}
+
+
+#define DUP_SHALLOW 0
+#define DUP_DEEP 1
+
+struct dup_data
+{
+ int duptype;
+ struct mu_cfg_cont *cont;
+ struct mu_cfg_section **endsect;
+};
- if (!root_section)
+static int dup_container (struct mu_cfg_cont **pcont,
+ struct mu_cfg_section **endsect);
+
+static int
+_dup_section_action (void *item, void *cbdata)
+{
+ int rc;
+ struct mu_cfg_cont *cont = item;
+ struct dup_data *pdd = cbdata;
+
+ switch (pdd->duptype)
{
- root_section = calloc (1, sizeof (root_section[0]));
- if (!root_section)
- return MU_ERR_NOENT;
+ case DUP_DEEP:
+ rc = dup_container (&cont, pdd->endsect);
+ if (rc)
+ return rc;
+ break;
+
+ case DUP_SHALLOW:
+ break;
+ }
+ 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, pdd->endsect);
+ 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, struct mu_cfg_section **endsect)
+{
+ 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;
+ dd.endsect = endsect;
+ 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.subsec = NULL;
+ newcont->v.section.param = NULL;
+ if (endsect && &oldcont->v.section == *endsect)
+ dd.duptype = DUP_SHALLOW;
+ else
+ dd.duptype = DUP_DEEP;
+ mu_list_do (oldcont->v.section.subsec, _dup_section_action, &dd);
+ mu_list_do (oldcont->v.section.param, _dup_param_action, &dd);
+ if (dd.duptype == DUP_SHALLOW)
+ *endsect = &newcont->v.section;
+ break;
+
+ case mu_cfg_cont_param:
+ newcont->v.param = oldcont->v.param;
+ break;
+ }
+ *pcont = newcont;
+ return 0;
+}
+
+
+static int
+_destroy_container_action (void *item, void *cbdata)
+{
+ struct mu_cfg_cont *cont = item;
+ mu_config_destroy_container (&cont);
+ return 0;
+}
+
+void
+mu_config_destroy_container (struct mu_cfg_cont **pcont)
+{
+ struct mu_cfg_cont *cont = *pcont;
+ unsigned refcount = mu_refcount_dec (cont->refcount);
+ switch (cont->type)
+ {
+ case mu_cfg_cont_section:
+ mu_list_do (cont->v.section.subsec, _destroy_container_action, NULL);
+ mu_list_destroy (&cont->v.section.subsec);
+ mu_list_do (cont->v.section.param, _destroy_container_action, NULL);
+ mu_list_destroy (&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);
+ 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;
}
+ root_section = &(*proot)->v.section;
+
if (parent_path)
{
if (mu_cfg_find_section (root_section, parent_path, &parent))
@@ -253,51 +463,60 @@ mu_config_register_section (const char *parent_path,
else
parent = root_section;
+ if (mu_refcount_value ((*proot)->refcount) > 1)
+ {
+ /* It is a clone, do copy-on-write */
+ rc = dup_container (proot, &parent);
+ if (rc)
+ return rc;
+ }
+
if (ident)
{
+ struct mu_cfg_cont *container;
struct mu_cfg_section *s;
-
- if (parent->subsec)
- for (s = parent->subsec; s->ident; s++)
- size++;
-
- s = realloc (parent->subsec, (size + 2) * sizeof parent->subsec[0]);
- if (!s)
- return ENOMEM;
- parent->subsec = s;
- s = parent->subsec + size;
- s[1].ident = NULL;
+
+ 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 = param;
+ s->param = NULL;
+ add_parameters (s, param);
+ if (psection)
+ *psection = s;
}
else
{
- size_t orig_size = 0;
- struct mu_cfg_param *p;
- if (parent->param)
- for (p = parent->param; p->ident; p++)
- orig_size++;
- size = 0;
- for (p = param; p->ident; p++)
- size++;
- parent->param = realloc (parent->param,
- (size + orig_size + 1)
- * sizeof (parent->param[0]));
- memcpy (parent->param + orig_size, param,
- size * sizeof (parent->param[0]));
+ 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)
{
@@ -305,7 +524,20 @@ mu_config_register_plain_section (const char *parent_path, const char *ident,
}
static int
-_mu_parse_config (char *file, char *progname)
+prog_parser (enum mu_cfg_section_stage stage,
+ const mu_cfg_node_t *node,
+ void *section_data, void *call_data)
+{
+ if (stage == mu_cfg_section_start)
+ {
+ return strcmp (node->tag_label, call_data);
+ }
+ return 0;
+}
+
+static int
+_mu_parse_config (char *file, char *progname,
+ struct mu_cfg_param *progparam, int global)
{
struct lexer_data data;
struct stat st;
@@ -351,8 +583,61 @@ _mu_parse_config (char *file, char *progname)
if (rc == 0)
{
- rc = mu_cfg_scan_tree (parse_tree, root_section,
+ struct mu_cfg_cont *cont = root_container;
+
+ mu_config_clone_container (cont);
+ if (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, "prog", prog_parser,
+ progname,
+ progparam, &prog_sect);
+
+ mu_config_clone_container (old_root);
+
+ 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_section *s;
+ mu_iterator_current (iter, (void**)&s);
+ mu_list_append (prog_sect->subsec, s);
+ }
+ 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_param *p;
+ mu_iterator_current (iter, (void**)&p);
+ mu_list_append (prog_sect->param, p);
+ }
+ mu_iterator_destroy (&iter);
+ }
+ }
+ else if (progparam)
+ {
+ _mu_config_register_section (&cont, NULL, NULL, NULL, NULL,
+ progparam, NULL);
+ }
+ rc = mu_cfg_scan_tree (parse_tree, &cont->v.section,
progname, NULL, NULL, NULL);
+ mu_config_destroy_container (&cont);
}
mu_cfg_destroy_tree (&parse_tree);
@@ -363,7 +648,8 @@ _mu_parse_config (char *file, char *progname)
}
int
-mu_parse_config (char *file, char *progname)
+mu_parse_config (char *file, char *progname,
+ struct mu_cfg_param *progparam, int global)
{
int rc;
char *full_name = mu_tilde_expansion (file, "/", NULL);
@@ -371,7 +657,7 @@ mu_parse_config (char *file, char *progname)
{
if (access (full_name, R_OK) == 0)
{
- rc = _mu_parse_config (full_name, progname);
+ rc = _mu_parse_config (full_name, progname, progparam, global);
free (full_name);
}
else
diff --git a/mailbox/cfg_parser.y b/mailbox/cfg_parser.y
index 70dc053b7..2c97743ef 100644
--- a/