]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
snapshot-20011029
authorWietse Venema <wietse@porcupine.org>
Mon, 29 Oct 2001 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <viktor@dukhovni.org>
Tue, 5 Feb 2013 06:27:29 +0000 (06:27 +0000)
57 files changed:
postfix/HISTORY
postfix/conf/main.cf
postfix/conf/sample-misc.cf
postfix/conf/sample-smtpd.cf
postfix/errors_to [new file with mode: 0644]
postfix/html/faq.html
postfix/html/local.8.html
postfix/html/qmqpd.8.html
postfix/html/sendmail.1.html
postfix/man/man1/sendmail.1
postfix/man/man8/local.8
postfix/src/bounce/Makefile.in
postfix/src/cleanup/Makefile.in
postfix/src/cleanup/cleanup.c
postfix/src/cleanup/cleanup.h
postfix/src/cleanup/cleanup_api.c
postfix/src/cleanup/cleanup_map1n.c
postfix/src/cleanup/cleanup_message.c
postfix/src/cleanup/cleanup_out_recipient.c
postfix/src/cleanup/cleanup_state.c
postfix/src/flush/Makefile.in
postfix/src/global/Makefile.in
postfix/src/global/been_here.h
postfix/src/global/been_here_level.c [new file with mode: 0644]
postfix/src/global/cleanup_user.h
postfix/src/global/mail_stream.c
postfix/src/global/mail_trigger.c
postfix/src/global/mail_version.h
postfix/src/global/pipe_command.c
postfix/src/global/rec_type.c
postfix/src/global/rec_type.h
postfix/src/lmtp/Makefile.in
postfix/src/local/Makefile.in
postfix/src/local/forward.c
postfix/src/master/Makefile.in
postfix/src/master/multi_server.c
postfix/src/nqmgr/Makefile.in
postfix/src/pickup/Makefile.in
postfix/src/pickup/pickup.c
postfix/src/postconf/Makefile.in
postfix/src/postdrop/Makefile.in
postfix/src/postkick/Makefile.in
postfix/src/qmgr/Makefile.in
postfix/src/qmqpd/Makefile.in
postfix/src/qmqpd/qmqpd.c
postfix/src/sendmail/Makefile.in
postfix/src/sendmail/sendmail.c
postfix/src/showq/Makefile.in
postfix/src/smtp/Makefile.in
postfix/src/smtpd/Makefile.in
postfix/src/smtpd/smtpd.c
postfix/src/smtpd/smtpd_check.c
postfix/src/trivial-rewrite/Makefile.in
postfix/src/util/Makefile.in
postfix/src/util/attr.h
postfix/src/util/attr_scan.c
postfix/src/util/attr_table.c [deleted file]

index a9b3636bfb594ba5845c1b8fbbc97b5ba7fd631a..fffd1d750699001148934e45b2484b913c92241b 100644 (file)
@@ -5487,6 +5487,12 @@ Apologies for any names omitted.
        Bugfix: there was a minute memory leak when an smtpd access
        restriction is misconfigured. File: smtpd/smtpd_check.c.
 
+20011010
+
+       Specify the name of the UNIX-domain socket (instead of
+       "unknown stream") when a Postfix daemon complains about a
+       malformed client request. Files:  master/*server.c.
+
 20011010-14
 
        Replaced the internal protocols by (name,value) attribute
@@ -5502,10 +5508,29 @@ Apologies for any names omitted.
        is sent to the originator. Files: cleanup/cleanup.c,
        cleanup/cleanup_message.c, conf/sample-filter.cf.
 
+20011016
+
+       Bugfix: As of 20000625, Errors-To: was broken, because the
+       code to extract the address was not moved from recipient
+       address rewriting to sender address rewriting. Problem
+       reported by Roelof Osinga @ nisser.com. File:
+       cleanup/cleanup_message.c.
+
+20011029
+
+       Bugfix: virtual map expansion terminated early because the
+       detection of self-referential entries was flawed.  File:
+       cleanup/cleanup_map1n.c.
+
 Open problems:
 
        Minor: The $process_id_directory setting is not used anywhere
        in Postfix. Problem reported by Michael Smith, texas.net.
+       This should either be documented, or better, the code should
+       issue a warning to set a read-only parameter.
 
        Medium: address rewriting should be on/off configurable
        for envelopes and/or headers.
+
+       Medium: smtpd access maps doesn't understand the recipient
+       delimiter setting.
index 752db3c00a86f7bb3e3cb079eaaa6749ef884282..43220c108870455213dac93aef4fa2c9d8837239 100644 (file)
@@ -214,8 +214,6 @@ mail_owner = postfix
 #
 # In the case of SMTP, specify a domain, host, host:port, [host]:port,
 # [address] or [address]:port; the form [host] turns off MX lookups.
-# If you specify multiple SMTP destinations, Postfix will try them
-# in the specified order.
 #
 # If you're connected via UUCP, see also the default_transport parameter.
 #
index e1d23a60f8d72c16f9dcc6665f19e710b4c068a8..4b2d7d502f50fb9b28cd99f04881bbe6a616c991 100644 (file)
@@ -329,8 +329,6 @@ recipient_delimiter =
 #
 # In the case of SMTP, specify a domain, host, host:port, [host]:port,
 # [address] or [address]:port; the form [host] turns off MX lookups.
-# If you specify multiple SMTP destinations, Postfix will try them
-# in the specified order.
 #
 # If you're connected via UUCP, see also the default_transport parameter.
 #
index 081bcb8b06c9e884c4612335b7f4d02409efd8ef..0a8ba1f84562c0b913d4de61958ddfa4207fe3fe 100644 (file)
@@ -40,7 +40,7 @@ smtpd_banner = $myhostname ESMTP $mail_name
 #   maptype:mapname: look up client name, parent domains, client address,
 #      or networks obtained by stripping octets.
 #      Reject if result is REJECT or "[45]xx text"
-#      Permit otherwise.
+#      Permit result is OK or all numerical.
 #   reject_maps_rbl: reject if the reverse client network address
 #      is listed under $maps_rbl_domains.
 #   reject: reject the request. Place this at the end of a restriction.
@@ -154,7 +154,7 @@ mynetworks_style = subnet
 #   maptype:mapname: look up client name, parent domains, client address,
 #      or networks obtained by stripping octets.
 #      Reject if result is REJECT or "[45]xx text"
-#      Permit otherwise.
+#      Permit result is OK or all numerical.
 #   reject_maps_rbl: reject if the client is listed under $maps_rbl_domains.
 #   reject: reject the request. Place this at the end of a restriction.
 #   permit: permit the request. Place this at the end of a restriction.
@@ -191,7 +191,7 @@ smtpd_helo_required = no
 #   check_helo_access maptype:mapname
 #   maptype:mapname: look up HELO hostname or parent domains.
 #      Reject if result is REJECT or "[45]xx text"
-#      Permit otherwise.
+#      Permit result is OK or all numerical.
 #   check_client_access maptype:mapname: see smtpd_client_restrictions.
 #   reject: reject the request. Place this at the end of a restriction.
 #   permit: permit the request. Place this at the end of a restriction.
@@ -221,7 +221,7 @@ smtpd_helo_restrictions =
 #   check_sender_access maptype:mapname
 #   maptype:mapname: look up sender address, parent domain, or localpart@.
 #      Reject if result is REJECT or "[45]xx text"
-#      Permit otherwise.
+#      Permit result is OK or all numerical.
 #   check_client_access maptype:mapname: see smtpd_client_restrictions.
 #   check_helo_access maptype:mapname: see smtpd_helo_restrictions.
 #   reject_non_fqdn_hostname: reject HELO hostname that is not in FQDN form
@@ -289,7 +289,7 @@ smtpd_sender_restrictions =
 #   check_recipient_access maptype:mapname
 #   maptype:mapname: look up recipient address, parent domain, or localpart@.
 #      Reject if result is REJECT or "[45]xx text"
-#      Permit otherwise.
+#      Permit result is OK or all numerical.
 #   check_client_access maptype:mapname: see smtpd_client_restrictions.
 #   check_helo_access maptype:mapname: see smtpd_helo_restrictions.
 #   check_sender_access maptype:mapname: see smtpd_sender_restrictions.
diff --git a/postfix/errors_to b/postfix/errors_to
new file mode 100644 (file)
index 0000000..e69de29
index 394cb330bafcd414f6a1f8eb4a3e57ee7eae0a82..9ce25228b15ead8f741831a7ebbe12fe65aade30 100644 (file)
@@ -1225,7 +1225,7 @@ commands as <b>root</b>:
 
 In order to run hundreds of processes you may have to adjust the
 per-process open file limit. According to the <a
-href="http://www.wins.uva.nl/pub/solaris/solaris2.html#q3.45">Solaris
+href="http://www.science.uva.nl/pub/solaris/solaris2.html#q3.45">Solaris
 FAQ</a>, add the following lines to /etc/system on Solaris 2.4 and later: 
 
 <p> 
index c028f65cf6060c772dcf19251b6cc38e609a96de..08274fbdf39e8ac1015c156e9a1fe7c45b24ddf5 100644 (file)
@@ -328,6 +328,11 @@ LOCAL(8)                                                 LOCAL(8)
               (exception: root). The string is subject  to  $name
               expansions.
 
+       <b>mailbox</b><i>_</i><b>command</b><i>_</i><b>maps</b>
+              Lookup  tables with per-recipient external commands
+              to use for mailbox delivery. Behavior  is  as  with
+              <b>mailbox</b><i>_</i><b>command</b>.
+
        <b>mailbox</b><i>_</i><b>transport</b>
               Message  transport  to  use for mailbox delivery to
               all local recipients, whether or not they are found
index 5d5792ef3008df5e7fb6d16b3816a06f1a34c0fb..7bed7101b580e1b6381e1c2c3ce7d8b7b43b74f9 100644 (file)
@@ -102,7 +102,7 @@ QMQPD(8)                                                 QMQPD(8)
               of a problem. This slows down run-away errors.
 
 <b>SEE</b> <b>ALSO</b>
-       <a href="http://cr.yp.to/proto/qmqp.html">http://cr.yp.to/proto/qmqp.html</a>, QMQP protocol
+       http://cr.yp.to/proto/qmqp.html, QMQP protocol
        <a href="cleanup.8.html">cleanup(8)</a> message canonicalization
        <a href="master.8.html">master(8)</a> process manager
        syslogd(8) system logging
index 6261883ad3c0353f9c262b2ec8b79ef5fab10003..282a7bd3eb3ff8d01d34c13acb84a6fb246ffa7b 100644 (file)
@@ -181,12 +181,10 @@ SENDMAIL(1)                                           SENDMAIL(1)
 
        <b>-qR</b><i>site</i>
               Schedule  immediate  delivery  of  all mail that is
-              queued for the named <i>site</i>. Depending on the  desti-
-              nation,  this  uses "fast flush" service, or it has
-              the same effect as <b>sendmail</b>  <b>-q</b>.   This  is  imple-
-              mented by connecting to the local SMTP server.  See
-              <a href="smtpd.8.html"><b>smtpd</b>(8)</a>  for  more  information  about  the  "fast
-              flush" service.
+              queued for the named <i>site</i>. This uses  "fast  flush"
+              service,  and  is  implemented by connecting to the
+              local SMTP server at <b>$myhostname</b>.  See <a href="smtpd.8.html"><b>smtpd</b>(8)</a> for
+              more information about the "fast flush" service.
 
        <b>-qS</b><i>site</i>
               This  command  is  not  implemented. Use the slower
index faaa064b4ac35b60deeac73319567ffa5bc41b42..7db99fb6dff66cddb337e5684f379979da306969 100644 (file)
@@ -154,9 +154,8 @@ The interval between queue runs. Use the \fBqueue_run_delay\fR
 configuration parameter instead.
 .IP \fB-qR\fIsite\fR
 Schedule immediate delivery of all mail that is queued for the named
-\fIsite\fR. Depending on the destination, this uses "fast flush"
-service, or it has the same effect as \fBsendmail -q\fR.
-This is implemented by connecting to the local SMTP server.
+\fIsite\fR. This uses "fast flush" service, and is implemented
+by connecting to the local SMTP server at \fB$myhostname\fR.
 See \fBsmtpd\fR(8) for more information about the "fast flush"
 service.
 .IP \fB-qS\fIsite\fR
index c0929a6acba14f09b6769d874c09c0e5f5f7d3eb..f0eb862f9a0ebf48e8e4a983e6db5502cb17d351 100644 (file)
@@ -335,6 +335,9 @@ dependent.
 External command to use for mailbox delivery. The command executes
 with the recipient privileges (exception: root). The string is subject
 to $name expansions.
+.IP \fBmailbox_command_maps\fR
+Lookup tables with per-recipient external commands to use for mailbox
+delivery. Behavior is as with \fBmailbox_command\fR.
 .IP \fBmailbox_transport\fR
 Message transport to use for mailbox delivery to all local
 recipients, whether or not they are found in the UNIX passwd database.
index d77256556baad31e9b6ac2e72f3b5c6bab11550a..e3769be8432878ad1a2f8d44727b6df1f89af8e2 100644 (file)
@@ -65,6 +65,8 @@ bounce.o: ../../include/vstream.h
 bounce.o: ../../include/stringops.h
 bounce.o: ../../include/mail_proto.h
 bounce.o: ../../include/iostuff.h
+bounce.o: ../../include/attr.h
+bounce.o: ../../include/htable.h
 bounce.o: ../../include/mail_queue.h
 bounce.o: ../../include/mail_params.h
 bounce.o: ../../include/mail_conf.h
index 3ed1de67b0b8530bc3f448711ac537cf7a83a789..46cb770ca4e53eb35d35bd649695efadfbdb7bc3 100644 (file)
@@ -72,6 +72,8 @@ cleanup.o: ../../include/mail_conf.h
 cleanup.o: ../../include/cleanup_user.h
 cleanup.o: ../../include/mail_proto.h
 cleanup.o: ../../include/iostuff.h
+cleanup.o: ../../include/attr.h
+cleanup.o: ../../include/htable.h
 cleanup.o: ../../include/mail_params.h
 cleanup.o: ../../include/record.h
 cleanup.o: ../../include/rec_type.h
@@ -93,6 +95,8 @@ cleanup_api.o: ../../include/mail_queue.h
 cleanup_api.o: ../../include/vstream.h
 cleanup_api.o: ../../include/mail_proto.h
 cleanup_api.o: ../../include/iostuff.h
+cleanup_api.o: ../../include/attr.h
+cleanup_api.o: ../../include/htable.h
 cleanup_api.o: ../../include/bounce.h
 cleanup_api.o: ../../include/mail_params.h
 cleanup_api.o: ../../include/mail_stream.h
index cd8091898faf6bdd845364bfda4956424cbbdb04..594f2bbdfb6fb45ba8b352ddbef41f73e7831469 100644 (file)
@@ -235,8 +235,8 @@ static void cleanup_service(VSTREAM *src, char *unused_service, char **argv)
      */
     attr_print(src, ATTR_FLAG_NONE,
               ATTR_TYPE_NUM, MAIL_ATTR_STATUS, cleanup_close(state),
-              ATTR_TYPE_STR, MAIL_ATTR_WHY, state->why_rejected ?
-              vstring_str(state->why_rejected) : "",
+              ATTR_TYPE_STR, MAIL_ATTR_WHY, state->reason ?
+              state->reason : "",
               ATTR_TYPE_END);
     cleanup_free(state);
 
