2
0
mirror of https://github.com/vdukhovni/postfix synced 2025-08-30 05:38:06 +00:00

postfix-2.5-20071224

This commit is contained in:
Wietse Venema 2007-12-24 00:00:00 -05:00 committed by Viktor Dukhovni
parent a82a55628d
commit 54a1b6ce1f
17 changed files with 222 additions and 119 deletions

View File

@ -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].

View File

@ -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
============================================

View File

@ -264,7 +264,7 @@ SMTPD(8) SMTPD(8)
<b><a href="postconf.5.html#milter_end_of_header_macros">milter_end_of_header_macros</a> (see postconf -n output)</b>
The macros that are sent to Milter (mail filter)
applications after the message header.
applications after the end of the message header.
<b><a href="postconf.5.html#milter_end_of_data_macros">milter_end_of_data_macros</a> (see postconf -n output)</b>
The macros that are sent to Milter (mail filter)

View File

@ -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.

View File

@ -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)

View File

@ -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,

View File

@ -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

View File

@ -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);

View File

@ -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.
*/

View File

@ -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

View File

@ -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);
}

View File

@ -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':

View File

@ -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;

View File

@ -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)

View File

@ -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

View File

@ -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,

View File

@ -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