]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-3.1-20150216
authorWietse Venema <wietse@porcupine.org>
Mon, 16 Feb 2015 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <postfix-users@dukhovni.org>
Tue, 17 Feb 2015 15:56:59 +0000 (10:56 -0500)
24 files changed:
postfix/HISTORY
postfix/html/socketmap_table.5.html
postfix/man/man5/socketmap_table.5
postfix/proto/socketmap_table
postfix/src/global/Makefile.in
postfix/src/global/mail_command_client.c
postfix/src/global/mail_connect.c
postfix/src/global/mail_version.h
postfix/src/global/post_mail.c
postfix/src/local/forward.c
postfix/src/postalias/postalias.c
postfix/src/postdrop/postdrop.c
postfix/src/postlog/postlog.c
postfix/src/postmap/postmap.c
postfix/src/postqueue/postqueue.c
postfix/src/postsuper/postsuper.c
postfix/src/sendmail/sendmail.c
postfix/src/smtpd/smtpd.c
postfix/src/util/allascii.c
postfix/src/util/casefold.c
postfix/src/util/strcasecmp_utf8.c
postfix/src/util/strcasecmp_utf8_test.in
postfix/src/util/strcasecmp_utf8_test.ref
postfix/src/util/stringops.h

index 7585c0aa130ec16897fb9bdf861fbbb6f93067a6..7ea927eb69626add9283f90c7e99e7559b133830 100644 (file)
@@ -21453,7 +21453,7 @@ Apologies for any names omitted.
        tls/tls_client.c, util/dict_alloc.c, util/dict_open.c,
        util/match_list.c.
 
-20150214
+20150124
 
        Workaround: nroff has been improved so that "-" comes out as
        some non-ASCII character, unlike HTML where it comes out
@@ -21461,12 +21461,10 @@ Apologies for any names omitted.
        hops to generate HTML and nroff input from the same source
        text.  Files; mantools/srctoman, mantools/postconf2man.
 
-20150524
-
        Cleanup: UTF-8 support in masquerade_domains.  File:
        cleanup/cleanup_masquerade.c.
 
-20150525
+20150125
 
        Cleanup: simplified the casefold() API: no input-dependent
        failure modes. Files: cleanup/cleanup_masquerade.c,
@@ -21502,7 +21500,7 @@ Apologies for any names omitted.
 
 20150127
 
-       Cleanup: simplified the 20150525 and 20150126 APIs, replacing
+       Cleanup: simplified the 20150125 and 20150126 APIs, replacing
        the most-common use cases with convenience macros that have
        fewer arguments. Files: anything that implements or invokes
        casefold*() or str*casecmp().
@@ -21595,3 +21593,41 @@ Apologies for any names omitted.
        Cleanup: after many years, the access(5) map BCC action is
        part of the stable release. Files: smtpd/smtpd_check.c,
        proto/acces.
+
+20150210
+
+       Cleanup: socketmap documentation. File: proto/socketmap_table.
+
+20150211
+
+       Cleanup: strncasecmp_utf8() streamlining. Files: util/stringops.h,
+       util/allascii.c, util/strcasecmp_utf8.c.
+
+20150212
+
+       Cleanup: in code after reading main.cf, removed bogus guard
+       before re-evaluating the mail_task() syslog prefix.  File:
+       postlog/postlog.c.
+
+20150214
+
+       Bugfix: missing #ifdef USE_TLS inside #ifdef USE_SASL_AUTH
+       broke the build. Viktor Dukhovni. File: smtpd/smtpd.c.
+
+       Cleanup: missing errno logging in bounce daemon clients.
+       This made troubleshooting significantly more difficult.
+       File: global/mail_command_client.c.
+
+20150216
+
+       Cleanup: documented that mail_connect() produces no errno
+       logging.  The functions that call it should log the error
+       (and the majority does). File: global/mail_connect.c.
+
+       Cleanup: added errno logging after mail_connect() failure.
+       Files: global/post_mail.c, local/forward.c.
+
+       Cleanup: in code after reading main.cf, removed bogus guard
+       before re-evaluating the mail_task() syslog prefix. Files:
+       postalias/postalias.c, postdrop/postdrop.c, postmap/postmap.c,
+       postqueue/postqueue.c, postsuper/postsuper.c, sendmail/sendmail.c.
index 5fa003c5f7fd9622489898c033690353dd1a261e..24908e35c8b4d598e229851256978d18b2607f44 100644 (file)
@@ -31,20 +31,21 @@ SOCKETMAP_TABLE(5)                                          SOCKETMAP_TABLE(5)
        string object.
 
 <b>REQUEST FORMAT</b>
