summaryrefslogtreecommitdiffabout
authorSergey Poznyakoff <gray@gnu.org>2016-10-11 14:20:38 (GMT)
committer Sergey Poznyakoff <gray@gnu.org>2016-10-11 14:36:10 (GMT)
commitbc73fc65600b6021dfe7a9fa1fba7e9b823993e2 (patch) (side-by-side diff)
tree934b239ddd68b1bc91a42b66ddccfe3bcf01accf
parent6e8147334cf9ffe36367760c06002a1e5b7ae0d5 (diff)
downloadmailutils-bc73fc65600b6021dfe7a9fa1fba7e9b823993e2.tar.gz
mailutils-bc73fc65600b6021dfe7a9fa1fba7e9b823993e2.tar.bz2
Introduce new CLI/configuration code for mailutils applications.
The new API is to replace libmu_cfg and libmu_argp. A smooth transition is scheduled, during which the two APIs will coexist, * configure.ac: Build libmailutils/cli/Makefile * include/mailutils/cli.h: New file. * include/mailutils/Makefile.am: Add cli.h * libmailutils/cli/Makefile.am: New file. * libmailutils/cli/capa.c: New file. * libmailutils/cli/cli.c: New file. * libmailutils/cli/stdcapa.c: New file. * libmailutils/Makefile.am (SUBDIRS): Add cli. * include/mailutils/cfg.h (mu_cfg_parse_hints): New members: append_tree and data. (MU_PARSE_CONFIG_LINT): New flag. * include/mailutils/diag.h (mu_program_name) (mu_full_program_name): Remove const qualifier. * include/mailutils/locker.h (mu_locker_set_default_external_program): Argument is const. * libmailutils/base/locker.c: Likewise. * include/mailutils/opt.h (mu_progname, mu_absprogname): Replace with mu_program_name and mu_full_program_name. (mu_set_progname): Rename to mu_set_program_name. (mu_parseopt) <po_data>: Change type to void *. (po_help_hook, po_version_hook): Change signatures. (mu_parseopt_error): New function. * libmailutils/opt/progname.c (mu_progname, mu_absprogname): Replace with mu_program_name and mu_full_program_name. (mu_set_progname): Rename to mu_set_program_name. * libmailutils/opt/help.c: Minor changes * libmailutils/opt/opt.c (parse_error): Rename to mu_parse_error (extern). (next_opt): Fix permutations. * libmailutils/tests/parseopt.c: Reflect changes. * libmailutils/tests/parseopt17.at: Improve test case * libmailutils/tests/parseopt_help05.at: Reflect changes. * libmailutils/tests/parseopt_help07.at: Reflect changes. * include/mailutils/stdstream.h (mu_program_name): Remove qualifier. * libmailutils/cfg/driver.c (mu_cfg_tree_reduce): Remove useless condition * libmailutils/cfg/lexer.l (mu_cfg_parse_file): Additional info messages. * libmailutils/cfg/parser.y (mu_cfg_parse_config): Join in the append_tree. * libmailutils/diag/diag.c (mu_program_name, mu_full_program_name) (mu_set_program_name): Remove. Declared elsewhere. * libmu_sieve/conf.c: Add new configuration code. Mark old text for removal. * libmailutils/tests/tcli.c: New program. * libmailutils/tests/Makefile.am: Add tcli.c
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--configure.ac1
-rw-r--r--include/mailutils/Makefile.am1
-rw-r--r--include/mailutils/cfg.h5
-rw-r--r--include/mailutils/cli.h55
-rw-r--r--include/mailutils/diag.h4
-rw-r--r--include/mailutils/locker.h2
-rw-r--r--include/mailutils/opt.h16
-rw-r--r--include/mailutils/stdstream.h2
-rw-r--r--libmailutils/Makefile.am3
-rw-r--r--libmailutils/base/locker.c2
-rw-r--r--libmailutils/cfg/driver.c12
-rw-r--r--libmailutils/cfg/lexer.l6
-rw-r--r--libmailutils/cfg/parser.y5
-rw-r--r--libmailutils/cli/Makefile.am26
-rw-r--r--libmailutils/cli/capa.c96
-rw-r--r--libmailutils/cli/cli.c420
-rw-r--r--libmailutils/cli/stdcapa.c466
-rw-r--r--libmailutils/diag/diag.c26
-rw-r--r--libmailutils/opt/help.c8
-rw-r--r--libmailutils/opt/opt.c24
-rw-r--r--libmailutils/opt/progname.c14
-rw-r--r--libmailutils/tests/.gitignore1
-rw-r--r--libmailutils/tests/Makefile.am1
-rw-r--r--libmailutils/tests/parseopt.c4
-rw-r--r--libmailutils/tests/parseopt17.at20
-rw-r--r--libmailutils/tests/parseopt_help05.at2
-rw-r--r--libmailutils/tests/parseopt_help07.at2
-rw-r--r--libmailutils/tests/tcli.c75
-rw-r--r--libmu_sieve/conf.c171
29 files changed, 1390 insertions, 80 deletions
diff --git a/configure.ac b/configure.ac
index dc244de..d729747 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1506,6 +1506,7 @@ AC_CONFIG_FILES([
libmailutils/address/Makefile
libmailutils/sockaddr/Makefile
libmailutils/cidr/Makefile
+ libmailutils/cli/Makefile
libmailutils/cfg/Makefile
libmailutils/datetime/Makefile
libmailutils/diag/Makefile
diff --git a/include/mailutils/Makefile.am b/include/mailutils/Makefile.am
index ba87486..9ae3929 100644
--- a/include/mailutils/Makefile.am
+++ b/include/mailutils/Makefile.am
@@ -36,6 +36,7 @@ pkginclude_HEADERS = \
cctype.h\
cfg.h\
cidr.h\
+ cli.h\
cstr.h\
datetime.h\
daemon.h\
diff --git a/include/mailutils/cfg.h b/include/mailutils/cfg.h
index 7ea8e08..e9f3587 100644
--- a/include/mailutils/cfg.h
+++ b/include/mailutils/cfg.h
@@ -79,6 +79,8 @@ struct mu_cfg_parse_hints
char *site_rcfile;
char *custom_rcfile;
char *program;
+ struct mu_cfg_tree *append_tree;
+ void *data;
};
struct mu_cfg_tree
@@ -238,7 +240,8 @@ int mu_config_register_plain_section (const char *parent_path,
#define MU_CFG_FMT_LOCUS 0x080
#define MU_CFG_FMT_VALUE_ONLY 0x100
#define MU_CFG_FMT_PARAM_PATH 0x200
-
+#define MU_PARSE_CONFIG_LINT 0x400
+
#ifdef MU_CFG_COMPATIBILITY
# define MU_CFG_DEPRECATED
#else
diff --git a/include/mailutils/cli.h b/include/mailutils/cli.h
new file mode 100644
index 0000000..2943bc4
--- a/dev/null
+++ b/include/mailutils/cli.h
@@ -0,0 +1,55 @@
+/* opt.h -- general-purpose command line option parser
+ Copyright (C) 2016 Free Software Foundation, Inc.
+
+ GNU Mailutils is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 3, or (at
+ your option) any later version.
+
+ GNU Mailutils is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _MAILUTILS_CLI_H
+#define _MAILUTILS_CLI_H
+#include <stdio.h>
+#include <mailutils/types.h>
+#include <mailutils/cfg.h>
+#include <mailutils/opt.h>
+
+typedef void (*mu_cli_capa_commit_fp) (void *);
+
+struct mu_cli_capa
+{
+ char *name;
+ struct mu_option *opt;
+ struct mu_cfg_param *cfg;
+ mu_cfg_section_fp parser;
+ mu_cli_capa_commit_fp commit;
+};
+
+void mu_cli_capa_init (void);
+void mu_cli_capa_register (struct mu_cli_capa *capa);
+void mu_cli_capa_apply (char const *name, mu_list_t opts, mu_list_t commits);
+
+struct mu_cli_setup
+{
+ struct mu_option **optv;
+ struct mu_cfg_param *cfg;
+ char *prog_doc;
+ char *prog_args;
+};
+
+void mu_version_func (struct mu_parseopt *po, FILE *stream);
+void mu_cli (int argc, char **argv, struct mu_cli_setup *setup,
+ char **capa, void *data,
+ int *ret_argc, char ***ret_argv);
+
+char *mu_site_config_file (void);
+
+#endif
diff --git a/include/mailutils/diag.h b/include/mailutils/diag.h
index 3e2bc51..0a5ebd2 100644
--- a/include/mailutils/diag.h
+++ b/include/mailutils/diag.h
@@ -29,8 +29,8 @@
extern "C" {
#endif
-extern const char *mu_program_name;
-extern const char *mu_full_program_name;
+extern char *mu_program_name;
+extern char *mu_full_program_name;
#define MU_DIAG_EMERG MU_LOG_EMERG
#define MU_DIAG_ALERT MU_LOG_ALERT
diff --git a/include/mailutils/locker.h b/include/mailutils/locker.h
index b8c4a93..718338f 100644
--- a/include/mailutils/locker.h
+++ b/include/mailutils/locker.h
@@ -103,7 +103,7 @@ extern int mu_locker_set_default_flags (int flags, enum mu_locker_set_mode mode)
extern void mu_locker_set_default_retry_timeout (time_t to);
extern void mu_locker_set_default_retry_count (size_t n);
extern void mu_locker_set_default_expire_timeout (time_t t);
-extern int mu_locker_set_default_external_program (char *path);
+extern int mu_locker_set_default_external_program (char const *path);
/* A flags of 0 means that the default will be used. */
extern int mu_locker_create (mu_locker_t *, const char *filename, int flags);
diff --git a/include/mailutils/opt.h b/include/mailutils/opt.h
index 8e3b03b..cc56342 100644
--- a/include/mailutils/opt.h
+++ b/include/mailutils/opt.h
@@ -23,10 +23,10 @@
#include <mailutils/util.h>
#include <mailutils/cctype.h>
-extern char *mu_progname;
-extern char *mu_absprogname;
+extern char *mu_program_name;
+extern char *mu_full_program_name;
-void mu_set_progname (char const *arg);
+void mu_set_program_name (char const *arg);
#define MU_OPTION_DEFAULT 0
#define MU_OPTION_ARG_OPTIONAL 0x01
@@ -118,7 +118,7 @@ struct mu_parseopt
struct mu_option **po_optv; /* Array of ptrs to option structures */
int po_flags;
- char *po_data; /* Call-specific data */
+ void *po_data; /* Call-specific data */
int po_exit_error; /* Exit on error with this code */
@@ -130,9 +130,10 @@ struct mu_parseopt
char const *po_package_name;
char const *po_package_url;
char const *po_extra_info;
-
- void (*po_help_hook) (FILE *stream); /* FIXME: should take mu_stream_t ?*/
- void (*po_version_hook) (FILE *stream);
+
+ /* FIXME: should these take mu_stream_t ?*/
+ void (*po_help_hook) (struct mu_parseopt *po, FILE *stream);
+ void (*po_version_hook) (struct mu_parseopt *po, FILE *stream);
/* Output data */
int po_ind; /* Index of the next option */
@@ -162,6 +163,7 @@ struct mu_parseopt
int mu_parseopt (struct mu_parseopt *p,
int argc, char **argv, struct mu_option **optv,
int flags);
+void mu_parseopt_error (struct mu_parseopt *po, char const *fmt, ...);
int mu_parseopt_apply (struct mu_parseopt *p);
void mu_parseopt_free (struct mu_parseopt *p);
diff --git a/include/mailutils/stdstream.h b/include/mailutils/stdstream.h
index ac35ff7..9771881 100644
--- a/include/mailutils/stdstream.h
+++ b/include/mailutils/stdstream.h
@@ -28,7 +28,7 @@ extern mu_stream_t mu_strin;
extern mu_stream_t mu_strout;
extern mu_stream_t mu_strerr;
-extern const char *mu_program_name;
+extern char *mu_program_name;
#define MU_STRERR_STDERR 0
#define MU_STRERR_SYSLOG 1
diff --git a/libmailutils/Makefile.am b/libmailutils/Makefile.am
index 7a5270c..82550c2 100644
--- a/libmailutils/Makefile.am
+++ b/libmailutils/Makefile.am
@@ -17,7 +17,7 @@
# <http://www.gnu.org/licenses/>.
SUBDIRS = \
- auth base address list sockaddr cidr cfg diag\
+ auth base address list sockaddr cidr cfg cli diag\
filter mailbox mailer mime msgset opt server string stream stdstream\
property url imapio datetime . tests
@@ -33,6 +33,7 @@ libmailutils_la_LIBADD = \
sockaddr/libsockaddr.la\
cidr/libcidr.la\
cfg/libcfg.la\
+ cli/libcli.la\
datetime/libdatetime.la\
diag/libdiag.la\
filter/libfilter.la\
diff --git a/libmailutils/base/locker.c b/libmailutils/base/locker.c
index b4663b9..c4fe993 100644
--- a/libmailutils/base/locker.c
+++ b/libmailutils/base/locker.c
@@ -242,7 +242,7 @@ mu_locker_set_default_expire_timeout (time_t t)
}
int
-mu_locker_set_default_external_program (char *path)
+mu_locker_set_default_external_program (char const *path)
{
char *p = strdup (path);
if (!p)
diff --git a/libmailutils/cfg/driver.c b/libmailutils/cfg/driver.c
index c0cd2d5..f2a43a3 100644
--- a/libmailutils/cfg/driver.c
+++ b/libmailutils/cfg/driver.c
@@ -463,7 +463,7 @@ mu_cfg_tree_reduce (mu_cfg_tree_t *parse_tree,
void *target_ptr)
{
int rc = 0;
-
+ struct mu_cfg_cont *cont;
if (!parse_tree)
return 0;
if (hints && (hints->flags & MU_PARSE_CONFIG_DUMP))
@@ -477,13 +477,9 @@ mu_cfg_tree_reduce (mu_cfg_tree_t *parse_tree,
mu_stream_destroy (&stream);
}
- if (root_container)
- {
- struct mu_cfg_cont *cont = mu_build_container (progparam);
- rc = mu_cfg_scan_tree (parse_tree, &cont->v.section, target_ptr,
- NULL);
- mu_config_destroy_container (&cont);
- }
+ cont = mu_build_container (progparam);
+ rc = mu_cfg_scan_tree (parse_tree, &cont->v.section, target_ptr, NULL);
+ mu_config_destroy_container (&cont);
return rc;
}
diff --git a/libmailutils/cfg/lexer.l b/libmailutils/cfg/lexer.l
index 40598a1..b6c49ec 100644
--- a/libmailutils/cfg/lexer.l
+++ b/libmailutils/cfg/lexer.l
@@ -330,10 +330,16 @@ mu_cfg_parse_file (mu_cfg_tree_t **return_tree, const char *file, int flags)
int rc;
char *full_name = mu_tilde_expansion (file, MU_HIERARCHY_DELIMITER, NULL);
+ if (flags & MU_PARSE_CONFIG_VERBOSE)
+ mu_diag_output (MU_DIAG_INFO, _("opening configuration file %s"),
+ full_name);
if (stat (full_name, &st))
{
if (errno != ENOENT)
mu_error (_("cannot stat `%s': %s"), full_name, mu_strerror (errno));
+ else if (flags & MU_PARSE_CONFIG_VERBOSE)
+ mu_diag_output (MU_DIAG_INFO, _("configuration file %s doesn't exist"),
+ full_name);
free (full_name);
return ENOENT;
}
diff --git a/libmailutils/cfg/parser.y b/libmailutils/cfg/parser.y
index e36b513..043f7e0 100644
--- a/libmailutils/cfg/parser.y
+++ b/libmailutils/cfg/parser.y
@@ -1589,7 +1589,10 @@ mu_cfg_parse_config (mu_cfg_tree_t **ptree, struct mu_cfg_parse_hints *hints)
mu_cfg_tree_union (&tree, &tmp);
}
}
-
+
+ if (hints->append_tree)
+ mu_cfg_tree_union (&tree, &hints->append_tree);
+
*ptree = tree;
return rc;
}
diff --git a/libmailutils/cli/Makefile.am b/libmailutils/cli/Makefile.am
new file mode 100644
index 0000000..48770e8
--- a/dev/null
+++ b/libmailutils/cli/Makefile.am
@@ -0,0 +1,26 @@
+# GNU Mailutils -- a suite of utilities for electronic mail
+# Copyright (C) 2016 Free Software Foundation, Inc.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 3 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General
+# Public License along with this library. If not, see
+# <http://www.gnu.org/licenses/>.
+
+noinst_LTLIBRARIES = libcli.la
+
+libcli_la_SOURCES = \
+ capa.c\
+ cli.c\
+ stdcapa.c
+
+AM_CPPFLAGS = \
+ @MU_LIB_COMMON_INCLUDES@ -I/libmailutils
diff --git a/libmailutils/cli/capa.c b/libmailutils/cli/capa.c
new file mode 100644
index 0000000..bd5c557
--- a/dev/null
+++ b/libmailutils/cli/capa.c
@@ -0,0 +1,96 @@
+/* capa.c -- CLI capabilities for GNU Mailutils
+ Copyright (C) 2016 Free Software Foundation, Inc.
+
+ GNU Mailutils is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 3, or (at
+ your option) any later version.
+
+ GNU Mailutils is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <mailutils/cli.h>
+#include <mailutils/list.h>
+#include <mailutils/alloc.h>
+#include <mailutils/nls.h>
+
+static mu_list_t capa_list;
+
+static void
+capa_free (void *ptr)
+{
+ struct mu_cli_capa *cp = ptr;
+ free (cp->name);
+ free (cp);
+}
+
+void
+mu_cli_capa_register (struct mu_cli_capa *capa)
+{
+ struct mu_cli_capa *cp = mu_alloc (sizeof (*cp));
+ cp->name = mu_strdup (capa->name);
+ cp->opt = capa->opt;
+ cp->cfg = capa->cfg;
+ cp->parser = capa->parser;
+ cp->commit = capa->commit;
+ if (!capa_list)
+ {
+ mu_list_create (&capa_list);
+ mu_list_set_destroy_item (capa_list, capa_free);
+ }
+ mu_list_append (capa_list, cp);
+}
+
+struct capa_apply
+{
+ char const *name;
+ mu_list_t opts;
+ mu_list_t commits;
+ int found;
+};
+
+static int
+capa_apply (void *item, void *data)
+{
+ struct mu_cli_capa *cp = item;
+ struct capa_apply *ap = data;
+
+ if (strcmp (cp->name, ap->name) == 0)
+ {
+ ap->found = 1;
+ if (cp->opt)
+ mu_list_append (ap->opts, cp->opt);
+ if (cp->commit)
+ mu_list_append (ap->commits, cp->commit);
+ if (cp->parser || cp->cfg)
+ mu_config_root_register_section (NULL, cp->name, NULL,
+ cp->parser, cp->cfg);
+ }
+ return 0;
+}
+
+void
+mu_cli_capa_apply (char const *name, mu_list_t opts, mu_list_t commits)
+{
+ struct capa_apply app;
+ app.name = name;
+ app.opts = opts;
+ app.commits = commits;
+ app.found = 0;
+ mu_list_foreach (capa_list, capa_apply, &app);
+ if (!app.found)
+ mu_error (_("INTERNAL ERROR at %s:%d: unknown standard capability `%s'"),
+ __FILE__, __LINE__, name);
+}
+
+
diff --git a/libmailutils/cli/cli.c b/libmailutils/cli/cli.c
new file mode 100644
index 0000000..2be1af8
--- a/dev/null
+++ b/libmailutils/cli/cli.c
@@ -0,0 +1,420 @@
+/* cli.c -- Command line interface for GNU Mailutils
+ Copyright (C) 2016 Free Software Foundation, Inc.
+
+ GNU Mailutils is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 3, or (at
+ your option) any later version.
+
+ GNU Mailutils is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <stdlib.h>
+#include <sysexits.h>
+#include <mailutils/cfg.h>
+#include <mailutils/opt.h>
+#include <mailutils/cli.h>
+#include <mailutils/list.h>
+#include <mailutils/alloc.h>
+#include <mailutils/nls.h>
+#include <mailutils/errno.h>
+#include <mailutils/version.h>
+#include <mailutils/stream.h>
+#include <mailutils/stdstream.h>
+#include <mailutils/io.h>
+#include <mailutils/syslog.h>
+
+#ifndef MU_SITE_CONFIG_FILE
+# define MU_SITE_CONFIG_FILE SYSCONFDIR "/mailutils.rc"
+#endif
+
+char *
+mu_site_config_file (void)
+{
+ char *p = getenv ("MU_SITE_CONFIG_FILE");
+ if (p)
+ return p;
+ return MU_SITE_CONFIG_FILE;
+}
+
+
+const char mu_version_copyright[] =
+ /* Do *not* mark this string for translation. %s is a copyright
+ symbol suitable for this locale, and %d is the copyright
+ year. */
+ "Copyright %s 2007-2016 Free Software Foundation, inc.";
+
+void
+mu_version_func (struct mu_parseopt *po, FILE *stream)
+{
+#ifdef GIT_DESCRIBE
+ fprintf (stream, "%s (%s) %s [%s]\n",
+ mu_program_name, PACKAGE_NAME, PACKAGE_VERSION, GIT_DESCRIBE);
+#else
+ fprintf (stream, "%s (%s) %s\n", mu_program_name,
+ PACKAGE_NAME, PACKAGE_VERSION);
+#endif
+ /* TRANSLATORS: Translate "(C)" to the copyright symbol
+ (C-in-a-circle), if this symbol is available in the user's
+ locale. Otherwise, do not translate "(C)"; leave it as-is. */
+ fprintf (stream, mu_version_copyright, _("(C)"));
+ fputs (_("\
+\n\
+License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\nThis is free software: you are free to change and redistribute it.\n\
+There is NO WARRANTY, to the extent permitted by law.\n\
+\n\
+"),
+ stream);
+}
+
+static char gnu_general_help_url[] =
+ N_("General help using GNU software: <http://www.gnu.org/gethelp/>");
+
+
+static void
+change_progname (struct mu_parseopt *po, struct mu_option *opt,
+ char const *arg)
+{
+ po->po_prog_name = mu_strdup (arg);
+}
+
+static void
+no_user_config (struct mu_parseopt *po, struct mu_option *opt,
+ char const *arg)
+{
+ struct mu_cfg_parse_hints *hints = po->po_data;
+ hints->flags &= ~MU_CFG_PARSE_PROGRAM;
+}
+
+static void
+no_site_config (struct mu_parseopt *po, struct mu_option *opt,
+ char const *arg)
+{
+ struct mu_cfg_parse_hints *hints = po->po_data;
+ hints->flags &= ~MU_CFG_PARSE_SITE_RCFILE;
+}
+
+static void
+config_file (struct mu_parseopt *po, struct mu_option *opt,
+ char const *arg)
+{
+ struct mu_cfg_parse_hints *hints = po->po_data;
+ hints->flags |= MU_CFG_PARSE_CUSTOM_RCFILE;
+ hints->custom_rcfile = mu_strdup (arg);
+}
+
+static void
+config_verbose (struct mu_parseopt *po, struct mu_option *opt,
+ char const *arg)
+{
+ struct mu_cfg_parse_hints *hints = po->po_data;
+ if (hints->flags & MU_PARSE_CONFIG_VERBOSE)
+ hints->flags |= MU_PARSE_CONFIG_DUMP;
+ else
+ hints->flags |= MU_PARSE_CONFIG_VERBOSE;
+}
+
+static void
+config_lint (struct mu_parseopt *po, struct mu_option *opt,
+ char const *arg)
+{
+ struct mu_cfg_parse_hints *hints = po->po_data;
+ hints->flags |= MU_PARSE_CONFIG_VERBOSE|MU_PARSE_CONFIG_LINT;
+}
+
+static void
+param_set (struct mu_parseopt *po, struct mu_option *opt, char const *arg)
+{
+ struct mu_cfg_parse_hints *hints = po->po_data;
+ mu_cfg_node_t *node;
+ int rc = mu_cfg_create_subtree (arg, &node);
+ if (rc)
+ mu_parseopt_error (po, "%s: cannot create node: %s",
+ arg, mu_strerror (rc));
+ if (!hints->append_tree)
+ mu_cfg_tree_create (&hints->append_tree);
+ mu_cfg_tree_add_node (hints->append_tree, node);
+}
+
+struct mu_option mu_common_options[] = {
+ MU_OPTION_GROUP(N_("Common options")),
+ { "program-name", 0, N_("NAME"), MU_OPTION_IMMEDIATE|MU_OPTION_HIDDEN,
+ N_("set program name"),
+ mu_c_string, NULL, change_progname },
+
+ { "no-user-config", 0, NULL, MU_OPTION_IMMEDIATE,
+ N_("do not load user configuration file"),
+ mu_c_string, NULL, no_user_config },
+ { "no-user-rcfile", 0, NULL, MU_OPTION_ALIAS },
+
+ { "no-site-config", 0, NULL, MU_OPTION_IMMEDIATE,
+ N_("do not load user configuration file"),
+ mu_c_string, NULL, no_site_config },
+ { "no-site-rcfile", 0, NULL, MU_OPTION_ALIAS },
+
+ { "config-file", 0, N_("FILE"), MU_OPTION_IMMEDIATE,
+ N_("load this configuration file"),
+ mu_c_string, NULL, config_file },
+ { "rcfile", 0, NULL, MU_OPTION_ALIAS },
+
+ { "config-verbose", 0, NULL, MU_OPTION_IMMEDIATE,
+ N_("verbosely log parsing of the configuration files"),
+ mu_c_string, NULL, config_verbose },
+ { "rcfile-verbose", 0, NULL, MU_OPTION_ALIAS },
+
+ { "config-lint", 0, NULL, MU_OPTION_IMMEDIATE,
+ N_("check configuration file syntax and exit"),
+ mu_c_string, NULL, config_lint },
+ { "rcfile-lint", 0, NULL, MU_OPTION_ALIAS },
+
+ { "set", 0, N_("PARAM=VALUE"), MU_OPTION_IMMEDIATE,
+ N_("set configuration parameter"),
+ mu_c_string, NULL, param_set },
+
+ MU_OPTION_END
+};
+
+static void
+show_comp_defaults (struct mu_parseopt *po, struct mu_option *opt,
+ char const *unused)
+{
+ mu_print_options ();
+ exit (0);
+}
+
+static void
+show_config_help (struct mu_parseopt *po, struct mu_option *opt,
+ char const *unused)
+{
+ struct mu_cfg_parse_hints *hints = po->po_data;
+
+ char *comment;
+ mu_stream_t stream;
+ struct mu_cfg_cont *cont;
+ static struct mu_cfg_param dummy_include_param[] = {
+ { "include", mu_c_string, NULL, 0, NULL,
+ N_("Include contents of the given file. If a directory is given, "
+ "include contents of the file <file>/<program>, where "
+ "<program> is the name of the program. This latter form is "
+ "allowed only in the site-wide configuration file."),
+ N_("file-or-directory") },
+ { NULL }
+ };
+
+ mu_stdio_stream_create (&stream, MU_STDOUT_FD, 0);
+
+ mu_asprintf (&comment,
+ "Configuration file structure for %s utility.",
+ po->po_prog_name);
+ mu_cfg_format_docstring (stream, comment, 0);
+ free (comment);
+
+ mu_asprintf (&comment,
+ "For use in global configuration file (%s), enclose it "
+ "in `program %s { ... };",
+ mu_site_config_file (),
+ po->po_prog_name);
+ mu_cfg_format_docstring (stream, comment, 0);
+ free (comment);
+
+ /* FIXME: %s should be replaced by the canonical utility name */
+ mu_asprintf (&comment, "For more information, use `info %s'.",
+ po->po_prog_name);
+ mu_cfg_format_docstring (stream, comment, 0);
+ free (comment);
+
+ cont = mu_config_clone_root_container ();
+ mu_config_container_register_section (&cont, NULL, NULL, NULL, NULL,
+ dummy_include_param, NULL);
+ if (hints->data)
+ mu_config_container_register_section (&cont, NULL, NULL, NULL, NULL,
+ hints->data, NULL);
+ mu_cfg_format_container (stream, cont);
+ mu_config_destroy_container (&cont);
+
+ mu_stream_destroy (&stream);
+ exit (0);
+}
+
+struct mu_option mu_extra_help_options[] = {
+ MU_OPTION_GROUP (N_("Informational options")),
+ { "show-config-options", 0, NULL, MU_OPTION_IMMEDIATE,
+ N_("show compilation options"),
+ mu_c_string, NULL, show_comp_defaults },
+ { "config-help", 0, NULL, MU_OPTION_IMMEDIATE,
+ N_("show configuration file summary"),
+ mu_c_string, NULL, show_config_help },
+ MU_OPTION_END
+};
+
+
+static int
+add_opt_group (void *item, void *data)
+{
+ struct mu_parseopt *po = data;
+ struct mu_option *opt = item;
+ po->po_optv[po->po_optc++] = opt;
+ return 0;
+}
+
+/* Build the list of option groups and configuration sections */
+static struct mu_option **
+init_options (char **capa, struct mu_cli_setup *setup,
+ mu_list_t *ret_comlist)
+{
+ size_t i, s;
+ mu_list_t oplist;
+ struct mu_parseopt po;
+
+ mu_list_create (&oplist);
+ if (setup->optv)
+ {
+ for (i = 0; setup->optv[i]; i++)
+ mu_list_append (oplist, setup->optv[i]);
+ }
+ if (capa)
+ {
+ mu_list_t comlist;
+ mu_list_create (&comlist);
+ for (i = 0; capa[i]; i++)
+ mu_cli_capa_apply (capa[i], oplist, comlist);
+ *ret_comlist = comlist;
+ }
+ else
+ *ret_comlist = NULL;
+
+ mu_list_append (oplist, mu_common_options);
+ mu_list_append (oplist, mu_extra_help_options);
+
+ mu_list_count (oplist, &s);
+
+ po.po_optv = mu_calloc (s + 1, sizeof (po.po_optv[0]));
+ po.po_optc = 0;
+ mu_list_foreach (oplist, add_opt_group, &po);
+ if (po.po_optc != s)
+ abort ();
+ po.po_optv[po.po_optc] = NULL;
+ mu_list_destroy (&oplist);
+ return po.po_optv;
+}
+
+static int
+run_commit (void *item, void *data)
+{
+ mu_cli_capa_commit_fp commit = item;
+ commit (data);
+ return 0;
+}
+
+void
+mu_cli (int argc, char **argv, struct mu_cli_setup *setup, char **capa,
+ void *data,
+ int *ret_argc, char ***ret_argv)
+{
+ struct mu_parseopt po;
+ int flags = 0;
+ struct mu_cfg_tree *parse_tree = NULL;
+ struct mu_cfg_parse_hints hints;
+ struct mu_option **optv;
+ mu_list_t com_list;
+
+ /* Set program name */
+ mu_set_program_name (argv[0]);
+
+ if (!mu_log_tag)
+ mu_log_tag = (char*)mu_program_name;
+
+ /* Initialize standard streams */
+ mu_stdstream_setup (MU_STDSTREAM_RESET_NONE);
+
+ /* Initialize standard capabilities */
+ mu_cli_capa_init ();
+
+ /* Initialize hints */
+ memset (&hints, 0, sizeof (hints));
+ hints.flags |= MU_CFG_PARSE_SITE_RCFILE;
+ hints.site_rcfile = mu_site_config_file ();
+
+ hints.flags |= MU_CFG_PARSE_PROGRAM;
+ hints.program = (char*) mu_program_name;
+
+ hints.data = setup->cfg;
+
+ /* Initialize po */
+ if (setup->prog_doc)
+ {
+ po.po_prog_doc = setup->prog_doc;
+ flags |= MU_PARSEOPT_PROG_DOC;
+ }
+
+ if (setup->prog_args)
+ {
+ po.po_prog_args = setup->prog_args;
+ flags |= MU_PARSEOPT_PROG_ARGS;
+ }
+
+ po.po_package_name = PACKAGE_NAME;
+ flags |= MU_PARSEOPT_PACKAGE_NAME;
+
+ po.po_package_url = PACKAGE_URL;
+ flags |= MU_PARSEOPT_PACKAGE_URL;
+
+ po.po_bug_address = PACKAGE_BUGREPORT;
+ flags |= MU_PARSEOPT_BUG_ADDRESS;
+
+ po.po_extra_info = gnu_general_help_url;
+ flags |= MU_PARSEOPT_EXTRA_INFO;
+
+ po.po_version_hook = mu_version_func;
+ flags |= MU_PARSEOPT_VERSION_HOOK;
+
+ po.po_data = &hints;
+ flags |= MU_PARSEOPT_DATA;
+
+ po.po_exit_error = EX_USAGE;
+
+ optv = init_options (capa, setup, &com_list);
+
+ if (mu_parseopt (&po, argc, argv, optv, flags))
+ exit (EX_USAGE);
+
+ argc -= po.po_arg_start;
+ argv += po.po_arg_start;
+
+ if (ret_argc)
+ {
+ *ret_argc = argc;
+ *ret_argv = argv;
+ }
+ else if (argc)
+ mu_parseopt_error (&po, "%s", _("unexpected arguments"));
+
+ if (mu_cfg_parse_config (&parse_tree, &hints))
+ exit (EX_CONFIG);
+
+ if (mu_cfg_tree_reduce (parse_tree, &hints, setup->cfg, data))
+ exit (EX_CONFIG);
+
+ if (mu_cfg_error_count) //FIXME
+ exit (EX_CONFIG);
+
+ mu_parseopt_apply (&po);
+
+ mu_list_foreach (com_list, run_commit, NULL);
+ mu_list_destroy (&com_list);
+
+ if (hints.flags & MU_PARSE_CONFIG_LINT)
+ exit (0);
+
+ mu_cfg_destroy_tree (&parse_tree);
+ free (optv);
+ mu_parseopt_free (&po);
+}
diff --git a/libmailutils/cli/stdcapa.c b/libmailutils/cli/stdcapa.c
new file mode 100644
index 0000000..3b1cabe
--- a/dev/null
+++ b/libmailutils/cli/stdcapa.c
@@ -0,0 +1,466 @@
+/* stdcapa.c -- Standard CLI capabilities for GNU Mailutils
+ Copyright (C) 2016 Free Software Foundation, Inc.
+
+ GNU Mailutils is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 3, or (at
+ your option) any later version.
+
+ GNU Mailutils is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <stdlib.h>
+#include <mailutils/cli.h>
+#include <mailutils/cfg.h>
+#include <mailutils/nls.h>
+#include <mailutils/syslog.h>
+#include <mailutils/stdstream.h>
+#include <mailutils/mailer.h>
+#include <mailutils/errno.h>
+#include <mailutils/mailbox.h>
+#include <mailutils/registrar.h>
+#include <mailutils/locker.h>
+
+/* *************************************************************************
+ * Logging section
+ * ************************************************************************* */
+static void
+cli_log_facility (struct mu_parseopt *po, struct mu_option *opt,
+ char const *arg)
+{
+ if (mu_string_to_syslog_facility (arg, &mu_log_facility))
+ mu_parseopt_error (po, _("unknown syslog facility `%s'"), arg);
+}
+
+static int
+cb_facility (void *data, mu_config_value_t *val)
+{
+ if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
+ return 1;
+
+ if (mu_string_to_syslog_facility (val->v.string, &mu_log_facility))
+ {
+ mu_error (_("unknown syslog facility `%s'"), val->v.string);
+ return 1;
+ }
+ return 0;
+}
+
+static int
+cb_severity (void *data, mu_config_value_t *val)
+{
+ unsigned n;
+
+ if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
+ return 1;
+ if (mu_severity_from_string (val->v.string, &n))
+ {
+ mu_error (_("unknown severity `%s'"), val->v.string);
+ return 1;
+ }
+ mu_log_severity_threshold = n;
+ return 0;
+}
+
+static struct mu_cfg_param logging_cfg[] = {
+ { "syslog", mu_c_bool, &mu_log_syslog, 0, NULL,
+ N_("Send diagnostics to syslog.") },
+ { "print-severity", mu_c_bool, &mu_log_print_severity, 0, NULL,
+ N_("Print message severity levels.") },
+ { "severity", mu_cfg_callback, NULL, 0, cb_severity,
+ N_("Output only messages with a severity equal to or greater than "
+ "this one."),
+ N_("arg: string")},
+ { "facility", mu_cfg_callback, NULL, 0, cb_facility,
+ N_("Set syslog facility. Arg is one of the following: user, daemon, "
+ "auth, authpriv, mail, cron, local0 through local7 (case-insensitive), "
+ "or a facility number."),
+ N_("arg: string") },
+ { "session-id", mu_c_bool, &mu_log_session_id, 0, NULL,
+ N_("Log session ID") },
+ { "tag", mu_c_string, &mu_log_tag, 0, NULL,
+ N_("Tag syslog messages with this string.") },
+ { NULL }
+};
+
+static struct mu_option logging_option[] = {
+ { "log-facility", 0, N_("FACILITY"), MU_OPTION_DEFAULT,
+ N_("output logs to syslog FACILITY"),
+ mu_c_int, &mu_log_facility, cli_log_facility },
+ MU_OPTION_END
+};
+
+static void
+logging_commit (void *unused)
+{
+ if (mu_log_syslog >= 0)
+ mu_stdstream_strerr_setup (mu_log_syslog ?
+ MU_STRERR_SYSLOG : MU_STRERR_STDERR);
+}
+
+/* *************************************************************************
+ * Mailer
+ * ************************************************************************* */
+static void
+cli_mailer (struct mu_parseopt *po, struct mu_option *opt, char const *arg)
+{
+ int rc = mu_mailer_set_url_default (arg);
+ if (rc != 0)
+ mu_parseopt_error (po, _("invalid mailer URL `%s': %s"),
+ arg, mu_strerror (rc));
+}
+
+static struct mu_option mailer_option[] = {
+ { "mailer", 'M', N_("MAILER"), MU_OPTION_DEFAULT,
+ N_("use specified URL as the default mailer"),
+ mu_c_string, NULL, cli_mailer },
+ MU_OPTION_END
+};
+
+static int
+cb_mailer (void *data, mu_config_value_t *val)
+{
+ int rc;
+
+ if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
+ return 1;
+ rc = mu_mailer_set_url_default (val->v.string);
+ if (rc != 0)
+ mu_error (_("%s: invalid mailer URL: %s"),
+ val->v.string, mu_strerror (rc));
+ return rc;
+}
+
+static struct mu_cfg_param mailer_cfg[] = {
+ { "url", mu_cfg_callback, NULL, 0, cb_mailer,
+ N_("Use this URL as the default mailer"),
+ N_("url: string") },
+ { NULL }
+};
+
+/* *************************************************************************
+ * Debugging
+ * ************************************************************************* */
+static void
+cli_debug_level (struct mu_parseopt *po, struct mu_option *opt,
+ char const *arg)
+{
+ mu_debug_clear_all ();
+ mu_debug_parse_spec (arg);
+ /* FIXME: Error handling */
+}
+
+static struct mu_option debug_option[] = {
+ MU_OPTION_GROUP (N_("Global debugging settings")),
+ { "debug-level", 0, N_("LEVEL"), MU_OPTION_DEFAULT,
+ N_("set Mailutils debugging level"),
+ mu_c_string, NULL, cli_debug_level },
+ { "debug-line-info", 0, NULL, MU_OPTION_DEFAULT,
+ N_("show source info with debugging messages"),
+ mu_c_bool, &mu_debug_line_info },
+ MU_OPTION_END
+};
+
+static int
+cb_debug_level (void *data, mu_config_value_t *val)
+{
+ if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
+ return 1;
+ mu_debug_parse_spec (val->v.string);
+ return 0;
+}
+
+static struct mu_cfg_param debug_cfg[] = {
+ { "level", mu_cfg_callback, NULL, 0, &cb_debug_level,
+ N_("Set Mailutils debugging level. Argument is a colon-separated list "
+ "of debugging specifications in the form:\n"
+ " <object: string>[[:]=<level: number>]."),
+ N_("arg: string") },
+ { "line-info", mu_c_bool, &mu_debug_line_info, 0, NULL,
+ N_("Prefix debug messages with Mailutils source locations.") },
+ { NULL }
+};
+
+/* ************************************************************************* *
+ * Mailbox *
+ * ************************************************************************* */
+
+static int
+cb_mail_spool (void *data, mu_config_value_t *val)
+{
+ int rc;
+ if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
+ return 1;
+ rc = mu_set_mail_directory (val->v.string);
+ if (rc)
+ mu_error (_("cannot set mail directory name to `%s': %s"),
+ val->v.string, mu_strerror (rc));
+ return rc;
+}
+
+static int
+cb_mailbox_pattern (void *data, mu_config_value_t *val)
+{
+ int rc;
+ if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
+ return 1;
+
+ rc = mu_set_mailbox_pattern (val->v.string);
+ if (rc)
+ mu_error (_("cannot set mailbox pattern to `%s': %s"),
+ val->v.string, mu_strerror (rc));
+ return rc;
+}
+
+static int
+cb_mailbox_type (void *data, mu_config_value_t *val)
+{
+ if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
+ return 1;
+ if (mu_registrar_set_default_scheme (val->v.string))
+ mu_error (_("invalid mailbox type: %s"), val->v.string);
+ return 0;
+}
+
+static int
+cb_folder (void *data, mu_config_value_t *val)
+{
+ if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
+ return 1;
+ mu_set_folder_directory (val->v.string);
+ return 0;
+}
+
+static struct mu_cfg_param mailbox_cfg[] = {
+ { "mail-spool", mu_cfg_callback, NULL, 0, cb_mail_spool,
+ N_("Use specified URL as a mailspool directory."),
+ N_("url: string") },
+ { "mailbox-pattern", mu_cfg_callback, NULL, 0, cb_mailbox_pattern,
+ N_("Create mailbox URL using <pattern>."),
+ N_("pattern: string") },
+ { "mailbox-type", mu_cfg_callback, NULL, 0, cb_mailbox_type,
+ N_("Default mailbox type."),
+ N_("protocol: string") },
+ { "folder", mu_cfg_callback, NULL, 0, cb_folder,
+ N_("Default user mail folder"),
+ N_("dir: string") },
+ { NULL }
+};
+
+/* ************************************************************************* *
+ * Locking *
+ * ************************************************************************* */
+static int
+cb_locker_flags (void *data, mu_config_value_t *val)
+{
+ int flags = 0;
+ char const *s;
+
+ if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
+ return 1;
+
+ for (s = val->v.string; *s; s++)
+ {
+ switch (*s)
+ {
+ case 'E':
+ flags |= MU_LOCKER_EXTERNAL;
+ break;
+
+ case 'R':
+ flags |= MU_LOCKER_RETRY;
+ break;
+
+ case 'T':
+ flags |= MU_LOCKER_TIME;
+ break;
+
+ case 'P':
+ flags |= MU_LOCKER_PID;
+ break;
+
+ default:
+ mu_error (_("invalid lock flag `%c'"), *s);
+ }
+ }
+ mu_locker_set_default_flags (flags, mu_locker_assign);
+ return 0;
+}
+
+static int
+cb_locker_retry_timeout (void *data, mu_config_value_t *val)
+{
+ int rc;
+ time_t t;
+ char *errmsg;
+
+ if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
+ return 1;
+ rc = mu_str_to_c (val->v.string, mu_c_time, &t, &errmsg);
+ if (rc)
+ {
+ mu_error (_("conversion failed: %s"), errmsg ? errmsg :
+ mu_strerror (rc));
+ free (errmsg);
+ }
+ else
+ {
+ mu_locker_set_default_retry_timeout (t);
+ mu_locker_set_default_flags (MU_LOCKER_RETRY, mu_locker_set_bit);
+ }
+ return 0;
+}
+
+static int
+cb_locker_retry_count (void *data, mu_config_value_t *val)
+{
+ int rc;
+ size_t n;
+ char *errmsg;
+
+ if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
+ return 1;
+ rc = mu_str_to_c (val->v.string, mu_c_size, &n, &errmsg);
+ if (rc)
+ {
+ mu_error (_("conversion failed: %s"), errmsg ? errmsg :
+ mu_strerror (rc));
+ free (errmsg);
+ }
+ else
+ {
+ mu_locker_set_default_retry_count (n);
+ mu_locker_set_default_flags (MU_LOCKER_RETRY, mu_locker_set_bit);
+ }
+ return 0;
+}
+
+static int
+cb_locker_expire_timeout (void *data, mu_config_value_t *val)
+{
+ int rc;
+ time_t t;
+ char *errmsg;
+
+ if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
+ return 1;
+ rc = mu_str_to_c (val->v.string, mu_c_time, &t, &errmsg);
+ if (rc)
+ {
+ mu_error (_("conversion failed: %s"), errmsg ? errmsg :
+ mu_strerror (rc));
+ free (errmsg);
+ }
+ else
+ {
+ mu_locker_set_default_expire_timeout (t);
+ mu_locker_set_default_flags (MU_LOCKER_EXTERNAL, mu_locker_set_bit);
+ }
+ return 0;
+}
+
+static int
+cb_locker_external (void *data, mu_config_value_t *val)
+{
+ if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
+ return 1;
+ mu_locker_set_default_external_program (val->v.string);
+ mu_locker_set_default_flags (MU_LOCKER_TIME, mu_locker_set_bit);
+ return 0;
+}
+
+static struct mu_cfg_param locking_cfg[] = {
+ /* FIXME: Flags are superfluous. */
+ { "flags", mu_cfg_callback, NULL, 0, cb_locker_flags,
+ N_("Default locker flags (E=external, R=retry, T=time, P=pid)."),
+ N_("arg: string") },
+ { "retry-timeout", mu_cfg_callback, NULL, 0, cb_locker_retry_timeout,
+ N_("Set timeout for acquiring the lock."),
+ N_("arg: interval")},
+ { "retry-count", mu_cfg_callback, NULL, 0, cb_locker_retry_count,
+ N_("Set the maximum number of times to retry acquiring the lock."),
+ N_("arg: integer") },
+ { "expire-timeout", mu_cfg_callback, NULL, 0, cb_locker_expire_timeout,
+ N_("Expire locks older than this amount of time."),
+ N_("arg: interval")},
+ { "external-locker", mu_cfg_callback, NULL, 0, cb_locker_external,
+ N_("Use external locker program."),
+ N_("prog: string") },
+ { NULL, }
+};
+
+/* ************************************************************************* *
+ * Address *
+ * ************************************************************************* */
+static int
+cb_email_addr (void *data, mu_config_value_t *val)
+{
+ int rc;
+
+ if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
+ return 1;
+
+ rc = mu_set_user_email (val->v.string);
+ if (rc)
+ mu_error (_("invalid email address `%s': %s"),
+ val->v.string, mu_strerror (rc));
+ return 0;
+}
+
+static int
+cb_email_domain (void *data, mu_config_value_t *val)
+{
+ int rc;
+
+ if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
+ return 1;
+
+ rc = mu_set_user_email_domain (val->v.string);
+ if (rc)
+ mu_error (_("invalid email domain `%s': %s"),
+ val->v.string, mu_strerror (rc));
+ return 0;
+}
+
+static struct mu_cfg_param address_cfg[] = {
+ { "email-addr", mu_cfg_callback, NULL, 0, cb_email_addr,
+ N_("Set the current user email address (default is "
+ "loginname@defaultdomain)."),
+ N_("email: address") },
+ { "email-domain", mu_cfg_callback, NULL, 0, cb_email_domain,
+ N_("Set e-mail domain for unqualified user names (default is this host)"),
+ N_("domain: string") },
+ { NULL }
+};
+
+
+/* ************************************************************************* *
+ * Registry of standard mailutils' capabilities *
+ * ************************************************************************* */
+struct mu_cli_capa mu_cli_std_capa[] = {
+ { "mailutils" }, /* Dummy */
+ { "logging", logging_option, logging_cfg, NULL, logging_commit },
+ { "mailer", mailer_option, mailer_cfg, NULL, NULL },
+ { "debug", debug_option, debug_cfg, NULL, NULL },
+ { "mailbox", NULL, mailbox_cfg, NULL, NULL },
+ { "locking", NULL, locking_cfg, NULL, NULL },
+ { "address", NULL, address_cfg, NULL, NULL },
+ { NULL }
+};
+
+void
+mu_cli_capa_init (void)
+{
+ size_t i;
+
+ for (i = 0; mu_cli_std_capa[i].name; i++)
+ mu_cli_capa_register (&mu_cli_std_capa[i]);
+}
diff --git a/libmailutils/diag/diag.c b/libmailutils/diag/diag.c
index ba055b2..3f10356 100644
--- a/libmailutils/diag/diag.c
+++ b/libmailutils/diag/diag.c
@@ -30,32 +30,6 @@
#include <mailutils/stdstream.h>
#include <mailutils/stream.h>
-const char *mu_program_name;
-const char *mu_full_program_name;
-
-void
-mu_set_program_name (const char *name)
-{
- const char *progname;
-
- mu_full_program_name = name;
- if (!name)
- progname = name;
- else
- {
- progname = strrchr (name, '/');
- if (progname)
- progname++;
- else
- progname = name;
-
- if (strlen (progname) > 3 && memcmp (progname, "lt-", 3) == 0)
- progname += 3;
- }
-
- mu_program_name = progname;
-}
-
void
mu_diag_init ()
{
diff --git a/libmailutils/opt/help.c b/libmailutils/opt/help.c
index b106d9a..f91c126 100644
--- a/libmailutils/opt/help.c
+++ b/libmailutils/opt/help.c
@@ -155,7 +155,7 @@ init_usage_vars (struct mu_parseopt *po)
fmt = getenv ("ARGP_HELP_FMT");
if (!fmt)
return;
- ws.ws_delim=",";
+ ws.ws_delim = ",";
if (mu_wordsplit (fmt, &ws,
MU_WRDSF_DELIM | MU_WRDSF_NOVAR | MU_WRDSF_NOCMD
| MU_WRDSF_WS | MU_WRDSF_SHOWERR))
@@ -346,20 +346,20 @@ mu_program_help (struct mu_parseopt *po)
mu_option_describe_options (po->po_optv, po->po_optc);
if (po->po_help_hook)
- po->po_help_hook (stdout);
+ po->po_help_hook (po, stdout);
if (po->po_bug_address)
/* TRANSLATORS: The placeholder indicates the bug-reporting address
for this package. Please add _another line_ saying
"Report translation bugs to <...>\n" with the address for translation
bugs (typically your translation team's web or email address). */
- printf (_("Report bugs to %s.\n"), po->po_bug_address);
+ printf (_("Report bugs to <%s>.\n"), po->po_bug_address);
if (po->po_package_name && po->po_package_url)
printf (_("%s home page: <%s>\n"),
po->po_package_name, po->po_package_url);
if (po->po_flags & MU_PARSEOPT_EXTRA_INFO)
- print_option_descr (po->po_extra_info, 0, rmargin);
+ print_option_descr (_(po->po_extra_info), 0, rmargin);
}
static struct mu_option **option_tab;
diff --git a/libmailutils/opt/opt.c b/libmailutils/opt/opt.c
index 61bd00f..ae269db 100644
--- a/libmailutils/opt/opt.c
+++ b/libmailutils/opt/opt.c
@@ -85,7 +85,7 @@ fn_usage (struct mu_parseopt *po, struct mu_option *opt, char const *unused)
static void
fn_version (struct mu_parseopt *po, struct mu_option *opt, char const *unused)
{
- po->po_version_hook (stdout);
+ po->po_version_hook (po, stdout);
exit (EXIT_SUCCESS);
}
@@ -107,8 +107,8 @@ struct mu_option mu_version_options[] = {
};
/* Output error message */
-static void
-parse_error (struct mu_parseopt *po, char const *fmt, ...)
+void
+mu_parseopt_error (struct mu_parseopt *po, char const *fmt, ...)
{
va_list ap;
@@ -176,7 +176,7 @@ find_short_option (struct mu_parseopt *po, int chr)
&& po->po_optv[i]->opt_short == chr)
return option_unalias (po, i);
}
- parse_error (po, _("unrecognized option '-%c'"), chr);
+ mu_parseopt_error (po, _("unrecognized option '-%c'"), chr);
return NULL;
}
@@ -209,7 +209,7 @@ find_long_option (struct mu_parseopt *po, char const *optstr,
case 1:
if (po->po_flags & MU_PARSEOPT_IGNORE_ERRORS)
return NULL;
- parse_error (po,
+ mu_parseopt_error (po,
_("option '--%*.*s' is ambiguous; possibilities:"),
optlen, optlen, optstr);
fprintf (stderr, "--%s\n", po->po_optv[ind]->opt_long);
@@ -224,7 +224,7 @@ find_long_option (struct mu_parseopt *po, char const *optstr,
switch (found)
{
case 0:
- parse_error (po, _("unrecognized option '--%s'"), optstr);
+ mu_parseopt_error (po, _("unrecognized option '--%s'"), optstr);
break;
case 1:
@@ -303,7 +303,7 @@ next_opt (struct mu_parseopt *po)
break;
if (!(po->po_flags & MU_PARSEOPT_IN_ORDER))
{
- if (!po->po_permuted)
+ if (!po->po_permuted && po->po_arg_count == 0)
po->po_arg_start = po->po_ind - 1;
po->po_arg_count++;
continue;
@@ -405,11 +405,11 @@ parse (struct mu_parseopt *po)
else
{
if (long_opt)
- parse_error (po,
+ mu_parseopt_error (po,
_("option '--%s' requires an argument"),
long_opt);
else
- parse_error (po,
+ mu_parseopt_error (po,
_("option '-%c' requires an argument"),
po->po_chr);
po->po_opterr = po->po_ind;
@@ -428,7 +428,7 @@ parse (struct mu_parseopt *po)
&& po->po_cur[0]
&& !(po->po_flags & MU_OPTION_ARG_OPTIONAL))
{
- parse_error (po,
+ mu_parseopt_error (po,
_("option '--%s' doesn't allow an argument"),
long_opt);
po->po_opterr = po->po_ind;
@@ -661,9 +661,9 @@ mu_option_set_value (struct mu_parseopt *po, struct mu_option *opt,
errtext = mu_strerror (rc);
if (opt->opt_long)
- parse_error (po, "--%s: %s", opt->opt_long, errtext);
+ mu_parseopt_error (po, "--%s: %s", opt->opt_long, errtext);
else
- parse_error (po, "-%c: %s", opt->opt_short, errtext);
+ mu_parseopt_error (po, "-%c: %s", opt->opt_short, errtext);
free (errmsg);
if (!(po->po_flags & MU_PARSEOPT_NO_ERREXIT))
diff --git a/libmailutils/opt/progname.c b/libmailutils/opt/progname.c
index 19d430e..0d19773 100644
--- a/libmailutils/opt/progname.c
+++ b/libmailutils/opt/progname.c
@@ -22,16 +22,16 @@
#include <mailutils/alloc.h>
#include <mailutils/opt.h>
-char *mu_progname;
-char *mu_absprogname;
+char *mu_program_name;
+char *mu_full_program_name;
void
-mu_set_progname (char const *arg)
+mu_set_program_name (const char *arg)
{
char *p;
- free (mu_absprogname);
- mu_absprogname = mu_strdup (arg);
+ free (mu_full_program_name);
+ mu_full_program_name = mu_strdup (arg);
p = strrchr (arg, '/');
if (p)
@@ -40,6 +40,6 @@ mu_set_progname (char const *arg)
p = (char*) arg;
if (strlen (p) > 3 && memcmp (p, "lt-", 3) == 0)
p += 3;
- free (mu_progname);
- mu_progname = mu_strdup (p);
+ free (mu_program_name);
+ mu_program_name = mu_strdup (p);
}
diff --git a/libmailutils/tests/.gitignore b/libmailutils/tests/.gitignore
index 51e4e68..62b06b4 100644
--- a/libmailutils/tests/.gitignore
+++ b/libmailutils/tests/.gitignore
@@ -27,6 +27,7 @@ strftime
strin
strout
strtoc
+tcli
tempfile
url-comp
url-parse
diff --git a/libmailutils/tests/Makefile.am b/libmailutils/tests/Makefile.am
index 349eb24..728eaec 100644
--- a/libmailutils/tests/Makefile.am
+++ b/libmailutils/tests/Makefile.am
@@ -64,6 +64,7 @@ noinst_PROGRAMS = \
strout\
strtoc\
tempfile\
+ tcli\
url-comp\
url-parse\
wicket\
diff --git a/libmailutils/tests/parseopt.c b/libmailutils/tests/parseopt.c
index bef57ee..f25aabf 100644
--- a/libmailutils/tests/parseopt.c
+++ b/libmailutils/tests/parseopt.c
@@ -64,7 +64,7 @@ struct mu_option group_b[] = {
struct mu_option *optv[] = { group_a, group_b, NULL };
static void
-version_func (FILE *fp)
+version_hook (struct mu_parseopt *po, FILE *fp)
{
fputs ("version hook called\n", fp);
}
@@ -144,7 +144,7 @@ main (int argc, char *argv[])
}
}
if (flags & MU_PARSEOPT_VERSION_HOOK)
- po.po_version_hook = version_func;
+ po.po_version_hook = version_hook;
}
rc = mu_parseopt (&po, argc, argv, optv, flags);
diff --git a/libmailutils/tests/parseopt17.at b/libmailutils/tests/parseopt17.at
index 2823e0a..b57a070 100644
--- a/libmailutils/tests/parseopt17.at
+++ b/libmailutils/tests/parseopt17.at
@@ -35,4 +35,24 @@ argv:
2: follow
3: options
])
+
+AT_CHECK([
+PARSEOPT_DEFAULT
+parseopt --file=file more arguments follow -x -o options
+],
+[0],
+[rc=0
+file_name=file
+opt_value=(null)
+x_option=1
+a_option=0
+find_value=(null)
+d_option=0
+jobs=0
+argv:
+0: more
+1: arguments
+2: follow
+3: options
+])
AT_CLEANUP
diff --git a/libmailutils/tests/parseopt_help05.at b/libmailutils/tests/parseopt_help05.at
index 9a0c1ed..4fe6960 100644
--- a/libmailutils/tests/parseopt_help05.at
+++ b/libmailutils/tests/parseopt_help05.at
@@ -18,7 +18,7 @@ AT_SETUP([MU_PARSEOPT_BUG_ADDRESS])
AT_KEYWORDS([parseopt parseopt_help parseopt_help05])
AT_CHECK([
PARSEOPT_DEFAULT
-MU_PARSEOPT_BUG_ADDRESS='<gray@gnu.org>' parseopt --help
+MU_PARSEOPT_BUG_ADDRESS='gray@gnu.org' parseopt --help
],
[0],
[Usage: parseopt [[OPTION]]...
diff --git a/libmailutils/tests/parseopt_help07.at b/libmailutils/tests/parseopt_help07.at
index 265acb4..91c3c19 100644
--- a/libmailutils/tests/parseopt_help07.at
+++ b/libmailutils/tests/parseopt_help07.at
@@ -20,7 +20,7 @@ AT_CHECK([
PARSEOPT_DEFAULT
MU_PARSEOPT_PROG_DOC="Tests option parsing"\
MU_PARSEOPT_PROG_ARGS="SOME MORE ARGS"\
- MU_PARSEOPT_BUG_ADDRESS='<gray@gnu.org>'\
+ MU_PARSEOPT_BUG_ADDRESS='gray@gnu.org'\
MU_PARSEOPT_PACKAGE_NAME='GNU Mailutils'\
MU_PARSEOPT_PACKAGE_URL='http://mailutils.org'\
MU_PARSEOPT_EXTRA_INFO='General help using GNU software: <http://www.gnu.org/gethelp/>'\
diff --git a/libmailutils/tests/tcli.c b/libmailutils/tests/tcli.c
new file mode 100644
index 0000000..9a640d5
--- a/dev/null
+++ b/libmailutils/tests/tcli.c
@@ -0,0 +1,75 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 2016 Free Software Foundation, Inc.
+
+ GNU Mailutils is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ GNU Mailutils is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <mailutils/mailutils.h>
+#include <mailutils/cli.h>
+
+int dtrt_option;
+
+struct mu_option group_a[] = {
+ { "dtrt", 'd', "VALUE", MU_OPTION_DEFAULT,
+ "do the right thing",
+ mu_c_int, &dtrt_option },
+ MU_OPTION_END
+};
+
+struct mu_option *options[] = { group_a, NULL };
+
+static struct mu_cfg_param config[] = {
+ { "do-the-right-thing", mu_c_int, &dtrt_option, 0, NULL,
+ "do the right thing" },
+ { NULL }
+};
+
+struct mu_cli_setup cli = {
+ options,
+ config,
+ "Tests standard command line interface",
+ "ARGUMENTS"
+};
+
+static char **
+getcapa (void)
+{
+ struct mu_wordsplit ws;
+ char *p;
+
+ p = getenv ("MU_CLI_CAPA");
+ if (!p)
+ return NULL;
+ ws.ws_delim = ",";
+ if (mu_wordsplit (p, &ws,
+ MU_WRDSF_DELIM | MU_WRDSF_NOVAR | MU_WRDSF_NOCMD
+ | MU_WRDSF_WS | MU_WRDSF_SHOWERR))
+ exit (1);
+ return ws.ws_wordv;
+}
+
+int
+main (int argc, char **argv)
+{
+ int i;
+
+ mu_cli (argc, argv, &cli, getcapa (), NULL, &argc, &argv);
+ printf ("DTRT=%d\n", dtrt_option);
+ printf ("%d arguments:\n", argc);
+ for (i = 0; i < argc; i++)
+ printf ("%d: %s\n", i, argv[i]);
+ return 0;
+}
diff --git a/libmu_sieve/conf.c b/libmu_sieve/conf.c
index 0f9283a..15b33aa 100644
--- a/libmu_sieve/conf.c
+++ b/libmu_sieve/conf.c
@@ -18,23 +18,28 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
-#endif
+#endif
+#include <stdlib.h>
#include <sieve-priv.h>
#include <string.h>
+#include <mailutils/cli.h>
mu_list_t mu_sieve_include_path = NULL;
mu_list_t mu_sieve_library_path = NULL;
mu_list_t mu_sieve_library_path_prefix = NULL;
-
mu_debug_handle_t mu_sieve_debug_handle;
+//FIXME: provide definition (from gocs.h)
+static struct mu_gocs_sieve sieve_settings;
+
void
-mu_sieve_debug_init ()
+mu_sieve_debug_init (void)
{
if (!mu_sieve_debug_handle)
mu_sieve_debug_handle = mu_debug_register_category ("sieve");
}
+/*FIXME: REMOVE BEGIN */
static int
_path_append (void *item, void *data)
{
@@ -73,7 +78,7 @@ mu_sieve_module_init (enum mu_gocs_op op, void *data)
mu_list_destroy (&mu_sieve_library_path_prefix);
}
mu_list_foreach (p->library_path_prefix, _path_append,
- &mu_sieve_library_path_prefix);
+ &mu_sieve_library_path_prefix);
mu_list_foreach (p->library_path, _path_append, &mu_sieve_library_path);
mu_list_destroy (&p->library_path);
mu_list_destroy (&p->library_path_prefix);
@@ -81,3 +86,161 @@ mu_sieve_module_init (enum mu_gocs_op op, void *data)
mu_sieve_debug_init ();
return 0;
}
+/* FIXME: REMOVE END */
+
+static int
+cb_clear_library_path (void *data, mu_config_value_t *val)
+{
+ int flag;
+
+ if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
+ return 1;
+ if (mu_str_to_c (val->v.string, mu_c_bool, &flag, NULL))
+ {
+ mu_error (_("not a boolean"));
+ return 1;
+ }
+ if (flag)
+ sieve_settings.clearflags |= MU_SIEVE_CLEAR_LIBRARY_PATH;
+ return 0;
+}
+
+static int
+cb_clear_include_path (void *data, mu_config_value_t *val)
+{
+ int flag;
+
+ if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
+ return 1;
+ if (mu_str_to_c (val->v.string, mu_c_bool, &flag, NULL))
+ {
+ mu_error (_("not a boolean"));
+ return 1;
+ }
+ if (flag)
+ sieve_settings.clearflags |= MU_SIEVE_CLEAR_INCLUDE_PATH;
+ return 0;
+}
+
+static int
+_add_path (const char *arg, void *data)
+{
+ mu_list_t *plist = data;
+
+ if (!*plist)
+ {
+ int rc = mu_list_create (plist);
+ if (rc)
+ {
+ mu_error (_("cannot create list: %s"), mu_strerror (rc));
+ exit (1);
+ }
+ mu_list_set_destroy_item (*plist, mu_list_free_item);
+ }
+ return mu_string_split (arg, ":", *plist);
+}
+
+static int
+cb_include_path (void *data, mu_config_value_t *val)
+{
+ return mu_cfg_string_value_cb (val, _add_path,
+ &sieve_settings.include_path);
+}
+
+static int
+cb_library_path (void *data, mu_config_value_t *val)
+{
+ return mu_cfg_string_value_cb (val, _add_path,
+ &sieve_settings.library_path);
+}
+
+static int
+cb_library_path_prefix (void *data, mu_config_value_t *val)
+{
+ return mu_cfg_string_value_cb (val, _add_path,
+ &sieve_settings.library_path_prefix);
+}
+
+static struct mu_cfg_param mu_sieve_param[] = {
+ { "clear-library-path", mu_cfg_callback, NULL, 0, cb_clear_library_path,
+ N_("Clear library search path.") },
+ { "clear-include-path", mu_cfg_callback, NULL, 0, cb_clear_include_path,
+ N_("Clear include search path.") },
+ { "library-path", mu_cfg_callback, NULL, 0, cb_library_path,
+ N_("Add directories to the library search path. Argument is a "
+ "colon-separated list of directories."),
+ N_("list") },
+ { "library-path-prefix", mu_cfg_callback, NULL, 0, cb_library_path_prefix,
+ N_("Add directories to the beginning of the library search path. "
+ "Argument is a colon-separated list of directories."),
+ N_("list") },
+ { "include-path", mu_cfg_callback, NULL, 0, cb_include_path,
+ N_("Add directories to the include search path. Argument is a "
+ "colon-separated list of directories."),
+ N_("list") },
+ { NULL }
+};
+
+/* New capability support */
+static void
+cli_includedir (struct mu_parseopt *po, struct mu_option *opt,
+ char const *arg)
+{
+ _add_path (arg, &sieve_settings.include_path);
+}
+
+static void
+cli_libdir (struct mu_parseopt *po, struct mu_option *opt, char const *arg)
+{
+ _add_path (arg, &sieve_settings.library_path);
+}
+
+static void
+cli_libdir_prefix (struct mu_parseopt *po, struct mu_option *opt,
+ char const *arg)
+{
+ _add_path (arg, &sieve_settings.library_path_prefix);
+}
+
+static void
+cli_clear_include_path (struct mu_parseopt *po, struct mu_option *opt,
+ char const *arg)
+{
+ sieve_settings.clearflags |= MU_SIEVE_CLEAR_INCLUDE_PATH;
+}
+
+static void
+cli_clear_library_path (struct mu_parseopt *po, struct mu_option *opt,
+ char const *arg)
+{
+ sieve_settings.clearflags |= MU_SIEVE_CLEAR_LIBRARY_PATH;
+}
+
+static struct mu_option sieve_option[] = {
+ MU_OPTION_GROUP (N_("Sieve options")),
+ { "includedir", 'I', N_("DIR"), MU_OPTION_DEFAULT,
+ N_("append DIR to the list of directories searched for include files"),
+ mu_c_string, NULL, cli_includedir },
+ { "libdir", 'L', N_("DIR"), MU_OPTION_DEFAULT,
+ N_("append DIR to the list of directories searched for library files"),
+ mu_c_string, NULL, cli_libdir },
+ { "libdir-prefix", 0, N_("DIR"), MU_OPTION_DEFAULT,
+ N_("add DIR to the beginning of the list of directories searched for "
+ "library files"),
+ mu_c_string, NULL, cli_libdir_prefix },
+ { "clear-include-path", 0, NULL, MU_OPTION_DEFAULT,
+ N_("clear Sieve include path"),
+ mu_c_string, NULL, cli_clear_include_path },
+ { "clear-library-path", 0, NULL, MU_OPTION_DEFAULT,
+ N_("clear Sieve library path"),
+ mu_c_string, NULL, cli_clear_library_path },
+ { "clearpath", 0, NULL, MU_OPTION_ALIAS },
+ MU_OPTION_END
+};
+
+struct mu_cli_capa mu_cli_capa_sieve = {
+ "sieve",
+ sieve_option,
+ mu_sieve_param,
+ NULL, NULL
+};

Return to:

Send suggestions and report system problems to the System administrator.