diff --git a/postfix/HISTORY b/postfix/HISTORY
index 5e90db6fd..a5890f1c3 100644
--- a/postfix/HISTORY
+++ b/postfix/HISTORY
@@ -14057,8 +14057,17 @@ Apologies for any names omitted.
20071123
Further polishing of the Milter code. With SETSYMLIST, each
- Milter can update its own macros instead of clobbering
- the global copy is shared with other Milters. Also an
+ Milter can now update its own macros instead of clobbering
+ the global copy that is shared with other Milters. Also an
opportunity to clean up some ad-hoc code for sending macro
lists from smtp(8) to cleanup(8). Files: milter/milter.c,
milter/milter8.c, milter/milter_macros.c.
+
+20071224
+
+ Further polishing of the Milter code. Eliminated unnecessary
+ steps from the initial smtpd/cleanup Milter handshake. Files:
+ milter/milter.c, milter/milter8.c, milter/milter_macros.c.
+
+ Cleanup: name_code(3) and name_mask(3) now support read-only
+ tables. Files: util/name_code.[hc] util/name_mask.[hc].
diff --git a/postfix/RELEASE_NOTES b/postfix/RELEASE_NOTES
index 504707671..c953a33dd 100644
--- a/postfix/RELEASE_NOTES
+++ b/postfix/RELEASE_NOTES
@@ -11,6 +11,17 @@ instead, a new snapshot is released.
The mail_release_date configuration parameter (format: yyyymmdd)
specifies the release date of a stable release or snapshot release.
+Incompatibility with Postfix snapshot 20071224
+==============================================
+
+The protocol to send Milter information from smtpd(8) to cleanup(8)
+processes was cleaned up. If you use the Milter feature, and upgrade
+a live Postfix system, you may see an "unexpected record type"
+warning from a cleanup(8) server process. To prevent this, execute
+the command "postfix reload". The incompatibility affects only
+systems that use the Milter feature. It does not cause loss of mail,
+just a minor delay until the remote SMTP client retries.
+
Major changes with Postfix snapshot 20071221
============================================
diff --git a/postfix/html/smtpd.8.html b/postfix/html/smtpd.8.html
index 13d051ff5..5c0872ada 100644
--- a/postfix/html/smtpd.8.html
+++ b/postfix/html/smtpd.8.html
@@ -264,7 +264,7 @@ SMTPD(8) SMTPD(8)
milter_end_of_header_macros (see postconf -n output)
The macros that are sent to Milter (mail filter)
- applications after the message header.
+ applications after the end of the message header.
milter_end_of_data_macros (see postconf -n output)
The macros that are sent to Milter (mail filter)
diff --git a/postfix/man/man8/smtpd.8 b/postfix/man/man8/smtpd.8
index 565c1e65e..118ff8b95 100644
--- a/postfix/man/man8/smtpd.8
+++ b/postfix/man/man8/smtpd.8
@@ -235,7 +235,7 @@ The macros that are sent to version 3 or higher Milter (mail
filter) applications after an unknown SMTP command.
.IP "\fBmilter_end_of_header_macros (see postconf -n output)\fR"
The macros that are sent to Milter (mail filter) applications
-after the message header.
+after the end of the message header.
.IP "\fBmilter_end_of_data_macros (see postconf -n output)\fR"
The macros that are sent to Milter (mail filter) applications
after the message end-of-data.
diff --git a/postfix/src/cleanup/cleanup_envelope.c b/postfix/src/cleanup/cleanup_envelope.c
index 830f37093..b21da3e85 100644
--- a/postfix/src/cleanup/cleanup_envelope.c
+++ b/postfix/src/cleanup/cleanup_envelope.c
@@ -146,6 +146,14 @@ static void cleanup_envelope_process(CLEANUP_STATE *state, int type,
return;
}
#endif
+
+ /*
+ * XXX We instantiate a MILTERS structure even when the filter count is
+ * zero (for example, all filters are in ACCEPT state, or the SMTP server
+ * sends a dummy MILTERS structure without any filters), otherwise the
+ * cleanup server would apply the non_smtpd_milters setting
+ * inappropriately.
+ */
if (type == REC_TYPE_MILT_COUNT) {
/* Not part of queue file format. */
if ((milter_count = atoi(buf)) >= 0)
diff --git a/postfix/src/cleanup/cleanup_milter.c b/postfix/src/cleanup/cleanup_milter.c
index 8b9a81b77..9a060326b 100644
--- a/postfix/src/cleanup/cleanup_milter.c
+++ b/postfix/src/cleanup/cleanup_milter.c
@@ -1332,6 +1332,8 @@ void cleanup_milter_receive(CLEANUP_STATE *state, int count)
state->milters = milter_receive(state->src, count);
if (state->milters == 0)
msg_fatal("cleanup_milter_receive: milter receive failed");
+ if (count <= 0)
+ return;
milter_macro_callback(state->milters, cleanup_milter_eval, (void *) state);
milter_edit_callback(state->milters,
cleanup_add_header, cleanup_upd_header,
diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h
index 70c942d3c..78c67017d 100644
--- a/postfix/src/global/mail_version.h
+++ b/postfix/src/global/mail_version.h
@@ -20,7 +20,7 @@
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
-#define MAIL_RELEASE_DATE "20071223"
+#define MAIL_RELEASE_DATE "20071224"
#define MAIL_VERSION_NUMBER "2.5"
#ifdef SNAPSHOT
diff --git a/postfix/src/milter/milter.c b/postfix/src/milter/milter.c
index 54871653d..c8a6b556a 100644
--- a/postfix/src/milter/milter.c
+++ b/postfix/src/milter/milter.c
@@ -603,6 +603,10 @@ int milter_send(MILTERS *milters, VSTREAM *stream)
* to a cleanup server. For now we skip only the filters that are known
* to be disabled (either in global error state or in global accept
* state).
+ *
+ * XXX We must send *some* information, even when there are no active
+ * filters, otherwise the cleanup server would try to apply its own
+ * non_smtpd_milters settings.
*/
if (milters != 0)
for (m = milters->milter_list; m != 0; m = m->next)
@@ -611,7 +615,14 @@ int milter_send(MILTERS *milters, VSTREAM *stream)
(void) rec_fprintf(stream, REC_TYPE_MILT_COUNT, "%d", count);
/*
- * Send the filter macro names.
+ * XXX Optimization: don't send or receive further information when there
+ * aren't any active filters.
+ */
+ if (count <= 0)
+ return (0);
+
+ /*
+ * Send the filter macro name lists.
*/
(void) attr_print(stream, ATTR_FLAG_MORE,
ATTR_TYPE_FUNC, milter_macros_print,
@@ -624,6 +635,10 @@ int milter_send(MILTERS *milters, VSTREAM *stream)
for (m = milters->milter_list; m != 0; m = m->next)
if (m->active(m) && (status = m->send(m, stream)) != 0)
break;
+
+ /*
+ * Over to you.
+ */
if (status != 0
|| attr_scan(stream, ATTR_FLAG_STRICT,
ATTR_TYPE_INT, MAIL_ATTR_STATUS, &status,
@@ -643,20 +658,39 @@ MILTERS *milter_receive(VSTREAM *stream, int count)
MILTER *head = 0;
MILTER *tail = 0;
MILTER *milter = 0;
- MILTER_MACROS *macros = milter_macros_alloc(MILTER_MACROS_ALLOC_ZERO);
- if (attr_scan(stream, ATTR_FLAG_STRICT | ATTR_FLAG_MORE,
- ATTR_TYPE_FUNC, milter_macros_scan, (void *) macros,
- ATTR_TYPE_END) != 1) {
- milter_macros_free(macros);
- return (0);
- }
+ /*
+ * XXX We must instantiate a MILTERS structure even when the sender has
+ * no active filters, otherwise the cleanup server would try to use its
+ * own non_smtpd_milters settings.
+ */
#define NO_MILTERS ((char *) 0)
#define NO_TIMEOUTS 0, 0, 0
#define NO_PROTOCOL ((char *) 0)
#define NO_ACTION ((char *) 0)
+#define NO_MACROS ((MILTER_MACROS *) 0)
- milters = milter_new(NO_MILTERS, NO_TIMEOUTS, NO_PROTOCOL, NO_ACTION, macros);
+ milters = milter_new(NO_MILTERS, NO_TIMEOUTS, NO_PROTOCOL, NO_ACTION,
+ NO_MACROS);
+
+ /*
+ * XXX Optimization: don't send or receive further information when there
+ * aren't any active filters.
+ */
+ if (count <= 0)
+ return (milters);
+
+ /*
+ * Receive the global macro name lists.
+ */
+ milters->macros = milter_macros_alloc(MILTER_MACROS_ALLOC_ZERO);
+ if (attr_scan(stream, ATTR_FLAG_STRICT | ATTR_FLAG_MORE,
+ ATTR_TYPE_FUNC, milter_macros_scan,
+ (void *) milters->macros,
+ ATTR_TYPE_END) != 1) {
+ milter_free(milters);
+ return (0);
+ }
/*
* Receive the filters.
@@ -677,6 +711,9 @@ MILTERS *milter_receive(VSTREAM *stream, int count)
tail = milter;
}
+ /*
+ * Over to you.
+ */
(void) attr_print(stream, ATTR_FLAG_NONE,
ATTR_TYPE_INT, MAIL_ATTR_STATUS, 0,
ATTR_TYPE_END);
diff --git a/postfix/src/milter/milter.h b/postfix/src/milter/milter.h
index 1f9b7f629..f27c047d8 100644
--- a/postfix/src/milter/milter.h
+++ b/postfix/src/milter/milter.h
@@ -80,42 +80,6 @@ extern int milter_macros_scan(ATTR_SCAN_MASTER_FN, VSTREAM *, int, void *);
#define MILTER_MACROS_ALLOC_ZERO 1 /* null pointer */
#define MILTER_MACROS_ALLOC_EMPTY 2 /* mystrdup(""); */
-#define milter_macros_wipe(mp) do { \
- MILTER_MACROS *__mp = mp; \
- if (__mp->conn_macros) \
- myfree(__mp->conn_macros); \
- if (__mp->helo_macros) \
- myfree(__mp->helo_macros); \
- if (__mp->mail_macros) \
- myfree(__mp->mail_macros); \
- if (__mp->rcpt_macros) \
- myfree(__mp->rcpt_macros); \
- if (__mp->data_macros) \
- myfree(__mp->data_macros); \
- if (__mp->eoh_macros) \
- myfree(__mp->eoh_macros); \
- if (__mp->eod_macros) \
- myfree(__mp->eod_macros); \
- if (__mp->unk_macros) \
- myfree(__mp->unk_macros); \
- } while (0)
-
-#define milter_macros_zero(mp) milter_macros_init(mp, 0)
-
-#define milter_macros_init(mp, expr) do { \
- MILTER_MACROS *__mp = (mp); \
- char *__expr = (expr); \
- __mp->conn_macros = __expr; \
- __mp->helo_macros = __expr; \
- __mp->mail_macros = __expr; \
- __mp->rcpt_macros = __expr; \
- __mp->data_macros = __expr; \
- __mp->eoh_macros = __expr; \
- __mp->eod_macros = __expr; \
- __mp->unk_macros = __expr; \
- } while (0)
-
-
/*
* A bunch of Milters.
*/
diff --git a/postfix/src/milter/milter8.c b/postfix/src/milter/milter8.c
index fc2cccc33..17aa1ee02 100644
--- a/postfix/src/milter/milter8.c
+++ b/postfix/src/milter/milter8.c
@@ -123,7 +123,7 @@
/* Introduced with Sendmail 8.14. */
#define SMFIC_QUIT_NC 'K' /* Quit + new connection */
-static NAME_CODE smfic_table[] = {
+static const NAME_CODE smfic_table[] = {
"SMFIC_ABORT", SMFIC_ABORT,
"SMFIC_BODY", SMFIC_BODY,
"SMFIC_CONNECT", SMFIC_CONNECT,
@@ -168,7 +168,7 @@ static NAME_CODE smfic_table[] = {
#define SMFIR_ADDRCPT_PAR '2' /* add recipient (incl. ESMTP args) */
#define SMFIR_SETSYMLIST 'l' /* set list of symbols (macros) */
-static NAME_CODE smfir_table[] = {
+static const NAME_CODE smfir_table[] = {
"SMFIR_ADDRCPT", SMFIR_ADDRCPT,
"SMFIR_DELRCPT", SMFIR_DELRCPT,
"SMFIR_ACCEPT", SMFIR_ACCEPT,
@@ -231,7 +231,7 @@ static NAME_CODE smfir_table[] = {
| SMFIP_NR_DATA | SMFIP_NR_UNKN | SMFIP_NR_HDR | SMFIP_NR_EOH | \
SMFIP_NR_BODY)
-static NAME_MASK smfip_table[] = {
+static const NAME_MASK smfip_table[] = {
"SMFIP_NOCONNECT", SMFIP_NOCONNECT,
"SMFIP_NOHELO", SMFIP_NOHELO,
"SMFIP_NOMAIL", SMFIP_NOMAIL,
@@ -272,7 +272,7 @@ static NAME_MASK smfip_table[] = {
#define SMFIF_ADDRCPT_PAR (1L<<7) /* filter may add recipients + args */
#define SMFIF_SETSYMLIST (1L<<8) /* filter may send macro names */
-static NAME_MASK smfif_table[] = {
+static const NAME_MASK smfif_table[] = {
"SMFIF_ADDHDRS", SMFIF_ADDHDRS,
"SMFIF_CHGBODY", SMFIF_CHGBODY,
"SMFIF_ADDRCPT", SMFIF_ADDRCPT,
@@ -306,7 +306,7 @@ static NAME_MASK smfif_table[] = {
#define SMFIM_EOM 5 /* macros for end-of-message */
#define SMFIM_EOH 6 /* macros for end-of-header */
-static NAME_CODE smfim_table[] = {
+static const NAME_CODE smfim_table[] = {
"SMFIM_CONNECT", SMFIM_CONNECT,
"SMFIM_HELO", SMFIM_HELO,
"SMFIM_ENVFROM", SMFIM_ENVFROM,
@@ -318,10 +318,10 @@ static NAME_CODE smfim_table[] = {
};
/*
- * Mapping from external macro set numbers to our internal MILTERS structure
- * members, without using a switch statement.
+ * Mapping from external macro set numbers to our internal MILTER_MACROS
+ * structure members, without using an array or switch statement.
*/
-static size_t milter8_macro_offsets[] = {
+static const size_t milter8_macro_offsets[] = {
offsetof(MILTER_MACROS, conn_macros), /* SMFIM_CONNECT */
offsetof(MILTER_MACROS, helo_macros), /* SMFIM_HELO */
offsetof(MILTER_MACROS, mail_macros), /* SMFIM_ENVFROM */
@@ -445,7 +445,7 @@ typedef struct {
* XXX Is this still needed? Sendmail 8.14 provides a proper way to negotiate
* what replies the mail filter will send.
*/
-static NAME_CODE milter8_event_masks[] = {
+static const NAME_CODE milter8_event_masks[] = {
"2", MILTER8_V2_PROTO_MASK,
"3", MILTER8_V3_PROTO_MASK,
"4", MILTER8_V4_PROTO_MASK,
@@ -460,7 +460,7 @@ static NAME_CODE milter8_event_masks[] = {
* protocol extensions such as "no_header_reply", and require that exactly
* one version number is specified.
*/
-static NAME_CODE milter8_versions[] = {
+static const NAME_CODE milter8_versions[] = {
"2", 2,
"3", 3,
"4", 4,
@@ -1750,8 +1750,7 @@ static void milter8_connect(MILTER8 *milter)
msg_info("override %s macro list with \"%s\"",
smfim_name, STR(buf));
mac_value_ptr = MILTER8_MACRO_PTR(milter->m.macros, mac_type);
- if (*mac_value_ptr != 0)
- myfree(*mac_value_ptr);
+ myfree(*mac_value_ptr);
*mac_value_ptr = mystrdup(STR(buf));
}
}
@@ -2536,7 +2535,7 @@ static int milter8_send(MILTER *m, VSTREAM *stream)
}
static MILTER8 *milter8_alloc(const char *, int, int, int, const char *,
- const char *, MILTERS *);
+ const char *, MILTERS *);
/* milter8_receive - receive milter instance */
@@ -2712,7 +2711,7 @@ MILTER *milter8_create(const char *name, int conn_timeout, int cmd_timeout,
* Fill in the structure.
*/
milter = milter8_alloc(name, conn_timeout, cmd_timeout, msg_timeout,
- protocol, def_action, parent);
+ protocol, def_action, parent);
/*
* XXX Sendmail 8 libmilter closes the MTA-to-filter socket when it finds
diff --git a/postfix/src/milter/milter_macros.c b/postfix/src/milter/milter_macros.c
index db5c36db9..b62f32be7 100644
--- a/postfix/src/milter/milter_macros.c
+++ b/postfix/src/milter/milter_macros.c
@@ -38,47 +38,52 @@
/* void *ptr;
/* DESCRIPTION
/* Sendmail mail filter (Milter) applications receive sets of
-/* macro (name=value) pairs with each SMTP or content event.
-/* In Postfix, the lists of names are stored in MILTER_MACROS
-/* structures. By default, the same structure is shared by all
-/* Milter applications; it is initialized with information
-/* from main.cf. With Sendmail 8.14 a Milter can override one
-/* or more lists of macro names, and individual filters may
-/* have their own partial list.
+/* macro name=value pairs with each SMTP or content event.
+/* In Postfix, these macro names are stored in MILTER_MACROS
+/* structures, as one list for each event type. By default,
+/* the same structure is shared by all Milter applications;
+/* it is initialized with information from main.cf. With
+/* Sendmail 8.14 a Milter can override one or more lists of
+/* macro names. Postfix implements this by giving the Milter
+/* its own MILTER_MACROS structure and by storing the per-Milter
+/* information there.
/*
-/* This module maintains the macro name lists as mystrdup()'ed
-/* values. The user is explicitly allowed to update these
-/* values directly, as long as they respect the mystrdup()
-/* interface.
+/* This module maintains per-event macro name lists as
+/* mystrdup()'ed values. The user is explicitly allowed to
+/* update these values directly, as long as the result is
+/* compatible with mystrdup().
/*
/* milter_macros_create() creates a MILTER_MACROS structure
/* and initializes it with copies of its string arguments.
+/* Null pointers are not valid as input.
/*
-/* milter_macros_alloc() creates a MILTER_MACROS structure
+/* milter_macros_alloc() creates am empty MILTER_MACROS structure
/* that is initialized according to its init_mode argument.
/* .IP MILTER_MACROS_ALLOC_ZERO
-/* Initialize all members as null pointers. This mode is
-/* recommended for applications that use milter_macros_scan().
+/* Initialize all structure members as null pointers. This
+/* mode must be used with milter_macros_scan(), because that
+/* function blindly overwrites all structure members. No other
+/* function except milter_macros_free() allows structure members
+/* with null pointer values.
/* .IP MILTER_MACROS_ALLOC_EMPTY
-/* Initialize all members with mystrdup(""). This is not as
-/* expensive as it appears to be. This mode is recommend for
-/* applications that update individual MILTER_MACROS members
-/* directly.
+/* Initialize all structure members with mystrdup(""). This
+/* is not as expensive as it appears to be.
/* .PP
/* milter_macros_free() destroys a MILTER_MACROS structure and
/* frees any strings referenced by it.
/*
/* milter_macros_print() writes the contents of a MILTER_MACROS
/* structure to the named stream using the specified attribute
-/* print routine. milter_macros_print() is meant to be passed
+/* print routine. milter_macros_print() is meant to be passed
/* as a call-back to attr_print*(), thusly:
/*
/* ATTR_TYPE_FUNC, milter_macros_print, (void *) macros,
/*
/* milter_macros_scan() reads a MILTER_MACROS structure from
/* the named stream using the specified attribute scan routine.
-/* milter_macros_scan() is meant to be passed as a call-back
-/* to attr_scan*(), thusly:
+/* No attempt is made to free the memory of existing structure
+/* members. milter_macros_scan() is meant to be passed as a
+/* call-back to attr_scan*(), thusly:
/*
/* ATTR_TYPE_FUNC, milter_macros_scan, (void *) macros,
/* DIAGNOSTICS
@@ -121,7 +126,7 @@
#define MAIL_ATTR_MILT_MAC_EOD "eod_macros"
#define MAIL_ATTR_MILT_MAC_UNK "unk_macros"
-/* milter_macros_print - write recipient to stream */
+/* milter_macros_print - write macros structure to stream */
int milter_macros_print(ATTR_PRINT_MASTER_FN print_fn, VSTREAM *fp,
int flags, void *ptr)
@@ -146,13 +151,17 @@ int milter_macros_print(ATTR_PRINT_MASTER_FN print_fn, VSTREAM *fp,
return (ret);
}
-/* milter_macros_scan - receive milter macro name list */
+/* milter_macros_scan - receive macros structure from stream */
int milter_macros_scan(ATTR_SCAN_MASTER_FN scan_fn, VSTREAM *fp,
int flags, void *ptr)
{
MILTER_MACROS *mp = (MILTER_MACROS *) ptr;
int ret;
+
+ /*
+ * We could simplify this by moving memory allocation into attr_scan*().
+ */
VSTRING *conn_macros = vstring_alloc(10);
VSTRING *helo_macros = vstring_alloc(10);
VSTRING *mail_macros = vstring_alloc(10);
@@ -218,12 +227,28 @@ MILTER_MACROS *milter_macros_create(const char *conn_macros,
return (mp);
}
-/* milter_macros_alloc - allocate memory for structure with simple initialization */
+/* milter_macros_alloc - allocate macros structure with simple initialization */
MILTER_MACROS *milter_macros_alloc(int mode)
{
MILTER_MACROS *mp;
+ /*
+ * This macro was originally in milter.h, but no-one else needed it.
+ */
+#define milter_macros_init(mp, expr) do { \
+ MILTER_MACROS *__mp = (mp); \
+ char *__expr = (expr); \
+ __mp->conn_macros = __expr; \
+ __mp->helo_macros = __expr; \
+ __mp->mail_macros = __expr; \
+ __mp->rcpt_macros = __expr; \
+ __mp->data_macros = __expr; \
+ __mp->eoh_macros = __expr; \
+ __mp->eod_macros = __expr; \
+ __mp->unk_macros = __expr; \
+ } while (0)
+
mp = (MILTER_MACROS *) mymalloc(sizeof(*mp));
switch (mode) {
case MILTER_MACROS_ALLOC_ZERO:
@@ -242,6 +267,30 @@ MILTER_MACROS *milter_macros_alloc(int mode)
void milter_macros_free(MILTER_MACROS *mp)
{
+
+ /*
+ * This macro was originally in milter.h, but no-one else needed it.
+ */
+#define milter_macros_wipe(mp) do { \
+ MILTER_MACROS *__mp = mp; \
+ if (__mp->conn_macros) \
+ myfree(__mp->conn_macros); \
+ if (__mp->helo_macros) \
+ myfree(__mp->helo_macros); \
+ if (__mp->mail_macros) \
+ myfree(__mp->mail_macros); \
+ if (__mp->rcpt_macros) \
+ myfree(__mp->rcpt_macros); \
+ if (__mp->data_macros) \
+ myfree(__mp->data_macros); \
+ if (__mp->eoh_macros) \
+ myfree(__mp->eoh_macros); \
+ if (__mp->eod_macros) \
+ myfree(__mp->eod_macros); \
+ if (__mp->unk_macros) \
+ myfree(__mp->unk_macros); \
+ } while (0)
+
milter_macros_wipe(mp);
myfree((char *) mp);
}
diff --git a/postfix/src/milter/test-milter.c b/postfix/src/milter/test-milter.c
index c13f6be67..cc65212da 100644
--- a/postfix/src/milter/test-milter.c
+++ b/postfix/src/milter/test-milter.c
@@ -18,7 +18,7 @@
/* Arguments (multiple alternatives are separated by "\fB|\fR"):
/* .IP "\fB-a accept|tempfail|reject|discard|skip|\fIddd x.y.z text\fR"
/* Specifies a non-default reply for the MTA command specified
-/* with \fB-a\fR. The default is \fBtempfail\fR.
+/* with \fB-c\fR. The default is \fBtempfail\fR.
/* .IP "\fB-d\fI level\fR"
/* Enable libmilter debugging at the specified level.
/* .IP "\fB-c connect|helo|mail|rcpt|data|header|eoh|body|eom|unknown|close|abort\fR"
@@ -28,6 +28,9 @@
/* Terminate after \fIcount\fR connections.
/* .IP "\fB-i \fI'index header-label header-value'\fR"
/* Insert header at specified position.
+/* .IP "\fB-l\fR"
+/* Header values include leading space. Specify this option
+/* before \fB-i\fR or \fB-r\fR.
/* .IP "\fB-m connect|helo|mail|rcpt|data|eoh|eom\fR"
/* The protocol stage that receives the list of macros specified
/* with \fB-M\fR. The default protocol stage is \fBconnect\fR.
@@ -100,7 +103,7 @@ struct command_map {
int *reply;
};
-static struct command_map command_map[] = {
+static const struct command_map command_map[] = {
"connect", &test_connect_reply,
"helo", &test_helo_reply,
"mail", &test_mail_reply,
@@ -387,7 +390,7 @@ struct noproto_map {
FILTER_ACTION *action;
};
-static struct noproto_map noproto_map[] = {
+static const struct noproto_map noproto_map[] = {
"connect", SMFIP_NOCONNECT, SMFIP_NR_CONN, &test_connect_reply, &smfilter.xxfi_connect,
"helo", SMFIP_NOHELO, SMFIP_NR_HELO, &test_helo_reply, &smfilter.xxfi_helo,
"mail", SMFIP_NOMAIL, SMFIP_NR_MAIL, &test_mail_reply, &smfilter.xxfi_envfrom,
@@ -402,6 +405,7 @@ static struct noproto_map noproto_map[] = {
static int nosend_mask;
static int noreply_mask;
+static int misc_mask;
static sfsistat test_negotiate(SMFICTX *ctx,
unsigned long f0,
@@ -420,10 +424,10 @@ static sfsistat test_negotiate(SMFICTX *ctx,
smfi_setsymlist(ctx, set_macro_state, set_macro_list);
}
if (verbose)
- printf("negotiate f0=%lx *pf0 = %lx f1=%lx *pf1=%lx nosend=%lx noreply=%lx\n",
- f0, *pf0, f1, *pf1, (long) nosend_mask, (long) noreply_mask);
+ printf("negotiate f0=%lx *pf0 = %lx f1=%lx *pf1=%lx nosend=%lx noreply=%lx misc=%lx\n",
+ f0, *pf0, f1, *pf1, (long) nosend_mask, (long) noreply_mask, (long) misc_mask);
*pf0 = f0;
- *pf1 = f1 & (nosend_mask | noreply_mask);
+ *pf1 = f1 & (nosend_mask | noreply_mask | misc_mask);
return (SMFIS_CONTINUE);
}
@@ -439,7 +443,9 @@ static void parse_hdr_info(const char *optarg, int *idx,
fprintf(stderr, "out of memory\n");
exit(1);
}
- if (sscanf(optarg, "%d %s %[^\n]", idx, *hdr, *value) != 3) {
+ if ((misc_mask & SMFIP_HDR_LEADSPC) == 0 ?
+ sscanf(optarg, "%d %s %[^\n]", idx, *hdr, *value) != 3 :
+ sscanf(optarg, "%d %[^ ]%[^\n]", idx, *hdr, *value) != 3) {
fprintf(stderr, "bad header info: %s\n", optarg);
exit(1);
}
@@ -449,16 +455,16 @@ int main(int argc, char **argv)
{
char *action = 0;
char *command = 0;
- struct command_map *cp;
+ const struct command_map *cp;
int ch;
int code;
const char **cpp;
char *set_macro_state_arg = 0;
char *nosend = 0;
char *noreply = 0;
- struct noproto_map *np;
+ const struct noproto_map *np;
- while ((ch = getopt(argc, argv, "a:c:C:d:i:m:M:n:N:p:r:R:v")) > 0) {
+ while ((ch = getopt(argc, argv, "a:c:C:d:i:lm:M:n:N:p:r:R:v")) > 0) {
switch (ch) {
case 'a':
action = optarg;
@@ -482,6 +488,18 @@ int main(int argc, char **argv)
#else
fprintf(stderr, "no libmilter support to insert header\n");
exit(1);
+#endif
+ break;
+ case 'l':
+#if SMFI_VERSION > 5
+ if (ins_hdr || chg_hdr) {
+ fprintf(stderr, "specify -l before -i or -r\n");
+ exit(1);
+ }
+ misc_mask |= SMFIP_HDR_LEADSPC;
+#else
+ fprintf(stderr, "no libmilter support for leading space\n");
+ exit(1);
#endif
break;
case 'm':
@@ -493,6 +511,7 @@ int main(int argc, char **argv)
set_macro_state_arg = optarg;
#else
fprintf(stderr, "no libmilter support to specify macro list\n");
+ exit(1);
#endif
break;
case 'M':
diff --git a/postfix/src/smtpd/smtpd.c b/postfix/src/smtpd/smtpd.c
index 16e550b46..231fe99f3 100644
--- a/postfix/src/smtpd/smtpd.c
+++ b/postfix/src/smtpd/smtpd.c
@@ -211,7 +211,7 @@
/* filter) applications after an unknown SMTP command.
/* .IP "\fBmilter_end_of_header_macros (see postconf -n output)\fR"
/* The macros that are sent to Milter (mail filter) applications
-/* after the message header.
+/* after the end of the message header.
/* .IP "\fBmilter_end_of_data_macros (see postconf -n output)\fR"
/* The macros that are sent to Milter (mail filter) applications
/* after the message end-of-data.
@@ -1654,6 +1654,11 @@ static int mail_open_stream(SMTPD_STATE *state)
* XXX Send Milter information first, because this will hang when cleanup
* goes into "throw away" mode. Also, cleanup needs to know early on
* whether or not it has to do its own SMTP event emulation.
+ *
+ * XXX At this point we send only dummy information to keep the cleanup
+ * server from using its non_smtpd_milters settings. We have to send
+ * up-to-date Milter information after DATA so that the cleanup server
+ * knows the actual Milter state.
*/
if (state->dest) {
state->cleanup = state->dest->stream;
diff --git a/postfix/src/util/name_code.c b/postfix/src/util/name_code.c
index dce373bbb..0fd9f99cb 100644
--- a/postfix/src/util/name_code.c
+++ b/postfix/src/util/name_code.c
@@ -14,12 +14,12 @@
/* } NAME_CODE;
/*
/* int name_code(table, flags, name)
-/* NAME_CODE *table;
+/* const NAME_CODE *table;
/* int flags;
/* const char *name;
/*
/* const char *str_name_code(table, code)
-/* NAME_CODE *table;
+/* const NAME_CODE *table;
/* int code;
/* DESCRIPTION
/* This module does simple name<->number mapping. The process
@@ -66,9 +66,9 @@
/* name_code - look up code by name */
-int name_code(NAME_CODE *table, int flags, const char *name)
+int name_code(const NAME_CODE *table, int flags, const char *name)
{
- NAME_CODE *np;
+ const NAME_CODE *np;
int (*lookup) (const char *, const char *);
if (flags & NAME_CODE_FLAG_STRICT_CASE)
@@ -84,9 +84,9 @@ int name_code(NAME_CODE *table, int flags, const char *name)
/* str_name_code - look up name by code */
-const char *str_name_code(NAME_CODE *table, int code)
+const char *str_name_code(const NAME_CODE *table, int code)
{
- NAME_CODE *np;
+ const NAME_CODE *np;
for (np = table; np->name; np++)
if (code == np->code)
diff --git a/postfix/src/util/name_code.h b/postfix/src/util/name_code.h
index dd251b7aa..e08618d46 100644
--- a/postfix/src/util/name_code.h
+++ b/postfix/src/util/name_code.h
@@ -22,8 +22,8 @@ typedef struct {
#define NAME_CODE_FLAG_NONE 0
#define NAME_CODE_FLAG_STRICT_CASE (1<<0)
-extern int name_code(NAME_CODE *, int, const char *);
-extern const char *str_name_code(NAME_CODE *, int);
+extern int name_code(const NAME_CODE *, int, const char *);
+extern const char *str_name_code(const NAME_CODE *, int);
/* LICENSE
/* .ad
diff --git a/postfix/src/util/name_mask.c b/postfix/src/util/name_mask.c
index bee3735f4..9565461db 100644
--- a/postfix/src/util/name_mask.c
+++ b/postfix/src/util/name_mask.c
@@ -8,23 +8,23 @@
/*
/* int name_mask(context, table, names)
/* const char *context;
-/* NAME_MASK *table;
+/* const NAME_MASK *table;
/* const char *names;
/*
/* const char *str_name_mask(context, table, mask)
/* const char *context;
-/* NAME_MASK *table;
+/* const NAME_MASK *table;
/* int mask;
/*
/* int name_mask_opt(context, table, names, flags)
/* const char *context;
-/* NAME_MASK *table;
+/* const NAME_MASK *table;
/* const char *names;
/* int flags;
/*
/* int name_mask_delim_opt(context, table, names, delim, flags)
/* const char *context;
-/* NAME_MASK *table;
+/* const NAME_MASK *table;
/* const char *names;
/* const char *delim;
/* int flags;
@@ -32,7 +32,7 @@
/* const char *str_name_mask_opt(buf, context, table, mask, flags)
/* VSTRING *buf;
/* const char *context;
-/* NAME_MASK *table;
+/* const NAME_MASK *table;
/* int mask;
/* int flags;
/* DESCRIPTION
@@ -129,14 +129,14 @@
/* name_mask_delim_opt - compute mask corresponding to list of names */
-int name_mask_delim_opt(const char *context, NAME_MASK *table,
+int name_mask_delim_opt(const char *context, const NAME_MASK *table,
const char *names, const char *delim, int flags)
{
const char *myname = "name_mask";
char *saved_names = mystrdup(names);
char *bp = saved_names;
int result = 0;
- NAME_MASK *np;
+ const NAME_MASK *np;
char *name;
int (*lookup) (const char *, const char *);
@@ -177,11 +177,11 @@ int name_mask_delim_opt(const char *context, NAME_MASK *table,
/* str_name_mask_opt - mask to string */
const char *str_name_mask_opt(VSTRING *buf, const char *context,
- NAME_MASK *table,
+ const NAME_MASK *table,
int mask, int flags)
{
const char *myname = "name_mask";
- NAME_MASK *np;
+ const NAME_MASK *np;
int len;
static VSTRING *my_buf = 0;
int delim = (flags & NAME_MASK_COMMA ? ',' :
@@ -230,7 +230,7 @@ const char *str_name_mask_opt(VSTRING *buf, const char *context,
int main(int argc, char **argv)
{
- static NAME_MASK table[] = {
+ static const NAME_MASK table[] = {
"zero", 1 << 0,
"one", 1 << 1,
"two", 1 << 2,
diff --git a/postfix/src/util/name_mask.h b/postfix/src/util/name_mask.h
index 69631d38e..91df83f79 100644
--- a/postfix/src/util/name_mask.h
+++ b/postfix/src/util/name_mask.h
@@ -45,8 +45,8 @@ typedef struct {
#define str_name_mask(tag, table, mask) \
str_name_mask_opt(((VSTRING *) 0), (tag), (table), (mask), NAME_MASK_DEFAULT)
-extern int name_mask_delim_opt(const char *, NAME_MASK *, const char *, const char *, int);
-extern const char *str_name_mask_opt(VSTRING *, const char *, NAME_MASK *, int, int);
+extern int name_mask_delim_opt(const char *, const NAME_MASK *, const char *, const char *, int);
+extern const char *str_name_mask_opt(VSTRING *, const char *, const NAME_MASK *, int, int);
/* LICENSE
/* .ad