]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-2.9-20120115
authorWietse Venema <wietse@porcupine.org>
Sun, 15 Jan 2012 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <viktor@dukhovni.org>
Tue, 5 Feb 2013 06:37:56 +0000 (06:37 +0000)
19 files changed:
postfix/HISTORY
postfix/README_FILES/MEMCACHE_README
postfix/html/MEMCACHE_README.html
postfix/html/memcache_table.5.html
postfix/man/man5/memcache_table.5
postfix/proto/MEMCACHE_README.html
postfix/proto/memcache_table
postfix/src/global/Makefile.in
postfix/src/global/mail_version.h
postfix/src/global/namadr_list.ref
postfix/src/global/surrogate.ref [new file with mode: 0644]
postfix/src/smtpd/smtpd.c
postfix/src/util/Makefile.in
postfix/src/util/dict_cidr.c
postfix/src/util/dict_db.c
postfix/src/util/dict_open.c
postfix/src/util/dict_surrogate.c
postfix/src/util/dict_thash.c
postfix/src/util/surrogate.ref [new file with mode: 0644]

index 1d43a28cb6dd39238576c65d3f9147a868fa128a..56e9bde2972c1aa126efde0d973ae53c637d4ae1 100644 (file)
@@ -17544,3 +17544,16 @@ Apologies for any names omitted.
        SMTP client to report about sessions that fail because a
        table is unavailable. Files: global/mail_error.[hc],
        smtpd/smtpd_check.c, smtp/smtp_trouble.c.
+
+20111215
+
+       Fine tuning: SMTP server error messages. File: smtpd/smtpd.c.
+
+       Fine tuning: documentation. Files: proto/MEMCACHE_README.html.
+       proto/memcache_table.html.
+
+       Apply "gradual degradation" also when an unsupported database
+       *type* is specified. File: util/dict_open.c.
+
+       Cleanup: tiny memory leaks after surrogate database opens.
+       Files: util/dict_cidr.c, util/dict_db.c.
index 56b31cd4c0ce3f7e74869c04653bea5a8bb14821..c668b177cacb035621790943767c31b7f58247fb 100644 (file)
@@ -24,7 +24,7 @@ L\bLi\bim\bmi\bit\bta\bat\bti\bio\bon\bns\bs
     virtual_mailbox_maps (these specify UNIX process privileges or "/file/name"
     destinations). Typically, a memcache database is writable by any process
     that can talk to the memcache server; in contrast, security-sensitive
-    tables must not be writable by the unprivileged Postfix user.
+    tables must never be writable by the unprivileged Postfix user.
 
   * The Postfix memcache client requires additional configuration when used as
     postscreen(8) or verify(8) cache. For details see the backup and ttl
index 5ee1d554c0c64250b0651b483e2d7b55fab136f1..78be1733abfc635907874eac115a1a83ef8a72b8 100644 (file)
@@ -44,7 +44,7 @@ and "<tt>/file/name</tt>" destinations), or <tt><a href="postconf.5.html#virtual
 specify UNIX process privileges or "<tt>/file/name</tt>" destinations).
 Typically, a memcache database is writable by any process that can
 talk to the memcache server; in contrast, security-sensitive tables
-must not be writable by the unprivileged Postfix user.  </p>
+must never be writable by the unprivileged Postfix user.  </p>
 
 <li> <p> The Postfix memcache client requires additional configuration
 when used as <a href="postscreen.8.html">postscreen(8)</a> or <a href="verify.8.html">verify(8)</a> cache.  For details see the
index 11ab0ff7e6ec2090da078f0faed59ff9844c05ce..c10aab16ac35098a4c98032cf13d6e492fc60965 100644 (file)
@@ -75,12 +75,12 @@ MEMCACHE_TABLE(5)                                            MEMCACHE_TABLE(5)
               in all Postfix instances except  for  one  instance
               that will be responsible for cache cleanup.
 