index 5e2f38548682c588034e44e1b580bfc688adc496..955a014ef3b9aaaf04d5de2b166755bd02ec2097 100644 (file)
@@ -59,7 +59,7 @@ typedef struct CLEANUP_STATE {
     off_t   xtra_offset;               /* start of extra segment */
     int     end_seen;                  /* REC_TYPE_END seen */
     int     rcpt_count;                        /* recipient count */
-    VSTRING *why_rejected;             /* REJECT reason */
+    char   *reason;                    /* failure reason */
 } CLEANUP_STATE;
 
  /*
index 37239fbbfe727175d67f4ac047c25e25acfa402d..4728be59510cfa3b4b0bfa2c597dbe106bfd071d 100644 (file)
 /*     cleanup_open() creates a new queue file and performs other
 /*     per-message initialization. The result is a handle that should be
 /*     given to the cleanup_control(), cleanup_record(), cleanup_close()
-/*     and cleanup_close()
-/*     routines. The name of the queue file is in the queue_id result
-/*     structure member.
+/*     and cleanup_free() routines. The name of the queue file is in the
+/*     queue_id result structure member.
 /*
 /*     cleanup_control() processes per-message flags specified by the caller.
 /*     These flags control the handling of data errors, and must be set
 /*     before processing the first message record.
-/*
+/* .IP CLEANUP_FLAG_BOUNCE
+/*     The cleanup server is responsible for returning undeliverable 
+/*     mail (too many hops, message too large) to the sender.
+/* .IP CLEANUP_FLAG_FILTER
+/*     Enable header/body filtering. This should be enabled only with mail 
+/*     that enters Postfix, not with locally forwarded mail or with bounce 
+/*     messages.
+/* .IP CLEANUP_FLAG_EXTRACT
+/*     Extract recipients from message headers when no recipients are
+/*     provided in the message envelope records.
+/* .PP
 /*     CLEANUP_RECORD() is a macro that processes one message record,
 /*     that copies the result to the queue file, and that maintains a
 /*     little state machine. The last record in a valid message has type
@@ -49,8 +58,9 @@
 /*
 /*     cleanup_close() closes a queue file. In case of any errors,
 /*     the file is removed. The result value is non-zero in case of
-/*     problems. Use cleanup_strerror() to translate the result into
-/*     human_readable text.
+/*     problems. In some cases a human-readable text can be found in
+/*     the state->reason member. In all other cases, use cleanup_strerror()
+/*     to translate the result into human-readable text.
 /*
 /*     cleanup_free() destroys its argument.
 /* DIAGNOSTICS
@@ -154,10 +164,9 @@ void    cleanup_control(CLEANUP_STATE *state, int flags)
      * definition.
      */
     if ((state->flags = flags) & CLEANUP_FLAG_BOUNCE) {
-       state->err_mask =
-       (CLEANUP_STAT_BAD | CLEANUP_STAT_WRITE | CLEANUP_STAT_SIZE);
+       state->err_mask = CLEANUP_STAT_MASK_INCOMPLETE;
     } else {
-       state->err_mask = CLEANUP_STAT_LETHAL;
+       state->err_mask = ~CLEANUP_STAT_MASK_EXTRACT_RCPT;
     }
 }
 
