diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2007-11-07 22:32:26 +0000 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2007-11-07 22:32:26 +0000 |
commit | 6bd4a8b2ed555986e20ad09e11d6a95470a9be71 (patch) | |
tree | fd4460349b8bdf053639bcc9db9870ddb7350e18 | |
parent | 6c26e9b60fc16d4b4afa64f6a2128ada847c7084 (diff) | |
download | mailutils-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-- | ChangeLog | 54 | ||||
-rw-r--r-- | dotlock/dotlock.c | 28 | ||||
-rw-r--r-- | imap4d/imap4d.c | 2 | ||||
-rw-r--r-- | include/mailutils/argp.h | 3 | ||||
-rw-r--r-- | include/mailutils/cfg.h | 31 | ||||
-rw-r--r-- | include/mailutils/mu_auth.h | 2 | ||||
-rw-r--r-- | include/mailutils/refcount.h | 12 | ||||
-rw-r--r-- | mail.local/main.c | 122 | ||||
-rw-r--r-- | mail.remote/mail.remote.c | 10 | ||||
-rw-r--r-- | mailbox/Makefile.am | 1 | ||||
-rw-r--r-- | mailbox/cfg_lexer.c | 368 | ||||
-rw-r--r-- | mailbox/cfg_parser.y | 70 | ||||
-rw-r--r-- | mailbox/mu_argp.c | 17 | ||||
-rw-r--r-- | mailbox/mu_auth.c | 40 | ||||
-rw-r--r-- | mailbox/refcount.c | 29 | ||||
-rw-r--r-- | mimeview/mimeview.c | 56 | ||||
-rw-r--r-- | movemail/movemail.c | 13 | ||||
-rw-r--r-- | pop3d/pop3d.c | 63 | ||||
-rw-r--r-- | pop3d/signal.c | 1 | ||||
-rw-r--r-- | readmsg/readmsg.c | 13 | ||||
-rw-r--r-- | sieve/sieve.c | 215 | ||||
-rw-r--r-- | testsuite/lib/mailutils.exp | 1 |
22 files changed, 897 insertions, 254 deletions
@@ -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, "adbname }, +#endif +#ifdef USE_SQL + { "quota-query", mu_cfg_string, "a_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 (§->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 |