]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-3.2.10 v3.2.10
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:43:22 +0000 (03:43 -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 4be1d313de6851e73962fdaf2fc0ab2e0388fd22..89c5163cbd1c74baeddf016a57ea77f70735e763 100644 (file)
@@ -23162,3 +23162,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 ab8155f1d49e663e73573a24de09c16ffbbd8064..07180c516dc83cb6c3468c34e88d31bf1710f024 100644 (file)
@@ -16,6 +16,16 @@ specifies the release date of a stable release or snapshot release.
 If you upgrade from Postfix 3.0 or earlier, read RELEASE_NOTES-3.1
 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.
+
 License change with Postfix 3.2.5
 ---------------------------------
 
index ee0ec5f62bb5729c2080f319effaead161e85aad..1be182f1fd40cc4d83cb4ffba7e27057348a17f6 100644 (file)
@@ -566,6 +566,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 ed7093f6c1e8b0cd8c3e03a1d061d0adefadf3db..922e88603fb2e9b0b7a360c5fe4bc2c619643790 100644 (file)
@@ -17797,6 +17797,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 ee0ec5f62bb5729c2080f319effaead161e85aad..1be182f1fd40cc4d83cb4ffba7e27057348a17f6 100644 (file)
@@ -566,6 +566,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 2e52d32918283edfe6eaa9ec9648604192b6e5d6..350629140938ea87a67e45d37258ed2200596ea6 100644 (file)
@@ -571,6 +571,12 @@ SMTPD(8)                                                              SMTPD(8)
               The prioritized list of elliptic curves supported by the Postfix
               SMTP client and server.
 
+       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 54c6a3e9ed7a830d63e7c138acd479c3d20b4d56..b68e38bddb2679f0f0948d71ed84ea8d54986dbf 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 84e7c534c9318055a6738082613835255c93560b..57ed46f95dd66c98ac2ab2e36fa2f0ddb3a53718 100644 (file)
@@ -12274,6 +12274,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 c755fccd7395a89540523fb7fa6c3355406212ff..b1f88888c3d8533de21d5157290a894208798e66 100644 (file)
@@ -502,6 +502,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 402460e09101bbec18ab143b768ba277a1054644..10a99de207f4605fe167bfbe1e67ccc4aeb2fd72 100644 (file)
@@ -512,6 +512,11 @@ Available in Postfix version 3.2 and later:
 .IP "\fBtls_eecdh_auto_curves (see 'postconf -d' output)\fR"
 The prioritized list of elliptic curves supported by the Postfix
 SMTP client and server.
+.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 87ecfac3ee3297a5db118801057d9f15681eb302..bf21f06730b70aface6a88ccd9df634f478c6236 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 76d260ad7dd708d84979e5db6b2b0f1599ad2b74..ab17d924148d34576936194537b7c2280c55a0bc 100755 (executable)
@@ -750,6 +750,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 6f4dbda83473ec004989a4d6012220892d08fb88..2e72dd7a9b08d8d35d5ff30aa79cd7930f59a38b 100644 (file)
@@ -16086,6 +16086,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 fd5fd551c513d866cb41c1a48b24a57eb7bf7590..a0a1a4e8b2ebd52b86748dda247d4de08e33cc94 100644 (file)
@@ -3307,6 +3307,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 cae85277f891bbea5b7595ec3d58a03f13c2af8f..1e983826ffa5620f1308d967a857ed16cad736bc 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.2.9"
+#define MAIL_RELEASE_DATE      "20190629"
+#define MAIL_VERSION_NUMBER    "3.2.10"
 
 #ifdef SNAPSHOT
 #define MAIL_VERSION_DATE      "-" MAIL_RELEASE_DATE
index fd90bd13dcf3e5371df1a4dbc7f7e2922b10a590..3d0aabb3cc1a6bbfb5d79883b629839a46912e82 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 cd460093652ae07480d6266adfcf2ad1dd77b0ca..6e42ca3907b925a82bf1633ddfd245b2aa27cba9 100644 (file)
 /* .IP "\fBtls_eecdh_auto_curves (see 'postconf -d' output)\fR"
 /*     The prioritized list of elliptic curves supported by the Postfix
 /*     SMTP client and server.
+/* .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
@@ -3485,6 +3490,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))
@@ -3492,7 +3503,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;
@@ -3527,11 +3541,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;
@@ -4992,15 +5001,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
@@ -5391,6 +5391,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 55dfd1ecce917733b3d2534f7f8d7d9be215c006..ab6fd55a242e01168b919fcfe55e290d1e647b6a 100644 (file)
@@ -431,6 +431,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 9460d9fd605f1f8876977c39d4141434be25a3a5..ee6a26e7516b844085741e07891175e119e10e52 100644 (file)
@@ -45,6 +45,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;
@@ -285,6 +286,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;
@@ -739,6 +741,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 0796dd20063208e5bd4c85b20bc24231a4296715..8709d248658dc46a7cd71dfc4fd0b7774a126d74 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 32b1c775401300111fb670327033b3383f045cd2..c54a5268b82ee0480902e205586fb054b4acf735 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 *);
@@ -86,6 +89,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