]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-2.5-20071224
authorWietse Venema <wietse@porcupine.org>
Mon, 24 Dec 2007 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <viktor@dukhovni.org>
Tue, 5 Feb 2013 06:33:46 +0000 (06:33 +0000)
17 files changed:
postfix/HISTORY
postfix/RELEASE_NOTES
postfix/html/smtpd.8.html
postfix/man/man8/smtpd.8
postfix/src/cleanup/cleanup_envelope.c
postfix/src/cleanup/cleanup_milter.c
postfix/src/global/mail_version.h
postfix/src/milter/milter.c
postfix/src/milter/milter.h
postfix/src/milter/milter8.c
postfix/src/milter/milter_macros.c
postfix/src/milter/test-milter.c
postfix/src/smtpd/smtpd.c
postfix/src/util/name_code.c
postfix/src/util/name_code.h
postfix/src/util/name_mask.c
postfix/src/util/name_mask.h

index 5e90db6fd9d7b25471034fb3945e3d0e9b77910f..a5890f1c3175953f311fb360d48da51e6ad4178e 100644 (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].
index 5047076710c844fa37951aaa3963f05c43501e0c..c953a33dd79c6d8a4110b5326cfd434235f56fb4 100644 (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
 ============================================
 
index 13d051ff56b60db0956d26dff0fa730b4aa96f36..5c0872ada11455584c69729f59755424a2a0b251 100644 (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)
index 565c1e65e67056089fab4f7e383d4918889943f1..118ff8b95d2f91263c27986709faa8e3b522c362 100644 (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.
index 830f37093dbe10525cab539f608bd011a428f503..b21da3e8572638f1b11ae46bfe63d3e90b7f2da7 100644 (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)
index 8b9a81b770a9825eac39c717df88a7d9a03e3d20..9a060326b7e677acaee7f68da95b553a0f55fe44 100644 (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,
index 70c942d3cbc41d64d7669cb26bcedd0d02a1fc11..78c67017db9316d848f5074b5b57d01d67a0b8b9 100644 (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
index 54871653d31c36a51a5f8d075d7e6551c3b4514b..c8a6b556ab1e93dab353490d5342fdb06a02cfa6 100644 (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);
index 1f9b7f62920677d0d3888f828cb343529616d08b..f27c047d8c83383557c88abfd7305aaa5b3c657b 100644 (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.
   */
index fc2cccc330568112a05a6a71de8b26872c541120..17aa1ee0287812be435a2ff3f63034e3d2e2bb4d 100644 (file)
  /* 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
index db5c36db9be127cccd71904f1bab613363478507..b62f32be78e012aa632bf92cec9f81b90a08b72c 100644 (file)
 /*     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
 #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);
 }
index c13f6be67e7c68836d2f4a077c0fdb47bb08218c..cc65212da37a7bb187e048d5151555cca38b862b 100644 (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':
index 16e550b46de6627bdf441a5fa501541dbb23d4fb..231fe99f3c1a3c2b0be3df958f715f08f5f612b5 100644 (file)
 /*     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;
index dce373bbb3158fcaccd7fe95e9bc2aa1e561e943..0fd9f99cb42f5072be181705d70dbf84ea744cc1 100644 (file)
 /*     } 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)
index dd251b7aac04dd25a72be35d484d06c9c06c05e3..e08618d464465257252f85753e2642df28555cd6 100644 (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
index bee3735f4edc5552c37d3f3800d005f13c553048..9565461dbd493d239b20d806a8d2088fc1a6f683 100644 (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
 
 /* 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,
index 69631d38e82603741af6b4fd2c991e9ed8c94f5f..91df83f79b37368e77615a8a5487bd4d9a030733 100644 (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