Commit bc73fc65 bc73fc65600b6021dfe7a9fa1fba7e9b823993e2 by Sergey Poznyakoff

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
1 parent 6e814733
......@@ -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
......
......@@ -36,6 +36,7 @@ pkginclude_HEADERS = \
cctype.h\
cfg.h\
cidr.h\
cli.h\
cstr.h\
datetime.h\
daemon.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
......
/* 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
......@@ -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
......
......@@ -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);
......
......@@ -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);
......
......@@ -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
......
......@@ -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\
......
......@@ -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)
......
......@@ -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;
}
......
......@@ -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;
}
......
......@@ -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;
}
......
# 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
/* 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);
}
/* 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);
}
/* 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]);
}
......@@ -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 ()
{
......
......@@ -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;
......
......@@ -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))
......
......@@ -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);
}
......
......@@ -27,6 +27,7 @@ strftime
strin
strout
strtoc
tcli
tempfile
url-comp
url-parse
......
......@@ -64,6 +64,7 @@ noinst_PROGRAMS = \
strout\
strtoc\
tempfile\
tcli\
url-comp\
url-parse\
wicket\
......
......@@ -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);
......
......@@ -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
......
......@@ -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]]...
......
......@@ -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/>'\
......
/* 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;
}
......@@ -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
};
......