]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-3.1.13 v3.1.13
authorWietse Venema <wietse@porcupine.org>
Sat, 29 Jun 2019 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <postfix-users@dukhovni.org>
Tue, 23 Jul 2019 07:36:01 +0000 (03:36 -0400)
23 files changed:
postfix/HISTORY
postfix/RELEASE_NOTES
postfix/html/lmtp.8.html
postfix/html/postconf.5.html
postfix/html/smtp.8.html
postfix/html/smtpd.8.html
postfix/html/tlsproxy.8.html
postfix/man/man5/postconf.5
postfix/man/man8/smtp.8
postfix/man/man8/smtpd.8
postfix/man/man8/tlsproxy.8
postfix/mantools/postlink
postfix/proto/postconf.proto
postfix/src/global/mail_params.h
postfix/src/global/mail_version.h
postfix/src/smtp/smtp.c
postfix/src/smtpd/smtpd.c
postfix/src/tls/Makefile.in
postfix/src/tls/tls_misc.c
postfix/src/tls/tls_session.c
postfix/src/tlsproxy/tlsproxy.c
postfix/src/util/printable.c
postfix/src/util/stringops.h

index e2e9cc20cffb3ea5667f1a9b2b3f1c97436fa1f6..ca6cad1d1bc21ce8cd4f778fd9db983ec4592b75 100644 (file)
@@ -22490,3 +22490,27 @@ Apologies for any names omitted.
        could exhaust LMTP server resources, resulting in two-second
        pauses between email deliveries. This problem was investigated
        by Juliana Rodrigueiro. File: smtp/smtp_connect.c.
+
+20190403
+
+       Bugfix (introduced: Postfix 2.3): a censoring filter broke
+       multiline Milter responses for header/body events. Problem
+       report by Andreas Thienemann. Files: util/printable.c,
+       util/stringops.h, smtpd/smtpd.c
+
+20190615
+
+       Workaround for implementations that hang Postfix while
+       shutting down a TLS session, until Postfix times out. With
+       "tls_fast_shutdown_enable = yes" (the default), Postfix no
+       longer waits for the TLS peer to respond to a TLS 'close'
+       request. This is recommended with TLSv1.0 and later. Files:
+       global/mail_params.h, tls/tls_session.c, and documentation.
+
+20190621
+
+       Bugfix (introduced: Postfix 3.0): the code to reset Postfix
+       SMTP server command counts was not called after a HaProxy
+       handshake failure, causing stale numbers to be reported.
+       The command counts are now reset in the function that reports
+       the counts. File: smtpd/smtpd.c.
index cc6d7c0d84703dc6f0551eb2efc84c31ccfe851d..179208264437d1c22ee513879222ca8edc5ce761 100644 (file)
@@ -16,6 +16,16 @@ specifies the release date of a stable release or snapshot release.
 If you upgrade from Postfix 2.11 or earlier, read RELEASE_NOTES-3.0
 before proceeding.
 
+TLS Workaround for Postfix 3.4.6, 3.3.5, 3.2.10 and 3.1.13
+-----------------------------------------------------------
+
+This release introduces a workaround for implementations that hang
+Postfix while shutting down a TLS session, until Postfix times out.
+With "tls_fast_shutdown_enable = yes" (the default), Postfix no
+longer waits for a remote TLS peer to respond to a TLS 'close'
+request. This behavior is recommended with TLSv1.0 and later. Specify
+"tls_fast_shutdown_enable = no" to get historical Postfix behavior.
+
 Workaround - UTF8 support in Postfix MySQL queries
 --------------------------------------------------
 
index e458eefd4440bafcab222f53c0366cd96916dbed..64ac34f0d91fdd6d8c008b7983c79fe0f7238008 100644 (file)
@@ -569,6 +569,12 @@ SMTP(8)                                                                SMTP(8)
               nexthop  destination  security  level is <b>dane</b>, but the MX record
               was found via an "insecure" MX lookup.
 