-              NOTE 2: In the case of a proxied database, the full
-              database name (including the "<a href="proxymap.8.html">proxy</a>:" prefix)  must
-              be    specified    in    the    proxymap   server's
-              <a href="postconf.5.html#proxy_read_maps">proxy_read_maps</a>   or    <a href="postconf.5.html#proxy_write_maps">proxy_write_maps</a>    setting
-              (depending  on  whether  the access is read-only or
-              read-write).
+              NOTE  2:  In the case of a proxied backup database,
+              the  full  backup  database  name  (including   the
+              "<a href="proxymap.8.html">proxy</a>:"  prefix) must be specified in the proxymap
+              server's <a href="postconf.5.html#proxy_read_maps">proxy_read_maps</a> or  <a href="postconf.5.html#proxy_write_maps">proxy_write_maps</a>  set-
+              ting  (depending on whether the access is read-only
+              or read-write).
 
        <b>flags (default: 0)</b>
               Optional flags that should be stored along  with  a
@@ -200,7 +200,7 @@ MEMCACHE_TABLE(5)                                            MEMCACHE_TABLE(5)
        destinations).  In a typical deployment a  memcache  data-
        base  is writable by any process that can talk to the mem-
        cache server; in contrast, security-sensitive tables  must
-       not be writable by the unprivileged Postfix user.
+       never be writable by the unprivileged Postfix user.
 
        The Postfix memcache client requires additional configura-
        tion when used as <a href="postscreen.8.html"><b>postscreen</b>(8)</a> or <a href="verify.8.html"><b>verify</b>(8)</a>  cache.   For
index 00276685964aa576b923a413b9edf889870fd41b..f8f286e282e468b668d2273c2fe0c33ab7c75c91 100644 (file)
@@ -80,7 +80,8 @@ automatic cache cleanup (*_cache_cleanup_interval = 0) in
 all Postfix instances except for one instance that will be
 responsible for cache cleanup.
 
-NOTE 2: In the case of a proxied database, the full database
+NOTE 2: In the case of a proxied backup database, the full
+backup database
 name (including the "proxy:" prefix) must be specified in
 the proxymap server's proxy_read_maps or proxy_write_maps
 setting (depending on whether the access is read-only or
@@ -198,7 +199,7 @@ tables such as \fBalias_maps\fR (these may contain
 privileges or "\fI/file/name\fR" destinations).  In a typical
 deployment a memcache database is writable by any process
 that can talk to the memcache server; in contrast,
-security-sensitive tables must not be writable by the
+security-sensitive tables must never be writable by the
 unprivileged Postfix user.
 
 The Postfix memcache client requires additional configuration
index 3f2c3e09b7ab35dae626fd31f3e4b4f563b62bec..ad445892f89e872a31e6346fbd6a2b4067272378 100644 (file)
@@ -44,7 +44,7 @@ and "<tt>/file/name</tt>" destinations), or <tt>virtual_uid_maps</tt>,
 specify UNIX process privileges or "<tt>/file/name</tt>" destinations).
 Typically, a memcache database is writable by any process that can
 talk to the memcache server; in contrast, security-sensitive tables
-must not be writable by the unprivileged Postfix user.  </p>
+must never be writable by the unprivileged Postfix user.  </p>
 
 <li> <p> The Postfix memcache client requires additional configuration
 when used as postscreen(8) or verify(8) cache.  For details see the
index fc5827c13fcc1692c1e4a03eee178d7dff534d27..d4a3658c3bee725c8de6268264a0690efd27753b 100644 (file)
@@ -72,7 +72,8 @@
 #      all Postfix instances except for one instance that will be
 #      responsible for cache cleanup.
 #
-#      NOTE 2: In the case of a proxied database, the full database
+#      NOTE 2: In the case of a proxied backup database, the full
+#      backup database
 #      name (including the "proxy:" prefix) must be specified in
 #      the proxymap server's proxy_read_maps or proxy_write_maps
 #      setting (depending on whether the access is read-only or
 #      privileges or "\fI/file/name\fR" destinations).  In a typical
 #      deployment a memcache database is writable by any process
 #      that can talk to the memcache server; in contrast,
-#      security-sensitive tables must not be writable by the
+#      security-sensitive tables must never be writable by the
 #      unprivileged Postfix user.
 #
 #      The Postfix memcache client requires additional configuration
index 0a5d596ef96af44f1533639cfa3f36695dfb4a47..a1644a32acb11fa572973a83dfa37388fea26206 100644 (file)
@@ -422,6 +422,20 @@ maps_test: maps maps.in maps.ref
        diff  maps.ref maps.tmp
        rm -f maps.tmp
 
