aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS8
-rw-r--r--configure.ac4
-rw-r--r--doc/mailfromd.texi9
-rw-r--r--lib/Makefile.am1
-rw-r--r--lib/libmf.h4
-rw-r--r--lib/mfgetopt.c55
-rw-r--r--lib/mudefs.h1
-rw-r--r--mtasim/mtasim.c553
-rw-r--r--pmult/pmult.c188
-rw-r--r--po/POTFILES.in1
-rw-r--r--src/calloutd.c63
-rw-r--r--src/mailfromd.h1
-rw-r--r--src/main.c42
-rw-r--r--src/mfdbtool.c310
-rw-r--r--tests/atlocal.in1
15 files changed, 500 insertions, 741 deletions
diff --git a/NEWS b/NEWS
index 502663d5..d65f83de 100644
--- a/NEWS
+++ b/NEWS
@@ -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;
-