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
Showing
29 changed files
with
1384 additions
and
74 deletions
... | @@ -1506,6 +1506,7 @@ AC_CONFIG_FILES([ | ... | @@ -1506,6 +1506,7 @@ AC_CONFIG_FILES([ |
1506 | libmailutils/address/Makefile | 1506 | libmailutils/address/Makefile |
1507 | libmailutils/sockaddr/Makefile | 1507 | libmailutils/sockaddr/Makefile |
1508 | libmailutils/cidr/Makefile | 1508 | libmailutils/cidr/Makefile |
1509 | libmailutils/cli/Makefile | ||
1509 | libmailutils/cfg/Makefile | 1510 | libmailutils/cfg/Makefile |
1510 | libmailutils/datetime/Makefile | 1511 | libmailutils/datetime/Makefile |
1511 | libmailutils/diag/Makefile | 1512 | libmailutils/diag/Makefile | ... | ... |
... | @@ -79,6 +79,8 @@ struct mu_cfg_parse_hints | ... | @@ -79,6 +79,8 @@ struct mu_cfg_parse_hints |
79 | char *site_rcfile; | 79 | char *site_rcfile; |
80 | char *custom_rcfile; | 80 | char *custom_rcfile; |
81 | char *program; | 81 | char *program; |
82 | struct mu_cfg_tree *append_tree; | ||
83 | void *data; | ||
82 | }; | 84 | }; |
83 | 85 | ||
84 | struct mu_cfg_tree | 86 | struct mu_cfg_tree |
... | @@ -238,6 +240,7 @@ int mu_config_register_plain_section (const char *parent_path, | ... | @@ -238,6 +240,7 @@ int mu_config_register_plain_section (const char *parent_path, |
238 | #define MU_CFG_FMT_LOCUS 0x080 | 240 | #define MU_CFG_FMT_LOCUS 0x080 |
239 | #define MU_CFG_FMT_VALUE_ONLY 0x100 | 241 | #define MU_CFG_FMT_VALUE_ONLY 0x100 |
240 | #define MU_CFG_FMT_PARAM_PATH 0x200 | 242 | #define MU_CFG_FMT_PARAM_PATH 0x200 |
243 | #define MU_PARSE_CONFIG_LINT 0x400 | ||
241 | 244 | ||
242 | #ifdef MU_CFG_COMPATIBILITY | 245 | #ifdef MU_CFG_COMPATIBILITY |
243 | # define MU_CFG_DEPRECATED | 246 | # define MU_CFG_DEPRECATED | ... | ... |
include/mailutils/cli.h
0 → 100644
1 | /* opt.h -- general-purpose command line option parser | ||
2 | Copyright (C) 2016 Free Software Foundation, Inc. | ||
3 | |||
4 | GNU Mailutils is free software; you can redistribute it and/or | ||
5 | modify it under the terms of the GNU General Public License as | ||
6 | published by the Free Software Foundation; either version 3, or (at | ||
7 | your option) any later version. | ||
8 | |||
9 | GNU Mailutils is distributed in the hope that it will be useful, but | ||
10 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License | ||
15 | along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. | ||
16 | */ | ||
17 | |||
18 | #ifndef _MAILUTILS_CLI_H | ||
19 | #define _MAILUTILS_CLI_H | ||
20 | #include <stdio.h> | ||
21 | #include <mailutils/types.h> | ||
22 | #include <mailutils/cfg.h> | ||
23 | #include <mailutils/opt.h> | ||
24 | |||
25 | typedef void (*mu_cli_capa_commit_fp) (void *); | ||
26 | |||
27 | struct mu_cli_capa | ||
28 | { | ||
29 | char *name; | ||
30 | struct mu_option *opt; | ||
31 | struct mu_cfg_param *cfg; | ||
32 | mu_cfg_section_fp parser; | ||
33 | mu_cli_capa_commit_fp commit; | ||
34 | }; | ||
35 | |||
36 | void mu_cli_capa_init (void); | ||
37 | void mu_cli_capa_register (struct mu_cli_capa *capa); | ||
38 | void mu_cli_capa_apply (char const *name, mu_list_t opts, mu_list_t commits); | ||
39 | |||
40 | struct mu_cli_setup | ||
41 | { | ||
42 | struct mu_option **optv; | ||
43 | struct mu_cfg_param *cfg; | ||
44 | char *prog_doc; | ||
45 | char *prog_args; | ||
46 | }; | ||
47 | |||
48 | void mu_version_func (struct mu_parseopt *po, FILE *stream); | ||
49 | void mu_cli (int argc, char **argv, struct mu_cli_setup *setup, | ||
50 | char **capa, void *data, | ||
51 | int *ret_argc, char ***ret_argv); | ||
52 | |||
53 | char *mu_site_config_file (void); | ||
54 | |||
55 | #endif |
... | @@ -29,8 +29,8 @@ | ... | @@ -29,8 +29,8 @@ |
29 | extern "C" { | 29 | extern "C" { |
30 | #endif | 30 | #endif |
31 | 31 | ||
32 | extern const char *mu_program_name; | 32 | extern char *mu_program_name; |
33 | extern const char *mu_full_program_name; | 33 | extern char *mu_full_program_name; |
34 | 34 | ||
35 | #define MU_DIAG_EMERG MU_LOG_EMERG | 35 | #define MU_DIAG_EMERG MU_LOG_EMERG |
36 | #define MU_DIAG_ALERT MU_LOG_ALERT | 36 | #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) | ... | @@ -103,7 +103,7 @@ extern int mu_locker_set_default_flags (int flags, enum mu_locker_set_mode mode) |
103 | extern void mu_locker_set_default_retry_timeout (time_t to); | 103 | extern void mu_locker_set_default_retry_timeout (time_t to); |
104 | extern void mu_locker_set_default_retry_count (size_t n); | 104 | extern void mu_locker_set_default_retry_count (size_t n); |
105 | extern void mu_locker_set_default_expire_timeout (time_t t); | 105 | extern void mu_locker_set_default_expire_timeout (time_t t); |
106 | extern int mu_locker_set_default_external_program (char *path); | 106 | extern int mu_locker_set_default_external_program (char const *path); |
107 | 107 | ||
108 | /* A flags of 0 means that the default will be used. */ | 108 | /* A flags of 0 means that the default will be used. */ |
109 | extern int mu_locker_create (mu_locker_t *, const char *filename, int flags); | 109 | extern int mu_locker_create (mu_locker_t *, const char *filename, int flags); | ... | ... |
... | @@ -23,10 +23,10 @@ | ... | @@ -23,10 +23,10 @@ |
23 | #include <mailutils/util.h> | 23 | #include <mailutils/util.h> |
24 | #include <mailutils/cctype.h> | 24 | #include <mailutils/cctype.h> |
25 | 25 | ||
26 | extern char *mu_progname; | 26 | extern char *mu_program_name; |
27 | extern char *mu_absprogname; | 27 | extern char *mu_full_program_name; |
28 | 28 | ||
29 | void mu_set_progname (char const *arg); | 29 | void mu_set_program_name (char const *arg); |
30 | 30 | ||
31 | #define MU_OPTION_DEFAULT 0 | 31 | #define MU_OPTION_DEFAULT 0 |
32 | #define MU_OPTION_ARG_OPTIONAL 0x01 | 32 | #define MU_OPTION_ARG_OPTIONAL 0x01 |
... | @@ -118,7 +118,7 @@ struct mu_parseopt | ... | @@ -118,7 +118,7 @@ struct mu_parseopt |
118 | struct mu_option **po_optv; /* Array of ptrs to option structures */ | 118 | struct mu_option **po_optv; /* Array of ptrs to option structures */ |
119 | int po_flags; | 119 | int po_flags; |
120 | 120 | ||
121 | char *po_data; /* Call-specific data */ | 121 | void *po_data; /* Call-specific data */ |
122 | 122 | ||
123 | int po_exit_error; /* Exit on error with this code */ | 123 | int po_exit_error; /* Exit on error with this code */ |
124 | 124 | ||
... | @@ -131,8 +131,9 @@ struct mu_parseopt | ... | @@ -131,8 +131,9 @@ struct mu_parseopt |
131 | char const *po_package_url; | 131 | char const *po_package_url; |
132 | char const *po_extra_info; | 132 | char const *po_extra_info; |
133 | 133 | ||
134 | void (*po_help_hook) (FILE *stream); /* FIXME: should take mu_stream_t ?*/ | 134 | /* FIXME: should these take mu_stream_t ?*/ |
135 | void (*po_version_hook) (FILE *stream); | 135 | void (*po_help_hook) (struct mu_parseopt *po, FILE *stream); |
136 | void (*po_version_hook) (struct mu_parseopt *po, FILE *stream); | ||
136 | 137 | ||
137 | /* Output data */ | 138 | /* Output data */ |
138 | int po_ind; /* Index of the next option */ | 139 | int po_ind; /* Index of the next option */ |
... | @@ -162,6 +163,7 @@ struct mu_parseopt | ... | @@ -162,6 +163,7 @@ struct mu_parseopt |
162 | int mu_parseopt (struct mu_parseopt *p, | 163 | int mu_parseopt (struct mu_parseopt *p, |
163 | int argc, char **argv, struct mu_option **optv, | 164 | int argc, char **argv, struct mu_option **optv, |
164 | int flags); | 165 | int flags); |
166 | void mu_parseopt_error (struct mu_parseopt *po, char const *fmt, ...); | ||
165 | 167 | ||
166 | int mu_parseopt_apply (struct mu_parseopt *p); | 168 | int mu_parseopt_apply (struct mu_parseopt *p); |
167 | void mu_parseopt_free (struct mu_parseopt *p); | 169 | void mu_parseopt_free (struct mu_parseopt *p); | ... | ... |
... | @@ -28,7 +28,7 @@ extern mu_stream_t mu_strin; | ... | @@ -28,7 +28,7 @@ extern mu_stream_t mu_strin; |
28 | extern mu_stream_t mu_strout; | 28 | extern mu_stream_t mu_strout; |
29 | extern mu_stream_t mu_strerr; | 29 | extern mu_stream_t mu_strerr; |
30 | 30 | ||
31 | extern const char *mu_program_name; | 31 | extern char *mu_program_name; |
32 | 32 | ||
33 | #define MU_STRERR_STDERR 0 | 33 | #define MU_STRERR_STDERR 0 |
34 | #define MU_STRERR_SYSLOG 1 | 34 | #define MU_STRERR_SYSLOG 1 | ... | ... |
... | @@ -17,7 +17,7 @@ | ... | @@ -17,7 +17,7 @@ |
17 | # <http://www.gnu.org/licenses/>. | 17 | # <http://www.gnu.org/licenses/>. |
18 | 18 | ||
19 | SUBDIRS = \ | 19 | SUBDIRS = \ |
20 | auth base address list sockaddr cidr cfg diag\ | 20 | auth base address list sockaddr cidr cfg cli diag\ |
21 | filter mailbox mailer mime msgset opt server string stream stdstream\ | 21 | filter mailbox mailer mime msgset opt server string stream stdstream\ |
22 | property url imapio datetime . tests | 22 | property url imapio datetime . tests |
23 | 23 | ||
... | @@ -33,6 +33,7 @@ libmailutils_la_LIBADD = \ | ... | @@ -33,6 +33,7 @@ libmailutils_la_LIBADD = \ |
33 | sockaddr/libsockaddr.la\ | 33 | sockaddr/libsockaddr.la\ |
34 | cidr/libcidr.la\ | 34 | cidr/libcidr.la\ |
35 | cfg/libcfg.la\ | 35 | cfg/libcfg.la\ |
36 | cli/libcli.la\ | ||
36 | datetime/libdatetime.la\ | 37 | datetime/libdatetime.la\ |
37 | diag/libdiag.la\ | 38 | diag/libdiag.la\ |
38 | filter/libfilter.la\ | 39 | filter/libfilter.la\ | ... | ... |
... | @@ -242,7 +242,7 @@ mu_locker_set_default_expire_timeout (time_t t) | ... | @@ -242,7 +242,7 @@ mu_locker_set_default_expire_timeout (time_t t) |
242 | } | 242 | } |
243 | 243 | ||
244 | int | 244 | int |
245 | mu_locker_set_default_external_program (char *path) | 245 | mu_locker_set_default_external_program (char const *path) |
246 | { | 246 | { |
247 | char *p = strdup (path); | 247 | char *p = strdup (path); |
248 | if (!p) | 248 | if (!p) | ... | ... |
... | @@ -463,7 +463,7 @@ mu_cfg_tree_reduce (mu_cfg_tree_t *parse_tree, | ... | @@ -463,7 +463,7 @@ mu_cfg_tree_reduce (mu_cfg_tree_t *parse_tree, |
463 | void *target_ptr) | 463 | void *target_ptr) |
464 | { | 464 | { |
465 | int rc = 0; | 465 | int rc = 0; |
466 | 466 | struct mu_cfg_cont *cont; | |
467 | if (!parse_tree) | 467 | if (!parse_tree) |
468 | return 0; | 468 | return 0; |
469 | if (hints && (hints->flags & MU_PARSE_CONFIG_DUMP)) | 469 | if (hints && (hints->flags & MU_PARSE_CONFIG_DUMP)) |
... | @@ -477,13 +477,9 @@ mu_cfg_tree_reduce (mu_cfg_tree_t *parse_tree, | ... | @@ -477,13 +477,9 @@ mu_cfg_tree_reduce (mu_cfg_tree_t *parse_tree, |
477 | mu_stream_destroy (&stream); | 477 | mu_stream_destroy (&stream); |
478 | } | 478 | } |
479 | 479 | ||
480 | if (root_container) | 480 | cont = mu_build_container (progparam); |
481 | { | 481 | rc = mu_cfg_scan_tree (parse_tree, &cont->v.section, target_ptr, NULL); |
482 | struct mu_cfg_cont *cont = mu_build_container (progparam); | ||
483 | rc = mu_cfg_scan_tree (parse_tree, &cont->v.section, target_ptr, | ||
484 | NULL); | ||
485 | mu_config_destroy_container (&cont); | 482 | mu_config_destroy_container (&cont); |
486 | } | ||
487 | 483 | ||
488 | return rc; | 484 | return rc; |
489 | } | 485 | } | ... | ... |
... | @@ -330,10 +330,16 @@ mu_cfg_parse_file (mu_cfg_tree_t **return_tree, const char *file, int flags) | ... | @@ -330,10 +330,16 @@ mu_cfg_parse_file (mu_cfg_tree_t **return_tree, const char *file, int flags) |
330 | int rc; | 330 | int rc; |
331 | char *full_name = mu_tilde_expansion (file, MU_HIERARCHY_DELIMITER, NULL); | 331 | char *full_name = mu_tilde_expansion (file, MU_HIERARCHY_DELIMITER, NULL); |
332 | 332 | ||
333 | if (flags & MU_PARSE_CONFIG_VERBOSE) | ||
334 | mu_diag_output (MU_DIAG_INFO, _("opening configuration file %s"), | ||
335 | full_name); | ||
333 | if (stat (full_name, &st)) | 336 | if (stat (full_name, &st)) |
334 | { | 337 | { |
335 | if (errno != ENOENT) | 338 | if (errno != ENOENT) |
336 | mu_error (_("cannot stat `%s': %s"), full_name, mu_strerror (errno)); | 339 | mu_error (_("cannot stat `%s': %s"), full_name, mu_strerror (errno)); |
340 | else if (flags & MU_PARSE_CONFIG_VERBOSE) | ||
341 | mu_diag_output (MU_DIAG_INFO, _("configuration file %s doesn't exist"), | ||
342 | full_name); | ||
337 | free (full_name); | 343 | free (full_name); |
338 | return ENOENT; | 344 | return ENOENT; |
339 | } | 345 | } | ... | ... |
... | @@ -1590,6 +1590,9 @@ mu_cfg_parse_config (mu_cfg_tree_t **ptree, struct mu_cfg_parse_hints *hints) | ... | @@ -1590,6 +1590,9 @@ mu_cfg_parse_config (mu_cfg_tree_t **ptree, struct mu_cfg_parse_hints *hints) |
1590 | } | 1590 | } |
1591 | } | 1591 | } |
1592 | 1592 | ||
1593 | if (hints->append_tree) | ||
1594 | mu_cfg_tree_union (&tree, &hints->append_tree); | ||
1595 | |||
1593 | *ptree = tree; | 1596 | *ptree = tree; |
1594 | return rc; | 1597 | return rc; |
1595 | } | 1598 | } | ... | ... |
libmailutils/cli/Makefile.am
0 → 100644
1 | # GNU Mailutils -- a suite of utilities for electronic mail | ||
2 | # Copyright (C) 2016 Free Software Foundation, Inc. | ||
3 | # | ||
4 | # This library is free software; you can redistribute it and/or | ||
5 | # modify it under the terms of the GNU Lesser General Public | ||
6 | # License as published by the Free Software Foundation; either | ||
7 | # version 3 of the License, or (at your option) any later version. | ||
8 | # | ||
9 | # This library is distributed in the hope that it will be useful, | ||
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | # Lesser General Public License for more details. | ||
13 | # | ||
14 | # You should have received a copy of the GNU Lesser General | ||
15 | # Public License along with this library. If not, see | ||
16 | # <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | noinst_LTLIBRARIES = libcli.la | ||
19 | |||
20 | libcli_la_SOURCES = \ | ||
21 | capa.c\ | ||
22 | cli.c\ | ||
23 | stdcapa.c | ||
24 | |||
25 | AM_CPPFLAGS = \ | ||
26 | @MU_LIB_COMMON_INCLUDES@ -I/libmailutils |
libmailutils/cli/capa.c
0 → 100644
1 | /* capa.c -- CLI capabilities for GNU Mailutils | ||
2 | Copyright (C) 2016 Free Software Foundation, Inc. | ||
3 | |||
4 | GNU Mailutils is free software; you can redistribute it and/or | ||
5 | modify it under the terms of the GNU General Public License as | ||
6 | published by the Free Software Foundation; either version 3, or (at | ||
7 | your option) any later version. | ||
8 | |||
9 | GNU Mailutils is distributed in the hope that it will be useful, but | ||
10 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License | ||
15 | along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. | ||
16 | */ | ||
17 | #ifdef HAVE_CONFIG_H | ||
18 | # include <config.h> | ||
19 | #endif | ||
20 | #include <stdlib.h> | ||
21 | #include <string.h> | ||
22 | #include <mailutils/cli.h> | ||
23 | #include <mailutils/list.h> | ||
24 | #include <mailutils/alloc.h> | ||
25 | #include <mailutils/nls.h> | ||
26 | |||
27 | static mu_list_t capa_list; | ||
28 | |||
29 | static void | ||
30 | capa_free (void *ptr) | ||
31 | { | ||
32 | struct mu_cli_capa *cp = ptr; | ||
33 | free (cp->name); | ||
34 | free (cp); | ||
35 | } | ||
36 | |||
37 | void | ||
38 | mu_cli_capa_register (struct mu_cli_capa *capa) | ||
39 | { | ||
40 | struct mu_cli_capa *cp = mu_alloc (sizeof (*cp)); | ||
41 | cp->name = mu_strdup (capa->name); | ||
42 | cp->opt = capa->opt; | ||
43 | cp->cfg = capa->cfg; | ||
44 | cp->parser = capa->parser; | ||
45 | cp->commit = capa->commit; | ||
46 | if (!capa_list) | ||
47 | { | ||
48 | mu_list_create (&capa_list); | ||
49 | mu_list_set_destroy_item (capa_list, capa_free); | ||
50 | } | ||
51 | mu_list_append (capa_list, cp); | ||
52 | } | ||
53 | |||
54 | struct capa_apply | ||
55 | { | ||
56 | char const *name; | ||
57 | mu_list_t opts; | ||
58 | mu_list_t commits; | ||
59 | int found; | ||
60 | }; | ||
61 | |||
62 | static int | ||
63 | capa_apply (void *item, void *data) | ||
64 | { | ||
65 | struct mu_cli_capa *cp = item; | ||
66 | struct capa_apply *ap = data; | ||
67 | |||
68 | if (strcmp (cp->name, ap->name) == 0) | ||
69 | { | ||
70 | ap->found = 1; | ||
71 | if (cp->opt) | ||
72 | mu_list_append (ap->opts, cp->opt); | ||
73 | if (cp->commit) | ||
74 | mu_list_append (ap->commits, cp->commit); | ||
75 | if (cp->parser || cp->cfg) | ||
76 | mu_config_root_register_section (NULL, cp->name, NULL, | ||
77 | cp->parser, cp->cfg); | ||
78 | } | ||
79 | return 0; | ||
80 | } | ||
81 | |||
82 | void | ||
83 | mu_cli_capa_apply (char const *name, mu_list_t opts, mu_list_t commits) | ||
84 | { | ||
85 | struct capa_apply app; | ||
86 | app.name = name; | ||
87 | app.opts = opts; | ||
88 | app.commits = commits; | ||
89 | app.found = 0; | ||
90 | mu_list_foreach (capa_list, capa_apply, &app); | ||
91 | if (!app.found) | ||
92 | mu_error (_("INTERNAL ERROR at %s:%d: unknown standard capability `%s'"), | ||
93 | __FILE__, __LINE__, name); | ||
94 | } | ||
95 | |||
96 |
libmailutils/cli/cli.c
0 → 100644
1 | /* cli.c -- Command line interface for GNU Mailutils | ||
2 | Copyright (C) 2016 Free Software Foundation, Inc. | ||
3 | |||
4 | GNU Mailutils is free software; you can redistribute it and/or | ||
5 | modify it under the terms of the GNU General Public License as | ||
6 | published by the Free Software Foundation; either version 3, or (at | ||
7 | your option) any later version. | ||
8 | |||
9 | GNU Mailutils is distributed in the hope that it will be useful, but | ||
10 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License | ||
15 | along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. | ||
16 | */ | ||
17 | #ifdef HAVE_CONFIG_H | ||
18 | # include <config.h> | ||
19 | #endif | ||
20 | #include <stdlib.h> | ||
21 | #include <sysexits.h> | ||
22 | #include <mailutils/cfg.h> | ||
23 | #include <mailutils/opt.h> | ||
24 | #include <mailutils/cli.h> | ||
25 | #include <mailutils/list.h> | ||
26 | #include <mailutils/alloc.h> | ||
27 | #include <mailutils/nls.h> | ||
28 | #include <mailutils/errno.h> | ||
29 | #include <mailutils/version.h> | ||
30 | #include <mailutils/stream.h> | ||
31 | #include <mailutils/stdstream.h> | ||
32 | #include <mailutils/io.h> | ||
33 | #include <mailutils/syslog.h> | ||
34 | |||
35 | #ifndef MU_SITE_CONFIG_FILE | ||
36 | # define MU_SITE_CONFIG_FILE SYSCONFDIR "/mailutils.rc" | ||
37 | #endif | ||
38 | |||
39 | char * | ||
40 | mu_site_config_file (void) | ||
41 | { | ||
42 | char *p = getenv ("MU_SITE_CONFIG_FILE"); | ||
43 | if (p) | ||
44 | return p; | ||
45 | return MU_SITE_CONFIG_FILE; | ||
46 | } | ||
47 | |||
48 | |||
49 | const char mu_version_copyright[] = | ||
50 | /* Do *not* mark this string for translation. %s is a copyright | ||
51 | symbol suitable for this locale, and %d is the copyright | ||
52 | year. */ | ||
53 | "Copyright %s 2007-2016 Free Software Foundation, inc."; | ||
54 | |||
55 | void | ||
56 | mu_version_func (struct mu_parseopt *po, FILE *stream) | ||
57 | { | ||
58 | #ifdef GIT_DESCRIBE | ||
59 | fprintf (stream, "%s (%s) %s [%s]\n", | ||
60 | mu_program_name, PACKAGE_NAME, PACKAGE_VERSION, GIT_DESCRIBE); | ||
61 | #else | ||
62 | fprintf (stream, "%s (%s) %s\n", mu_program_name, | ||
63 | PACKAGE_NAME, PACKAGE_VERSION); | ||
64 | #endif | ||
65 | /* TRANSLATORS: Translate "(C)" to the copyright symbol | ||
66 | (C-in-a-circle), if this symbol is available in the user's | ||
67 | locale. Otherwise, do not translate "(C)"; leave it as-is. */ | ||
68 | fprintf (stream, mu_version_copyright, _("(C)")); | ||
69 | fputs (_("\ | ||
70 | \n\ | ||
71 | 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\ | ||
72 | There is NO WARRANTY, to the extent permitted by law.\n\ | ||
73 | \n\ | ||
74 | "), | ||
75 | stream); | ||
76 | } | ||
77 | |||
78 | static char gnu_general_help_url[] = | ||
79 | N_("General help using GNU software: <http://www.gnu.org/gethelp/>"); | ||
80 | |||
81 | |||
82 | static void | ||
83 | change_progname (struct mu_parseopt *po, struct mu_option *opt, | ||
84 | char const *arg) | ||
85 | { | ||
86 | po->po_prog_name = mu_strdup (arg); | ||
87 | } | ||
88 | |||
89 | static void | ||
90 | no_user_config (struct mu_parseopt *po, struct mu_option *opt, | ||
91 | char const *arg) | ||
92 | { | ||
93 | struct mu_cfg_parse_hints *hints = po->po_data; | ||
94 | hints->flags &= ~MU_CFG_PARSE_PROGRAM; | ||
95 | } | ||
96 | |||
97 | static void | ||
98 | no_site_config (struct mu_parseopt *po, struct mu_option *opt, | ||
99 | char const *arg) | ||
100 | { | ||
101 | struct mu_cfg_parse_hints *hints = po->po_data; | ||
102 | hints->flags &= ~MU_CFG_PARSE_SITE_RCFILE; | ||
103 | } | ||
104 | |||
105 | static void | ||
106 | config_file (struct mu_parseopt *po, struct mu_option *opt, | ||
107 | char const *arg) | ||
108 | { | ||
109 | struct mu_cfg_parse_hints *hints = po->po_data; | ||
110 | hints->flags |= MU_CFG_PARSE_CUSTOM_RCFILE; | ||
111 | hints->custom_rcfile = mu_strdup (arg); | ||
112 | } | ||
113 | |||
114 | static void | ||
115 | config_verbose (struct mu_parseopt *po, struct mu_option *opt, | ||
116 | char const *arg) | ||
117 | { | ||
118 | struct mu_cfg_parse_hints *hints = po->po_data; | ||
119 | if (hints->flags & MU_PARSE_CONFIG_VERBOSE) | ||
120 | hints->flags |= MU_PARSE_CONFIG_DUMP; | ||
121 | else | ||
122 | hints->flags |= MU_PARSE_CONFIG_VERBOSE; | ||
123 | } | ||
124 | |||
125 | static void | ||
126 | config_lint (struct mu_parseopt *po, struct mu_option *opt, | ||
127 | char const *arg) | ||
128 | { | ||
129 | struct mu_cfg_parse_hints *hints = po->po_data; | ||
130 | hints->flags |= MU_PARSE_CONFIG_VERBOSE|MU_PARSE_CONFIG_LINT; | ||
131 | } | ||
132 | |||
133 | static void | ||
134 | param_set (struct mu_parseopt *po, struct mu_option *opt, char const *arg) | ||
135 | { | ||
136 | struct mu_cfg_parse_hints *hints = po->po_data; | ||
137 | mu_cfg_node_t *node; | ||
138 | int rc = mu_cfg_create_subtree (arg, &node); | ||
139 | if (rc) | ||
140 | mu_parseopt_error (po, "%s: cannot create node: %s", | ||
141 | arg, mu_strerror (rc)); | ||
142 | if (!hints->append_tree) | ||
143 | mu_cfg_tree_create (&hints->append_tree); | ||
144 | mu_cfg_tree_add_node (hints->append_tree, node); | ||
145 | } | ||
146 | |||
147 | struct mu_option mu_common_options[] = { | ||
148 | MU_OPTION_GROUP(N_("Common options")), | ||
149 | { "program-name", 0, N_("NAME"), MU_OPTION_IMMEDIATE|MU_OPTION_HIDDEN, | ||
150 | N_("set program name"), | ||
151 | mu_c_string, NULL, change_progname }, | ||
152 | |||
153 | { "no-user-config", 0, NULL, MU_OPTION_IMMEDIATE, | ||
154 | N_("do not load user configuration file"), | ||
155 | mu_c_string, NULL, no_user_config }, | ||
156 | { "no-user-rcfile", 0, NULL, MU_OPTION_ALIAS }, | ||
157 | |||
158 | { "no-site-config", 0, NULL, MU_OPTION_IMMEDIATE, | ||
159 | N_("do not load user configuration file"), | ||
160 | mu_c_string, NULL, no_site_config }, | ||
161 | { "no-site-rcfile", 0, NULL, MU_OPTION_ALIAS }, | ||
162 | |||
163 | { "config-file", 0, N_("FILE"), MU_OPTION_IMMEDIATE, | ||
164 | N_("load this configuration file"), | ||
165 | mu_c_string, NULL, config_file }, | ||
166 | { "rcfile", 0, NULL, MU_OPTION_ALIAS }, | ||
167 | |||
168 | { "config-verbose", 0, NULL, MU_OPTION_IMMEDIATE, | ||
169 | N_("verbosely log parsing of the configuration files"), | ||
170 | mu_c_string, NULL, config_verbose }, | ||
171 | { "rcfile-verbose", 0, NULL, MU_OPTION_ALIAS }, | ||
172 | |||
173 | { "config-lint", 0, NULL, MU_OPTION_IMMEDIATE, | ||
174 | N_("check configuration file syntax and exit"), | ||
175 | mu_c_string, NULL, config_lint }, | ||
176 | { "rcfile-lint", 0, NULL, MU_OPTION_ALIAS }, | ||
177 | |||
178 | { "set", 0, N_("PARAM=VALUE"), MU_OPTION_IMMEDIATE, | ||
179 | N_("set configuration parameter"), | ||
180 | mu_c_string, NULL, param_set }, | ||
181 | |||
182 | MU_OPTION_END | ||
183 | }; | ||
184 | |||
185 | static void | ||
186 | show_comp_defaults (struct mu_parseopt *po, struct mu_option *opt, | ||
187 | char const *unused) | ||
188 | { | ||
189 | mu_print_options (); | ||
190 | exit (0); | ||
191 | } | ||
192 | |||
193 | static void | ||
194 | show_config_help (struct mu_parseopt *po, struct mu_option *opt, | ||
195 | char const *unused) | ||
196 | { | ||
197 | struct mu_cfg_parse_hints *hints = po->po_data; | ||
198 | |||
199 | char *comment; | ||
200 | mu_stream_t stream; | ||
201 | struct mu_cfg_cont *cont; | ||
202 | static struct mu_cfg_param dummy_include_param[] = { | ||
203 | { "include", mu_c_string, NULL, 0, NULL, | ||
204 | N_("Include contents of the given file. If a directory is given, " | ||
205 | "include contents of the file <file>/<program>, where " | ||
206 | "<program> is the name of the program. This latter form is " | ||
207 | "allowed only in the site-wide configuration file."), | ||
208 | N_("file-or-directory") }, | ||
209 | { NULL } | ||
210 | }; | ||
211 | |||
212 | mu_stdio_stream_create (&stream, MU_STDOUT_FD, 0); | ||
213 | |||
214 | mu_asprintf (&comment, | ||
215 | "Configuration file structure for %s utility.", | ||
216 | po->po_prog_name); | ||
217 | mu_cfg_format_docstring (stream, comment, 0); | ||
218 | free (comment); | ||
219 | |||
220 | mu_asprintf (&comment, | ||
221 | "For use in global configuration file (%s), enclose it " | ||
222 | "in `program %s { ... };", | ||
223 | mu_site_config_file (), | ||
224 | po->po_prog_name); | ||
225 | mu_cfg_format_docstring (stream, comment, 0); | ||
226 | free (comment); | ||
227 | |||
228 | /* FIXME: %s should be replaced by the canonical utility name */ | ||
229 | mu_asprintf (&comment, "For more information, use `info %s'.", | ||
230 | po->po_prog_name); | ||
231 | mu_cfg_format_docstring (stream, comment, 0); | ||
232 | free (comment); | ||
233 | |||
234 | cont = mu_config_clone_root_container (); | ||
235 | mu_config_container_register_section (&cont, NULL, NULL, NULL, NULL, | ||
236 | dummy_include_param, NULL); | ||
237 | if (hints->data) | ||
238 | mu_config_container_register_section (&cont, NULL, NULL, NULL, NULL, | ||
239 | hints->data, NULL); | ||
240 | mu_cfg_format_container (stream, cont); | ||
241 | mu_config_destroy_container (&cont); | ||
242 | |||
243 | mu_stream_destroy (&stream); | ||
244 | exit (0); | ||
245 | } | ||
246 | |||
247 | struct mu_option mu_extra_help_options[] = { | ||
248 | MU_OPTION_GROUP (N_("Informational options")), | ||
249 | { "show-config-options", 0, NULL, MU_OPTION_IMMEDIATE, | ||
250 | N_("show compilation options"), | ||
251 | mu_c_string, NULL, show_comp_defaults }, | ||
252 | { "config-help", 0, NULL, MU_OPTION_IMMEDIATE, | ||
253 | N_("show configuration file summary"), | ||
254 | mu_c_string, NULL, show_config_help }, | ||
255 | MU_OPTION_END | ||
256 | }; | ||
257 | |||
258 | |||
259 | static int | ||
260 | add_opt_group (void *item, void *data) | ||
261 | { | ||
262 | struct mu_parseopt *po = data; | ||
263 | struct mu_option *opt = item; | ||
264 | po->po_optv[po->po_optc++] = opt; | ||
265 | return 0; | ||
266 | } | ||
267 | |||
268 | /* Build the list of option groups and configuration sections */ | ||
269 | static struct mu_option ** | ||
270 | init_options (char **capa, struct mu_cli_setup *setup, | ||
271 | mu_list_t *ret_comlist) | ||
272 | { | ||
273 | size_t i, s; | ||
274 | mu_list_t oplist; | ||
275 | struct mu_parseopt po; | ||
276 | |||
277 | mu_list_create (&oplist); | ||
278 | if (setup->optv) | ||
279 | { | ||
280 | for (i = 0; setup->optv[i]; i++) | ||
281 | mu_list_append (oplist, setup->optv[i]); | ||
282 | } | ||
283 | if (capa) | ||
284 | { | ||
285 | mu_list_t comlist; | ||
286 | mu_list_create (&comlist); | ||
287 | for (i = 0; capa[i]; i++) | ||
288 | mu_cli_capa_apply (capa[i], oplist, comlist); | ||
289 | *ret_comlist = comlist; | ||
290 | } | ||
291 | else | ||
292 | *ret_comlist = NULL; | ||
293 | |||
294 | mu_list_append (oplist, mu_common_options); | ||
295 | mu_list_append (oplist, mu_extra_help_options); | ||
296 | |||
297 | mu_list_count (oplist, &s); | ||
298 | |||
299 | po.po_optv = mu_calloc (s + 1, sizeof (po.po_optv[0])); | ||
300 | po.po_optc = 0; | ||
301 | mu_list_foreach (oplist, add_opt_group, &po); | ||
302 | if (po.po_optc != s) | ||
303 | abort (); | ||
304 | po.po_optv[po.po_optc] = NULL; | ||
305 | mu_list_destroy (&oplist); | ||
306 | return po.po_optv; | ||
307 | } | ||
308 | |||
309 | static int | ||
310 | run_commit (void *item, void *data) | ||
311 | { | ||
312 | mu_cli_capa_commit_fp commit = item; | ||
313 | commit (data); | ||
314 | return 0; | ||
315 | } | ||
316 | |||
317 | void | ||
318 | mu_cli (int argc, char **argv, struct mu_cli_setup *setup, char **capa, | ||
319 | void *data, | ||
320 | int *ret_argc, char ***ret_argv) | ||
321 | { | ||
322 | struct mu_parseopt po; | ||
323 | int flags = 0; | ||
324 | struct mu_cfg_tree *parse_tree = NULL; | ||
325 | struct mu_cfg_parse_hints hints; | ||
326 | struct mu_option **optv; | ||
327 | mu_list_t com_list; | ||
328 | |||
329 | /* Set program name */ | ||
330 | mu_set_program_name (argv[0]); | ||
331 | |||
332 | if (!mu_log_tag) | ||
333 | mu_log_tag = (char*)mu_program_name; | ||
334 | |||
335 | /* Initialize standard streams */ | ||
336 | mu_stdstream_setup (MU_STDSTREAM_RESET_NONE); | ||
337 | |||
338 | /* Initialize standard capabilities */ | ||
339 | mu_cli_capa_init (); | ||
340 | |||
341 | /* Initialize hints */ | ||
342 | memset (&hints, 0, sizeof (hints)); | ||
343 | hints.flags |= MU_CFG_PARSE_SITE_RCFILE; | ||
344 | hints.site_rcfile = mu_site_config_file (); | ||
345 | |||
346 | hints.flags |= MU_CFG_PARSE_PROGRAM; | ||
347 | hints.program = (char*) mu_program_name; | ||
348 | |||
349 | hints.data = setup->cfg; | ||
350 | |||
351 | /* Initialize po */ | ||
352 | if (setup->prog_doc) | ||
353 | { | ||
354 | po.po_prog_doc = setup->prog_doc; | ||
355 | flags |= MU_PARSEOPT_PROG_DOC; | ||
356 | } | ||
357 | |||
358 | if (setup->prog_args) | ||
359 | { | ||
360 | po.po_prog_args = setup->prog_args; | ||
361 | flags |= MU_PARSEOPT_PROG_ARGS; | ||
362 | } | ||
363 | |||
364 | po.po_package_name = PACKAGE_NAME; | ||
365 | flags |= MU_PARSEOPT_PACKAGE_NAME; | ||
366 | |||
367 | po.po_package_url = PACKAGE_URL; | ||
368 | flags |= MU_PARSEOPT_PACKAGE_URL; | ||
369 | |||
370 | po.po_bug_address = PACKAGE_BUGREPORT; | ||
371 | flags |= MU_PARSEOPT_BUG_ADDRESS; | ||
372 | |||
373 | po.po_extra_info = gnu_general_help_url; | ||
374 | flags |= MU_PARSEOPT_EXTRA_INFO; | ||
375 | |||
376 | po.po_version_hook = mu_version_func; | ||
377 | flags |= MU_PARSEOPT_VERSION_HOOK; | ||
378 | |||
379 | po.po_data = &hints; | ||
380 | flags |= MU_PARSEOPT_DATA; | ||
381 | |||
382 | po.po_exit_error = EX_USAGE; | ||
383 | |||
384 | optv = init_options (capa, setup, &com_list); | ||
385 | |||
386 | if (mu_parseopt (&po, argc, argv, optv, flags)) | ||
387 | exit (EX_USAGE); | ||
388 | |||
389 | argc -= po.po_arg_start; | ||
390 | argv += po.po_arg_start; | ||
391 | |||
392 | if (ret_argc) | ||
393 | { | ||
394 | *ret_argc = argc; | ||
395 | *ret_argv = argv; | ||
396 | } | ||
397 | else if (argc) | ||
398 | mu_parseopt_error (&po, "%s", _("unexpected arguments")); | ||
399 | |||
400 | if (mu_cfg_parse_config (&parse_tree, &hints)) | ||
401 | exit (EX_CONFIG); | ||
402 | |||
403 | if (mu_cfg_tree_reduce (parse_tree, &hints, setup->cfg, data)) | ||
404 | exit (EX_CONFIG); | ||
405 | |||
406 | if (mu_cfg_error_count) //FIXME | ||
407 | exit (EX_CONFIG); | ||
408 | |||
409 | mu_parseopt_apply (&po); | ||
410 | |||
411 | mu_list_foreach (com_list, run_commit, NULL); | ||
412 | mu_list_destroy (&com_list); | ||
413 | |||
414 | if (hints.flags & MU_PARSE_CONFIG_LINT) | ||
415 | exit (0); | ||
416 | |||
417 | mu_cfg_destroy_tree (&parse_tree); | ||
418 | free (optv); | ||
419 | mu_parseopt_free (&po); | ||
420 | } |
libmailutils/cli/stdcapa.c
0 → 100644
1 | /* stdcapa.c -- Standard CLI capabilities for GNU Mailutils | ||
2 | Copyright (C) 2016 Free Software Foundation, Inc. | ||
3 | |||
4 | GNU Mailutils is free software; you can redistribute it and/or | ||
5 | modify it under the terms of the GNU General Public License as | ||
6 | published by the Free Software Foundation; either version 3, or (at | ||
7 | your option) any later version. | ||
8 | |||
9 | GNU Mailutils is distributed in the hope that it will be useful, but | ||
10 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License | ||
15 | along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. | ||
16 | */ | ||
17 | #ifdef HAVE_CONFIG_H | ||
18 | # include <config.h> | ||
19 | #endif | ||
20 | #include <stdlib.h> | ||
21 | #include <mailutils/cli.h> | ||
22 | #include <mailutils/cfg.h> | ||
23 | #include <mailutils/nls.h> | ||
24 | #include <mailutils/syslog.h> | ||
25 | #include <mailutils/stdstream.h> | ||
26 | #include <mailutils/mailer.h> | ||
27 | #include <mailutils/errno.h> | ||
28 | #include <mailutils/mailbox.h> | ||
29 | #include <mailutils/registrar.h> | ||
30 | #include <mailutils/locker.h> | ||
31 | |||
32 | /* ************************************************************************* | ||
33 | * Logging section | ||
34 | * ************************************************************************* */ | ||
35 | static void | ||
36 | cli_log_facility (struct mu_parseopt *po, struct mu_option *opt, | ||
37 | char const *arg) | ||
38 | { | ||
39 | if (mu_string_to_syslog_facility (arg, &mu_log_facility)) | ||
40 | mu_parseopt_error (po, _("unknown syslog facility `%s'"), arg); | ||
41 | } | ||
42 | |||
43 | static int | ||
44 | cb_facility (void *data, mu_config_value_t *val) | ||
45 | { | ||
46 | if (mu_cfg_assert_value_type (val, MU_CFG_STRING)) | ||
47 | return 1; | ||
48 | |||
49 | if (mu_string_to_syslog_facility (val->v.string, &mu_log_facility)) | ||
50 | { | ||
51 | mu_error (_("unknown syslog facility `%s'"), val->v.string); | ||
52 | return 1; | ||
53 | } | ||
54 | return 0; | ||
55 | } | ||
56 | |||
57 | static int | ||
58 | cb_severity (void *data, mu_config_value_t *val) | ||
59 | { | ||
60 | unsigned n; | ||
61 | |||
62 | if (mu_cfg_assert_value_type (val, MU_CFG_STRING)) | ||
63 | return 1; | ||
64 | if (mu_severity_from_string (val->v.string, &n)) | ||
65 | { | ||
66 | mu_error (_("unknown severity `%s'"), val->v.string); | ||
67 | return 1; | ||
68 | } | ||
69 | mu_log_severity_threshold = n; | ||
70 | return 0; | ||
71 | } | ||
72 | |||
73 | static struct mu_cfg_param logging_cfg[] = { | ||
74 | { "syslog", mu_c_bool, &mu_log_syslog, 0, NULL, | ||
75 | N_("Send diagnostics to syslog.") }, | ||
76 | { "print-severity", mu_c_bool, &mu_log_print_severity, 0, NULL, | ||
77 | N_("Print message severity levels.") }, | ||
78 | { "severity", mu_cfg_callback, NULL, 0, cb_severity, | ||
79 | N_("Output only messages with a severity equal to or greater than " | ||
80 | "this one."), | ||
81 | N_("arg: string")}, | ||
82 | { "facility", mu_cfg_callback, NULL, 0, cb_facility, | ||
83 | N_("Set syslog facility. Arg is one of the following: user, daemon, " | ||
84 | "auth, authpriv, mail, cron, local0 through local7 (case-insensitive), " | ||
85 | "or a facility number."), | ||
86 | N_("arg: string") }, | ||
87 | { "session-id", mu_c_bool, &mu_log_session_id, 0, NULL, | ||
88 | N_("Log session ID") }, | ||
89 | { "tag", mu_c_string, &mu_log_tag, 0, NULL, | ||
90 | N_("Tag syslog messages with this string.") }, | ||
91 | { NULL } | ||
92 | }; | ||
93 | |||
94 | static struct mu_option logging_option[] = { | ||
95 | { "log-facility", 0, N_("FACILITY"), MU_OPTION_DEFAULT, | ||
96 | N_("output logs to syslog FACILITY"), | ||
97 | mu_c_int, &mu_log_facility, cli_log_facility }, | ||
98 | MU_OPTION_END | ||
99 | }; | ||
100 | |||
101 | static void | ||
102 | logging_commit (void *unused) | ||
103 | { | ||
104 | if (mu_log_syslog >= 0) | ||
105 | mu_stdstream_strerr_setup (mu_log_syslog ? | ||
106 | MU_STRERR_SYSLOG : MU_STRERR_STDERR); | ||
107 | } | ||
108 | |||
109 | /* ************************************************************************* | ||
110 | * Mailer | ||
111 | * ************************************************************************* */ | ||
112 | static void | ||
113 | cli_mailer (struct mu_parseopt *po, struct mu_option *opt, char const *arg) | ||
114 | { | ||
115 | int rc = mu_mailer_set_url_default (arg); | ||
116 | if (rc != 0) | ||
117 | mu_parseopt_error (po, _("invalid mailer URL `%s': %s"), | ||
118 | arg, mu_strerror (rc)); | ||
119 | } | ||
120 | |||
121 | static struct mu_option mailer_option[] = { | ||
122 | { "mailer", 'M', N_("MAILER"), MU_OPTION_DEFAULT, | ||
123 | N_("use specified URL as the default mailer"), | ||
124 | mu_c_string, NULL, cli_mailer }, | ||
125 | MU_OPTION_END | ||
126 | }; | ||
127 | |||
128 | static int | ||
129 | cb_mailer (void *data, mu_config_value_t *val) | ||
130 | { | ||
131 | int rc; | ||
132 | |||
133 | if (mu_cfg_assert_value_type (val, MU_CFG_STRING)) | ||
134 | return 1; | ||
135 | rc = mu_mailer_set_url_default (val->v.string); | ||
136 | if (rc != 0) | ||
137 | mu_error (_("%s: invalid mailer URL: %s"), | ||
138 | val->v.string, mu_strerror (rc)); | ||
139 | return rc; | ||
140 | } | ||
141 | |||
142 | static struct mu_cfg_param mailer_cfg[] = { | ||
143 | { "url", mu_cfg_callback, NULL, 0, cb_mailer, | ||
144 | N_("Use this URL as the default mailer"), | ||
145 | N_("url: string") }, | ||
146 | { NULL } | ||
147 | }; | ||
148 | |||
149 | /* ************************************************************************* | ||
150 | * Debugging | ||
151 | * ************************************************************************* */ | ||
152 | static void | ||
153 | cli_debug_level (struct mu_parseopt *po, struct mu_option *opt, | ||
154 | char const *arg) | ||
155 | { | ||
156 | mu_debug_clear_all (); | ||
157 | mu_debug_parse_spec (arg); | ||
158 | /* FIXME: Error handling */ | ||
159 | } | ||
160 | |||
161 | static struct mu_option debug_option[] = { | ||
162 | MU_OPTION_GROUP (N_("Global debugging settings")), | ||
163 | { "debug-level", 0, N_("LEVEL"), MU_OPTION_DEFAULT, | ||
164 | N_("set Mailutils debugging level"), | ||
165 | mu_c_string, NULL, cli_debug_level }, | ||
166 | { "debug-line-info", 0, NULL, MU_OPTION_DEFAULT, | ||
167 | N_("show source info with debugging messages"), | ||
168 | mu_c_bool, &mu_debug_line_info }, | ||
169 | MU_OPTION_END | ||
170 | }; | ||
171 | |||
172 | static int | ||
173 | cb_debug_level (void *data, mu_config_value_t *val) | ||
174 | { | ||
175 | if (mu_cfg_assert_value_type (val, MU_CFG_STRING)) | ||
176 | return 1; | ||
177 | mu_debug_parse_spec (val->v.string); | ||
178 | return 0; | ||
179 | } | ||
180 | |||
181 | static struct mu_cfg_param debug_cfg[] = { | ||
182 | { "level", mu_cfg_callback, NULL, 0, &cb_debug_level, | ||
183 | N_("Set Mailutils debugging level. Argument is a colon-separated list " | ||
184 | "of debugging specifications in the form:\n" | ||
185 | " <object: string>[[:]=<level: number>]."), | ||
186 | N_("arg: string") }, | ||
187 | { "line-info", mu_c_bool, &mu_debug_line_info, 0, NULL, | ||
188 | N_("Prefix debug messages with Mailutils source locations.") }, | ||
189 | { NULL } | ||
190 | }; | ||
191 | |||
192 | /* ************************************************************************* * | ||
193 | * Mailbox * | ||
194 | * ************************************************************************* */ | ||
195 | |||
196 | static int | ||
197 | cb_mail_spool (void *data, mu_config_value_t *val) | ||
198 | { | ||
199 | int rc; | ||
200 | if (mu_cfg_assert_value_type (val, MU_CFG_STRING)) | ||
201 | return 1; | ||
202 | rc = mu_set_mail_directory (val->v.string); | ||
203 | if (rc) | ||
204 | mu_error (_("cannot set mail directory name to `%s': %s"), | ||
205 | val->v.string, mu_strerror (rc)); | ||
206 | return rc; | ||
207 | } | ||
208 | |||
209 | static int | ||
210 | cb_mailbox_pattern (void *data, mu_config_value_t *val) | ||
211 | { | ||
212 | int rc; | ||
213 | if (mu_cfg_assert_value_type (val, MU_CFG_STRING)) | ||
214 | return 1; | ||
215 | |||
216 | rc = mu_set_mailbox_pattern (val->v.string); | ||
217 | if (rc) | ||
218 | mu_error (_("cannot set mailbox pattern to `%s': %s"), | ||
219 | val->v.string, mu_strerror (rc)); | ||
220 | return rc; | ||
221 | } | ||
222 | |||
223 | static int | ||
224 | cb_mailbox_type (void *data, mu_config_value_t *val) | ||
225 | { | ||
226 | if (mu_cfg_assert_value_type (val, MU_CFG_STRING)) | ||
227 | return 1; | ||
228 | if (mu_registrar_set_default_scheme (val->v.string)) | ||
229 | mu_error (_("invalid mailbox type: %s"), val->v.string); | ||
230 | return 0; | ||
231 | } | ||
232 | |||
233 | static int | ||
234 | cb_folder (void *data, mu_config_value_t *val) | ||
235 | { | ||
236 | if (mu_cfg_assert_value_type (val, MU_CFG_STRING)) | ||
237 | return 1; | ||
238 | mu_set_folder_directory (val->v.string); | ||
239 | return 0; | ||
240 | } | ||
241 | |||
242 | static struct mu_cfg_param mailbox_cfg[] = { | ||
243 | { "mail-spool", mu_cfg_callback, NULL, 0, cb_mail_spool, | ||
244 | N_("Use specified URL as a mailspool directory."), | ||
245 | N_("url: string") }, | ||
246 | { "mailbox-pattern", mu_cfg_callback, NULL, 0, cb_mailbox_pattern, | ||
247 | N_("Create mailbox URL using <pattern>."), | ||
248 | N_("pattern: string") }, | ||
249 | { "mailbox-type", mu_cfg_callback, NULL, 0, cb_mailbox_type, | ||
250 | N_("Default mailbox type."), | ||
251 | N_("protocol: string") }, | ||
252 | { "folder", mu_cfg_callback, NULL, 0, cb_folder, | ||
253 | N_("Default user mail folder"), | ||
254 | N_("dir: string") }, | ||
255 | { NULL } | ||
256 | }; | ||
257 | |||
258 | /* ************************************************************************* * | ||
259 | * Locking * | ||
260 | * ************************************************************************* */ | ||
261 | static int | ||
262 | cb_locker_flags (void *data, mu_config_value_t *val) | ||
263 | { | ||
264 | int flags = 0; | ||
265 | char const *s; | ||
266 | |||
267 | if (mu_cfg_assert_value_type (val, MU_CFG_STRING)) | ||
268 | return 1; | ||
269 | |||
270 | for (s = val->v.string; *s; s++) | ||
271 | { | ||
272 | switch (*s) | ||
273 | { | ||
274 | case 'E': | ||
275 | flags |= MU_LOCKER_EXTERNAL; | ||
276 | break; | ||
277 | |||
278 | case 'R': | ||
279 | flags |= MU_LOCKER_RETRY; | ||
280 | break; | ||
281 | |||
282 | case 'T': | ||
283 | flags |= MU_LOCKER_TIME; | ||
284 | break; | ||
285 | |||
286 | case 'P': | ||
287 | flags |= MU_LOCKER_PID; | ||
288 | break; | ||
289 | |||
290 | default: | ||
291 | mu_error (_("invalid lock flag `%c'"), *s); | ||
292 | } | ||
293 | } | ||
294 | mu_locker_set_default_flags (flags, mu_locker_assign); | ||
295 | return 0; | ||
296 | } | ||
297 | |||
298 | static int | ||
299 | cb_locker_retry_timeout (void *data, mu_config_value_t *val) | ||
300 | { | ||
301 | int rc; | ||
302 | time_t t; | ||
303 | char *errmsg; | ||
304 | |||
305 | if (mu_cfg_assert_value_type (val, MU_CFG_STRING)) | ||
306 | return 1; | ||
307 | rc = mu_str_to_c (val->v.string, mu_c_time, &t, &errmsg); | ||
308 | if (rc) | ||
309 | { | ||
310 | mu_error (_("conversion failed: %s"), errmsg ? errmsg : | ||
311 | mu_strerror (rc)); | ||
312 | free (errmsg); | ||
313 | } | ||
314 | else | ||
315 | { | ||
316 | mu_locker_set_default_retry_timeout (t); | ||
317 | mu_locker_set_default_flags (MU_LOCKER_RETRY, mu_locker_set_bit); | ||
318 | } | ||
319 | return 0; | ||
320 | } | ||
321 | |||
322 | static int | ||
323 | cb_locker_retry_count (void *data, mu_config_value_t *val) | ||
324 | { | ||
325 | int rc; | ||
326 | size_t n; | ||
327 | char *errmsg; | ||
328 | |||
329 | if (mu_cfg_assert_value_type (val, MU_CFG_STRING)) | ||
330 | return 1; | ||
331 | rc = mu_str_to_c (val->v.string, mu_c_size, &n, &errmsg); | ||
332 | if (rc) | ||
333 | { | ||
334 | mu_error (_("conversion failed: %s"), errmsg ? errmsg : | ||
335 | mu_strerror (rc)); | ||
336 | free (errmsg); | ||
337 | } | ||
338 | else | ||
339 | { | ||
340 | mu_locker_set_default_retry_count (n); | ||
341 | mu_locker_set_default_flags (MU_LOCKER_RETRY, mu_locker_set_bit); | ||
342 | } | ||
343 | return 0; | ||
344 | } | ||
345 | |||
346 | static int | ||
347 | cb_locker_expire_timeout (void *data, mu_config_value_t *val) | ||
348 | { | ||
349 | int rc; | ||
350 | time_t t; | ||
351 | char *errmsg; | ||
352 | |||
353 | if (mu_cfg_assert_value_type (val, MU_CFG_STRING)) | ||
354 | return 1; | ||
355 | rc = mu_str_to_c (val->v.string, mu_c_time, &t, &errmsg); | ||
356 | if (rc) | ||
357 | { | ||
358 | mu_error (_("conversion failed: %s"), errmsg ? errmsg : | ||
359 | mu_strerror (rc)); | ||
360 | free (errmsg); | ||
361 | } | ||
362 | else | ||
363 | { | ||
364 | mu_locker_set_default_expire_timeout (t); | ||
365 | mu_locker_set_default_flags (MU_LOCKER_EXTERNAL, mu_locker_set_bit); | ||
366 | } | ||
367 | return 0; | ||
368 | } | ||
369 | |||
370 | static int | ||
371 | cb_locker_external (void *data, mu_config_value_t *val) | ||
372 | { | ||
373 | if (mu_cfg_assert_value_type (val, MU_CFG_STRING)) | ||
374 | return 1; | ||
375 | mu_locker_set_default_external_program (val->v.string); | ||
376 | mu_locker_set_default_flags (MU_LOCKER_TIME, mu_locker_set_bit); | ||
377 | return 0; | ||
378 | } | ||
379 | |||
380 | static struct mu_cfg_param locking_cfg[] = { | ||
381 | /* FIXME: Flags are superfluous. */ | ||
382 | { "flags", mu_cfg_callback, NULL, 0, cb_locker_flags, | ||
383 | N_("Default locker flags (E=external, R=retry, T=time, P=pid)."), | ||
384 | N_("arg: string") }, | ||
385 | { "retry-timeout", mu_cfg_callback, NULL, 0, cb_locker_retry_timeout, | ||
386 | N_("Set timeout for acquiring the lock."), | ||
387 | N_("arg: interval")}, | ||
388 | { "retry-count", mu_cfg_callback, NULL, 0, cb_locker_retry_count, | ||
389 | N_("Set the maximum number of times to retry acquiring the lock."), | ||
390 | N_("arg: integer") }, | ||
391 | { "expire-timeout", mu_cfg_callback, NULL, 0, cb_locker_expire_timeout, | ||
392 | N_("Expire locks older than this amount of time."), | ||
393 | N_("arg: interval")}, | ||
394 | { "external-locker", mu_cfg_callback, NULL, 0, cb_locker_external, | ||
395 | N_("Use external locker program."), | ||
396 | N_("prog: string") }, | ||
397 | { NULL, } | ||
398 | }; | ||
399 | |||
400 | /* ************************************************************************* * | ||
401 | * Address * | ||
402 | * ************************************************************************* */ | ||
403 | static int | ||
404 | cb_email_addr (void *data, mu_config_value_t *val) | ||
405 | { | ||
406 | int rc; | ||
407 | |||
408 | if (mu_cfg_assert_value_type (val, MU_CFG_STRING)) | ||
409 | return 1; | ||
410 | |||
411 | rc = mu_set_user_email (val->v.string); | ||
412 | if (rc) | ||
413 | mu_error (_("invalid email address `%s': %s"), | ||
414 | val->v.string, mu_strerror (rc)); | ||
415 | return 0; | ||
416 | } | ||
417 | |||
418 | static int | ||
419 | cb_email_domain (void *data, mu_config_value_t *val) | ||
420 | { | ||
421 | int rc; | ||
422 | |||
423 | if (mu_cfg_assert_value_type (val, MU_CFG_STRING)) | ||
424 | return 1; | ||
425 | |||
426 | rc = mu_set_user_email_domain (val->v.string); | ||
427 | if (rc) | ||
428 | mu_error (_("invalid email domain `%s': %s"), | ||
429 | val->v.string, mu_strerror (rc)); | ||
430 | return 0; | ||
431 | } | ||
432 | |||
433 | static struct mu_cfg_param address_cfg[] = { | ||
434 | { "email-addr", mu_cfg_callback, NULL, 0, cb_email_addr, | ||
435 | N_("Set the current user email address (default is " | ||
436 | "loginname@defaultdomain)."), | ||
437 | N_("email: address") }, | ||
438 | { "email-domain", mu_cfg_callback, NULL, 0, cb_email_domain, | ||
439 | N_("Set e-mail domain for unqualified user names (default is this host)"), | ||
440 | N_("domain: string") }, | ||
441 | { NULL } | ||
442 | }; | ||
443 | |||
444 | |||
445 | /* ************************************************************************* * | ||
446 | * Registry of standard mailutils' capabilities * | ||
447 | * ************************************************************************* */ | ||
448 | struct mu_cli_capa mu_cli_std_capa[] = { | ||
449 | { "mailutils" }, /* Dummy */ | ||
450 | { "logging", logging_option, logging_cfg, NULL, logging_commit }, | ||
451 | { "mailer", mailer_option, mailer_cfg, NULL, NULL }, | ||
452 | { "debug", debug_option, debug_cfg, NULL, NULL }, | ||
453 | { "mailbox", NULL, mailbox_cfg, NULL, NULL }, | ||
454 | { "locking", NULL, locking_cfg, NULL, NULL }, | ||
455 | { "address", NULL, address_cfg, NULL, NULL }, | ||
456 | { NULL } | ||
457 | }; | ||
458 | |||
459 | void | ||
460 | mu_cli_capa_init (void) | ||
461 | { | ||
462 | size_t i; | ||
463 | |||
464 | for (i = 0; mu_cli_std_capa[i].name; i++) | ||
465 | mu_cli_capa_register (&mu_cli_std_capa[i]); | ||
466 | } |
... | @@ -30,32 +30,6 @@ | ... | @@ -30,32 +30,6 @@ |
30 | #include <mailutils/stdstream.h> | 30 | #include <mailutils/stdstream.h> |
31 | #include <mailutils/stream.h> | 31 | #include <mailutils/stream.h> |
32 | 32 | ||
33 | const char *mu_program_name; | ||
34 | const char *mu_full_program_name; | ||
35 | |||
36 | void | ||
37 | mu_set_program_name (const char *name) | ||
38 | { | ||
39 | const char *progname; | ||
40 | |||
41 | mu_full_program_name = name; | ||
42 | if (!name) | ||
43 | progname = name; | ||
44 | else | ||
45 | { | ||
46 | progname = strrchr (name, '/'); | ||
47 | if (progname) | ||
48 | progname++; | ||
49 | else | ||
50 | progname = name; | ||
51 | |||
52 | if (strlen (progname) > 3 && memcmp (progname, "lt-", 3) == 0) | ||
53 | progname += 3; | ||
54 | } | ||
55 | |||
56 | mu_program_name = progname; | ||
57 | } | ||
58 | |||
59 | void | 33 | void |
60 | mu_diag_init () | 34 | mu_diag_init () |
61 | { | 35 | { | ... | ... |
... | @@ -155,7 +155,7 @@ init_usage_vars (struct mu_parseopt *po) | ... | @@ -155,7 +155,7 @@ init_usage_vars (struct mu_parseopt *po) |
155 | fmt = getenv ("ARGP_HELP_FMT"); | 155 | fmt = getenv ("ARGP_HELP_FMT"); |
156 | if (!fmt) | 156 | if (!fmt) |
157 | return; | 157 | return; |
158 | ws.ws_delim=","; | 158 | ws.ws_delim = ","; |
159 | if (mu_wordsplit (fmt, &ws, | 159 | if (mu_wordsplit (fmt, &ws, |
160 | MU_WRDSF_DELIM | MU_WRDSF_NOVAR | MU_WRDSF_NOCMD | 160 | MU_WRDSF_DELIM | MU_WRDSF_NOVAR | MU_WRDSF_NOCMD |
161 | | MU_WRDSF_WS | MU_WRDSF_SHOWERR)) | 161 | | MU_WRDSF_WS | MU_WRDSF_SHOWERR)) |
... | @@ -346,20 +346,20 @@ mu_program_help (struct mu_parseopt *po) | ... | @@ -346,20 +346,20 @@ mu_program_help (struct mu_parseopt *po) |
346 | mu_option_describe_options (po->po_optv, po->po_optc); | 346 | mu_option_describe_options (po->po_optv, po->po_optc); |
347 | 347 | ||
348 | if (po->po_help_hook) | 348 | if (po->po_help_hook) |
349 | po->po_help_hook (stdout); | 349 | po->po_help_hook (po, stdout); |
350 | 350 | ||
351 | if (po->po_bug_address) | 351 | if (po->po_bug_address) |
352 | /* TRANSLATORS: The placeholder indicates the bug-reporting address | 352 | /* TRANSLATORS: The placeholder indicates the bug-reporting address |
353 | for this package. Please add _another line_ saying | 353 | for this package. Please add _another line_ saying |
354 | "Report translation bugs to <...>\n" with the address for translation | 354 | "Report translation bugs to <...>\n" with the address for translation |
355 | bugs (typically your translation team's web or email address). */ | 355 | bugs (typically your translation team's web or email address). */ |
356 | printf (_("Report bugs to %s.\n"), po->po_bug_address); | 356 | printf (_("Report bugs to <%s>.\n"), po->po_bug_address); |
357 | 357 | ||
358 | if (po->po_package_name && po->po_package_url) | 358 | if (po->po_package_name && po->po_package_url) |
359 | printf (_("%s home page: <%s>\n"), | 359 | printf (_("%s home page: <%s>\n"), |
360 | po->po_package_name, po->po_package_url); | 360 | po->po_package_name, po->po_package_url); |
361 | if (po->po_flags & MU_PARSEOPT_EXTRA_INFO) | 361 | if (po->po_flags & MU_PARSEOPT_EXTRA_INFO) |
362 | print_option_descr (po->po_extra_info, 0, rmargin); | 362 | print_option_descr (_(po->po_extra_info), 0, rmargin); |
363 | } | 363 | } |
364 | 364 | ||
365 | static struct mu_option **option_tab; | 365 | static struct mu_option **option_tab; | ... | ... |
... | @@ -85,7 +85,7 @@ fn_usage (struct mu_parseopt *po, struct mu_option *opt, char const *unused) | ... | @@ -85,7 +85,7 @@ fn_usage (struct mu_parseopt *po, struct mu_option *opt, char const *unused) |
85 | static void | 85 | static void |
86 | fn_version (struct mu_parseopt *po, struct mu_option *opt, char const *unused) | 86 | fn_version (struct mu_parseopt *po, struct mu_option *opt, char const *unused) |
87 | { | 87 | { |
88 | po->po_version_hook (stdout); | 88 | po->po_version_hook (po, stdout); |
89 | exit (EXIT_SUCCESS); | 89 | exit (EXIT_SUCCESS); |
90 | } | 90 | } |
91 | 91 | ||
... | @@ -107,8 +107,8 @@ struct mu_option mu_version_options[] = { | ... | @@ -107,8 +107,8 @@ struct mu_option mu_version_options[] = { |
107 | }; | 107 | }; |
108 | 108 | ||
109 | /* Output error message */ | 109 | /* Output error message */ |
110 | static void | 110 | void |
111 | parse_error (struct mu_parseopt *po, char const *fmt, ...) | 111 | mu_parseopt_error (struct mu_parseopt *po, char const *fmt, ...) |
112 | { | 112 | { |
113 | va_list ap; | 113 | va_list ap; |
114 | 114 | ||
... | @@ -176,7 +176,7 @@ find_short_option (struct mu_parseopt *po, int chr) | ... | @@ -176,7 +176,7 @@ find_short_option (struct mu_parseopt *po, int chr) |
176 | && po->po_optv[i]->opt_short == chr) | 176 | && po->po_optv[i]->opt_short == chr) |
177 | return option_unalias (po, i); | 177 | return option_unalias (po, i); |
178 | } | 178 | } |
179 | parse_error (po, _("unrecognized option '-%c'"), chr); | 179 | mu_parseopt_error (po, _("unrecognized option '-%c'"), chr); |
180 | return NULL; | 180 | return NULL; |
181 | } | 181 | } |
182 | 182 | ||
... | @@ -209,7 +209,7 @@ find_long_option (struct mu_parseopt *po, char const *optstr, | ... | @@ -209,7 +209,7 @@ find_long_option (struct mu_parseopt *po, char const *optstr, |
209 | case 1: | 209 | case 1: |
210 | if (po->po_flags & MU_PARSEOPT_IGNORE_ERRORS) | 210 | if (po->po_flags & MU_PARSEOPT_IGNORE_ERRORS) |
211 | return NULL; | 211 | return NULL; |
212 | parse_error (po, | 212 | mu_parseopt_error (po, |
213 | _("option '--%*.*s' is ambiguous; possibilities:"), | 213 | _("option '--%*.*s' is ambiguous; possibilities:"), |
214 | optlen, optlen, optstr); | 214 | optlen, optlen, optstr); |
215 | fprintf (stderr, "--%s\n", po->po_optv[ind]->opt_long); | 215 | fprintf (stderr, "--%s\n", po->po_optv[ind]->opt_long); |
... | @@ -224,7 +224,7 @@ find_long_option (struct mu_parseopt *po, char const *optstr, | ... | @@ -224,7 +224,7 @@ find_long_option (struct mu_parseopt *po, char const *optstr, |
224 | switch (found) | 224 | switch (found) |
225 | { | 225 | { |
226 | case 0: | 226 | case 0: |
227 | parse_error (po, _("unrecognized option '--%s'"), optstr); | 227 | mu_parseopt_error (po, _("unrecognized option '--%s'"), optstr); |
228 | break; | 228 | break; |
229 | 229 | ||
230 | case 1: | 230 | case 1: |
... | @@ -303,7 +303,7 @@ next_opt (struct mu_parseopt *po) | ... | @@ -303,7 +303,7 @@ next_opt (struct mu_parseopt *po) |
303 | break; | 303 | break; |
304 | if (!(po->po_flags & MU_PARSEOPT_IN_ORDER)) | 304 | if (!(po->po_flags & MU_PARSEOPT_IN_ORDER)) |
305 | { | 305 | { |
306 | if (!po->po_permuted) | 306 | if (!po->po_permuted && po->po_arg_count == 0) |
307 | po->po_arg_start = po->po_ind - 1; | 307 | po->po_arg_start = po->po_ind - 1; |
308 | po->po_arg_count++; | 308 | po->po_arg_count++; |
309 | continue; | 309 | continue; |
... | @@ -405,11 +405,11 @@ parse (struct mu_parseopt *po) | ... | @@ -405,11 +405,11 @@ parse (struct mu_parseopt *po) |
405 | else | 405 | else |
406 | { | 406 | { |
407 | if (long_opt) | 407 | if (long_opt) |
408 | parse_error (po, | 408 | mu_parseopt_error (po, |
409 | _("option '--%s' requires an argument"), | 409 | _("option '--%s' requires an argument"), |
410 | long_opt); | 410 | long_opt); |
411 | else | 411 | else |
412 | parse_error (po, | 412 | mu_parseopt_error (po, |
413 | _("option '-%c' requires an argument"), | 413 | _("option '-%c' requires an argument"), |
414 | po->po_chr); | 414 | po->po_chr); |
415 | po->po_opterr = po->po_ind; | 415 | po->po_opterr = po->po_ind; |
... | @@ -428,7 +428,7 @@ parse (struct mu_parseopt *po) | ... | @@ -428,7 +428,7 @@ parse (struct mu_parseopt *po) |
428 | && po->po_cur[0] | 428 | && po->po_cur[0] |
429 | && !(po->po_flags & MU_OPTION_ARG_OPTIONAL)) | 429 | && !(po->po_flags & MU_OPTION_ARG_OPTIONAL)) |
430 | { | 430 | { |
431 | parse_error (po, | 431 | mu_parseopt_error (po, |
432 | _("option '--%s' doesn't allow an argument"), | 432 | _("option '--%s' doesn't allow an argument"), |
433 | long_opt); | 433 | long_opt); |
434 | po->po_opterr = po->po_ind; | 434 | po->po_opterr = po->po_ind; |
... | @@ -661,9 +661,9 @@ mu_option_set_value (struct mu_parseopt *po, struct mu_option *opt, | ... | @@ -661,9 +661,9 @@ mu_option_set_value (struct mu_parseopt *po, struct mu_option *opt, |
661 | errtext = mu_strerror (rc); | 661 | errtext = mu_strerror (rc); |
662 | 662 | ||
663 | if (opt->opt_long) | 663 | if (opt->opt_long) |
664 | parse_error (po, "--%s: %s", opt->opt_long, errtext); | 664 | mu_parseopt_error (po, "--%s: %s", opt->opt_long, errtext); |
665 | else | 665 | else |
666 | parse_error (po, "-%c: %s", opt->opt_short, errtext); | 666 | mu_parseopt_error (po, "-%c: %s", opt->opt_short, errtext); |
667 | free (errmsg); | 667 | free (errmsg); |
668 | 668 | ||
669 | if (!(po->po_flags & MU_PARSEOPT_NO_ERREXIT)) | 669 | if (!(po->po_flags & MU_PARSEOPT_NO_ERREXIT)) | ... | ... |
... | @@ -22,16 +22,16 @@ | ... | @@ -22,16 +22,16 @@ |
22 | #include <mailutils/alloc.h> | 22 | #include <mailutils/alloc.h> |
23 | #include <mailutils/opt.h> | 23 | #include <mailutils/opt.h> |
24 | 24 | ||
25 | char *mu_progname; | 25 | char *mu_program_name; |
26 | char *mu_absprogname; | 26 | char *mu_full_program_name; |
27 | 27 | ||
28 | void | 28 | void |
29 | mu_set_progname (char const *arg) | 29 | mu_set_program_name (const char *arg) |
30 | { | 30 | { |
31 | char *p; | 31 | char *p; |
32 | 32 | ||
33 | free (mu_absprogname); | 33 | free (mu_full_program_name); |
34 | mu_absprogname = mu_strdup (arg); | 34 | mu_full_program_name = mu_strdup (arg); |
35 | 35 | ||
36 | p = strrchr (arg, '/'); | 36 | p = strrchr (arg, '/'); |
37 | if (p) | 37 | if (p) |
... | @@ -40,6 +40,6 @@ mu_set_progname (char const *arg) | ... | @@ -40,6 +40,6 @@ mu_set_progname (char const *arg) |
40 | p = (char*) arg; | 40 | p = (char*) arg; |
41 | if (strlen (p) > 3 && memcmp (p, "lt-", 3) == 0) | 41 | if (strlen (p) > 3 && memcmp (p, "lt-", 3) == 0) |
42 | p += 3; | 42 | p += 3; |
43 | free (mu_progname); | 43 | free (mu_program_name); |
44 | mu_progname = mu_strdup (p); | 44 | mu_program_name = mu_strdup (p); |
45 | } | 45 | } | ... | ... |
... | @@ -64,7 +64,7 @@ struct mu_option group_b[] = { | ... | @@ -64,7 +64,7 @@ struct mu_option group_b[] = { |
64 | struct mu_option *optv[] = { group_a, group_b, NULL }; | 64 | struct mu_option *optv[] = { group_a, group_b, NULL }; |
65 | 65 | ||
66 | static void | 66 | static void |
67 | version_func (FILE *fp) | 67 | version_hook (struct mu_parseopt *po, FILE *fp) |
68 | { | 68 | { |
69 | fputs ("version hook called\n", fp); | 69 | fputs ("version hook called\n", fp); |
70 | } | 70 | } |
... | @@ -144,7 +144,7 @@ main (int argc, char *argv[]) | ... | @@ -144,7 +144,7 @@ main (int argc, char *argv[]) |
144 | } | 144 | } |
145 | } | 145 | } |
146 | if (flags & MU_PARSEOPT_VERSION_HOOK) | 146 | if (flags & MU_PARSEOPT_VERSION_HOOK) |
147 | po.po_version_hook = version_func; | 147 | po.po_version_hook = version_hook; |
148 | } | 148 | } |
149 | 149 | ||
150 | rc = mu_parseopt (&po, argc, argv, optv, flags); | 150 | rc = mu_parseopt (&po, argc, argv, optv, flags); | ... | ... |
... | @@ -35,4 +35,24 @@ argv: | ... | @@ -35,4 +35,24 @@ argv: |
35 | 2: follow | 35 | 2: follow |
36 | 3: options | 36 | 3: options |
37 | ]) | 37 | ]) |
38 | |||
39 | AT_CHECK([ | ||
40 | PARSEOPT_DEFAULT | ||
41 | parseopt --file=file more arguments follow -x -o options | ||
42 | ], | ||
43 | [0], | ||
44 | [rc=0 | ||
45 | file_name=file | ||
46 | opt_value=(null) | ||
47 | x_option=1 | ||
48 | a_option=0 | ||
49 | find_value=(null) | ||
50 | d_option=0 | ||
51 | jobs=0 | ||
52 | argv: | ||
53 | 0: more | ||
54 | 1: arguments | ||
55 | 2: follow | ||
56 | 3: options | ||
57 | ]) | ||
38 | AT_CLEANUP | 58 | AT_CLEANUP | ... | ... |
... | @@ -18,7 +18,7 @@ AT_SETUP([MU_PARSEOPT_BUG_ADDRESS]) | ... | @@ -18,7 +18,7 @@ AT_SETUP([MU_PARSEOPT_BUG_ADDRESS]) |
18 | AT_KEYWORDS([parseopt parseopt_help parseopt_help05]) | 18 | AT_KEYWORDS([parseopt parseopt_help parseopt_help05]) |
19 | AT_CHECK([ | 19 | AT_CHECK([ |
20 | PARSEOPT_DEFAULT | 20 | PARSEOPT_DEFAULT |
21 | MU_PARSEOPT_BUG_ADDRESS='<gray@gnu.org>' parseopt --help | 21 | MU_PARSEOPT_BUG_ADDRESS='gray@gnu.org' parseopt --help |
22 | ], | 22 | ], |
23 | [0], | 23 | [0], |
24 | [Usage: parseopt [[OPTION]]... | 24 | [Usage: parseopt [[OPTION]]... | ... | ... |
... | @@ -20,7 +20,7 @@ AT_CHECK([ | ... | @@ -20,7 +20,7 @@ AT_CHECK([ |
20 | PARSEOPT_DEFAULT | 20 | PARSEOPT_DEFAULT |
21 | MU_PARSEOPT_PROG_DOC="Tests option parsing"\ | 21 | MU_PARSEOPT_PROG_DOC="Tests option parsing"\ |
22 | MU_PARSEOPT_PROG_ARGS="SOME MORE ARGS"\ | 22 | MU_PARSEOPT_PROG_ARGS="SOME MORE ARGS"\ |
23 | MU_PARSEOPT_BUG_ADDRESS='<gray@gnu.org>'\ | 23 | MU_PARSEOPT_BUG_ADDRESS='gray@gnu.org'\ |
24 | MU_PARSEOPT_PACKAGE_NAME='GNU Mailutils'\ | 24 | MU_PARSEOPT_PACKAGE_NAME='GNU Mailutils'\ |
25 | MU_PARSEOPT_PACKAGE_URL='http://mailutils.org'\ | 25 | MU_PARSEOPT_PACKAGE_URL='http://mailutils.org'\ |
26 | MU_PARSEOPT_EXTRA_INFO='General help using GNU software: <http://www.gnu.org/gethelp/>'\ | 26 | MU_PARSEOPT_EXTRA_INFO='General help using GNU software: <http://www.gnu.org/gethelp/>'\ | ... | ... |
libmailutils/tests/tcli.c
0 → 100644
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | ||
2 | Copyright (C) 2016 Free Software Foundation, Inc. | ||
3 | |||
4 | GNU Mailutils is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Public License as published by | ||
6 | the Free Software Foundation; either version 3, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | GNU Mailutils is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License | ||
15 | along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */ | ||
16 | |||
17 | #ifdef HAVE_CONFIG_H | ||
18 | # include <config.h> | ||
19 | #endif | ||
20 | #include <mailutils/mailutils.h> | ||
21 | #include <mailutils/cli.h> | ||
22 | |||
23 | int dtrt_option; | ||
24 | |||
25 | struct mu_option group_a[] = { | ||
26 | { "dtrt", 'd', "VALUE", MU_OPTION_DEFAULT, | ||
27 | "do the right thing", | ||
28 | mu_c_int, &dtrt_option }, | ||
29 | MU_OPTION_END | ||
30 | }; | ||
31 | |||
32 | struct mu_option *options[] = { group_a, NULL }; | ||
33 | |||
34 | static struct mu_cfg_param config[] = { | ||
35 | { "do-the-right-thing", mu_c_int, &dtrt_option, 0, NULL, | ||
36 | "do the right thing" }, | ||
37 | { NULL } | ||
38 | }; | ||
39 | |||
40 | struct mu_cli_setup cli = { | ||
41 | options, | ||
42 | config, | ||
43 | "Tests standard command line interface", | ||
44 | "ARGUMENTS" | ||
45 | }; | ||
46 | |||
47 | static char ** | ||
48 | getcapa (void) | ||
49 | { | ||
50 | struct mu_wordsplit ws; | ||
51 | char *p; | ||
52 | |||
53 | p = getenv ("MU_CLI_CAPA"); | ||
54 | if (!p) | ||
55 | return NULL; | ||
56 | ws.ws_delim = ","; | ||
57 | if (mu_wordsplit (p, &ws, | ||
58 | MU_WRDSF_DELIM | MU_WRDSF_NOVAR | MU_WRDSF_NOCMD | ||
59 | | MU_WRDSF_WS | MU_WRDSF_SHOWERR)) | ||
60 | exit (1); | ||
61 | return ws.ws_wordv; | ||
62 | } | ||
63 | |||
64 | int | ||
65 | main (int argc, char **argv) | ||
66 | { | ||
67 | int i; | ||
68 | |||
69 | mu_cli (argc, argv, &cli, getcapa (), NULL, &argc, &argv); | ||
70 | printf ("DTRT=%d\n", dtrt_option); | ||
71 | printf ("%d arguments:\n", argc); | ||
72 | for (i = 0; i < argc; i++) | ||
73 | printf ("%d: %s\n", i, argv[i]); | ||
74 | return 0; | ||
75 | } |
... | @@ -19,22 +19,27 @@ | ... | @@ -19,22 +19,27 @@ |
19 | #ifdef HAVE_CONFIG_H | 19 | #ifdef HAVE_CONFIG_H |
20 | # include <config.h> | 20 | # include <config.h> |
21 | #endif | 21 | #endif |
22 | #include <stdlib.h> | ||
22 | #include <sieve-priv.h> | 23 | #include <sieve-priv.h> |
23 | #include <string.h> | 24 | #include <string.h> |
25 | #include <mailutils/cli.h> | ||
24 | 26 | ||
25 | mu_list_t mu_sieve_include_path = NULL; | 27 | mu_list_t mu_sieve_include_path = NULL; |
26 | mu_list_t mu_sieve_library_path = NULL; | 28 | mu_list_t mu_sieve_library_path = NULL; |
27 | mu_list_t mu_sieve_library_path_prefix = NULL; | 29 | mu_list_t mu_sieve_library_path_prefix = NULL; |
28 | |||
29 | mu_debug_handle_t mu_sieve_debug_handle; | 30 | mu_debug_handle_t mu_sieve_debug_handle; |
30 | 31 | ||
32 | //FIXME: provide definition (from gocs.h) | ||
33 | static struct mu_gocs_sieve sieve_settings; | ||
34 | |||
31 | void | 35 | void |
32 | mu_sieve_debug_init () | 36 | mu_sieve_debug_init (void) |
33 | { | 37 | { |
34 | if (!mu_sieve_debug_handle) | 38 | if (!mu_sieve_debug_handle) |
35 | mu_sieve_debug_handle = mu_debug_register_category ("sieve"); | 39 | mu_sieve_debug_handle = mu_debug_register_category ("sieve"); |
36 | } | 40 | } |
37 | 41 | ||
42 | /*FIXME: REMOVE BEGIN */ | ||
38 | static int | 43 | static int |
39 | _path_append (void *item, void *data) | 44 | _path_append (void *item, void *data) |
40 | { | 45 | { |
... | @@ -81,3 +86,161 @@ mu_sieve_module_init (enum mu_gocs_op op, void *data) | ... | @@ -81,3 +86,161 @@ mu_sieve_module_init (enum mu_gocs_op op, void *data) |
81 | mu_sieve_debug_init (); | 86 | mu_sieve_debug_init (); |
82 | return 0; | 87 | return 0; |
83 | } | 88 | } |
89 | /* FIXME: REMOVE END */ | ||
90 | |||
91 | static int | ||
92 | cb_clear_library_path (void *data, mu_config_value_t *val) | ||
93 | { | ||
94 | int flag; | ||
95 | |||
96 | if (mu_cfg_assert_value_type (val, MU_CFG_STRING)) | ||
97 | return 1; | ||
98 | if (mu_str_to_c (val->v.string, mu_c_bool, &flag, NULL)) | ||
99 | { | ||
100 | mu_error (_("not a boolean")); | ||
101 | return 1; | ||
102 | } | ||
103 | if (flag) | ||
104 | sieve_settings.clearflags |= MU_SIEVE_CLEAR_LIBRARY_PATH; | ||
105 | return 0; | ||
106 | } | ||
107 | |||
108 | static int | ||
109 | cb_clear_include_path (void *data, mu_config_value_t *val) | ||
110 | { | ||
111 | int flag; | ||
112 | |||
113 | if (mu_cfg_assert_value_type (val, MU_CFG_STRING)) | ||
114 | return 1; | ||
115 | if (mu_str_to_c (val->v.string, mu_c_bool, &flag, NULL)) | ||
116 | { | ||
117 | mu_error (_("not a boolean")); | ||
118 | return 1; | ||
119 | } | ||
120 | if (flag) | ||
121 | sieve_settings.clearflags |= MU_SIEVE_CLEAR_INCLUDE_PATH; | ||
122 | return 0; | ||
123 | } | ||
124 | |||
125 | static int | ||
126 | _add_path (const char *arg, void *data) | ||
127 | { | ||
128 | mu_list_t *plist = data; | ||
129 | |||
130 | if (!*plist) | ||
131 | { | ||
132 | int rc = mu_list_create (plist); | ||
133 | if (rc) | ||
134 | { | ||
135 | mu_error (_("cannot create list: %s"), mu_strerror (rc)); | ||
136 | exit (1); | ||
137 | } | ||
138 | mu_list_set_destroy_item (*plist, mu_list_free_item); | ||
139 | } | ||
140 | return mu_string_split (arg, ":", *plist); | ||
141 | } | ||
142 | |||
143 | static int | ||
144 | cb_include_path (void *data, mu_config_value_t *val) | ||
145 | { | ||
146 | return mu_cfg_string_value_cb (val, _add_path, | ||
147 | &sieve_settings.include_path); | ||
148 | } | ||
149 | |||
150 | static int | ||
151 | cb_library_path (void *data, mu_config_value_t *val) | ||
152 | { | ||
153 | return mu_cfg_string_value_cb (val, _add_path, | ||
154 | &sieve_settings.library_path); | ||
155 | } | ||
156 | |||
157 | static int | ||
158 | cb_library_path_prefix (void *data, mu_config_value_t *val) | ||
159 | { | ||
160 | return mu_cfg_string_value_cb (val, _add_path, | ||
161 | &sieve_settings.library_path_prefix); | ||
162 | } | ||
163 | |||
164 | static struct mu_cfg_param mu_sieve_param[] = { | ||
165 | { "clear-library-path", mu_cfg_callback, NULL, 0, cb_clear_library_path, | ||
166 | N_("Clear library search path.") }, | ||
167 | { "clear-include-path", mu_cfg_callback, NULL, 0, cb_clear_include_path, | ||
168 | N_("Clear include search path.") }, | ||
169 | { "library-path", mu_cfg_callback, NULL, 0, cb_library_path, | ||
170 | N_("Add directories to the library search path. Argument is a " | ||
171 | "colon-separated list of directories."), | ||
172 | N_("list") }, | ||
173 | { "library-path-prefix", mu_cfg_callback, NULL, 0, cb_library_path_prefix, | ||
174 | N_("Add directories to the beginning of the library search path. " | ||
175 | "Argument is a colon-separated list of directories."), | ||
176 | N_("list") }, | ||
177 | { "include-path", mu_cfg_callback, NULL, 0, cb_include_path, | ||
178 | N_("Add directories to the include search path. Argument is a " | ||
179 | "colon-separated list of directories."), | ||
180 | N_("list") }, | ||
181 | { NULL } | ||
182 | }; | ||
183 | |||
184 | /* New capability support */ | ||
185 | static void | ||
186 | cli_includedir (struct mu_parseopt *po, struct mu_option *opt, | ||
187 | char const *arg) | ||
188 | { | ||
189 | _add_path (arg, &sieve_settings.include_path); | ||
190 | } | ||
191 | |||
192 | static void | ||
193 | cli_libdir (struct mu_parseopt *po, struct mu_option *opt, char const *arg) | ||
194 | { | ||
195 | _add_path (arg, &sieve_settings.library_path); | ||
196 | } | ||
197 | |||
198 | static void | ||
199 | cli_libdir_prefix (struct mu_parseopt *po, struct mu_option *opt, | ||
200 | char const *arg) | ||
201 | { | ||
202 | _add_path (arg, &sieve_settings.library_path_prefix); | ||
203 | } | ||
204 | |||
205 | static void | ||
206 | cli_clear_include_path (struct mu_parseopt *po, struct mu_option *opt, | ||
207 | char const *arg) | ||
208 | { | ||
209 | sieve_settings.clearflags |= MU_SIEVE_CLEAR_INCLUDE_PATH; | ||
210 | } | ||
211 | |||
212 | static void | ||
213 | cli_clear_library_path (struct mu_parseopt *po, struct mu_option *opt, | ||
214 | char const *arg) | ||
215 | { | ||
216 | sieve_settings.clearflags |= MU_SIEVE_CLEAR_LIBRARY_PATH; | ||
217 | } | ||
218 | |||
219 | static struct mu_option sieve_option[] = { | ||
220 | MU_OPTION_GROUP (N_("Sieve options")), | ||
221 | { "includedir", 'I', N_("DIR"), MU_OPTION_DEFAULT, | ||
222 | N_("append DIR to the list of directories searched for include files"), | ||
223 | mu_c_string, NULL, cli_includedir }, | ||
224 | { "libdir", 'L', N_("DIR"), MU_OPTION_DEFAULT, | ||
225 | N_("append DIR to the list of directories searched for library files"), | ||
226 | mu_c_string, NULL, cli_libdir }, | ||
227 | { "libdir-prefix", 0, N_("DIR"), MU_OPTION_DEFAULT, | ||
228 | N_("add DIR to the beginning of the list of directories searched for " | ||
229 | "library files"), | ||
230 | mu_c_string, NULL, cli_libdir_prefix }, | ||
231 | { "clear-include-path", 0, NULL, MU_OPTION_DEFAULT, | ||
232 | N_("clear Sieve include path"), | ||
233 | mu_c_string, NULL, cli_clear_include_path }, | ||
234 | { "clear-library-path", 0, NULL, MU_OPTION_DEFAULT, | ||
235 | N_("clear Sieve library path"), | ||
236 | mu_c_string, NULL, cli_clear_library_path }, | ||
237 | { "clearpath", 0, NULL, MU_OPTION_ALIAS }, | ||
238 | MU_OPTION_END | ||
239 | }; | ||
240 | |||
241 | struct mu_cli_capa mu_cli_capa_sieve = { | ||
242 | "sieve", | ||
243 | sieve_option, | ||
244 | mu_sieve_param, | ||
245 | NULL, NULL | ||
246 | }; | ... | ... |
-
Please register or sign in to post a comment