+surrogate_test: mail_dict surrogate.ref
+       cp /dev/null surrogate.tmp
+       echo get foo|./mail_dict ldap:/xx write >>surrogate.tmp 2>&1
+       echo get foo|./mail_dict ldap:/xx read >>surrogate.tmp 2>&1
+       echo get foo|./mail_dict mysql:/xx write >>surrogate.tmp 2>&1
+       echo get foo|./mail_dict mysql:/xx read >>surrogate.tmp 2>&1
+       echo get foo|./mail_dict pgsql:/xx write >>surrogate.tmp 2>&1
+       echo get foo|./mail_dict pgsql:/xx read >>surrogate.tmp 2>&1
+       echo get foo|./mail_dict sqlite:/xx write >>surrogate.tmp 2>&1
+       echo get foo|./mail_dict sqlite:/xx read >>surrogate.tmp 2>&1
+       echo get foo|./mail_dict memcache:/xx read >>surrogate.tmp 2>&1
+       diff surrogate.ref surrogate.tmp
+       rm -f surrogate.tmp
+
 # Requires: Postfix running, root privileges
 
 rewrite_clnt_test: rewrite_clnt rewrite_clnt.in rewrite_clnt.ref
index cbb946c714f20c7d8ff29a1afef687644c298383..870efbe8c27d41adfe3e987dfdd1560437f18ca0 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      "20120114"
+#define MAIL_RELEASE_DATE      "20120115"
 #define MAIL_VERSION_NUMBER    "2.9"
 
 #ifdef SNAPSHOT
index 1f62aa216616ad7e4cd7fd34777563b8fc1f56be..1aa895a6c2608008b50204301a531243f1aa4ee6 100644 (file)
@@ -7,7 +7,10 @@ dummy/168.100.189.16: ERROR
 ./namadr_list: warning: bad net/mask pattern: "168.100.589.0/28"
 dummy/168.100.189.16: ERROR
 dummy/168.100.989.16: NO
-./namadr_list: fatal: unsupported dictionary type: 2001
+./namadr_list: error: unsupported dictionary type: 2001
+./namadr_list: warning: 2001:240:5c7:0:2d0:b7ff:fe88:2ca7 is unavailable. unsupported dictionary type: 2001
+./namadr_list: warning: 2001:240:5c7:0:2d0:b7ff:fe88:2ca7: table lookup problem
+dummy/2001:240:5c7:0:2d0:b7ff:fe88:2ca7: ERROR
 dummy/2001:240:5c7:0:2d0:b7ff:fe88:2ca7: YES
 dummy/2001:240:5c7:0:2d0:b7ff:fe88:2ca8: NO
 ./namadr_list: warning: non-null host address bits in "2001:240:5c7:0:2d0:b7ff:fe88:2ca7/64", perhaps you should use "2001:240:5c7::/64" instead