-       The socketmap protocol supports only the lookup request.
-
-       Postfix  will  not  generate  partial  search keys such as domain names
-       without one or more subdomains, network addresses without one  or  more
-       least-significant  octets,  or  email  addresses without the localpart,
-       address extension or domain portion. This behavior is also  found  with
-       <a href="cidr_table.5.html">cidr</a>:, <a href="pcre_table.5.html">pcre</a>:, and <a href="regexp_table.5.html">regexp</a>: tables.
+       The  socketmap  protocol supports only the lookup request.  The request
+       has the following form:
 
        <i>name</i> &lt;<b>space</b>&gt; <i>key</i>
               Search the named socketmap for the specified key.
 
+       Postfix will not generate partial search  keys  such  as  domain  names
+       without  one  or more subdomains, network addresses without one or more
+       least-significant octets, or email  addresses  without  the  localpart,
+       address  extension  or domain portion. This behavior is also found with
+       <a href="cidr_table.5.html">cidr</a>:, <a href="pcre_table.5.html">pcre</a>:, and <a href="regexp_table.5.html">regexp</a>: tables.
+
 <b>REPLY FORMAT</b>
-       The  Postfix socketmap client requires that replies are not longer than
-       100000 characters (not including the netstring encapsulation).  Replies
+       The Postfix socketmap client requires that replies are not longer  than
+       100000  characters (not including the netstring encapsulation). Replies
        must have the following form:
 
        <b>OK</b> &lt;<b>space</b>&gt; <i>data</i>
@@ -58,7 +59,7 @@ SOCKETMAP_TABLE(5)                                          SOCKETMAP_TABLE(5)
        <b>TIMEOUT</b> &lt;<b>space</b>&gt; <i>reason</i>
 
        <b>PERM</b> &lt;<b>space</b>&gt; <i>reason</i>
-              The  request  failed.  The  reason, if non-empty, is descriptive
+              The request failed. The reason,  if  non-empty,  is  descriptive
               text.
 
 <b>SECURITY</b>
index 07a59da07a8c03452ccf94a7aa92404dd9e2219c..9b1a2769b81e294ba03444feb6f1e45483a0a687 100644 (file)
@@ -40,15 +40,17 @@ reply are sent as one netstring object.
 .ad
 .fi
 The socketmap protocol supports only the lookup request.
+The request has the following form:
 
+.IP "\fB\fIname\fB <space> \fIkey\fR"
+Search the named socketmap for the specified key.
+.PP
 Postfix will not generate partial search keys such as domain
 names without one or more subdomains, network addresses
 without one or more least\-significant octets, or email
 addresses without the localpart, address extension or domain
 portion. This behavior is also found with cidr:, pcre:, and
 regexp: tables.
-.IP "\fB\fIname\fB <space> \fIkey\fR"
-Search the named socketmap for the specified key.
 .SH "REPLY FORMAT"
 .na
 .nf
index 96c7dfca588b7b9e0c4a94caf950b2d23a2f130e..b74b44c7e74cc841056b36956b14270cf06ee42a 100644 (file)
 # .ad
 # .fi
 #      The socketmap protocol supports only the lookup request.
+#      The request has the following form:
 #
+# .IP "\fB\fIname\fB <space> \fIkey\fR"
+#      Search the named socketmap for the specified key. 
+# .PP
 #      Postfix will not generate partial search keys such as domain
 #      names without one or more subdomains, network addresses
 #      without one or more least-significant octets, or email
 #      addresses without the localpart, address extension or domain
 #      portion. This behavior is also found with cidr:, pcre:, and
 #      regexp: tables.
-# .IP "\fB\fIname\fB <space> \fIkey\fR"
-#      Search the named socketmap for the specified key. 
 # REPLY FORMAT
 # .ad
 # .fi
index dc7f82cff47dd5937ed0b573843cd5f9a3dd1866..cedbed2f61943da40661237559c195920103c9fb 100644 (file)
@@ -1451,6 +1451,7 @@ mail_command_client.o: ../../include/attr.h
 mail_command_client.o: ../../include/check_arg.h
 mail_command_client.o: ../../include/htable.h
 mail_command_client.o: ../../include/iostuff.h
+mail_command_client.o: ../../include/msg.h
 mail_command_client.o: ../../include/mymalloc.h
 mail_command_client.o: ../../include/nvtable.h
 mail_command_client.o: ../../include/sys_defs.h