+       Introduced with Postfix 3.4.6, 3.3.5, 3.2.10, and 3.1.13:
+
+       <b><a href="postconf.5.html#tls_fast_shutdown_enable">tls_fast_shutdown_enable</a> (yes)</b>
+              A workaround for implementations that hang Postfix while shuting
+              down a TLS session, until Postfix times out.
+
 <b>OBSOLETE STARTTLS CONTROLS</b>
        The following configuration parameters  exist  for  compatibility  with
        Postfix  versions  before  2.3.  Support for these will be removed in a
index 73a8b3a7cfab4c942576b48dbccab02aef74c9b1..8f866103d61c0839f49ad24ed025edd79bca0b2e 100644 (file)
@@ -17758,6 +17758,21 @@ encouraged to not change this setting.  </p>
 <p> This feature is available in Postfix 2.3 and later. </p>
 
 
+</DD>
+
+<DT><b><a name="tls_fast_shutdown_enable">tls_fast_shutdown_enable</a>
+(default: yes)</b></DT><DD>
+
+<p> A workaround for implementations that hang Postfix while shuting
+down a TLS session, until Postfix times out. With this enabled,
+Postfix will not wait for the remote TLS peer to respond to a TLS
+'close' notification. This behavior is recommended for TLSv1.0 and
+later. </p>
+
+<p> This feature was introduced with Postfix 3.4.6, 3.3.5, 3.2.10,
+and 3.1.13. </p>
+
+
 </DD>
 
 <DT><b><a name="tls_high_cipherlist">tls_high_cipherlist</a>
index e458eefd4440bafcab222f53c0366cd96916dbed..64ac34f0d91fdd6d8c008b7983c79fe0f7238008 100644 (file)
@@ -569,6 +569,12 @@ SMTP(8)                                                                SMTP(8)
               nexthop  destination  security  level is <b>dane</b>, but the MX record
               was found via an "insecure" MX lookup.
 
+       Introduced with Postfix 3.4.6, 3.3.5, 3.2.10, and 3.1.13:
+
+       <b><a href="postconf.5.html#tls_fast_shutdown_enable">tls_fast_shutdown_enable</a> (yes)</b>
+              A workaround for implementations that hang Postfix while shuting
+              down a TLS session, until Postfix times out.
+
 <b>OBSOLETE STARTTLS CONTROLS</b>
        The following configuration parameters  exist  for  compatibility  with
        Postfix  versions  before  2.3.  Support for these will be removed in a
index c0679b10048a186d7e7b7b0fb215aaf3925e40c7..dfd362bc7ef22f52d6e8291939bcce038ebab782 100644 (file)
@@ -559,6 +559,12 @@ SMTPD(8)                                                              SMTPD(8)
        <b>aes-128-cbc)</b>
               Algorithm used to encrypt <a href="http://tools.ietf.org/html/rfc5077">RFC5077</a> TLS session tickets.
 
+       Introduced with Postfix 3.4.6, 3.3.5, 3.2.10, and 3.1.13:
+
+       <b><a href="postconf.5.html#tls_fast_shutdown_enable">tls_fast_shutdown_enable</a> (yes)</b>
+              A workaround for implementations that hang Postfix while shuting
+              down a TLS session, until Postfix times out.
+
 <b>OBSOLETE STARTTLS CONTROLS</b>
        The  following  configuration  parameters  exist for compatibility with
        Postfix versions before 2.3. Support for these will  be  removed  in  a
index d9125667805e072c5db5e2b965374ba1012755dc..81fbbfc8988fb3b3a89c73ad507a8bb279d18e27 100644 (file)
@@ -159,6 +159,12 @@ TLSPROXY(8)                                                        TLSPROXY(8)
        <b><a href="postconf.5.html#tlsmgr_service_name">tlsmgr_service_name</a> (tlsmgr)</b>
               The name of the <a href="tlsmgr.8.html"><b>tlsmgr</b>(8)</a> service entry in <a href="master.5.html">master.cf</a>.
 
