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
1 2007-12-11 Sergey Poznyakoff <gray@gnu.org.ua>
2
3 * include/mailutils/cfg.h (mu_cfg_section): New type.
4 (struct mu_cfg_param.offset): New member
5 (mu_offsetof): New define
6 (mu_cfg_section_fp): Change signature
7 (struct mu_cfg_section.label,target): New members.
8 (struct mu_cfg_section.data): Remove.
9 (struct mu_cfg_section.children): New member, instead of
10 param and subsec which are removed.
11 (mu_cfg_scan_tree): Change signature.
12 (mu_config_register_section): Change signature.
13 (mu_parse_config): Change signature.
14 (mu_parse_config_tree): Rename to mu_cfg_tree_reduce.
15 (mu_get_config): New proto.
16
17 * include/mailutils/libcfg.h (mu_parse_config_files): Change
18 prototype.
19
20 * dotlock/dotlock.c, imap4d/imap4d.c, lib/tcpwrap.h,
21 libargp/muinit.c, libcfg/auth.c, libcfg/common.c, libcfg/gsasl.c,
22 libcfg/init.c, libcfg/ldap.c, libcfg/pam.c, libcfg/radius.c,
23 libcfg/sieve.c, libcfg/sql.c, libcfg/tls.c, libcfg/virtdomain.c,
24 maidag/maidag.c, mail.local/main.c, mail.remote/mail.remote.c,
25 mailbox/cfg_format.c, mailbox/cfg_parser.y, mimeview/mimeview.c,
26 movemail/movemail.c, pop3d/pop3d.c, readmsg/readmsg.c,
27 sieve/sieve.c: Reflect changes to the cfg framework.
28
29 * mailbox/Makefile.am (libmailutils_la_SOURCES): Add cfg_driver.c.
30 * mailbox/cfg_driver.c: New file.
31 * mailbox/cfg_lexer.c: Move driver part into a separate file.
32
33 * examples/Makefile.am (AM_LDFLAGS): Remove libmuaux
34 * examples/echosrv.c: Remove getopt.h
35
1 2007-12-09 Sergey Poznyakoff <gray@gnu.org.ua> 36 2007-12-09 Sergey Poznyakoff <gray@gnu.org.ua>
2 37
3 * examples/Makefile.am: add echosrv.c. 38 * examples/Makefile.am: add echosrv.c.
......
...@@ -125,11 +125,11 @@ parse_opt (int key, char *arg, struct argp_state *state) ...@@ -125,11 +125,11 @@ parse_opt (int key, char *arg, struct argp_state *state)
125 125
126 126
127 struct mu_cfg_param dotlock_cfg_param[] = { 127 struct mu_cfg_param dotlock_cfg_param[] = {
128 { "force", mu_cfg_time, &force, NULL, 128 { "force", mu_cfg_time, &force, 0, NULL,
129 N_("Forcibly break an existing lock older than the specified time.") }, 129 N_("Forcibly break an existing lock older than the specified time.") },
130 { "retry", mu_cfg_int, &retries, NULL, 130 { "retry", mu_cfg_int, &retries, 0, NULL,
131 N_("Number of times to retry acquiring the lock.") }, 131 N_("Number of times to retry acquiring the lock.") },
132 { "debug", mu_cfg_bool, &debug, NULL, 132 { "debug", mu_cfg_bool, &debug, 0, NULL,
133 N_("Print details of failure reasons to stderr.") }, 133 N_("Print details of failure reasons to stderr.") },
134 { NULL } 134 { NULL }
135 }; 135 };
......
...@@ -54,7 +54,6 @@ mod_LTLIBRARIES = numaddr.la ...@@ -54,7 +54,6 @@ mod_LTLIBRARIES = numaddr.la
54 INCLUDES = @MU_COMMON_INCLUDES@ 54 INCLUDES = @MU_COMMON_INCLUDES@
55 55
56 AM_LDFLAGS = \ 56 AM_LDFLAGS = \
57 ../lib/libmuaux.la\
58 ${MU_LIB_MAILUTILS}\ 57 ${MU_LIB_MAILUTILS}\
59 @MU_COMMON_LIBRARIES@ 58 @MU_COMMON_LIBRARIES@
60 59
...@@ -132,4 +131,4 @@ muauth_LDADD = \ ...@@ -132,4 +131,4 @@ muauth_LDADD = \
132 @MU_AUTHLIBS@ \ 131 @MU_AUTHLIBS@ \
133 ${MU_LIB_MAILUTILS} 132 ${MU_LIB_MAILUTILS}
134 133
135 muemail_LDADD = ${MU_APP_LIBRARIES}
...\ No newline at end of file ...\ No newline at end of file
134 muemail_LDADD = ${MU_APP_LIBRARIES}
......
...@@ -28,7 +28,6 @@ ...@@ -28,7 +28,6 @@
28 #include <arpa/inet.h> 28 #include <arpa/inet.h>
29 #include <signal.h> 29 #include <signal.h>
30 #include <sys/wait.h> 30 #include <sys/wait.h>
31 #include "getopt.h"
32 31
33 #include <mailutils/mailutils.h> 32 #include <mailutils/mailutils.h>
34 #include <mailutils/server.h> 33 #include <mailutils/server.h>
...@@ -185,7 +184,8 @@ server_idle (void *server_data) ...@@ -185,7 +184,8 @@ server_idle (void *server_data)
185 (unsigned long) pid, 184 (unsigned long) pid,
186 WTERMSIG (status)); 185 WTERMSIG (status));
187 else 186 else
188 mu_diag_output (MU_DIAG_ERR, "%lu: terminated (cause unknown)"); 187 mu_diag_output (MU_DIAG_ERR, "%lu: terminated (cause unknown)",
188 (unsigned long) pid);
189 } 189 }
190 } 190 }
191 return 0; 191 return 0;
......
...@@ -272,33 +272,33 @@ cb_preauth (mu_debug_t debug, void *data, char *arg) ...@@ -272,33 +272,33 @@ cb_preauth (mu_debug_t debug, void *data, char *arg)
272 } 272 }
273 273
274 static struct mu_cfg_param imap4d_cfg_param[] = { 274 static struct mu_cfg_param imap4d_cfg_param[] = {
275 { "other-namespace", mu_cfg_callback, NULL, cb_other, 275 { "other-namespace", mu_cfg_callback, NULL, 0, cb_other,
276 N_("Set other users' namespace. Argument is a colon-separated list " 276 N_("Set other users' namespace. Argument is a colon-separated list "
277 "of directories comprising the namespace.") }, 277 "of directories comprising the namespace.") },
278 { "shared-namespace", mu_cfg_callback, NULL, cb_shared, 278 { "shared-namespace", mu_cfg_callback, NULL, 0, cb_shared,
279 N_("Set shared namespace. Argument is a colon-separated list " 279 N_("Set shared namespace. Argument is a colon-separated list "
280 "of directories comprising the namespace.") }, 280 "of directories comprising the namespace.") },
281 { "login-disabled", mu_cfg_int, &login_disabled, NULL, 281 { "login-disabled", mu_cfg_int, &login_disabled, 0, NULL,
282 N_("Disable LOGIN command.") }, 282 N_("Disable LOGIN command.") },
283 { "create-home-dir", mu_cfg_bool, &create_home_dir, NULL, 283 { "create-home-dir", mu_cfg_bool, &create_home_dir, 0, NULL,
284 N_("If true, create non-existing user home directories.") }, 284 N_("If true, create non-existing user home directories.") },
285 { "home-dir-mode", mu_cfg_callback, NULL, cb_mode, 285 { "home-dir-mode", mu_cfg_callback, NULL, 0, cb_mode,
286 N_("File mode for creating user home directories (octal)."), 286 N_("File mode for creating user home directories (octal)."),
287 N_("mode") }, 287 N_("mode") },
288 { "tls-required", mu_cfg_int, &tls_required, NULL, 288 { "tls-required", mu_cfg_int, &tls_required, 0, NULL,
289 N_("Always require STARTTLS before entering authentication phase.") }, 289 N_("Always require STARTTLS before entering authentication phase.") },
290 { "preauth", mu_cfg_callback, NULL, cb_preauth, 290 { "preauth", mu_cfg_callback, NULL, 0, cb_preauth,
291 N_("Configure PREAUTH mode. MODE is one of:\n" 291 N_("Configure PREAUTH mode. MODE is one of:\n"
292 " prog:///<full-program-name: string>\n" 292 " prog:///<full-program-name: string>\n"
293 " ident[://:<port: string-or-number>]\n" 293 " ident[://:<port: string-or-number>]\n"
294 " stdio"), 294 " stdio"),
295 N_("MODE") }, 295 N_("MODE") },
296 { "preauth-only", mu_cfg_bool, &preauth_only, NULL, 296 { "preauth-only", mu_cfg_bool, &preauth_only, 0, NULL,
297 N_("Use only preauth mode. If unable to setup it, disconnect " 297 N_("Use only preauth mode. If unable to setup it, disconnect "
298 "immediately.") }, 298 "immediately.") },
299 { "ident-keyfile", mu_cfg_string, &ident_keyfile, NULL, 299 { "ident-keyfile", mu_cfg_string, &ident_keyfile, 0, NULL,
300 N_("Name of DES keyfile for decoding ecrypted ident responses.") }, 300 N_("Name of DES keyfile for decoding ecrypted ident responses.") },
301 { "ident-entrypt-only", mu_cfg_bool, &ident_encrypt_only, NULL, 301 { "ident-entrypt-only", mu_cfg_bool, &ident_encrypt_only, 0, NULL,
302 N_("Use only encrypted ident responses.") }, 302 N_("Use only encrypted ident responses.") },
303 TCP_WRAPPERS_CONFIG 303 TCP_WRAPPERS_CONFIG
304 { NULL } 304 { NULL }
......
...@@ -118,7 +118,8 @@ enum mu_cfg_param_data_type ...@@ -118,7 +118,8 @@ enum mu_cfg_param_data_type
118 mu_cfg_ipv4, 118 mu_cfg_ipv4,
119 mu_cfg_cidr, 119 mu_cfg_cidr,
120 mu_cfg_host, 120 mu_cfg_host,
121 mu_cfg_callback 121 mu_cfg_callback,
122 mu_cfg_section
122 }; 123 };
123 124
124 typedef int (*mu_cfg_callback_t) (mu_debug_t, void *, char *); 125 typedef int (*mu_cfg_callback_t) (mu_debug_t, void *, char *);
...@@ -128,11 +129,17 @@ struct mu_cfg_param ...@@ -128,11 +129,17 @@ struct mu_cfg_param
128 const char *ident; 129 const char *ident;
129 enum mu_cfg_param_data_type type; 130 enum mu_cfg_param_data_type type;
130 void *data; 131 void *data;
132 size_t offset;
131 mu_cfg_callback_t callback; 133 mu_cfg_callback_t callback;
132 const char *docstring; 134 const char *docstring;
133 const char *argname; 135 const char *argname;
134 }; 136 };
135 137
138 #define mu_offsetof(s,f) ((size_t)&((s*)0).f)
139
140 #define MU_TARGET_REF(f) &f, 0
141 #define MU_TARGET_OFF(s,f) NULL, mu_offsetof(s,f)
142
136 enum mu_cfg_section_stage 143 enum mu_cfg_section_stage
137 { 144 {
138 mu_cfg_section_start, 145 mu_cfg_section_start,
...@@ -141,17 +148,18 @@ enum mu_cfg_section_stage ...@@ -141,17 +148,18 @@ enum mu_cfg_section_stage
141 148
142 typedef int (*mu_cfg_section_fp) (enum mu_cfg_section_stage stage, 149 typedef int (*mu_cfg_section_fp) (enum mu_cfg_section_stage stage,
143 const mu_cfg_node_t *node, 150 const mu_cfg_node_t *node,
144 void *section_data, 151 const char *label,
152 void **section_data_ptr,
145 void *call_data, 153 void *call_data,
146 mu_cfg_tree_t *tree); 154 mu_cfg_tree_t *tree);
147 155
148 struct mu_cfg_section 156 struct mu_cfg_section
149 { 157 {
150 const char *ident; 158 const char *ident;
159 char *label;
151 mu_cfg_section_fp parser; 160 mu_cfg_section_fp parser;
152 void *data; 161 void *target;
153 mu_list_t /* of mu_cfg_cont/mu_cfg_section */ subsec; 162 mu_list_t /* of mu_cfg_cont */ children;
154 mu_list_t /* of mu_cfg_cont/mu_cfg_param */ param;
155 char *docstring; 163 char *docstring;
156 }; 164 };
157 165
...@@ -187,15 +195,15 @@ int mu_config_clone_container (struct mu_cfg_cont *cont); ...@@ -187,15 +195,15 @@ int mu_config_clone_container (struct mu_cfg_cont *cont);
187 void mu_config_destroy_container (struct mu_cfg_cont **pcont); 195 void mu_config_destroy_container (struct mu_cfg_cont **pcont);
188 196
189 int mu_cfg_scan_tree (mu_cfg_tree_t *tree, struct mu_cfg_section *sections, 197 int mu_cfg_scan_tree (mu_cfg_tree_t *tree, struct mu_cfg_section *sections,
190 void *call_data); 198 void *target, void *call_data);
191 199
192 int mu_cfg_find_section (struct mu_cfg_section *root_sec, 200 int mu_cfg_find_section (struct mu_cfg_section *root_sec,
193 const char *path, struct mu_cfg_section **retval); 201 const char *path, struct mu_cfg_section **retval);
194 202
195 int mu_config_register_section (const char *parent_path, 203 int mu_config_register_section (const char *parent_path,
196 const char *ident, 204 const char *ident,
205 const char *label,
197 mu_cfg_section_fp parser, 206 mu_cfg_section_fp parser,
198 void *data,
199 struct mu_cfg_param *param); 207 struct mu_cfg_param *param);
200 int mu_config_register_plain_section (const char *parent_path, 208 int mu_config_register_plain_section (const char *parent_path,
201 const char *ident, 209 const char *ident,
...@@ -206,7 +214,8 @@ int mu_config_register_plain_section (const char *parent_path, ...@@ -206,7 +214,8 @@ int mu_config_register_plain_section (const char *parent_path,
206 #define MU_PARSE_CONFIG_DUMP 0x4 214 #define MU_PARSE_CONFIG_DUMP 0x4
207 215
208 int mu_parse_config (const char *file, const char *progname, 216 int mu_parse_config (const char *file, const char *progname,
209 struct mu_cfg_param *progparam, int flags); 217 struct mu_cfg_param *progparam, int flags,
218 void *target_ptr);
210 219
211 int mu_cfg_parse_boolean (const char *str, int *res); 220 int mu_cfg_parse_boolean (const char *str, int *res);
212 221
...@@ -218,8 +227,14 @@ void mu_cfg_format_parse_tree (mu_stream_t stream, struct mu_cfg_tree *tree); ...@@ -218,8 +227,14 @@ void mu_cfg_format_parse_tree (mu_stream_t stream, struct mu_cfg_tree *tree);
218 void mu_cfg_format_container (mu_stream_t stream, struct mu_cfg_cont *cont); 227 void mu_cfg_format_container (mu_stream_t stream, struct mu_cfg_cont *cont);
219 void mu_format_config_tree (mu_stream_t stream, const char *progname, 228 void mu_format_config_tree (mu_stream_t stream, const char *progname,
220 struct mu_cfg_param *progparam, int flags); 229 struct mu_cfg_param *progparam, int flags);
221 int mu_parse_config_tree (mu_cfg_tree_t *parse_tree, const char *progname, 230 int mu_cfg_tree_reduce (mu_cfg_tree_t *parse_tree, const char *progname,
222 struct mu_cfg_param *progparam, int flags); 231 struct mu_cfg_param *progparam,
232 int flags, void *target_ptr);
233
234 int mu_get_config (const char *file, const char *progname,
235 struct mu_cfg_param *progparam, int flags,
236 void *target_ptr);
237
223 238
224 int mu_cfg_tree_create (struct mu_cfg_tree **ptree); 239 int mu_cfg_tree_create (struct mu_cfg_tree **ptree);
225 void mu_cfg_tree_set_debug (struct mu_cfg_tree *tree, mu_debug_t debug); 240 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, ...@@ -49,7 +49,8 @@ extern int mu_register_cfg_capa (const char *name,
49 mu_cfg_section_fp *parser); 49 mu_cfg_section_fp *parser);
50 50
51 extern void mu_libcfg_init (char **cnames); 51 extern void mu_libcfg_init (char **cnames);
52 extern int mu_parse_config_files (struct mu_cfg_param *param); 52 extern int mu_parse_config_files (struct mu_cfg_param *param,
53 void *target_ptr);
53 54
54 #define __mu_common_cat2__(a,b) a ## b 55 #define __mu_common_cat2__(a,b) a ## b
55 #define __mu_common_cat3__(a,b,c) a ## b ## c 56 #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); ...@@ -57,7 +58,8 @@ extern int mu_parse_config_files (struct mu_cfg_param *param);
57 int \ 58 int \
58 __mu_common_cat3__(mu_,capa,_section_parser) \ 59 __mu_common_cat3__(mu_,capa,_section_parser) \
59 (enum mu_cfg_section_stage stage, const mu_cfg_node_t *node, \ 60 (enum mu_cfg_section_stage stage, const mu_cfg_node_t *node, \
60 void *section_data, void *call_data, mu_cfg_tree_t *tree) \ 61 const char *section_label, void **section_data, \
62 void *call_data, mu_cfg_tree_t *tree) \
61 { \ 63 { \
62 switch (stage) \ 64 switch (stage) \
63 { \ 65 { \
......
...@@ -33,25 +33,27 @@ extern int mu_tcpwrapper_access (int fd); ...@@ -33,25 +33,27 @@ extern int mu_tcpwrapper_access (int fd);
33 33
34 #ifdef WITH_LIBWRAP 34 #ifdef WITH_LIBWRAP
35 # define TCP_WRAPPERS_CONFIG \ 35 # define TCP_WRAPPERS_CONFIG \
36 { "tcp-wrapper-enable", mu_cfg_bool, &mu_tcp_wrapper_enable, NULL, \ 36 { "tcp-wrapper-enable", mu_cfg_bool, &mu_tcp_wrapper_enable, 0, NULL, \
37 N_("Enable TCP wrapper access control. Default is \"yes\".") }, \ 37 N_("Enable TCP wrapper access control. Default is \"yes\".") }, \
38 { "tcp-wrapper-daemon", mu_cfg_string, &mu_tcp_wrapper_daemon, NULL, \ 38 { "tcp-wrapper-daemon", mu_cfg_string, &mu_tcp_wrapper_daemon, 0, NULL, \
39 N_("Set daemon name for TCP wrapper lookups. Default is program name."), \ 39 N_("Set daemon name for TCP wrapper lookups. Default is program name."), \
40 N_("name") }, \ 40 N_("name") }, \
41 { "hosts-allow-table", mu_cfg_callback, NULL, mu_tcp_wrapper_cb_hosts_allow,\ 41 { "hosts-allow-table", mu_cfg_callback, NULL, 0, \
42 mu_tcp_wrapper_cb_hosts_allow, \
42 N_("Use file for positive client address access control " \ 43 N_("Use file for positive client address access control " \
43 "(default: /etc/hosts.allow)."), \ 44 "(default: /etc/hosts.allow)."), \
44 N_("file") }, \ 45 N_("file") }, \
45 { "hosts-deny-table", mu_cfg_callback, NULL, mu_tcp_wrapper_cb_hosts_deny, \ 46 { "hosts-deny-table", mu_cfg_callback, NULL, 0, \
47 mu_tcp_wrapper_cb_hosts_deny, \
46 N_("Use file for negative client address access control " \ 48 N_("Use file for negative client address access control " \
47 "(default: /etc/hosts.deny)."), \ 49 "(default: /etc/hosts.deny)."), \
48 N_("file") }, \ 50 N_("file") }, \
49 { "hosts-allow-syslog-level", mu_cfg_callback, NULL, \ 51 { "hosts-allow-syslog-level", mu_cfg_callback, NULL, 0, \
50 mu_tcp_wrapper_cb_hosts_allow_syslog, \ 52 mu_tcp_wrapper_cb_hosts_allow_syslog, \
51 N_("Log host allows at this syslog level. See logging { facility } for " \ 53 N_("Log host allows at this syslog level. See logging { facility } for " \
52 "a description of argument syntax."), \ 54 "a description of argument syntax."), \
53 N_("level") }, \ 55 N_("level") }, \
54 { "hosts-allow-deny-level", mu_cfg_callback, NULL, \ 56 { "hosts-allow-deny-level", mu_cfg_callback, NULL, 0, \
55 mu_tcp_wrapper_cb_hosts_deny_syslog, \ 57 mu_tcp_wrapper_cb_hosts_deny_syslog, \
56 N_("Log host denies at this syslog level. See logging { facility } for " \ 58 N_("Log host denies at this syslog level. See logging { facility } for " \
57 "a description of argument syntax."), \ 59 "a description of argument syntax."), \
......
...@@ -77,7 +77,7 @@ mu_app_init (struct argp *myargp, const char **capa, ...@@ -77,7 +77,7 @@ mu_app_init (struct argp *myargp, const char **capa,
77 77
78 mu_libcfg_init (excapa); 78 mu_libcfg_init (excapa);
79 free (excapa); 79 free (excapa);
80 mu_parse_config_files (cfg_param); 80 mu_parse_config_files (cfg_param, data);
81 81
82 if (mu_help_config_mode) 82 if (mu_help_config_mode)
83 { 83 {
...@@ -113,8 +113,8 @@ mu_app_init (struct argp *myargp, const char **capa, ...@@ -113,8 +113,8 @@ mu_app_init (struct argp *myargp, const char **capa,
113 cfgflags |= MU_PARSE_CONFIG_VERBOSE; 113 cfgflags |= MU_PARSE_CONFIG_VERBOSE;
114 if (mu_cfg_parser_verbose > 1) 114 if (mu_cfg_parser_verbose > 1)
115 cfgflags |= MU_PARSE_CONFIG_DUMP; 115 cfgflags |= MU_PARSE_CONFIG_DUMP;
116 rc = mu_parse_config_tree (mu_argp_tree, mu_program_name, cfg_param, 116 rc = mu_cfg_tree_reduce (mu_argp_tree, mu_program_name, cfg_param,
117 cfgflags); 117 cfgflags, data);
118 118
119 mu_gocs_flush (); 119 mu_gocs_flush ();
120 mu_cfg_destroy_tree (&mu_argp_tree); 120 mu_cfg_destroy_tree (&mu_argp_tree);
......
...@@ -50,12 +50,12 @@ cb_authorization (mu_debug_t err, void *data, char *arg) ...@@ -50,12 +50,12 @@ cb_authorization (mu_debug_t err, void *data, char *arg)
50 } 50 }
51 51
52 static struct mu_cfg_param mu_auth_param[] = { 52 static struct mu_cfg_param mu_auth_param[] = {
53 { "authentication", mu_cfg_callback, NULL, cb_authentication, 53 { "authentication", mu_cfg_callback, NULL, 0, cb_authentication,
54 N_("Set a list of modules for authentication. Modlist is a " 54 N_("Set a list of modules for authentication. Modlist is a "
55 "colon-separated list of module names or a word `clear' to " 55 "colon-separated list of module names or a word `clear' to "
56 "clear the previously set up values."), 56 "clear the previously set up values."),
57 N_("modlist") }, 57 N_("modlist") },
58 { "authorization", mu_cfg_callback, NULL, cb_authorization, 58 { "authorization", mu_cfg_callback, NULL, 0, cb_authorization,
59 N_("Set a list of modules for authorization. Modlist is a " 59 N_("Set a list of modules for authorization. Modlist is a "
60 "colon-separated list of module names or a word `clear' to " 60 "colon-separated list of module names or a word `clear' to "
61 "clear the previously set up values."), 61 "clear the previously set up values."),
...@@ -66,7 +66,8 @@ static struct mu_cfg_param mu_auth_param[] = { ...@@ -66,7 +66,8 @@ static struct mu_cfg_param mu_auth_param[] = {
66 int 66 int
67 mu_auth_section_parser 67 mu_auth_section_parser
68 (enum mu_cfg_section_stage stage, const mu_cfg_node_t *node, 68 (enum mu_cfg_section_stage stage, const mu_cfg_node_t *node,
69 void *section_data, void *call_data, mu_cfg_tree_t *tree) 69 const char *section_label, void **section_data, void *call_data,
70 mu_cfg_tree_t *tree)
70 { 71 {
71 switch (stage) 72 switch (stage)
72 { 73 {
......
...@@ -40,10 +40,10 @@ static struct mu_gocs_debug debug_settings; ...@@ -40,10 +40,10 @@ static struct mu_gocs_debug debug_settings;
40 /* ************************************************************************* */ 40 /* ************************************************************************* */
41 41
42 static struct mu_cfg_param mu_mailbox_param[] = { 42 static struct mu_cfg_param mu_mailbox_param[] = {
43 { "mail-spool", mu_cfg_string, &mailbox_settings.mail_spool, NULL, 43 { "mail-spool", mu_cfg_string, &mailbox_settings.mail_spool, 0, NULL,
44 N_("Use specified URL as a mailspool directory."), 44 N_("Use specified URL as a mailspool directory."),
45 N_("url") }, 45 N_("url") },
46 { "mailbox-type", mu_cfg_string, &mailbox_settings.mailbox_type, NULL, 46 { "mailbox-type", mu_cfg_string, &mailbox_settings.mailbox_type, 0, NULL,
47 N_("Default mailbox type."), N_("protocol") }, 47 N_("Default mailbox type."), N_("protocol") },
48 { NULL } 48 { NULL }
49 }; 49 };
...@@ -57,16 +57,18 @@ DCL_CFG_CAPA (mailbox); ...@@ -57,16 +57,18 @@ DCL_CFG_CAPA (mailbox);
57 57
58 static struct mu_cfg_param mu_locking_param[] = { 58 static struct mu_cfg_param mu_locking_param[] = {
59 /* FIXME: Flags are superfluous. */ 59 /* FIXME: Flags are superfluous. */
60 { "flags", mu_cfg_string, &locking_settings.lock_flags, NULL, 60 { "flags", mu_cfg_string, &locking_settings.lock_flags, 0, NULL,
61 N_("Default locker flags (E=external, R=retry, T=time, P=pid).") }, 61 N_("Default locker flags (E=external, R=retry, T=time, P=pid).") },
62 { "retry-timeout", mu_cfg_ulong, &locking_settings.lock_retry_timeout, NULL, 62 { "retry-timeout", mu_cfg_ulong, &locking_settings.lock_retry_timeout,
63 0, NULL,
63 N_("Set timeout for acquiring the lock.") }, 64 N_("Set timeout for acquiring the lock.") },
64 { "retry-count", mu_cfg_ulong, &locking_settings.lock_retry_count, NULL, 65 { "retry-count", mu_cfg_ulong, &locking_settings.lock_retry_count, 0, NULL,
65 N_("Set the maximum number of times to retry acquiring the lock.") }, 66 N_("Set the maximum number of times to retry acquiring the lock.") },
66 { "expire-timeout", mu_cfg_ulong, &locking_settings.lock_expire_timeout, 67 { "expire-timeout", mu_cfg_ulong, &locking_settings.lock_expire_timeout,
67 NULL, 68 0, NULL,
68 N_("Expire locks older than this amount of time.") }, 69 N_("Expire locks older than this amount of time.") },
69 { "external-locker", mu_cfg_string, &locking_settings.external_locker, NULL, 70 { "external-locker", mu_cfg_string, &locking_settings.external_locker,
71 0, NULL,
70 N_("Use external locker program."), 72 N_("Use external locker program."),
71 N_("prog") }, 73 N_("prog") },
72 { NULL, } 74 { NULL, }
...@@ -80,11 +82,11 @@ DCL_CFG_CAPA (locking); ...@@ -80,11 +82,11 @@ DCL_CFG_CAPA (locking);
80 /* ************************************************************************* */ 82 /* ************************************************************************* */
81 83
82 static struct mu_cfg_param mu_address_param[] = { 84 static struct mu_cfg_param mu_address_param[] = {
83 { "email-addr", mu_cfg_string, &address_settings.address, NULL, 85 { "email-addr", mu_cfg_string, &address_settings.address, 0, NULL,
84 N_("Set the current user email address (default is " 86 N_("Set the current user email address (default is "
85 "loginname@defaultdomain)."), 87 "loginname@defaultdomain)."),
86 N_("email") }, 88 N_("email") },
87 { "email-domain", mu_cfg_string, &address_settings.domain, NULL, 89 { "email-domain", mu_cfg_string, &address_settings.domain, 0, NULL,
88 N_("Set e-mail domain for unqualified user names (default is this host)"), 90 N_("Set e-mail domain for unqualified user names (default is this host)"),
89 N_("domain") }, 91 N_("domain") },
90 { NULL } 92 { NULL }
...@@ -98,7 +100,7 @@ DCL_CFG_CAPA (address); ...@@ -98,7 +100,7 @@ DCL_CFG_CAPA (address);
98 /* ************************************************************************* */ 100 /* ************************************************************************* */
99 101
100 static struct mu_cfg_param mu_mailer_param[] = { 102 static struct mu_cfg_param mu_mailer_param[] = {
101 { "url", mu_cfg_string, &mailer_settings.mailer, NULL, 103 { "url", mu_cfg_string, &mailer_settings.mailer, 0, NULL,
102 N_("Use this URL as the default mailer"), 104 N_("Use this URL as the default mailer"),
103 N_("url") }, 105 N_("url") },
104 { NULL } 106 { NULL }
...@@ -125,7 +127,7 @@ cb_facility (mu_debug_t debug, void *data, char *arg) ...@@ -125,7 +127,7 @@ cb_facility (mu_debug_t debug, void *data, char *arg)
125 } 127 }
126 128
127 static struct mu_cfg_param mu_logging_param[] = { 129 static struct mu_cfg_param mu_logging_param[] = {
128 { "facility", mu_cfg_callback, NULL, cb_facility, 130 { "facility", mu_cfg_callback, NULL, 0, cb_facility,
129 N_("Set syslog facility. Arg is one of the following: user, daemon, " 131 N_("Set syslog facility. Arg is one of the following: user, daemon, "
130 "auth, authpriv, mail, cron, local0 through local7 (case-insensitive), " 132 "auth, authpriv, mail, cron, local0 through local7 (case-insensitive), "
131 "or a facility number.") }, 133 "or a facility number.") },
...@@ -156,19 +158,19 @@ _cb_daemon_mode (mu_debug_t debug, void *data, char *arg) ...@@ -156,19 +158,19 @@ _cb_daemon_mode (mu_debug_t debug, void *data, char *arg)
156 } 158 }
157 159
158 static struct mu_cfg_param mu_daemon_param[] = { 160 static struct mu_cfg_param mu_daemon_param[] = {
159 { "max-children", mu_cfg_ulong, &daemon_settings.maxchildren, NULL, 161 { "max-children", mu_cfg_ulong, &daemon_settings.maxchildren, 0, NULL,
160 N_("Maximum number of children processes to run simultaneously.") }, 162 N_("Maximum number of children processes to run simultaneously.") },
161 { "mode", mu_cfg_callback, NULL, _cb_daemon_mode, 163 { "mode", mu_cfg_callback, NULL, 0, _cb_daemon_mode,
162 N_("Set daemon mode (either inetd (or interactive) or daemon)."), 164 N_("Set daemon mode (either inetd (or interactive) or daemon)."),
163 N_("mode") }, 165 N_("mode") },
164 { "transcript", mu_cfg_bool, &daemon_settings.transcript, NULL, 166 { "transcript", mu_cfg_bool, &daemon_settings.transcript, 0, NULL,
165 N_("Log the session transcript.") }, 167 N_("Log the session transcript.") },
166 { "pidfile", mu_cfg_string, &daemon_settings.pidfile, NULL, 168 { "pidfile", mu_cfg_string, &daemon_settings.pidfile, 0, NULL,
167 N_("Store PID of the master process in this file."), 169 N_("Store PID of the master process in this file."),
168 N_("file") }, 170 N_("file") },
169 { "port", mu_cfg_ushort, &daemon_settings.port, NULL, 171 { "port", mu_cfg_ushort, &daemon_settings.port, 0, NULL,
170 N_("Listen on the specified port number.") }, 172 N_("Listen on the specified port number.") },
171 { "timeout", mu_cfg_ulong, &daemon_settings.timeout, NULL, 173 { "timeout", mu_cfg_ulong, &daemon_settings.timeout, 0, NULL,
172 N_("Set idle timeout.") }, 174 N_("Set idle timeout.") },
173 { NULL } 175 { NULL }
174 }; 176 };
...@@ -176,7 +178,8 @@ static struct mu_cfg_param mu_daemon_param[] = { ...@@ -176,7 +178,8 @@ static struct mu_cfg_param mu_daemon_param[] = {
176 int 178 int
177 mu_daemon_section_parser 179 mu_daemon_section_parser
178 (enum mu_cfg_section_stage stage, const mu_cfg_node_t *node, 180 (enum mu_cfg_section_stage stage, const mu_cfg_node_t *node,
179 void *section_data, void *call_data, mu_cfg_tree_t *tree) 181 const char *section_label, void **section_data,
182 void *call_data, mu_cfg_tree_t *tree)
180 { 183 {
181 switch (stage) 184 switch (stage)
182 { 185 {
...@@ -208,8 +211,10 @@ cb_debug_level (mu_debug_t debug, void *data, char *arg) ...@@ -208,8 +211,10 @@ cb_debug_level (mu_debug_t debug, void *data, char *arg)
208 size_t size; 211 size_t size;
209 char *pfx; 212 char *pfx;
210 struct mu_debug_locus locus; 213 struct mu_debug_locus locus;
211 214
212 debug_settings.string = arg; 215 if (debug_settings.string)
216 free (debug_settings.string);
217 debug_settings.string = strdup (arg);
213 if (mu_debug_get_locus (debug, &locus) == 0) 218 if (mu_debug_get_locus (debug, &locus) == 0)
214 { 219 {
215 p = umaxtostr (locus.line, buf); 220 p = umaxtostr (locus.line, buf);
...@@ -232,11 +237,11 @@ cb_debug_level (mu_debug_t debug, void *data, char *arg) ...@@ -232,11 +237,11 @@ cb_debug_level (mu_debug_t debug, void *data, char *arg)
232 } 237 }
233 238
234 static struct mu_cfg_param mu_debug_param[] = { 239 static struct mu_cfg_param mu_debug_param[] = {
235 { "level", mu_cfg_callback, NULL, &cb_debug_level, 240 { "level", mu_cfg_callback, NULL, 0, &cb_debug_level,
236 N_("Set Mailutils debugging level. Argument is a colon-separated list " 241 N_("Set Mailutils debugging level. Argument is a colon-separated list "
237 "of debugging specifications in the form:\n" 242 "of debugging specifications in the form:\n"
238 " <object: string>[[:]=<level: number>].") }, 243 " <object: string>[[:]=<level: number>].") },
239 { "line-info", mu_cfg_bool, &debug_settings.line_info, NULL, 244 { "line-info", mu_cfg_bool, &debug_settings.line_info, 0, NULL,
240 N_("Prefix debug messages with Mailutils source locations.") }, 245 N_("Prefix debug messages with Mailutils source locations.") },
241 { NULL } 246 { NULL }
242 }; 247 };
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
25 static struct mu_gsasl_module_data gsasl_settings; 25 static struct mu_gsasl_module_data gsasl_settings;
26 26
27 static struct mu_cfg_param mu_gsasl_param[] = { 27 static struct mu_cfg_param mu_gsasl_param[] = {
28 { "cram-passwd", mu_cfg_string, &gsasl_settings.cram_md5_pwd, NULL, 28 { "cram-passwd", mu_cfg_string, &gsasl_settings.cram_md5_pwd, 0, NULL,
29 N_("Name of GSASL password file."), 29 N_("Name of GSASL password file."),
30 N_("file") }, 30 N_("file") },
31 { NULL } 31 { NULL }
......
...@@ -78,14 +78,14 @@ mu_libcfg_init (char **cnames) ...@@ -78,14 +78,14 @@ mu_libcfg_init (char **cnames)
78 mu_error (_("Requested unknown configuration group `%s'"), 78 mu_error (_("Requested unknown configuration group `%s'"),
79 cnames[i]); 79 cnames[i]);
80 else 80 else
81 mu_config_register_section (NULL, cp->name, cp->parser, NULL, 81 mu_config_register_section (NULL, cp->name, NULL,
82 cp->cfgparam); 82 cp->parser, cp->cfgparam);
83 } 83 }
84 } 84 }
85 } 85 }
86 86
87 int 87 int
88 mu_parse_config_files (struct mu_cfg_param *param) 88 mu_parse_config_files (struct mu_cfg_param *param, void *target)
89 { 89 {
90 int flags = 0; 90 int flags = 0;
91 91
...@@ -96,7 +96,7 @@ mu_parse_config_files (struct mu_cfg_param *param) ...@@ -96,7 +96,7 @@ mu_parse_config_files (struct mu_cfg_param *param)
96 96
97 if (mu_load_site_rcfile) 97 if (mu_load_site_rcfile)
98 mu_parse_config (MU_CONFIG_FILE, mu_program_name, param, 98 mu_parse_config (MU_CONFIG_FILE, mu_program_name, param,
99 flags | MU_PARSE_CONFIG_GLOBAL); 99 flags | MU_PARSE_CONFIG_GLOBAL, target);
100 100
101 if (mu_load_user_rcfile && mu_program_name) 101 if (mu_load_user_rcfile && mu_program_name)
102 { 102 {
...@@ -107,14 +107,14 @@ mu_parse_config_files (struct mu_cfg_param *param) ...@@ -107,14 +107,14 @@ mu_parse_config_files (struct mu_cfg_param *param)
107 strcpy (file_name, "~/."); 107 strcpy (file_name, "~/.");
108 strcat (file_name, mu_program_name); 108 strcat (file_name, mu_program_name);
109 109
110 mu_parse_config (file_name, mu_program_name, param, flags); 110 mu_parse_config (file_name, mu_program_name, param, flags, target);
111 111
112 free (file_name); 112 free (file_name);
113 } 113 }
114 } 114 }
115 115
116 if (mu_load_rcfile) 116 if (mu_load_rcfile)
117 mu_parse_config (mu_load_rcfile, mu_program_name, param, flags); 117 mu_parse_config (mu_load_rcfile, mu_program_name, param, flags, target);
118 118
119 return 0; 119 return 0;
120 } 120 }
......
...@@ -37,24 +37,24 @@ cb_field_map (mu_debug_t debug, void *data, char *arg) ...@@ -37,24 +37,24 @@ cb_field_map (mu_debug_t debug, void *data, char *arg)
37 } 37 }
38 38
39 static struct mu_cfg_param mu_ldap_param[] = { 39 static struct mu_cfg_param mu_ldap_param[] = {
40 { "enable", mu_cfg_bool, &ldap_settings.enable, NULL, 40 { "enable", mu_cfg_bool, &ldap_settings.enable, 0, NULL,
41 N_("Enable LDAP lookups.") }, 41 N_("Enable LDAP lookups.") },
42 { "url", mu_cfg_string, &ldap_settings.url, NULL, 42 { "url", mu_cfg_string, &ldap_settings.url, 0, NULL,
43 N_("Set URL of the LDAP server."), 43 N_("Set URL of the LDAP server."),
44 N_("url") }, 44 N_("url") },
45 { "base", mu_cfg_string, &ldap_settings.base, NULL, 45 { "base", mu_cfg_string, &ldap_settings.base, 0, NULL,
46 N_("Base DN for LDAP lookups."), 46 N_("Base DN for LDAP lookups."),
47 N_("dn") }, 47 N_("dn") },
48 { "binddn", mu_cfg_string, &ldap_settings.binddn, NULL, 48 { "binddn", mu_cfg_string, &ldap_settings.binddn, 0, NULL,
49 N_("DN for accessing LDAP database."), 49 N_("DN for accessing LDAP database."),
50 N_("dn") }, 50 N_("dn") },
51 { "passwd", mu_cfg_string, &ldap_settings.passwd, NULL, 51 { "passwd", mu_cfg_string, &ldap_settings.passwd, 0, NULL,
52 N_("Password for use with binddn.") }, 52 N_("Password for use with binddn.") },
53 { "tls", mu_cfg_bool, &ldap_settings.tls, NULL, 53 { "tls", mu_cfg_bool, &ldap_settings.tls, 0, NULL,
54 N_("Use TLS encryption.") }, 54 N_("Use TLS encryption.") },
55 { "debug", mu_cfg_int, &ldap_settings.debug, NULL, 55 { "debug", mu_cfg_int, &ldap_settings.debug, 0, NULL,
56 N_("Set LDAP debugging level.") }, 56 N_("Set LDAP debugging level.") },
57 { "field-map", mu_cfg_callback, NULL, cb_field_map, 57 { "field-map", mu_cfg_callback, NULL, 0, cb_field_map,
58 N_("Set a field-map for parsing LDAP replies. The map is a " 58 N_("Set a field-map for parsing LDAP replies. The map is a "
59 "column-separated list of definitions. Each definition has the " 59 "column-separated list of definitions. Each definition has the "
60 "following form:\n" 60 "following form:\n"
...@@ -63,10 +63,10 @@ static struct mu_cfg_param mu_ldap_param[] = { ...@@ -63,10 +63,10 @@ static struct mu_cfg_param mu_ldap_param[] = {
63 "gecos, dir, shell, mailbox, quota, and <attr> is the name of " 63 "gecos, dir, shell, mailbox, quota, and <attr> is the name of "
64 "the correspondind LDAP attribute."), 64 "the correspondind LDAP attribute."),
65 N_("map") }, 65 N_("map") },
66 { "getpwnam", mu_cfg_string, &ldap_settings.getpwnam_filter, NULL, 66 { "getpwnam", mu_cfg_string, &ldap_settings.getpwnam_filter, 0, NULL,
67 N_("LDAP filter to use for getpwnam requests."), 67 N_("LDAP filter to use for getpwnam requests."),
68 N_("filter") }, 68 N_("filter") },
69 { "getpwuid", mu_cfg_string, &ldap_settings.getpwuid_filter, NULL, 69 { "getpwuid", mu_cfg_string, &ldap_settings.getpwuid_filter, 0, NULL,
70 N_("LDAP filter to use for getpwuid requests."), 70 N_("LDAP filter to use for getpwuid requests."),
71 N_("filter") }, 71 N_("filter") },
72 { NULL } 72 { NULL }
...@@ -75,7 +75,8 @@ static struct mu_cfg_param mu_ldap_param[] = { ...@@ -75,7 +75,8 @@ static struct mu_cfg_param mu_ldap_param[] = {
75 int 75 int
76 mu_ldap_section_parser 76 mu_ldap_section_parser
77 (enum mu_cfg_section_stage stage, const mu_cfg_node_t *node, 77 (enum mu_cfg_section_stage stage, const mu_cfg_node_t *node,
78 void *section_data, void *call_data, mu_cfg_tree_t *tree) 78 const char *section_label, void **section_data,
79 void *call_data, mu_cfg_tree_t *tree)
79 { 80 {
80 switch (stage) 81 switch (stage)
81 { 82 {
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
24 static char *pam_settings; 24 static char *pam_settings;
25 25
26 static struct mu_cfg_param mu_pam_param[] = { 26 static struct mu_cfg_param mu_pam_param[] = {
27 { "service", mu_cfg_string, &pam_settings, NULL, 27 { "service", mu_cfg_string, &pam_settings, 0, NULL,
28 N_("Set PAM service name."), 28 N_("Set PAM service name."),
29 N_("name") }, 29 N_("name") },
30 { NULL } 30 { NULL }
......
...@@ -25,16 +25,16 @@ ...@@ -25,16 +25,16 @@
25 static struct mu_radius_module_data radius_settings; 25 static struct mu_radius_module_data radius_settings;
26 26
27 static struct mu_cfg_param mu_radius_param[] = { 27 static struct mu_cfg_param mu_radius_param[] = {
28 { "auth", mu_cfg_string, &radius_settings.auth_request, NULL, 28 { "auth", mu_cfg_string, &radius_settings.auth_request, 0, NULL,
29 N_("Radius request for authorization."), 29 N_("Radius request for authorization."),
30 N_("request") }, 30 N_("request") },
31 { "getpwnam", mu_cfg_string, &radius_settings.getpwnam_request, NULL, 31 { "getpwnam", mu_cfg_string, &radius_settings.getpwnam_request, 0, NULL,
32 N_("Radius request for getpwnam."), 32 N_("Radius request for getpwnam."),
33 N_("request") }, 33 N_("request") },
34 { "getpwuid", mu_cfg_string, &radius_settings.getpwuid_request, NULL, 34 { "getpwuid", mu_cfg_string, &radius_settings.getpwuid_request, 0, NULL,
35 N_("Radius request for getpwuid."), 35 N_("Radius request for getpwuid."),
36 N_("request") }, 36 N_("request") },
37 { "directory", mu_cfg_string, &radius_settings.config_dir, NULL, 37 { "directory", mu_cfg_string, &radius_settings.config_dir, 0, NULL,
38 N_("Set radius configuration directory.") }, 38 N_("Set radius configuration directory.") },
39 { NULL } 39 { NULL }
40 }; 40 };
......
...@@ -92,15 +92,15 @@ cb_library_path (mu_debug_t debug, void *data, char *arg) ...@@ -92,15 +92,15 @@ cb_library_path (mu_debug_t debug, void *data, char *arg)
92 } 92 }
93 93
94 static struct mu_cfg_param mu_sieve_param[] = { 94 static struct mu_cfg_param mu_sieve_param[] = {
95 { "clear-library-path", mu_cfg_callback, NULL, cb_clear_library_path, 95 { "clear-library-path", mu_cfg_callback, NULL, 0, cb_clear_library_path,
96 N_("Clear library search path.") }, 96 N_("Clear library search path.") },
97 { "clear-include-path", mu_cfg_callback, NULL, cb_clear_include_path, 97 { "clear-include-path", mu_cfg_callback, NULL, 0, cb_clear_include_path,
98 N_("Clear include search path.") }, 98 N_("Clear include search path.") },
99 { "library-path", mu_cfg_callback, NULL, cb_library_path, 99 { "library-path", mu_cfg_callback, NULL, 0, cb_library_path,
100 N_("Add directories to the library search path. Argument is a " 100 N_("Add directories to the library search path. Argument is a "
101 "comma-separated list of directories."), 101 "comma-separated list of directories."),
102 N_("list") }, 102 N_("list") },
103 { "include-path", mu_cfg_callback, NULL, cb_include_path, 103 { "include-path", mu_cfg_callback, NULL, 0, cb_include_path,
104 N_("Add directories to the include search path. Argument is a " 104 N_("Add directories to the include search path. Argument is a "
105 "comma-separated list of directories."), 105 "comma-separated list of directories."),
106 N_("list") }, 106 N_("list") },
......
...@@ -50,31 +50,31 @@ cb_field_map (mu_debug_t debug, void *data, char *arg) ...@@ -50,31 +50,31 @@ cb_field_map (mu_debug_t debug, void *data, char *arg)
50 } 50 }
51 51
52 static struct mu_cfg_param mu_sql_param[] = { 52 static struct mu_cfg_param mu_sql_param[] = {
53 { "interface", mu_cfg_string, &sql_settings.interface, NULL, 53 { "interface", mu_cfg_string, &sql_settings.interface, 0, NULL,
54 N_("Set SQL interface to use (one of: mysql, odbc, or postgres).") }, 54 N_("Set SQL interface to use (one of: mysql, odbc, or postgres).") },
55 { "getwpnam", mu_cfg_string, &sql_settings.getpwnam_query, NULL, 55 { "getwpnam", mu_cfg_string, &sql_settings.getpwnam_query, 0, NULL,
56 N_("SQL query to use for getpwnam requests."), 56 N_("SQL query to use for getpwnam requests."),
57 N_("query") }, 57 N_("query") },
58 { "getpwuid", mu_cfg_string, &sql_settings.getpwuid_query, NULL, 58 { "getpwuid", mu_cfg_string, &sql_settings.getpwuid_query, 0, NULL,
59 N_("SQL query to use for getpwuid requests."), 59 N_("SQL query to use for getpwuid requests."),
60 N_("query") }, 60 N_("query") },
61 { "getpass", mu_cfg_string, &sql_settings.getpass_query, NULL, 61 { "getpass", mu_cfg_string, &sql_settings.getpass_query, 0, NULL,
62 N_("SQL query returning the user's password."), 62 N_("SQL query returning the user's password."),
63 N_("query") }, 63 N_("query") },
64 { "host", mu_cfg_string, &sql_settings.host, NULL, 64 { "host", mu_cfg_string, &sql_settings.host, 0, NULL,
65 N_("SQL server host name.") }, 65 N_("SQL server host name.") },
66 { "user", mu_cfg_string, &sql_settings.user, NULL, 66 { "user", mu_cfg_string, &sql_settings.user, 0, NULL,
67 N_("SQL user name.") }, 67 N_("SQL user name.") },
68 { "passwd", mu_cfg_string, &sql_settings.passwd, NULL, 68 { "passwd", mu_cfg_string, &sql_settings.passwd, 0, NULL,
69 N_("Password for the SQL user.") }, 69 N_("Password for the SQL user.") },
70 { "port", mu_cfg_int, &sql_settings.port, NULL, 70 { "port", mu_cfg_int, &sql_settings.port, 0, NULL,
71 N_("SQL server port.") }, 71 N_("SQL server port.") },
72 { "db", mu_cfg_string, &sql_settings.db, NULL, 72 { "db", mu_cfg_string, &sql_settings.db, 0, NULL,
73 N_("Database name.") }, 73 N_("Database name.") },
74 { "password-type", mu_cfg_callback, NULL, cb_password_type, 74 { "password-type", mu_cfg_callback, NULL, 0, cb_password_type,
75 N_("Type of password returned by getpass query (one of: plain, hash, " 75 N_("Type of password returned by getpass query (one of: plain, hash, "
76 "scrambled).") }, 76 "scrambled).") },
77 { "field-map", mu_cfg_callback, NULL, cb_field_map, 77 { "field-map", mu_cfg_callback, NULL, 0, cb_field_map,
78 N_("Set a field-map for parsing SQL replies. The map is a " 78 N_("Set a field-map for parsing SQL replies. The map is a "
79 "column-separated list of definitions. Each definition has the " 79 "column-separated list of definitions. Each definition has the "
80 "following form:\n" 80 "following form:\n"
......
...@@ -25,15 +25,15 @@ ...@@ -25,15 +25,15 @@
25 static struct mu_tls_module_config tls_settings; 25 static struct mu_tls_module_config tls_settings;
26 26
27 static struct mu_cfg_param mu_tls_param[] = { 27 static struct mu_cfg_param mu_tls_param[] = {
28 { "tls", mu_cfg_bool, &tls_settings.client_enable, NULL, 28 { "tls", mu_cfg_bool, &tls_settings.client_enable, 0, NULL,
29 N_("Enable client TLS encryption.") }, 29 N_("Enable client TLS encryption.") },
30 { "ssl-cert", mu_cfg_string, &tls_settings.ssl_cert, NULL, 30 { "ssl-cert", mu_cfg_string, &tls_settings.ssl_cert, 0, NULL,
31 N_("Specify SSL certificate file."), 31 N_("Specify SSL certificate file."),
32 N_("file") }, 32 N_("file") },
33 { "ssl-key", mu_cfg_string, &tls_settings.ssl_key, NULL, 33 { "ssl-key", mu_cfg_string, &tls_settings.ssl_key, 0, NULL,
34 N_("Specify SSL certificate key file."), 34 N_("Specify SSL certificate key file."),
35 N_("file") }, 35 N_("file") },
36 { "ssl-cafile", mu_cfg_string, &tls_settings.ssl_cafile, NULL, 36 { "ssl-cafile", mu_cfg_string, &tls_settings.ssl_cafile, 0, NULL,
37 N_("Specify trusted CAs file."), 37 N_("Specify trusted CAs file."),
38 N_("file") }, 38 N_("file") },
39 { NULL } 39 { NULL }
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
24 static struct mu_gocs_virtual virtdomain_settings; 24 static struct mu_gocs_virtual virtdomain_settings;
25 25
26 static struct mu_cfg_param mu_virtdomain_param[] = { 26 static struct mu_cfg_param mu_virtdomain_param[] = {
27 { "passwd-dir", mu_cfg_string, &virtdomain_settings, NULL, 27 { "passwd-dir", mu_cfg_string, &virtdomain_settings, 0, NULL,
28 N_("Name of the directory where virtual domain password files are " 28 N_("Name of the directory where virtual domain password files are "
29 "located."), 29 "located."),
30 N_("dir") }, 30 N_("dir") },
......
...@@ -238,57 +238,57 @@ cb_debug (mu_debug_t debug, void *data, char *arg) ...@@ -238,57 +238,57 @@ cb_debug (mu_debug_t debug, void *data, char *arg)
238 } 238 }
239 239
240 struct mu_cfg_param maidag_cfg_param[] = { 240 struct mu_cfg_param maidag_cfg_param[] = {
241 { "exit-multiple-delivery-success", mu_cfg_bool, &multiple_delivery, NULL, 241 { "exit-multiple-delivery-success", mu_cfg_bool, &multiple_delivery, 0, NULL,
242 N_("In case of multiple delivery, exit with code 0 if at least one " 242 N_("In case of multiple delivery, exit with code 0 if at least one "
243 "delivery succeeded.") }, 243 "delivery succeeded.") },
244 { "exit-quota-tempfail", mu_cfg_bool, &ex_quota_tempfail, NULL, 244 { "exit-quota-tempfail", mu_cfg_bool, &ex_quota_tempfail, 0, NULL,
245 N_("Indicate temporary failure if the recipient is over his mail quota.") 245 N_("Indicate temporary failure if the recipient is over his mail quota.")
246 }, 246 },
247 #ifdef USE_DBM 247 #ifdef USE_DBM
248 { "quota-db", mu_cfg_string, &quotadbname, NULL, 248 { "quota-db", mu_cfg_string, &quotadbname, 0, NULL,
249 N_("Name of DBM quota database file."), 249 N_("Name of DBM quota database file."),
250 N_("file") }, 250 N_("file") },
251 #endif 251 #endif
252 #ifdef USE_SQL 252 #ifdef USE_SQL
253 { "quota-query", mu_cfg_string, &quota_query, NULL, 253 { "quota-query", mu_cfg_string, &quota_query, 0, NULL,
254 N_("SQL query to retrieve mailbox quota. This is deprecated, use " 254 N_("SQL query to retrieve mailbox quota. This is deprecated, use "
255 "sql { ... } instead."), 255 "sql { ... } instead."),
256 N_("query") }, 256 N_("query") },
257 #endif 257 #endif
258 { "sieve-filter", mu_cfg_string, &sieve_pattern, NULL, 258 { "sieve-filter", mu_cfg_string, &sieve_pattern, 0, NULL,
259 N_("File name or name pattern for Sieve filter file."), 259 N_("File name or name pattern for Sieve filter file."),
260 N_("file-or-pattern") }, 260 N_("file-or-pattern") },
261 { "message-id-header", mu_cfg_string, &message_id_header, NULL, 261 { "message-id-header", mu_cfg_string, &message_id_header, 0, NULL,
262 N_("When logging Sieve actions, identify messages by the value of " 262 N_("When logging Sieve actions, identify messages by the value of "
263 "this header."), 263 "this header."),
264 N_("name") }, 264 N_("name") },
265 #ifdef WITH_GUILE 265 #ifdef WITH_GUILE
266 { "guile-filter", mu_cfg_string, &progfile_pattern, NULL, 266 { "guile-filter", mu_cfg_string, &progfile_pattern, 0, NULL,
267 N_("File name or name pattern for Guile filter file."), 267 N_("File name or name pattern for Guile filter file."),
268 N_("file-or-pattern") }, 268 N_("file-or-pattern") },
269 #endif 269 #endif
270 { "debug", mu_cfg_callback, NULL, cb_debug, 270 { "debug", mu_cfg_callback, NULL, 0, cb_debug,
271 N_("Set maidag debug level. Debug level consists of one or more " 271 N_("Set maidag debug level. Debug level consists of one or more "
272 "of the following letters:\n" 272 "of the following letters:\n"
273 " g - guimb stack traces\n" 273 " g - guimb stack traces\n"
274 " t - sieve trace (MU_SIEVE_DEBUG_TRACE)\n" 274 " t - sieve trace (MU_SIEVE_DEBUG_TRACE)\n"
275 " i - sieve instructions trace (MU_SIEVE_DEBUG_INSTR)\n" 275 " i - sieve instructions trace (MU_SIEVE_DEBUG_INSTR)\n"
276 " l - sieve action logs\n") }, 276 " l - sieve action logs\n") },
277 { "stderr", mu_cfg_bool, &log_to_stderr, NULL, 277 { "stderr", mu_cfg_bool, &log_to_stderr, 0, NULL,
278 N_("Log to stderr instead of syslog.") }, 278 N_("Log to stderr instead of syslog.") },
279 /* LMTP support */ 279 /* LMTP support */
280 { "lmtp", mu_cfg_bool, &lmtp_mode, NULL, 280 { "lmtp", mu_cfg_bool, &lmtp_mode, 0, NULL,
281 N_("Run in LMTP mode.") }, 281 N_("Run in LMTP mode.") },
282 { "group", mu_cfg_string, &lmtp_group, NULL, 282 { "group", mu_cfg_string, &lmtp_group, 0, NULL,
283 N_("In LMTP mode, change to this group after startup.") }, 283 N_("In LMTP mode, change to this group after startup.") },
284 { "listen", mu_cfg_string, &lmtp_url_string, NULL, 284 { "listen", mu_cfg_string, &lmtp_url_string, 0, NULL,
285 N_("In LMTP mode, listen on the given URL. Valid URLs are:\n" 285 N_("In LMTP mode, listen on the given URL. Valid URLs are:\n"
286 " tcp://<address: string>:<port: number> (note that port is " 286 " tcp://<address: string>:<port: number> (note that port is "
287 "mandatory)\n" 287 "mandatory)\n"
288 " file://<socket-file-name>\n" 288 " file://<socket-file-name>\n"
289 "or socket://<socket-file-name>"), 289 "or socket://<socket-file-name>"),
290 N_("url") }, 290 N_("url") },
291 { "reuse-address", mu_cfg_bool, &reuse_lmtp_address, NULL, 291 { "reuse-address", mu_cfg_bool, &reuse_lmtp_address, 0, NULL,
292 N_("Reuse existing address (LMTP mode). Default is \"yes\".") }, 292 N_("Reuse existing address (LMTP mode). Default is \"yes\".") },
293 TCP_WRAPPERS_CONFIG 293 TCP_WRAPPERS_CONFIG
294 { NULL } 294 { NULL }
......
...@@ -255,36 +255,36 @@ cb_debug (mu_debug_t debug, void *data, char *arg) ...@@ -255,36 +255,36 @@ cb_debug (mu_debug_t debug, void *data, char *arg)
255 } 255 }
256 256
257 struct mu_cfg_param mail_local_cfg_param[] = { 257 struct mu_cfg_param mail_local_cfg_param[] = {
258 { "ex-multiple-delivery-success", mu_cfg_bool, &multiple_delivery, NULL, 258 { "ex-multiple-delivery-success", mu_cfg_bool, &multiple_delivery, 0, NULL,
259 N_("In case of multiple delivery, exit with code 0 if at least one " 259 N_("In case of multiple delivery, exit with code 0 if at least one "
260 "delivery succeeded.") }, 260 "delivery succeeded.") },
261 { "ex-quota-tempfail", mu_cfg_bool, &ex_quota_tempfail, NULL, 261 { "ex-quota-tempfail", mu_cfg_bool, &ex_quota_tempfail, 0, NULL,
262 N_("Indicate temporary failure if the recipient is over his mail quota.") 262 N_("Indicate temporary failure if the recipient is over his mail quota.")
263 }, 263 },
264 #ifdef USE_DBM 264 #ifdef USE_DBM
265 { "quota-db", mu_cfg_string, &quotadbname, NULL, 265 { "quota-db", mu_cfg_string, &quotadbname, 0, NULL,
266 N_("Name of DBM quota database file."), 266 N_("Name of DBM quota database file."),
267 N_("file") }, 267 N_("file") },
268 #endif 268 #endif
269 #ifdef USE_SQL 269 #ifdef USE_SQL
270 { "quota-query", mu_cfg_string, &quota_query, NULL, 270 { "quota-query", mu_cfg_string, &quota_query, 0, NULL,
271 N_("SQL query to retrieve mailbox quota. This is deprecated, use " 271 N_("SQL query to retrieve mailbox quota. This is deprecated, use "
272 "sql { ... } instead."), 272 "sql { ... } instead."),
273 N_("query") }, 273 N_("query") },
274 #endif 274 #endif
275 { "sieve-filter", mu_cfg_string, &sieve_pattern, NULL, 275 { "sieve-filter", mu_cfg_string, &sieve_pattern, 0, NULL,
276 N_("File name or name pattern for Sieve filter file."), 276 N_("File name or name pattern for Sieve filter file."),
277 N_("file-or-pattern") }, 277 N_("file-or-pattern") },
278 { "message-id-header", mu_cfg_string, &message_id_header, NULL, 278 { "message-id-header", mu_cfg_string, &message_id_header, 0, NULL,
279 N_("When logging Sieve actions, identify messages by the value of " 279 N_("When logging Sieve actions, identify messages by the value of "
280 "this header."), 280 "this header."),
281 N_("name") }, 281 N_("name") },
282 #ifdef WITH_GUILE 282 #ifdef WITH_GUILE
283 { "guile-filter", mu_cfg_string, &progfile_pattern, NULL, 283 { "guile-filter", mu_cfg_string, &progfile_pattern, 0, NULL,
284 N_("File name or name pattern for Guile filter file."), 284 N_("File name or name pattern for Guile filter file."),
285 N_("file-or-pattern") }, 285 N_("file-or-pattern") },
286 #endif 286 #endif
287 { "debug", mu_cfg_callback, NULL, cb_debug, 287 { "debug", mu_cfg_callback, NULL, 0, cb_debug,
288 N_("Set mail.local debug level. Debug level consists of one or more " 288 N_("Set mail.local debug level. Debug level consists of one or more "
289 "of the following letters:\n" 289 "of the following letters:\n"
290 " g - guimb stack traces\n" 290 " g - guimb stack traces\n"
......
...@@ -136,12 +136,12 @@ static struct argp argp = { ...@@ -136,12 +136,12 @@ static struct argp argp = {
136 136
137 137
138 struct mu_cfg_param mail_remote_cfg_param[] = { 138 struct mu_cfg_param mail_remote_cfg_param[] = {
139 { "from", mu_cfg_string, &optfrom, NULL, 139 { "from", mu_cfg_string, &optfrom, 0, NULL,
140 N_("Set sender email address."), 140 N_("Set sender email address."),
141 N_("email") }, 141 N_("email") },
142 { "read-recipients", mu_cfg_string, &read_recipients, NULL, 142 { "read-recipients", mu_cfg_string, &read_recipients, 0, NULL,
143 N_("Read recipient addresses from the message.") }, 143 N_("Read recipient addresses from the message.") },
144 { "debug", mu_cfg_int, &optdebug, NULL, 144 { "debug", mu_cfg_int, &optdebug, 0, NULL,
145 N_("Set debug verbosity level. Level 1 prints envelope commands in " 145 N_("Set debug verbosity level. Level 1 prints envelope commands in "
146 "the SMTP protocol transaction. Levels 2 and above print the data " 146 "the SMTP protocol transaction. Levels 2 and above print the data "
147 "part of the transaction as well.") }, 147 "part of the transaction as well.") },
......
...@@ -50,6 +50,7 @@ libmailutils_la_SOURCES = \ ...@@ -50,6 +50,7 @@ libmailutils_la_SOURCES = \
50 dbgstderr.c\ 50 dbgstderr.c\
51 dbgsyslog.c\ 51 dbgsyslog.c\
52 debug.c\ 52 debug.c\
53 cfg_driver.c\
53 cfg_format.c\ 54 cfg_format.c\
54 cfg_lexer.c\ 55 cfg_lexer.c\
55 cfg_parser.c\ 56 cfg_parser.c\
......
1 /* cfg_driver.c -- Main driver for Mailutils configuration files
2 Copyright (C) 2007 Free Software Foundation, Inc.
3
4 GNU Mailutils is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License as
6 published by the Free Software Foundation; either version 3, or (at
7 your option) any later version.
8
9 This program is distributed in the hope that it will be useful, but
10 WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17 #ifdef HAVE_CONFIG_H
18 # include <config.h>
19 #endif
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <fcntl.h>
25 #include <errno.h>
26 #include <unistd.h>
27 #include <ctype.h>
28 #include <mailutils/argcv.h>
29 #include <mailutils/nls.h>
30 #include <mailutils/cfg.h>
31 #include <mailutils/errno.h>
32 #include <mailutils/error.h>
33 #include <mailutils/mutil.h>
34 #include <mailutils/monitor.h>
35 #include <mailutils/refcount.h>
36 #include <mailutils/list.h>
37 #include <mailutils/iterator.h>
38 #include <mailutils/stream.h>
39 #include <mailutils/assoc.h>
40
41
42 static mu_assoc_t section_tab;
43
44 static void
45 alloc_section_tab ()
46 {
47 if (!section_tab)
48 mu_assoc_create (&section_tab, sizeof (struct mu_cfg_cont *),
49 MU_ASSOC_COPY_KEY);
50 }
51
52 int
53 mu_create_canned_section (struct mu_cfg_section *section)
54 {
55 struct mu_cfg_cont *cont;
56 alloc_section_tab ();
57 mu_config_create_container (&cont, mu_cfg_cont_section);
58 cont->v.section = *section;
59 return mu_assoc_install (section_tab, cont->v.section.ident, &cont);
60 }
61
62 int
63 mu_create_canned_param (struct mu_cfg_param *param)
64 {
65 struct mu_cfg_cont *cont;
66 alloc_section_tab ();
67 mu_config_create_container (&cont, mu_cfg_cont_param);
68 cont->v.param = *param;
69 return mu_assoc_install (section_tab, cont->v.param.ident, &cont);
70 }
71
72 struct mu_cfg_cont *
73 mu_get_canned_container (const char *name)
74 {
75 struct mu_cfg_cont **pcont = mu_assoc_ref (section_tab, name);
76 return pcont ? *pcont : NULL;
77 }
78
79
80 static struct mu_cfg_cont *root_container;
81
82 int
83 mu_config_create_container (struct mu_cfg_cont **pcont,
84 enum mu_cfg_cont_type type)
85 {
86 struct mu_cfg_cont *cont;
87 int rc;
88
89 cont = calloc (1, sizeof (*cont));
90 if (!cont)
91 return ENOMEM;
92 rc = mu_refcount_create (&cont->refcount);
93 if (rc)
94 free (cont);
95 else
96 {
97 cont->type = type;
98 *pcont = cont;
99 }
100 return rc;
101 }
102
103
104 struct dup_data
105 {
106 struct mu_cfg_cont *cont;
107 };
108
109 static int dup_container (struct mu_cfg_cont **pcont);
110
111 static int
112 _dup_cont_action (void *item, void *cbdata)
113 {
114 int rc;
115 struct mu_cfg_cont *cont = item;
116 struct dup_data *pdd = cbdata;
117
118 rc = dup_container (&cont);
119 if (rc)
120 return rc;
121
122 if (!pdd->cont->v.section.children)
123 {
124 int rc = mu_list_create (&pdd->cont->v.section.children);
125 if (rc)
126 return rc;
127 }
128 return mu_list_append (pdd->cont->v.section.children, cont);
129 }
130
131 static int
132 dup_container (struct mu_cfg_cont **pcont)
133 {
134 int rc;
135 struct mu_cfg_cont *newcont, *oldcont = *pcont;
136 struct dup_data dd;
137
138 rc = mu_config_create_container (&newcont, oldcont->type);
139 if (rc)
140 return rc;
141
142 dd.cont = newcont;
143 switch (oldcont->type)
144 {
145 case mu_cfg_cont_section:
146 newcont->v.section.ident = oldcont->v.section.ident;
147 newcont->v.section.label = oldcont->v.section.label;
148 newcont->v.section.parser = oldcont->v.section.parser;
149 newcont->v.section.target = oldcont->v.section.target;
150 newcont->v.section.docstring = oldcont->v.section.docstring;
151 newcont->v.section.children = NULL;
152 mu_list_do (oldcont->v.section.children, _dup_cont_action, &dd);
153 break;
154
155 case mu_cfg_cont_param:
156 newcont->v.param = oldcont->v.param;
157 break;
158 }
159 *pcont = newcont;
160 return 0;
161 }
162
163
164 static void
165 destroy_list (mu_list_t *plist)
166 {
167 mu_list_t list = *plist;
168 mu_iterator_t itr = NULL;
169
170 if (!list)
171 return;
172
173 mu_list_get_iterator (list, &itr);
174 for (mu_iterator_first (itr); !mu_iterator_is_done (itr);
175 mu_iterator_next (itr))
176 {
177 struct mu_cfg_cont *cont, *p;
178 mu_iterator_current (itr, (void**)&cont);
179 p = cont;
180 mu_config_destroy_container (&p);
181 if (!p)
182 mu_list_remove (list, cont);
183 }
184 mu_iterator_destroy (&itr);
185 if (mu_list_is_empty (list))
186 mu_list_destroy (plist);
187 }
188
189 void
190 mu_config_destroy_container (struct mu_cfg_cont **pcont)
191 {
192 struct mu_cfg_cont *cont = *pcont;
193 unsigned refcount = mu_refcount_dec (cont->refcount);
194 /* printf ("destr %p-%s: %d\n", cont, cont->v.section.ident, refcount); */
195 switch (cont->type)
196 {
197 case mu_cfg_cont_section:
198 destroy_list (&cont->v.section.children);
199 break;
200
201 case mu_cfg_cont_param:
202 break;
203 }
204
205 if (refcount == 0)
206 {
207 free (cont);
208 *pcont = 0;
209 }
210 }
211
212
213 static int
214 add_parameters (struct mu_cfg_section *sect, struct mu_cfg_param *param)
215 {
216 if (!param)
217 return 0;
218 if (!sect->children)
219 mu_list_create (&sect->children);
220 for (; param->ident; param++)
221 {
222 int rc;
223 struct mu_cfg_cont *container;
224
225 if (param->type == mu_cfg_section)
226 {
227 container = mu_get_canned_container (param->ident);
228 if (!container)
229 {
230 mu_error (_("INTERNAL ERROR: Requested unknown canned "
231 "section %s"),
232 param->ident);
233 abort ();
234 }
235 mu_config_clone_container (container);
236 }
237 else
238 {
239 rc = mu_config_create_container (&container, mu_cfg_cont_param);
240 if (rc)
241 return rc;
242 container->v.param = *param;
243 }
244 mu_list_append (sect->children, container);
245 }
246 return 0;
247 }
248
249 static int
250 _clone_action (void *item, void *cbdata)
251 {
252 struct mu_cfg_cont *cont = item;
253 return mu_config_clone_container (cont);
254 }
255
256 int
257 mu_config_clone_container (struct mu_cfg_cont *cont)
258 {
259 mu_refcount_inc (cont->refcount);
260 /* printf("clone %p-%s: %d\n", cont, cont->v.section.ident, n); */
261 switch (cont->type)
262 {
263 case mu_cfg_cont_section:
264 mu_list_do (cont->v.section.children, _clone_action, NULL);
265 break;
266
267 case mu_cfg_cont_param:
268 break;
269 }
270 return 0;
271 }
272
273
274 int
275 _mu_config_register_section (struct mu_cfg_cont **proot,
276 const char *parent_path,
277 const char *ident,
278 const char *label,
279 mu_cfg_section_fp parser,
280 struct mu_cfg_param *param,
281 struct mu_cfg_section **psection)
282 {
283 int rc;
284 struct mu_cfg_section *root_section;
285 struct mu_cfg_section *parent;
286
287 if (!*proot)
288 {
289 rc = mu_config_create_container (proot, mu_cfg_cont_section);
290 if (rc)
291 return rc;
292 memset (&(*proot)->v.section, 0, sizeof (*proot)->v.section);
293 }
294
295 root_section = &(*proot)->v.section;
296
297 if (parent_path)
298 {
299 if (mu_cfg_find_section (root_section, parent_path, &parent))
300 return MU_ERR_NOENT;
301 }
302 else
303 parent = root_section;
304
305 if (mu_refcount_value ((*proot)->refcount) > 1)
306 {
307 /* It is a clone, do copy-on-write */
308 rc = dup_container (proot);
309 if (rc)
310 return rc;
311
312 root_section = &(*proot)->v.section;
313
314 if (parent_path)
315 {
316 if (mu_cfg_find_section (root_section, parent_path, &parent))
317 return MU_ERR_NOENT;
318 }
319 else
320 parent = root_section;
321 }
322
323 if (ident)
324 {
325 struct mu_cfg_cont *container;
326 struct mu_cfg_section *s;
327
328 if (!parent->children)
329 mu_list_create (&parent->children);
330 mu_config_create_container (&container, mu_cfg_cont_section);
331 mu_list_append (parent->children, container);
332 s = &container->v.section;
333
334 s->ident = strdup (ident);
335 s->label = label ? strdup (label) : NULL;
336 s->parser = parser;
337 s->children = NULL;
338 add_parameters (s, param);
339 if (psection)
340 *psection = s;
341 }
342 else
343 {
344 add_parameters (parent, param);
345 /* FIXME: */
346 if (!parent->parser)
347 parent->parser = parser;
348 if (psection)
349 *psection = parent;
350 }
351 return 0;
352 }
353
354 int
355 mu_config_register_section (const char *parent_path,
356 const char *ident,
357 const char *label,
358 mu_cfg_section_fp parser,
359 struct mu_cfg_param *param)
360 {
361 return _mu_config_register_section (&root_container,
362 parent_path,
363 ident, label,
364 parser, param, NULL);
365 }
366
367 int
368 mu_config_register_plain_section (const char *parent_path, const char *ident,
369 struct mu_cfg_param *params)
370 {
371 return mu_config_register_section (parent_path, ident, NULL, NULL, params);
372 }
373
374 static int
375 prog_parser (enum mu_cfg_section_stage stage,
376 const mu_cfg_node_t *node,
377 const char *label, void **section_data,
378 void *call_data,
379 mu_cfg_tree_t *tree)
380 {
381 if (stage == mu_cfg_section_start)
382 return strcmp (node->tag_label, label);
383
384 return 0;
385 }
386
387 static char *
388 make_file_name (const char *dir, const char *file)
389 {
390 char *tmp;
391 size_t len = strlen (dir) + 1 + strlen (file);
392 tmp = malloc (len + 1);
393 if (!tmp)
394 {
395 mu_error ("%s", mu_strerror (errno));
396 exit (1);
397 }
398 strcpy (tmp, dir);
399 strcat (tmp, "/");
400 strcat (tmp, file);
401 return tmp;
402 }
403
404 struct include_data
405 {
406 const char *progname;
407 struct mu_cfg_param *progparam;
408 int flags;
409 void *target;
410 };
411
412 static int
413 _cb_include (mu_debug_t debug, void *data, char *arg)
414 {
415 int ret = 0;
416 struct stat sb;
417 char *dirname = arg;
418 struct include_data *idp = data;
419 char *tmp = NULL;
420
421 if (dirname[0] != '/')
422 dirname = tmp = make_file_name (SYSCONFDIR, dirname);
423
424 if (stat (dirname, &sb) == 0)
425 {
426 if (S_ISDIR (sb.st_mode))
427 {
428 char *file = make_file_name (dirname, idp->progname);
429 ret = mu_get_config (file, idp->progname, idp->progparam, 0,
430 idp->target);
431 }
432 else
433 ret = mu_get_config (dirname, idp->progname, idp->progparam,
434 idp->flags, idp->target);
435 }
436 else if (errno == ENOENT)
437 {
438 mu_cfg_format_error (debug, MU_DEBUG_ERROR,
439 _("include file or directory does not exist"));
440 ret = 1;
441 }
442 else
443 {
444 mu_cfg_format_error (debug, MU_DEBUG_ERROR,
445 _("cannot stat include file or directory: %s"),
446 mu_strerror (errno));
447 ret = 1;
448 }
449 free (tmp);
450 return ret;
451 }
452
453 struct mu_cfg_cont *
454 mu_build_container (const char *progname,
455 struct mu_cfg_param *progparam, int flags, void *target)
456 {
457 struct mu_cfg_cont *cont = root_container;
458 struct include_data idata;
459 struct mu_cfg_param mu_include_param[] = {
460 { "include", mu_cfg_callback, &idata, 0, _cb_include,
461 N_("Include contents of the given file. If a directory is given, "
462 "include contents of the file <file>/<program>, where <program> is "
463 "the name of the program. This latter form is allowed only in "
464 "the site-wide configuration file."),
465 N_("file-or-directory") },
466 { NULL }
467 };
468
469 mu_config_clone_container (cont);
470 idata.progname = progname;
471 idata.progparam = progparam;
472 idata.flags = flags & MU_PARSE_CONFIG_GLOBAL;
473 idata.target = target;
474 _mu_config_register_section (&cont, NULL, NULL, NULL,
475 (void*) progname, mu_include_param, NULL);
476 if (flags & MU_PARSE_CONFIG_GLOBAL)
477 {
478 mu_iterator_t iter;
479 struct mu_cfg_section *prog_sect;
480 struct mu_cfg_cont *old_root = root_container;
481 static struct mu_cfg_param empty_param = { NULL };
482 if (!progparam)
483 progparam = &empty_param;
484
485 _mu_config_register_section (&cont, NULL, "program", progname,
486 prog_parser, progparam, &prog_sect);
487
488 if (old_root->v.section.children)
489 {
490 if (!prog_sect->children)
491 mu_list_create (&prog_sect->children);
492 mu_list_get_iterator (old_root->v.section.children, &iter);
493 for (mu_iterator_first (iter); !mu_iterator_is_done (iter);
494 mu_iterator_next (iter))
495 {
496 struct mu_cfg_cont *c;
497 mu_iterator_current (iter, (void**)&c);
498 mu_list_append (prog_sect->children, c);
499 }
500 mu_iterator_destroy (&iter);
501 }
502 }
503 else if (progparam)
504 _mu_config_register_section (&cont, NULL, NULL, NULL, NULL,
505 progparam, NULL);
506 return cont;
507 }
508
509 int
510 mu_cfg_tree_reduce (mu_cfg_tree_t *parse_tree, const char *progname,
511 struct mu_cfg_param *progparam, int flags,
512 void *target_ptr)
513 {
514 int rc = 1;
515
516 if (root_container)
517 {
518 struct mu_cfg_cont *cont = mu_build_container (progname, progparam,
519 flags, target_ptr);
520 rc = mu_cfg_scan_tree (parse_tree, &cont->v.section, target_ptr,
521 (void*) progname);
522 mu_config_destroy_container (&cont);
523 }
524
525 if (flags & MU_PARSE_CONFIG_DUMP)
526 {
527 mu_stream_t stream;
528 mu_stdio_stream_create (&stream, stderr,
529 MU_STREAM_NO_CHECK|MU_STREAM_NO_CLOSE);
530 mu_stream_open (stream);
531 mu_cfg_format_parse_tree (stream, parse_tree);
532 mu_stream_destroy (&stream, NULL);
533 }
534
535 return rc;
536 }
537
538 void
539 mu_format_config_tree (mu_stream_t stream, const char *progname,
540 struct mu_cfg_param *progparam, int flags)
541 {
542 struct mu_cfg_cont *cont = mu_build_container (progname, progparam, flags,
543 NULL);
544 mu_cfg_format_container (stream, cont);
545 mu_config_destroy_container (&cont);
546 }
547
548 int
549 mu_parse_config (const char *file, const char *progname,
550 struct mu_cfg_param *progparam, int flags,
551 void *target_ptr)
552 {
553 int rc;
554 char *full_name = mu_tilde_expansion (file, "/", NULL);
555 if (full_name)
556 {
557 if (access (full_name, R_OK) == 0)
558 {
559 rc = mu_get_config (full_name, progname, progparam, flags,
560 target_ptr);
561 free (full_name);
562 }
563 else
564 rc = ENOENT;
565 }
566 else
567 rc = ENOMEM;
568 return rc;
569 }
...@@ -172,6 +172,8 @@ mu_cfg_data_type_string (enum mu_cfg_param_data_type type) ...@@ -172,6 +172,8 @@ mu_cfg_data_type_string (enum mu_cfg_param_data_type type)
172 return N_("host"); 172 return N_("host");
173 case mu_cfg_callback: 173 case mu_cfg_callback:
174 return N_("string"); 174 return N_("string");
175 case mu_cfg_section:
176 return N_("section");
175 } 177 }
176 return N_("unknown"); 178 return N_("unknown");
177 } 179 }
...@@ -261,19 +263,16 @@ format_section (mu_stream_t stream, struct mu_cfg_section *sect, int level) ...@@ -261,19 +263,16 @@ format_section (mu_stream_t stream, struct mu_cfg_section *sect, int level)
261 if (sect->ident) 263 if (sect->ident)
262 { 264 {
263 mu_stream_sequential_write (stream, sect->ident, strlen (sect->ident)); 265 mu_stream_sequential_write (stream, sect->ident, strlen (sect->ident));
264 if (sect->data) 266 if (sect->label)
265 { 267 {
266 /* FIXME: This is wrong in general. Data is an opaque data
267 pointer. */
268 char *s = sect->data;
269 mu_stream_sequential_write (stream, " ", 1); 268 mu_stream_sequential_write (stream, " ", 1);
270 mu_stream_sequential_write (stream, s, strlen (s)); 269 mu_stream_sequential_write (stream, sect->label,
270 strlen (sect->label));
271 } 271 }
272 mu_stream_sequential_write (stream, " {\n", 3); 272 mu_stream_sequential_write (stream, " {\n", 3);
273 c.stream = stream; 273 c.stream = stream;
274 c.level = level + 1; 274 c.level = level + 1;
275 mu_list_do (sect->subsec, _f_helper, &c); 275 mu_list_do (sect->children, _f_helper, &c);
276 mu_list_do (sect->param, _f_helper, &c);
277 format_level (stream, level); 276 format_level (stream, level);
278 mu_stream_sequential_write (stream, "};\n\n", 4); 277 mu_stream_sequential_write (stream, "};\n\n", 4);
279 } 278 }
...@@ -281,8 +280,7 @@ format_section (mu_stream_t stream, struct mu_cfg_section *sect, int level) ...@@ -281,8 +280,7 @@ format_section (mu_stream_t stream, struct mu_cfg_section *sect, int level)
281 { 280 {
282 c.stream = stream; 281 c.stream = stream;
283 c.level = level; 282 c.level = level;
284 mu_list_do (sect->subsec, _f_helper, &c); 283 mu_list_do (sect->children, _f_helper, &c);
285 mu_list_do (sect->param, _f_helper, &c);
286 } 284 }
287 } 285 }
288 286
......
...@@ -25,17 +25,12 @@ ...@@ -25,17 +25,12 @@
25 #include <errno.h> 25 #include <errno.h>
26 #include <unistd.h> 26 #include <unistd.h>
27 #include <ctype.h> 27 #include <ctype.h>
28 #include <mailutils/errno.h>
29 #include <mailutils/error.h>
28 #include <mailutils/argcv.h> 30 #include <mailutils/argcv.h>
29 #include <mailutils/nls.h> 31 #include <mailutils/nls.h>
30 #include <mailutils/cfg.h> 32 #include <mailutils/cfg.h>
31 #include <mailutils/errno.h>
32 #include <mailutils/error.h>
33 #include <mailutils/mutil.h>
34 #include <mailutils/monitor.h>
35 #include <mailutils/refcount.h>
36 #include <mailutils/list.h> 33 #include <mailutils/list.h>
37 #include <mailutils/iterator.h>
38 #include <mailutils/stream.h>
39 34
40 #include "cfg_parser.h" 35 #include "cfg_parser.h"
41 36
...@@ -350,497 +345,9 @@ again: ...@@ -350,497 +345,9 @@ again:
350 } 345 }
351 346
352 347
353 static struct mu_cfg_cont *root_container;
354
355 int
356 mu_config_create_container (struct mu_cfg_cont **pcont,
357 enum mu_cfg_cont_type type)
358 {
359 struct mu_cfg_cont *cont;
360 int rc;
361
362 cont = calloc (1, sizeof (*cont));
363 if (!cont)
364 return ENOMEM;
365 rc = mu_refcount_create (&cont->refcount);
366 if (rc)
367 free (cont);
368 else
369 {
370 cont->type = type;
371 *pcont = cont;
372 }
373 return rc;
374 }
375
376
377 struct dup_data
378 {
379 struct mu_cfg_cont *cont;
380 };
381
382 static int dup_container (struct mu_cfg_cont **pcont);
383
384 static int
385 _dup_section_action (void *item, void *cbdata)
386 {
387 int rc;
388 struct mu_cfg_cont *cont = item;
389 struct dup_data *pdd = cbdata;
390
391 rc = dup_container (&cont);
392 if (rc)
393 return rc;
394
395 if (!pdd->cont->v.section.subsec)
396 {
397 int rc = mu_list_create (&pdd->cont->v.section.subsec);
398 if (rc)
399 return rc;
400 }
401 return mu_list_append (pdd->cont->v.section.subsec, cont);
402 }
403
404 static int
405 _dup_param_action (void *item, void *cbdata)
406 {
407 int rc;
408 struct mu_cfg_cont *cont = item;
409 struct dup_data *pdd = cbdata;
410 rc = dup_container (&cont);
411 if (rc)
412 return rc;
413 if (!pdd->cont->v.section.param)
414 {
415 rc = mu_list_create (&pdd->cont->v.section.param);
416 if (rc)
417 return rc;
418 }
419 return mu_list_append (pdd->cont->v.section.param, cont);
420 }
421
422 static int
423 dup_container (struct mu_cfg_cont **pcont)
424 {
425 int rc;
426 struct mu_cfg_cont *newcont, *oldcont = *pcont;
427 struct dup_data dd;
428
429 rc = mu_config_create_container (&newcont, oldcont->type);
430 if (rc)
431 return rc;
432
433 dd.cont = newcont;
434 switch (oldcont->type)
435 {
436 case mu_cfg_cont_section:
437 newcont->v.section.ident = oldcont->v.section.ident;
438 newcont->v.section.parser = oldcont->v.section.parser;
439 newcont->v.section.data = oldcont->v.section.data;
440 newcont->v.section.docstring = oldcont->v.section.docstring;
441 newcont->v.section.subsec = NULL;
442 newcont->v.section.param = NULL;
443 mu_list_do (oldcont->v.section.subsec, _dup_section_action, &dd);
444 mu_list_do (oldcont->v.section.param, _dup_param_action, &dd);
445 break;
446
447 case mu_cfg_cont_param:
448 newcont->v.param = oldcont->v.param;
449 break;
450 }
451 *pcont = newcont;
452 return 0;
453 }
454
455
456 static void
457 destroy_list (mu_list_t *plist)
458 {
459 mu_list_t list = *plist;
460 mu_iterator_t itr = NULL;
461
462 if (!list)
463 return;
464
465 mu_list_get_iterator (list, &itr);
466 for (mu_iterator_first (itr); !mu_iterator_is_done (itr);
467 mu_iterator_next (itr))
468 {
469 struct mu_cfg_cont *cont, *p;
470 mu_iterator_current (itr, (void**)&cont);
471 p = cont;
472 mu_config_destroy_container (&p);
473 if (!p)
474 mu_list_remove (list, cont);
475 }
476 mu_iterator_destroy (&itr);
477 if (mu_list_is_empty (list))
478 mu_list_destroy (plist);
479 }
480
481 void
482 mu_config_destroy_container (struct mu_cfg_cont **pcont)
483 {
484 struct mu_cfg_cont *cont = *pcont;
485 unsigned refcount = mu_refcount_dec (cont->refcount);
486 /* printf ("destr %p-%s: %d\n", cont, cont->v.section.ident, refcount); */
487 switch (cont->type)
488 {
489 case mu_cfg_cont_section:
490 destroy_list (&cont->v.section.subsec);
491 destroy_list (&cont->v.section.param);
492 break;
493
494 case mu_cfg_cont_param:
495 break;
496 }
497
498 if (refcount == 0)
499 {
500 free (cont);
501 *pcont = 0;
502 }
503 }
504
505
506 static int
507 add_parameters (struct mu_cfg_section *sect, struct mu_cfg_param *param)
508 {
509 if (!param)
510 return 0;
511 if (!sect->param)
512 mu_list_create (&sect->param);
513 for (; param->ident; param++)
514 {
515 int rc;
516 struct mu_cfg_cont *container;
517
518 rc = mu_config_create_container (&container, mu_cfg_cont_param);
519 if (rc)
520 return rc;
521 container->v.param = *param;
522 mu_list_append (sect->param, container);
523 }
524 return 0;
525 }
526
527 static int
528 _clone_action (void *item, void *cbdata)
529 {
530 struct mu_cfg_cont *cont = item;
531 return mu_config_clone_container (cont);
532 }
533
534 int
535 mu_config_clone_container (struct mu_cfg_cont *cont)
536 {
537 mu_refcount_inc (cont->refcount);
538 /* printf("clone %p-%s: %d\n", cont, cont->v.section.ident, n); */
539 switch (cont->type)
540 {
541 case mu_cfg_cont_section:
542 mu_list_do (cont->v.section.subsec, _clone_action, NULL);
543 mu_list_do (cont->v.section.param, _clone_action, NULL);
544 break;
545
546 case mu_cfg_cont_param:
547 break;
548 }
549 return 0;
550 }
551
552
553 int
554 _mu_config_register_section (struct mu_cfg_cont **proot,
555 const char *parent_path,
556 const char *ident,
557 mu_cfg_section_fp parser,
558 void *data,
559 struct mu_cfg_param *param,
560 struct mu_cfg_section **psection)
561 {
562 int rc;
563 struct mu_cfg_section *root_section;
564 struct mu_cfg_section *parent;
565
566 if (!*proot)
567 {
568 rc = mu_config_create_container (proot, mu_cfg_cont_section);
569 if (rc)
570 return rc;
571 memset (&(*proot)->v.section, 0, sizeof (*proot)->v.section);
572 }
573
574 root_section = &(*proot)->v.section;
575
576 if (parent_path)
577 {
578 if (mu_cfg_find_section (root_section, parent_path, &parent))
579 return MU_ERR_NOENT;
580 }
581 else
582 parent = root_section;
583
584 if (mu_refcount_value ((*proot)->refcount) > 1)
585 {
586 /* It is a clone, do copy-on-write */
587 rc = dup_container (proot);
588 if (rc)
589 return rc;
590
591 root_section = &(*proot)->v.section;
592
593 if (parent_path)
594 {
595 if (mu_cfg_find_section (root_section, parent_path, &parent))
596 return MU_ERR_NOENT;
597 }
598 else
599 parent = root_section;
600 }
601
602 if (ident)
603 {
604 struct mu_cfg_cont *container;
605 struct mu_cfg_section *s;
606
607 if (!parent->subsec)
608 mu_list_create (&parent->subsec);
609 mu_config_create_container (&container, mu_cfg_cont_section);
610 mu_list_append (parent->subsec, container);
611 s = &container->v.section;
612
613 s->ident = strdup (ident);
614 s->parser = parser;
615 s->data = data;
616 s->subsec = NULL;
617 s->param = NULL;
618 add_parameters (s, param);
619 if (psection)
620 *psection = s;
621 }
622 else
623 {
624 add_parameters (parent, param);
625 if (!parent->parser)
626 parent->parser = parser;
627 if (!parent->data)
628 parent->data = data;
629 if (psection)
630 *psection = parent;
631 }
632 return 0;
633 }
634
635 int 348 int
636 mu_config_register_section (const char *parent_path, 349 mu_get_config (const char *file, const char *progname,
637 const char *ident, 350 struct mu_cfg_param *progparam, int flags, void *target_ptr)
638 mu_cfg_section_fp parser,
639 void *data,
640 struct mu_cfg_param *param)
641 {
642 return _mu_config_register_section (&root_container,
643 parent_path,
644 ident, parser, data, param, NULL);
645 }
646
647 int
648 mu_config_register_plain_section (const char *parent_path, const char *ident,
649 struct mu_cfg_param *params)
650 {
651 return mu_config_register_section (parent_path, ident, NULL, NULL, params);
652 }
653
654 static int
655 prog_parser (enum mu_cfg_section_stage stage,
656 const mu_cfg_node_t *node,
657 void *section_data, void *call_data,
658 mu_cfg_tree_t *tree)
659 {
660 if (stage == mu_cfg_section_start)
661 {
662 return strcmp (node->tag_label, call_data);
663 }
664 return 0;
665 }
666
667 static char *
668 make_file_name (const char *dir, const char *file)
669 {
670 char *tmp;
671 size_t len = strlen (dir) + 1 + strlen (file);
672 tmp = malloc (len + 1);
673 if (!tmp)
674 {
675 mu_error ("%s", mu_strerror (errno));
676 exit (1);
677 }
678 strcpy (tmp, dir);
679 strcat (tmp, "/");
680 strcat (tmp, file);
681 return tmp;
682 }
683
684 struct include_data
685 {
686 const char *progname;
687 struct mu_cfg_param *progparam;
688 int flags;
689 };
690
691 static int _mu_parse_config (const char *file, const char *progname,
692 struct mu_cfg_param *progparam, int flags);
693
694 static int
695 _cb_include (mu_debug_t debug, void *data, char *arg)
696 {
697 int ret = 0;
698 struct stat sb;
699 char *dirname = arg;
700 struct include_data *idp = data;
701 char *tmp = NULL;
702
703 if (dirname[0] != '/')
704 dirname = tmp = make_file_name (SYSCONFDIR, dirname);
705
706 if (stat (dirname, &sb) == 0)
707 {
708 if (S_ISDIR (sb.st_mode))
709 {
710 char *file = make_file_name (dirname, idp->progname);
711 ret = _mu_parse_config (file, idp->progname, idp->progparam, 0);
712 }
713 else
714 ret = _mu_parse_config (dirname, idp->progname, idp->progparam,
715 idp->flags);
716 }
717 else if (errno == ENOENT)
718 {
719 mu_cfg_format_error (debug, MU_DEBUG_ERROR,
720 _("include file or directory does not exist"));
721 ret = 1;
722 }
723 else
724 {
725 mu_cfg_format_error (debug, MU_DEBUG_ERROR,
726 _("cannot stat include file or directory: %s"),
727 mu_strerror (errno));
728 ret = 1;
729 }
730 free (tmp);
731 return ret;
732 }
733
734 struct mu_cfg_cont *
735 mu_build_container (const char *progname,
736 struct mu_cfg_param *progparam, int flags)
737 {
738 struct mu_cfg_cont *cont = root_container;
739 struct include_data idata;
740 struct mu_cfg_param mu_include_param[] = {
741 { "include", mu_cfg_callback, &idata, _cb_include,
742 N_("Include contents of the given file. If a directory is given, "
743 "include contents of the file <file>/<program>, where <program> is "
744 "the name of the program. This latter form is allowed only in "
745 "the site-wide configuration file."),
746 N_("file-or-directory") },
747 { NULL }
748 };
749
750 mu_config_clone_container (cont);
751 idata.progname = progname;
752 idata.progparam = progparam;
753 idata.flags = flags & MU_PARSE_CONFIG_GLOBAL;
754 _mu_config_register_section (&cont, NULL, NULL, NULL,
755 (void*) progname, mu_include_param, NULL);
756 if (flags & MU_PARSE_CONFIG_GLOBAL)
757 {
758 mu_iterator_t iter;
759 struct mu_cfg_section *prog_sect;
760 struct mu_cfg_cont *old_root = root_container;
761 static struct mu_cfg_param empty_param = { NULL };
762 if (!progparam)
763 progparam = &empty_param;
764
765 _mu_config_register_section (&cont, NULL, "program", prog_parser,
766 (void*) progname,
767 progparam, &prog_sect);
768
769 if (old_root->v.section.subsec)
770 {
771 if (!prog_sect->subsec)
772 mu_list_create (&prog_sect->subsec);
773 mu_list_get_iterator (old_root->v.section.subsec, &iter);
774 for (mu_iterator_first (iter); !mu_iterator_is_done (iter);
775 mu_iterator_next (iter))
776 {
777 struct mu_cfg_cont *c;
778 mu_iterator_current (iter, (void**)&c);
779 mu_list_append (prog_sect->subsec, c);
780 }
781 mu_iterator_destroy (&iter);
782 }
783
784 if (old_root->v.section.param)
785 {
786 if (!prog_sect->param)
787 mu_list_create (&prog_sect->param);
788 mu_list_get_iterator (old_root->v.section.param, &iter);
789 for (mu_iterator_first (iter); !mu_iterator_is_done (iter);
790 mu_iterator_next (iter))
791 {
792 struct mu_cfg_cont *c;
793 mu_iterator_current (iter, (void**)&c);
794 mu_list_append (prog_sect->param, c);
795 }
796 mu_iterator_destroy (&iter);
797 }
798 }
799 else if (progparam)
800 _mu_config_register_section (&cont, NULL, NULL, NULL, NULL,
801 progparam, NULL);
802 return cont;
803 }
804
805 int
806 mu_parse_config_tree (mu_cfg_tree_t *parse_tree, const char *progname,
807 struct mu_cfg_param *progparam, int flags)
808 {
809 int rc = 1;
810
811 if (root_container)
812 {
813 struct mu_cfg_cont *cont = mu_build_container (progname, progparam,
814 flags);
815 rc = mu_cfg_scan_tree (parse_tree, &cont->v.section, (void*) progname);
816 mu_config_destroy_container (&cont);
817 }
818
819 if (flags & MU_PARSE_CONFIG_DUMP)
820 {
821 mu_stream_t stream;
822 mu_stdio_stream_create (&stream, stderr,
823 MU_STREAM_NO_CHECK|MU_STREAM_NO_CLOSE);
824 mu_stream_open (stream);
825 mu_cfg_format_parse_tree (stream, parse_tree);
826 mu_stream_destroy (&stream, NULL);
827 }
828
829 return rc;
830 }
831
832 void
833 mu_format_config_tree (mu_stream_t stream, const char *progname,
834 struct mu_cfg_param *progparam, int flags)
835 {
836 struct mu_cfg_cont *cont = mu_build_container (progname, progparam, flags);
837 mu_cfg_format_container (stream, cont);
838 mu_config_destroy_container (&cont);
839 }
840
841 static int
842 _mu_parse_config (const char *file, const char *progname,
843 struct mu_cfg_param *progparam, int flags)
844 { 351 {
845 struct lexer_data data; 352 struct lexer_data data;
846 struct stat st; 353 struct stat st;
...@@ -883,7 +390,8 @@ _mu_parse_config (const char *file, const char *progname, ...@@ -883,7 +390,8 @@ _mu_parse_config (const char *file, const char *progname,
883 NULL); 390 NULL);
884 391
885 if (rc == 0) 392 if (rc == 0)
886 rc = mu_parse_config_tree (parse_tree, progname, progparam, flags); 393 rc = mu_cfg_tree_reduce (parse_tree, progname, progparam, flags,
394 target_ptr);
887 395
888 mu_cfg_destroy_tree (&parse_tree); 396 mu_cfg_destroy_tree (&parse_tree);
889 mu_list_destroy (&data.mpool); 397 mu_list_destroy (&data.mpool);
...@@ -896,23 +404,3 @@ _mu_parse_config (const char *file, const char *progname, ...@@ -896,23 +404,3 @@ _mu_parse_config (const char *file, const char *progname,
896 return rc; 404 return rc;
897 } 405 }
898 406
899 int
900 mu_parse_config (const char *file, const char *progname,
901 struct mu_cfg_param *progparam, int flags)
902 {
903 int rc;
904 char *full_name = mu_tilde_expansion (file, "/", NULL);
905 if (full_name)
906 {
907 if (access (full_name, R_OK) == 0)
908 {
909 rc = _mu_parse_config (full_name, progname, progparam, flags);
910 free (full_name);
911 }
912 else
913 rc = ENOENT;
914 }
915 else
916 rc = ENOMEM;
917 return rc;
918 }
......
...@@ -497,13 +497,15 @@ struct mu_cfg_section_list ...@@ -497,13 +497,15 @@ struct mu_cfg_section_list
497 struct scan_tree_data 497 struct scan_tree_data
498 { 498 {
499 struct mu_cfg_section_list *list; 499 struct mu_cfg_section_list *list;
500 void *target;
500 void *call_data; 501 void *call_data;
501 mu_cfg_tree_t *tree; 502 mu_cfg_tree_t *tree;
502 int error; 503 int error;
503 }; 504 };
504 505
505 static struct mu_cfg_cont * 506 static struct mu_cfg_cont *
506 find_container (mu_list_t list, const char *ident, size_t len) 507 find_container (mu_list_t list, enum mu_cfg_cont_type type,
508 const char *ident, size_t len)
507 { 509 {
508 mu_iterator_t iter; 510 mu_iterator_t iter;
509 struct mu_cfg_cont *ret = NULL; 511 struct mu_cfg_cont *ret = NULL;
...@@ -518,7 +520,8 @@ find_container (mu_list_t list, const char *ident, size_t len) ...@@ -518,7 +520,8 @@ find_container (mu_list_t list, const char *ident, size_t len)
518 struct mu_cfg_cont *cont; 520 struct mu_cfg_cont *cont;
519 mu_iterator_current (iter, (void**) &cont); 521 mu_iterator_current (iter, (void**) &cont);
520 522
521 if (strlen (cont->v.ident) == len 523 if (cont->type == type
524 && strlen (cont->v.ident) == len
522 && memcmp (cont->v.ident, ident, len) == 0) 525 && memcmp (cont->v.ident, ident, len) == 0)
523 { 526 {
524 ret = cont; 527 ret = cont;
...@@ -534,9 +537,11 @@ find_subsection (struct mu_cfg_section *sec, const char *ident, size_t len) ...@@ -534,9 +537,11 @@ find_subsection (struct mu_cfg_section *sec, const char *ident, size_t len)
534 { 537 {
535 if (sec) 538 if (sec)
536 { 539 {
537 if (sec->subsec) 540 if (sec->children)
538 { 541 {
539 struct mu_cfg_cont *cont = find_container (sec->subsec, ident, len); 542 struct mu_cfg_cont *cont = find_container (sec->children,
543 mu_cfg_cont_section,
544 ident, len);
540 if (cont) 545 if (cont)
541 return &cont->v.section; 546 return &cont->v.section;
542 } 547 }
...@@ -549,9 +554,11 @@ find_param (struct mu_cfg_section *sec, const char *ident, size_t len) ...@@ -549,9 +554,11 @@ find_param (struct mu_cfg_section *sec, const char *ident, size_t len)
549 { 554 {
550 if (sec) 555 if (sec)
551 { 556 {
552 if (sec->param) 557 if (sec->children)
553 { 558 {
554 struct mu_cfg_cont *cont = find_container (sec->param, ident, len); 559 struct mu_cfg_cont *cont = find_container (sec->children,
560 mu_cfg_cont_param,
561 ident, len);
555 if (cont) 562 if (cont)
556 return &cont->v.param; 563 return &cont->v.param;
557 } 564 }
...@@ -842,8 +849,10 @@ parse_bool (struct scan_tree_data *sdata, const mu_cfg_node_t *node, int *res) ...@@ -842,8 +849,10 @@ parse_bool (struct scan_tree_data *sdata, const mu_cfg_node_t *node, int *res)
842 static int 849 static int
843 parse_param (struct scan_tree_data *sdata, const mu_cfg_node_t *node) 850 parse_param (struct scan_tree_data *sdata, const mu_cfg_node_t *node)
844 { 851 {
852 void *tgt;
845 struct mu_cfg_param *param = find_param (sdata->list->sec, node->tag_name, 853 struct mu_cfg_param *param = find_param (sdata->list->sec, node->tag_name,
846 0); 854 0);
855
847 if (!param) 856 if (!param)
848 { 857 {
849 _mu_cfg_perror (sdata->tree->debug, &node->locus, 858 _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) ...@@ -852,6 +861,22 @@ parse_param (struct scan_tree_data *sdata, const mu_cfg_node_t *node)
852 return 1; 861 return 1;
853 } 862 }
854 863
864 if (param->data)
865 tgt = param->data;
866 else if (sdata->list->sec->target)
867 tgt = (char*)sdata->list->sec->target + param->offset;
868 else if (sdata->target)
869 tgt = (char*)sdata->target + param->offset;
870 else if (param->type == mu_cfg_callback)
871 tgt = NULL;
872 else
873 {
874 _mu_cfg_perror (sdata->tree->debug, &node->locus,
875 _("INTERNAL ERROR: cannot determine target offset for "
876 "%s"), param->ident);
877 abort ();
878 }
879
855 switch (param->type) 880 switch (param->type)
856 { 881 {
857 case mu_cfg_string: 882 case mu_cfg_string:
...@@ -865,80 +890,80 @@ parse_param (struct scan_tree_data *sdata, const mu_cfg_node_t *node) ...@@ -865,80 +890,80 @@ parse_param (struct scan_tree_data *sdata, const mu_cfg_node_t *node)
865 return 1; 890 return 1;
866 } 891 }
867 strcpy (s, node->tag_label); 892 strcpy (s, node->tag_label);
868 /* FIXME: free param->data? */ 893 /* FIXME: free tgt? */
869 *(char**)param->data = s; 894 *(char**)tgt = s;
870 break; 895 break;
871 } 896 }
872 897
873 case mu_cfg_short: 898 case mu_cfg_short:
874 GETSNUM (node->tag_label, short, *(short*)param->data, 899 GETSNUM (node->tag_label, short, *(short*)tgt,
875 sdata->tree->debug); 900 sdata->tree->debug);
876 break; 901 break;
877 902
878 case mu_cfg_ushort: 903 case mu_cfg_ushort:
879 GETUNUM (node->tag_label, unsigned short, *(unsigned short*)param->data, 904 GETUNUM (node->tag_label, unsigned short, *(unsigned short*)tgt,
880 sdata->tree->debug); 905 sdata->tree->debug);
881 break; 906 break;
882 907
883 case mu_cfg_int: 908 case mu_cfg_int:
884 GETSNUM (node->tag_label, int, *(int*)param->data, sdata->tree->debug); 909 GETSNUM (node->tag_label, int, *(int*)tgt, sdata->tree->debug);
885 break; 910 break;
886 911
887 case mu_cfg_uint: 912 case mu_cfg_uint:
888 GETUNUM (node->tag_label, unsigned int, *(unsigned int*)param->data, 913 GETUNUM (node->tag_label, unsigned int, *(unsigned int*)tgt,
889 sdata->tree->debug); 914 sdata->tree->debug);
890 break; 915 break;
891 916
892 case mu_cfg_long: 917 case mu_cfg_long:
893 GETSNUM (node->tag_label, long, *(long*)param->data, 918 GETSNUM (node->tag_label, long, *(long*)tgt,
894 sdata->tree->debug); 919 sdata->tree->debug);
895 break; 920 break;
896 921
897 case mu_cfg_ulong: 922 case mu_cfg_ulong:
898 GETUNUM (node->tag_label, unsigned long, *(unsigned long*)param->data, 923 GETUNUM (node->tag_label, unsigned long, *(unsigned long*)tgt,
899 sdata->tree->debug); 924 sdata->tree->debug);
900 break; 925 break;
901 926
902 case mu_cfg_size: 927 case mu_cfg_size:
903 GETUNUM (node->tag_label, size_t, *(size_t*)param->data, 928 GETUNUM (node->tag_label, size_t, *(size_t*)tgt,
904 sdata->tree->debug); 929 sdata->tree->debug);
905 break; 930 break;
906 931
907 case mu_cfg_off: 932 case mu_cfg_off:
908 _mu_cfg_perror (sdata->tree->debug, &node->locus, 933 _mu_cfg_perror (sdata->tree->debug, &node->locus,
909 _("not implemented yet")); 934 _("not implemented yet"));
910 /* GETSNUM(node->tag_label, off_t, *(off_t*)param->data); */ 935 /* GETSNUM(node->tag_label, off_t, *(off_t*)tgt); */
911 return 1; 936 return 1;
912 937
913 case mu_cfg_time: 938 case mu_cfg_time:
914 GETUNUM (node->tag_label, time_t, *(time_t*)param->data, 939 GETUNUM (node->tag_label, time_t, *(time_t*)tgt,
915 sdata->tree->debug); 940 sdata->tree->debug);
916 break; 941 break;
917 942
918 case mu_cfg_bool: 943 case mu_cfg_bool:
919 if (parse_bool (sdata, node, (int*) param->data)) 944 if (parse_bool (sdata, node, (int*) tgt))
920 return 1; 945 return 1;
921 break; 946 break;
922 947
923 case mu_cfg_ipv4: 948 case mu_cfg_ipv4:
924 if (parse_ipv4 (sdata, node, (struct in_addr *)param->data)) 949 if (parse_ipv4 (sdata, node, (struct in_addr *)tgt))
925 return 1; 950 return 1;
926 break; 951 break;
927 952
928 case mu_cfg_cidr: 953 case mu_cfg_cidr:
929 if (parse_cidr (sdata, node, (mu_cfg_cidr_t *)param->data)) 954 if (parse_cidr (sdata, node, (mu_cfg_cidr_t *)tgt))
930 return 1; 955 return 1;
931 break; 956 break;
932 957
933 case mu_cfg_host: 958 case mu_cfg_host:
934 if (parse_host (sdata, node, (struct in_addr *)param->data)) 959 if (parse_host (sdata, node, (struct in_addr *)tgt))
935 return 1; 960 return 1;
936 break; 961 break;
937 962
938 case mu_cfg_callback: 963 case mu_cfg_callback:
939 mu_debug_set_locus (sdata->tree->debug, node->locus.file, 964 mu_debug_set_locus (sdata->tree->debug, node->locus.file,
940 node->locus.line); 965 node->locus.line);
941 if (param->callback (sdata->tree->debug, param->data, node->tag_label)) 966 if (param->callback (sdata->tree->debug, tgt, node->tag_label))
942 return 1; 967 return 1;
943 break; 968 break;
944 969
...@@ -972,11 +997,12 @@ _scan_tree_helper (const mu_cfg_node_t *node, void *data) ...@@ -972,11 +997,12 @@ _scan_tree_helper (const mu_cfg_node_t *node, void *data)
972 } 997 }
973 return MU_CFG_ITER_SKIP; 998 return MU_CFG_ITER_SKIP;
974 } 999 }
975 if (!sec->subsec && !sec->param) 1000 if (!sec->children)
976 return MU_CFG_ITER_SKIP; 1001 return MU_CFG_ITER_SKIP;
977 if (sec->parser && 1002 if (sec->parser &&
978 sec->parser (mu_cfg_section_start, node, 1003 sec->parser (mu_cfg_section_start, node,
979 sec->data, sdata->call_data, sdata->tree)) 1004 sec->label, &sec->target,
1005 sdata->call_data, sdata->tree))
980 { 1006 {
981 sdata->error++; 1007 sdata->error++;
982 return MU_CFG_ITER_SKIP; 1008 return MU_CFG_ITER_SKIP;
...@@ -1010,7 +1036,8 @@ _scan_tree_end_helper (const mu_cfg_node_t *node, void *data) ...@@ -1010,7 +1036,8 @@ _scan_tree_end_helper (const mu_cfg_node_t *node, void *data)
1010 sec = pop_section (sdata); 1036 sec = pop_section (sdata);
1011 if (sec && sec->parser) 1037 if (sec && sec->parser)
1012 { 1038 {
1013 if (sec->parser (mu_cfg_section_end, node, sec->data, 1039 if (sec->parser (mu_cfg_section_end, node,
1040 sec->label, &sec->target,
1014 sdata->call_data, sdata->tree)) 1041 sdata->call_data, sdata->tree))
1015 { 1042 {
1016 sdata->error++; 1043 sdata->error++;
...@@ -1023,13 +1050,14 @@ _scan_tree_end_helper (const mu_cfg_node_t *node, void *data) ...@@ -1023,13 +1050,14 @@ _scan_tree_end_helper (const mu_cfg_node_t *node, void *data)
1023 1050
1024 int 1051 int
1025 mu_cfg_scan_tree (mu_cfg_tree_t *tree, struct mu_cfg_section *sections, 1052 mu_cfg_scan_tree (mu_cfg_tree_t *tree, struct mu_cfg_section *sections,
1026 void *data) 1053 void *target, void *data)
1027 { 1054 {
1028 struct scan_tree_data dat; 1055 struct scan_tree_data dat;
1029 dat.tree = tree; 1056 dat.tree = tree;
1030 dat.list = NULL; 1057 dat.list = NULL;
1031 dat.error = 0; 1058 dat.error = 0;
1032 dat.call_data = data; 1059 dat.call_data = data;
1060 dat.target = target;
1033 if (push_section (&dat, sections)) 1061 if (push_section (&dat, sections))
1034 return 1; 1062 return 1;
1035 mu_cfg_preorder (tree->node, _scan_tree_helper, _scan_tree_end_helper, &dat); 1063 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) ...@@ -166,13 +166,13 @@ cb_metamail (mu_debug_t debug, void *data, char *arg)
166 } 166 }
167 167
168 struct mu_cfg_param mimeview_cfg_param[] = { 168 struct mu_cfg_param mimeview_cfg_param[] = {
169 { "debug", mu_cfg_callback, NULL, cb_debug, 169 { "debug", mu_cfg_callback, NULL, 0, cb_debug,
170 N_("Set debug verbosity level."), 170 N_("Set debug verbosity level."),
171 N_("flags") }, 171 N_("flags") },
172 { "mimetypes", mu_cfg_string, &mimetypes_config, NULL, 172 { "mimetypes", mu_cfg_string, &mimetypes_config, 0, NULL,
173 N_("Use this mime.types file."), 173 N_("Use this mime.types file."),
174 N_("file") }, 174 N_("file") },
175 { "metamail", mu_cfg_string, NULL, cb_metamail, 175 { "metamail", mu_cfg_string, NULL, 0, cb_metamail,
176 N_("Use this program to display files."), 176 N_("Use this program to display files."),
177 N_("prog") }, 177 N_("prog") },
178 { NULL } 178 { NULL }
......
...@@ -90,11 +90,11 @@ static struct argp argp = { ...@@ -90,11 +90,11 @@ static struct argp argp = {
90 90
91 91
92 struct mu_cfg_param movemail_cfg_param[] = { 92 struct mu_cfg_param movemail_cfg_param[] = {
93 { "preserve", mu_cfg_bool, &preserve_mail, NULL, 93 { "preserve", mu_cfg_bool, &preserve_mail, 0, NULL,
94 N_("Do not remove messages from the source mailbox.") }, 94 N_("Do not remove messages from the source mailbox.") },
95 { "reverse", mu_cfg_bool, &reverse_order, NULL, 95 { "reverse", mu_cfg_bool, &reverse_order, 0, NULL,
96 N_("Reverse message sorting order.") }, 96 N_("Reverse message sorting order.") },
97 { "emacs", mu_cfg_bool, &emacs_mode, NULL, 97 { "emacs", mu_cfg_bool, &emacs_mode, 0, NULL,
98 N_("Output information used by Emacs rmail interface.") }, 98 N_("Output information used by Emacs rmail interface.") },
99 { NULL } 99 { NULL }
100 }; 100 };
......
...@@ -134,28 +134,28 @@ cb_bulletin_db (mu_debug_t debug, void *data, char *arg) ...@@ -134,28 +134,28 @@ cb_bulletin_db (mu_debug_t debug, void *data, char *arg)
134 } 134 }
135 135
136 static struct mu_cfg_param pop3d_cfg_param[] = { 136 static struct mu_cfg_param pop3d_cfg_param[] = {
137 { "undelete", mu_cfg_int, &undelete_on_startup, NULL, 137 { "undelete", mu_cfg_int, &undelete_on_startup, 0, NULL,
138 N_("On startup, clear deletion marks from all the messages.") }, 138 N_("On startup, clear deletion marks from all the messages.") },
139 { "expire", mu_cfg_uint, &expire, NULL, 139 { "expire", mu_cfg_uint, &expire, 0, NULL,
140 N_("Automatically expire read messages after the given number of days."), 140 N_("Automatically expire read messages after the given number of days."),
141 N_("days") }, 141 N_("days") },
142 { "delete-expired", mu_cfg_int, &expire_on_exit, NULL, 142 { "delete-expired", mu_cfg_int, &expire_on_exit, 0, NULL,
143 N_("Delete expired messages upon closing the mailbox.") }, 143 N_("Delete expired messages upon closing the mailbox.") },
144 #ifdef WITH_TLS 144 #ifdef WITH_TLS
145 { "tls-required", mu_cfg_callback, NULL, cb_tls_required, 145 { "tls-required", mu_cfg_callback, NULL, 0, cb_tls_required,
146 N_("Always require STLS before entering authentication phase.") }, 146 N_("Always require STLS before entering authentication phase.") },
147 #endif 147 #endif
148 #ifdef ENABLE_LOGIN_DELAY 148 #ifdef ENABLE_LOGIN_DELAY
149 { "login-delay", mu_cfg_time, &login_delay, NULL, 149 { "login-delay", mu_cfg_time, &login_delay, 0, NULL,
150 N_("Set the minimal allowed delay between two successive logins.") }, 150 N_("Set the minimal allowed delay between two successive logins.") },
151 { "stat-file", mu_cfg_string, &login_stat_file, NULL, 151 { "stat-file", mu_cfg_string, &login_stat_file, 0, NULL,
152 N_("Set the name of login statistics file (for login-delay).") }, 152 N_("Set the name of login statistics file (for login-delay).") },
153 #endif 153 #endif
154 { "bulletin-source", mu_cfg_callback, NULL, cb_bulletin_source, 154 { "bulletin-source", mu_cfg_callback, NULL, 0, cb_bulletin_source,
155 N_("Get bulletins from the specified mailbox."), 155 N_("Get bulletins from the specified mailbox."),
156 N_("url") }, 156 N_("url") },
157 #ifdef USE_DBM 157 #ifdef USE_DBM
158 { "bulletin-db", mu_cfg_callback, NULL, cb_bulletin_db, 158 { "bulletin-db", mu_cfg_callback, NULL, 0, cb_bulletin_db,
159 N_("Set the bulletin database file name."), 159 N_("Set the bulletin database file name."),
160 N_("file") }, 160 N_("file") },
161 #endif 161 #endif
......
...@@ -129,21 +129,21 @@ readmsg_parse_opt (int key, char *arg, struct argp_state *astate) ...@@ -129,21 +129,21 @@ readmsg_parse_opt (int key, char *arg, struct argp_state *astate)
129 129
130 130
131 struct mu_cfg_param readmsg_cfg_param[] = { 131 struct mu_cfg_param readmsg_cfg_param[] = {
132 { "debug", mu_cfg_int, &dbug, NULL, 132 { "debug", mu_cfg_int, &dbug, 0, NULL,
133 N_("Set debug verbosity level.") }, 133 N_("Set debug verbosity level.") },
134 { "header", mu_cfg_bool, &all_header, NULL, 134 { "header", mu_cfg_bool, &all_header, 0, NULL,
135 N_("Display entire headers.") }, 135 N_("Display entire headers.") },
136 { "weedlist", mu_cfg_string, &weedlist, NULL, 136 { "weedlist", mu_cfg_string, &weedlist, 0, NULL,
137 N_("Display only headers from this list. Argument is a list of header " 137 N_("Display only headers from this list. Argument is a list of header "
138 "names separated by whitespace or commas."), 138 "names separated by whitespace or commas."),
139 N_("list") }, 139 N_("list") },
140 { "folder", mu_cfg_string, &mailbox_name, NULL, 140 { "folder", mu_cfg_string, &mailbox_name, 0, NULL,
141 N_("Read messages from this folder.") }, 141 N_("Read messages from this folder.") },
142 { "no-header", mu_cfg_bool, &no_header, NULL, 142 { "no-header", mu_cfg_bool, &no_header, 0, NULL,
143 N_("Exclude all headers.") }, 143 N_("Exclude all headers.") },
144 { "form-feeds", mu_cfg_bool, &form_feed, NULL, 144 { "form-feeds", mu_cfg_bool, &form_feed, 0, NULL,
145 N_("Output formfeed character between messages.") }, 145 N_("Output formfeed character between messages.") },
146 { "show-all-match", mu_cfg_bool, &show_all, NULL, 146 { "show-all-match", mu_cfg_bool, &show_all, 0, NULL,
147 N_("Print all messages matching pattern, not only the first.") }, 147 N_("Print all messages matching pattern, not only the first.") },
148 { NULL } 148 { NULL }
149 }; 149 };
......
...@@ -287,15 +287,15 @@ cb_ticket (mu_debug_t debug, void *data, char *arg) ...@@ -287,15 +287,15 @@ cb_ticket (mu_debug_t debug, void *data, char *arg)
287 } 287 }
288 288
289 static struct mu_cfg_param sieve_cfg_param[] = { 289 static struct mu_cfg_param sieve_cfg_param[] = {
290 { "keep-going", mu_cfg_int, &keep_going, NULL, 290 { "keep-going", mu_cfg_int, &keep_going, 0, NULL,
291 N_("Do not abort if execution fails on a message.") }, 291 N_("Do not abort if execution fails on a message.") },
292 { "mbox-url", mu_cfg_string, &mbox_url, NULL, 292 { "mbox-url", mu_cfg_string, &mbox_url, 0, NULL,
293 N_("Mailbox to sieve (defaults to user's mail spool)."), 293 N_("Mailbox to sieve (defaults to user's mail spool)."),
294 N_("url") }, 294 N_("url") },
295 { "ticket", mu_cfg_callback, NULL, cb_ticket, 295 { "ticket", mu_cfg_callback, NULL, 0, cb_ticket,
296 N_("Ticket file for user authentication."), 296 N_("Ticket file for user authentication."),
297 N_("ticket") }, 297 N_("ticket") },
298 { "debug", mu_cfg_callback, NULL, cb_debug, 298 { "debug", mu_cfg_callback, NULL, 0, cb_debug,
299 N_("Debug flags. Argument consists of one or more of the following " 299 N_("Debug flags. Argument consists of one or more of the following "
300 "flags:\n" 300 "flags:\n"
301 " g - main parser traces\n" 301 " g - main parser traces\n"
...@@ -303,11 +303,11 @@ static struct mu_cfg_param sieve_cfg_param[] = { ...@@ -303,11 +303,11 @@ static struct mu_cfg_param sieve_cfg_param[] = {
303 " P - network protocols (MU_DEBUG_PROT)\n" 303 " P - network protocols (MU_DEBUG_PROT)\n"
304 " t - sieve trace (MU_SIEVE_DEBUG_TRACE)\n" 304 " t - sieve trace (MU_SIEVE_DEBUG_TRACE)\n"
305 " i - sieve instructions trace (MU_SIEVE_DEBUG_INSTR).") }, 305 " i - sieve instructions trace (MU_SIEVE_DEBUG_INSTR).") },
306 { "verbose", mu_cfg_bool, &verbose, NULL, 306 { "verbose", mu_cfg_bool, &verbose, 0, NULL,
307 N_("Log all executed actions.") }, 307 N_("Log all executed actions.") },
308 { "line-info", mu_cfg_bool, &sieve_print_locus, NULL, 308 { "line-info", mu_cfg_bool, &sieve_print_locus, 0, NULL,
309 N_("Print source locations along with action logs (default).") }, 309 N_("Print source locations along with action logs (default).") },
310 { "email", mu_cfg_callback, NULL, cb_email, 310 { "email", mu_cfg_callback, NULL, 0, cb_email,
311 N_("Set user email address.") }, 311 N_("Set user email address.") },
312 { NULL } 312 { NULL }
313 }; 313 };
......