@@ -167,13 +176,16 @@ int     cleanup_close(CLEANUP_STATE *state)
 {
     char   *junk;
     int     status;
-    const char *reason;
 
     /*
-     * See if there are any errors. For example, the message is incomplete,
-     * or it needs to be bounced for lack of recipients. We want to turn on
-     * the execute bits on a file only when we really want the queue manager
-     * to process it.
+     * Ignore recipient extraction alarms if (a) we did (not need to) extract
+     * recipients, or (b) we did not examine all queue file records.
+     */
+    if (state->recip != 0 || CLEANUP_OUT_OK(state) == 0)
+       state->errs &= ~CLEANUP_STAT_MASK_EXTRACT_RCPT;
+
+    /*
+     * Raise these errors only if we examined all queue file records.
      */
     if (CLEANUP_OUT_OK(state)) {
        if (state->recip == 0)
@@ -187,10 +199,11 @@ int     cleanup_close(CLEANUP_STATE *state)
      * because we are about to tell the sender that it can throw away its
      * copy of the message.
      */
-    if ((state->errs & CLEANUP_STAT_LETHAL) == 0)
-       state->errs |= mail_stream_finish(state->handle, (VSTRING *) 0);
-    else
+    if (state->errs == 0) {
+       state->errs = mail_stream_finish(state->handle, (VSTRING *) 0);
+    } else {
        mail_stream_cleanup(state->handle);
+    }
     state->handle = 0;
     state->dst = 0;
 
@@ -207,35 +220,26 @@ int     cleanup_close(CLEANUP_STATE *state)
      * 
      * Do not log the arrival of a message that will be bounced by the client.
      * 
-     * XXX CLEANUP_STAT_LETHAL masks errors that are not directly fatal (e.g.,
-     * header buffer overflow is normally allowed to happen), but that can
-     * indirectly become a problem (e.g., no recipients were extracted from
-     * message headers because we could not process all the message headers).
-     * However, cleanup_strerror() prioritizes errors so that it can report
-     * the cause (e.g., header buffer overflow), which is more useful.
-     * 
      * XXX When bouncing, should log sender because qmgr won't be able to.
      */
 #define CAN_BOUNCE() \
-       ((state->errs & (CLEANUP_STAT_BAD | CLEANUP_STAT_WRITE)) == 0 \
+       ((state->errs & CLEANUP_STAT_MASK_CANT_BOUNCE) == 0 \
            && state->sender != 0 \
            && (state->flags & CLEANUP_FLAG_BOUNCE) != 0)
 
-    if (state->errs & CLEANUP_STAT_LETHAL) {
+    if (state->errs != 0) {
        if (CAN_BOUNCE()) {
-           reason = cleanup_strerror(state->errs);
-           if (reason == cleanup_strerror(CLEANUP_STAT_CONT))
-               reason = vstring_str(state->why_rejected);
            if (bounce_append(BOUNCE_FLAG_CLEAN, state->queue_id,
                              state->recip ? state->recip : "unknown",
                              "cleanup", state->time,
-                             "Message processing aborted: %s",
-                             reason) == 0
+                          "Message processing aborted: %s", state->reason ?
+                        state->reason : cleanup_strerror(state->errs)) == 0
                && bounce_flush(BOUNCE_FLAG_CLEAN, MAIL_QUEUE_INCOMING,
                                state->queue_id, state->sender) == 0) {
                state->errs = 0;
            } else {
-               msg_warn("%s: bounce message failure", state->queue_id);
+               if (var_soft_bounce == 0)
+                   msg_warn("%s: bounce message failure", state->queue_id);
                state->errs = CLEANUP_STAT_WRITE;
            }
        }
@@ -258,11 +262,11 @@ int     cleanup_close(CLEANUP_STATE *state)
      */
     if (msg_verbose)
        msg_info("cleanup_close: status %d", state->errs);
-    status = state->errs & CLEANUP_STAT_LETHAL;
+    status = state->errs;
     return (status);
 }
 
-/* cleanup_close - pay the last respects */
+/* cleanup_free - pay the last respects */
 
 void    cleanup_free(CLEANUP_STATE *state)
 {
index 6af064a103939c365feb66b8066daf92efd0a484..72127c180540a4409a01a191dfb436fee63ac5f6 100644 (file)
@@ -101,7 +101,11 @@ ARGV   *cleanup_map1n_internal(CLEANUP_STATE *state, char *addr,
            break;
        }
        for (count = 0; /* void */ ; count++) {
-           if (been_here_fixed(been_here, argv->argv[arg]) != 0)
+
+           /*
+            * Don't expand an address that already expanded into itself.
+            */
+           if (been_here_check_fixed(been_here, argv->argv[arg]) != 0)
                break;
            if (count >= MAX_RECURSION) {
                msg_warn("%s: unreasonable %s map nesting for %s",
@@ -118,6 +122,12 @@ ARGV   *cleanup_map1n_internal(CLEANUP_STATE *state, char *addr,
                        argv_add(argv, STR(state->temp1), ARGV_END);
                        argv_terminate(argv);
                    }
+
+                   /*
+                    * Allow an address to expand into itself once.
+                    */
+                   if (strcasecmp(saved_lhs, STR(state->temp1)) == 0)
+                       been_here_fixed(been_here, argv->argv[arg]);
                }
                myfree(saved_lhs);
                argv_free(lookup);
index 6843d6c358ba706ff81cc447083f9ddeb91b8153..e1742a760839ba0e3e67496b3ee953c342973e31 100644 (file)
@@ -186,6 +186,12 @@ static void cleanup_rewrite_sender(CLEANUP_STATE *state, HEADER_OPTS *hdr_opts)
        if (hdr_opts->type == HDR_RESENT_FROM && state->resent_from == 0)
            state->resent_from =
                cleanup_extract_internal(state->header_buf, *tpp);
+       if (hdr_opts->type == HDR_RETURN_RECEIPT_TO && !state->return_receipt)
+           state->return_receipt =
+               cleanup_extract_internal(state->header_buf, *tpp);
+       if (hdr_opts->type == HDR_ERRORS_TO && !state->errors_to)
+           state->errors_to =
+               cleanup_extract_internal(state->header_buf, *tpp);
     }
     vstring_sprintf(state->header_buf, "%s: ", hdr_opts->name);
     tok822_externalize(state->header_buf, tree, TOK822_STR_HEAD);
@@ -239,12 +245,6 @@ static void cleanup_rewrite_recip(CLEANUP_STATE *state, HEADER_OPTS *hdr_opts)
        if (cleanup_masq_domains
            && (cleanup_masq_flags & CLEANUP_MASQ_FLAG_HDR_RCPT))
            cleanup_masquerade_tree(*tpp, cleanup_masq_domains);
-       if (hdr_opts->type == HDR_RETURN_RECEIPT_TO && !state->return_receipt)
-           state->return_receipt =
-               cleanup_extract_internal(state->header_buf, *tpp);
-       if (hdr_opts->type == HDR_ERRORS_TO && !state->errors_to)
-           state->errors_to =
-               cleanup_extract_internal(state->header_buf, *tpp);
     }
     vstring_sprintf(state->header_buf, "%s: ", hdr_opts->name);
     tok822_externalize(state->header_buf, tree, TOK822_STR_HEAD);
@@ -254,36 +254,28 @@ static void cleanup_rewrite_recip(CLEANUP_STATE *state, HEADER_OPTS *hdr_opts)
        cleanup_fold_header(state);
 }
 
-/* cleanup_parse_reject - parse REJECT liune and pick up the reason */
+/* cleanup_check_reject - parse and match header/body REJECT line */
 
-static const char *cleanup_parse_reject(CLEANUP_STATE *state, const char *value)
+static int cleanup_check_reject(CLEANUP_STATE *state, const char *value)
 {
-    const char *reason;
+    const char *reason = value + strcspn(value, " \t");
 
     /*
      * See if they spelled REJECT right.
+     * 
+     * XXX The reason should be set only if we have a more severe error than
+     * anything that was found before. This calls for a cleanup_set_error()
+     * routine that takes an error code and an optional text.
      */
-    if (strcasecmp(value, "REJECT") == 0) {
-       reason = "Content rejected";
-    } else if (strncasecmp(value, "REJECT ", 7) == 0
-              || strncasecmp(value, "REJECT\t", 7) == 0) {
-       reason = value + 7;
-       while (*reason && ISSPACE(*reason))
-           reason++;
-       if (*reason == 0)
-           reason = "Content rejected";
+    if (strncasecmp(value, "REJECT", reason - value) == 0) {
+       if (state->reason == 0)
+           state->reason = mystrdup(*reason ? reason :
+                                    cleanup_strerror(CLEANUP_STAT_CONT));
+       state->errs |= CLEANUP_STAT_CONT;
+       return (1);
     } else {
        return (0);
     }
-
-    /*
-     * Update the remembered reason if none was stored.
-     */
-    if (state->why_rejected == 0) {
-       state->why_rejected = vstring_alloc(10);
-       vstring_strcpy(state->why_rejected, reason);
-    }
-    return (reason);
 }
 
 /* cleanup_header - process one complete header line */
@@ -299,14 +291,13 @@ static void cleanup_header(CLEANUP_STATE *state)
     if ((state->flags & CLEANUP_FLAG_FILTER) && cleanup_header_checks) {
        char   *header = vstring_str(state->header_buf);
        const char *value;
-       const char *reason;
 
        if ((value = maps_find(cleanup_header_checks, header, 0)) != 0) {
-           if ((reason = cleanup_parse_reject(state, value)) != 0) {
+           if (cleanup_check_reject(state, value) != 0) {
                msg_info("%s: reject: header %.200s; from=<%s> to=<%s>: %s",
                         state->queue_id, header, state->sender,
-                        state->recip ? state->recip : "unknown", reason);
-               state->errs |= CLEANUP_STAT_CONT;
+                        state->recip ? state->recip : "unknown",
+                        state->reason);
            } else if (strcasecmp(value, "IGNORE") == 0) {
                return;
            }
@@ -580,14 +571,13 @@ static void cleanup_message_body(CLEANUP_STATE *state, int type, char *buf, int
         */
        if ((state->flags & CLEANUP_FLAG_FILTER) && cleanup_body_checks) {
            const char *value;
-           const char *reason;
 
            if ((value = maps_find(cleanup_body_checks, buf, 0)) != 0) {
-               if ((reason = cleanup_parse_reject(state, value)) != 0) {
+               if (cleanup_check_reject(state, value) != 0) {
                    msg_info("%s: reject: body %.200s; from=<%s> to=<%s>: %s",
                             state->queue_id, buf, state->sender,
-                          state->recip ? state->recip : "unknown", reason);
-                   state->errs |= CLEANUP_STAT_CONT;
+                            state->recip ? state->recip : "unknown",
+                            state->reason);
                } else if (strcasecmp(value, "IGNORE") == 0) {
                    return;
                }
index bb283aa3cc6bb6bc166bee8df96ddefb9d637852..147fef30d016564add2c2022c82f71b1ff8a25c5 100644 (file)
@@ -60,6 +60,7 @@ void    cleanup_out_recipient(CLEANUP_STATE *state, char *recip)
 {
     ARGV   *argv;
     char  **cpp;
+    int     envelope_changed;
 
     if (cleanup_virtual_maps == 0) {
        if (been_here_fixed(state->dups, recip) == 0)
@@ -67,9 +68,13 @@ void    cleanup_out_recipient(CLEANUP_STATE *state, char *recip)
     } else {
        argv = cleanup_map1n_internal(state, recip, cleanup_virtual_maps,
                                  cleanup_ext_prop_mask & EXT_PROP_VIRTUAL);
+       envelope_changed = (argv->argc > 1 || strcmp(recip, argv->argv[0]));
        for (cpp = argv->argv; *cpp; cpp++)
-           if (been_here_fixed(state->dups, *cpp) == 0)
+           if (been_here_fixed(state->dups, *cpp) == 0) {
+               if (envelope_changed)
+                   cleanup_out_string(state, REC_TYPE_ORCP, recip);
                cleanup_out_string(state, REC_TYPE_RCPT, *cpp), state->rcpt_count++;
+           }
        argv_free(argv);
     }
 }
index 615238e48d91bcd50cb01740016af7ba478a8274..2206d7a42ec71042ce8dd854e72a8858ea790d92 100644 (file)
@@ -84,7 +84,7 @@ CLEANUP_STATE *cleanup_state_alloc(void)
     state->xtra_offset = -1;
     state->end_seen = 0;
     state->rcpt_count = 0;
-    state->why_rejected = 0;
+    state->reason = 0;
     return (state);
 }
 
@@ -114,7 +114,7 @@ void    cleanup_state_free(CLEANUP_STATE *state)
     if (state->queue_id)
        myfree(state->queue_id);
     been_here_free(state->dups);
-    if (state->why_rejected)
-       vstring_free(state->why_rejected);
+    if (state->reason)
+       myfree(state->reason);
     myfree((char *) state);
 }
index 19b51de2809805dfffd752e3fb40915f0392747d..fc0819df193a1bf7d19087cf38367e3e08556665 100644 (file)
@@ -71,6 +71,7 @@ flush.o: ../../include/mail_params.h
 flush.o: ../../include/mail_queue.h
 flush.o: ../../include/mail_proto.h
 flush.o: ../../include/iostuff.h
+flush.o: ../../include/attr.h
 flush.o: ../../include/mail_flush.h
 flush.o: ../../include/flush_clnt.h
 flush.o: ../../include/mail_conf.h
index b96837dc843627ffd2a4da8f10869a8f180bd1b3..7d5152cb2d13f984a482663681688972a21be933 100644 (file)
@@ -19,7 +19,7 @@ SRCS  = been_here.c bounce.c canon_addr.c cleanup_strerror.c clnt_stream.c \
        timed_ipc.c tok822_find.c tok822_node.c tok822_parse.c \
        tok822_resolve.c tok822_rewrite.c tok822_tree.c xtext.c bounce_log.c \
        flush_clnt.c mail_conf_time.c mbox_conf.c mbox_open.c abounce.c \
-       verp_sender.c
+       verp_sender.c been_here_level.c
 OBJS   = been_here.o bounce.o canon_addr.o cleanup_strerror.o clnt_stream.o \
        debug_peer.o debug_process.o defer.o deliver_completed.o \
        deliver_flock.o deliver_pass.o deliver_request.o domain_list.o \
@@ -40,7 +40,7 @@ OBJS  = been_here.o bounce.o canon_addr.o cleanup_strerror.o clnt_stream.o \
        timed_ipc.o tok822_find.o tok822_node.o tok822_parse.o \
        tok822_resolve.o tok822_rewrite.o tok822_tree.o xtext.o bounce_log.o \
        flush_clnt.o mail_conf_time.o mbox_conf.o mbox_open.o abounce.o \
-       verp_sender.o
+       verp_sender.o been_here_level.o
 HDRS   = been_here.h bounce.h canon_addr.h cleanup_user.h clnt_stream.h \
        config.h debug_peer.h debug_process.h defer.h deliver_completed.h \
        deliver_flock.h deliver_pass.h deliver_request.h domain_list.h \
@@ -267,6 +267,15 @@ been_here.o: ../../include/vstring.h
 been_here.o: ../../include/vbuf.h
 been_here.o: ../../include/stringops.h
 been_here.o: been_here.h
+been_here_level.o: been_here_level.c
+been_here_level.o: ../../include/sys_defs.h
+been_here_level.o: ../../include/msg.h
+been_here_level.o: ../../include/mymalloc.h
+been_here_level.o: ../../include/htable.h
+been_here_level.o: ../../include/vstring.h
+been_here_level.o: ../../include/vbuf.h
+been_here_level.o: ../../include/stringops.h
+been_here_level.o: been_here.h
 bounce.o: bounce.c
 bounce.o: ../../include/sys_defs.h
 bounce.o: ../../include/msg.h
@@ -499,6 +508,15 @@ mail_command_client.o: mail_proto.h
 mail_command_client.o: ../../include/iostuff.h
 mail_command_client.o: ../../include/attr.h
 mail_command_client.o: ../../include/htable.h
+mail_command_read.o: mail_command_read.c
+mail_command_read.o: ../../include/sys_defs.h
+mail_command_read.o: ../../include/vstring.h
+mail_command_read.o: ../../include/vbuf.h
+mail_command_read.o: ../../include/vstream.h
+mail_command_read.o: mail_proto.h
+mail_command_read.o: ../../include/iostuff.h
+mail_command_read.o: ../../include/attr.h
+mail_command_read.o: ../../include/htable.h
 mail_command_server.o: mail_command_server.c
 mail_command_server.o: ../../include/sys_defs.h
 mail_command_server.o: ../../include/vstream.h
@@ -507,6 +525,14 @@ mail_command_server.o: mail_proto.h
 mail_command_server.o: ../../include/iostuff.h
 mail_command_server.o: ../../include/attr.h
 mail_command_server.o: ../../include/htable.h
+mail_command_write.o: mail_command_write.c
+mail_command_write.o: ../../include/sys_defs.h
+mail_command_write.o: ../../include/vstream.h
+mail_command_write.o: ../../include/vbuf.h
+mail_command_write.o: mail_proto.h
+mail_command_write.o: ../../include/iostuff.h
+mail_command_write.o: ../../include/attr.h
+mail_command_write.o: ../../include/htable.h
 mail_conf.o: mail_conf.c
 mail_conf.o: ../../include/sys_defs.h
 mail_conf.o: ../../include/msg.h
@@ -568,6 +594,8 @@ mail_connect.o: ../../include/vbuf.h
 mail_connect.o: ../../include/connect.h
 mail_connect.o: ../../include/iostuff.h
 mail_connect.o: ../../include/mymalloc.h
+mail_connect.o: ../../include/stringops.h
+mail_connect.o: ../../include/vstring.h
 mail_connect.o: timed_ipc.h
 mail_connect.o: mail_proto.h
 mail_connect.o: ../../include/attr.h
index 855001d61184fef53380f48026468d6e7cea576c..c4f8a5287681837cca3aaf8f10e735a626a78731 100644 (file)
@@ -28,6 +28,9 @@ typedef struct {
 #define BH_FLAG_NONE   0               /* no special processing */
 #define BH_FLAG_FOLD   (1<<0)          /* fold case */
 
+ /*
+  * been_here.c
+  */
 extern BH_TABLE *been_here_init(int, int);
 extern void been_here_free(BH_TABLE *);
 extern int been_here_fixed(BH_TABLE *, const char *);
@@ -35,6 +38,14 @@ extern int PRINTFLIKE(2, 3) been_here(BH_TABLE *, const char *,...);
 extern int been_here_check_fixed(BH_TABLE *, const char *);
 extern int PRINTFLIKE(2, 3) been_here_check(BH_TABLE *, const char *,...);
 
+ /*
+  * been_here_level.c
+  */
+extern int been_here_level_fixed(BH_TABLE *, int, const char *);
+extern int PRINTFLIKE(3, 4) been_here_level(BH_TABLE *, int, const char *,...);
+extern int been_here_level_check_fixed(BH_TABLE *, const char *);
+extern int PRINTFLIKE(2, 3) been_here_level_check(BH_TABLE *, const char *,...);
+
 /* LICENSE
 /* .ad
 /* .fi
diff --git a/postfix/src/global/been_here_level.c b/postfix/src/global/been_here_level.c
new file mode 100644 (file)
index 0000000..8391b87
--- /dev/null
@@ -0,0 +1,239 @@
+/*++
+/* NAME
+/*     been_here_level 3
+/* SUMMARY
+/*     detect repeated occurrence of string
+/* SYNOPSIS
+/*     #include <been_here.h>
+/*
+/*     int     been_here_level_fixed(dup_filter, level, string)
+/*     BH_TABLE *dup_filter;
+/*     int     level;
+/*     char    *string;
+/*
+/*     int     been_here_level(dup_filter, level, format, ...)
+/*     BH_TABLE *dup_filter;
+/*     int     level;
+/*     char    *format;
+/*
+/*     int     been_here_level_check_fixed(dup_filter, level, string)
+/*     BH_TABLE *dup_filter;
+/*     int     level;
+/*     char    *string;
+/*
+/*     int     been_here_level_check(dup_filter, level, format, ...)
+/*     BH_TABLE *dup_filter;
+/*     int     level;
+/*     char    *format;
+/* DESCRIPTION
+/*     This module implements a simple filter to detect repeated
+/*     occurrences of character strings. Each string has associated with
+/*     an integer level, the meaning of which is left up to the application.
+/*     Otherwise the code is like been_here(3).
+/*
+/*     been_here_level_fixed() looks up a fixed string in the given table, and
+/*     makes an entry in the table if the string was not found. The result
+/*     is >= 0 if the string was found, -1 otherwise.
+/*
+/*     been_here_level() formats its arguments, looks up the result in the
+/*     given table, and makes an entry in the table if the string was
+/*     not found. The result is >= 0 if the formatted result was
+/*     found, -1 otherwise.
+/*
+/*     been_here_level_check_fixed() and been_here_level_check() are similar
+/*     but do not update the duplicate filter.
+/*
+/*     Arguments:
+/* .IP size
+/*     Upper bound on the table size; at most \fIsize\fR strings will
+/*     be remembered.  Specify a value <= 0 to disable the upper bound.
+/* .IP flags
+/*     Requests for special processing. Specify the bitwise OR of zero
+/*     or more flags:
+/* .RS
+/* .IP BH_FLAG_FOLD
+/*     Enable case-insensitive lookup.
+/* .IP BH_FLAG_NONE
+/*     A manifest constant that requests no special processing.
+/* .RE
+/* .IP dup_filter
+/*     The table with remembered names
+/* .IP level
+/*     The value that will be returned when the string is found by either
+/*     been_here_level() or been_here_check_level(). This value must be
+/*     >= 0.
+/* .IP string
+/*     Fixed search string.
+/* .IP format
+/*     Format for building the search string.
+/* LICENSE
+/* .ad
+/* .fi
+/*     The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include "sys_defs.h"
+#include <stdlib.h>                    /* 44BSD stdarg.h uses abort() */
+#include <stdarg.h>
+
+/* Utility library. */
+
+#include <msg.h>
+#include <mymalloc.h>
+#include <htable.h>
+#include <vstring.h>
+#include <stringops.h>
+
+/* Global library. */
+
+#include "been_here.h"
+
+/* been_here_level - duplicate detector with finer control */
+
+int     been_here_level(BH_TABLE *dup_filter, int level, const char *fmt,...)
+{
+    VSTRING *buf = vstring_alloc(100);
+    int     status;
+    va_list ap;
+
+    /*
+     * Construct the string to be checked.
+     */
+    va_start(ap, fmt);
+    vstring_vsprintf(buf, fmt, ap);
+    va_end(ap);
+
+    /*
+     * Do the duplicate check.
+     */
+    status = been_here_level_fixed(dup_filter, level, vstring_str(buf));
+
+    /*
+     * Cleanup.
+     */
+    vstring_free(buf);
+    return (status);
+}
+
+/* been_here_level_fixed - duplicate detector */
+
+int     been_here_level_fixed(BH_TABLE *dup_filter, int level, const char *string)
+{
+    char   *folded_string;
+    const char *lookup_key;
+    int     status;
+    HTABLE_INFO *info;
+
+    /*
+     * Sanity check.
+     */
+    if (level < 0)
+       msg_panic("been_here_level_fixed: bad level %d", level);
+
+    /*
+     * Special processing: case insensitive lookup.
+     */
+    if (dup_filter->flags & BH_FLAG_FOLD) {
+       folded_string = mystrdup(string);
+       lookup_key = lowercase(folded_string);
+    } else {
+       folded_string = 0;
+       lookup_key = string;
+    }
+
+    /*
+     * Do the duplicate check.
+     */
+    if ((info = htable_locate(dup_filter->table, lookup_key)) != 0) {
+       status = CAST_CHAR_PTR_TO_INT(info->value);
+    } else {
+       if (dup_filter->limit <= 0
+           || dup_filter->limit > dup_filter->table->used)
+           htable_enter(dup_filter->table, lookup_key,
+                        CAST_INT_TO_CHAR_PTR(level));
+       status = -1;
+    }
+    if (msg_verbose)
+       msg_info("been_here_level: %s: %d", string, status);
+
+    /*
+     * Cleanup.
+     */
+    if (folded_string)
+       myfree(folded_string);
+
+    return (status);
+}
+
+/* been_here_level_check - query duplicate detector with finer control */
+
+int     been_here_level_check(BH_TABLE *dup_filter, const char *fmt,...)
+{
+    VSTRING *buf = vstring_alloc(100);
+    int     status;
+    va_list ap;
+
+    /*
+     * Construct the string to be checked.
+     */
+    va_start(ap, fmt);
+    vstring_vsprintf(buf, fmt, ap);
+    va_end(ap);
+
+    /*
+     * Do the duplicate check.
+     */
+    status = been_here_level_check_fixed(dup_filter, vstring_str(buf));
+
+    /*
+     * Cleanup.
+     */
+    vstring_free(buf);
+    return (status);
+}
+
+/* been_here_level_check_fixed - query duplicate detector */
+
+int     been_here_level_check_fixed(BH_TABLE *dup_filter, const char *string)
+{
+    char   *folded_string;
+    const char *lookup_key;
+    int     status;
+    HTABLE_INFO *info;
+
+    /*
+     * Special processing: case insensitive lookup.
+     */
+    if (dup_filter->flags & BH_FLAG_FOLD) {
+       folded_string = mystrdup(string);
+       lookup_key = lowercase(folded_string);
+    } else {
+       folded_string = 0;
+       lookup_key = string;
+    }
+
+    /*
+     * Do the duplicate check.
+     */
+    if ((info = htable_locate(dup_filter->table, lookup_key)) != 0)
+       status = (-1);
+    else
+       status = CAST_CHAR_PTR_TO_INT(info->value);
+    if (msg_verbose)
+       msg_info("been_here_level_check: %s: %d", string, status);
+
+    /*
+     * Cleanup.
+     */
+    if (folded_string)
+       myfree(folded_string);
+
+    return (status);
+}
index 8dff9102277a9ea9b4c90dd690aeb6d91959cafc..c60565d622913d215d3b42a3eeb01fb5d64e852e 100644 (file)
 #define CLEANUP_STAT_HOVFL     (1<<7)  /* Header overflow */
 #define CLEANUP_STAT_ROVFL     (1<<8)  /* Recipient overflow */
 
-#define CLEANUP_STAT_LETHAL    ~(CLEANUP_STAT_HOVFL|CLEANUP_STAT_ROVFL)
+ /*
+  * These are set when we can't bounce even if we were asked to.
+  */
+#define CLEANUP_STAT_MASK_CANT_BOUNCE \
+       (CLEANUP_STAT_BAD | CLEANUP_STAT_WRITE)
+
+ /*
+  * These are set when we can't examine every record of a message.
+  */
+#define CLEANUP_STAT_MASK_INCOMPLETE \
+       (CLEANUP_STAT_BAD | CLEANUP_STAT_WRITE | CLEANUP_STAT_SIZE)
+
+ /*
+  * These are relevant for extracting recipients from headers.
+  */
+#define CLEANUP_STAT_MASK_EXTRACT_RCPT \
+       (CLEANUP_STAT_HOVFL | CLEANUP_STAT_ROVFL | CLEANUP_STAT_RCPT)
 
 extern const char *cleanup_strerror(unsigned);
 
index 02d50707b1e7c7175a76415c86fa8bb9e3450048..41ae0d38f8867685f17b24cde5f24bb8d7646109 100644 (file)
@@ -29,8 +29,9 @@
 /*     void    mail_stream_cleanup(info)
 /*     MAIL_STREAM *info;
 /*
-/*     int     mail_stream_finish(info)
+/*     int     mail_stream_finish(info, why)
 /*     MAIL_STREAM *info;
+/*     VSTRING *why;
 /* DESCRIPTION
 /*     This module provides a generic interface to Postfix queue file
 /*     format messages to file, to Postfix server, or to external command.
@@ -62,6 +63,7 @@
 /*     any of the mail_stream_xxx() routines, and destroys the argument.
 /*     The result is any of the status codes defined in <cleanup_user.h>.
 /*     It is up to the caller to remove incomplete file objects.
+/*     The why argument can be a null pointer.
 /* LICENSE
 /* .ad
 /* .fi
@@ -123,7 +125,15 @@ static int mail_stream_finish_file(MAIL_STREAM * info, VSTRING *unused_why)
 
     /*
      * Make sure the message makes it to file. Set the execute bit when no
-     * write error was detected.
+     * write error was detected. Some people believe that this code has a
+     * problem if the system crashes before fsync() returns; fchmod() could
+     * take effect before all the data blocks are written. Wietse claims that
+     * this is not a problem. Postfix rejects incomplete queue files, even
+     * when the +x attribute is set. Every Postfix queue file record has a
+     * type code and a length field. Files with truncated records are
+     * rejected, as are files with unknown type codes. Every Postfix queue
+     * file must end with an explicit END record. Postfix queue files without
+     * END record are discarded.
      */
     if (vstream_fflush(info->stream)
        || fchmod(vstream_fileno(info->stream), 0700)
@@ -168,10 +178,13 @@ static int mail_stream_finish_ipc(MAIL_STREAM * info, VSTRING *why)
     /*
      * Receive the peer's completion status.
      */
-    if (attr_scan(info->stream, ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA,
-                 ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &status,
-                 ATTR_TYPE_STR, MAIL_ATTR_WHY, why,
-                 ATTR_TYPE_END) != 2)
+    if ((why && attr_scan(info->stream, ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA,
+                         ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &status,
+                         ATTR_TYPE_STR, MAIL_ATTR_WHY, why,
+                         ATTR_TYPE_END) != 2)
+       || (!why && attr_scan(info->stream, ATTR_FLAG_MISSING,
+                             ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &status,
+                             ATTR_TYPE_END) != 1))
        status = CLEANUP_STAT_WRITE;
 
     /*
index 4d4d61c3f8b345d0e4527bd1f8dd79c26c634b77..457f19d6b8fd4a0cf0485d5c37290a5a287d1799 100644 (file)
@@ -79,7 +79,7 @@ int     mail_trigger(const char *class, const char *service,
      */
     path = mail_pathname(class, service);
     if ((status = stat(path, &st)) < 0) {
-        /* void */ ;
+        msg_warn("unable to look up %s: %m", path);
     } else if (S_ISFIFO(st.st_mode)) {
        status = fifo_trigger(path, req_buf, req_len, var_trigger_timeout);
        if (status < 0 && S_ISSOCK(st.st_mode))
index 6508da3b3d03955bfcec33aab2a6b086ec848637..d37440660e3991829449df0fef8c38f83f20ea54 100644 (file)
@@ -15,7 +15,7 @@
   * Version of this program.
   */
 #define VAR_MAIL_VERSION       "mail_version"
-#define DEF_MAIL_VERSION       "Snapshot-20011015"
+#define DEF_MAIL_VERSION       "Snapshot-20011029"
 extern char *var_mail_version;
 
 /* LICENSE
index 8c9615a6fd44c97342e8339daf93b90707589c1b..766a41360060ffcb49399b550d52f70c0904bb96 100644 (file)
 /*     or when it appears to be a shell built-in command, otherwise
 /*     the command is executed without invoking a shell.
 /*     One of PIPE_CMD_COMMAND or PIPE_CMD_ARGV must be specified.
+/*     See also the PIPE_CMD_SHELL attribute below.
 /* .IP "PIPE_CMD_ARGV (char **)"
 /*     The command is specified as an argument vector. This vector is
 /*     passed without further inspection to the \fIexecvp\fR() routine.
 /*     One of PIPE_CMD_COMMAND or PIPE_CMD_ARGV must be specified.
-/*     See also the PIPE_CMD_SHELL attribute below.
 /* .IP "PIPE_CMD_ENV (char **)"
 /*     Additional environment information, in the form of a null-terminated
 /*     list of name, value, name, value, ... elements. By default only the
index 3b8f46f059f19240c14f96ea0b2f0404e3a7cd8f..84e03dd132c7e82cdf199d8823b400272b18cad4 100644 (file)
@@ -47,6 +47,7 @@ REC_TYPE_NAME rec_type_names[] = {
     REC_TYPE_FILT, "content_filter",
     REC_TYPE_FROM, "sender",
     REC_TYPE_DONE, "done",
+    REC_TYPE_ORCP, "envelope-to-recipient",
     REC_TYPE_RCPT, "recipient",
     REC_TYPE_WARN, "warning_message_time",
     REC_TYPE_MESG, "message_content",
index 1a89d8c959fbb39906003ce521b668bc798d5a9e..58db373a5b10aab06b557a131d8d9b46bba03d8b 100644 (file)
@@ -32,6 +32,7 @@
 #define REC_TYPE_FILT  'L'             /* loop filter transport */
 #define REC_TYPE_FROM  'S'             /* sender, required */
 #define REC_TYPE_DONE  'D'             /* delivered recipient, optional */
+#define REC_TYPE_ORCP  'O'             /* envelope-to recipient */
 #define REC_TYPE_RCPT  'R'             /* todo recipient, optional */
 #define REC_TYPE_WARN  'W'             /* warning message time */
 
@@ -54,9 +55,9 @@
   * record groups. The first member in each set is the record type that
   * indicates the end of that record group.
   */
-#define REC_TYPE_ENVELOPE      "MCTFILSDRWV"
+#define REC_TYPE_ENVELOPE      "MCTFILSDORWV"
 #define REC_TYPE_CONTENT       "XLN"
-#define REC_TYPE_EXTRACT       "EDRPre"
+#define REC_TYPE_EXTRACT       "EDORPre"
 #define REC_TYPE_NOEXTRACT     "E"
 
  /*
index 9821cf6af489375037a8f60af0a8ab6dfd4db20e..c10125b2a45050c6b6166619303267a3202e935e 100644 (file)
@@ -132,6 +132,8 @@ lmtp_connect.o: ../../include/timed_connect.h
 lmtp_connect.o: ../../include/stringops.h
 lmtp_connect.o: ../../include/mail_params.h
 lmtp_connect.o: ../../include/mail_proto.h
+lmtp_connect.o: ../../include/attr.h
+lmtp_connect.o: ../../include/htable.h
 lmtp_connect.o: ../../include/dns.h
 lmtp_connect.o: lmtp.h
 lmtp_connect.o: ../../include/argv.h
index ff36cf9bf6573415a8887ba61616a41df04c5e8a..5aa5fec5c108883b3e802d62fef9c720ccd91506 100644 (file)
@@ -213,6 +213,7 @@ forward.o: ../../include/vstring_vstream.h
 forward.o: ../../include/iostuff.h
 forward.o: ../../include/stringops.h
 forward.o: ../../include/mail_proto.h
+forward.o: ../../include/attr.h
 forward.o: ../../include/cleanup_user.h
 forward.o: ../../include/sent.h
 forward.o: ../../include/record.h
@@ -334,13 +335,16 @@ mailbox.o: ../../include/deliver_request.h
 mailbox.o: ../../include/recipient_list.h
 mailbox.o: ../../include/mail_proto.h
 mailbox.o: ../../include/iostuff.h
+mailbox.o: ../../include/attr.h
 mailbox.o: ../../include/mbox_open.h
 mailbox.o: ../../include/safe_open.h
+mailbox.o: ../../include/maps.h
+mailbox.o: ../../include/dict.h
+mailbox.o: ../../include/argv.h
 mailbox.o: local.h
 mailbox.o: ../../include/tok822.h
 mailbox.o: ../../include/resolve_clnt.h
 mailbox.o: ../../include/mbox_conf.h
-mailbox.o: ../../include/argv.h
 mailbox.o: biff_notify.h
 maildir.o: maildir.c
 maildir.o: ../../include/sys_defs.h
@@ -403,6 +407,7 @@ resolve.o: ../../include/htable.h
 resolve.o: ../../include/mail_proto.h
 resolve.o: ../../include/vstream.h
 resolve.o: ../../include/iostuff.h
+resolve.o: ../../include/attr.h
 resolve.o: ../../include/resolve_clnt.h
 resolve.o: ../../include/rewrite_clnt.h
 resolve.o: ../../include/tok822.h
@@ -446,9 +451,10 @@ unknown.o: ../../include/mail_params.h
 unknown.o: ../../include/mail_proto.h
 unknown.o: ../../include/vstream.h
 unknown.o: ../../include/iostuff.h
+unknown.o: ../../include/attr.h
+unknown.o: ../../include/htable.h
 unknown.o: ../../include/bounce.h
 unknown.o: local.h
-unknown.o: ../../include/htable.h
 unknown.o: ../../include/tok822.h
 unknown.o: ../../include/resolve_clnt.h
 unknown.o: ../../include/deliver_request.h
index 742eb478fe208db8f1ddeecfc3851d944e159116..c8fcdc145f8acad41c90e814c314fb52dd5a9d67 100644 (file)
@@ -120,6 +120,10 @@ static FORWARD_INFO *forward_open(char *sender)
      * Contact the cleanup service and save the new mail queue id. Request
      * that the cleanup service bounces bad messages to the sender so that we
      * can avoid the trouble of bounce management.
+     * 
+     * In case you wonder what kind of bounces, examples are "too many hops",
+     * "message too large", perhaps some others. The reason not to bounce
+     * ourselves is that we don't really know who the recipients are.
      */
     cleanup = mail_connect(MAIL_CLASS_PRIVATE, MAIL_SERVICE_CLEANUP, BLOCKING);
     if (cleanup == 0)
index db445d72ac5aa45d132e4a325308dcb6577ff96b..729a06b2d26136d89dc715e6c8500be9946c62f1 100644 (file)
@@ -131,6 +131,8 @@ master_ent.o: ../../include/inet_util.h
 master_ent.o: ../../include/inet_addr_host.h
 master_ent.o: ../../include/mail_proto.h
 master_ent.o: ../../include/iostuff.h
+master_ent.o: ../../include/attr.h
+master_ent.o: ../../include/htable.h
 master_ent.o: ../../include/mail_params.h
 master_ent.o: ../../include/own_inet_addr.h
 master_ent.o: master_proto.h
@@ -205,6 +207,8 @@ master_wakeup.o: ../../include/mail_proto.h
 master_wakeup.o: ../../include/vstream.h
 master_wakeup.o: ../../include/vbuf.h
 master_wakeup.o: ../../include/iostuff.h
+master_wakeup.o: ../../include/attr.h
+master_wakeup.o: ../../include/htable.h
 master_wakeup.o: mail_server.h
 master_wakeup.o: master.h
 multi_server.o: multi_server.c
index 39aab4331b85a98b42ea8deff39ada7a49684764..602db54c71ae2bf2ea2631f331125e11c93c9aa0 100644 (file)
@@ -273,6 +273,7 @@ static void multi_server_wakeup(int fd)
 {
     VSTREAM *stream;
     char   *tmp;
+
     if (msg_verbose)
        msg_info("connection established fd %d", fd);
     non_blocking(fd, BLOCKING);
@@ -280,7 +281,7 @@ static void multi_server_wakeup(int fd)
     client_count++;
     stream = vstream_fdopen(fd, O_RDWR);
     tmp = concatenate(multi_server_name, " socket", (char *) 0);
-    vstream_control(stream, VSTREAM_CTL_PATH, tmp,  VSTREAM_CTL_END);
+    vstream_control(stream, VSTREAM_CTL_PATH, tmp, VSTREAM_CTL_END);
     myfree(tmp);
     timed_ipc_setup(stream);
     if (multi_server_in_flow_delay && mail_flow_get(1) < 0)
index ddf61ea7373bedb64199b3587f42117aed0e96d9..4ead1237cb7b9a3dc86e92d3d91d41578dcbc488 100644 (file)
@@ -75,6 +75,8 @@ qmgr.o: ../../include/mail_conf.h
 qmgr.o: ../../include/mail_params.h
 qmgr.o: ../../include/mail_proto.h
 qmgr.o: ../../include/iostuff.h
+qmgr.o: ../../include/attr.h
+qmgr.o: ../../include/htable.h
 qmgr.o: ../../include/mail_flow.h
 qmgr.o: ../../include/master_proto.h
 qmgr.o: ../../include/mail_server.h
@@ -136,6 +138,8 @@ qmgr_deliver.o: ../../include/events.h
 qmgr_deliver.o: ../../include/iostuff.h
 qmgr_deliver.o: ../../include/mail_queue.h
 qmgr_deliver.o: ../../include/mail_proto.h
+qmgr_deliver.o: ../../include/attr.h
+qmgr_deliver.o: ../../include/htable.h
 qmgr_deliver.o: ../../include/recipient_list.h
 qmgr_deliver.o: ../../include/mail_params.h
 qmgr_deliver.o: ../../include/deliver_request.h
@@ -283,6 +287,7 @@ qmgr_transport.o: ../../include/vstream.h
 qmgr_transport.o: ../../include/vbuf.h
 qmgr_transport.o: ../../include/iostuff.h
 qmgr_transport.o: ../../include/mail_proto.h
+qmgr_transport.o: ../../include/attr.h
 qmgr_transport.o: ../../include/recipient_list.h
 qmgr_transport.o: ../../include/mail_conf.h
 qmgr_transport.o: ../../include/mail_params.h
index 19f5688fc7408317e7158c4b5474a7ccaf658aa2..144288104fa23e198bf4f16582e0e367aeb24609 100644 (file)
@@ -67,6 +67,8 @@ pickup.o: ../../include/mail_open_ok.h
 pickup.o: ../../include/mymalloc.h
 pickup.o: ../../include/mail_proto.h
 pickup.o: ../../include/iostuff.h
+pickup.o: ../../include/attr.h
+pickup.o: ../../include/htable.h
 pickup.o: ../../include/cleanup_user.h
 pickup.o: ../../include/mail_date.h
 pickup.o: ../../include/mail_params.h
index 03b7df23b7e6c28374c3f03ec9dcf78b7e0e2a2d..c21c9b8867b63ba4263e1aef5558dbc583e10fd8 100644 (file)
@@ -295,7 +295,7 @@ static int pickup_copy(VSTREAM *qfile, VSTREAM *cleanup,
      * bounce, the cleanup service can report only soft errors here.
      */
     rec_fputs(cleanup, REC_TYPE_END, "");
-    if (attr_scan(cleanup, ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA,
+    if (attr_scan(cleanup, ATTR_FLAG_MISSING,
                  ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &status,
                  ATTR_TYPE_END) != 1)
        return (cleanup_service_error(info, CLEANUP_STAT_WRITE));
index 1cf46772319c64ddeb584df85514d06d70623878..d9559dd9a705cdc29a64e54e5600b460b998dec2 100644 (file)
@@ -85,6 +85,7 @@ postconf.o: ../../include/mynetworks.h
 postconf.o: ../../include/mail_conf.h
 postconf.o: ../../include/mail_proto.h
 postconf.o: ../../include/iostuff.h
+postconf.o: ../../include/attr.h
 postconf.o: ../../include/mail_version.h
 postconf.o: ../../include/mail_params.h
 postconf.o: ../../include/mail_addr.h
index 2d893c3ac61449bab3e60bae24351b1aaba42e69..21f69e983e43492420e501c4189e89617452e93e 100644 (file)
@@ -65,6 +65,8 @@ postdrop.o: ../../include/msg_syslog.h
 postdrop.o: ../../include/argv.h
 postdrop.o: ../../include/mail_proto.h
 postdrop.o: ../../include/iostuff.h
+postdrop.o: ../../include/attr.h
+postdrop.o: ../../include/htable.h
 postdrop.o: ../../include/mail_queue.h
 postdrop.o: ../../include/mail_params.h
 postdrop.o: ../../include/mail_conf.h
index 411aa984fa0697212751e4779e165c06032be4b9..d028e21e6e5b0066b7a95f0d534f9ae33c8cc4bc 100644 (file)
@@ -64,5 +64,7 @@ postkick.o: ../../include/safe.h
 postkick.o: ../../include/events.h
 postkick.o: ../../include/mail_proto.h
 postkick.o: ../../include/iostuff.h
+postkick.o: ../../include/attr.h
+postkick.o: ../../include/htable.h
 postkick.o: ../../include/mail_params.h
 postkick.o: ../../include/mail_conf.h
index eaddb56f53e7a1e8793d64dc6332bc1e5e3a3690..2b04de679b2c20511462b3f5556b8dc026fc37bc 100644 (file)
@@ -73,6 +73,8 @@ qmgr.o: ../../include/mail_conf.h
 qmgr.o: ../../include/mail_params.h
 qmgr.o: ../../include/mail_proto.h
 qmgr.o: ../../include/iostuff.h
+qmgr.o: ../../include/attr.h
+qmgr.o: ../../include/htable.h
 qmgr.o: ../../include/mail_flow.h
 qmgr.o: ../../include/master_proto.h
 qmgr.o: ../../include/mail_server.h
@@ -134,6 +136,8 @@ qmgr_deliver.o: ../../include/events.h
 qmgr_deliver.o: ../../include/iostuff.h
 qmgr_deliver.o: ../../include/mail_queue.h
 qmgr_deliver.o: ../../include/mail_proto.h
+qmgr_deliver.o: ../../include/attr.h
+qmgr_deliver.o: ../../include/htable.h
 qmgr_deliver.o: ../../include/recipient_list.h
 qmgr_deliver.o: ../../include/mail_params.h
 qmgr_deliver.o: ../../include/deliver_request.h
@@ -255,6 +259,7 @@ qmgr_transport.o: ../../include/vstream.h
 qmgr_transport.o: ../../include/vbuf.h
 qmgr_transport.o: ../../include/iostuff.h
 qmgr_transport.o: ../../include/mail_proto.h
+qmgr_transport.o: ../../include/attr.h
 qmgr_transport.o: ../../include/recipient_list.h
 qmgr_transport.o: ../../include/mail_conf.h
 qmgr_transport.o: ../../include/mail_params.h
index 117cf9ea4293e2ad0672b90fe51fb84a930babba..8eb77b61297b568c354185293fb7a62b562062a9 100644 (file)
@@ -82,6 +82,8 @@ qmqpd.o: ../../include/record.h
 qmqpd.o: ../../include/rec_type.h
 qmqpd.o: ../../include/mail_proto.h
 qmqpd.o: ../../include/iostuff.h
+qmqpd.o: ../../include/attr.h
+qmqpd.o: ../../include/htable.h
 qmqpd.o: ../../include/cleanup_user.h
 qmqpd.o: ../../include/mail_date.h
 qmqpd.o: ../../include/mail_conf.h
index f1d599578b5aef7dc1f2149936f095c2ae77392d..40ea8083997c70764681b6af79bdb7f3ea39c376 100644 (file)
@@ -436,6 +436,8 @@ static int qmqpd_send_status(QMQPD_STATE *state)
     /*
      * One message may suffer from multiple errors, so complain only about
      * the most severe error.
+     * 
+     * See also: smtpd.c
      */
     state->where = "sending completion status";
 
@@ -461,7 +463,8 @@ static int qmqpd_send_status(QMQPD_STATE *state)
        qmqpd_reply(state, DO_LOG, QMQPD_STAT_HARD,
                    "Error: no recipients specified");
     } else {
-       msg_panic("qmqpd_send_status: unknown status %d", state->err);
+       qmqpd_reply(state, DO_LOG, QMQPD_STAT_RETRY,
+                   "Error: internal error %d", state->err);
     }
 }
 
index b1b7386514c206be4d81ee5d70b51ea1cdb68239..13bbb4370179e76a7de98c30ae91c650e8c86639 100644 (file)
@@ -73,6 +73,8 @@ sendmail.o: ../../include/set_ugid.h
 sendmail.o: ../../include/connect.h
 sendmail.o: ../../include/mail_queue.h
 sendmail.o: ../../include/mail_proto.h
+sendmail.o: ../../include/attr.h
+sendmail.o: ../../include/htable.h
 sendmail.o: ../../include/mail_params.h
 sendmail.o: ../../include/record.h
 sendmail.o: ../../include/rec_type.h
index 694e99a558f139fe982383260d9cb9b27769b00c..cdf6ad88003e465733e8ace47efb33f227cbbdcd 100644 (file)
 /*     configuration parameter instead.
 /* .IP \fB-qR\fIsite\fR
 /*     Schedule immediate delivery of all mail that is queued for the named
-/*     \fIsite\fR. Depending on the destination, this uses "fast flush"
-/*     service, or it has the same effect as \fBsendmail -q\fR.
-/*     This is implemented by connecting to the local SMTP server.
+/*     \fIsite\fR. This uses "fast flush" service, and is implemented
+/*     by connecting to the local SMTP server at \fB$myhostname\fR.
 /*     See \fBsmtpd\fR(8) for more information about the "fast flush"
 /*     service.
 /* .IP \fB-qS\fIsite\fR
@@ -516,7 +515,7 @@ static void enqueue(const int flags, const char *sender, const char *full_name,
     if (vstream_ferror(VSTREAM_IN))
        msg_fatal("%s(%ld): error reading input: %m",
                  saved_sender, (long) uid);
-    if ((status = mail_stream_finish(handle, buf)) != 0)
+    if ((status = mail_stream_finish(handle, (VSTRING *) 0)) != 0)
        msg_fatal("%s(%ld): %s", saved_sender,
                  (long) uid, cleanup_strerror(status));
     if (sendmail_path) {
index 23d15c420d5463146f443230b4e9eb42959db9e8..5c714ef1145d9a6485792236b50f60850ac81e7b 100644 (file)
@@ -68,6 +68,7 @@ showq.o: ../../include/mail_queue.h
 showq.o: ../../include/mail_open_ok.h
 showq.o: ../../include/mail_proto.h
 showq.o: ../../include/iostuff.h
+showq.o: ../../include/attr.h
 showq.o: ../../include/mail_date.h
 showq.o: ../../include/mail_params.h
 showq.o: ../../include/mail_scan_dir.h
index 15f860f611cb08938f431cfc6c0b960edfb39d42..5f749ea5f3ff910913726096b32d47eea04000f4 100644 (file)
@@ -80,6 +80,8 @@ smtp.o: ../../include/mail_error.h
 smtp.o: ../../include/deliver_pass.h
 smtp.o: ../../include/mail_proto.h
 smtp.o: ../../include/iostuff.h
+smtp.o: ../../include/attr.h
+smtp.o: ../../include/htable.h
 smtp.o: ../../include/mail_server.h
 smtp.o: smtp.h
 smtp.o: smtp_sasl.h
index 73a26230671e98ad9543a2539d72c9275f01cd72..33c3d96bacb9438d2d16c1f5b471dc8b7fa9a788 100644 (file)
@@ -113,6 +113,8 @@ smtpd.o: ../../include/record.h
 smtpd.o: ../../include/rec_type.h
 smtpd.o: ../../include/mail_proto.h
 smtpd.o: ../../include/iostuff.h
+smtpd.o: ../../include/attr.h
+smtpd.o: ../../include/htable.h
 smtpd.o: ../../include/cleanup_user.h
 smtpd.o: ../../include/mail_date.h
 smtpd.o: ../../include/mail_conf.h
@@ -148,6 +150,8 @@ smtpd_chat.o: ../../include/record.h
 smtpd_chat.o: ../../include/rec_type.h
 smtpd_chat.o: ../../include/mail_proto.h
 smtpd_chat.o: ../../include/iostuff.h
+smtpd_chat.o: ../../include/attr.h
+smtpd_chat.o: ../../include/htable.h
 smtpd_chat.o: ../../include/mail_params.h
 smtpd_chat.o: ../../include/mail_addr.h
 smtpd_chat.o: ../../include/post_mail.h
@@ -226,6 +230,8 @@ smtpd_sasl_proto.o: ../../include/mail_proto.h
 smtpd_sasl_proto.o: ../../include/vstream.h
 smtpd_sasl_proto.o: ../../include/vbuf.h
 smtpd_sasl_proto.o: ../../include/iostuff.h
+smtpd_sasl_proto.o: ../../include/attr.h
+smtpd_sasl_proto.o: ../../include/htable.h
 smtpd_sasl_proto.o: ../../include/mail_error.h
 smtpd_sasl_proto.o: ../../include/name_mask.h
 smtpd_sasl_proto.o: smtpd.h
index 0ecd36fcddb663e8c871f55f4420ef46b1eae567..f3954d1b0a8a56a459edabf570e983499f9229d5 100644 (file)
@@ -516,7 +516,7 @@ static void mail_open_stream(SMTPD_STATE *state)
                                          MAIL_SERVICE_CLEANUP);
        if (state->dest == 0
            || attr_print(state->dest->stream, ATTR_FLAG_NONE,
-                         ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, CLEANUP_FLAG_FILTER,
+                       ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, CLEANUP_FLAG_FILTER,
                          ATTR_TYPE_END) != 0)
            msg_fatal("unable to connect to the %s %s service",
                      MAIL_CLASS_PRIVATE, MAIL_SERVICE_CLEANUP);
@@ -1000,7 +1000,7 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
      * Finish the queue file or finish the cleanup conversation.
      */
     if (state->err == 0)
-       state->err |= mail_stream_finish(state->dest, why = vstring_alloc(10));
+       state->err = mail_stream_finish(state->dest, why = vstring_alloc(10));
     else
        mail_stream_cleanup(state->dest);
     state->dest = 0;
@@ -1024,6 +1024,8 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
      * Handle any errors. One message may suffer from multiple errors, so
      * complain only about the most severe error. Forgive any previous client
      * errors when a message was received successfully.
+     * 
+     * See also: qmqpd.c
      */
     if (state->err == CLEANUP_STAT_OK) {
        state->error_count = 0;
@@ -1041,15 +1043,14 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
        smtpd_chat_reply(state, "554 Error: too many hops");
     } else if ((state->err & CLEANUP_STAT_CONT) != 0) {
        state->error_mask |= MAIL_ERROR_POLICY;
-       smtpd_chat_reply(state, "552 Error: %s", STR(why));
+       smtpd_chat_reply(state, "552 Error: %s", LEN(why) ?
+                        STR(why) : "content rejected");
     } else if ((state->err & CLEANUP_STAT_WRITE) != 0) {
        state->error_mask |= MAIL_ERROR_RESOURCE;
        smtpd_chat_reply(state, "451 Error: queue file write error");
-    } else if ((state->err & CLEANUP_STAT_RCPT) != 0) {
+    } else {
        state->error_mask |= MAIL_ERROR_SOFTWARE;
        smtpd_chat_reply(state, "451 Error: internal error %d", state->err);
-    } else {
-       msg_panic("data_cmd: unknown status %d", state->err);
     }
 
     /*
index afbe44e62ecd88568d7c4e30406556504f7feb06..d558c37c3b250814740ebd8ea445f7489de37abd 100644 (file)
@@ -1158,7 +1158,7 @@ static int i_am_mx(DNS_RR *mx_list)
 static int permit_mx_primary(DNS_RR *mx_list)
 {
     DNS_RR *mx;
-    int     best_pref;
+    unsigned int best_pref;
     int     status;
 
     /*
index 1065ce0cfeac53eddb554b1dc05e1a1b62b116ed..6e97b0ba92140c43150ff88035706e42ab443e8e 100644 (file)
@@ -70,6 +70,8 @@ resolve.o: ../../include/split_at.h
 resolve.o: ../../include/mail_params.h
 resolve.o: ../../include/mail_proto.h
 resolve.o: ../../include/iostuff.h
+resolve.o: ../../include/attr.h
+resolve.o: ../../include/htable.h
 resolve.o: ../../include/mail_addr.h
 resolve.o: ../../include/rewrite_clnt.h
 resolve.o: ../../include/resolve_local.h
@@ -90,6 +92,8 @@ rewrite.o: ../../include/split_at.h
 rewrite.o: ../../include/mail_params.h
 rewrite.o: ../../include/mail_proto.h
 rewrite.o: ../../include/iostuff.h
+rewrite.o: ../../include/attr.h
+rewrite.o: ../../include/htable.h
 rewrite.o: ../../include/resolve_local.h
 rewrite.o: ../../include/tok822.h
 rewrite.o: ../../include/resolve_clnt.h
@@ -123,6 +127,8 @@ trivial-rewrite.o: ../../include/argv.h
 trivial-rewrite.o: ../../include/mail_params.h
 trivial-rewrite.o: ../../include/mail_proto.h
 trivial-rewrite.o: ../../include/iostuff.h
+trivial-rewrite.o: ../../include/attr.h
+trivial-rewrite.o: ../../include/htable.h
 trivial-rewrite.o: ../../include/resolve_local.h
 trivial-rewrite.o: ../../include/mail_conf.h
 trivial-rewrite.o: ../../include/resolve_clnt.h
index 0d51b9b21428599c68becfdd9fd865fdb13e68d6..cd039e043f771bed05fcdafcc633dd0cf0f08610 100644 (file)
@@ -24,7 +24,7 @@ SRCS  = argv.c argv_split.c attr.c basename.c binhash.c chroot_uid.c \
        sane_link.c unescape.c timed_read.c timed_write.c dict_tcp.c \
        hex_quote.c dict_alloc.c rand_sleep.c sane_time.c dict_debug.c \
        sane_socketpair.c myrand.c netstring.c ctable.c attr_print.c intv.c \
-       attr_scan.c attr_table.c base64_code.c
+       attr_scan.c base64_code.c
 OBJS   = argv.o argv_split.o attr.o basename.o binhash.o chroot_uid.o \
        close_on_exec.o concatenate.o dict.o dict_db.o dict_dbm.o \
        dict_env.o dict_ht.o dict_ldap.o dict_mysql.o dict_ni.o dict_nis.o \
@@ -50,7 +50,7 @@ OBJS  = argv.o argv_split.o attr.o basename.o binhash.o chroot_uid.o \
        sane_link.o unescape.o timed_read.o timed_write.o dict_tcp.o \
        hex_quote.o dict_alloc.o rand_sleep.o sane_time.o dict_debug.o \
        sane_socketpair.o myrand.o netstring.o ctable.o attr_print.o intv.o \
-       attr_scan.o attr_table.o base64_code.o
+       attr_scan.o base64_code.o
 HDRS   = argv.h attr.h binhash.h chroot_uid.h connect.h dict.h dict_db.h \
        dict_dbm.h dict_env.h dict_ht.h dict_ldap.h dict_mysql.h \
        dict_ni.h dict_nis.h dict_nisplus.h dir_forest.h events.h \
@@ -84,7 +84,7 @@ TESTPROG= dict_open dup2_pass_on_exec events exec_command fifo_open \
        mystrtok sigdelay translit valid_hostname vstream_popen \
        vstring vstring_vstream doze select_bug stream_test mac_expand \
        watchdog unescape hex_quote name_mask rand_sleep sane_time ctable \
-       inet_addr_list attr_print attr_scan attr_table base64_code
+       inet_addr_list attr_print attr_scan base64_code
 
 LIB_DIR        = ../../lib
 INC_DIR        = ../../include
@@ -298,11 +298,6 @@ attr_scan: $(LIB) $@.o
        $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS)
        mv junk $@.o
 
-attr_table: $(LIB) $@.o
-       mv $@.o junk
-       $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS)
-       mv junk $@.o
-
 base64_code: $(LIB) $@.o
        mv $@.o junk
        $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS)
index 4e5febec50a4f6a898f89e7017b1e622ff770b6e..b0b0601c65cdba5c366be4065cc6e694f8224976 100644 (file)
@@ -50,17 +50,6 @@ extern int attr_vprint(VSTREAM *, int, va_list);
 extern int attr_scan(VSTREAM *, int,...);
 extern int attr_vscan(VSTREAM *, int, va_list);
 
- /*
-  * attr_table.c.
-  */
-typedef HTABLE ATTR_TABLE;
-
-extern ATTR_TABLE *attr_table_create(int);
-extern void attr_table_free(ATTR_TABLE *);
-extern int attr_table_read(ATTR_TABLE *, int, VSTREAM *);
-extern int attr_table_get(ATTR_TABLE *, int,...);
-extern int attr_table_vget(ATTR_TABLE *, int, va_list);
-
  /*
   * attr.c.
   */
@@ -78,11 +67,6 @@ extern int attr_find(HTABLE *, int,...);
 #define ATTR_NAME_STR_ARRAY    "string_array"
 #endif
 
- /*
-  * Testing.
-  */
-#define BASE64_DECODE(buf, str, len)   vstring_strncpy((buf), (str), (len))
-
 /* LICENSE
 /* .ad
 /* .fi
index 3039f1a94265be14f64c1bcb7fae6bedd0e73315..51320bf5fe4a0288ff19b4f1fa73df455b9675fe 100644 (file)
@@ -29,6 +29,8 @@
 /*     (item1 | item2) stands for choice:
 /*
 /* .in +5
+/*     input :== attr-list
+/* .br
 /*     attr-list :== (simple-attr | list-attr)* newline
 /* .br
 /*     simple-attr :== attr-name colon attr-value newline
@@ -227,7 +229,7 @@ int     attr_vscan(VSTREAM *fp, int flags, va_list ap)
     static VSTRING *name_buf = 0;
     int     wanted_type = -1;
     char   *wanted_name;
-    int    *number;
+    unsigned int *number;
     VSTRING *string;
     INTV   *number_array;
     ARGV   *string_array;
diff --git a/postfix/src/util/attr_table.c b/postfix/src/util/attr_table.c
deleted file mode 100644 (file)
index 2d69c81..0000000
+++ /dev/null
@@ -1,439 +0,0 @@
-/*++
-/* NAME
-/*     attr_table 3
-/* SUMMARY
-/*     recover attributes from byte stream
-/* SYNOPSIS
-/*     #include <attr.h>
-/*
-/*     ATTR_TABLE *attr_table_create(size)
-/*     int     size;
-/*
-/*     void    attr_table_free(attr)
-/*     ATTR_TABLE *attr;
-/*
-/*     int     attr_table_read(attr, flags, fp)
-/*     ATTR_TABLE *attr;
-/*     int     flags;
-/*     VSTREAM fp;
-/*
-/*     int     attr_table_get(attr, flags, type, name, ...)
-/*     ATTR_TABLE *attr;
-/*     int     flags;
-/*     int     type;
-/*     char    *name;
-/* DESCRIPTION
-/*     This module provides an alternative process for recovering
-/*     attribute lists from a byte stream. The process involves the
-/*     storage in an intermediate attribute table that is subsequently
-/*     queried. This procedure gives more control to the application,
-/*     at the cost of complexity and of memory resources.
-/*
-/*     attr_table_create() creates an empty table for storage of
-/*     the intermediate result from attr_table_read().
-/*
-/*     attr_table_free() destroys its argument.
-/*
-/*     attr_table_read() reads an attribute list from a byte stream
-/*     and stores the intermediate result into a table that can be
-/*     queried with attr_table_get().
-/*
-/*     attr_table_get() takes zero or more (name, value) scalar or array
-/*     attribute arguments, and recovers the attribute values from the
-/*     intermediate attribute table produced by attr_table_read().
-/*
-/*     Arguments:
-/* .IP fp
-/*     Stream to recover the attributes from.
-/* .IP flags
-/*     The bit-wise OR of zero or more of the following.
-/* .RS
-/* .IP ATTR_FLAG_MISSING
-/*     Log a warning when the input attribute list terminates before all
-/*     requested attributes are recovered. It is always an error when the
-/*     input stream ends without the newline attribute list terminator.
-/*     This flag has no effect with attr_table_read().
-/* .IP ATTR_FLAG_EXTRA
-/*     Log a warning and stop attribute recovery when the input stream
-/*     contains multiple instances of an attribute.
-/*     This flag has no effect with attr_table_get().
-/* .IP ATTR_FLAG_NONE
-/*     For convenience, this value requests none of the above.
-/* .RE
-/* .IP type
-/*     The type determines the arguments that follow.
-/* .RS
-/* .IP "ATTR_TYPE_NUM (char *, int *)"
-/*     This argument is followed by an attribute name and an integer pointer.
-/*     This is used for recovering an integer attribute value.
-/* .IP "ATTR_TYPE_STR (char *, VSTRING *)"
-/*     This argument is followed by an attribute name and a VSTRING pointer.
-/*     This is used for recovering a string attribute value.
-/* .IP "ATTR_TYPE_NUM_ARRAY (char *, INTV *)"
-/*     This argument is followed by an attribute name and an INTV pointer.
-/*     This is used for recovering an integer array attribute value.
-/* .IP "ATTR_TYPE_NUM_ARRAY (char *, ARGV *)"
-/*     This argument is followed by an attribute name and an ARGV pointer.
-/*     This is used for recovering a string array attribute value.
-/* .IP ATTR_TYPE_END
-/*     This terminates the requested attribute list.
-/* .RE
-/* DIAGNOSTICS
-/*     The result value from attr_table_read() and from attr_table_get()
-/*     is the number of attributes that were successfully recovered from
-/*     the input stream (an array-valued attribute counts as one attribute).
-/*
-/*     Panic: interface violation. All system call errors are fatal.
-/* SEE ALSO
-/*     attr_print(3) send attributes over byte stream.
-/* LICENSE
-/* .ad
-/* .fi
-/*     The Secure Mailer license must be distributed with this software.
-/* AUTHOR(S)
-/*     Wietse Venema
-/*     IBM T.J. Watson Research
-/*     P.O. Box 704
-/*     Yorktown Heights, NY 10598, USA
-/*--*/
-
-/* System library. */
-
-#include <sys_defs.h>
-#include <stdarg.h>
-#include <string.h>
-#include <stdio.h>
-
-/* Utility library. */
-
-#include <msg.h>
-#include <htable.h>
-#include <mymalloc.h>
-#include <vstring.h>
-#include <vstream.h>
-#include <vstring_vstream.h>
-#include <argv.h>
-#include <intv.h>
-#include <attr.h>
-
-/* Application-specific. */
-
-#define STR(x) vstring_str(x)
-#define LEN(x) VSTRING_LEN(x)
-
-static VSTRING *base64_buf;
-static VSTRING *plain_buf;
-
-/* attr_table_create - create attribute table */
-
-ATTR_TABLE *attr_table_create(int size)
-{
-    return (htable_create(size));
-}
-
-/* attr_table_free - destroy attribute table */
-
-void    attr_table_free(ATTR_TABLE *table)
-{
-    htable_free(table, myfree);
-}
-
-/* attr_table_read - read attribute stream into table */
-
-int     attr_table_read(ATTR_TABLE *table, int flags, VSTREAM *stream)
-{
-    char   *attr_value;
-    int     attr_count;
-    int     ch;
-
-    if (base64_buf == 0) {
-       base64_buf = vstring_alloc(10);
-       plain_buf = vstring_alloc(10);
-    }
-    for (attr_count = 0; /* void */ ; attr_count++) {
-
-       /*
-        * Unexpected end-of-file is always an error.
-        */
-       if ((ch = vstring_get_nonl(base64_buf, stream)) == VSTREAM_EOF) {
-           msg_warn("unexpected EOF while reading attributes from %s",
-                    VSTREAM_PATH(stream));
-           return (attr_count);
-       }
-
-       /*
-        * A legitimate end of attribute list is OK.
-        */
-       if (LEN(base64_buf) == 0)
-           return (attr_count);
-
-       /*
-        * Split into name and value, but keep the ':' separator so that we
-        * can distinguish between no value or a zero-length value; decode
-        * the name but keep the value in one piece, so that we can process
-        * array-valued attributes.
-        */
-       if ((attr_value = strchr(STR(base64_buf), ':')) != 0)
-           *attr_value = 0;
-       if (BASE64_DECODE(plain_buf, STR(base64_buf), attr_value ?
-                  (attr_value - STR(base64_buf)) : LEN(base64_buf)) == 0) {
-           msg_warn("malformed base64 data from %s: %.100s",
-                    VSTREAM_PATH(stream), STR(base64_buf));
-           return (attr_count);
-       }
-       if (attr_value != 0)
-           *attr_value = ':';
-       else
-           attr_value = "";
-
-       /*
-        * Stop if there are multiple instances of the same attribute name
-        * and extra attributes are to be treated as an error. We can
-        * remember only one instance.
-        */
-       if (htable_locate(table, STR(plain_buf)) != 0) {
-           if (flags & ATTR_FLAG_EXTRA) {
-               msg_warn("multiple instances of attribute %s from %s",
-                        STR(plain_buf), VSTREAM_PATH(stream));
-               return (attr_count);
-           }
-       } else {
-           htable_enter(table, STR(plain_buf), mystrdup(attr_value));
-       }
-    }
-}
-
-/* attr_conv_string - convert attribute value field to string */
-
-static int attr_conv_string(char **src, VSTRING *plain_buf,
-                                   const char *attr_name)
-{
-    char   *myname = "attr_table_get";
-    extern int var_line_limit;
-    int     limit = var_line_limit * 5 / 4;
-    char   *cp = *src;
-    int     len = 0;
-    int     ch;
-
-    for (;;) {
-       if ((ch = *(unsigned char *) cp) == 0)
-           break;
-       cp++;
-       if (ch == ':')
-           break;
-       len++;
-       if (len > limit) {
-           msg_warn("%s: string length > %d characters in attribute %s",
-                    myname, limit, attr_name);
-           return (-1);
-       }
-    }
-    if (BASE64_DECODE(plain_buf, *src, len) == 0) {
-       msg_warn("%s: malformed base64 data in attribute %s: %.*s",
-                myname, attr_name, len > 100 ? 100 : len, *src);
-       return (-1);
-    }
-    if (msg_verbose)
-       msg_info("%s: name %s value %s", myname, attr_name, STR(plain_buf));
-
-    *src = cp;
-    return (ch);
-}
-
-/* attr_conv_number - convert attribute value field to number */
-
-static int attr_conv_number(char **src, unsigned *dst, VSTRING *plain_buf,
-                                   const char *attr_name)
-{
-    char   *myname = "attr_table_get";
-    char    junk = 0;
-    int     ch;
-
-    if ((ch = attr_conv_string(src, plain_buf, attr_name)) < 0)
-       return (-1);
-    if (sscanf(STR(plain_buf), "%u%c", dst, &junk) != 1 || junk != 0) {
-       msg_warn("%s: malformed numerical data in attribute %s: %.100s",
-                myname, attr_name, STR(plain_buf));
-       return (-1);
-    }
-    return (ch);
-}
-
-/* attr_table_vget - recover attributes from table */
-
-int     attr_table_vget(ATTR_TABLE *attr, int flags, va_list ap)
-{
-    char   *myname = "attr_table_get";
-    int     attr_count;
-    char   *attr_name;
-    char   *attr_value;
-    int     attr_type;
-    int    *number;
-    VSTRING *string;
-    INTV   *number_array;
-    ARGV   *string_array;
-    unsigned num_val;
-    int     ch;
-
-    if (base64_buf == 0) {
-       base64_buf = vstring_alloc(10);
-       plain_buf = vstring_alloc(10);
-    }
-
-    /*
-     * Iterate over all (type, name, value) triples.
-     */
-    for (attr_count = 0; /* void */ ; attr_count++) {
-
-       /*
-        * Determine the next attribute name on the caller's wish list.
-        */
-       attr_type = va_arg(ap, int);
-       if (attr_type == ATTR_TYPE_END)
-           return (attr_count);
-       attr_name = va_arg(ap, char *);
-
-       /*
-        * Look up the attribute value. Peel off, but keep, the separator
-        * between name and value.
-        */
-       if ((attr_value = htable_find(attr, attr_name)) == 0) {
-           if (attr_type != ATTR_TYPE_END
-               && (flags & ATTR_FLAG_MISSING) != 0)
-               msg_warn("%s: missing attribute %s", myname, attr_name);
-           return (attr_count);
-       }
-       if ((ch = *(unsigned char *) attr_value) != 0)
-           attr_value++;
-
-       /*
-        * Do the requested conversion. If the target attribute is a
-        * non-array type, disallow sending a multi-valued attribute, and
-        * disallow sending no value. If the target attribute is an array
-        * type, allow the sender to send a zero-element array (i.e. no value
-        * at all). XXX Need to impose a bound on the number of array
-        * elements.
-        */
-       switch (attr_type) {
-       case ATTR_TYPE_NUM:
-           if (ch != ':') {
-               msg_warn("%s: missing value for attribute %s",
-                        myname, attr_name);
-               return (attr_count);
-           }
-           number = va_arg(ap, int *);
-           if ((ch = attr_conv_number(&attr_value, number, plain_buf, attr_name)) < 0)
-               return (attr_count);
-           if (ch != '\0') {
-               msg_warn("%s: too many values for attribute %s",
-                        myname, attr_name);
-               return (attr_count);
-           }
-           break;
-       case ATTR_TYPE_STR:
-           if (ch != ':') {
-               msg_warn("%s: missing value for attribute %s",
-                        myname, attr_name);
-               return (attr_count);
-           }
-           string = va_arg(ap, VSTRING *);
-           if ((ch = attr_conv_string(&attr_value, string, attr_name)) < 0)
-               return (attr_count);
-           if (ch != '\0') {
-               msg_warn("%s: too many values for attribute %s",
-                        myname, attr_name);
-               return (attr_count);
-           }
-           break;
-       case ATTR_TYPE_NUM_ARRAY:
-           number_array = va_arg(ap, INTV *);
-           while (ch != '\0') {
-               if ((ch = attr_conv_number(&attr_value, &num_val, plain_buf, attr_name)) < 0)
-                   return (attr_count);
-               intv_add(number_array, 1, num_val);
-           }
-           break;
-       case ATTR_TYPE_STR_ARRAY:
-           string_array = va_arg(ap, ARGV *);
-           while (ch != '\0') {
-               if ((ch = attr_conv_string(&attr_value, plain_buf, attr_name)) < 0)
-                   return (attr_count);
-               argv_add(string_array, STR(plain_buf), (char *) 0);
-           }
-           break;
-       default:
-           msg_panic("%s: unknown type code: %d", myname, attr_type);
-       }
-    }
-}
-
-/* attr_table_get - recover attributes from table */
-
-int     attr_table_get(ATTR_TABLE *attr, int flags,...)
-{
-    va_list ap;
-    int     ret;
-
-    va_start(ap, flags);
-    ret = attr_table_vget(attr, flags, ap);
-    va_end(ap);
-
-    return (ret);
-}
-
-#ifdef TEST
-
- /*
-  * Proof of concept test program.  Mirror image of the attr_scan test
-  * program.
-  */
-#include <msg_vstream.h>
-
-int     var_line_limit = 2048;
-
-int     main(int unused_argc, char **used_argv)
-{
-    ATTR_TABLE *attr;
-    INTV   *intv = intv_alloc(1);
-    ARGV   *argv = argv_alloc(1);
-    VSTRING *str_val = vstring_alloc(1);
-    int     int_val;
-    int     ret;
-    int     i;
-
-    msg_verbose = 1;
-    msg_vstream_init(used_argv[0], VSTREAM_ERR);
-    attr = attr_table_create(1);
-    if (attr_table_read(attr, ATTR_FLAG_EXTRA, VSTREAM_IN) > 0
-       && (ret = attr_table_get(attr,
-                                ATTR_FLAG_MISSING,
-                                ATTR_TYPE_NUM, ATTR_NAME_NUM, &int_val,
-                                ATTR_TYPE_STR, ATTR_NAME_STR, str_val,
-                            ATTR_TYPE_NUM_ARRAY, ATTR_NAME_NUM_ARRAY, intv,
-                            ATTR_TYPE_STR_ARRAY, ATTR_NAME_STR_ARRAY, argv,
-                                ATTR_TYPE_END)) == 4) {
-       vstream_printf("%s %d\n", ATTR_NAME_NUM, int_val);
-       vstream_printf("%s %s\n", ATTR_NAME_STR, STR(str_val));
-       vstream_printf("%s", ATTR_NAME_NUM_ARRAY);
-       for (i = 0; i < intv->intc; i++)
-           vstream_printf(" %d", intv->intv[i]);
-       vstream_printf("\n");
-       vstream_printf("%s", ATTR_NAME_STR_ARRAY);
-       for (i = 0; i < argv->argc; i++)
-           vstream_printf(" %s", argv->argv[i]);
-       vstream_printf("\n");
-    } else {
-       vstream_printf("return: %d\n", ret);
-    }
-    if (vstream_fflush(VSTREAM_OUT) != 0)
-       msg_fatal("write error: %m");
-
-    attr_table_free(attr);
-    intv_free(intv);
-    argv_free(argv);
-    vstring_free(str_val);
-
-    return (0);
-}
-
-#endif