Commit e0f4a7db e0f4a7db8af17b10d588db2d0a2eeeb6a9cb95f4 by Sergey Poznyakoff

Extend --config-help output. Each configuration parameter

has a docstring which is displayed as a comment before it.
A docstring is also added to the configuration group structure,
for use in future.

* include/mailutils/cfg.h (struct mu_cfg_param): New members
`docstring' and `argname'.
(struct mu_cfg_section): New member `docstring'.
(mu_cfg_format_docstring): New function.
* include/mailutils/libargp.h (mu_help_config_mode): New
declaration.
* libargp/cmdline.h (mu_help_config_mode): Remove.
* libargp/muinit.c (mu_app_init): Better format the initial
comment.
* mailbox/cfg_format.c (mu_cfg_data_type_string): Use NLS.
(mu_cfg_format_docstring): New function.
(format_param,format_section): Use mu_cfg_format_docstring.
* mailbox/cfg_lexer.c (mu_config_create_container): Initialize
allocated memory chunk with zeros.
(dup_container): Duplicate docstring.
(mu_build_container): Document include statement.

* dotlock/dotlock.c, imap4d/imap4d.c, libargp/tls.c,
libcfg/auth.c, libcfg/common.c, libcfg/gsasl.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, mimeview/mimeview.c,
movemail/movemail.c, pop3d/pop3d.c, readmsg/readmsg.c,
sieve/sieve.c: Document configuration file statements.

* pop3d/pop3d.h (expire): Change type to unsigned int.

* po/POTFILES.in: Add missing files.
1 parent 2bce826f
2007-12-04 Sergey Poznyakoff <gray@gnu.org.ua>
II. Extend --config-help output. Each configuration parameter
has a docstring which is displayed as a comment before it.
A docstring is also added to the configuration group structure,
for use in future.
* include/mailutils/cfg.h (struct mu_cfg_param): New members
`docstring' and `argname'.
(struct mu_cfg_section): New member `docstring'.
(mu_cfg_format_docstring): New function.
* include/mailutils/libargp.h (mu_help_config_mode): New
declaration.
* libargp/cmdline.h (mu_help_config_mode): Remove.
* libargp/muinit.c (mu_app_init): Better format the initial
comment.
* mailbox/cfg_format.c (mu_cfg_data_type_string): Use NLS.
(mu_cfg_format_docstring): New function.
(format_param,format_section): Use mu_cfg_format_docstring.
* mailbox/cfg_lexer.c (mu_config_create_container): Initialize
allocated memory chunk with zeros.
(dup_container): Duplicate docstring.
(mu_build_container): Document include statement.
* dotlock/dotlock.c, imap4d/imap4d.c, libargp/tls.c,
libcfg/auth.c, libcfg/common.c, libcfg/gsasl.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, mimeview/mimeview.c,
movemail/movemail.c, pop3d/pop3d.c, readmsg/readmsg.c,
sieve/sieve.c: Document configuration file statements.
* pop3d/pop3d.h (expire): Change type to unsigned int.
* po/POTFILES.in: Add missing files.
I. Implement --config-help option, which displays configuration
file statements understood by the given program.
* imap4d/imap4d.h: Include xalloc.h
* frm/common.c, imap4d/imap4d.c: Shut compiler warnings.
* include/mailutils/cfg.h (mu_cfg_format_tree): Rename to
mu_cfg_format_parse_tree
mu_cfg_format_parse_tree.
(mu_cfg_format_container,mu_format_config_tree): New functions.
(mu_parse_config_tree): New prototype.
(mu_cfg_tree_create_node): Change signature (const char* instead
......
......@@ -105,8 +105,10 @@ parse_opt (int key, char *arg, struct argp_state *state)
break;
case ARGP_KEY_NO_ARGS:
argp_error (state, _("FILE must be specified"));
if (!mu_help_config_mode)
argp_error (state, _("FILE must be specified"));
return ARGP_ERR_UNKNOWN;
case ARGP_KEY_INIT:
mu_argp_node_list_init (&lst);
break;
......@@ -123,9 +125,12 @@ parse_opt (int key, char *arg, struct argp_state *state)
struct mu_cfg_param dotlock_cfg_param[] = {
{ "force", mu_cfg_time, &force },
{ "retry", mu_cfg_int, &retries },
{ "debug", mu_cfg_bool, &debug },
{ "force", mu_cfg_time, &force, NULL,
N_("Forcibly break an existing lock older than the specified time.") },
{ "retry", mu_cfg_int, &retries, NULL,
N_("Number of times to retry acquiring the lock.") },
{ "debug", mu_cfg_bool, &debug, NULL,
N_("Print details of failure reasons to stderr.") },
{ NULL }
};
......
......@@ -272,16 +272,34 @@ cb_preauth (mu_debug_t debug, void *data, char *arg)
}
static struct mu_cfg_param imap4d_cfg_param[] = {
{ "other-namespace", mu_cfg_callback, NULL, cb_other },
{ "shared-namespace", mu_cfg_callback, NULL, cb_shared },
{ "login-disabled", mu_cfg_int, &login_disabled },
{ "create-home-dir", mu_cfg_bool, &create_home_dir },
{ "home-dir-mode", mu_cfg_callback, NULL, cb_mode },
{ "tls-required", mu_cfg_int, &tls_required },
{ "preauth", mu_cfg_callback, NULL, cb_preauth },
{ "preauth-only", mu_cfg_bool, &preauth_only },
{ "ident-keyfile", mu_cfg_string, &ident_keyfile },
{ "ident-entrypt-only", mu_cfg_bool, &ident_encrypt_only },
{ "other-namespace", mu_cfg_callback, NULL, cb_other,
N_("Set other users' namespace. Argument is a colon-separated list "
"of directories comprising the namespace.") },
{ "shared-namespace", mu_cfg_callback, NULL, cb_shared,
N_("Set shared namespace. Argument is a colon-separated list "
"of directories comprising the namespace.") },
{ "login-disabled", mu_cfg_int, &login_disabled, NULL,
N_("Disable LOGIN command.") },
{ "create-home-dir", mu_cfg_bool, &create_home_dir, NULL,
N_("If true, create non-existing user home directories.") },
{ "home-dir-mode", mu_cfg_callback, NULL, cb_mode,
N_("File mode for creating user home directories (octal)."),
N_("mode") },
{ "tls-required", mu_cfg_int, &tls_required, NULL,
N_("Always require STARTTLS before entering authentication phase.") },
{ "preauth", mu_cfg_callback, NULL, cb_preauth,
N_("Configure PREAUTH mode. MODE is one of:\n"
" prog:///<full-program-name: string>\n"
" ident[://:<port: string-or-number>]\n"
" stdio"),
N_("MODE") },
{ "preauth-only", mu_cfg_bool, &preauth_only, NULL,
N_("Use only preauth mode. If unable to setup it, disconnect "
"immediately.") },
{ "ident-keyfile", mu_cfg_string, &ident_keyfile, NULL,
N_("Name of DES keyfile for decoding ecrypted ident responses.") },
{ "ident-entrypt-only", mu_cfg_bool, &ident_encrypt_only, NULL,
N_("Use only ecrypted ident responses.") },
{ NULL }
};
......
......@@ -129,6 +129,8 @@ struct mu_cfg_param
enum mu_cfg_param_data_type type;
void *data;
mu_cfg_callback_t callback;
const char *docstring;
const char *argname;
};
enum mu_cfg_section_stage
......@@ -150,6 +152,7 @@ struct mu_cfg_section
void *data;
mu_list_t /* of mu_cfg_cont/mu_cfg_section */ subsec;
mu_list_t /* of mu_cfg_cont/mu_cfg_param */ param;
char *docstring;
};
enum mu_cfg_cont_type
......@@ -209,6 +212,8 @@ int mu_cfg_parse_boolean (const char *str, int *res);
extern int mu_cfg_parser_verbose;
void mu_cfg_format_docstring (mu_stream_t stream, const char *docstring,
int level);
void mu_cfg_format_parse_tree (mu_stream_t stream, struct mu_cfg_tree *tree);
void mu_cfg_format_container (mu_stream_t stream, struct mu_cfg_cont *cont);
void mu_format_config_tree (mu_stream_t stream, const char *progname,
......
......@@ -42,6 +42,8 @@ struct mu_cmdline_capa
struct argp_child *child;
};
extern int mu_help_config_mode;
extern struct mu_cmdline_capa mu_common_cmdline;
extern struct mu_cmdline_capa mu_logging_cmdline;
extern struct mu_cmdline_capa mu_license_cmdline;
......
......@@ -20,4 +20,3 @@
#include "mailutils/libargp.h"
extern struct mu_cfg_tree *mu_argp_tree;
extern int mu_help_config_mode;
......
......@@ -81,22 +81,28 @@ mu_app_init (struct argp *myargp, const char **capa,
if (mu_help_config_mode)
{
char *comment;
char *canonical_name = get_canonical_name ();
mu_stream_t stream;
mu_stdio_stream_create (&stream, stdout,
MU_STREAM_NO_CHECK|MU_STREAM_NO_CLOSE);
mu_stream_open (stream);
mu_stream_sequential_printf (stream,
"# Configuration file structure for %s utility.\n",
mu_program_name);
mu_stream_sequential_printf (stream,
"# For use in global configuration file (%s), enclose it\n"
"# in `program %s { ... };'\n",
MU_CONFIG_FILE,
mu_program_name);
mu_stream_sequential_printf (stream,
"# For more information, use `info %s'.\n",
canonical_name);
asprintf (&comment,
"Configuration file structure for %s utility.",
mu_program_name);
mu_cfg_format_docstring (stream, comment, 0);
free (comment);
asprintf (&comment,
"For use in global configuration file (%s), enclose it "
"in `program %s { ... };",
MU_CONFIG_FILE,
mu_program_name);
mu_cfg_format_docstring (stream, comment, 0);
free (comment);
asprintf (&comment, "For more information, use `info %s'.",
canonical_name);
mu_cfg_format_docstring (stream, comment, 0);
free (comment);
mu_format_config_tree (stream, mu_program_name, cfg_param, 0);
mu_stream_destroy (&stream, NULL);
......
......@@ -31,7 +31,7 @@ enum {
static struct argp_option _tls_argp_options[] = {
{"ssl-cert", OPT_SSL_CERT, N_("FILE"), OPTION_HIDDEN,
N_("Specify SSL certificate file"), 0},
N_("Specify SSL certificate filep"), 0},
{"ssl-key", OPT_SSL_KEY, N_("FILE"), OPTION_HIDDEN,
N_("Specify SSL certificate key"), },
{"ssl-cafile", OPT_SSL_CAFILE, N_("FILE"), OPTION_HIDDEN,
......
......@@ -50,8 +50,16 @@ cb_authorization (mu_debug_t err, void *data, char *arg)
}
static struct mu_cfg_param mu_auth_param[] = {
{ "authentication", mu_cfg_callback, NULL, cb_authentication },
{ "authorization", mu_cfg_callback, NULL, cb_authorization },
{ "authentication", mu_cfg_callback, NULL, cb_authentication,
N_("Set a list of modules for authentication. Modlist is a "
"colon-separated list of module names or a word `clear' to "
"clear the previously set up values."),
N_("modlist") },
{ "authorization", mu_cfg_callback, NULL, cb_authorization,
N_("Set a list of modules for authorization. Modlist is a "
"colon-separated list of module names or a word `clear' to "
"clear the previously set up values."),
N_("modlist") },
{ NULL }
};
......
......@@ -40,8 +40,11 @@ static struct mu_gocs_debug debug_settings;
/* ************************************************************************* */
static struct mu_cfg_param mu_mailbox_param[] = {
{ "mail-spool", mu_cfg_string, &mailbox_settings.mail_spool },
{ "mailbox-type", mu_cfg_string, &mailbox_settings.mailbox_type },
{ "mail-spool", mu_cfg_string, &mailbox_settings.mail_spool, NULL,
N_("Use specified URL as a mailspool directory."),
N_("url") },
{ "mailbox-type", mu_cfg_string, &mailbox_settings.mailbox_type, NULL,
N_("Default mailbox type."), N_("protocol") },
{ NULL }
};
......@@ -53,11 +56,19 @@ DCL_CFG_CAPA (mailbox);
/* ************************************************************************* */
static struct mu_cfg_param mu_locking_param[] = {
{ "flags", mu_cfg_string, &locking_settings.lock_flags },
{ "retry-timeout", mu_cfg_ulong, &locking_settings.lock_retry_timeout },
{ "retry-count", mu_cfg_ulong, &locking_settings.lock_retry_count },
{ "expire-timeout", mu_cfg_ulong, &locking_settings.lock_expire_timeout },
{ "external-locker", mu_cfg_string, &locking_settings.external_locker },
/* FIXME: Flags are superfluous. */
{ "flags", mu_cfg_string, &locking_settings.lock_flags, NULL,
N_("Default locker flags (E=external, R=retry, T=time, P=pid).") },
{ "retry-timeout", mu_cfg_ulong, &locking_settings.lock_retry_timeout, NULL,
N_("Set timeout for acquiring the lock.") },
{ "retry-count", mu_cfg_ulong, &locking_settings.lock_retry_count, NULL,
N_("Set the maximum number of times to retry acquiring the lock.") },
{ "expire-timeout", mu_cfg_ulong, &locking_settings.lock_expire_timeout,
NULL,
N_("Expire locks older than this amount of time.") },
{ "external-locker", mu_cfg_string, &locking_settings.external_locker, NULL,
N_("Use external locker program."),
N_("prog") },
{ NULL, }
};
......@@ -69,8 +80,13 @@ DCL_CFG_CAPA (locking);
/* ************************************************************************* */
static struct mu_cfg_param mu_address_param[] = {
{ "email-addr", mu_cfg_string, &address_settings.address },
{ "email-domain", mu_cfg_string, &address_settings.domain },
{ "email-addr", mu_cfg_string, &address_settings.address, NULL,
N_("Set the current user email address (default is "
"loginname@defaultdomain)."),
N_("email") },
{ "email-domain", mu_cfg_string, &address_settings.domain, NULL,
N_("Set e-mail domain for unqualified user names (default is this host)"),
N_("domain") },
{ NULL }
};
......@@ -82,7 +98,9 @@ DCL_CFG_CAPA (address);
/* ************************************************************************* */
static struct mu_cfg_param mu_mailer_param[] = {
{ "url", mu_cfg_string, &mailer_settings.mailer },
{ "url", mu_cfg_string, &mailer_settings.mailer, NULL,
N_("Use this URL as the default mailer"),
N_("url") },
{ NULL }
};
......@@ -107,7 +125,10 @@ cb_facility (mu_debug_t debug, void *data, char *arg)
}
static struct mu_cfg_param mu_logging_param[] = {
{ "facility", mu_cfg_callback, NULL, cb_facility },
{ "facility", mu_cfg_callback, NULL, cb_facility,
N_("Set syslog facility. Arg is one of the following: user, daemon, "
"auth, authpriv, mail, cron, local0 through local7 (case-insensitive), "
"or a facility number.") },
{ NULL }
};
......@@ -135,12 +156,20 @@ _cb_daemon_mode (mu_debug_t debug, void *data, char *arg)
}
static struct mu_cfg_param mu_daemon_param[] = {
{ "max-children", mu_cfg_ulong, &daemon_settings.maxchildren },
{ "mode", mu_cfg_callback, NULL, _cb_daemon_mode },
{ "transcript", mu_cfg_bool, &daemon_settings.transcript },
{ "pidfile", mu_cfg_string, &daemon_settings.pidfile },
{ "port", mu_cfg_ushort, &daemon_settings.port },
{ "timeout", mu_cfg_ulong, &daemon_settings.timeout },
{ "max-children", mu_cfg_ulong, &daemon_settings.maxchildren, NULL,
N_("Maximum number of children processes to run simultaneously.") },
{ "mode", mu_cfg_callback, NULL, _cb_daemon_mode,
N_("Set daemon mode (either inetd (or interactive) or daemon)."),
N_("mode") },
{ "transcript", mu_cfg_bool, &daemon_settings.transcript, NULL,
N_("Log the session transcript.") },
{ "pidfile", mu_cfg_string, &daemon_settings.pidfile, NULL,
N_("Store PID of the master process in this file."),
N_("file") },
{ "port", mu_cfg_ushort, &daemon_settings.port, NULL,
N_("Listen on the specified port number.") },
{ "timeout", mu_cfg_ulong, &daemon_settings.timeout, NULL,
N_("Set idle timeout.") },
{ NULL }
};
......@@ -203,8 +232,12 @@ cb_debug_level (mu_debug_t debug, void *data, char *arg)
}
static struct mu_cfg_param mu_debug_param[] = {
{ "level", mu_cfg_callback, NULL, &cb_debug_level },
{ "line-info", mu_cfg_bool, &debug_settings.line_info },
{ "level", mu_cfg_callback, NULL, &cb_debug_level,
N_("Set Mailutils debugging level. Argument is a colon-separated list "
"of debugging specifications in the form:\n"
" <object: string>[[:]=<level: number>].") },
{ "line-info", mu_cfg_bool, &debug_settings.line_info, NULL,
N_("Prefix debug messages with Mailutils source locations.") },
{ NULL }
};
......
......@@ -25,7 +25,9 @@
static struct mu_gsasl_module_data gsasl_settings;
static struct mu_cfg_param mu_gsasl_param[] = {
{ "cram-passwd", mu_cfg_string, &gsasl_settings.cram_md5_pwd },
{ "cram-passwd", mu_cfg_string, &gsasl_settings.cram_md5_pwd, NULL,
N_("Name of GSASL password file."),
N_("file") },
{ NULL }
};
......
......@@ -37,16 +37,38 @@ cb_field_map (mu_debug_t debug, void *data, char *arg)
}
static struct mu_cfg_param mu_ldap_param[] = {
{ "enable", mu_cfg_bool, &ldap_settings.enable },
{ "url", mu_cfg_string, &ldap_settings.url },
{ "base", mu_cfg_string, &ldap_settings.base },
{ "binddn", mu_cfg_string, &ldap_settings.binddn },
{ "passwd", mu_cfg_string, &ldap_settings.passwd },
{ "tls", mu_cfg_bool, &ldap_settings.tls },
{ "debug", mu_cfg_int, &ldap_settings.debug },
{ "field-map", mu_cfg_callback, NULL, cb_field_map },
{ "getpwnam", mu_cfg_string, &ldap_settings.getpwnam_filter },
{ "getpwuid", mu_cfg_string, &ldap_settings.getpwuid_filter },
{ "enable", mu_cfg_bool, &ldap_settings.enable, NULL,
N_("Enable LDAP lookups.") },
{ "url", mu_cfg_string, &ldap_settings.url, NULL,
N_("Set URL of the LDAP server."),
N_("url") },
{ "base", mu_cfg_string, &ldap_settings.base, NULL,
N_("Base DN for LDAP lookups."),
N_("dn") },
{ "binddn", mu_cfg_string, &ldap_settings.binddn, NULL,
N_("DN for accessing LDAP database."),
N_("dn") },
{ "passwd", mu_cfg_string, &ldap_settings.passwd, NULL,
N_("Password for use with binddn.") },
{ "tls", mu_cfg_bool, &ldap_settings.tls, NULL,
N_("Use TLS encryption.") },
{ "debug", mu_cfg_int, &ldap_settings.debug, NULL,
N_("Set LDAP debugging level.") },
{ "field-map", mu_cfg_callback, NULL, cb_field_map,
N_("Set a field-map for parsing LDAP replies. The map is a "
"column-separated list of definitions. Each definition has the "
"following form:\n"
" <name: string>=<attr: string>\n"
"where <name> is one of the following: name, passwd, uid, gid, "
"gecos, dir, shell, mailbox, quota, and <attr> is the name of "
"the correspondind LDAP attribute."),
N_("map") },
{ "getpwnam", mu_cfg_string, &ldap_settings.getpwnam_filter, NULL,
N_("LDAP filter to use for getpwnam requests."),
N_("filter") },
{ "getpwuid", mu_cfg_string, &ldap_settings.getpwuid_filter, NULL,
N_("LDAP filter to use for getpwuid requests."),
N_("filter") },
{ NULL }
};
......
......@@ -24,7 +24,9 @@
static char *pam_settings;
static struct mu_cfg_param mu_pam_param[] = {
{ "service", mu_cfg_string, &pam_settings },
{ "service", mu_cfg_string, &pam_settings, NULL,
N_("Set PAM service name."),
N_("name") },
{ NULL }
};
......
......@@ -25,10 +25,17 @@
static struct mu_radius_module_data radius_settings;
static struct mu_cfg_param mu_radius_param[] = {
{ "auth-request", mu_cfg_string, &radius_settings.auth_request },
{ "getpwnam-request", mu_cfg_string, &radius_settings.getpwnam_request },
{ "getpwuid-request", mu_cfg_string, &radius_settings.getpwuid_request },
{ "directory", mu_cfg_string, &radius_settings.config_dir },
{ "auth", mu_cfg_string, &radius_settings.auth_request, NULL,
N_("Radius request for authorization."),
N_("request") },
{ "getpwnam", mu_cfg_string, &radius_settings.getpwnam_request, NULL,
N_("Radius request for getpwnam."),
N_("request") },
{ "getpwuid", mu_cfg_string, &radius_settings.getpwuid_request, NULL,
N_("Radius request for getpwuid."),
N_("request") },
{ "directory", mu_cfg_string, &radius_settings.config_dir, NULL,
N_("Set radius configuration directory.") },
{ NULL }
};
......
......@@ -92,10 +92,18 @@ cb_library_path (mu_debug_t debug, void *data, char *arg)
}
static struct mu_cfg_param mu_sieve_param[] = {
{ "clear-library-path", mu_cfg_callback, NULL, cb_clear_library_path },
{ "clear-include-path", mu_cfg_callback, NULL, cb_clear_include_path },
{ "library-path", mu_cfg_callback, NULL, cb_library_path },
{ "include-path", mu_cfg_callback, NULL, cb_include_path },
{ "clear-library-path", mu_cfg_callback, NULL, cb_clear_library_path,
N_("Clear library search path.") },
{ "clear-include-path", mu_cfg_callback, NULL, cb_clear_include_path,
N_("Clear include search path.") },
{ "library-path", mu_cfg_callback, NULL, cb_library_path,
N_("Add directories to the library search path. Argument is a "
"comma-separated list of directories."),
N_("list") },
{ "include-path", mu_cfg_callback, NULL, cb_include_path,
N_("Add directories to the include search path. Argument is a "
"comma-separated list of directories."),
N_("list") },
{ NULL }
};
......
......@@ -50,17 +50,39 @@ cb_field_map (mu_debug_t debug, void *data, char *arg)
}
static struct mu_cfg_param mu_sql_param[] = {
{ "interface", mu_cfg_string, &sql_settings.interface },
{ "getwpnam", mu_cfg_string, &sql_settings.getpwnam_query },
{ "getpwuid", mu_cfg_string, &sql_settings.getpwuid_query },
{ "getpass", mu_cfg_string, &sql_settings.getpass_query },
{ "host", mu_cfg_string, &sql_settings.host },
{ "user", mu_cfg_string, &sql_settings.user },
{ "passwd", mu_cfg_string, &sql_settings.passwd },
{ "db", mu_cfg_string, &sql_settings.db },
{ "port", mu_cfg_int, &sql_settings.port },
{ "password-type", mu_cfg_callback, NULL, cb_password_type },
{ "field-map", mu_cfg_callback, NULL, cb_field_map },
{ "interface", mu_cfg_string, &sql_settings.interface, NULL,
N_("Set SQL interface to use (one of: mysql, odbc, or postgres).") },
{ "getwpnam", mu_cfg_string, &sql_settings.getpwnam_query, NULL,
N_("SQL query to use for getpwnam requests."),
N_("query") },
{ "getpwuid", mu_cfg_string, &sql_settings.getpwuid_query, NULL,
N_("SQL query to use for getpwuid requests."),
N_("query") },
{ "getpass", mu_cfg_string, &sql_settings.getpass_query, NULL,
N_("SQL query returning the user's password."),
N_("query") },
{ "host", mu_cfg_string, &sql_settings.host, NULL,
N_("SQL server host name.") },
{ "user", mu_cfg_string, &sql_settings.user, NULL,
N_("SQL user name.") },
{ "passwd", mu_cfg_string, &sql_settings.passwd, NULL,
N_("Password for the SQL user.") },
{ "port", mu_cfg_int, &sql_settings.port, NULL,
N_("SQL server port.") },
{ "db", mu_cfg_string, &sql_settings.db, NULL,
N_("Database name.") },
{ "password-type", mu_cfg_callback, NULL, cb_password_type,
N_("Type of password returned by getpass query (one of: plain, hash, "
"scrambled).") },
{ "field-map", mu_cfg_callback, NULL, cb_field_map,
N_("Set a field-map for parsing SQL replies. The map is a "
"column-separated list of definitions. Each definition has the "
"following form:\n"
" <name: string>=<column: string>\n"
"where <name> is one of the following: name, passwd, uid, gid, "
"gecos, dir, shell, mailbox, quota, and <column> is the name of "
"the corresponding SQL column."),
N_("map") },
{ NULL }
};
......
......@@ -25,10 +25,17 @@
static struct mu_tls_module_config tls_settings;
static struct mu_cfg_param mu_tls_param[] = {
{ "tls", mu_cfg_bool, &tls_settings.client_enable },
{ "ssl-cert", mu_cfg_string, &tls_settings.ssl_cert },
{ "ssl-key", mu_cfg_string, &tls_settings.ssl_key },
{ "ssl-cafile", mu_cfg_string, &tls_settings.ssl_cafile },
{ "tls", mu_cfg_bool, &tls_settings.client_enable, NULL,
N_("Enable client TLS encryption.") },
{ "ssl-cert", mu_cfg_string, &tls_settings.ssl_cert, NULL,
N_("Specify SSL certificate file."),
N_("file") },
{ "ssl-key", mu_cfg_string, &tls_settings.ssl_key, NULL,
N_("Specify SSL certificate key file."),
N_("file") },
{ "ssl-cafile", mu_cfg_string, &tls_settings.ssl_cafile, NULL,
N_("Specify trusted CAs file."),
N_("file") },
{ NULL }
};
......
......@@ -24,7 +24,10 @@
static struct mu_gocs_virtual virtdomain_settings;
static struct mu_cfg_param mu_virtdomain_param[] = {
{ "passwd-dir", mu_cfg_string, &virtdomain_settings },
{ "passwd-dir", mu_cfg_string, &virtdomain_settings, NULL,
N_("Name of the directory where virtual domain password files are "
"located."),
N_("dir") },
{ NULL }
};
......
......@@ -66,7 +66,7 @@ N_("Debug flags are:\n\
t - sieve trace (MU_SIEVE_DEBUG_TRACE)\n\
i - sieve instructions trace (MU_SIEVE_DEBUG_INSTR)\n\
l - sieve action logs\n\
0-9 - Set mail.local debugging level\n");
0-9 - Set maidag debugging level\n");
static char args_doc[] = N_("[recipient...]");
......@@ -237,26 +237,58 @@ cb_debug (mu_debug_t debug, void *data, char *arg)
}
struct mu_cfg_param maidag_cfg_param[] = {
{ "exit-multiple-delivery-success", mu_cfg_bool, &multiple_delivery },
{ "exit-quota-tempfail", mu_cfg_bool, &ex_quota_tempfail },
{ "exit-multiple-delivery-success", mu_cfg_bool, &multiple_delivery, NULL,
N_("In case of multiple delivery, exit with code 0 if at least one "
"delivery succeeded.") },
{ "exit-quota-tempfail", mu_cfg_bool, &ex_quota_tempfail, NULL,
N_("Indicate temporary failure if the recipient is over his mail quota.")
},
#ifdef USE_DBM
{ "quota-db", mu_cfg_string, &quotadbname },
{ "quota-db", mu_cfg_string, &quotadbname, NULL,
N_("Name of DBM quota database file."),
N_("file") },
#endif
#ifdef USE_SQL
{ "quota-query", mu_cfg_string, &quota_query },
{ "quota-query", mu_cfg_string, &quota_query, NULL,
N_("SQL query to retrieve mailbox quota. This is deprecated, use "
"sql { ... } instead."),
N_("query") },
#endif
{ "sieve-filter", mu_cfg_string, &sieve_pattern },
{ "message-id-header", mu_cfg_string, &message_id_header },
{ "sieve-filter", mu_cfg_string, &sieve_pattern, NULL,
N_("File name or name pattern for Sieve filter file."),
N_("file-or-pattern") },
{ "message-id-header", mu_cfg_string, &message_id_header, NULL,
N_("When logging Sieve actions, identify messages by the value of "
"this header."),
N_("name") },
#ifdef WITH_GUILE
{ "guile-filter", mu_cfg_string, &progfile_pattern },
{ "guile-filter", mu_cfg_string, &progfile_pattern, NULL,
N_("File name or name pattern for Guile filter file."),
N_("file-or-pattern") },
#endif
{ "debug", mu_cfg_callback, NULL, cb_debug },
{ "stderr", mu_cfg_bool, &log_to_stderr },
{ "debug", mu_cfg_callback, NULL, cb_debug,
N_("Set maidag debug level. Debug level consists of one or more "
"of the following letters:\n"
" g - guimb stack traces\n"
" t - sieve trace (MU_SIEVE_DEBUG_TRACE)\n"
" i - sieve instructions trace (MU_SIEVE_DEBUG_INSTR)\n"
" l - sieve action logs\n") },
{ "stderr", mu_cfg_bool, &log_to_stderr, NULL,
N_("Log to stderr instead of syslog.") },
/* LMTP support */
{ "lmtp", mu_cfg_bool, &lmtp_mode },
{ "group", mu_cfg_string, &lmtp_group },
{ "listen", mu_cfg_string, &lmtp_url_string },
{ "reuse-address", mu_cfg_bool, &reuse_lmtp_address },
{ "lmtp", mu_cfg_bool, &lmtp_mode, NULL,
N_("Run in LMTP mode.") },
{ "group", mu_cfg_string, &lmtp_group, NULL,
N_("In LMTP mode, change to this group after startup.") },
{ "listen", mu_cfg_string, &lmtp_url_string, NULL,
N_("In LMTP mode, listen on the given URL. Valid URLs are:\n"
" tcp://<address: string>:<port: number> (note that port is "
"mandatory)\n"
" file://<socket-file-name>\n"
"or socket://<socket-file-name>"),
N_("url") },
{ "reuse-address", mu_cfg_bool, &reuse_lmtp_address, NULL,
N_("Reuse existing address (LMTP mode). Default is \"yes\".") },
{ NULL }
};
......
......@@ -255,21 +255,42 @@ cb_debug (mu_debug_t debug, void *data, char *arg)
}
struct mu_cfg_param mail_local_cfg_param[] = {
{ "ex-multiple-delivery-success", mu_cfg_bool, &multiple_delivery },
{ "ex-quota-tempfail", mu_cfg_bool, &ex_quota_tempfail },
{ "from", mu_cfg_string, &from },
{ "ex-multiple-delivery-success", mu_cfg_bool, &multiple_delivery, NULL,
N_("In case of multiple delivery, exit with code 0 if at least one "
"delivery succeeded.") },
{ "ex-quota-tempfail", mu_cfg_bool, &ex_quota_tempfail, NULL,
N_("Indicate temporary failure if the recipient is over his mail quota.")
},
#ifdef USE_DBM
{ "quota-db", mu_cfg_string, &quotadbname },
{ "quota-db", mu_cfg_string, &quotadbname, NULL,
N_("Name of DBM quota database file."),
N_("file") },
#endif
#ifdef USE_SQL
{ "quota-query", mu_cfg_string, &quota_query },
{ "quota-query", mu_cfg_string, &quota_query, NULL,
N_("SQL query to retrieve mailbox quota. This is deprecated, use "
"sql { ... } instead."),
N_("query") },
#endif
{ "sieve", mu_cfg_string, &sieve_pattern },
{ "message-id-header", mu_cfg_string, &message_id_header },
{ "sieve-filter", mu_cfg_string, &sieve_pattern, NULL,
N_("File name or name pattern for Sieve filter file."),
N_("file-or-pattern") },
{ "message-id-header", mu_cfg_string, &message_id_header, NULL,
N_("When logging Sieve actions, identify messages by the value of "
"this header."),
N_("name") },
#ifdef WITH_GUILE
{ "source", mu_cfg_string, &progfile_pattern },
{ "guile-filter", mu_cfg_string, &progfile_pattern, NULL,
N_("File name or name pattern for Guile filter file."),
N_("file-or-pattern") },
#endif
{ "debug", mu_cfg_callback, NULL, cb_debug },
{ "debug", mu_cfg_callback, NULL, cb_debug,
N_("Set mail.local debug level. Debug level consists of one or more "
"of the following letters:\n"
" g - guimb stack traces\n"
" t - sieve trace (MU_SIEVE_DEBUG_TRACE)\n"
" i - sieve instructions trace (MU_SIEVE_DEBUG_INSTR)\n"
" l - sieve action logs\n") },
{ NULL }
};
......
......@@ -136,10 +136,16 @@ static struct argp argp = {
struct mu_cfg_param mail_remote_cfg_param[] = {
{ "from", mu_cfg_string, &optfrom },
{ "read-recipients", mu_cfg_string, &read_recipients },
{ "debug", mu_cfg_int, &optdebug },
{ NULL}
{ "from", mu_cfg_string, &optfrom, NULL,
N_("Set sender email address."),
N_("email") },
{ "read-recipients", mu_cfg_string, &read_recipients, NULL,
N_("Read recipient addresses from the message.") },
{ "debug", mu_cfg_int, &optdebug, NULL,
N_("Set debug verbosity level. Level 1 prints envelope commands in "
"the SMTP protocol transaction. Levels 2 and above print the data "
"part of the transaction as well.") },
{ NULL }
};
......
......@@ -23,6 +23,7 @@
#include <mailutils/cfg.h>
#include <mailutils/argcv.h>
#include <mailutils/nls.h>
#include <ctype.h>
struct tree_print
{
......@@ -149,7 +150,7 @@ mu_cfg_data_type_string (enum mu_cfg_param_data_type type)
switch (type)
{
case mu_cfg_string:
return "string";
return N_("string");
case mu_cfg_short:
case mu_cfg_ushort:
case mu_cfg_int:
......@@ -158,30 +159,84 @@ mu_cfg_data_type_string (enum mu_cfg_param_data_type type)
case mu_cfg_ulong:
case mu_cfg_size:
case mu_cfg_off:
return "number";
return N_("number");
case mu_cfg_time:
return "time";
return N_("time");
case mu_cfg_bool:
return "boolean";
return N_("boolean");
case mu_cfg_ipv4:
return "ipv4";
return N_("ipv4");
case mu_cfg_cidr:
return "cidr";
return N_("cidr");
case mu_cfg_host:
return "host";
return N_("host");
case mu_cfg_callback:
return "string"; /* FIXME: opaque data */
return N_("string");
}
return N_("unknown");
}
void
mu_cfg_format_docstring (mu_stream_t stream, const char *docstring, int level)
{
size_t len = strlen (docstring);
int width = 78 - level * 2;
if (width < 0)
{
width = 78;
level = 0;
}
while (len)
{
size_t seglen;
const char *p;
for (seglen = 0, p = docstring; p < docstring + width && *p; p++)
{
if (*p == '\n')
{
seglen = p - docstring;
break;
}
if (isspace (*p))
seglen = p - docstring;
}
if (seglen == 0 || *p == 0)
seglen = p - docstring;
format_level (stream, level);
mu_stream_sequential_write (stream, "# ", 2);
mu_stream_sequential_write (stream, docstring, seglen);
mu_stream_sequential_write (stream, "\n", 1);
len -= seglen;
docstring += seglen;
if (*docstring == '\n')
{
docstring++;
len--;
}
else
while (*docstring && isspace (*docstring))
{
docstring++;
len--;
}
}
return "unknown";
}
static void
format_param (mu_stream_t stream, struct mu_cfg_param *param, int level)
{
if (param->docstring)
mu_cfg_format_docstring (stream, gettext (param->docstring), level);
format_level (stream, level);
mu_stream_sequential_printf (stream, "%s <%s>;\n",
mu_stream_sequential_printf (stream, "%s <%s: %s>;\n",
param->ident,
mu_cfg_data_type_string (param->type));
gettext (param->argname ?
param->argname : N_("arg")),
gettext (mu_cfg_data_type_string (param->type)));
}
static void format_container (mu_stream_t stream, struct mu_cfg_cont *cont,
......@@ -200,6 +255,8 @@ static void
format_section (mu_stream_t stream, struct mu_cfg_section *sect, int level)
{
struct tree_print c;
if (sect->docstring)
mu_cfg_format_docstring (stream, gettext (sect->docstring), level);
format_level (stream, level);
if (sect->ident)
{
......
......@@ -359,7 +359,7 @@ mu_config_create_container (struct mu_cfg_cont **pcont,
struct mu_cfg_cont *cont;
int rc;
cont = malloc (sizeof (*cont));
cont = calloc (1, sizeof (*cont));
if (!cont)
return ENOMEM;
rc = mu_refcount_create (&cont->refcount);
......@@ -437,6 +437,7 @@ dup_container (struct mu_cfg_cont **pcont)
newcont->v.section.ident = oldcont->v.section.ident;
newcont->v.section.parser = oldcont->v.section.parser;
newcont->v.section.data = oldcont->v.section.data;
newcont->v.section.docstring = oldcont->v.section.docstring;
newcont->v.section.subsec = NULL;
newcont->v.section.param = NULL;
mu_list_do (oldcont->v.section.subsec, _dup_section_action, &dd);
......@@ -737,7 +738,12 @@ mu_build_container (const char *progname,
struct mu_cfg_cont *cont = root_container;
struct include_data idata;
struct mu_cfg_param mu_include_param[] = {
{ "include", mu_cfg_callback, &idata, _cb_include },
{ "include", mu_cfg_callback, &idata, _cb_include,
N_("Include contents of the given file. If a directory is given, "
"include contents of the file <file>/<program>, where <program> is "
"the name of the program. This latter form is allowed only in "
"the site-wide configuration file."),
N_("file-or-directory") },
{ NULL }
};
......
......@@ -158,10 +158,23 @@ cb_debug (mu_debug_t debug, void *data, char *arg)
return 0;
}
static int
cb_metamail (mu_debug_t debug, void *data, char *arg)
{
metamail = strdup ("metamail");
return 0;
}
struct mu_cfg_param mimeview_cfg_param[] = {
{"debug", mu_cfg_callback, NULL, cb_debug },
{"mimetypes", mu_cfg_string, &mimetypes_config },
{"metamail", mu_cfg_string, &metamail },
{ "debug", mu_cfg_callback, NULL, cb_debug,
N_("Set debug verbosity level."),
N_("flags") },
{ "mimetypes", mu_cfg_string, &mimetypes_config, NULL,
N_("Use this mime.types file."),
N_("file") },
{ "metamail", mu_cfg_string, NULL, cb_metamail,
N_("Use this program to display files."),
N_("prog") },
{ NULL }
};
......
......@@ -90,9 +90,12 @@ static struct argp argp = {
struct mu_cfg_param movemail_cfg_param[] = {
{ "preserve", mu_cfg_bool, &preserve_mail },
{ "reverse", mu_cfg_bool, &reverse_order },
{ "emacs", mu_cfg_bool, &emacs_mode },
{ "preserve", mu_cfg_bool, &preserve_mail, NULL,
N_("Do not remove messages from the source mailbox.") },
{ "reverse", mu_cfg_bool, &reverse_order, NULL,
N_("Reverse message sorting order.") },
{ "emacs", mu_cfg_bool, &emacs_mode, NULL,
N_("Output information used by Emacs rmail interface.") },
{ NULL }
};
......
......@@ -32,11 +32,12 @@ lib/argp-parse.c
lib/getopt.c
lib/mailcap.c
lib/xmalloc.c
libargp/mu_argp.c
libargp/auth.c
libargp/cmdline.c
libargp/common.c
libargp/gsasl.c
libargp/mu_argp.c
libargp/muinit.c
libargp/pam.c
libargp/radius.c
libargp/sql.c
......@@ -46,8 +47,10 @@ 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
......@@ -67,6 +70,7 @@ libsieve/sieve.l
libsieve/sieve.y
libsieve/tests.c
libsieve/util.c
maidag/maidag.c
mail.local/mailquota.c
mail.local/main.c
mail.local/script.c
......@@ -97,6 +101,8 @@ mail/summary.c
mail/unalias.c
mail/util.c
mail/z.c
mailbox/cfg_format.c
mailbox/cfg_lexer.c
mailbox/errors
mailbox/file_stream.c
mailbox/filter_iconv.c
......
......@@ -54,7 +54,7 @@ time_t login_delay = 0;
char *login_stat_file = LOGIN_STAT_FILE;
#endif
time_t expire = EXPIRE_NEVER; /* Expire messages after this number of days */
unsigned expire = EXPIRE_NEVER; /* Expire messages after this number of days */
int expire_on_exit = 0; /* Delete expired messages on exit */
static int pop3d_mainloop (int fd, FILE *, FILE *);
......@@ -91,7 +91,7 @@ static struct argp_option options[] = {
#define GRP 10
#ifdef ENABLE_LOGIN_DELAY
{"login-delay", OPT_LOGIN_DELAY, N_("SECONDS"), OPTION_HIDDEN,
N_("Allowed delay between the two successive logins"), GRP+1},
N_("Allowed delay between two successive logins"), GRP+1},
{"stat-file", OPT_STAT_FILE, N_("FILENAME"), OPTION_HIDDEN,
N_("Name of login statistics file"), GRP+1},
#endif
......@@ -134,19 +134,30 @@ cb_bulletin_db (mu_debug_t debug, void *data, char *arg)
}
static struct mu_cfg_param pop3d_cfg_param[] = {
{ "undelete", mu_cfg_int, &undelete_on_startup },
{ "expire", mu_cfg_time, &expire },
{ "delete-expired", mu_cfg_int, &expire_on_exit },
{ "undelete", mu_cfg_int, &undelete_on_startup, NULL,
N_("On startup, clear deletion marks from all the messages.") },
{ "expire", mu_cfg_uint, &expire, NULL,
N_("Automatically expire read messages after the given number of days."),
N_("days") },
{ "delete-expired", mu_cfg_int, &expire_on_exit, NULL,
N_("Delete expired messages upon closing the mailbox.") },
#ifdef WITH_TLS
{ "tls-required", mu_cfg_callback, NULL, cb_tls_required },
{ "tls-required", mu_cfg_callback, NULL, cb_tls_required,
N_("Always require STLS before entering authentication phase.") },
#endif
#ifdef ENABLE_LOGIN_DELAY
{ "login-delay", mu_cfg_time, &login_delay },
{ "stat-file", mu_cfg_string, &login_stat_file },
{ "login-delay", mu_cfg_time, &login_delay, NULL,
N_("Set the minimal allowed delay between two successive logins.") },
{ "stat-file", mu_cfg_string, &login_stat_file, NULL,
N_("Set the name of login statistics file (for login-delay).") },
#endif
{ "bulletin-source", mu_cfg_callback, NULL, cb_bulletin_source },
{ "bulletin-source", mu_cfg_callback, NULL, cb_bulletin_source,
N_("Get bulletins from the specified mailbox."),
N_("url") },
#ifdef USE_DBM
{ "bulletin-db", mu_cfg_callback, NULL, cb_bulletin_db },
{ "bulletin-db", mu_cfg_callback, NULL, cb_bulletin_db,
N_("Set the bulletin database file name."),
N_("file") },
#endif
{ NULL }
};
......
......@@ -94,10 +94,10 @@ extern void login_delay_capa (void);
#endif
/* Minimum advertise retention time for messages. */
extern time_t expire;
extern unsigned expire;
extern int expire_on_exit;
#define EXPIRE_NEVER ((time_t)-1)
#define EXPIRE_NEVER ((unsigned)-1)
/* Size of the MD5 digest for APOP */
#define APOP_DIGEST 70
......
......@@ -47,7 +47,7 @@ static struct argp_option options[] =
{ "no-header", 'n', 0, 0, N_("Exclude all headers"), 1 },
{ "form-feeds", 'p', 0, 0, N_("Output formfeeds between messages"), 1 },
{ "show-all-match", 'a', NULL, 0,
N_("Print all messages matching pattern, not just the first"), 1 },
N_("Print all messages matching pattern, not only the first"), 1 },
{0, 0, 0, 0}
};
......@@ -129,13 +129,22 @@ readmsg_parse_opt (int key, char *arg, struct argp_state *astate)
struct mu_cfg_param readmsg_cfg_param[] = {
{ "debug", mu_cfg_int, &dbug },
{ "header", mu_cfg_bool, &all_header },
{ "weedlist", mu_cfg_string, &weedlist },
{ "folder", mu_cfg_string, &mailbox_name },
{ "no-header", mu_cfg_bool, &no_header },
{ "form-feeds", mu_cfg_bool, &form_feed },
{ "show-all-match", mu_cfg_bool, &show_all },
{ "debug", mu_cfg_int, &dbug, NULL,
N_("Set debug verbosity level.") },
{ "header", mu_cfg_bool, &all_header, NULL,
N_("Display entire headers.") },
{ "weedlist", mu_cfg_string, &weedlist, NULL,
N_("Display only headers from this list. Argument is a list of header "
"names separated by whitespace or commas."),
N_("list") },
{ "folder", mu_cfg_string, &mailbox_name, NULL,
N_("Read messages from this folder.") },
{ "no-header", mu_cfg_bool, &no_header, NULL,
N_("Exclude all headers.") },
{ "form-feeds", mu_cfg_bool, &form_feed, NULL,
N_("Output formfeed character between messages.") },
{ "show-all-match", mu_cfg_bool, &show_all, NULL,
N_("Print all messages matching pattern, not only the first.") },
{ NULL }
};
......
......@@ -82,7 +82,7 @@ static struct argp_option options[] =
N_("Mailbox to sieve (defaults to user's mail spool)"), 0},
{"ticket", 't', N_("TICKET"), 0,
N_("Ticket file for mailbox authentication"), 0},
N_("Ticket file for user authentication"), 0},
{"debug", 'd', N_("FLAGS"), OPTION_ARG_OPTIONAL,
N_("Debug flags (defaults to \"" D_DEFAULT "\")"), 0},
......@@ -233,8 +233,10 @@ parser (int key, char *arg, struct argp_state *state)
break;
case ARGP_KEY_NO_ARGS:
argp_error (state, _("SCRIPT must be specified"));
if (!mu_help_config_mode)
argp_error (state, _("SCRIPT must be specified"));
return ARGP_ERR_UNKNOWN;
case ARGP_KEY_INIT:
mu_argp_node_list_init (&lst);
break;
......@@ -285,13 +287,28 @@ cb_ticket (mu_debug_t debug, void *data, char *arg)
}
static struct mu_cfg_param sieve_cfg_param[] = {
{ "keep-going", mu_cfg_int, &keep_going },
{ "mbox-url", mu_cfg_string, &mbox_url },
{ "ticket", mu_cfg_callback, NULL, cb_ticket },
{ "debug", mu_cfg_callback, NULL, cb_debug },
{ "verbose", mu_cfg_bool, &verbose },
{ "line-info", mu_cfg_bool, &sieve_print_locus },
{ "email", mu_cfg_callback, NULL, cb_email },
{ "keep-going", mu_cfg_int, &keep_going, NULL,
N_("Do not abort if execution fails on a message.") },
{ "mbox-url", mu_cfg_string, &mbox_url, NULL,
N_("Mailbox to sieve (defaults to user's mail spool)."),
N_("url") },
{ "ticket", mu_cfg_callback, NULL, cb_ticket,
N_("Ticket file for user authentication."),
N_("ticket") },
{ "debug", mu_cfg_callback, NULL, cb_debug,
N_("Debug flags. Argument consists of one or more of the following "
"flags:\n"
" g - main parser traces\n"
" T - mailutils traces (MU_DEBUG_TRACE0-MU_DEBUG_TRACE1)\n"
" P - network protocols (MU_DEBUG_PROT)\n"
" t - sieve trace (MU_SIEVE_DEBUG_TRACE)\n"
" i - sieve instructions trace (MU_SIEVE_DEBUG_INSTR).") },
{ "verbose", mu_cfg_bool, &verbose, NULL,
N_("Log all executed actions.") },
{ "line-info", mu_cfg_bool, &sieve_print_locus, NULL,
N_("Print source locations along with action logs (default).") },
{ "email", mu_cfg_callback, NULL, cb_email,
N_("Set user email address.") },
{ NULL }
};
......