diff options
-rw-r--r-- | NEWS | 8 | ||||
-rw-r--r-- | configure.ac | 4 | ||||
-rw-r--r-- | doc/mailfromd.texi | 9 | ||||
-rw-r--r-- | lib/Makefile.am | 1 | ||||
-rw-r--r-- | lib/libmf.h | 4 | ||||
-rw-r--r-- | lib/mfgetopt.c | 55 | ||||
-rw-r--r-- | lib/mudefs.h | 1 | ||||
-rw-r--r-- | mtasim/mtasim.c | 553 | ||||
-rw-r--r-- | pmult/pmult.c | 188 | ||||
-rw-r--r-- | po/POTFILES.in | 1 | ||||
-rw-r--r-- | src/calloutd.c | 63 | ||||
-rw-r--r-- | src/mailfromd.h | 1 | ||||
-rw-r--r-- | src/main.c | 42 | ||||
-rw-r--r-- | src/mfdbtool.c | 310 | ||||
-rw-r--r-- | tests/atlocal.in | 1 |
15 files changed, 500 insertions, 741 deletions
@@ -1,11 +1,11 @@ -Mailfromd NEWS -- history of user-visible changes. 2016-08-09 +Mailfromd NEWS -- history of user-visible changes. 2016-10-28 Copyright (C) 2005-2016 Sergey Poznyakoff See the end of file for copying conditions. Please send Mailfromd bug reports to <bug-mailfromd@gnu.org.ua> -Version 7.99.95, (Git) +Version 7.99.96, (Git) This version is highly experimental and lacks documentation. Use `git log' for a detailed description of changes. @@ -29,7 +29,7 @@ recommended, because many existing VRFY implementations always return affirmative result, no matter is the requested email handled by the server or not. -** `listen' statement withdrawn +** The `listen' statement withdrawn Use `server milter' statement instead, e.g.: @@ -37,6 +37,8 @@ server milter { listen "inet://127.0.0.1:7788"; } +** The `--remove' option withdrawn + ** The `backlog' statement The new `backlog' statement is provided for configuring the size diff --git a/configure.ac b/configure.ac index 0a1a1746..dc376fdc 100644 --- a/configure.ac +++ b/configure.ac @@ -17,7 +17,7 @@ AC_PREREQ(2.63) m4_define([MF_VERSION_MAJOR], 7) m4_define([MF_VERSION_MINOR], 99) -m4_define([MF_VERSION_PATCH], 95) +m4_define([MF_VERSION_PATCH], 96) AC_INIT([mailfromd], MF_VERSION_MAJOR.MF_VERSION_MINOR[]m4_ifdef([MF_VERSION_PATCH],.MF_VERSION_PATCH), [bug-mailfromd@gnu.org.ua], @@ -111,7 +111,7 @@ AH_BOTTOM([ ]) # Check for GNU Mailutils -AM_GNU_MAILUTILS([2.99.991], [all auth dbm sieve], [:]) +AM_GNU_MAILUTILS([2.99.992], [all auth dbm sieve], [:]) AC_CHECK_TYPES([struct mu_argp_node_list],,,[#include <mailutils/libargp.h>]) ### Check for Emacs site-lisp directory diff --git a/doc/mailfromd.texi b/doc/mailfromd.texi index 28533e8c..d8ff6046 100644 --- a/doc/mailfromd.texi +++ b/doc/mailfromd.texi @@ -9674,13 +9674,6 @@ relayed-domain-file}), which you are advised to use instead. @xref{Avoiding Verification Loops}, and the description of @code{relayed} function (@pxref{relayed}) for more information. -@opsummary{remove, mailfromd} -@item -r -@itemx --remove -Force removing local socket file, if it already exists. Unless this -option is specified, @command{mailfromd} will refuse to start if -this file exists. - @opsummary{state-directory, mailfromd} @item --state-directory=@var{dir} Set new program state directory. @xref{statedir, Local state directory}, for @@ -10104,7 +10097,7 @@ process and its command line, for example: @group $ @kbd{/etc/rc.d/rc.mailfromd status} mailformd appears to be running at 26030 -26030 /usr/local/sbin/mailfromd @/--remove @/--group smmsp +26030 /usr/local/sbin/mailfromd @/--group smmsp @end group @end smallexample diff --git a/lib/Makefile.am b/lib/Makefile.am index 7df87557..5427a1e2 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -34,6 +34,7 @@ libmf_a_SOURCES=\ dict.c\ ftimestr.c\ logger.c\ + mfgetopt.c\ namefixup.c\ nls.c\ parsetime.c\ diff --git a/lib/libmf.h b/lib/libmf.h index 41815574..08a61a26 100644 --- a/lib/libmf.h +++ b/lib/libmf.h @@ -22,6 +22,7 @@ #include <mailutils/types.h> #include <mailutils/cfg.h> #include <mailutils/stdstream.h> +#include <mailutils/cli.h> #include <pwd.h> #include <grp.h> @@ -101,7 +102,8 @@ enum smtp_timeout { #define SMTP_NUM_TIMEOUT (smtp_timeout_quit+1) -struct mu_parseopt; +int mf_getopt(struct mu_cli_setup *cli, int *pargc, char ***pargv, char **capa, + int iorder, char const *cfile); void mailfromd_version(struct mu_parseopt *po, mu_stream_t stream); int mf_vercmp(const char *a, const char *b, int *pres); void mf_init_nls (void); diff --git a/lib/mfgetopt.c b/lib/mfgetopt.c new file mode 100644 index 00000000..411e0771 --- /dev/null +++ b/lib/mfgetopt.c @@ -0,0 +1,55 @@ +/* This file is part of Mailfromd. + Copyright (C) 2016 Sergey Poznyakoff + + This program 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. + + This program 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 this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif +#include "libmf.h" + +int +mf_getopt(struct mu_cli_setup *cli, int *pargc, char ***pargv, char **capa, + int inorder, + char const *cfile) +{ + struct mu_parseopt pohint; + struct mu_cfg_parse_hints cfhint; + + if (cfile) { + cfhint.site_rcfile = (char*) cfile; + cfhint.flags = MU_CFG_PARSE_SITE_RCFILE; + } + + pohint.po_flags = 0; + + pohint.po_package_name = PACKAGE_NAME; + pohint.po_flags |= MU_PARSEOPT_PACKAGE_NAME; + + pohint.po_package_url = PACKAGE_URL; + pohint.po_flags |= MU_PARSEOPT_PACKAGE_URL; + + pohint.po_bug_address = PACKAGE_BUGREPORT; + pohint.po_flags |= MU_PARSEOPT_BUG_ADDRESS; + + pohint.po_version_hook = mailfromd_version; + pohint.po_flags |= MU_PARSEOPT_VERSION_HOOK; + + pohint.po_negation = "no-"; + pohint.po_flags |= MU_PARSEOPT_NEGATION; + + mu_cli_ext (*pargc, *pargv, cli, &pohint, &cfhint, capa, NULL, + pargc, pargv); +} + diff --git a/lib/mudefs.h b/lib/mudefs.h index 9bd4b749..7c9f54c2 100644 --- a/lib/mudefs.h +++ b/lib/mudefs.h @@ -18,7 +18,6 @@ # include <config.h> #endif #include <mailutils/types.h> -#include <mailutils/libargp.h> /* struct mu_argp_node_list was removed in Mailutils' commit e1f5e01f (before version 2.1.91). */ diff --git a/mtasim/mtasim.c b/mtasim/mtasim.c index d6414b87..0d08da87 100644 --- a/mtasim/mtasim.c +++ b/mtasim/mtasim.c @@ -49,7 +49,6 @@ #define obstack_chunk_alloc malloc #define obstack_chunk_free free #include <obstack.h> -#include <argp.h> #include <mailutils/alloc.h> #include <mailutils/cctype.h> @@ -71,6 +70,14 @@ struct mf_gid_list *grouplist; /* List of additional groups to be retained */ char *sender_hostname; struct sockaddr *sender_sockaddr; +int mta_daemon (void); +int mta_stdio (void); + +int (*mta_mode) (void) = mta_stdio; +char *trace_name = NULL; +int append; +int statedir_option; + #ifdef HAVE_TLS char *tls_cert; /* TLS sertificate */ char *tls_key; /* TLS key */ @@ -88,8 +95,6 @@ static gnutls_certificate_server_credentials x509_cred; int interactive; char *prompt = "(mtasim) "; -int mta_daemon (void); -int mta_stdio (void); void error (const char *, ...); void smtp_reply (int, char *, ...); void reset_capa (char *); @@ -117,23 +122,6 @@ struct timeval milter_timeouts[GACOPYZ_TO_COUNT] = { static void -add_group (const char *gname) -{ - struct group *group = getgrnam(gname); - if (group) - { - if (!grouplist) - grouplist = mf_gid_list_alloc (); - mf_gid_list_add (grouplist, group->gr_gid); - } - else - { - mu_error(_("unknown group: %s"), gname); - exit (EX_DATAERR); - } -} - -static void priv_setup () { if (getuid() == 0 && user) @@ -164,16 +152,24 @@ update_nrcpts (char *name, unsigned n) static mu_list_t defnlist; int -defer_define_macro (char *arg) +defer_define_macro (char const *arg) { - char *p; - p = strchr (arg, '='); + char *copy, *p; + + copy = mu_strdup (arg); + p = strchr (copy, '='); if (!p) - return 1; - *p++ = 0; + { + free (copy); + return 1; + } + *p = 0; if (!defnlist) - mu_list_create (&defnlist); - mu_list_append (defnlist, arg); + { + mu_list_create (&defnlist); + mu_list_set_destroy_item (defnlist, mu_list_free_item); + } + mu_list_append (defnlist, copy); return 0; } @@ -252,139 +248,73 @@ check_expected_code (char *str) } -const char *argp_program_version = "mtasim (" PACKAGE_STRING ")"; -const char *argp_program_bug_address = "<" PACKAGE_BUGREPORT ">"; -static char doc[] = N_("mtasim -- MTA simulator for mailfromd"); - - -enum { - OPTION_STDIO = 128, - OPTION_GACOPYZ_LOG, - OPTION_DAEMON, - OPTION_TLS_CERT, - OPTION_TLS_CA, - OPTION_TLS_KEY, - OPTION_TRACE_FILE, - OPTION_BODY_CHUNK, - OPTION_MILTER_VERSION, - OPTION_MILTER_PROTO, - OPTION_MILTER_ACTS, - OPTION_MILTER_TIMEOUT, - OPTION_NO_INTERACTIVE, - OPTION_PROMPT, - OPTION_SENDER_SOCKADDR, - OPTION_STATEDIR -}; +static char prog_doc[] = N_("mtasim -- MTA simulator for mailfromd"); #ifndef WITH_READLINE -# define OPT_INTERACTIVE OPTION_HIDDEN +# define OPT_INTERACTIVE MU_OPTION_HIDDEN #else -# define OPT_INTERACTIVE 0 +# define OPT_INTERACTIVE MU_OPTION_DEFAULT #endif -static struct argp_option options[] = { -#define GRP 1 - { NULL, 0, NULL, 0, - N_("Mode selection"), GRP }, - { NULL, 'b', N_("MODE"), 0, - N_("set MTA mode (-bd or -bs)"), GRP+1 }, - { "stdio", OPTION_STDIO, NULL, 0, - N_("use the SMTP protocol on standard input and output (same as -bs)"), - GRP+1 }, - { "daemon", OPTION_DAEMON, NULL, 0, - N_("run as daemon (same as -bd)"), - GRP+1 }, - { "user", 'u', N_("NAME"), 0, - N_("run with this user privileges"), - GRP+1 }, - { "group", 'g', N_("NAME"), 0, - N_("retain the supplementary group NAME when switching to user " - "privileges"), - GRP+1 }, -#undef GRP +static void +opt_mta_mode(struct mu_parseopt *po, struct mu_option *opt, char const *arg) +{ + switch (arg[0]) + { + case 'd': + mta_mode = mta_daemon; + break; + + case 's': + mta_mode = mta_stdio; + break; + + default: + mu_parseopt_error (po, _("unsupported mode")); + exit(po->po_exit_error); + } +} -#define GRP 10 - { NULL, 0, NULL, 0, - N_("Operation modifiers"), GRP }, - { "define", 'D', N_("MACRO=VALUE"), 0, - N_("define Sendmail macro"), - GRP+1 }, - { "port", 'X', N_("PORT"), 0, - N_("communicate with Milter PORT"), - GRP+1 }, - { "statedir", OPTION_STATEDIR, NULL, 0, - N_("pass temporary directory to mailfromd as its state dir (with -Xauto)"), - GRP+1 }, - { "body-chunk", OPTION_BODY_CHUNK, N_("NUMBER"), 0, - N_("set the body chunk for xxfi_body calls"), - GRP+1 }, - { "milter-version", OPTION_MILTER_VERSION, N_("VER"), 0, - N_("force using the given Milter protocol version number"), GRP+1 }, - { "milter-actions", OPTION_MILTER_ACTS, N_("BITMASK"), 0, - N_("force the given Milter actions"), GRP+1 }, - { "milter-proto", OPTION_MILTER_PROTO, N_("BITMASK"), 0, - N_("set Milter protocol capabilities"), GRP+1 }, - { "milter-timeout", OPTION_MILTER_TIMEOUT, N_("F=V[,F=V...]"), 0, - N_("set milter timeouts"), GRP+1 }, - { "sender-sockaddr", OPTION_SENDER_SOCKADDR, - N_("FAMILY[,HOSTNAME,ADDRESS[,PORT]]"), 0, - N_("set sender socket address") }, -#undef GRP - -#define GRP 20 - { "no-interactive", OPTION_NO_INTERACTIVE, NULL, OPT_INTERACTIVE, - N_("not-interactive mode (disable readline)"), GRP+1 }, - { "prompt", OPTION_PROMPT, N_("STRING"), OPT_INTERACTIVE, - N_("set readline prompt"), GRP+1 }, -#undef GRP - -#define GRP 30 - { NULL, 0, NULL, 0, - N_("Debugging and tracing"), GRP }, - { "append", 'a', NULL, 0, - N_("append to the trace file"), GRP+1 }, - { "trace-file", OPTION_TRACE_FILE, N_("FILE"), 0, - N_("set name of the trace file"), GRP+1 }, - { "verbose", 'v', NULL, 0, - N_("increase verbosity level"), - GRP+1 }, - { "gacopyz-log", OPTION_GACOPYZ_LOG, N_("LEVEL"), 0, - N_("set Gacopyz log level"), GRP+1 }, -#undef GRP - -#define GRP 40 -#ifdef HAVE_TLS - { NULL, 0, NULL, 0, - N_("TLS options"), GRP }, - { "tls-cert", OPTION_TLS_CERT, N_("FILE"), 0, - N_("set name of the TLS certificate file"), - GRP+1 }, - { "tls-ca", OPTION_TLS_CA, N_("FILE"), 0, - N_("set name of the TLS CA file"), - GRP+1 }, - { "tls-key", OPTION_TLS_KEY, N_("FILE"), 0, - N_("set name of the TLS key file"), - GRP+1 }, -#endif -#undef GRP - - { NULL } -}; +static void +opt_group(struct mu_parseopt *po, struct mu_option *opt, char const *arg) +{ + struct group *group = getgrnam(arg); + if (group) + { + if (!grouplist) + grouplist = mf_gid_list_alloc (); + mf_gid_list_add (grouplist, group->gr_gid); + } + else + { + mu_parseopt_error(po, _("unknown group: %s"), arg); + exit (EX_DATAERR); + } +} -int (*mta_mode) (void) = mta_stdio; -char *trace_name = NULL; -int append; -int statedir_option; +static void +opt_define (struct mu_parseopt *po, struct mu_option *opt, char const *arg) +{ + if (defer_define_macro (arg)) + { + mu_parseopt_error (po, _("wrong assignment format: %s"), arg); + exit (po->po_exit_error); + } +} -static unsigned long -parse_version (char *arg, struct argp_state *state) +static void +opt_milter_version (struct mu_parseopt *po, struct mu_option *opt, + char const *arg) { char *p; unsigned long maj, min, pat; maj = strtoul (arg, &p, 0); if (*p == 0) - return maj; + { + milter_version_option = maj; + return; + } else if (*p == '.') { min = strtoul (p + 1, &p, 0); @@ -392,17 +322,24 @@ parse_version (char *arg, struct argp_state *state) { pat = strtoul (p + 1, &p, 0); if (*p == 0) - return GACOPYZ_SM_MKVER (maj, min, pat); + { + milter_version_option = GACOPYZ_SM_MKVER (maj, min, pat); + return; + } } else if (*p == 0) - return GACOPYZ_SM_MKVER (maj, min, 0); + { + milter_version_option = GACOPYZ_SM_MKVER (maj, min, 0); + return; + } } - argp_error (state, _("invalid version syntax (near %s)"), p); - return 0; + mu_parseopt_error (po, _("invalid version syntax (near %s)"), p); + exit (po->po_exit_error); } -void -parse_milter_timeouts (char *arg, struct argp_state *state) +static void +opt_milter_timeout (struct mu_parseopt *po, struct mu_option *opt, + char const *arg) { while (*arg) { @@ -437,10 +374,14 @@ parse_milter_timeouts (char *arg, struct argp_state *state) break; default: - argp_error (state, _("unknown timeout: %c"), *arg); + mu_parseopt_error (po, _("unknown timeout: %c"), *arg); + exit (po->po_exit_error); } if (*++arg != '=') - argp_error (state, _("missing '=' after %c"), *arg); + { + mu_parseopt_error (po, _("missing '=' after %c"), *arg); + exit (po->po_exit_error); + } tv.tv_sec = strtoul (arg + 1, &p, 10); if (*p == '.') tv.tv_usec = strtoul (p + 1, &p, 10); @@ -451,12 +392,27 @@ parse_milter_timeouts (char *arg, struct argp_state *state) else if (*p == 0) arg = p; else - argp_error (state, _("unexpected character: %c"), *p); + { + mu_parseopt_error (po, _("unexpected character: %c"), *p); + exit (po->po_exit_error); + } tv.tv_usec = 0; milter_timeouts[ind] = tv; } } +static void +_sockaddr_error_getopt (void *data, const char *msg, const char *arg) +{ + struct mu_parseopt *po = data; + + if (arg) + mu_parseopt_error (po, "%s: %s", msg, arg); + else + mu_parseopt_error (po, "%s", msg); + exit (po->po_exit_error); +} + /* family [hostname address [port]] */ static int convert_sender_sockaddr (int argc, char **argv, @@ -602,171 +558,125 @@ convert_sender_sockaddr (int argc, char **argv, } static void -_sockaddr_error_getopt (void *data, const char *msg, const char *arg) +opt_sender_sockaddr (struct mu_parseopt *po, struct mu_option *opt, + char const *arg) { - struct argp_state *state = data; - - if (arg) - argp_error (state, "%s: %s", msg, arg); - else - argp_error (state, "%s", msg); + struct mu_wordsplit ws; + int rc; + + ws.ws_delim = ","; + rc = mu_wordsplit (arg, &ws, MU_WRDSF_DEFFLAGS|MU_WRDSF_DELIM); + if (rc) + { + mu_parseopt_error (po, _("error parsing --sender-sockaddr argument: %s"), + mu_wordsplit_strerror (&ws)); + exit (po->po_exit_error); + } + convert_sender_sockaddr (ws.ws_wordc, ws.ws_wordv, + _sockaddr_error_getopt, po); + mu_wordsplit_free (&ws); } -static error_t -parse_opt (int key, char *arg, struct argp_state *state) +static void +opt_gacopyz_log (struct mu_parseopt *po, struct mu_option *opt, + char const *arg) { - char *p; - - switch (key) + int lev = gacopyz_string_to_log_level (arg); + if (lev == -1) { - case 'a': - append = 1; - break; + mu_parseopt_error (po, _("%s: invalid log level"), arg); + exit (po->po_exit_error); + } + gacopyz_log_mask = SMI_LOG_FROM (lev); +} - case 'b': - switch (arg[0]) - { - case 'd': - mta_mode = mta_daemon; - break; - - case 's': - mta_mode = mta_stdio; - break; - - default: - argp_error (state, _("unsupported mode")); - } - break; +static struct mu_option mtasim_options[] = { + MU_OPTION_GROUP (N_("Mode selection")), + { NULL, 'b', N_("MODE"), MU_OPTION_DEFAULT, + N_("set MTA mode (-bd or -bs)"), + mu_c_string, NULL, opt_mta_mode }, + { "stdio", 0, NULL, MU_OPTION_DEFAULT, + N_("use the SMTP protocol on standard input and output (same as -bs)"), + mu_c_string, NULL, opt_mta_mode, "s" }, + { "daemon", 0, NULL, MU_OPTION_DEFAULT, + N_("run as daemon (same as -bd)"), + mu_c_string, NULL, opt_mta_mode, "d" }, + { "user", 'u', N_("NAME"), MU_OPTION_DEFAULT, + N_("run with this user privileges"), + mu_c_string, &user }, + { "group", 'g', N_("NAME"), MU_OPTION_DEFAULT, + N_("retain the supplementary group NAME when switching to user " + "privileges"), + mu_c_string, NULL, opt_group }, - case OPTION_GACOPYZ_LOG: - { - int lev = gacopyz_string_to_log_level(arg); - if (lev == -1) - argp_error(state, _("%s: invalid log level"), arg); - gacopyz_log_mask = SMI_LOG_FROM (lev); - } - break; - - case OPTION_STDIO: - mta_mode = mta_stdio; - break; + MU_OPTION_GROUP (N_("Operation modifiers")), + { "define", 'D', N_("MACRO=VALUE"), MU_OPTION_DEFAULT, + N_("define Sendmail macro"), + mu_c_string, NULL, opt_define }, + { "port", 'X', N_("PORT"), MU_OPTION_DEFAULT, + N_("communicate with Milter PORT"), + mu_c_string, &milter_port }, + { "statedir", 0, NULL, MU_OPTION_DEFAULT, + N_("pass temporary directory to mailfromd as its state dir (with -Xauto)"), + mu_c_bool, &statedir_option }, + { "body-chunk", 0, N_("NUMBER"), MU_OPTION_DEFAULT, + N_("set the body chunk for xxfi_body calls"), + mu_c_size, &max_body_chunk }, + { "milter-version", 0, N_("VER"), MU_OPTION_DEFAULT, + N_("force using the given Milter protocol version number"), + mu_c_string, NULL, opt_milter_version }, + { "milter-actions", 0, N_("BITMASK"), MU_OPTION_DEFAULT, + N_("force the given Milter actions"), + mu_c_ulong, &milter_acts_option }, + { "milter-proto", 0, N_("BITMASK"), MU_OPTION_DEFAULT, + N_("set Milter protocol capabilities"), + mu_c_ulong, &milter_proto_option }, + { "milter-timeout", 0, N_("F=V[,F=V...]"), MU_OPTION_DEFAULT, + N_("set milter timeouts"), + mu_c_string, NULL, opt_milter_timeout }, + { "sender-sockaddr", 0, + N_("FAMILY[,HOSTNAME,ADDRESS[,PORT]]"), MU_OPTION_DEFAULT, + N_("set sender socket address"), + mu_c_string, NULL, opt_sender_sockaddr }, + + { "interactive", 0, NULL, OPT_INTERACTIVE, + N_("interactive mode"), + mu_c_bool, &interactive }, + + { "prompt", 0, N_("STRING"), MU_OPTION_DEFAULT, + N_("set readline prompt"), + mu_c_string, &prompt }, + + MU_OPTION_GROUP(N_("Debugging and tracing")), + { "append", 'a', NULL, MU_OPTION_DEFAULT, + N_("append to the trace file"), + mu_c_bool, &append }, + { "trace-file", 0, N_("FILE"), MU_OPTION_DEFAULT, + N_("set name of the trace file"), + mu_c_string, &trace_name }, + { "verbose", 'v', NULL, MU_OPTION_DEFAULT, + N_("increase verbosity level"), + mu_c_incr, &verbose }, + { "gacopyz-log", 0, N_("LEVEL"), MU_OPTION_DEFAULT, + N_("set Gacopyz log level"), + mu_c_string, NULL, opt_gacopyz_log }, - case OPTION_DAEMON: - mta_mode = mta_daemon; - break; - #ifdef HAVE_TLS - case OPTION_TLS_CERT: - tls_cert = arg; - break; - - case OPTION_TLS_CA: - tls_cafile = arg; - break; - - case OPTION_TLS_KEY: - tls_key = arg; - break; -#endif - - case 'D': - if (defer_define_macro (arg)) - mu_error (_("wrong assignment format: %s"), arg); - break; - - case 'g': - add_group (arg); - break; - - case OPTION_TRACE_FILE: - trace_name = arg; - break; - - case 'u': - user = arg; - break; - - case 'X': - milter_port = arg; - break; - - case 'v': - verbose++; - break; - - case OPTION_BODY_CHUNK: - max_body_chunk = strtoul (arg, &p, 0); - if (*p) - argp_error (state, _("invalid number: %s"), arg); - break; - - case OPTION_MILTER_VERSION: - milter_version_option = parse_version (arg, state); - break; - - case OPTION_MILTER_PROTO: - milter_proto_option = strtoul (arg, &p, 0); - if (*p) - argp_error (state, _("invalid number: %s"), arg); - break; - - case OPTION_MILTER_ACTS: - milter_acts_option = strtoul (arg, &p, 0); - if (*p) - argp_error (state, _("invalid number: %s"), arg); - break; - - case OPTION_MILTER_TIMEOUT: - parse_milter_timeouts (arg, state); - break; - -#ifdef WITH_READLINE - case OPTION_NO_INTERACTIVE: - interactive = 0; - break; - - case OPTION_PROMPT: - prompt = arg; - break; + MU_OPTION_GROUP (N_("TLS options")), + { "tls-cert", 0, N_("FILE"), MU_OPTION_DEFAULT, + N_("set name of the TLS certificate file"), + mu_c_string, &tls_cert }, + { "tls-ca", 0, N_("FILE"), MU_OPTION_DEFAULT, + N_("set name of the TLS CA file"), + mu_c_string, &tls_cafile }, + { "tls-key", 0, N_("FILE"), MU_OPTION_DEFAULT, + N_("set name of the TLS key file"), + mu_c_string, &tls_key}, #endif + + MU_OPTION_END +}, *options[] = { mtasim_options, NULL }; - case OPTION_SENDER_SOCKADDR: - { - struct mu_wordsplit ws; - int rc; - - ws.ws_delim = ","; - rc = mu_wordsplit (arg, &ws, MU_WRDSF_DEFFLAGS|MU_WRDSF_DELIM); - if (rc) - argp_error (state, _("error parsing --sender-sockaddr argument: %s"), - mu_wordsplit_strerror (&ws)); - convert_sender_sockaddr (ws.ws_wordc, ws.ws_wordv, - _sockaddr_error_getopt, state); - mu_wordsplit_free (&ws); - } - break; - - case OPTION_STATEDIR: - statedir_option = 1; - break; - - default: - return ARGP_ERR_UNKNOWN; - } - return 0; -} - -static struct argp argp = { - options, - parse_opt, - NULL, - doc, - NULL, - NULL, - NULL -}; - void alloc_die_func () { @@ -993,7 +903,6 @@ start_mailfromd (int argc, char **argv) for (i = 1; i <= argc; i++) xargv[i] = argv[i-1]; xargv[i++] = "--mtasim"; - xargv[i++] = "--remove"; xargv[i++] = "--port"; xargv[i++] = milter_port; if (statedir_option) @@ -1042,36 +951,29 @@ static char **mta_command_completion (char *cmd, int start, int end); static char *get_history_file_name (void); #endif -static void -version (FILE *stream, struct argp_state *state) -{ - mailfromd_version("mtasim", stream); -} - -extern char *program_invocation_short_name;//FIXME +struct mu_cli_setup cli = { + .optv = options, + .prog_doc = prog_doc, +}; int main (int argc, char **argv) { - int status, index; + int status; mf_init_nls (); interactive = isatty(0); mu_alloc_die_hook = alloc_die_func; - if (!program_invocation_short_name) - program_invocation_short_name = argv[0]; - argp_program_version_hook = version; - if (argp_parse (&argp, argc, argv, 0, &index, NULL)) - exit (EX_USAGE); + mf_getopt (&cli, &argc, &argv, NULL, 0, NULL); priv_setup (); #ifdef WITH_READLINE if (interactive) { - rl_readline_name = program_invocation_short_name; + rl_readline_name = mu_program_name; rl_attempted_completion_function = (CPPFunction*) mta_command_completion; read_history (get_history_file_name ()); } @@ -1088,9 +990,6 @@ main (int argc, char **argv) } } - argc -= index; - argv += index; - if (!mta_mode) { mu_error (_("use either --stdio or --daemon")); diff --git a/pmult/pmult.c b/pmult/pmult.c index cc603f58..77ec1ede 100644 --- a/pmult/pmult.c +++ b/pmult/pmult.c @@ -23,7 +23,7 @@ #include <mailutils/mailutils.h> #include <mailutils/daemon.h> #include <mailutils/syslog.h> -#include <mailutils/libargp.h> +#include <mailutils/cli.h> #include <sysexits.h> #include <pthread.h> #include <gacopyz.h> @@ -47,7 +47,6 @@ #endif const char *program_version = "pmult (" PACKAGE_STRING ")"; -const char *package_bugreport = "<" PACKAGE_BUGREPORT ">"; int log_to_stderr = -1; const char *log_stream; @@ -403,7 +402,7 @@ struct mu_cfg_param client_cfg_param[] = { /* TRANSLATORS: 'milter' and 'pmilter' are keywords, do not translate them. */ N_("{milter [version: number]|pmilter}") }, - { "url", mu_cfg_string, NULL, mu_offsetof(struct pmult_client, url), NULL, + { "url", mu_c_string, NULL, mu_offsetof(struct pmult_client, url), NULL, N_("Set remote client URL.") }, { "write-timeout", mu_cfg_callback, NULL, 0, _cb_write_timeout, N_("Set write timeout."), @@ -427,30 +426,22 @@ struct mu_cfg_param client_cfg_param[] = { { NULL } }; -static int -_cb_portspec (void *data, mu_config_value_t *arg) +static char * +convert_url (char const *arg) { - char **pptr = data, *ptr; + char *ptr; char *proto = NULL; char *port = NULL; char *path = NULL; size_t len; - if (mu_cfg_assert_value_type (arg, MU_CFG_STRING)) - return 1; - if (gacopyz_parse_connection (arg->v.string, &proto, &port, &path)) - { - mu_error (_("invalid URL: %s"), arg->v.string); - return 1; - } + if (gacopyz_parse_connection (arg, &proto, &port, &path)) + return NULL; if (!proto) { if (port) - { - mu_error (_("invalid URL: %s"), arg->v.string); - return 1; - } + return NULL; ptr = mu_strdup (path); } else @@ -470,6 +461,19 @@ _cb_portspec (void *data, mu_config_value_t *arg) free (path); free (port); free (proto); + return ptr; +} + +static int +_cb_portspec (void *data, mu_config_value_t *arg) +{ + char **pptr = data, *ptr; + + if (mu_cfg_assert_value_type (arg, MU_CFG_STRING)) + return 1; + ptr = convert_url (arg->v.string); + if (!ptr) + return 1; *pptr = ptr; return 0; } @@ -654,23 +658,23 @@ struct mu_cfg_param pmult_cfg_param[] = { { "listen", mu_cfg_callback, &portspec, 0, _cb_portspec, N_("Listen for milter requests on the given URL."), N_("url") }, - { "max-threads-soft", mu_cfg_uint, &max_threads_soft, 0, NULL, + { "max-threads-soft", mu_c_uint, &max_threads_soft, 0, NULL, N_("Maximum number of threads (soft limit).") }, - { "max-threads-hard", mu_cfg_uint, &max_threads_hard, 0, NULL, + { "max-threads-hard", mu_c_uint, &max_threads_hard, 0, NULL, N_("Maximum number of threads (hard limit).") }, - { "max-pmilter-fd", mu_cfg_uint, &max_pmilter_fd, 0, NULL, + { "max-pmilter-fd", mu_c_uint, &max_pmilter_fd, 0, NULL, N_("Maximum number of file descriptors pmilter is allowed to open") }, { "client", mu_cfg_section }, - { "pmilter-debug", mu_cfg_uint, &pmilter_debug_level, 0, NULL, + { "pmilter-debug", mu_c_uint, &pmilter_debug_level, 0, NULL, N_("Set pmilter debug verbosity level.") }, - { "pidfile", mu_cfg_string, &pidfile, 0, NULL, + { "pidfile", mu_c_string, &pidfile, 0, NULL, N_("Write PID to this file.") }, - { "auth-macros", mu_cfg_bool, &want_auth_macros, 0, NULL, + { "auth-macros", mu_c_bool, &want_auth_macros, 0, NULL, N_("Pass auth macros to MAIL handler.") }, { "define-macros", mu_cfg_callback, NULL, 0, _cb_define, N_("Define macros for the given SMTP stage."), N_("stage: string> <macros: strings") }, - { "logger", mu_cfg_string, &log_stream, 0, NULL, + { "logger", mu_c_string, &log_stream, 0, NULL, N_("Set logger stream.") }, { NULL } }; @@ -754,94 +758,50 @@ pmult_cfg_init () /* Command line parsing */ -static char doc[] = N_("pmult -- pmilter multiplexer"); -static char args_doc[] = ""; - -enum { - OPTION_URL = 256, - OPTION_SYSLOG, - OPTION_LOG_TAG, - OPTION_NO_SIGNAL_HANDLER, -}; - -static struct argp_option options[] = { - { "url", OPTION_URL, N_("URL"), 0, - N_("listen on the given URL"), 0 }, - { "syslog", OPTION_SYSLOG, NULL, 0, - N_("log to syslog (default)"), }, - { "stderr", 's', NULL, 0, - N_("log to stderr"), }, - { "log-tag", OPTION_LOG_TAG, N_("STRING"), 0, - N_("set the identifier used in syslog messages to STRING"), }, - { "debug", 'x', N_("LEVEL"), 0, - N_("set debug verbosity level") }, - { "no-signal-handler", OPTION_NO_SIGNAL_HANDLER, NULL, 0, - N_("disable signal handling in the main thread (use for debugging).") }, - { NULL } -}; +static char prog_doc[] = N_("pmilter multiplexer"); -static error_t -parse_opt (int key, char *arg, struct argp_state *state) +static void +opt_url (struct mu_parseopt *po, struct mu_option *opt, char const *arg) { - static MUDEF_ARGP_NODE_LIST lst; - |