summaryrefslogtreecommitdiffabout
authorSergey Poznyakoff <gray@gnu.org.ua>2009-05-07 12:17:34 (GMT)
committer Sergey Poznyakoff <gray@gnu.org.ua>2009-05-07 12:17:34 (GMT)
commit05a8bb0ca988f41f016420ffc7dde427e423c187 (patch) (unidiff)
treefff58297f073bec8148c2d5468a45d592eab0379
parent9f8f65324491b4186f4fd3c2580a8e0b14a248d9 (diff)
downloadmailfromd-05a8bb0ca988f41f016420ffc7dde427e423c187.tar.gz
mailfromd-05a8bb0ca988f41f016420ffc7dde427e423c187.tar.bz2
Implement v6 negotiation on the server side.
* gacopyz/stagenames.c: New file. * gacopyz/Makefile.am (libgacopyz_a_SOURCES): Add stagenames.c. * gacopyz/gacopyz.c (gacopyz_context_loop): Free req_macros. (gacopyz_addrcpt_par): rename to gacopyz_add_rcpt_par. * gacopyz/gacopyz.h (SM_LM_VRS_MAJOR, SM_LM_VRS_MAJOR) (SM_LM_VRS_PLVL, GACOPYZ_SM_MKVER): New macros. (macro_index): Rename to gacopyz_stage. All uses updated. (smfi_version): New proto. (gacopyz_addrcpt_par): rename to gacopyz_add_rcpt_par. (gacopyz_stage_name): New declaration. (gacopyz_srv_get_required_macros): New proto. (gacopyz_srv_set_version, gacopyz_srv_set_protocol) (gacopyz_srv_set_actions): 2nd argument is unsigned long. * gacopyz/server.c (struct gacopyz_srv): New member req_macros. (gacopyz_srv_get_required_macros): New function. (gacopyz_srv_destroy): Free req_macros. (gacopyz_srv_negotiate): Read macros. * mfd/gram.y (milter_state_name): Removed. Use gacopyz_stage_name instead. * mtasim/mtasim.c: New options: --gacopyz-log, --milter-proto, --milter-acts. * doc/mtasim.texi, doc/mailfromd.texi: Update.
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--doc/mailfromd.texi8
-rw-r--r--doc/mtasim.texi33
-rw-r--r--gacopyz/Makefile.am1
-rw-r--r--gacopyz/context.c4
-rw-r--r--gacopyz/gacopyz.c71
-rw-r--r--gacopyz/gacopyz.h58
-rw-r--r--gacopyz/gacopyz_priv.h4
-rw-r--r--gacopyz/server.c121
-rw-r--r--gacopyz/smfi.c17
-rw-r--r--gacopyz/stagenames.c27
-rw-r--r--mfd/engine.c4
-rw-r--r--mfd/gram.y44
-rw-r--r--mfd/mailfromd.h2
-rw-r--r--mtasim/mtasim.c111
14 files changed, 383 insertions, 122 deletions
diff --git a/doc/mailfromd.texi b/doc/mailfromd.texi
index 3f8f893..fd270c1 100644
--- a/doc/mailfromd.texi
+++ b/doc/mailfromd.texi
@@ -12295,6 +12295,7 @@ Overrides @code{#pragma option stack-trace}, which you are advised to
12295use instead (@pxref{pragma stack-trace}). @xref{tracing runtime 12295use instead (@pxref{pragma stack-trace}). @xref{tracing runtime
12296errors}, for more information on this feature. 12296errors}, for more information on this feature.
12297 12297
12298@anchor{gacopyz-log option}
12298@opsummary{gacopyz-log} 12299@opsummary{gacopyz-log}
12299@item --gacopyz-log=@var{level} 12300@item --gacopyz-log=@var{level}
12300Set desired logging level for @command{gacopyz} library 12301Set desired logging level for @command{gacopyz} library
@@ -12326,7 +12327,10 @@ Apr 28 09:00:11 host mailfromd[9411]: finishing
12326This level can be useful for debugging your scripts. 12327This level can be useful for debugging your scripts.
12327 12328
12328@item debug 12329@item debug
12329Log debugging information. This level prints huge amounts of 12330Log debugging information.
12331
12332@item proto
12333Log Milter protocol interactions. This level prints huge amounts of
12330information, in particular it displays dumps of each Milter packet 12334information, in particular it displays dumps of each Milter packet
12331sent and received. 12335sent and received.
12332 12336
@@ -12339,7 +12343,7 @@ other, it is seldom practical. Therefore, the option
12339log levels @samp{warn}, @samp{err} and @samp{fatal}. It is the 12343log levels @samp{warn}, @samp{err} and @samp{fatal}. It is the
12340default. If you need to trace each subprocess startup and shutdown, 12344default. If you need to trace each subprocess startup and shutdown,
12341set @option{--gacopyz-log=info}. Setting the logging level to 12345set @option{--gacopyz-log=info}. Setting the logging level to
12342@samp{debug} can be needed only for @command{Gacopyz} developers, to 12346@samp{proto} can be needed only for @command{Gacopyz} developers, to
12343debug the protocol. 12347debug the protocol.
12344 12348
12345@xref{Testing Filter Scripts}. 12349@xref{Testing Filter Scripts}.
diff --git a/doc/mtasim.texi b/doc/mtasim.texi
index a8849fe..513d045 100644
--- a/doc/mtasim.texi
+++ b/doc/mtasim.texi
@@ -454,6 +454,14 @@ cases.
454 Define Sendmail macro @var{macro} to the given @var{value}. It is 454 Define Sendmail macro @var{macro} to the given @var{value}. It is
455similar to the @code{\D} administrative command (@pxref{D command}) 455similar to the @code{\D} administrative command (@pxref{D command})
456 456
457@mtasimopt{gacopyz-log, summary}
458@item --gacopyz-log=@var{level}
459Set desired logging level for @command{gacopyz} library
460(@pxref{Gacopyz}). @xref{gacopyz-log option}, for a detailed
461description of @var{level}. Notice, that unless this option is used,
462the @option{--verbose} (@option{-v}) command line option implies
463@option{--gacopyz-log=debug}.
464
457@mtasimopt{group, summary} 465@mtasimopt{group, summary}
458@mtindex g, -g, @command{mtasim} option, summary 466@mtindex g, -g, @command{mtasim} option, summary
459@item --group=@var{name} 467@item --group=@var{name}
@@ -476,11 +484,29 @@ privileges.
476 Display a short help summary 484 Display a short help summary
477 485
478@mtasimopt{milter-version, summary} 486@mtasimopt{milter-version, summary}
479@item --milter-version=@var{number} 487@item --milter-version=@var{version}
480 Force using the given Milter protocol version number. This option 488 Force using the given Milter protocol version number. The
489@var{version} argument is either a numeric version (e.g. @samp{2}), or
490a version string in form @samp{@var{major}.@var{minor}[.@var{patch}]},
491where square brackets indicate optional part. The default is
492@samp{1.0.0}. If @var{version} is any of @samp{2}, @samp{3} or
493@samp{1.0.0}, the default protocol capabilities and actions for that
494version are set automatically. This option
481is intended for development and testing of the Gacopyz library 495is intended for development and testing of the Gacopyz library
482(@pxref{Gacopyz}). 496(@pxref{Gacopyz}).
483 497
498@mtasimopt{milter-proto, summary}
499@item --milter-proto=@var{bitmask}
500Set Milter protocol capabilities. See @file{gacopyz/gacopyz.h} for
501the meaning of various bits in the @var{bitmask}. Look for the C
502macros with the prefix @samp{SMFIP_}.
503
504@mtasimopt{milter-actions, summary}
505@item --milter-actions=@var{bitmask}
506Set Milter actions. See @file{gacopyz/gacopyz.h} for
507the meaning of various bits in the @var{bitmask}. Look for the C
508macros with the prefix @samp{SMFIF_}.
509
484@mtasimopt{no-interactive, summary} 510@mtasimopt{no-interactive, summary}
485@item --no-interactive 511@item --no-interactive
486 Not-interactive mode (disable readline). @xref{Command Line Editing, , 512 Not-interactive mode (disable readline). @xref{Command Line Editing, ,
@@ -520,7 +546,8 @@ is the default mode for @command{mtasim}. @xref{interactive mode}.
520@mtindex v, -v, @command{mtasim} option, summary 546@mtindex v, -v, @command{mtasim} option, summary
521@item --verbose 547@item --verbose
522@itemx -v 548@itemx -v
523 Increase verbosity level. 549 Increase verbosity level. Implies @option{--gacopyz-log=debug},
550unless that option is used explicitly.
524 551
525@item --version 552@item --version
526@itemx -V 553@itemx -V
diff --git a/gacopyz/Makefile.am b/gacopyz/Makefile.am
index 7d8c012..d658b3e 100644
--- a/gacopyz/Makefile.am
+++ b/gacopyz/Makefile.am
@@ -27,6 +27,7 @@ libgacopyz_a_SOURCES = \
27 mfapi.h\ 27 mfapi.h\
28 proc.c\ 28 proc.c\
29 server.c\ 29 server.c\
30 stagenames.c\
30 trans.h 31 trans.h
31 32
32EXTRA_DIST=trans.tab trans.awk 33EXTRA_DIST=trans.tab trans.awk
diff --git a/gacopyz/context.c b/gacopyz/context.c
index 41d64c4..12094fd 100644
--- a/gacopyz/context.c
+++ b/gacopyz/context.c
@@ -1,5 +1,5 @@
1/* This file is part of gacopyz. 1/* This file is part of gacopyz.
2 Copyright (C) 2006, 2007 Sergey Poznyakoff 2 Copyright (C) 2006, 2007, 2009 Sergey Poznyakoff
3 3
4 This program is free software; you can redistribute it and/or modify 4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by 5 it under the terms of the GNU General Public License as published by
@@ -50,7 +50,7 @@ gacopyz_getsymval(SMFICTX *ctx, const char *name)
50 if (name[len-1] == '}') 50 if (name[len-1] == '}')
51 len--; 51 len--;
52 52
53 for (i = maci_max - 1; i >= 0; i--) { 53 for (i = gacopyz_stage_max - 1; i >= 0; i--) {
54 if (ctx->macros[i].argv) { 54 if (ctx->macros[i].argv) {
55 char **p; 55 char **p;
56 56
diff --git a/gacopyz/gacopyz.c b/gacopyz/gacopyz.c
index f29681b..e26f7e2 100644
--- a/gacopyz/gacopyz.c
+++ b/gacopyz/gacopyz.c
@@ -764,7 +764,7 @@ make_optneg_buf(SMFICTX *ctx, gacopyz_uint32_t *vbuf,
764 size_t bufsize = 0; 764 size_t bufsize = 0;
765 int i; 765 int i;
766 766
767 for (i = 0; i < maci_max; i++) { 767 for (i = 0; i < gacopyz_stage_max; i++) {
768 if (ctx->req_macros[i]) 768 if (ctx->req_macros[i])
769 bufsize += strlen(ctx->req_macros[i]) + 1 + 769 bufsize += strlen(ctx->req_macros[i]) + 1 +
770 sizeof(gacopyz_uint32_t); 770 sizeof(gacopyz_uint32_t);
@@ -789,7 +789,7 @@ make_optneg_buf(SMFICTX *ctx, gacopyz_uint32_t *vbuf,
789 *pbuf = buf; 789 *pbuf = buf;
790 790
791 buf += OPTLEN; 791 buf += OPTLEN;
792 for (i = 0; i < maci_max; i++) { 792 for (i = 0; i < gacopyz_stage_max; i++) {
793 if (ctx->req_macros[i]) { 793 if (ctx->req_macros[i]) {
794 gacopyz_uint32_t v; 794 gacopyz_uint32_t v;
795 size_t len; 795 size_t len;
@@ -901,7 +901,7 @@ macro_assoc_free(macro_assoc_t *p)
901static void 901static void
902clear_macros(SMFICTX *ctx, int i) 902clear_macros(SMFICTX *ctx, int i)
903{ 903{
904 for (; i < maci_max; i++) 904 for (; i < gacopyz_stage_max; i++)
905 macro_assoc_free(&ctx->macros[i]); 905 macro_assoc_free(&ctx->macros[i]);
906} 906}
907 907
@@ -962,7 +962,7 @@ shan_abort(SMFICTX *ctx, union state_arg *arg, unsigned char *cmd)
962static state_ret_type 962static state_ret_type
963shan_macro(SMFICTX *ctx, union state_arg *arg, unsigned char *cmd) 963shan_macro(SMFICTX *ctx, union state_arg *arg, unsigned char *cmd)
964{ 964{
965 enum macro_index ind; 965 enum gacopyz_stage ind;
966 char **p; 966 char **p;
967 967
968 if (!arg->argv.v) 968 if (!arg->argv.v)
@@ -970,31 +970,31 @@ shan_macro(SMFICTX *ctx, union state_arg *arg, unsigned char *cmd)
970 970
971 switch (arg->argv.cmd) { 971 switch (arg->argv.cmd) {
972 case SMFIC_CONNECT: 972 case SMFIC_CONNECT:
973 ind = maci_conn; 973 ind = gacopyz_stage_conn;
974 break; 974 break;
975 975
976 case SMFIC_HELO: 976 case SMFIC_HELO:
977 ind = maci_helo; 977 ind = gacopyz_stage_helo;
978 break; 978 break;
979 979
980 case SMFIC_MAIL: 980 case SMFIC_MAIL:
981 ind = maci_mail; 981 ind = gacopyz_stage_mail;
982 break; 982 break;
983 983
984 case SMFIC_RCPT: 984 case SMFIC_RCPT:
985 ind = maci_rcpt; 985 ind = gacopyz_stage_rcpt;
986 break; 986 break;
987 987
988 case SMFIC_DATA: 988 case SMFIC_DATA:
989 ind = maci_data; 989 ind = gacopyz_stage_data;
990 break; 990 break;
991 991
992 case SMFIC_BODYEOB: 992 case SMFIC_BODYEOB:
993 ind = maci_eom; 993 ind = gacopyz_stage_eom;
994 break; 994 break;
995 995
996 case SMFIC_EOH: 996 case SMFIC_EOH:
997 ind = maci_eoh; 997 ind = gacopyz_stage_eoh;
998 break; 998 break;
999 999
1000 default: 1000 default:
@@ -1346,33 +1346,33 @@ shan_unkn(SMFICTX *ctx, union state_arg *arg, unsigned char *cmd)
1346 1346
1347static struct state_disp disp[] = { 1347static struct state_disp disp[] = {
1348 { SMFIC_ABORT, "abort", 1348 { SMFIC_ABORT, "abort",
1349 arg_no_args, shan_abort, st_abrt, CT_CNT, maci_none }, 1349 arg_no_args, shan_abort, st_abrt, CT_CNT, gacopyz_stage_none },
1350 { SMFIC_MACRO, "macro", 1350 { SMFIC_MACRO, "macro",
1351 arg_argvc, shan_macro, st_none, CT_CNT, maci_none }, 1351 arg_argvc, shan_macro, st_none, CT_CNT, gacopyz_stage_none },
1352 { SMFIC_BODY, "body", 1352 { SMFIC_BODY, "body",
1353 arg_one_string, shan_body, st_body, CT_CNT, maci_none }, 1353 arg_one_string, shan_body, st_body, CT_CNT, gacopyz_stage_none },
1354 { SMFIC_CONNECT, "connect", 1354 { SMFIC_CONNECT, "connect",
1355 arg_two_strings, shan_connect, st_conn, CT_CLR, maci_conn }, 1355 arg_two_strings, shan_connect, st_conn, CT_CLR, gacopyz_stage_conn },
1356 { SMFIC_BODYEOB, "endm", 1356 { SMFIC_BODYEOB, "endm",
1357 arg_one_string, shan_endm, st_endm, CT_CNT, maci_eom }, 1357 arg_one_string, shan_endm, st_endm, CT_CNT, gacopyz_stage_eom },
1358 { SMFIC_HELO, "helo", 1358 { SMFIC_HELO, "helo",
1359 arg_one_string, shan_helo, st_helo, CT_CLR, maci_helo }, 1359 arg_one_string, shan_helo, st_helo, CT_CLR, gacopyz_stage_helo },
1360 { SMFIC_HEADER, "header", 1360 { SMFIC_HEADER, "header",
1361 arg_two_strings, shan_header, st_hdrs, CT_CNT, maci_none }, 1361 arg_two_strings, shan_header, st_hdrs, CT_CNT, gacopyz_stage_none },
1362 { SMFIC_MAIL, "mail", 1362 { SMFIC_MAIL, "mail",
1363 arg_argv, shan_mail, st_mail, CT_CLR, maci_mail }, 1363 arg_argv, shan_mail, st_mail, CT_CLR, gacopyz_stage_mail },
1364 { SMFIC_OPTNEG, "optneg", 1364 { SMFIC_OPTNEG, "optneg",
1365 arg_ints, shan_optneg, st_opts, CT_CNT, maci_none }, 1365 arg_ints, shan_optneg, st_opts, CT_CNT, gacopyz_stage_none },
1366 { SMFIC_EOH, "eoh", 1366 { SMFIC_EOH, "eoh",
1367 arg_no_args, shan_eoh, st_eohs, CT_CNT, maci_none }, 1367 arg_no_args, shan_eoh, st_eohs, CT_CNT, gacopyz_stage_none },
1368 { SMFIC_QUIT, "quit", 1368 { SMFIC_QUIT, "quit",
1369 arg_no_args, shan_quit, st_quit, CT_END, maci_none }, 1369 arg_no_args, shan_quit, st_quit, CT_END, gacopyz_stage_none },
1370 { SMFIC_DATA, "data", 1370 { SMFIC_DATA, "data",
1371 arg_no_args, shan_data, st_data, CT_CNT, maci_none }, 1371 arg_no_args, shan_data, st_data, CT_CNT, gacopyz_stage_none },
1372 { SMFIC_RCPT, "rcpt", 1372 { SMFIC_RCPT, "rcpt",
1373 arg_argv, shan_rcpt, st_rcpt, CT_IGN|CT_CLR, maci_rcpt }, 1373 arg_argv, shan_rcpt, st_rcpt, CT_IGN|CT_CLR, gacopyz_stage_rcpt },
1374 { SMFIC_UNKNOWN, "unknown", 1374 { SMFIC_UNKNOWN, "unknown",
1375 arg_one_string, shan_unkn, st_unkn, CT_IGN|CT_CLR, maci_none } 1375 arg_one_string, shan_unkn, st_unkn, CT_IGN|CT_CLR, gacopyz_stage_none }
1376}; 1376};
1377 1377
1378struct state_disp * 1378struct state_disp *
@@ -1488,6 +1488,17 @@ report_command(enum state state, enum state next_state,
1488 gacopyz_logdump(SMI_LOG_WARN, _("buffer"), buffer, size); 1488 gacopyz_logdump(SMI_LOG_WARN, _("buffer"), buffer, size);
1489} 1489}
1490 1490
1491static int
1492ctx_free(SMFICTX *ctx)
1493{
1494 int i;
1495
1496 free(ctx->reply);
1497 clear_macros(&ctx, 0);
1498 for (i = 0; i < gacopyz_stage_max; i++)
1499 free(ctx->req_macros[i]);
1500}
1501
1491int 1502int
1492gacopyz_context_loop(int fd, struct smfiDesc *desc) 1503gacopyz_context_loop(int fd, struct smfiDesc *desc)
1493{ 1504{
@@ -1648,9 +1659,9 @@ gacopyz_context_loop(int fd, struct smfiDesc *desc)
1648 free(buffer); 1659 free(buffer);
1649 if (desc->xxfi_close) 1660 if (desc->xxfi_close)
1650 desc->xxfi_close(&ctx); 1661 desc->xxfi_close(&ctx);
1651 free(ctx.reply);
1652 clear_macros(&ctx, 0);
1653 1662
1663 ctx_free(&ctx);
1664
1654 if (desc->xxfi_finish) 1665 if (desc->xxfi_finish)
1655 desc->xxfi_finish(); 1666 desc->xxfi_finish();
1656 1667
@@ -2026,7 +2037,7 @@ gacopyz_quarantine(SMFICTX *ctx, const char *reason)
2026} 2037}
2027 2038
2028int 2039int
2029gacopyz_addrcpt_par(SMFICTX *ctx, const char *rcpt, const char *args) 2040gacopyz_add_rcpt_par(SMFICTX *ctx, const char *rcpt, const char *args)
2030{ 2041{
2031 if (!rcpt || !*rcpt) 2042 if (!rcpt || !*rcpt)
2032 return MI_FAILURE; 2043 return MI_FAILURE;
@@ -2046,9 +2057,9 @@ gacopyz_chgfrom(SMFICTX *ctx, const char *from, const char *args)
2046} 2057}
2047 2058
2048int 2059int
2049gacopyz_setsymlist(SMFICTX *ctx, enum macro_index ind, const char *macros) 2060gacopyz_setsymlist(SMFICTX *ctx, enum gacopyz_stage ind, const char *macros)
2050{ 2061{
2051 if (ind < 0 || ind >= maci_max) 2062 if (ind < 0 || ind >= gacopyz_stage_max)
2052 return MI_FAILURE; 2063 return MI_FAILURE;
2053 if (ctx->req_macros[ind]) 2064 if (ctx->req_macros[ind])
2054 free(ctx->req_macros[ind]); 2065 free(ctx->req_macros[ind]);
diff --git a/gacopyz/gacopyz.h b/gacopyz/gacopyz.h
index f0b5bff..f7d547a 100644
--- a/gacopyz/gacopyz.h
+++ b/gacopyz/gacopyz.h
@@ -48,6 +48,13 @@ extern "C" {
48 /* Implementation version number */ 48 /* Implementation version number */
49#define SMFI_VERSION 0x01000000 49#define SMFI_VERSION 0x01000000
50 50
51#define SM_LM_VRS_MAJOR(v) (((v) & 0x7f000000) >> 24)
52#define SM_LM_VRS_MINOR(v) (((v) & 0x007fff00) >> 8)
53#define SM_LM_VRS_PLVL(v) ((v) & 0x0000007f)
54
55#define GACOPYZ_SM_MKVER(maj,min,pat) \
56 ((((maj) & 0x7f)<<24) | (((min) & 0x7ffff) << 8) | ((pat) & 0x7f))
57
51 /* Milter protocol version */ 58 /* Milter protocol version */
52#define SMFI_PROT_VERSION 6 59#define SMFI_PROT_VERSION 6
53 60
@@ -199,26 +206,26 @@ typedef union {
199 struct sockaddr_un sunix; 206 struct sockaddr_un sunix;
200} milter_sockaddr_t; 207} milter_sockaddr_t;
201 208
202enum macro_index { 209enum gacopyz_stage {
203 maci_conn, 210 gacopyz_stage_conn,
204 maci_helo, 211 gacopyz_stage_helo,
205 maci_mail, 212 gacopyz_stage_mail,
206 maci_rcpt, 213 gacopyz_stage_rcpt,
207 maci_data, 214 gacopyz_stage_data,
208 maci_eom, 215 gacopyz_stage_eom,
209 maci_eoh, 216 gacopyz_stage_eoh,
210 217
211 maci_max, 218 gacopyz_stage_max,
212 maci_none = maci_max 219 gacopyz_stage_none = gacopyz_stage_max
213}; 220};
214 221
215#define SMFIM_CONNECT maci_conn 222#define SMFIM_CONNECT gacopyz_stage_conn
216#define SMFIM_HELO maci_helo 223#define SMFIM_HELO gacopyz_stage_helo
217#define SMFIM_ENVFROM maci_mail 224#define SMFIM_ENVFROM gacopyz_stage_mail
218#define SMFIM_ENVRCPT maci_rcpt 225#define SMFIM_ENVRCPT gacopyz_stage_rcpt
219#define SMFIM_DATA maci_data 226#define SMFIM_DATA gacopyz_stage_data
220#define SMFIM_EOM maci_eom 227#define SMFIM_EOM gacopyz_stage_eom
221#define SMFIM_EOH maci_eoh 228#define SMFIM_EOH gacopyz_stage_eoh
222 229
223 #define _SOCK_ADDR milter_sockaddr_t 230 #define _SOCK_ADDR milter_sockaddr_t
224#define smfiDesc gacopyz_milter_descr 231#define smfiDesc gacopyz_milter_descr
@@ -275,6 +282,7 @@ struct gacopyz_milter_descr
275}; 282};
276 283
277/* Standard API calls */ 284/* Standard API calls */
285extern int smfi_version (unsigned int *, unsigned int *, unsigned int *);
278extern int smfi_opensocket (int); 286extern int smfi_opensocket (int);
279extern int smfi_register (struct smfiDesc); 287extern int smfi_register (struct smfiDesc);
280extern int smfi_main (void); 288extern int smfi_main (void);
@@ -365,15 +373,17 @@ int gacopyz_replace_body(SMFICTX *ctx, const unsigned char *bodyp,
365 size_t bodylen); 373 size_t bodylen);
366int gacopyz_progress(SMFICTX *ctx); 374int gacopyz_progress(SMFICTX *ctx);
367int gacopyz_quarantine(SMFICTX *ctx, const char *reason); 375int gacopyz_quarantine(SMFICTX *ctx, const char *reason);
368int gacopyz_addrcpt_par(SMFICTX *ctx, const char *rcpt, const char *args); 376int gacopyz_add_rcpt_par(SMFICTX *ctx, const char *rcpt, const char *args);
369int gacopyz_chgfrom(SMFICTX *ctx, const char *from, const char *args); 377int gacopyz_chgfrom(SMFICTX *ctx, const char *from, const char *args);
370 378
371int gacopyz_setsymlist(SMFICTX *ctx, enum macro_index ind, const char *macros); 379int gacopyz_setsymlist(SMFICTX *ctx, enum gacopyz_stage ind, const char *macros);
372 380
373int gacopyz_setpriv (SMFICTX *ctx, void *data); 381int gacopyz_setpriv (SMFICTX *ctx, void *data);
374void *gacopyz_getpriv (SMFICTX *ctx); 382void *gacopyz_getpriv (SMFICTX *ctx);
375 383
376/* Logging (extensions) */ 384/* Logging (extensions) */
385extern const char *gacopyz_stage_name[gacopyz_stage_max];
386
377#define GACOPYZ_VBUFSIZE 69 387#define GACOPYZ_VBUFSIZE 69
378size_t gacopyz_format_vbuf(char vbuf[GACOPYZ_VBUFSIZE], const char *buf, 388size_t gacopyz_format_vbuf(char vbuf[GACOPYZ_VBUFSIZE], const char *buf,
379 size_t size); 389 size_t size);
@@ -411,6 +421,10 @@ void gacopyz_srv_iterate_macros (gacopyz_srv_t srv,
411 void *data), 421 void *data),
412 void *data); 422 void *data);
413void gacopyz_srv_count_macros (gacopyz_srv_t srv, size_t *count); 423void gacopyz_srv_count_macros (gacopyz_srv_t srv, size_t *count);
424
425const char **gacopyz_srv_get_required_macros(gacopyz_srv_t srv,
426 enum gacopyz_stage stage);
427
414int gacopyz_srv_connect (gacopyz_srv_t srv); 428int gacopyz_srv_connect (gacopyz_srv_t srv);
415int gacopyz_srv_init(gacopyz_srv_t srv); 429int gacopyz_srv_init(gacopyz_srv_t srv);
416int gacopyz_srv_negotiate(gacopyz_srv_t srv); 430int gacopyz_srv_negotiate(gacopyz_srv_t srv);
@@ -440,9 +454,9 @@ void gacopyz_srv_set_callback(gacopyz_srv_t srv,
440void gacopyz_srv_set_callback_data(gacopyz_srv_t, void *); 454void gacopyz_srv_set_callback_data(gacopyz_srv_t, void *);
441 455
442int gacopyz_srv_set_source(gacopyz_srv_t srv, unsigned long addr); 456int gacopyz_srv_set_source(gacopyz_srv_t srv, unsigned long addr);
443int gacopyz_srv_set_version(gacopyz_srv_t srv, int version); 457int gacopyz_srv_set_version(gacopyz_srv_t srv, unsigned long version);
444int gacopyz_srv_set_protocol(gacopyz_srv_t srv, int proto); 458int gacopyz_srv_set_protocol(gacopyz_srv_t srv, unsigned long proto);
445int gacopyz_srv_set_actions(gacopyz_srv_t srv, int acts); 459int gacopyz_srv_set_actions(gacopyz_srv_t srv, unsigned long acts);
446 460
447#define GACOPYZ_WRITE_TIMEOUT 10 461#define GACOPYZ_WRITE_TIMEOUT 10
448#define GACOPYZ_READ_TIMEOUT 10 462#define GACOPYZ_READ_TIMEOUT 10
diff --git a/gacopyz/gacopyz_priv.h b/gacopyz/gacopyz_priv.h
index 76be161..d7e1ffe 100644
--- a/gacopyz/gacopyz_priv.h
+++ b/gacopyz/gacopyz_priv.h
@@ -34,8 +34,8 @@ struct smfi_str {
34 unsigned long mta_pflags; /* pflags supported by MTA */ 34 unsigned long mta_pflags; /* pflags supported by MTA */
35 unsigned long aflags; /* milter action flags (from xxfi_flags) */ 35 unsigned long aflags; /* milter action flags (from xxfi_flags) */
36 int nmacros; /* Number of entries in macros */ 36 int nmacros; /* Number of entries in macros */
37 macro_assoc_t macros[maci_max]; /* Macro tables */ 37 macro_assoc_t macros[gacopyz_stage_max]; /* Macro tables */
38 char *req_macros[maci_max]; /* Required macros */ 38 char *req_macros[gacopyz_stage_max]; /* Required macros */
39 char *reply; /* reply code */ 39 char *reply; /* reply code */
40 void *privdata; /* private data */ 40 void *privdata; /* private data */
41}; 41};
diff --git a/gacopyz/server.c b/gacopyz/server.c
index a61836e..e7cfa64 100644
--- a/gacopyz/server.c
+++ b/gacopyz/server.c
@@ -1,5 +1,5 @@
1/* This file is part of gacopyz. 1/* This file is part of gacopyz.
2 Copyright (C) 2007, 2008 Sergey Poznyakoff 2 Copyright (C) 2007, 2008, 2009 Sergey Poznyakoff
3 3
4 This program is free software; you can redistribute it and/or modify 4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by 5 it under the terms of the GNU General Public License as published by
@@ -49,6 +49,7 @@ struct gacopyz_srv {
49 unsigned long version; 49 unsigned long version;
50 unsigned long acts; 50 unsigned long acts;
51 unsigned long proto; 51 unsigned long proto;
52 char **req_macros[gacopyz_stage_max]; /* Required macros */
52 53
53 int (*cb_reply) (gacopyz_srv_t srv, int cmd, int rcmd, void *data); 54 int (*cb_reply) (gacopyz_srv_t srv, int cmd, int rcmd, void *data);
54 void *cb_data; 55 void *cb_data;
@@ -279,6 +280,13 @@ gacopyz_srv_count_macros(gacopyz_srv_t srv, size_t *count)
279} 280}
280 281
281 282
283const char **
284gacopyz_srv_get_required_macros(gacopyz_srv_t srv, enum gacopyz_stage stage)
285{
286 return (const char **) srv->req_macros[stage];
287}
288
289
282 290
283struct timeval default_gacopyz_timeout[GACOPYZ_TO_COUNT] = { 291struct timeval default_gacopyz_timeout[GACOPYZ_TO_COUNT] = {
284 { GACOPYZ_WRITE_TIMEOUT, 0 }, 292 { GACOPYZ_WRITE_TIMEOUT, 0 },
@@ -612,7 +620,7 @@ gacopyz_srv_set_source(gacopyz_srv_t srv, unsigned long addr)
612} 620}
613 621
614int 622int
615gacopyz_srv_set_version(gacopyz_srv_t srv, int version) 623gacopyz_srv_set_version(gacopyz_srv_t srv, unsigned long version)
616{ 624{
617 GACOPYZ_ASSERT(srv); 625 GACOPYZ_ASSERT(srv);
618 626
@@ -621,7 +629,7 @@ gacopyz_srv_set_version(gacopyz_srv_t srv, int version)
621} 629}
622 630
623int 631int
624gacopyz_srv_set_protocol(gacopyz_srv_t srv, int proto) 632gacopyz_srv_set_protocol(gacopyz_srv_t srv, unsigned long proto)
625{ 633{
626 GACOPYZ_ASSERT(srv); 634 GACOPYZ_ASSERT(srv);
627 635
@@ -630,7 +638,7 @@ gacopyz_srv_set_protocol(gacopyz_srv_t srv, int proto)
630} 638}
631 639
632int 640int
633gacopyz_srv_set_actions(gacopyz_srv_t srv, int acts) 641gacopyz_srv_set_actions(gacopyz_srv_t srv, unsigned long acts)
634{ 642{
635 GACOPYZ_ASSERT(srv); 643 GACOPYZ_ASSERT(srv);
636 644
@@ -638,15 +646,24 @@ gacopyz_srv_set_actions(gacopyz_srv_t srv, int acts)
638 return MI_SUCCESS; 646 return MI_SUCCESS;
639} 647}
640 648
641
642void 649void
643gacopyz_srv_destroy(gacopyz_srv_t *p) 650gacopyz_srv_destroy(gacopyz_srv_t *p)
644{ 651{
652 int i;
653
645 gacopyz_srv_t srv = *p; 654 gacopyz_srv_t srv = *p;
646 gacopyz_srv_clear_macros(srv); 655 gacopyz_srv_clear_macros(srv);
647 free(srv->portspec); 656 free(srv->portspec);
648 free(srv->id); 657 free(srv->id);
649 free(srv->def); 658 free(srv->def);
659 for (i = 0; i < gacopyz_stage_max; i++)
660 if (srv->req_macros[i]) {
661 int j;
662
663 for (j = 0; srv->req_macros[i][j]; j++)
664 free(srv->req_macros[i][j]);
665 free(srv->req_macros[i]);
666 }
650 free(srv->buf); 667 free(srv->buf);
651 free(srv); 668 free(srv);
652 *p = 0; 669 *p = 0;
@@ -860,6 +877,94 @@ gacopyz_srv_connect(gacopyz_srv_t srv)
860 return MI_SUCCESS; 877 return MI_SUCCESS;
861} 878}
862 879
880#define ISWS(c) ((c) == ' ' || (c) == '\t')
881
882static void
883parse_macros(gacopyz_srv_t srv, enum gacopyz_stage stage, char *buf)
884{
885 char *p;
886 char **argv;
887 size_t count;
888
889 count = 0;
890 for (p = buf; *p;) {
891 while (*p && ISWS(*p))
892 p++;
893 if (*p) {
894 count++;
895 while (*p && !ISWS(*p))
896 p++;
897 }
898 }
899 if (count == 0)
900 return;
901 GACOPYZ_ALLOC(srv, argv = calloc(count + 1, sizeof(argv[0])));
902 count = 0;
903 for (p = buf; *p;) {
904 while (*p && ISWS(*p))
905 p++;
906 if (*p) {
907 size_t i;
908 char *str = p;
909
910 for (i = 0; *p && !ISWS(*p); p++, i++)
911 ;
912 if (i > 0) {
913 char *newstr;
914
915 if (*str == '{' && str[i-1] == '}') {
916 str++;
917 i -= 2;
918 }
919 GACOPYZ_ALLOC(srv, newstr = malloc(i + 1));
920 memcpy(newstr, str, i);
921 newstr[i] = 0;
922 argv[count++] = newstr;
923 }
924 }
925 }
926 argv[count] = NULL;
927 srv->req_macros[stage] = argv;
928}
929
930
931static void
932read_macros(gacopyz_srv_t srv)
933{
934 char *buf = srv->buf + 3 * sizeof(gacopyz_uint32_t);
935 size_t size = srv->bufsize - 3 * sizeof(gacopyz_uint32_t);
936
937 while (size > sizeof(gacopyz_uint32_t)) {
938 gacopyz_uint32_t v;
939 unsigned n;
940 size_t len;
941
942 memcpy (&v, buf, sizeof(gacopyz_uint32_t));
943 n = ntohl(v);
944 if (n >= gacopyz_stage_max) {
945 gacopyz_io_log(&srv->iod, SMI_LOG_ERR,
946 _("received invalid stage number"));
947 break;
948 }
949 buf += sizeof(gacopyz_uint32_t);
950 size -= sizeof(gacopyz_uint32_t);
951 if (size == 0)
952 break;
953 len = strlen(buf) + 1;
954 if (len > size) {
955 gacopyz_io_log(&srv->iod, SMI_LOG_ERR,
956 _("invalid macro list"));
957 break;
958 }
959 gacopyz_io_log(&srv->iod, SMI_LOG_DEBUG,
960 _("macros for stage \"%s\" (%d): %s"),
961 gacopyz_stage_name[n], n, buf);
962 parse_macros(srv, n, buf);
963 buf += len;
964 size -= len;
965 }
966}
967
863int 968int
864gacopyz_srv_negotiate(gacopyz_srv_t srv) 969gacopyz_srv_negotiate(gacopyz_srv_t srv)
865{ 970{
@@ -927,6 +1032,10 @@ gacopyz_srv_negotiate(gacopyz_srv_t srv)
927 return MI_FAILURE; 1032 return MI_FAILURE;
928 } 1033 }
929 1034
1035 if (milter_version > 3
1036 && srv->bufsize > 3 * sizeof(gacopyz_uint32_t))
1037 read_macros(srv);
1038
930 srv->version = milter_version; 1039 srv->version = milter_version;
931 srv->acts = milter_acts; 1040 srv->acts = milter_acts;
932 srv->proto = milter_proto; 1041 srv->proto = milter_proto;
@@ -1209,8 +1318,6 @@ gacopyz_srv_conn(gacopyz_srv_t srv, const char *hostname, struct sockaddr *sa)
1209int 1318int
1210gacopyz_srv_helo(gacopyz_srv_t srv, const char *domain) 1319gacopyz_srv_helo(gacopyz_srv_t srv, const char *domain)
1211{ 1320{
1212 int rc;
1213
1214 GACOPYZ_ASSERT(srv); 1321 GACOPYZ_ASSERT(srv);
1215 if (srv->state == srv_msgproc) 1322 if (srv->state == srv_msgproc)
1216 gacopyz_srv_abort(srv); 1323 gacopyz_srv_abort(srv);
diff --git a/gacopyz/smfi.c b/gacopyz/smfi.c
index 721b346..4f8628d 100644
--- a/gacopyz/smfi.c
+++ b/gacopyz/smfi.c
@@ -197,7 +197,7 @@ smfi_quarantine(SMFICTX *ctx, char *reason)
197int 197int
198smfi_addrcpt_par(SMFICTX *ctx, char *rcpt, char *args) 198smfi_addrcpt_par(SMFICTX *ctx, char *rcpt, char *args)
199{ 199{
200 return gacopyz_addrcpt_par(ctx, rcpt, args); 200 return gacopyz_add_rcpt_par(ctx, rcpt, args);
201} 201}
202 202
203int 203int
@@ -209,12 +209,23 @@ smfi_chgfrom(SMFICTX *ctx, char *from, char *args)
209int 209int
210smfi_setsymlist(SMFICTX *ctx, int n, char *macros) 210smfi_setsymlist(SMFICTX *ctx, int n, char *macros)
211{ 211{
212 if (n < 0 || n >= maci_max) 212 if (n < 0 || n >= gacopyz_stage_max)
213 return MI_FAILURE; 213 return MI_FAILURE;
214 if (!macros || !*macros || ctx->req_macros[n]) 214 if (!macros || !*macros || ctx->req_macros[n])
215 return MI_FAILURE; 215 return MI_FAILURE;
216 return gacopyz_setsymlist(ctx, n, macros); 216 return gacopyz_setsymlist(ctx, n, macros);
217} 217}
218 218
219 219int
220smfi_version(unsigned int *maj, unsigned int *min, unsigned int *pat)
221{
222 if (maj)
223 *maj = SM_LM_VRS_MAJOR(SMFI_VERSION);
224 if (min)
225 *min = SM_LM_VRS_MINOR(SMFI_VERSION);
226 if (pat)
227 *pat = SM_LM_VRS_MINOR(SMFI_VERSION);
228 return MI_SUCCESS;
229}
230
220 231
diff --git a/gacopyz/stagenames.c b/gacopyz/stagenames.c
new file mode 100644
index 0000000..0be6761
--- a/dev/null
+++ b/gacopyz/stagenames.c
@@ -0,0 +1,27 @@
1/* This file is part of gacopyz.
2 Copyright (C) 2009 Sergey Poznyakoff
3
4 This program 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 This program 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 this program. If not, see <http://www.gnu.org/licenses/>. */
16
17#include <gacopyz_priv.h>
18
19const char *gacopyz_stage_name[gacopyz_stage_max] = {
20 "connect",
21 "helo",
22 "envfrom",
23 "envrcpt",
24 "data",
25 "eom",
26 "eoh"
27};
diff --git a/mfd/engine.c b/mfd/engine.c
index 2ddfd5f..a9b42b2 100644
--- a/mfd/engine.c
+++ b/mfd/engine.c
@@ -1358,13 +1358,13 @@ mlfi_negotiate(SMFICTX *ctx,
1358 unsigned long *unused4, 1358 unsigned long *unused4,
1359 unsigned long *unused5) 1359 unsigned long *unused5)
1360{ 1360{
1361 enum macro_index i; 1361 enum gacopyz_stage i;
1362 1362
1363 debug4(70, "Negotiate: mta_actions=%#lx, mta_capa=%#lx, " 1363 debug4(70, "Negotiate: mta_actions=%#lx, mta_capa=%#lx, "
1364 "filter_actions=%#lx, filter_capa=%#lx", 1364 "filter_actions=%#lx, filter_capa=%#lx",
1365 mta_actions, mta_capa, *filter_actions, *filter_capa); 1365 mta_actions, mta_capa, *filter_actions, *filter_capa);
1366 1366
1367 for (i = 0; i < maci_max; i++) { 1367 for (i = 0; i < gacopyz_stage_max; i++) {
1368 char *str = get_stage_macro_string(i); 1368 char *str = get_stage_macro_string(i);
1369 gacopyz_setsymlist(ctx, i, str); 1369 gacopyz_setsymlist(ctx, i, str);
1370 free(str); 1370 free(str);
diff --git a/mfd/gram.y b/mfd/gram.y
index 0b27897..15a7f06 100644
--- a/mfd/gram.y
+++ b/mfd/gram.y
@@ -2412,49 +2412,39 @@ print_xref()
2412} 2412}
2413 2413
2414 2414
2415static mu_list_t smtp_macro_list[maci_max]; 2415static mu_list_t smtp_macro_list[gacopyz_stage_max];
2416 2416
2417static enum macro_index 2417static enum gacopyz_stage
2418smtp_to_milter_state(enum smtp_state tag) 2418smtp_to_gacopyz_stage(enum smtp_state tag)
2419{ 2419{
2420 switch (tag) { 2420 switch (tag) {
2421 case smtp_state_connect: 2421 case smtp_state_connect:
2422 return maci_conn; 2422 return gacopyz_stage_conn;
2423 case smtp_state_helo: 2423 case smtp_state_helo:
2424 return maci_helo; 2424 return gacopyz_stage_helo;
2425 case smtp_state_envfrom: 2425 case smtp_state_envfrom:
2426 return maci_mail; 2426 return gacopyz_stage_mail;
2427 case smtp_state_envrcpt: 2427 case smtp_state_envrcpt:
2428 return maci_rcpt; 2428 return gacopyz_stage_rcpt;
2429 case smtp_state_data: 2429 case smtp_state_data:
2430 case smtp_state_header: 2430 case smtp_state_header:
2431 case smtp_state_body: 2431 case smtp_state_body:
2432 return maci_data; 2432 return gacopyz_stage_data;
2433 case smtp_state_eoh: 2433 case smtp_state_eoh:
2434 return maci_eoh; 2434 return gacopyz_stage_eoh;
2435 case smtp_state_eom: 2435 case smtp_state_eom:
2436 return maci_eom; 2436 return gacopyz_stage_eom;
2437 default: 2437 default:
2438 break; 2438 break;
2439 } 2439 }
2440 return maci_none; 2440 return gacopyz_stage_none;
2441} 2441}
2442 2442
2443static const char *milter_state_name[maci_max] = {
2444 "connect",
2445 "helo",
2446 "envfrom",
2447 "envrcpt",
2448 "data",
2449 "eom",
2450 "eoh"
2451};
2452
2453void 2443void
2454register_macro(enum smtp_state state, const char *macro) 2444register_macro(enum smtp_state state, const char *macro)
2455{ 2445{
2456 enum macro_index ind = smtp_to_milter_state(state); 2446 enum gacopyz_stage ind = smtp_to_gacopyz_stage(state);
2457 if (ind == maci_none) 2447 if (ind == gacopyz_stage_none)
2458 return; 2448 return;
2459 if (!smtp_macro_list[ind]) { 2449 if (!smtp_macro_list[ind]) {
2460 mu_list_create(&smtp_macro_list[ind]); 2450 mu_list_create(&smtp_macro_list[ind]);
@@ -2481,12 +2471,12 @@ print_macro(void *item, void *data)
2481void 2471void
2482print_used_macros() 2472print_used_macros()
2483{ 2473{
2484 enum macro_index i; 2474 enum gacopyz_stage i;
2485 2475
2486 for (i = 0; i < maci_max; i++) { 2476 for (i = 0; i < gacopyz_stage_max; i++) {
2487 if (smtp_macro_list[i]) { 2477 if (smtp_macro_list[i]) {
2488 int n = 1; 2478 int n = 1;
2489 printf("%s", milter_state_name[i]); 2479 printf("%s", gacopyz_stage_name[i]);
2490 mu_list_do(smtp_macro_list[i], print_macro, &n); 2480 mu_list_do(smtp_macro_list[i], print_macro, &n);
2491 printf("\n"); 2481 printf("\n");
2492 } 2482 }
@@ -2521,7 +2511,7 @@ concat_macro(void *item, void *data)
2521} 2511}
2522 2512
2523char * 2513char *
2524get_stage_macro_string(enum macro_index i) 2514get_stage_macro_string(enum gacopyz_stage i)
2525{ 2515{
2526 struct macro_acc acc; 2516 struct macro_acc acc;
2527 size_t size; 2517 size_t size;
diff --git a/mfd/mailfromd.h b/mfd/mailfromd.h
index 47360b8..a45bf34 100644
--- a/mfd/mailfromd.h
+++ b/mfd/mailfromd.h
@@ -732,7 +732,7 @@ char *mf_strdup(const char *str);
732void regex_push(void); 732void regex_push(void);
733void regex_pop(void); 733void regex_pop(void);
734 734
735char *get_stage_macro_string(enum macro_index i); 735char *get_stage_macro_string(enum gacopyz_stage i);
736 736
737 737
738/* Data types and declarations for handling compiled configuration code */ 738/* Data types and declarations for handling compiled configuration code */
diff --git a/mtasim/mtasim.c b/mtasim/mtasim.c
index 5c79ff7..f9a85f5 100644
--- a/mtasim/mtasim.c
+++ b/mtasim/mtasim.c
@@ -102,7 +102,10 @@ int define_macro (char *arg);
102/* Milter-related options */ 102/* Milter-related options */
103char *milter_port; 103char *milter_port;
104size_t max_body_chunk = 65535; 104size_t max_body_chunk = 65535;
105int milter_version_option = 0; 105unsigned long milter_version_option = 0;
106unsigned long milter_proto_option = 0;
107unsigned long milter_acts_option = 0;
108int gacopyz_log_mask;
106struct timeval milter_timeouts[GACOPYZ_TO_COUNT] = { 109struct timeval milter_timeouts[GACOPYZ_TO_COUNT] = {
107 { GACOPYZ_WRITE_TIMEOUT, 0 }, 110 { GACOPYZ_WRITE_TIMEOUT, 0 },
108 { GACOPYZ_READ_TIMEOUT, 0 }, 111 { GACOPYZ_READ_TIMEOUT, 0 },
@@ -268,6 +271,7 @@ static char doc[] = N_("mtasim -- MTA simulator for mailfromd");
268 271
269enum { 272enum {
270 OPTION_STDIO = 128, 273 OPTION_STDIO = 128,
274 OPTION_GACOPYZ_LOG,
271 OPTION_DAEMON, 275 OPTION_DAEMON,
272 OPTION_TLS_CERT, 276 OPTION_TLS_CERT,
273 OPTION_TLS_CA, 277 OPTION_TLS_CA,
@@ -275,6 +279,8 @@ enum {
275 OPTION_TRACE_FILE, 279 OPTION_TRACE_FILE,
276 OPTION_BODY_CHUNK, 280 OPTION_BODY_CHUNK,
277 OPTION_MILTER_VERSION, 281 OPTION_MILTER_VERSION,
282 OPTION_MILTER_PROTO,
283 OPTION_MILTER_ACTS,
278 OPTION_NO_INTERACTIVE, 284 OPTION_NO_INTERACTIVE,
279 OPTION_PROMPT, 285 OPTION_PROMPT,
280 OPTION_STATEDIR 286 OPTION_STATEDIR
@@ -322,8 +328,12 @@ static struct argp_option options[] = {
322 { "body-chunk", OPTION_BODY_CHUNK, N_("NUMBER"), 0, 328 { "body-chunk", OPTION_BODY_CHUNK, N_("NUMBER"), 0,
323 N_("Set the body chunk for xxfi_body calls"), 329 N_("Set the body chunk for xxfi_body calls"),
324 GRP+1 }, 330 GRP+1 },
325 { "milter-version", OPTION_MILTER_VERSION, N_("NUMBER"), 0, 331 { "milter-version", OPTION_MILTER_VERSION, N_("VER"), 0,
326 N_("Force using the given Milter protocol version number"), GRP+1 }, 332 N_("Force using the given Milter protocol version number"), GRP+1 },
333 { "milter-actions", OPTION_MILTER_ACTS, N_("BITMASK"), 0,
334 N_("Force the given Milter actions"), GRP+1 },
335 { "milter-proto", OPTION_MILTER_PROTO, N_("BITMASK"), 0,
336 N_("Set Milter protocol capabilities"), GRP+1 },
327#undef GRP 337#undef GRP
328 338
329#define GRP 20 339#define GRP 20
@@ -343,6 +353,8 @@ static struct argp_option options[] = {
343 { "verbose", 'v', NULL, 0, 353 { "verbose", 'v', NULL, 0,
344 N_("Increase verbosity level"), 354 N_("Increase verbosity level"),
345 GRP+1 }, 355 GRP+1 },
356 { "gacopyz-log", OPTION_GACOPYZ_LOG, N_("LEVEL"), 0,
357 N_("Set Gacopyz log level"), GRP+1 },
346#undef GRP 358#undef GRP
347 359
348#define GRP 40 360#define GRP 40
@@ -369,6 +381,31 @@ char *trace_name = NULL;
369int append; 381int append;
370int statedir_option; 382int statedir_option;
371 383
384static unsigned long
385parse_version (char *arg, struct argp_state *state)
386{
387 char *p;
388 unsigned long maj, min, pat;
389
390 maj = strtoul (arg, &p, 0);
391 if (*p == 0)
392 return maj;
393 else if (*p == '.')
394 {
395 min = strtoul (p + 1, &p, 0);
396 if (*p == '.')
397 {
398 pat = strtoul (p + 1, &p, 0);
399 if (*p == 0)
400 return GACOPYZ_SM_MKVER (maj, min, pat);
401 }
402 else if (*p == 0)
403 return GACOPYZ_SM_MKVER (maj, min, 0);
404 }
405 argp_error (state, _("invalid version syntax (near %s)"), p);
406 return 0;
407}
408
372static error_t 409static error_t
373parse_opt (int key, char *arg, struct argp_state *state) 410parse_opt (int key, char *arg, struct argp_state *state)
374{ 411{
@@ -392,11 +429,19 @@ parse_opt (int key, char *arg, struct argp_state *state)
392 break; 429 break;
393 430
394 default: 431 default:
395 mu_error (_("unsupported mode")); 432 argp_error (state, _("unsupported mode"));
396 exit (EX_USAGE);
397 } 433 }
398 break; 434 break;
399 435
436 case OPTION_GACOPYZ_LOG:
437 {
438 int lev = gacopyz_string_to_log_level(arg);
439 if (lev == -1)
440 argp_error(state, _("%s: invalid log level"), arg);
441 gacopyz_log_mask = SMI_LOG_FROM (lev);
442 }
443 break;
444
400 case OPTION_STDIO: 445 case OPTION_STDIO:
401 mta_mode = mta_stdio; 446 mta_mode = mta_stdio;
402 break; 447 break;
@@ -447,21 +492,25 @@ parse_opt (int key, char *arg, struct argp_state *state)
447 case OPTION_BODY_CHUNK: 492 case OPTION_BODY_CHUNK:
448 max_body_chunk = strtoul (arg, &p, 0); 493 max_body_chunk = strtoul (arg, &p, 0);
449 if (*p) 494 if (*p)
450 { 495 argp_error (state, _("invalid number: %s"), arg);
451 mu_error (_("invalid number: %s"), arg);
452 exit (EX_USAGE);
453 }
454 break; 496 break;
455 497
456 case OPTION_MILTER_VERSION: 498 case OPTION_MILTER_VERSION:
457 milter_version_option = strtoul (arg, &p, 0); 499 milter_version_option = parse_version (arg, state);
500 break;
501
502 case OPTION_MILTER_PROTO:
503 milter_proto_option = strtoul (arg, &p, 0);
458 if (*p) 504 if (*p)
459 { 505 argp_error (state, _("invalid number: %s"), arg);
460 mu_error (_("invalid number: %s"), arg);
461 exit (EX_USAGE);
462 }
463 break; 506 break;
464 507
508 case OPTION_MILTER_ACTS:
509 milter_acts_option = strtoul (arg, &p, 0);
510 if (*p)
511 argp_error (state, _("invalid number: %s"), arg);
512 break;
513
465#ifdef WITH_READLINE 514#ifdef WITH_READLINE
466 case OPTION_NO_INTERACTIVE: 515 case OPTION_NO_INTERACTIVE:
467 interactive = 0; 516 interactive = 0;
@@ -766,20 +815,23 @@ main (int argc, char **argv)
766 if (milter_port) 815 if (milter_port)
767 { 816 {
768 int rc; 817 int rc;
769 int mask = SMI_DEFAULT_LOG_MASK;
770
771 if (verbose)
772 mask |= SMI_LOG_MASK (SMI_LOG_DEBUG);
773 818
819 if (gacopyz_log_mask == 0)
820 {
821 gacopyz_log_mask = SMI_DEFAULT_LOG_MASK;
822 if (verbose)
823 gacopyz_log_mask |= SMI_LOG_MASK (SMI_LOG_DEBUG);
824 }
825
774 gacopyz_set_logger (gacopyz_stderr_log_printer); 826 gacopyz_set_logger (gacopyz_stderr_log_printer);
775 827
776 if (strcmp (milter_port, "auto") == 0) 828 if (strcmp (milter_port, "auto") == 0)
777 start_mailfromd (argc, argv); 829 start_mailfromd (argc, argv);
778 830
779 if (portspec_p (milter_port)) 831 if (portspec_p (milter_port))
780 rc = gacopyz_srv_create (&gsrv, "Test", milter_port, mask); 832 rc = gacopyz_srv_create (&gsrv, "Test", milter_port, gacopyz_log_mask);
781 else 833 else
782 rc = gacopyz_srv_create_X (&gsrv, milter_port, mask); 834 rc = gacopyz_srv_create_X (&gsrv, milter_port, gacopyz_log_mask);
783 835
784 if (rc != MI_SUCCESS) 836 if (rc != MI_SUCCESS)
785 { 837 {
@@ -788,8 +840,25 @@ main (int argc, char **argv)
788 } 840 }
789 841
790 if (milter_version_option) 842 if (milter_version_option)
791 gacopyz_srv_set_version (gsrv, milter_version_option); 843 {
844 unsigned long acts = SMFI_DEFAULT_ACTS, proto = SMFI_DEFAULT_PROT;
845
846 if (milter_version_option == 2 || milter_version_option == 3)
847 {
848 acts = SMFI_V2_ACTS;
849 proto = SMFI_V2_PROT;
850 }
851
852 gacopyz_srv_set_version (gsrv, milter_version_option);
853 gacopyz_srv_set_protocol (gsrv, proto);
854 gacopyz_srv_set_actions (gsrv, acts);
855 }
792 856
857 if (milter_proto_option)
858 gacopyz_srv_set_protocol (gsrv, milter_proto_option);
859 if (milter_acts_option)
860 gacopyz_srv_set_actions (gsrv, milter_acts_option);
861
793 gacopyz_srv_set_all_timeouts (gsrv, milter_timeouts); 862 gacopyz_srv_set_all_timeouts (gsrv, milter_timeouts);
794 863
795 if (gacopyz_srv_connect (gsrv) != MI_SUCCESS) 864 if (gacopyz_srv_connect (gsrv) != MI_SUCCESS)
@@ -823,7 +892,7 @@ static void *in, *out;
823static const char * 892static const char *
824_def_strerror (int rc) 893_def_strerror (int rc)
825{ 894{
826 return rc == -1 ? "end of file reached" : strerror (rc); 895 return rc == -1 ? _("end of file reached") : strerror (rc);
827} 896}
828 897
829static int 898static int

Return to:

Send suggestions and report system problems to the System administrator.