index b5cb21c78446cc2b967dfabc807730a928068314..f70771b209f70f4b9c8573040943ce1f1b75bece 100644 (file)
@@ -52,6 +52,7 @@
 /* Utility library. */
 
 #include <vstream.h>
+#include <msg.h>
 
 /* Global library. */
 
@@ -67,16 +68,26 @@ int     mail_command_client(const char *class, const char *name,...)
 
     /*
      * Talk a little protocol with the specified service.
+     * 
+     * This function is used for non-critical services where it is OK to back
+     * off after the first error. Log what communication stage failed, to
+     * facilitate trouble analysis.
      */
-    if ((stream = mail_connect(class, name, BLOCKING)) == 0)
+    if ((stream = mail_connect(class, name, BLOCKING)) == 0) {
+       msg_warn("connect to %s/%s: %m", class, name);
        return (-1);
+    }
     va_start(ap, name);
     status = attr_vprint(stream, ATTR_FLAG_NONE, ap);
     va_end(ap);
-    if (status != 0
-       || attr_scan(stream, ATTR_FLAG_STRICT,
-                    RECV_ATTR_INT(MAIL_ATTR_STATUS, &status), 0) != 1)
+    if (status != 0) {
+       msg_warn("write %s: %m", VSTREAM_PATH(stream));
        status = -1;
+    } else if (attr_scan(stream, ATTR_FLAG_STRICT,
+                        RECV_ATTR_INT(MAIL_ATTR_STATUS, &status), 0) != 1) {
+       msg_warn("write/read %s: %m", VSTREAM_PATH(stream));
+       status = -1;
+    }
     (void) vstream_fclose(stream);
     return (status);
 }
index e655687b3166c8d0fc81a38e78ee61a640e263f1..4fdfe7807b873020fc05932a2fc05410f34ce337 100644 (file)
@@ -22,6 +22,7 @@
 /*
 /*     mail_connect() attempts to connect to the UNIX-domain socket of
 /*     the named subsystem. The result is a null pointer in case of failure.
+/*     By default this function provides no errno logging.
 /*
 /*     mail_connect_wait() is like mail_connect(), but keeps trying until
 /*     the connection succeeds. However, mail_connect_wait() terminates
index 5a649187d3ac0802613351a8ea002a9dd40ca646..f012fcd9da5dc8962c7f1bbd65263a77fced90f9 100644 (file)
@@ -20,7 +20,7 @@
   * Patches change both the patchlevel and the release date. Snapshots have no
   * patchlevel; they change the release date only.
   */
-#define MAIL_RELEASE_DATE      "20150208"
+#define MAIL_RELEASE_DATE      "20150216"
 #define MAIL_VERSION_NUMBER    "3.1"
 
 #ifdef SNAPSHOT
index a267e34c5f2a7d30eea34687a5fac5ad310590a7..002b8d99d7cc4664cb117fdfae026a95329c2206 100644 (file)
@@ -268,6 +268,9 @@ VSTREAM *post_mail_fopen_nowait(const char *sender, const char *recipient,
                               BLOCKING)) != 0)
        post_mail_init(stream, sender, recipient, source_class, trace_flags,
                       utf8_flags, queue_id);
+    else
+       msg_warn("connect to %s/%s: %m",
+                MAIL_CLASS_PUBLIC, var_cleanup_service);
     return (stream);
 }
 
index ac964f32ed930729bf21bef64cd8e52310f117fe..109279ea3521ae87d993dc8649ba64aae1c8817c 100644 (file)
@@ -134,8 +134,11 @@ static FORWARD_INFO *forward_open(DELIVER_REQUEST *request, const char *sender)
      * ourselves is that we don't really know who the recipients are.
      */
     cleanup = mail_connect(MAIL_CLASS_PUBLIC, var_cleanup_service, BLOCKING);
-    if (cleanup == 0)
+    if (cleanup == 0) {
+       msg_warn("connect to %s/%s: %m",
+                MAIL_CLASS_PUBLIC, var_cleanup_service);
        FORWARD_OPEN_RETURN(0);
+    }
     close_on_exec(vstream_fileno(cleanup), CLOSE_ON_EXEC);
     if (attr_scan(cleanup, ATTR_FLAG_STRICT,
                  RECV_ATTR_STR(MAIL_ATTR_QUEUEID, buffer),
index 707240b4af6101d535b8d2a8e5878d38888e0bcf..ca3bfd045e15e7dc36a94fe6202da7be93ac9e4a 100644 (file)
@@ -801,8 +801,8 @@ int     main(int argc, char **argv)
        }
     }
     mail_conf_read();