diff --git a/postfix/src/global/surrogate.ref b/postfix/src/global/surrogate.ref
new file mode 100644 (file)
index 0000000..cd12a54
--- /dev/null
@@ -0,0 +1,36 @@
+./mail_dict: error: ldap:/xx map requires O_RDONLY access mode
+> get foo
+./mail_dict: warning: ldap:/xx is unavailable. ldap:/xx map requires O_RDONLY access mode
+foo: error
+./mail_dict: error: open /xx: No such file or directory
+> get foo
+./mail_dict: warning: ldap:/xx is unavailable. open /xx: No such file or directory
+foo: error
+./mail_dict: error: mysql:/xx map requires O_RDONLY access mode
+> get foo
+./mail_dict: warning: mysql:/xx is unavailable. mysql:/xx map requires O_RDONLY access mode
+foo: error
+./mail_dict: error: open /xx: No such file or directory
+> get foo
+./mail_dict: warning: mysql:/xx is unavailable. open /xx: No such file or directory
+foo: error
+./mail_dict: error: pgsql:/xx map requires O_RDONLY access mode
+> get foo
+./mail_dict: warning: pgsql:/xx is unavailable. pgsql:/xx map requires O_RDONLY access mode
+foo: error
+./mail_dict: error: open /xx: No such file or directory
+> get foo
+./mail_dict: warning: pgsql:/xx is unavailable. open /xx: No such file or directory
+foo: error
+./mail_dict: error: sqlite:/xx map requires O_RDONLY access mode
+> get foo
+./mail_dict: warning: sqlite:/xx is unavailable. sqlite:/xx map requires O_RDONLY access mode
+foo: error
+./mail_dict: error: open /xx: No such file or directory
+> get foo
+./mail_dict: warning: sqlite:/xx is unavailable. open /xx: No such file or directory
+foo: error
+./mail_dict: error: open /xx: No such file or directory
+> get foo
+./mail_dict: warning: memcache:/xx is unavailable. open /xx: No such file or directory
+foo: error
index b2bfd231ddea10ca140aaa78b9915e712dda6800..a95f08a97e7c1f070fca87ac9befd58216f5d1ab 100644 (file)
@@ -1559,7 +1559,7 @@ static int helo_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
 
 static NORETURN cant_announce_feature(SMTPD_STATE *state, const char *feature)
 {
-    msg_warn("don't know if feature %s should be announced to %s",
+    msg_warn("don't know if EHLO feature %s should be announced to %s",
             feature, state->namaddr);
     vstream_longjmp(state->client, SMTP_ERR_DATA);
 }
@@ -1677,7 +1677,8 @@ static int ehlo_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
        if (discard_mask && !(discard_mask & EHLO_MASK_SILENT))
            msg_info("discarding EHLO keywords: %s", str_ehlo_mask(discard_mask));
     if (ehlo_discard_maps && ehlo_discard_maps->error) {
-       msg_warn("don't know what features to announce in EHLO");
+       msg_warn("don't know what EHLO features to announce to %s",
+                state->namaddr);
        vstream_longjmp(state->client, SMTP_ERR_DATA);
     }
 
@@ -4491,12 +4492,12 @@ static void smtpd_proto(SMTPD_STATE *state)
 
     case SMTP_ERR_DATA:
        msg_info("%s: reject: %s from %s: "
-                "421 4.3.0 %s Server configuration error",
+                "421 4.3.0 %s Server local data error",
                 (state->queue_id ? state->queue_id : "NOQUEUE"),
                 state->where, state->namaddr, var_myhostname);
        state->error_mask |= MAIL_ERROR_DATA;
        if (vstream_setjmp(state->client) == 0)
-           smtpd_chat_reply(state, "421 4.3.0 %s Server configuration error",
+           smtpd_chat_reply(state, "421 4.3.0 %s Server local data error",
                             var_myhostname);
        break;
 
index cff7d8a0588e4530de600faa25e9d831c788ef4d..c73642c98b8403416dd40c1805111b140e6fd7ce 100644 (file)
@@ -444,7 +444,7 @@ tests: valid_hostname_test mac_expand_test dict_test unescape_test \
        attr_scan64_test attr_scan0_test dict_pcre_test host_port_test \
        dict_cidr_test attr_scan_plain_test htable_test hex_code_test \
        myaddrinfo_test format_tv_test ip_match_test name_mask_tests \
-       base32_code_test dict_thash_test
+       base32_code_test dict_thash_test surrogate_test
 
 root_tests:
 
@@ -633,6 +633,22 @@ dict_thash_test: ../postmap/postmap dict_thash.map
        sort dict_thash.tmp | diff -b dict_thash.map -
        rm -f dict_thash.tmp
 
+surrogate_test: dict_open surrogate.ref
+       cp /dev/null surrogate.tmp
+       echo get foo|./dict_open cidr:/xx write >>surrogate.tmp 2>&1
+       echo get foo|./dict_open cidr:/xx read >>surrogate.tmp 2>&1
+       echo get foo|./dict_open pcre:/xx write >>surrogate.tmp 2>&1
+       echo get foo|./dict_open pcre:/xx read >>surrogate.tmp 2>&1
+       echo get foo|./dict_open regexp:/xx write >>surrogate.tmp 2>&1
+       echo get foo|./dict_open regexp:/xx read >>surrogate.tmp 2>&1
+       echo get foo|./dict_open unix:xx write >>surrogate.tmp 2>&1
+       echo get foo|./dict_open unix:xx read >>surrogate.tmp 2>&1
+       echo get foo|./dict_open texthash:/xx write >>surrogate.tmp 2>&1
+       echo get foo|./dict_open texthash:/xx read >>surrogate.tmp 2>&1
+       echo get foo|./dict_open hash:/xx read >>surrogate.tmp 2>&1
+       diff surrogate.ref surrogate.tmp
+       rm -f surrogate.tmp
+
 depend: $(MAKES)
        (sed '1,/^# do not edit/!d' Makefile.in; \
        set -e; for i in [a-z][a-z0-9]*.c; do \
index 5731e58d4e425755f87c03939f41878d61e73fb7..2ea7ab1fdb528fc6ec76e70c585442a128a8017f 100644 (file)
@@ -166,8 +166,8 @@ DICT   *dict_cidr_open(const char *mapname, int open_flags, int dict_flags)
     DICT_CIDR *dict_cidr;
     VSTREAM *map_fp;
     struct stat st;
-    VSTRING *line_buffer = vstring_alloc(100);
-    VSTRING *why = vstring_alloc(100);
+    VSTRING *line_buffer;
+    VSTRING *why;
     DICT_CIDR_ENTRY *rule;
     DICT_CIDR_ENTRY *last_rule = 0;
     int     lineno = 0;
@@ -189,6 +189,12 @@ DICT   *dict_cidr_open(const char *mapname, int open_flags, int dict_flags)
     if (fstat(vstream_fileno(map_fp), &st) < 0)
        msg_fatal("fstat %s: %m", mapname);
 
+    /*
+     * No early returns without memory leaks.
+     */
+    line_buffer = vstring_alloc(100);
+    why = vstring_alloc(100);
+
     /*
      * XXX Eliminate unnecessary queries by setting a flag that says "this
      * map matches network addresses only".
index 29e4cda09610c81c2f8bbedde6dc0cac14f83421..5a4287c86fff6d7e02baf2f1b0cf85f56ef0c402 100644 (file)
@@ -573,8 +573,8 @@ static DICT *dict_db_open(const char *class, const char *path, int open_flags,
 {
     DICT_DB *dict_db;
     struct stat st;
-    DB     *db;
-    char   *db_path;
+    DB     *db = 0;
+    char   *db_path = 0;
     int     lock_fd = -1;
     int     dbfd;
 
@@ -624,12 +624,16 @@ static DICT *dict_db_open(const char *class, const char *path, int open_flags,
      * db_open() create a non-existent file for us.
      */
 #define LOCK_OPEN_FLAGS(f) ((f) & ~(O_CREAT|O_TRUNC))
+#define FREE_RETURN(e) do { \
+       DICT *_dict = (e); if (db) DICT_DB_CLOSE(db); \
+       if (db_path) myfree(db_path); return (_dict); \
+    } while (0)
 
     if (dict_flags & DICT_FLAG_LOCK) {
        if ((lock_fd = open(db_path, LOCK_OPEN_FLAGS(open_flags), 0644)) < 0) {
            if (errno != ENOENT)
-               return (dict_surrogate(class, path, open_flags, dict_flags,
-                                      "open database %s: %m", db_path));
+               FREE_RETURN(dict_surrogate(class, path, open_flags, dict_flags,
+                                          "open database %s: %m", db_path));
        } else {
            if (myflock(lock_fd, INTERNAL_LOCK, MYFLOCK_OP_SHARED) < 0)
                msg_fatal("shared-lock database %s for open: %m", db_path);
@@ -644,8 +648,8 @@ static DICT *dict_db_open(const char *class, const char *path, int open_flags,
      */
 #if DB_VERSION_MAJOR < 2
     if ((db = dbopen(db_path, open_flags, 0644, type, tweak)) == 0)
-       return (dict_surrogate(class, path, open_flags, dict_flags,
-                              "open database %s: %m", db_path));
+       FREE_RETURN(dict_surrogate(class, path, open_flags, dict_flags,
+                                  "open database %s: %m", db_path));
     dbfd = db->fd(db);
 #endif
 
@@ -661,8 +665,8 @@ static DICT *dict_db_open(const char *class, const char *path, int open_flags,
     if (open_flags & O_TRUNC)
        db_flags |= DB_TRUNCATE;
     if ((errno = db_open(db_path, type, db_flags, 0644, 0, tweak, &db)) != 0)
-       return (dict_surrogate(class, path, open_flags, dict_flags,
-                              "open database %s: %m", db_path));
+       FREE_RETURN(dict_surrogate(class, path, open_flags, dict_flags,
+                                  "open database %s: %m", db_path));
     if (db == 0)
        msg_panic("db_open null result");
     if ((errno = db->fd(db, &dbfd)) != 0)
@@ -690,12 +694,12 @@ static DICT *dict_db_open(const char *class, const char *path, int open_flags,
        msg_fatal("set DB hash element count %d: %m", DICT_DB_NELM);
 #if DB_VERSION_MAJOR == 5 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 0)
     if ((errno = db->open(db, 0, db_path, 0, type, db_flags, 0644)) != 0)
-       return (dict_surrogate(class, path, open_flags, dict_flags,
-                              "open database %s: %m", db_path));
+       FREE_RETURN(dict_surrogate(class, path, open_flags, dict_flags,
+                                  "open database %s: %m", db_path));
 #elif (DB_VERSION_MAJOR == 3 || DB_VERSION_MAJOR == 4)
     if ((errno = db->open(db, db_path, 0, type, db_flags, 0644)) != 0)
-       return (dict_surrogate(class, path, open_flags, dict_flags,
-                              "open database %s: %m", db_path));
+       FREE_RETURN(dict_surrogate(class, path, open_flags, dict_flags,
+                                  "open database %s: %m", db_path));
 #else
 #error "Unsupported Berkeley DB version"
 #endif
index 49e2b2c3cfa66ddfbc1a126bd6fb708d4263efec..7b7c0c56ccd4e051457e8703a0a894507587d3c3 100644 (file)
@@ -339,9 +339,11 @@ DICT   *dict_open3(const char *dict_type, const char *dict_name,
     if (dict_open_hash == 0)
        dict_open_init();
     if ((dp = (DICT_OPEN_INFO *) htable_find(dict_open_hash, dict_type)) == 0)
-       msg_fatal("unsupported dictionary type: %s", dict_type);
+       return (dict_surrogate(dict_type, dict_name, open_flags, dict_flags,
+                            "unsupported dictionary type: %s", dict_type));
     if ((dict = dp->open(dict_name, open_flags, dict_flags)) == 0)
-       msg_fatal("opening %s:%s %m", dict_type, dict_name);
+       return (dict_surrogate(dict_type, dict_name, open_flags, dict_flags,
+                           "cannot open %s:%s: %m", dict_type, dict_name));
     if (msg_verbose)
        msg_info("%s: %s:%s", myname, dict_type, dict_name);
     /* XXX the choice between wait-for-lock or no-wait is hard-coded. */
index 42dbe8fadb5cc846783068987a6c544c0b84a431..4183d9259a80a4be1cc24da7fd406e73134d5d83 100644 (file)
@@ -6,7 +6,7 @@
 /* SYNOPSIS
 /*     #include <dict_surrogate.h>
 /*
-/*     DICT    *dict_surrogate(dict_type, dict_name, 
+/*     DICT    *dict_surrogate(dict_type, dict_name,
 /*                             open_flags, dict_flags,
 /*                             format, ...)
 /*     const char *dict_type;
@@ -24,7 +24,8 @@
 /*
 /*     The global dict_allow_surrogate variable controls the choice
 /*     between fatal error or reduced functionality. The default
-/*     value is zero (fatal error).
+/*     value is zero (fatal error). This is appropriate for user
+/*     commands; the non-default is more appropriate for daemons.
 /*
 /*     Arguments:
 /* .IP dict_type
@@ -34,7 +35,8 @@
 /*     The parameters to the failed dictionary open() request.
 /* .IP format, ...
 /*     The reason why the table could not be opened. This text is
-/*     logged immediately, and upon every attempt to access the
+/*     logged immediately as an "error" class message, and is logged
+/*     as a "warning" class message upon every attempt to access the
 /*     surrogate dictionary, before returning a "failed" completion
 /*     status.
 /* SEE ALSO
@@ -53,6 +55,7 @@
 /* System library. */
 
 #include <sys_defs.h>
+#include <errno.h>
 
 /* Utility library. */
 
@@ -123,7 +126,7 @@ static void dict_surrogate_close(DICT *dict)
     dict_free(dict);
 }
 
-int dict_allow_surrogate = 0;
+int     dict_allow_surrogate = 0;
 
 /* dict_surrogate - terminate or provide surrogate dictionary */
 
@@ -135,6 +138,7 @@ DICT   *dict_surrogate(const char *dict_type, const char *dict_name,
     DICT_SURROGATE *dp;
     VSTRING *buf;
     void    (*log_fn) (const char *, va_list);
+    int     saved_errno = errno;
 
     /*
      * Log the problem immediately when it is detected. The table may not be
@@ -161,6 +165,7 @@ DICT   *dict_surrogate(const char *dict_type, const char *dict_name,
     dp->dict.flags = dict_flags | DICT_FLAG_PATTERN;
     dp->dict.owner.status = DICT_OWNER_TRUSTED;
     buf = vstring_alloc(10);
+    errno = saved_errno;
     va_start(ap, fmt);
     vstring_vsprintf(buf, fmt, ap);
     va_end(ap);
index 2c35db9a3566f95c99d221aa2b37647e4a42e39a..0f09d4b933cde4659778bfecf191057947924854 100644 (file)
@@ -148,7 +148,7 @@ DICT   *dict_thash_open(const char *path, int open_flags, int dict_flags)
     struct stat st;
     time_t  before;
     time_t  after;
-    VSTRING *line_buffer = vstring_alloc(100);
+    VSTRING *line_buffer = 0;
     int     lineno;
     char   *key;
     char   *value;
@@ -172,6 +172,8 @@ DICT   *dict_thash_open(const char *path, int open_flags, int dict_flags)
            return (dict_surrogate(DICT_TYPE_THASH, path, open_flags, dict_flags,
                                   "open database %s: %m", path));
        }
+       if (line_buffer == 0)
+           line_buffer = vstring_alloc(100);
        lineno = 0;
        table = htable_create(13);
        while (readlline(line_buffer, fp, &lineno)) {
diff --git a/postfix/src/util/surrogate.ref b/postfix/src/util/surrogate.ref
new file mode 100644 (file)
index 0000000..2b8429b
--- /dev/null
@@ -0,0 +1,44 @@
+./dict_open: error: cidr:/xx map requires O_RDONLY access mode
+> get foo
+./dict_open: warning: cidr:/xx is unavailable. cidr:/xx map requires O_RDONLY access mode
+foo: error
+./dict_open: error: open /xx: No such file or directory
+> get foo
+./dict_open: warning: cidr:/xx is unavailable. open /xx: No such file or directory
+foo: error
+./dict_open: error: pcre:/xx map requires O_RDONLY access mode
+> get foo
+./dict_open: warning: pcre:/xx is unavailable. pcre:/xx map requires O_RDONLY access mode
+foo: error
+./dict_open: error: open /xx: No such file or directory
+> get foo
+./dict_open: warning: pcre:/xx is unavailable. open /xx: No such file or directory
+foo: error
+./dict_open: error: regexp:/xx map requires O_RDONLY access mode
+> get foo
+./dict_open: warning: regexp:/xx is unavailable. regexp:/xx map requires O_RDONLY access mode
+foo: error
+./dict_open: error: open /xx: No such file or directory
+> get foo
+./dict_open: warning: regexp:/xx is unavailable. open /xx: No such file or directory
+foo: error
+./dict_open: error: unix:xx map requires O_RDONLY access mode
+> get foo
+./dict_open: warning: unix:xx is unavailable. unix:xx map requires O_RDONLY access mode
+foo: error
+./dict_open: error: unknown table: unix:xx
+> get foo
+./dict_open: warning: unix:xx is unavailable. unknown table: unix:xx
+foo: error
+./dict_open: error: texthash:/xx map requires O_RDONLY access mode
+> get foo
+./dict_open: warning: texthash:/xx is unavailable. texthash:/xx map requires O_RDONLY access mode
+foo: error
+./dict_open: error: open database /xx: No such file or directory
+> get foo
+./dict_open: warning: texthash:/xx is unavailable. open database /xx: No such file or directory
+foo: error
+./dict_open: error: open database /xx.db: No such file or directory
+> get foo
+./dict_open: warning: hash:/xx is unavailable. open database /xx.db: No such file or directory
+foo: error