+       Introduced with Postfix 3.4.6, 3.3.5, 3.2.10, and 3.1.13:
+
+       <b><a href="postconf.5.html#tls_fast_shutdown_enable">tls_fast_shutdown_enable</a> (yes)</b>
+              A workaround for implementations that hang Postfix while shuting
+              down a TLS session, until Postfix times out.
+
 <b>OBSOLETE STARTTLS SUPPORT CONTROLS</b>
        These  parameters  are supported for compatibility with <a href="smtpd.8.html"><b>smtpd</b>(8)</a> legacy
        parameters.
index 61ebcdb5c6e2b3e12ab3f38b25cd2c9300a4bf48..e4d6d747aa05fc886a1a00efbd6a618c7f8443f7 100644 (file)
@@ -12249,6 +12249,15 @@ the default cipherlist for the SMTP server. You are strongly
 encouraged to not change this setting.
 .PP
 This feature is available in Postfix 2.3 and later.
+.SH tls_fast_shutdown_enable (default: yes)
+A workaround for implementations that hang Postfix while shuting
+down a TLS session, until Postfix times out. With this enabled,
+Postfix will not wait for the remote TLS peer to respond to a TLS
+'close' notification. This behavior is recommended for TLSv1.0 and
+later.
+.PP
+This feature was introduced with Postfix 3.4.6, 3.3.5, 3.2.10,
+and 3.1.13.
 .SH tls_high_cipherlist (default: see "postconf \-d" output)
 The OpenSSL cipherlist for "high" grade ciphers. This defines
 the meaning of the "high" setting in smtpd_tls_ciphers,
index 6fec2e81bbd7ce081e807a4814f20e835b5bfde5..7a2862d4df20b6e5ebbc490d863a1a821f03ae94 100644 (file)
@@ -504,6 +504,11 @@ Available in Postfix version 3.1 and later:
 The TLS policy for MX hosts with "secure" TLSA records when the
 nexthop destination security level is \fBdane\fR, but the MX
 record was found via an "insecure" MX lookup.
+.PP
+Introduced with Postfix 3.4.6, 3.3.5, 3.2.10, and 3.1.13:
+.IP "\fBtls_fast_shutdown_enable (yes)\fR"
+A workaround for implementations that hang Postfix while shuting
+down a TLS session, until Postfix times out.
 .SH "OBSOLETE STARTTLS CONTROLS"
 .na
 .nf
index 0057c5478bc5cf3e46d1fb38e01244f558cb9dff..df7cc7423d05bbb046a48d962123b3cd35ac2aff 100644 (file)
@@ -502,6 +502,11 @@ The name of the \fBtlsmgr\fR(8) service entry in master.cf.
 Available in Postfix version 3.0 and later:
 .IP "\fBtls_session_ticket_cipher (Postfix >= 3.0: aes\-256\-cbc, Postfix < 3.0: aes\-128\-cbc)\fR"
 Algorithm used to encrypt RFC5077 TLS session tickets.
+.PP
+Introduced with Postfix 3.4.6, 3.3.5, 3.2.10, and 3.1.13:
+.IP "\fBtls_fast_shutdown_enable (yes)\fR"
+A workaround for implementations that hang Postfix while shuting
+down a TLS session, until Postfix times out.
 .SH "OBSOLETE STARTTLS CONTROLS"
 .na
 .nf
index c8540a583d9445ed55e3bac9902e7ea474453d61..509931c2cde0199ec3701a91ee365ec3309387b0 100644 (file)
@@ -152,6 +152,11 @@ parameters smtpd_use_tls and smtpd_enforce_tls.
 Available in Postfix version 2.11 and later:
 .IP "\fBtlsmgr_service_name (tlsmgr)\fR"
 The name of the \fBtlsmgr\fR(8) service entry in master.cf.
+.PP
+Introduced with Postfix 3.4.6, 3.3.5, 3.2.10, and 3.1.13:
+.IP "\fBtls_fast_shutdown_enable (yes)\fR"
+A workaround for implementations that hang Postfix while shuting
+down a TLS session, until Postfix times out.
 .SH "OBSOLETE STARTTLS SUPPORT CONTROLS"
 .na
 .nf