-    if (strcmp(var_syslog_name, DEF_SYSLOG_NAME) != 0)
-       msg_syslog_init(mail_task(argv[0]), LOG_PID, LOG_FACILITY);
+    /* Re-evaluate mail_task() after reading main.cf. */
+    msg_syslog_init(mail_task(argv[0]), LOG_PID, LOG_FACILITY);
     mail_dict_init();
 
     /*
index 1a4096c7c647b119a9c108c54fdefb9b7263beb5..8d85f9a7c0efa3814a4be8543185e8ab486ce98f 100644 (file)
@@ -306,8 +306,8 @@ int     main(int argc, char **argv)
      * perform some sanity checks on the input.
      */
     mail_conf_read();
-    if (strcmp(var_syslog_name, DEF_SYSLOG_NAME) != 0)
-       msg_syslog_init(mail_task("postdrop"), LOG_PID, LOG_FACILITY);
+    /* Re-evaluate mail_task() after reading main.cf. */
+    msg_syslog_init(mail_task("postdrop"), LOG_PID, LOG_FACILITY);
     get_mail_conf_str_table(str_table);
 
     /*
index 6384396bdc8e19c487c9b25be04ca47817d7cb93..518f45a1a3966723e04f4c252da5292f7a97cea3 100644 (file)
@@ -170,7 +170,6 @@ MAIL_VERSION_STAMP_DECLARE;
 int     main(int argc, char **argv)
 {
     struct stat st;
-    char   *slash;
     int     fd;
     int     ch;
     const char *tag;
@@ -200,10 +199,7 @@ int     main(int argc, char **argv)
     /*
      * Set up diagnostics.
      */
-    if ((slash = strrchr(argv[0], '/')) != 0 && slash[1])
-       tag = mail_task(slash + 1);
-    else
-       tag = mail_task(argv[0]);
+    tag = mail_task(argv[0]);
     if (isatty(STDERR_FILENO))
        msg_vstream_init(tag, VSTREAM_ERR);
     msg_syslog_init(tag, LOG_PID, LOG_FACILITY);
@@ -216,10 +212,11 @@ int     main(int argc, char **argv)
     /*
      * Parse switches.
      */