index 0e4eb9c22c310a51a396a77ccd3c995a879437b5..10addc443f73c2910db9ff5c6c73bd86c8a84b75 100755 (executable)
@@ -748,6 +748,7 @@ while (<>) {
     s;\btls_wildcard_matches_multiple_labels\b;<a href="postconf.5.html#tls_wildcard_matches_multiple_labels">$&</a>;g;
     s;\btls_session_ticket_cipher\b;<a href="postconf.5.html#tls_session_ticket_cipher">$&</a>;g;
     s;\btls_ssl_options\b;<a href="postconf.5.html#tls_ssl_options">$&</a>;g;
+    s;\btls_fast_shutdown_enable\b;<a href="postconf.5.html#tls_fast_shutdown_enable">$&</a>;g;
 
     s;\bfrozen_delivered_to\b;<a href="postconf.5.html#frozen_delivered_to">$&</a>;g;
     s;\breset_owner_alias\b;<a href="postconf.5.html#reset_owner_alias">$&</a>;g;
index 3537396d18b76afb10328ffb4c5211e399b1b635..bed759746d31ff1569a04870a2c0a487cd1467c0 100644 (file)
@@ -16115,6 +16115,17 @@ support is via the tls_ssl_options parameter.  </p>
 
 <p> This feature is available in Postfix 3.0 and later. </p>
 
+%PARAM tls_fast_shutdown_enable yes
+
+<p> A workaround for implementations that hang Postfix while shuting
+down a TLS session, until Postfix times out. With this enabled,
+Postfix will not wait for the remote TLS peer to respond to a TLS
+'close' notification. This behavior is recommended for TLSv1.0 and
+later. </p>
+
+<p> This feature was introduced with Postfix 3.4.6, 3.3.5, 3.2.10,
+and 3.1.13. </p>
+
 %PARAM default_delivery_status_filter
 
 <p> Optional filter to replace the delivery status code or explanatory
index c11c763010f66c1066ec3b93261ad0273871f092..65328690545e4b6bd8ee08f410fff990e3ba6c72 100644 (file)
@@ -3260,6 +3260,13 @@ extern char *var_tls_dane_digests;
 #define DEF_TLS_DANE_TAA_DGST  1
 extern bool var_tls_dane_taa_dgst;
 
+ /*
+  * The default is backwards-incompatible.
+  */
+#define VAR_TLS_FAST_SHUTDOWN  "tls_fast_shutdown"
+#define DEF_TLS_FAST_SHUTDOWN  1
+extern bool var_tls_fast_shutdown;
+
  /*
   * Sendmail-style mail filter support.
   */
index df010242793edc586491c60bed4fa79e1280dc2b..c5113e18b28d4aaf85f79f57313d6c9d07834af3 100644 (file)
@@ -20,8 +20,8 @@
   * Patches change both the patchlevel and the release date. Snapshots have no
   * patchlevel; they change the release date only.
   */
-#define MAIL_RELEASE_DATE      "20190330"
-#define MAIL_VERSION_NUMBER    "3.1.12"
+#define MAIL_RELEASE_DATE      "20190629"
+#define MAIL_VERSION_NUMBER    "3.1.13"
 
 #ifdef SNAPSHOT
 #define MAIL_VERSION_DATE      "-" MAIL_RELEASE_DATE
index 33ee10272e1a53ce02d7e8f9a0b83f3a39240581..b49f3eb542b29229e6df91ff3e83fea0b64987e1 100644 (file)
 /*     The TLS policy for MX hosts with "secure" TLSA records when the
 /*     nexthop destination security level is \fBdane\fR, but the MX
 /*     record was found via an "insecure" MX lookup.
+/* .PP
+/*     Introduced with Postfix 3.4.6, 3.3.5, 3.2.10, and 3.1.13:
+/* .IP "\fBtls_fast_shutdown_enable (yes)\fR"
+/*     A workaround for implementations that hang Postfix while shuting
+/*     down a TLS session, until Postfix times out.
 /* OBSOLETE STARTTLS CONTROLS
 /* .ad
 /* .fi
index b54a7f0943831b9df5e78a049aa92f22461ffd1d..d3c8240994fdb551746a94c093fde9f695069df3 100644 (file)
 /*     Available in Postfix version 3.0 and later:
 /* .IP "\fBtls_session_ticket_cipher (Postfix >= 3.0: aes-256-cbc, Postfix < 3.0: aes-128-cbc)\fR"
 /*     Algorithm used to encrypt RFC5077 TLS session tickets.
+/* .PP
+/*     Introduced with Postfix 3.4.6, 3.3.5, 3.2.10, and 3.1.13:
+/* .IP "\fBtls_fast_shutdown_enable (yes)\fR"
+/*     A workaround for implementations that hang Postfix while shuting
+/*     down a TLS session, until Postfix times out.
 /* OBSOLETE STARTTLS CONTROLS
 /* .ad
 /* .fi
@@ -3448,6 +3453,12 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
            if (vstream_ferror(state->cleanup))
                state->err = CLEANUP_STAT_WRITE;
        }
+
+#define IS_SMTP_REJECT(s) \
+       (((s)[0] == '4' || (s)[0] == '5') \
+        && ISDIGIT((s)[1]) && ISDIGIT((s)[2]) \
+        && ((s)[3] == '\0' || (s)[3] == ' ' || (s)[3] == '-'))
+
        if (state->err == CLEANUP_STAT_OK)
            if (rec_fputs(state->cleanup, REC_TYPE_END, "") < 0
                || vstream_fflush(state->cleanup))
@@ -3455,7 +3466,10 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
        if (state->err == 0) {
            why = vstring_alloc(10);
            state->err = mail_stream_finish(state->dest, why);
-           printable(STR(why), ' ');
+           if (IS_SMTP_REJECT(STR(why)))
+               printable_except(STR(why), ' ', "\r\n");
+           else
+               printable(STR(why), ' ');
        } else
            mail_stream_cleanup(state->dest);
        state->dest = 0;
@@ -3490,11 +3504,6 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
      * 
      * See also: qmqpd.c
      */
-#define IS_SMTP_REJECT(s) \
-       (((s)[0] == '4' || (s)[0] == '5') \
-        && ISDIGIT((s)[1]) && ISDIGIT((s)[2]) \
-        && ((s)[3] == '\0' || (s)[3] == ' ' || (s)[3] == '-'))
-
     if (state->err == CLEANUP_STAT_OK) {
        state->error_count = 0;
        state->error_mask = 0;
@@ -4915,15 +4924,6 @@ static void smtpd_proto(SMTPD_STATE *state)
 
     case 0:
 
-       /*
-        * Reset the per-command counters.
-        */
-       for (cmdp = smtpd_cmd_table; /* see below */ ; cmdp++) {
-           cmdp->success_count = cmdp->total_count = 0;
-           if (cmdp->name == 0)
-               break;
-       }
-
        /*
         * In TLS wrapper mode, turn on TLS using code that is shared with
         * the STARTTLS command. This code does not return when the handshake
@@ -5315,6 +5315,15 @@ static char *smtpd_format_cmd_stats(VSTRING *buf)
            break;
     }
 
+    /*
+     * Reset the per-command counters.
+     */
+    for (cmdp = smtpd_cmd_table; /* see below */ ; cmdp++) {
+       cmdp->success_count = cmdp->total_count = 0;
+       if (cmdp->name == 0)
+           break;
+    }
+
     /*
      * Log total numbers, so that logfile analyzers will see something even
      * if the above loop produced no output. When no commands were received
index 1a4896053413eaa4a54dab789158686c7866a699..987a0d656839a6b89d20e02b866b45856331ff92 100644 (file)
@@ -429,6 +429,7 @@ tls_server.o: tls_server.c
 tls_session.o: ../../include/argv.h
 tls_session.o: ../../include/check_arg.h
 tls_session.o: ../../include/dns.h
+tls_session.o: ../../include/mail_params.h
 tls_session.o: ../../include/msg.h
 tls_session.o: ../../include/myaddrinfo.h
 tls_session.o: ../../include/mymalloc.h
index 5774175af09898da6e4333c0cb14f6183d754f5f..19aad0499d3c64e0d4db68fad1fad4362b05c683 100644 (file)
@@ -44,6 +44,7 @@
 /*     char    *var_tls_mgr_service;
 /*     char    *var_tls_tkt_cipher;
 /*     char    *var_openssl_path;
+/*     bool    var_tls_fast_shutdown;
 /*
 /*     TLS_APPL_STATE *tls_alloc_app_context(ssl_ctx, log_mask)
 /*     SSL_CTX *ssl_ctx;
@@ -283,6 +284,7 @@ bool    var_tls_multi_wildcard;
 char   *var_tls_mgr_service;
 char   *var_tls_tkt_cipher;
 char   *var_openssl_path;
+bool    var_tls_fast_shutdown;
 
 #ifdef VAR_TLS_PREEMPT_CLIST
 bool    var_tls_preempt_clist;
@@ -724,6 +726,7 @@ void    tls_param_init(void)
        VAR_TLS_DANE_TAA_DGST, DEF_TLS_DANE_TAA_DGST, &var_tls_dane_taa_dgst,
        VAR_TLS_PREEMPT_CLIST, DEF_TLS_PREEMPT_CLIST, &var_tls_preempt_clist,
        VAR_TLS_MULTI_WILDCARD, DEF_TLS_MULTI_WILDCARD, &var_tls_multi_wildcard,
+       VAR_TLS_FAST_SHUTDOWN, DEF_TLS_FAST_SHUTDOWN, &var_tls_fast_shutdown,
        0,
     };
     static int init_done;
index 8fc11cf26029259a3834eda854bcaa1e4ff031a9..8a95e903bbfb2341d6170f9d8d7659d12fed0998 100644 (file)
 #include <msg.h>
 #include <mymalloc.h>
 
+/* Global library. */
+
+#include <mail_params.h>
+
 /* TLS library. */
 
 #define TLS_INTERNAL
@@ -90,6 +94,18 @@ void    tls_session_stop(TLS_APPL_STATE *unused_ctx, VSTREAM *stream, int timeou
        msg_panic("%s: stream has no active TLS context", myname);
 
     /*
+     * According to RFC 2246 (TLS 1.0), there is no requirement to wait for
+     * the peer's close-notify. If the application protocol provides
+     * sufficient session termination signaling, then there's no need to
+     * duplicate that at the TLS close-notify layer.
+     * 
+     * https://tools.ietf.org/html/rfc2246#section-7.2.1
+     * https://tools.ietf.org/html/rfc4346#section-7.2.1
+     * https://tools.ietf.org/html/rfc5246#section-7.2.1
+     * 
+     * Specify 'tls_fast_shutdown = no' to enable the historical behavior
+     * described below.
+     * 
      * Perform SSL_shutdown() twice, as the first attempt will send out the
      * shutdown alert but it will not wait for the peer's shutdown alert.
      * Therefore, when we are the first party to send the alert, we must call
@@ -99,7 +115,7 @@ void    tls_session_stop(TLS_APPL_STATE *unused_ctx, VSTREAM *stream, int timeou
      */
     if (!failure) {
        retval = tls_bio_shutdown(vstream_fileno(stream), timeout, TLScontext);
-       if (retval == 0)
+       if (!var_tls_fast_shutdown && retval == 0)
            tls_bio_shutdown(vstream_fileno(stream), timeout, TLScontext);
     }
     tls_free_context(TLScontext);
index 00521c74a2d7017d61fd4b12d950cca85c9f39ef..52e4a54465a799a96c4d69767262e9bf8ff9793f 100644 (file)
 /*     Available in Postfix version 2.11 and later:
 /* .IP "\fBtlsmgr_service_name (tlsmgr)\fR"
 /*     The name of the \fBtlsmgr\fR(8) service entry in master.cf.
+/* .PP
+/*     Introduced with Postfix 3.4.6, 3.3.5, 3.2.10, and 3.1.13:
+/* .IP "\fBtls_fast_shutdown_enable (yes)\fR"
+/*     A workaround for implementations that hang Postfix while shuting
+/*     down a TLS session, until Postfix times out.
 /* OBSOLETE STARTTLS SUPPORT CONTROLS
 /* .ad
 /* .fi
index a37ff6306410478105b3416ed31b6407cd69978d..6c148fd0041a626056f0af2e26fb1a6019724c68 100644 (file)
 /*     char    *printable(buffer, replacement)
 /*     char    *buffer;
 /*     int     replacement;
+/*
+/*     char    *printable_except(buffer, replacement, except)
+/*     char    *buffer;
+/*     int     replacement;
+/*     const char *except;
 /* DESCRIPTION
 /*     printable() replaces non-printable characters
 /*     in its input with the given replacement.
@@ -24,6 +29,8 @@
 /* .IP replacement
 /*     Replacement value for characters in \fIbuffer\fR that do not
 /*     pass the ASCII isprint(3) test or that are not valid UTF8.
+/* .IP except
+/*     Null-terminated sequence of non-replaced ASCII characters.
 /* LICENSE
 /* .ad
 /* .fi
 /*     IBM T.J. Watson Research
 /*     P.O. Box 704
 /*     Yorktown Heights, NY 10598, USA
+/*
+/*     Wietse Venema
+/*     Google, Inc.
+/*     111 8th Avenue
+/*     New York, NY 10011, USA
 /*--*/
 
 /* System library. */
 
 #include "sys_defs.h"
 #include <ctype.h>
+#include <string.h>
 
 /* Utility library. */
 
 
 int util_utf8_enable = 0;
 
+/* printable -  binary compatibility */
+
+#undef printable
+
+char   *printable(char *, int);
+
 char   *printable(char *string, int replacement)
+{
+    return (printable_except(string, replacement, (char *) 0));
+}
+
+/* printable_except -  pass through printable or other preserved characters */
+
+char   *printable_except(char *string, int replacement, const char *except)
 {
     unsigned char *cp;
     int     ch;
@@ -57,7 +83,7 @@ char   *printable(char *string, int replacement)
      */
     cp = (unsigned char *) string;
     while ((ch = *cp) != 0) {
-       if (ISASCII(ch) && ISPRINT(ch)) {
+       if (ISASCII(ch) && (ISPRINT(ch) || (except && strchr(except, ch)))) {
            /* ok */
        } else if (util_utf8_enable && ch >= 194 && ch <= 254
                   && cp[1] >= 128 && cp[1] < 192) {
index de2ecc739384ec870b5ac6dca226668a1624f58a..a6489e49cab4b6444be0aabeaaa88f25a4023af8 100644 (file)
@@ -20,7 +20,7 @@
   * External interface.
   */
 extern int util_utf8_enable;
-extern char *printable(char *, int);
+extern char *printable_except(char *, int, const char *);
 extern char *neuter(char *, const char *, int);
 extern char *lowercase(char *);
 extern char *casefoldx(int, VSTRING *, const char *, ssize_t);
@@ -32,6 +32,9 @@ extern char *mystrtok(char **, const char *);
 extern char *mystrtokq(char **, const char *, const char *);
 extern char *translit(char *, const char *, const char *);
 
+#define printable(string, replacement) \
+       printable_except((string), (replacement), (char *) 0)
+
 #ifndef HAVE_BASENAME
 #define basename postfix_basename
 extern char *basename(const char *);
@@ -85,6 +88,11 @@ extern int strncasecmp_utf8x(int, const char *, const char *, ssize_t);
 /*     IBM T.J. Watson Research
 /*     P.O. Box 704
 /*     Yorktown Heights, NY 10598, USA
+/*
+/*     Wietse Venema
+/*     Google, Inc.
+/*     111 8th Avenue
+/*     New York, NY 10011, USA
 /*--*/
 
 #endif