+    tag = 0;
     while ((ch = GETOPT(argc, argv, "c:ip:t:v")) > 0) {
        switch (ch) {
        default:
-           msg_fatal("usage: %s [-c config_dir] [-i] [-p priority] [-t tag] [-v] [text]", tag);
+           msg_fatal("usage: %s [-c config_dir] [-i] [-p priority] [-t tag] [-v] [text]", argv[0]);
            break;
        case 'c':
            if (setenv(CONF_ENV_PATH, optarg, 1) < 0)
@@ -241,26 +238,20 @@ int     main(int argc, char **argv)
     }
 
     /*
-     * Process the main.cf file. This overrides any logging facility that was
-     * specified with msg_syslog_init();
+     * Process the main.cf file. This may change the syslog_name setting and
+     * may require that mail_task() be re-evaluated.
      */
     mail_conf_read();
-    if (tag == 0 && strcmp(var_syslog_name, DEF_SYSLOG_NAME) != 0) {
-       if ((slash = strrchr(argv[0], '/')) != 0 && slash[1])
-           tag = mail_task(slash + 1);
-       else
-           tag = mail_task(argv[0]);
-    }
+    if (tag == 0)
+       tag = mail_task(argv[0]);
 
     /*
      * Re-initialize the logging, this time with the tag specified in main.cf
      * or on the command line.
      */
-    if (tag != 0) {
-       if (isatty(STDERR_FILENO))
-           msg_vstream_init(tag, VSTREAM_ERR);
-       msg_syslog_init(tag, LOG_PID, LOG_FACILITY);
-    }
+    if (isatty(STDERR_FILENO))
+       msg_vstream_init(tag, VSTREAM_ERR);
+    msg_syslog_init(tag, LOG_PID, LOG_FACILITY);
 
     /*
      * Log the command line or log lines from standard input.
index 6302781bc414d3aad6ca679dc3b5188b2e84f6ff..7edabf7d9429543d966b9e91b97a08dda5f0d1a2 100644 (file)
@@ -941,8 +941,8 @@ int     main(int argc, char **argv)
        }
     }
     mail_conf_read();
-    if (strcmp(var_syslog_name, DEF_SYSLOG_NAME) != 0)
-       msg_syslog_init(mail_task(argv[0]), LOG_PID, LOG_FACILITY);
+    /* Re-evaluate mail_task() after reading main.cf. */
+    msg_syslog_init(mail_task(argv[0]), LOG_PID, LOG_FACILITY);
     mail_dict_init();
     if ((query == 0 || strcmp(query, "-") != 0)
        && (postmap_flags & POSTMAP_FLAG_ANY_KEY))
index c90285db73119b0eb23e705bc40c51c0b34c3258..fdf1d72840a639947b734a6cbbf046192f0695fa 100644 (file)
@@ -543,8 +543,8 @@ int     main(int argc, char **argv)
      * Further initialization...
      */
     mail_conf_read();
-    if (strcmp(var_syslog_name, DEF_SYSLOG_NAME) != 0)
-       msg_syslog_init(mail_task("postqueue"), LOG_PID, LOG_FACILITY);
+    /* Re-evaluate mail_task() after reading main.cf. */
+    msg_syslog_init(mail_task("postqueue"), LOG_PID, LOG_FACILITY);
     mail_dict_init();                          /* proxy, sql, ldap */
     get_mail_conf_str_table(str_table);
 
index 0e821367d767123960d110788d930caa87ac9c0b..f2ae791b5d0bc85ab3d64129cf36ccaa8db661a5 100644 (file)
@@ -1223,8 +1223,8 @@ int     main(int argc, char **argv)
      * configuration directory location.
      */
     mail_conf_read();
-    if (strcmp(var_syslog_name, DEF_SYSLOG_NAME) != 0)
-       msg_syslog_init(mail_task(argv[0]), LOG_PID, LOG_FACILITY);
+    /* Re-evaluate mail_task() after reading main.cf. */
+    msg_syslog_init(mail_task(argv[0]), LOG_PID, LOG_FACILITY);
     if (chdir(var_queue_dir))
        msg_fatal("chdir %s: %m", var_queue_dir);
 
index 4a91aa48e07b43a114d87e0f4e1b8d12251e4f05..5cfa8e45f1d96afafff2bcf2239c9bd003335692 100644 (file)
@@ -1073,8 +1073,8 @@ int     main(int argc, char **argv)
     }
     optind = saved_optind;
     mail_conf_read();
-    if (strcmp(var_syslog_name, DEF_SYSLOG_NAME) != 0)
-       msg_syslog_init(mail_task("sendmail"), LOG_PID, LOG_FACILITY);
+    /* Re-evaluate mail_task() after reading main.cf. */
+    msg_syslog_init(mail_task("sendmail"), LOG_PID, LOG_FACILITY);
     get_mail_conf_str_table(str_table);
 
     if (chdir(var_queue_dir))
index 6a704b4cdcd9b87b57a1e55402d5cf49dd61971b..abc00d9e302672ef6effbeaa17295c59790d6567 100644 (file)
@@ -4025,12 +4025,14 @@ static int xclient_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
        if (got_login)
            saved_username = mystrdup(state->sasl_username);
        smtpd_sasl_deactivate(state);
-       if (state->tls_context == 0)            /* TLS from XCLIENT proxy? */
-           smtpd_sasl_activate(state, VAR_SMTPD_SASL_OPTS,
-                               var_smtpd_sasl_opts);
-       else
+#ifdef USE_TLS
+       if (state->tls_context != 0)            /* TLS from XCLIENT proxy? */
            smtpd_sasl_activate(state, VAR_SMTPD_SASL_TLS_OPTS,
                                var_smtpd_sasl_tls_opts);
+       else
+#endif
+           smtpd_sasl_activate(state, VAR_SMTPD_SASL_OPTS,
+                               var_smtpd_sasl_opts);
        if (got_login) {
            smtpd_sasl_auth_extern(state, saved_username, XCLIENT_CMD);
            myfree(saved_username);
index aabbc8e0db5be52399348bbaa38cf09835fcb5e8..e2be6b95ae2f40491dff541b7c50b4446ccebf82 100644 (file)
@@ -8,12 +8,18 @@
 /*
 /*     int     allascii(buffer)
 /*     const char *buffer;
+/*
+/*     int     allascii_len(buffer len)
+/*     const char *buffer;
+/*     ssize_t len;
 /* DESCRIPTION
 /*     allascii() determines if its argument is an all-ASCII string.
 /*
 /*     Arguments:
 /* .IP buffer
 /*     The null-terminated input string.
+/* .IP len
+/*     The string length, -1 to determine the length dynamically.
 /* LICENSE
 /* .ad
 /* .fi
 
 #include "stringops.h"
 
-/* allascii - return true if string is all ASCII */
+/* allascii_len - return true if string is all ASCII */
 
-int     allascii(const char *string)
+int     allascii_len(const char *string, ssize_t len)
 {
     const char *cp;
     int     ch;
 
-    if (*string == 0)
+    if (len < 0)
+       len = strlen(string);
+    if (len == 0)
        return (0);
-    for (cp = string; (ch = *(unsigned char *) cp) != 0; cp++)
+    for (cp = string; cp < string + len
+        && (ch = *(unsigned char *) cp) != 0; cp++)
        if (!ISASCII(ch))
            return (0);
     return (1);
index 15bfa2d38951c55a7ed53ba7a3acc59a921e6015..1ece423056aaeb234367b1eb3a686461212c0b34 100644 (file)
@@ -52,7 +52,7 @@
 /* .IP dest
 /*     Output buffer, null-terminated. Specify a null pointer to
 /*     use an internal buffer that is overwritten upon each call.
-/* .IP len
+/* .IP src_len
 /*     The string length, -1 to determine the length dynamically.
 /* .IP flags
 /*     Bitwise OR of zero or more of the following:
index fa711dcaa4d3368ec3cc867d60acef8542d45e10..22ed434787e7dae32fc8fe37bb77537146757d29 100644 (file)
@@ -130,13 +130,10 @@ int     strncasecmp_utf8x(int flags, const char *s1, const char *s2,
     /*
      * Short-circuit optimization for ASCII-only text. This may be slower
      * than using a cache for all results. See comments above for limitations
-     * of strcasecmp(). XXX We could avoid the vstring_strncpy() if
-     * allascii() had a length argument.
+     * of strcasecmp().
      */
-    vstring_strncpy(f1, s1, len);
-    vstring_strncpy(f2, s2, len);
-    if (allascii(STR(f1)) && allascii(STR(f2)))
-       return (strncasecmp(STR(f1), STR(f2), len));
+    if (allascii_len(s1, len) && allascii_len(s2, len))
+       return (strncasecmp(s1, s2, len));
 
     /*
      * Caution: casefolding may change the number of bytes. See comments
index 673fff2735c4ab5a3d31fd0522418f56c2e62efc..8bafbf06de05427f9845d69b7a3a0d7bd655b7e9 100644 (file)
@@ -5,5 +5,6 @@ compare HeLlO.ExAmPlE.CoM hello.example.com
 compare HeLlO hellp
 compare hellp HeLlO
 compare-len HeLlO hellp 4
+compare-len HeLO help 4
 compare abcde abcdf 
 compare YYY\80\80\80XXX yyy\80\80\80xxx
index cbb41dd5af499a72647a4709cf30d5f461f8efd2..8c0e1a54d9d49e7aa2b72706b8987a6fcdc335c6 100644 (file)
@@ -12,6 +12,8 @@
 "hellp" > "HeLlO"
 > compare-len HeLlO hellp 4
 "HeLl" == "hell"
+> compare-len HeLO help 4
+"HeLO" < "help"
 > compare abcde abcdf 
 "abcde" < "abcdf"
 > compare YYY\80\80\80XXX yyy\80\80\80xxx
index 764fc95f911a4a508f35f964e3fbdbba066653b1..61ea515d8afecb926c45af1de29f578c1130d281 100644 (file)
@@ -44,7 +44,7 @@ extern VSTRING *escape(VSTRING *, const char *, ssize_t);
 extern int alldig(const char *);
 extern int allprint(const char *);
 extern int allspace(const char *);
-extern int allascii(const char *);
+extern int allascii_len(const char *, ssize_t);
 extern const char *split_nameval(char *, char **, char **);
 extern int valid_utf8_string(const char *, ssize_t);
 extern size_t balpar(const char *, const char *);
@@ -62,6 +62,7 @@ extern int strncasecmp_utf8x(int, const char *, const char *, ssize_t);
  /*
   * Convenience wrappers for most-common use cases.
   */
+#define allascii(s)    allascii_len((s), -1)
 #define casefold(dst, src) \
     casefoldx(util_utf8_enable ? CASEF_FLAG_UTF8 : 0, (dst), (src), -1)
 #define casefold_len(dst, src, len) \