]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
snapshot-19990327
authorWietse Venema <wietse@porcupine.org>
Sat, 27 Mar 1999 05:00:00 +0000 (00:00 -0500)
committerWietse Venema <wietse@porcupine.org>
Thu, 17 Jan 2013 03:34:01 +0000 (22:34 -0500)
71 files changed:
postfix/.indent.pro
postfix/HISTORY
postfix/bounce/.indent.pro
postfix/cleanup/.indent.pro
postfix/conf/sample-regexp.cf [new file with mode: 0644]
postfix/dns/.indent.pro
postfix/fsstone/.indent.pro
postfix/global/.indent.pro
postfix/global/mail_copy.c
postfix/global/mail_version.h
postfix/global/maps.c
postfix/global/mkmap.h
postfix/global/mkmap_db.c
postfix/global/mkmap_open.c
postfix/local/.indent.pro
postfix/local/dotforward.c
postfix/local/recipient.c
postfix/master/.indent.pro
postfix/pickup/.indent.pro
postfix/pipe/.indent.pro
postfix/postalias/.indent.pro
postfix/postalias/Makefile.in
postfix/postalias/postalias.c
postfix/postcat/.indent.pro
postfix/postconf/.indent.pro
postfix/postdrop/.indent.pro
postfix/postfix/.indent.pro
postfix/postkick/.indent.pro
postfix/postlock/.indent.pro
postfix/postlog/.indent.pro
postfix/postmap/.indent.pro
postfix/postmap/Makefile.in
postfix/postmap/postmap.c
postfix/postsuper/.indent.pro
postfix/qmgr/.indent.pro
postfix/sendmail/.indent.pro
postfix/showq/.indent.pro
postfix/smtp/.indent.pro
postfix/smtpd/.indent.pro
postfix/smtpd/smtpd_check.c
postfix/smtpstone/.indent.pro
postfix/trivial-rewrite/.indent.pro
postfix/util/.indent.pro
postfix/util/Makefile.in
postfix/util/dict.h
postfix/util/dict_db.c
postfix/util/dict_db.h
postfix/util/dict_dbm.c
postfix/util/dict_dbm.h
postfix/util/dict_env.c
postfix/util/dict_env.h
postfix/util/dict_ldap.c
postfix/util/dict_ldap.h
postfix/util/dict_ni.c
postfix/util/dict_ni.h
postfix/util/dict_nis.c
postfix/util/dict_nis.h
postfix/util/dict_nisplus.c
postfix/util/dict_nisplus.h
postfix/util/dict_open.c
postfix/util/dict_pcre.c
postfix/util/dict_pcre.h
postfix/util/dict_regexp.c [new file with mode: 0644]
postfix/util/dict_regexp.h [new file with mode: 0644]
postfix/util/dict_unix.c
postfix/util/dict_unix.h
postfix/util/environ.c
postfix/util/match_list.c
postfix/util/posix_signals.c
postfix/util/posix_signals.h
postfix/util/sys_defs.h

index 715b1fb48d3d338b47e149af697cf72397d48731..f683dc2bc1d1a54952a8451503a9d650b17d5076 100644 (file)
@@ -27,6 +27,8 @@
 -TDICT_NODE
 -TDICT_OPEN_INFO
 -TDICT_PCRE
+-TDICT_REGEXP
+-TDICT_REGEXP_LINE
 -TDICT_UNIX
 -TDNS_FIXED
 -TDNS_REPLY
index 4bcd7e03258c75ddb03bf55d2fbbe5b282b39407..cf850012deae0bdc9cb5d7caf155e3384d78c5ef 100644 (file)
@@ -2429,7 +2429,8 @@ Apologies for any names omitted.
        Workaround: Solaris NIS alias maps need special entries
        (YP_MASTER_NAME, YP_LAST_MODIFIED). What's worse, normal
        keys/values include a null byte at the end, but the YP_XXX
-       ones don't.  File: postalias/postalias.c.
+       ones don't. Problem reported by Walcir Fontanini, state
+       university of Campinas, Brazil.  File: postalias/postalias.c.
 
        Compatibility: Solaris NIS apparently does include a null
        byte at the end of keys and values. File: util/sys_defs.h.
@@ -2442,6 +2443,26 @@ Apologies for any names omitted.
        Bugfix: pcre didn't handle \\ right. Lamont Jones, Hewlett-
        Packard. File: util/dict_pcre.c.
 
+19990326
+
+       Compatibility: Postfix now puts to spaces after the sender
+       in a "From sender date..." header. Found by John A. Martin,
+       fixed by Lamont Jones, Hewlett-Packard.
+
+       Bugfix: when a recipient appeared multiple times in a local
+       alias or include expansion, the delivery status could be
+       left uninitialized, causing the mail to be deferred and 
+       delivered again. File: local/recipient.c.
+
+19990327
+
+       Cleanup: the dictionary routines now take an extra flag
+       argument to control such things as warning about duplicates,
+       and appending null bytes to key/value. This was needed for
+       a clean implementation of NIS master alias maps support.
+
+       Feature: POSIX regular expressions by Lamont Jones.
+
 Future:
 
        Planned: must be able to list the same hash table in
index 715b1fb48d3d338b47e149af697cf72397d48731..f683dc2bc1d1a54952a8451503a9d650b17d5076 100644 (file)
@@ -27,6 +27,8 @@
 -TDICT_NODE
 -TDICT_OPEN_INFO
 -TDICT_PCRE
+-TDICT_REGEXP
+-TDICT_REGEXP_LINE
 -TDICT_UNIX
 -TDNS_FIXED
 -TDNS_REPLY
index 715b1fb48d3d338b47e149af697cf72397d48731..f683dc2bc1d1a54952a8451503a9d650b17d5076 100644 (file)
@@ -27,6 +27,8 @@
 -TDICT_NODE
 -TDICT_OPEN_INFO
 -TDICT_PCRE
+-TDICT_REGEXP
+-TDICT_REGEXP_LINE
 -TDICT_UNIX
 -TDNS_FIXED
 -TDNS_REPLY
diff --git a/postfix/conf/sample-regexp.cf b/postfix/conf/sample-regexp.cf
new file mode 100644 (file)
index 0000000..263c550
--- /dev/null
@@ -0,0 +1,17 @@
+# Sample regexp lookup "table".
+#
+# Format is /regexp/flags or /regexp/flags!/regexp/flags
+# where regexp is a regular expression as found in regexp(5), and flags are
+#   i: toggle ignore case (REG_ICASE - default is to ignore case)
+#   x: toggle extended expression (REG_EXTENDED - default is extended)
+#   m: toggle multiline mode (REG_NEWLINE - default is non-multiline mode)
+#
+# In order for a line to match, the first regexp must match, and the
+# second (if present) must not match.  The first matching line wins,
+# terminating processing of the ruleset.
+
+# Postmaster is OK, that way they can talk to us about how to fix their problem.
+/^postmaster@.*$/                      OK
+
+# Protect your outgoing majordomo exploders
+/^(.*)-outgoing@(.*)$/!/^owner-.*/     550 Use ${1}@${2} instead
index 715b1fb48d3d338b47e149af697cf72397d48731..f683dc2bc1d1a54952a8451503a9d650b17d5076 100644 (file)
@@ -27,6 +27,8 @@
 -TDICT_NODE
 -TDICT_OPEN_INFO
 -TDICT_PCRE
+-TDICT_REGEXP
+-TDICT_REGEXP_LINE
 -TDICT_UNIX
 -TDNS_FIXED
 -TDNS_REPLY
index 715b1fb48d3d338b47e149af697cf72397d48731..f683dc2bc1d1a54952a8451503a9d650b17d5076 100644 (file)
@@ -27,6 +27,8 @@
 -TDICT_NODE
 -TDICT_OPEN_INFO
 -TDICT_PCRE
+-TDICT_REGEXP
+-TDICT_REGEXP_LINE
 -TDICT_UNIX
 -TDNS_FIXED
 -TDNS_REPLY
index 715b1fb48d3d338b47e149af697cf72397d48731..f683dc2bc1d1a54952a8451503a9d650b17d5076 100644 (file)
@@ -27,6 +27,8 @@
 -TDICT_NODE
 -TDICT_OPEN_INFO
 -TDICT_PCRE
+-TDICT_REGEXP
+-TDICT_REGEXP_LINE
 -TDICT_UNIX
 -TDNS_FIXED
 -TDNS_REPLY
index 6e58bf0465c309abd841102600afd17b22e695e0..4116270d4f32128bb588829da2a3b5b7662e6875 100644 (file)
@@ -131,7 +131,7 @@ int     mail_copy(const char *sender, const char *delivered,
        quote_822_local(buf, sender);
        if (flags & MAIL_COPY_FROM) {
            time(&now);
-           vstream_fprintf(dst, "From %s %s", *sender == 0 ?
+           vstream_fprintf(dst, "From %s  %s", *sender == 0 ?
                            MAIL_ADDR_MAIL_DAEMON :
                            vstring_str(buf),
                            asctime(localtime(&now)));
index e40ca1fb8a55dc69c4c4c02232ce2f5620f97693..49562d6a84cff4467db74d08b9ac508c422889da 100644 (file)
@@ -15,7 +15,7 @@
   * Version of this program.
   */
 #define VAR_MAIL_VERSION       "mail_version"
-#define DEF_MAIL_VERSION       "Snapshot-19990325"
+#define DEF_MAIL_VERSION       "Snapshot-19990327"
 extern char *var_mail_version;
 
 /* LICENSE
index 148ce8e56c9960417335979eb83c3d58eb27c2a9..13b9280e54d10ffaeb00dc4b16c41de00b37d9d5 100644 (file)
@@ -121,7 +121,7 @@ MAPS   *maps_create(const char *title, const char *map_names)
        if (msg_verbose)
            msg_info("%s: %s", myname, map_type_name);
        if ((dict = dict_handle(map_type_name)) == 0)
-           dict = dict_open(map_type_name, O_RDONLY);
+           dict = dict_open(map_type_name, O_RDONLY, 0);
        dict_register(map_type_name, dict);
        argv_add(maps->argv, map_type_name, ARGV_END);
     }
index d004d2fafa0bd79c0634c5b05c4e55c810455ed1..86384575b99e61ce139b66e2736138fecab473d2 100644 (file)
 /* DESCRIPTION
 /* .nf
 
+ /*
+  * Utility library.
+  */
+#include <dict.h>
+
  /*
   * A database handle is an opaque structure. The user is not supposed to
   * know its implementation.
   */
 typedef struct MKMAP {
-    struct DICT *(*open) (const char *, int);
+    struct DICT *(*open) (const char *, int, int);
     struct DICT *dict;
     char   *lock_file;
     int     lock_fd;
 } MKMAP;
 
-extern MKMAP *mkmap_open(const char *, const char *, int);
+extern MKMAP *mkmap_open(const char *, const char *, int, int);
 extern void mkmap_append(MKMAP *, const char *, const char *);
 extern void mkmap_close(MKMAP *);
 
index cc9eff87abbcc1c63595e88e40f9c585fbbca328..d89c3b5e6803f4420fb28192e44f9c90b48ad14d 100644 (file)
@@ -59,7 +59,7 @@
 /* mkmap_db_open - create or open database */
 
 static MKMAP *mkmap_db_open(const char *path,
-                            DICT *(*db_open) (const char *, int))
+                            DICT *(*db_open) (const char *, int, int))
 {
     MKMAP  *mkmap = (MKMAP *) mymalloc(sizeof(*mkmap));
 
index 530653d54e8dd0cf5d08fae8baefe33ce7764c8e..899c0b65ad2af948106cc3f2a817f9e14766b45b 100644 (file)
@@ -6,10 +6,11 @@
 /* SYNOPSIS
 /*     #include <mkmap.h>
 /*
-/*     MKMAP   *mkmap_open(type, path, flags)
+/*     MKMAP   *mkmap_open(type, path, open_flags, dict_flags)
 /*     char    *type;
 /*     char    *path;
-/*     int     flags;
+/*     int     open_flags;
+/*     int     dict_flags;
 /*
 /*     void    mkmap_append(mkmap, key, value, lineno)
 /*     MKMAP   *mkmap;
 /*     appending the appropriate suffixes to the specified filename.
 /*     Before the database is updated, it is locked for exclusive
 /*     access, and signal delivery is suspended.
+/*     See dict(3) for a description of \fBopen_flags\fR and \fBdict_flags\fR.
 /*     All errors are fatal.
 /*
 /*     mkmap_append() appends the named (key, value) pair to the
 /*     database. Update errors are fatal; duplicate keys are ignored
 /*     (but a warning is issued).
+/*     \fBlineno\fR is used for diagnostics.
 /*
 /*     mkmap_close() closes the database, releases any locks,
 /*     and resumes signal delivery. All errors are fatal.
@@ -118,7 +121,8 @@ void    mkmap_close(MKMAP *mkmap)
 
 /* mkmap_open - create or truncate database */
 
-MKMAP  *mkmap_open(const char *type, const char *path, int flags)
+MKMAP  *mkmap_open(const char *type, const char *path,
+                  int open_flags, int dict_flags)
 {
     MKMAP  *mkmap;
     MKMAP_OPEN_INFO *mp;
@@ -157,7 +161,7 @@ MKMAP  *mkmap_open(const char *type, const char *path, int flags)
      * Truncate the database upon open, and update it. Read-write mode is
      * needed because the underlying routines read as well as write.
      */
-    mkmap->dict = mkmap->open(path, flags);
+    mkmap->dict = mkmap->open(path, open_flags, dict_flags);
     mkmap->dict->fd = -1;                      /* XXX just in case */
     mkmap->dict->flags |= DICT_FLAG_DUP_WARN;
     return (mkmap);
index 715b1fb48d3d338b47e149af697cf72397d48731..f683dc2bc1d1a54952a8451503a9d650b17d5076 100644 (file)
@@ -27,6 +27,8 @@
 -TDICT_NODE
 -TDICT_OPEN_INFO
 -TDICT_PCRE
+-TDICT_REGEXP
+-TDICT_REGEXP_LINE
 -TDICT_UNIX
 -TDNS_FIXED
 -TDNS_REPLY
index 35cb9e2eaf78dd02376fc6bb6f70594ba38a71c0..9eea11caf2f7045e09cc383e2ebdb4466c0ec9ff 100644 (file)
@@ -102,6 +102,9 @@ static void dotforward_parse_callback(int type, VSTRING *buf, char *context)
     FW_CONTEXT *fw_context = (FW_CONTEXT *) context;
     char   *ptr;
 
+    if (fw_context->failures)
+       return;
+
     /*
      * Find out what data to substitute.
      */
index fd09619c8b8d90b3d8380e6cc7b62b2851776634..36452618f3dac053ac6b489b5c9c8e9c3eb40313 100644 (file)
@@ -91,7 +91,7 @@
 static int deliver_switch(LOCAL_STATE state, USER_ATTR usr_attr)
 {
     char   *myname = "deliver_switch";
-    int     status;
+    int     status = 0;
 
     /*
      * Make verbose logging easier to understand.
index 715b1fb48d3d338b47e149af697cf72397d48731..f683dc2bc1d1a54952a8451503a9d650b17d5076 100644 (file)
@@ -27,6 +27,8 @@
 -TDICT_NODE
 -TDICT_OPEN_INFO
 -TDICT_PCRE
+-TDICT_REGEXP
+-TDICT_REGEXP_LINE
 -TDICT_UNIX
 -TDNS_FIXED
 -TDNS_REPLY
index 715b1fb48d3d338b47e149af697cf72397d48731..f683dc2bc1d1a54952a8451503a9d650b17d5076 100644 (file)
@@ -27,6 +27,8 @@
 -TDICT_NODE
 -TDICT_OPEN_INFO
 -TDICT_PCRE
+-TDICT_REGEXP
+-TDICT_REGEXP_LINE
 -TDICT_UNIX
 -TDNS_FIXED
 -TDNS_REPLY
index 715b1fb48d3d338b47e149af697cf72397d48731..f683dc2bc1d1a54952a8451503a9d650b17d5076 100644 (file)
@@ -27,6 +27,8 @@
 -TDICT_NODE
 -TDICT_OPEN_INFO
 -TDICT_PCRE
+-TDICT_REGEXP
+-TDICT_REGEXP_LINE
 -TDICT_UNIX
 -TDNS_FIXED
 -TDNS_REPLY
index 715b1fb48d3d338b47e149af697cf72397d48731..f683dc2bc1d1a54952a8451503a9d650b17d5076 100644 (file)
@@ -27,6 +27,8 @@
 -TDICT_NODE
 -TDICT_OPEN_INFO
 -TDICT_PCRE
+-TDICT_REGEXP
+-TDICT_REGEXP_LINE
 -TDICT_UNIX
 -TDNS_FIXED
 -TDNS_REPLY
index 608f9f2a3258cc8ef7f3b613be5c57ae02623202..c053f40157ec2cf9924313cf6b4732ba446578c5 100644 (file)
@@ -70,3 +70,4 @@ postalias.o: ../include/resolve_clnt.h
 postalias.o: ../include/config.h
 postalias.o: ../include/mail_params.h
 postalias.o: ../include/mkmap.h
+postalias.o: ../include/dict.h
index ad4a91d6d366cf30736f63bd1f57e1b8cfbec56c..4159a63b9ab53c0b2d405a1e0790d954b7a07996 100644 (file)
 
 /* postalias - create or update alias database */
 
-static void postalias(char *map_type, char *path_name, int incremental)
+static void postalias(char *map_type, char *path_name,
+                             int open_flags, int dict_flags)
 {
     VSTREAM *source_fp;
     VSTRING *line_buffer;
@@ -140,7 +141,7 @@ static void postalias(char *map_type, char *path_name, int incremental)
     line_buffer = vstring_alloc(100);
     key_buffer = vstring_alloc(100);
     value_buffer = vstring_alloc(100);
-    if (incremental) {
+    if ((open_flags & O_TRUNC) == 0) {
        source_fp = VSTREAM_IN;
        vstream_control(source_fp, VSTREAM_CTL_PATH, "stdin", VSTREAM_CTL_END);
     } else if ((source_fp = vstream_fopen(path_name, O_RDONLY, 0)) == 0) {
@@ -151,8 +152,7 @@ static void postalias(char *map_type, char *path_name, int incremental)
      * Open the database, create it when it does not exist, truncate it when
      * it does exist, and lock out any spectators.
      */
-    mkmap = mkmap_open(map_type, path_name, incremental ?
-                      O_RDWR | O_CREAT : O_RDWR | O_CREAT | O_TRUNC);
+    mkmap = mkmap_open(map_type, path_name, open_flags, dict_flags);
 
     /*
      * Add records to the database.
@@ -245,8 +245,12 @@ static void postalias(char *map_type, char *path_name, int incremental)
     mkmap_append(mkmap, "@", "@");
 
     /*
-     * NIS compatibility: add time and master info.
+     * NIS compatibility: add time and master info. Unlike other information,
+     * this information MUST be written without a trailing null appended to
+     * key or value.
      */
+    mkmap->dict->flags &= ~DICT_FLAG_TRY1NULL;
+    mkmap->dict->flags |= DICT_FLAG_TRY0NULL;
     vstring_sprintf(value_buffer, "%010ld", (long) time((time_t *) 0));
     mkmap_append(mkmap, "YP_LAST_MODIFIED", STR(value_buffer));
     mkmap_append(mkmap, "YP_MASTER_NAME", get_hostname());
@@ -270,7 +274,7 @@ static void postalias(char *map_type, char *path_name, int incremental)
 
 static NORETURN usage(char *myname)
 {
-    msg_fatal("usage: %s [-c config_directory] [-i] [-v] [output_type:]file...",
+    msg_fatal("usage: %s [-c config_directory] [-i] [-v] [-w] [output_type:]file...",
              myname);
 }
 
@@ -281,7 +285,8 @@ int     main(int argc, char **argv)
     int     fd;
     char   *slash;
     struct stat st;
-    int     incremental = 0;
+    int     open_flags = O_RDWR | O_CREAT | O_TRUNC;
+    int     dict_flags = DICT_FLAG_DUP_WARN;
 
     /*
      * Be consistent with file permissions.
@@ -316,7 +321,7 @@ int     main(int argc, char **argv)
     /*
      * Parse JCL.
      */
-    while ((ch = GETOPT(argc, argv, "c:iv")) > 0) {
+    while ((ch = GETOPT(argc, argv, "c:ivw")) > 0) {
        switch (ch) {
        default:
            usage(argv[0]);
@@ -326,11 +331,15 @@ int     main(int argc, char **argv)
                msg_fatal("out of memory");
            break;
        case 'i':
-           incremental = 1;
+           open_flags &= ~O_TRUNC;
            break;
        case 'v':
            msg_verbose++;
            break;
+       case 'w':
+           dict_flags &= ~DICT_FLAG_DUP_WARN;
+           dict_flags |= DICT_FLAG_DUP_IGNORE;
+           break;
        }
     }
     read_config();
@@ -343,9 +352,9 @@ int     main(int argc, char **argv)
        usage(argv[0]);
     while (optind < argc) {
        if ((path_name = split_at(argv[optind], ':')) != 0) {
-           postalias(argv[optind], path_name, incremental);
+           postalias(argv[optind], path_name, open_flags, dict_flags);
        } else {
-           postalias(var_db_type, argv[optind], incremental);
+           postalias(var_db_type, argv[optind], open_flags, dict_flags);
        }
        optind++;
     }
index 715b1fb48d3d338b47e149af697cf72397d48731..f683dc2bc1d1a54952a8451503a9d650b17d5076 100644 (file)
@@ -27,6 +27,8 @@
 -TDICT_NODE
 -TDICT_OPEN_INFO
 -TDICT_PCRE
+-TDICT_REGEXP
+-TDICT_REGEXP_LINE
 -TDICT_UNIX
 -TDNS_FIXED
 -TDNS_REPLY
index 715b1fb48d3d338b47e149af697cf72397d48731..f683dc2bc1d1a54952a8451503a9d650b17d5076 100644 (file)
@@ -27,6 +27,8 @@
 -TDICT_NODE
 -TDICT_OPEN_INFO
 -TDICT_PCRE
+-TDICT_REGEXP
+-TDICT_REGEXP_LINE
 -TDICT_UNIX
 -TDNS_FIXED
 -TDNS_REPLY
index 715b1fb48d3d338b47e149af697cf72397d48731..f683dc2bc1d1a54952a8451503a9d650b17d5076 100644 (file)
@@ -27,6 +27,8 @@
 -TDICT_NODE
 -TDICT_OPEN_INFO
 -TDICT_PCRE
+-TDICT_REGEXP
+-TDICT_REGEXP_LINE
 -TDICT_UNIX
 -TDNS_FIXED
 -TDNS_REPLY
index 715b1fb48d3d338b47e149af697cf72397d48731..f683dc2bc1d1a54952a8451503a9d650b17d5076 100644 (file)
@@ -27,6 +27,8 @@
 -TDICT_NODE
 -TDICT_OPEN_INFO
 -TDICT_PCRE
+-TDICT_REGEXP
+-TDICT_REGEXP_LINE
 -TDICT_UNIX
 -TDNS_FIXED
 -TDNS_REPLY
index 715b1fb48d3d338b47e149af697cf72397d48731..f683dc2bc1d1a54952a8451503a9d650b17d5076 100644 (file)
@@ -27,6 +27,8 @@
 -TDICT_NODE
 -TDICT_OPEN_INFO
 -TDICT_PCRE
+-TDICT_REGEXP
+-TDICT_REGEXP_LINE
 -TDICT_UNIX
 -TDNS_FIXED
 -TDNS_REPLY
index 715b1fb48d3d338b47e149af697cf72397d48731..f683dc2bc1d1a54952a8451503a9d650b17d5076 100644 (file)
@@ -27,6 +27,8 @@
 -TDICT_NODE
 -TDICT_OPEN_INFO
 -TDICT_PCRE
+-TDICT_REGEXP
+-TDICT_REGEXP_LINE
 -TDICT_UNIX
 -TDNS_FIXED
 -TDNS_REPLY
index 715b1fb48d3d338b47e149af697cf72397d48731..f683dc2bc1d1a54952a8451503a9d650b17d5076 100644 (file)
@@ -27,6 +27,8 @@
 -TDICT_NODE
 -TDICT_OPEN_INFO
 -TDICT_PCRE
+-TDICT_REGEXP
+-TDICT_REGEXP_LINE
 -TDICT_UNIX
 -TDNS_FIXED
 -TDNS_REPLY
index 715b1fb48d3d338b47e149af697cf72397d48731..f683dc2bc1d1a54952a8451503a9d650b17d5076 100644 (file)
@@ -27,6 +27,8 @@
 -TDICT_NODE
 -TDICT_OPEN_INFO
 -TDICT_PCRE
+-TDICT_REGEXP
+-TDICT_REGEXP_LINE
 -TDICT_UNIX
 -TDNS_FIXED
 -TDNS_REPLY
index bb6eec9f987b84220b3861281fc40f46f4a5fbe6..ef896ce48acb57dca85f2841399aaef12563a1e7 100644 (file)
@@ -67,3 +67,4 @@ postmap.o: ../include/split_at.h
 postmap.o: ../include/config.h
 postmap.o: ../include/mail_params.h
 postmap.o: ../include/mkmap.h
+postmap.o: ../include/dict.h
index 9cd698ebc9cd159e11f714f0247cb35cd2ac4ca1..fc660d80d4b963f7a52b6f46ea1e349e2a285010 100644 (file)
 
 /* postmap - create or update mapping database */
 
-static void postmap(char *map_type, char *path_name, int incremental)
+static void postmap(char *map_type, char *path_name,
+                           int open_flags, int dict_flags)
 {
     VSTREAM *source_fp;
     VSTRING *line_buffer;
@@ -143,7 +144,7 @@ static void postmap(char *map_type, char *path_name, int incremental)
      * Initialize.
      */
     line_buffer = vstring_alloc(100);
-    if (incremental) {
+    if ((open_flags & O_TRUNC) == 0) {
        source_fp = VSTREAM_IN;
        vstream_control(source_fp, VSTREAM_CTL_PATH, "stdin", VSTREAM_CTL_END);
     } else if ((source_fp = vstream_fopen(path_name, O_RDONLY, 0)) == 0) {
@@ -151,11 +152,11 @@ static void postmap(char *map_type, char *path_name, int incremental)
     }
 
     /*
-     * Open the database, create it when it does not exist, truncate it when
-     * it does exist, and lock out any spectators.
+     * Open the database, optionally create it when it does not exist,
+     * optionally truncate it when it does exist, and lock out any
+     * spectators.
      */
-    mkmap = mkmap_open(map_type, path_name, incremental ?
-                      O_RDWR | O_CREAT : O_RDWR | O_CREAT | O_TRUNC);
+    mkmap = mkmap_open(map_type, path_name, open_flags, dict_flags);
 
     /*
      * Add records to the database.
@@ -227,7 +228,7 @@ static void postmap(char *map_type, char *path_name, int incremental)
 
 static NORETURN usage(char *myname)
 {
-    msg_fatal("usage: %s [-c config_directory] [-i] [-v] [output_type:]file...",
+    msg_fatal("usage: %s [-c config_directory] [-i] [-v] [-w] [output_type:]file...",
              myname);
 }
 
@@ -238,7 +239,8 @@ int     main(int argc, char **argv)
     int     fd;
     char   *slash;
     struct stat st;
-    int     incremental = 0;
+    int     open_flags = O_RDWR | O_CREAT | O_TRUNC;
+    int     dict_flags = DICT_FLAG_DUP_WARN;
 
     /*
      * Be consistent with file permissions.
@@ -273,7 +275,7 @@ int     main(int argc, char **argv)
     /*
      * Parse JCL.
      */
-    while ((ch = GETOPT(argc, argv, "c:iv")) > 0) {
+    while ((ch = GETOPT(argc, argv, "c:ivw")) > 0) {
        switch (ch) {
        default:
            usage(argv[0]);
@@ -283,11 +285,15 @@ int     main(int argc, char **argv)
                msg_fatal("out of memory");
            break;
        case 'i':
-           incremental = 1;
+           open_flags &= ~O_TRUNC;
            break;
        case 'v':
            msg_verbose++;
            break;
+       case 'w':
+           dict_flags &= ~DICT_FLAG_DUP_WARN;
+           dict_flags |= DICT_FLAG_DUP_IGNORE;
+           break;
        }
     }
     read_config();
@@ -300,9 +306,9 @@ int     main(int argc, char **argv)
        usage(argv[0]);
     while (optind < argc) {
        if ((path_name = split_at(argv[optind], ':')) != 0) {
-           postmap(argv[optind], path_name, incremental);
+           postmap(argv[optind], path_name, open_flags, dict_flags);
        } else {
-           postmap(var_db_type, argv[optind], incremental);
+           postmap(var_db_type, argv[optind], open_flags, dict_flags);
        }
        optind++;
     }
index 715b1fb48d3d338b47e149af697cf72397d48731..f683dc2bc1d1a54952a8451503a9d650b17d5076 100644 (file)
@@ -27,6 +27,8 @@
 -TDICT_NODE
 -TDICT_OPEN_INFO
 -TDICT_PCRE
+-TDICT_REGEXP
+-TDICT_REGEXP_LINE
 -TDICT_UNIX
 -TDNS_FIXED
 -TDNS_REPLY
index 715b1fb48d3d338b47e149af697cf72397d48731..f683dc2bc1d1a54952a8451503a9d650b17d5076 100644 (file)
@@ -27,6 +27,8 @@
 -TDICT_NODE
 -TDICT_OPEN_INFO
 -TDICT_PCRE
+-TDICT_REGEXP
+-TDICT_REGEXP_LINE
 -TDICT_UNIX
 -TDNS_FIXED
 -TDNS_REPLY
index 715b1fb48d3d338b47e149af697cf72397d48731..f683dc2bc1d1a54952a8451503a9d650b17d5076 100644 (file)
@@ -27,6 +27,8 @@
 -TDICT_NODE
 -TDICT_OPEN_INFO
 -TDICT_PCRE
+-TDICT_REGEXP
+-TDICT_REGEXP_LINE
 -TDICT_UNIX
 -TDNS_FIXED
 -TDNS_REPLY
index 715b1fb48d3d338b47e149af697cf72397d48731..f683dc2bc1d1a54952a8451503a9d650b17d5076 100644 (file)
@@ -27,6 +27,8 @@
 -TDICT_NODE
 -TDICT_OPEN_INFO
 -TDICT_PCRE
+-TDICT_REGEXP
+-TDICT_REGEXP_LINE
 -TDICT_UNIX
 -TDNS_FIXED
 -TDNS_REPLY
index 715b1fb48d3d338b47e149af697cf72397d48731..f683dc2bc1d1a54952a8451503a9d650b17d5076 100644 (file)
@@ -27,6 +27,8 @@
 -TDICT_NODE
 -TDICT_OPEN_INFO
 -TDICT_PCRE
+-TDICT_REGEXP
+-TDICT_REGEXP_LINE
 -TDICT_UNIX
 -TDNS_FIXED
 -TDNS_REPLY
index 715b1fb48d3d338b47e149af697cf72397d48731..f683dc2bc1d1a54952a8451503a9d650b17d5076 100644 (file)
@@ -27,6 +27,8 @@
 -TDICT_NODE
 -TDICT_OPEN_INFO
 -TDICT_PCRE
+-TDICT_REGEXP
+-TDICT_REGEXP_LINE
 -TDICT_UNIX
 -TDNS_FIXED
 -TDNS_REPLY
index 705f5b4cfa614800ba2b5173aa762fc20cf736ee..88f755fc2fa30b0c07fd9091ca512ebd5848ea54 100644 (file)
@@ -312,7 +312,7 @@ static ARGV *smtpd_check_parse(char *checks)
     while ((name = mystrtok(&bp, " \t\r\n,")) != 0) {
        argv_add(argv, name, (char *) 0);
        if (strchr(name, ':') && dict_handle(name) == 0)
-           dict_register(name, dict_open(name, 0));
+           dict_register(name, dict_open(name, 0, 0));
     }
     argv_terminate(argv);
 
index 715b1fb48d3d338b47e149af697cf72397d48731..f683dc2bc1d1a54952a8451503a9d650b17d5076 100644 (file)
@@ -27,6 +27,8 @@
 -TDICT_NODE
 -TDICT_OPEN_INFO
 -TDICT_PCRE
+-TDICT_REGEXP
+-TDICT_REGEXP_LINE
 -TDICT_UNIX
 -TDNS_FIXED
 -TDNS_REPLY
index 715b1fb48d3d338b47e149af697cf72397d48731..f683dc2bc1d1a54952a8451503a9d650b17d5076 100644 (file)
@@ -27,6 +27,8 @@
 -TDICT_NODE
 -TDICT_OPEN_INFO
 -TDICT_PCRE
+-TDICT_REGEXP
+-TDICT_REGEXP_LINE
 -TDICT_UNIX
 -TDNS_FIXED
 -TDNS_REPLY
index 715b1fb48d3d338b47e149af697cf72397d48731..f683dc2bc1d1a54952a8451503a9d650b17d5076 100644 (file)
@@ -27,6 +27,8 @@
 -TDICT_NODE
 -TDICT_OPEN_INFO
 -TDICT_PCRE
+-TDICT_REGEXP
+-TDICT_REGEXP_LINE
 -TDICT_UNIX
 -TDNS_FIXED
 -TDNS_REPLY
index b9e7a1268d25b8d3fdbe24091a64e4335706cae4..3ac316ab10763a50550e5ac7cd379f50bcd23de4 100644 (file)
@@ -19,7 +19,7 @@ SRCS  = argv.c argv_split.c attr.c basename.c binhash.c chroot_uid.c \
        unsafe.c username.c valid_hostname.c vbuf.c vbuf_print.c \
        vstream.c vstream_popen.c vstring.c vstring_vstream.c writable.c \
        write_buf.c write_wait.c dict_unix.c dict_pcre.c stream_listen.c \
-       stream_connect.c stream_trigger.c
+       stream_connect.c stream_trigger.c dict_regexp.c
 OBJS   = argv.o argv_split.o attr.o basename.o binhash.o chroot_uid.o \
        close_on_exec.o concatenate.o dict.o dict_db.o dict_dbm.o \
        dict_env.o dict_ht.o dict_ldap.o dict_ni.o dict_nis.o \
@@ -40,7 +40,7 @@ OBJS  = argv.o argv_split.o attr.o basename.o binhash.o chroot_uid.o \
        unsafe.o username.o valid_hostname.o vbuf.o vbuf_print.o \
        vstream.o vstream_popen.o vstring.o vstring_vstream.o writable.o \
        write_buf.o write_wait.o dict_unix.o dict_pcre.o stream_listen.o \
-       stream_connect.o stream_trigger.o
+       stream_connect.o stream_trigger.o dict_regexp.o
 HDRS   = argv.h attr.h binhash.h chroot_uid.h connect.h dict.h dict_db.h \
        dict_dbm.h dict_env.h dict_ht.h dict_ldap.h dict_ni.h dict_nis.h \
        dict_nisplus.h dir_forest.h events.h exec_command.h find_inet.h \
@@ -54,7 +54,7 @@ HDRS  = argv.h attr.h binhash.h chroot_uid.h connect.h dict.h dict_db.h \
        sigdelay.h split_at.h stat_as.h stringops.h sys_defs.h \
        timed_connect.h timed_wait.h trigger.h username.h valid_hostname.h \
        vbuf.h vbuf_print.h vstream.h vstring.h vstring_vstream.h \
-       dict_unix.h dict_pcre.h
+       dict_unix.h dict_pcre.h dict_regexp.h
 TESTSRC        = fifo_open.c fifo_rdwr_bug.c fifo_rdonly_bug.c select_bug.c \
        stream_test.c
 WARN   = -W -Wformat -Wimplicit -Wmissing-prototypes \
@@ -364,10 +364,24 @@ dict_open.o: dict_nisplus.h
 dict_open.o: dict_ni.h
 dict_open.o: dict_ldap.h
 dict_open.o: dict_pcre.h
+dict_open.o: dict_regexp.h
 dict_open.o: stringops.h
 dict_open.o: split_at.h
 dict_pcre.o: dict_pcre.c
 dict_pcre.o: sys_defs.h
+dict_regexp.o: dict_regexp.c
+dict_regexp.o: sys_defs.h
+dict_regexp.o: mymalloc.h
+dict_regexp.o: msg.h
+dict_regexp.o: safe.h
+dict_regexp.o: vstream.h
+dict_regexp.o: vbuf.h
+dict_regexp.o: vstring.h
+dict_regexp.o: stringops.h
+dict_regexp.o: readline.h
+dict_regexp.o: dict.h
+dict_regexp.o: dict_regexp.h
+dict_regexp.o: mac_parse.h
 dict_unix.o: dict_unix.c
 dict_unix.o: sys_defs.h
 dict_unix.o: msg.h
@@ -622,6 +636,7 @@ percentm.o: vbuf.h
 percentm.o: percentm.h
 posix_signals.o: posix_signals.c
 posix_signals.o: sys_defs.h
+posix_signals.o: posix_signals.h
 printable.o: printable.c
 printable.o: sys_defs.h
 printable.o: stringops.h
index a66962c3356d55171dea323a46c41fc051d0f1d4..73f2da441147132d256d68fb5303d1afc8fb3ba5 100644 (file)
@@ -35,6 +35,8 @@ typedef struct DICT {
 
 #define DICT_FLAG_DUP_WARN     (1<<0)  /* if file, warn about dups */
 #define DICT_FLAG_DUP_IGNORE   (1<<1)  /* if file, ignore dups */
+#define DICT_FLAG_TRY0NULL     (1<<2)  /* do not append 0 to key/value */
+#define DICT_FLAG_TRY1NULL     (1<<3)  /* append 0 to key/value */
 
 extern int dict_unknown_allowed;
 extern int dict_errno;
@@ -58,8 +60,8 @@ extern const char *dict_eval(const char *, const char *, int);
   * Low-level interface, with physical dictionary handles and no implied
   * locking.
   */
-extern DICT *dict_open(const char *, int);
-extern DICT *dict_open3(const char *, const char *, int);
+extern DICT *dict_open(const char *, int, int);
+extern DICT *dict_open3(const char *, const char *, int, int);
 
 #define dict_get(dp, key)      (dp)->lookup((dp), (key))
 #define dict_put(dp, key, val) (dp)->update((dp), (key), (val))
index 0e34c93753e16a09cbed907b05f86b9d34d8fbef..70d50a59c77dff8e2cb4b51a21231e3348ea5108 100644 (file)
@@ -6,13 +6,15 @@
 /* SYNOPSIS
 /*     #include <dict_db.h>
 /*
-/*     DICT    *dict_hash_open(path, flags)
+/*     DICT    *dict_hash_open(path, open_flags, dict_flags)
 /*     const char *path;
-/*     int     flags;
+/*     int     open_flags;
+/*     int     dict_flags;
 /*
-/*     DICT    *dict_btree_open(path, flags)
+/*     DICT    *dict_btree_open(path, open_flags, dict_flags)
 /*     const char *path;
-/*     int     flags;
+/*     int     open_flags;
+/*     int     dict_flags;
 /* DESCRIPTION
 /*     dict_XXX_open() opens the specified DB database.  The result is
 /*     a pointer to a structure that can be used to access the dictionary
 /*     Arguments:
 /* .IP path
 /*     The database pathname, not including the ".db" suffix.
-/* .IP flags
-/*     flags passed to dbopen().
+/* .IP open_flags
+/*     Flags passed to dbopen().
+/* .IP dict_flags
+/*     Flags used by the dictionary interface.
 /* SEE ALSO
 /*     dict(3) generic dictionary manager
 /* DIAGNOSTICS
@@ -71,9 +75,6 @@ typedef struct {
     char   *path;                      /* pathname */
 } DICT_DB;
 
-#define DICT_DB_TRY0NULL       (1<<0)
-#define DICT_DB_TRY1NULL       (1<<1)
-
 #define DICT_DB_CACHE_SIZE     (1024 * 1024)
 #define DICT_DB_NELM   4096
 
@@ -92,13 +93,13 @@ static const char *dict_db_lookup(DICT *dict, const char *name)
      * See if this DB file was written with one null byte appended to key and
      * value.
      */
-    if (dict_db->flags & DICT_DB_TRY1NULL) {
+    if (dict_db->flags & DICT_FLAG_TRY1NULL) {
        db_key.data = (void *) name;
        db_key.size = strlen(name) + 1;
        if ((status = db->get(db, &db_key, &db_value, 0)) < 0)
            msg_fatal("error reading %s: %m", dict_db->path);
        if (status == 0) {
-           dict_db->flags &= ~DICT_DB_TRY0NULL;
+           dict_db->flags &= ~DICT_FLAG_TRY0NULL;
            return (db_value.data);
        }
     }
@@ -107,7 +108,7 @@ static const char *dict_db_lookup(DICT *dict, const char *name)
      * See if this DB file was written with no null byte appended to key and
      * value.
      */
-    if (dict_db->flags & DICT_DB_TRY0NULL) {
+    if (dict_db->flags & DICT_FLAG_TRY0NULL) {
        db_key.data = (void *) name;
        db_key.size = strlen(name);
        if ((status = db->get(db, &db_key, &db_value, 0)) < 0)
@@ -116,7 +117,7 @@ static const char *dict_db_lookup(DICT *dict, const char *name)
            if (buf == 0)
                buf = vstring_alloc(10);
            vstring_strncpy(buf, db_value.data, db_value.size);
-           dict_db->flags &= ~DICT_DB_TRY1NULL;
+           dict_db->flags &= ~DICT_FLAG_TRY1NULL;
            return (vstring_str(buf));
        }
     }
@@ -142,19 +143,19 @@ static void dict_db_update(DICT *dict, const char *name, const char *value)
      * If undecided about appending a null byte to key and value, choose a
      * default depending on the platform.
      */
-    if ((dict_db->flags & DICT_DB_TRY1NULL)
-       && (dict_db->flags & DICT_DB_TRY0NULL)) {
+    if ((dict_db->flags & DICT_FLAG_TRY1NULL)
+       && (dict_db->flags & DICT_FLAG_TRY0NULL)) {
 #ifdef DB_NO_TRAILING_NULL
-       dict_db->flags = DICT_DB_TRY0NULL;
+       dict_db->flags = DICT_FLAG_TRY0NULL;
 #else
-       dict_db->flags = DICT_DB_TRY1NULL;
+       dict_db->flags = DICT_FLAG_TRY1NULL;
 #endif
     }
 
     /*
      * Optionally append a null byte to key and value.
      */
-    if (dict_db->flags & DICT_DB_TRY1NULL) {
+    if (dict_db->flags & DICT_FLAG_TRY1NULL) {
        db_key.size++;
        db_value.size++;
     }
@@ -188,7 +189,8 @@ static void dict_db_close(DICT *dict)
 
 /* dict_db_open - open data base */
 
-static DICT *dict_db_open(const char *path, int flags, int type, void *tweak)
+static DICT *dict_db_open(const char *path, int flags, int type,
+                                 void *tweak, int dict_flags)
 {
     DICT_DB *dict_db;
     DB     *db;
@@ -204,7 +206,9 @@ static DICT *dict_db_open(const char *path, int flags, int type, void *tweak)
     dict_db->dict.close = dict_db_close;
     dict_db->dict.fd = db->fd(db);
     close_on_exec(dict_db->dict.fd, CLOSE_ON_EXEC);
-    dict_db->flags = DICT_DB_TRY1NULL | DICT_DB_TRY0NULL;
+    dict_db->dict.flags = dict_flags;
+    if ((flags & (DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL)) == 0)
+       dict_db->dict.flags |= (DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL);
     dict_db->db = db;
     dict_db->path = db_path;
     return (&dict_db->dict);
@@ -212,26 +216,26 @@ static DICT *dict_db_open(const char *path, int flags, int type, void *tweak)
 
 /* dict_hash_open - create association with data base */
 
-DICT   *dict_hash_open(const char *path, int flags)
+DICT   *dict_hash_open(const char *path, int open_flags, int dict_flags)
 {
     HASHINFO tweak;
 
     memset((char *) &tweak, 0, sizeof(tweak));
     tweak.nelem = DICT_DB_NELM;
     tweak.cachesize = DICT_DB_CACHE_SIZE;
-    return (dict_db_open(path, flags, DB_HASH, (void *) &tweak));
+    return (dict_db_open(path, open_flags, DB_HASH, (void *) &tweak, dict_flags));
 }
 
 /* dict_btree_open - create association with data base */
 
-DICT   *dict_btree_open(const char *path, int flags)
+DICT   *dict_btree_open(const char *path, int open_flags, int dict_flags)
 {
     BTREEINFO tweak;
 
     memset((char *) &tweak, 0, sizeof(tweak));
     tweak.cachesize = DICT_DB_CACHE_SIZE;
 
-    return (dict_db_open(path, flags, DB_BTREE, (void *) &tweak));
+    return (dict_db_open(path, open_flags, DB_BTREE, (void *) &tweak, dict_flags));
 }
 
 #endif
index d03e282f3e01156385037ed75dcc86bc2513f4a6..43d7e35ab57b50cd56a48e4cd8477b33d73d7faf 100644 (file)
@@ -19,8 +19,8 @@
  /*
   * External interface.
   */
-extern DICT *dict_hash_open(const char *, int);
-extern DICT *dict_btree_open(const char *, int);
+extern DICT *dict_hash_open(const char *, int, int);
+extern DICT *dict_btree_open(const char *, int, int);
 
 /* LICENSE
 /* .ad
index a8adec77783ef4e599ab46733b88431ebb951432..87c6faad3066f8ff4ff29cf095140aa9fce2e7e6 100644 (file)
@@ -6,10 +6,11 @@
 /* SYNOPSIS
 /*     #include <dict_dbm.h>
 /*
-/*     DICT    *dict_dbm_open(path, flags)
+/*     DICT    *dict_dbm_open(path, open_flags, dict_flags)
 /*     const char *name;
 /*     const char *path;
-/*     int     flags;
+/*     int     open_flags;
+/*     int     dict_flags;
 /* DESCRIPTION
 /*     dict_dbm_open() opens the named DBM database and makes it available
 /*     via the generic interface described in dict_open(3).
@@ -57,9 +58,6 @@ typedef struct {
     char   *path;                      /* pathname */
 } DICT_DBM;
 
-#define DICT_DBM_TRY0NULL      (1<<0)
-#define DICT_DBM_TRY1NULL      (1<<1)
-
 /* dict_dbm_lookup - find database entry */
 
 static const char *dict_dbm_lookup(DICT *dict, const char *name)
@@ -73,12 +71,12 @@ static const char *dict_dbm_lookup(DICT *dict, const char *name)
      * See if this DBM file was written with one null byte appended to key
      * and value.
      */
-    if (dict_dbm->flags & DICT_DBM_TRY1NULL) {
+    if (dict_dbm->flags & DICT_FLAG_TRY1NULL) {
        dbm_key.dptr = (void *) name;
        dbm_key.dsize = strlen(name) + 1;
        dbm_value = dbm_fetch(dict_dbm->dbm, dbm_key);
        if (dbm_value.dptr != 0) {
-           dict_dbm->flags &= ~DICT_DBM_TRY0NULL;
+           dict_dbm->flags &= ~DICT_FLAG_TRY0NULL;
            return (dbm_value.dptr);
        }
     }
@@ -87,7 +85,7 @@ static const char *dict_dbm_lookup(DICT *dict, const char *name)
      * See if this DBM file was written with no null byte appended to key and
      * value.
      */
-    if (dict_dbm->flags & DICT_DBM_TRY0NULL) {
+    if (dict_dbm->flags & DICT_FLAG_TRY0NULL) {
        dbm_key.dptr = (void *) name;
        dbm_key.dsize = strlen(name);
        dbm_value = dbm_fetch(dict_dbm->dbm, dbm_key);
@@ -95,7 +93,7 @@ static const char *dict_dbm_lookup(DICT *dict, const char *name)
            if (buf == 0)
                buf = vstring_alloc(10);
            vstring_strncpy(buf, dbm_value.dptr, dbm_value.dsize);
-           dict_dbm->flags &= ~DICT_DBM_TRY1NULL;
+           dict_dbm->flags &= ~DICT_FLAG_TRY1NULL;
            return (vstring_str(buf));
        }
     }
@@ -120,21 +118,19 @@ static void dict_dbm_update(DICT *dict, const char *name, const char *value)
      * If undecided about appending a null byte to key and value, choose a
      * default depending on the platform.
      */
-    if ((dict_dbm->flags & DICT_DBM_TRY1NULL)
-       && (dict_dbm->flags & DICT_DBM_TRY0NULL)) {
+    if ((dict_dbm->flags & DICT_FLAG_TRY1NULL)
+       && (dict_dbm->flags & DICT_FLAG_TRY0NULL)) {
 #ifdef DBM_NO_TRAILING_NULL
-       dict_dbm->flags = DICT_DBM_TRY0NULL;
+       dict_dbm->flags = DICT_FLAG_TRY0NULL;
 #else
-       dict_dbm->flags = DICT_DBM_TRY1NULL;
+       dict_dbm->flags = DICT_FLAG_TRY1NULL;
 #endif
     }
 
     /*
      * Optionally append a null byte to key and value.
      */
-    if ((dict_dbm->flags & DICT_DBM_TRY1NULL)
-       && strcmp(name, "YP_MASTER_NAME") != 0
-       && strcmp(name, "YP_LAST_MODIFIED") != 0) {
+    if (dict_dbm->flags & DICT_FLAG_TRY1NULL) {
        dbm_key.dsize++;
        dbm_value.dsize++;
     }
@@ -167,7 +163,7 @@ static void dict_dbm_close(DICT *dict)
 
 /* dict_dbm_open - open DBM data base */
 
-DICT   *dict_dbm_open(const char *path, int flags)
+DICT   *dict_dbm_open(const char *path, int open_flags, int dict_flags)
 {
     DICT_DBM *dict_dbm;
     DBM    *dbm;
@@ -175,7 +171,7 @@ DICT   *dict_dbm_open(const char *path, int flags)
     /*
      * XXX SunOS 5.x has no const in dbm_open() prototype.
      */
-    if ((dbm = dbm_open((char *) path, flags, 0644)) == 0)
+    if ((dbm = dbm_open((char *) path, open_flags, 0644)) == 0)
        msg_fatal("open database %s.{dir,pag}: %m", path);
 
     dict_dbm = (DICT_DBM *) mymalloc(sizeof(*dict_dbm));
@@ -184,7 +180,9 @@ DICT   *dict_dbm_open(const char *path, int flags)
     dict_dbm->dict.close = dict_dbm_close;
     dict_dbm->dict.fd = dbm_dirfno(dbm);
     close_on_exec(dict_dbm->dict.fd, CLOSE_ON_EXEC);
-    dict_dbm->flags = DICT_DBM_TRY0NULL | DICT_DBM_TRY1NULL;
+    dict_dbm->dict.flags = dict_flags;
+    if (dict_flagsflags & (DICT_FLAG_TRY0NULL | DICT_FLAG_TRY1NULL)) == 0)
+       dict_dbm->dict.flags |= (DICT_FLAG_TRY0NULL | DICT_FLAG_TRY1NULL);
     dict_dbm->dbm = dbm;
     dict_dbm->path = mystrdup(path);
 
index da8f5c031d9eda14a9a59a871e9d6bfd019c3a63..e15e8fb7239546ba7b6ca2b76ab1d93fa948b212 100644 (file)
@@ -19,7 +19,7 @@
  /*
   * External interface.
   */
-extern DICT *dict_dbm_open(const char *, int);
+extern DICT *dict_dbm_open(const char *, int, int);
 
 /* LICENSE
 /* .ad
index cbc8249e71c0003bb8e4bc6f07e9e884f03a9ce9..926a2b9475b64467ac002c0fd8d6d1a771e6ed62 100644 (file)
@@ -6,13 +6,14 @@
 /* SYNOPSIS
 /*     #include <dict_env.h>
 /*
-/*     DICT    *dict_env_open(name, flags)
+/*     DICT    *dict_env_open(name, dummy, dict_flags)
 /*     const char *name;
-/*     int     flags;
+/*     int     dummy;
+/*     int     dict_flags;
 /* DESCRIPTION
 /*     dict_env_open() opens the environment variable array and
 /*     makes it accessible via the generic operations documented
-/*     in dict_open(3). The \fIname\fR and \fIflags\fR arguments
+/*     in dict_open(3). The \fIname\fR and \fIdummy\fR arguments
 /*     are ignored.
 /* SEE ALSO
 /*     dict(3) generic dictionary manager
@@ -68,7 +69,7 @@ static void dict_env_close(DICT *dict)
 
 /* dict_env_open - make association with environment array */
 
-DICT   *dict_env_open(const char *unused_name, int unused_flags)
+DICT   *dict_env_open(const char *unused_name, int unused_flags, int dict_flags)
 {
     DICT   *dict;
 
@@ -76,6 +77,7 @@ DICT   *dict_env_open(const char *unused_name, int unused_flags)
     dict->lookup = dict_env_lookup;
     dict->update = dict_env_update;
     dict->close = dict_env_close;
+    dict->flags = dict_flags;
     dict->fd = -1;
     return (dict);
 }
index 672c64a58b837f6b4abedc4683a0b221e98ffa0a..f49e10551ad4420713e7063aa3401725149eac24 100644 (file)
@@ -19,7 +19,7 @@
  /*
   * External interface.
   */
-extern DICT *dict_env_open(const char *, int);
+extern DICT *dict_env_open(const char *, int, int);
 
 /* LICENSE
 /* .ad
index d63150cbcde4c1d49c5231e4509e34877ecc23c9..d22adae36cc23c6cdfcfb3a695447451452970c8 100644 (file)
@@ -6,9 +6,10 @@
 /* SYNOPSIS
 /*     #include <dict_ldap.h>
 /*
-/*     DICT    *dict_ldap_open(attribute, dummy)
+/*     DICT    *dict_ldap_open(attribute, dummy, dict_flags)
 /*     const char *attribute;
 /*     int     dummy;
+/*     int     dict_flags;
 /* DESCRIPTION
 /*     dict_ldap_open() makes LDAP user information accessible via
 /*     the generic dictionary operations described in dict_open(3).
@@ -307,7 +308,7 @@ static void dict_ldap_close(DICT *dict)
 
 /* dict_ldap_open - create association with data base */
 
-DICT   *dict_ldap_open(const char *ldapsource, int flags)
+DICT   *dict_ldap_open(const char *ldapsource, int dummy, int dict_flags)
 {
     char   *myname = "dict_ldap_open";
     DICT_LDAP *dict_ldap;
@@ -320,6 +321,7 @@ DICT   *dict_ldap_open(const char *ldapsource, int flags)
     dict_ldap->dict.update = dict_ldap_update;
     dict_ldap->dict.close = dict_ldap_close;
     dict_ldap->dict.fd = -1;
+    dict_ldap->dict.flags = dict_flags;
 
     if (msg_verbose)
         msg_info("%s: using LDAP source %s", myname, ldapsource);
index 8a88cdcef041be053e10bc020a484be3dcc11fc2..818835df02cb3986fcbd82966bfeb5bb127463e6 100644 (file)
@@ -19,7 +19,7 @@
  /*
   * External interface.
   */
-extern DICT *dict_ldap_open(const char *, int);
+extern DICT *dict_ldap_open(const char *, int, int);
 
 /* AUTHOR(S)
 /*     Wietse Venema
index 06331d49193e5128555df5904539b2e8dc3b6f6f..5f7aabd85418737611d59eb5c1f02ab704e87336 100644 (file)
@@ -1,9 +1,193 @@
- /*
-  * The NetInfo software is not bundled with IBM's public release. It will be
-  * made available as contributed software from http://www.postfix.org/
-  */
+/*++
+/* NAME
+/*     dict_ni 3
+/* SUMMARY
+/*     dictionary manager interface to NetInfo
+/* SYNOPSIS
+/*     #include <dict_ni.h>
+/*
+/*     DICT    *dict_ni_open(path, dummy, dict_flags)
+/*     char    *path;
+/*     int     dummy;
+/*     int     dict_flags;
+/* DESCRIPTION
+/*     dict_ni_open() `opens' the named NetInfo database. The result is
+/*     a pointer to a structure that can be used to access the dictionary
+/*     using the generic methods documented in dict_open(3).
+/* DIAGNOSTICS
+/*     dict_ni_register() returns 0 in case of success, -1 in case
+/*     of problems.
+/*     Fatal errors: NetInfo errors, out of memory.
+/* SEE ALSO
+/*     dict(3) generic dictionary manager
+/*     netinfo(3N) data base subroutines
+/* AUTHOR(S)
+/*     Pieter Schoenmakers
+/*     Eindhoven University of Technology
+/*     P.O. Box 513
+/*     5600 MB Eindhoven
+/*     The Netherlands
+/*--*/
+
 #include "sys_defs.h"
 
 #ifdef HAS_NETINFO
-#error "This requires contributed software from http://www.postfix.org/"
+
+/* System library. */
+
+#include <stdio.h>
+#include <netinfo/ni.h>
+
+/* Utility library. */
+
+#include "dict.h"
+#include "dict_ni.h"
+#include "msg.h"
+#include "mymalloc.h"
+
+typedef struct {
+    DICT    dict;                      /* my super */
+    char   *path;                      /* directory path */
+} DICT_NI;
+
+ /*
+  * We'd like other possibilities, but that is not possible in the current
+  * dictionary setup...  An example of a different setup: use `members' for
+  * multi-valued lookups (to be compatible with /aliases), and `value' for
+  * single-valued tables.
+  */
+#define NETINFO_PROP_KEY       "name"
+#define NETINFO_PROP_VALUE     "members"
+#define NETINFO_VALUE_SEP       ","
+
+#define NETINFO_MAX_DOMAIN_DEPTH       100
+
+/* Hard worker doing lookups.  Returned value is statically allocated and
+   reused each call.  */
+static const char *dict_ni_do_lookup(char *path, char *key_prop,
+                                      const char *key_value, char *val_prop)
+{
+    unsigned int result_cap = 0;
+    static char *result = 0;
+
+    char   *return_val = 0;
+    ni_namelist values;
+    int     depth = 0;
+    void   *domain;
+    void   *next_domain;
+    char   *query;
+    ni_status r;
+    ni_id   dir;
+
+    if (msg_verbose)
+       msg_info("ni_lookup %s %s=%s", path, key_prop, key_value);
+
+    r = ni_open(NULL, ".", &domain);
+    if (r != NI_OK) {
+       msg_warn("ni_open `.': %d", r);
+       return NULL;
+    }
+    query = alloca(strlen(path) + strlen(key_prop) + 3 + strlen(key_value));
+    sprintf(query, "%s/%s=%s", path, key_prop, key_value);
+
+    for (;;) {
+
+       /*
+        * What does it _mean_ if we find the directory but not the value?
+        */
+       if (ni_pathsearch(domain, &dir, query) == NI_OK
+           && ni_lookupprop(domain, &dir, val_prop, &values) == NI_OK)
+           if (values.ni_namelist_len <= 0)
+               ni_namelist_free(&values);
+           else {
+               unsigned int i,
+                       l,
+                       n;
+
+               for (i = l = 0; i < values.ni_namelist_len; i++)
+                   l += 1 + strlen(values.ni_namelist_val[i]);
+               if (result_cap < l) {
+                   if (result)
+                       myfree(result);
+                   result_cap = l + 100;
+                   result = mymalloc(result_cap);
+               }
+               for (i = l = 0; i < values.ni_namelist_len; i++) {
+                   n = strlen(values.ni_namelist_val[i]);
+                   memcpy(result + l, values.ni_namelist_val[i], n);
+                   l += n;
+                   if (i < values.ni_namelist_len - 1)
+                       result[l++] = ',';
+               }
+               result[l] = '\0';
+               return_val = result;
+               break;
+           }
+
+       if (++depth >= NETINFO_MAX_DOMAIN_DEPTH) {
+           msg_warn("ni_open: domain depth limit");
+           break;
+       }
+       r = ni_open(domain, "..", &next_domain);
+       if (r != NI_OK) {
+           if (r != NI_FAILED)
+               msg_warn("ni_open `..': %d", r);
+           break;
+       }
+       ni_free(domain);
+       domain = next_domain;
+    }
+
+    ni_free(domain);
+
+    return return_val;
+}
+
+/* dict_ni_lookup - find table entry */
+
+static const char *dict_ni_lookup(DICT *dict, const char *key)
+{
+    DICT_NI *d = (DICT_NI *) dict;
+
+    return dict_ni_do_lookup(d->path, NETINFO_PROP_KEY,
+                            key, NETINFO_PROP_VALUE);
+}
+
+/* dict_ni_update - add or update table entry (not!) */
+
+static void dict_ni_update(DICT *dict, const char *unused_name,
+                                  const char *unused_value)
+{
+    DICT_NI *d = (DICT_NI *) dict;
+
+    msg_fatal("dict_ni_update: unimplemented: update NetInfo directory %s",
+             d->path);
+}
+
+/* dict_ni_close - disassociate from NetInfo map */
+
+static void dict_ni_close(DICT *dict)
+{
+    DICT_NI *d = (DICT_NI *) dict;
+
+    myfree(d->path);
+    myfree((char *) d);
+}
+
+/* dict_ni_open - create association with NetInfo map */
+
+DICT   *dict_ni_open(const char *path, int unused_flags, int dict_flags)
+{
+    DICT_NI *d = (void *) mymalloc(sizeof(*d));
+
+    d->dict.lookup = dict_ni_lookup;
+    d->dict.update = dict_ni_update;
+    d->dict.close = dict_ni_close;
+    d->dict.fd = -1;
+    d->dict.flags = dict_flags;
+    d->path = mystrdup(path);
+
+    return &d->dict;
+}
+
 #endif
index 2ce9c2db28546222c0ef41d088c2962654df8dae..b0221a4b6e2181854a37ca87882d276006a416ff 100644 (file)
@@ -1,4 +1,32 @@
+#ifndef _DICT_NI_H_INCLUDED_
+#define _DICT_NI_H_INCLUDED_
+
+/*++
+/* NAME
+/*     dict_ni 3h
+/* SUMMARY
+/*     dictionary manager interface to NetInfo maps
+/* SYNOPSIS
+/*     #include <dict_ni.h>
+/* DESCRIPTION
+/* .nf
+
  /*
-  * The NetInfo software is not bundled with IBM's public release. It will be
-  * made available as contributed software from http://www.postfix.org/
+  * Utility library.
   */
+#include <dict.h>
+
+ /*
+  * External interface.
+  */
+extern DICT *dict_ni_open(const char *, int, int);
+
+/* AUTHOR(S)
+/*     Pieter Schoenmakers
+/*     Eindhoven University of Technology
+/*     P.O. Box 513
+/*     5600 MB Eindhoven
+/*     The Netherlands
+/*--*/
+
+#endif
index 0441183d9716db29a1c8636bf940cd03df757299..a042f32993620a13a454a9fbd129fccca2796134 100644 (file)
@@ -6,9 +6,10 @@
 /* SYNOPSIS
 /*     #include <dict_nis.h>
 /*
-/*     DICT    *dict_nis_open(map, dummy)
+/*     DICT    *dict_nis_open(map, dummy, dict_flags)
 /*     const char *map;
 /*     int     dummy;
+/*     int     dict_flags;
 /* DESCRIPTION
 /*     dict_nis_open() makes the specified NIS map accessible via
 /*     the generic dictionary operations described in dict_open(3).
@@ -67,9 +68,6 @@ typedef struct {
     int     flags;                     /* see below */
 } DICT_NIS;
 
-#define DICT_NIS_TRY0NULL        (1<<0)
-#define DICT_NIS_TRY1NULL        (1<<1)
-
  /*
   * Class variables, so that multiple maps can share this info.
   */
@@ -156,12 +154,12 @@ static const char *dict_nis_lookup(DICT *dict, const char *key)
      * See if this NIS map was written with one null byte appended to key and
      * value.
      */
-    if (dict_nis->flags & DICT_NIS_TRY1NULL) {
+    if (dict_nis->flags & DICT_FLAG_TRY1NULL) {
        err = yp_match(dict_nis_domain, dict_nis->map,
                       (void *) key, strlen(key) + 1,
                       &result, &result_len);
        if (err == 0) {
-           dict_nis->flags &= ~DICT_NIS_TRY0NULL;
+           dict_nis->flags &= ~DICT_FLAG_TRY0NULL;
            return (result);
        }
     }
@@ -170,12 +168,12 @@ static const char *dict_nis_lookup(DICT *dict, const char *key)
      * See if this NIS map was written with no null byte appended to key and
      * value. This should never be the case, but better play safe.
      */
-    if (dict_nis->flags & DICT_NIS_TRY0NULL) {
+    if (dict_nis->flags & DICT_FLAG_TRY0NULL) {
        err = yp_match(dict_nis_domain, dict_nis->map,
                       (void *) key, strlen(key),
                       &result, &result_len);
        if (err == 0) {
-           dict_nis->flags &= ~DICT_NIS_TRY1NULL;
+           dict_nis->flags &= ~DICT_FLAG_TRY1NULL;
            if (buf == 0)
                buf = vstring_alloc(10);
            vstring_strncpy(buf, result, result_len);
@@ -218,7 +216,7 @@ static void dict_nis_close(DICT *dict)
 
 /* dict_nis_open - open NIS map */
 
-DICT   *dict_nis_open(const char *map, int unused_flags)
+DICT   *dict_nis_open(const char *map, int unused_flags, int dict_flags)
 {
     DICT_NIS *dict_nis;
 
@@ -228,7 +226,9 @@ DICT   *dict_nis_open(const char *map, int unused_flags)
     dict_nis->dict.close = dict_nis_close;
     dict_nis->dict.fd = -1;
     dict_nis->map = mystrdup(map);
-    dict_nis->flags = (DICT_NIS_TRY1NULL | DICT_NIS_TRY0NULL);
+    dict_nis->dict.flags = dict_flags;
+    if ((dict_flags & (DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL)) == 0)
+       dict_nis->dict.flags |= (DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL);
     if (dict_nis_domain == 0)
        dict_nis_init();
     return (&dict_nis->dict);
index 498715f9f765a9c03cf7514b2ef805f61f3d7611..ff2759b7c5c1e98555bcad94ec8b4c8f80358e0f 100644 (file)
@@ -19,7 +19,7 @@
  /*
   * External interface.
   */
-extern DICT *dict_nis_open(const char *, int);
+extern DICT *dict_nis_open(const char *, int, int);
 
 /* LICENSE
 /* .ad
index 0949f540ce6eb3dae8448e1000217802840ae9bb..02a8790f12ae2256a8940cbdb596ce465750d837 100644 (file)
@@ -6,9 +6,10 @@
 /* SYNOPSIS
 /*     #include <dict_nisplus.h>
 /*
-/*     DICT    *dict_nisplus_open(map, dummy)
+/*     DICT    *dict_nisplus_open(map, dummy, dict_flags)
 /*     char    *map;
 /*     int     dummy;
+/*     int     dict_flags;
 /* DESCRIPTION
 /*     dict_nisplus_open() makes the specified NIS+ map accessible via
 /*     the generic dictionary operations described in dict_open(3).
@@ -76,7 +77,7 @@ static void dict_nisplus_close(DICT *dict)
 
 /* dict_nisplus_open - open NISPLUS map */
 
-DICT   *dict_nisplus_open(const char *map, int unused_flags)
+DICT   *dict_nisplus_open(const char *map, int unused_flags, int dict_flags)
 {
     DICT_NISPLUS *dict_nisplus;
 
@@ -86,5 +87,6 @@ DICT   *dict_nisplus_open(const char *map, int unused_flags)
     dict_nisplus->dict.close = dict_nisplus_close;
     dict_nisplus->dict.fd = -1;
     dict_nisplus->map = mystrdup(map);
+    dict_nisplus->dict.flags = dict_flags;
     return (&dict_nisplus->dict);
 }
index 5c7a7c10b83f7d346c9e044e58143de8bd233a52..f43b3141ba932232ea0af3ef1bb97984f0490c44 100644 (file)
@@ -19,7 +19,7 @@
  /*
   * External interface.
   */
-extern DICT *dict_nisplus_open(const char *, int);
+extern DICT *dict_nisplus_open(const char *, int, int);
 
 /* LICENSE
 /* .ad
index b30defc8680c00120b3c2cbd08a17f28cff1cd0b..3f91b647a4a4bdd6f404d38012450300c11f8308 100644 (file)
@@ -6,14 +6,16 @@
 /* SYNOPSIS
 /*     #include <dict.h>
 /*
-/*     DICT    *dict_open(dict_spec, flags)
+/*     DICT    *dict_open(dict_spec, open_flags, dict_flags)
 /*     const char *dict_spec;
-/*     int     flags;
+/*     int     open_flags;
+/*     int     dict_flags;
 /*
-/*     DICT    *dict_open3(dict_type, dict_name, flags)
+/*     DICT    *dict_open3(dict_type, dict_name, open_flags, dict_flags)
 /*     const char *dict_type;
 /*     const char *dict_name;
-/*     int     flags;
+/*     int     open_flags;
+/*     int     dict_flags;
 /*
 /*     void    dict_put(dict, key, value)
 /*     DICT    *dict;
 /*
 /*     dict_open() takes a type:name pair that specifies a dictionary type
 /*     and dictionary name, opens the dictionary, and returns a dictionary
-/*     handle.  The \fIflags\fR arguments are as in open(2). The dictionary
-/*     types are as follows:
+/*     handle.  The \fIopen_flags\fR arguments are as in open(2). The
+/*     \fIdict_flags\fR are the bit-wise OR of zero or more of the following:
+/* .IP DICT_FLAG_DUP_WARN
+/*     Warn about duplicate keys, if the underlying database does not
+/*     support duplicate keys. The default is to terminate with a fatal
+/*     error.
+/* .IP DICT_FLAG_DUP_IGNORE
+/*     Ignore duplicate keys if the underlying database does not
+/*     support duplicate keys. The default is to terminate with a fatal
+/*     error.
+/* .PP
+/*     The dictionary types are as follows:
 /* .IP environ
 /*     The process environment array. The \fIdict_name\fR argument is ignored.
 /* .IP dbm
@@ -52,6 +64,8 @@
 /*     LDAP ("light-weight" directory access protocol) database access.
 /* .IP pcre
 /*     PERL-compatible regular expressions.
+/* .IP regexp
+/*     POSIX-compatible regular expressions.
 /* .PP
 /*     dict_open3() takes separate arguments for dictionary type and
 /*     name, but otherwise performs the same functions as dict_open().
 #include <dict_ni.h>
 #include <dict_ldap.h>
 #include <dict_pcre.h>
+#include <dict_regexp.h>
 #include <stringops.h>
 #include <split_at.h>
 
   */
 typedef struct {
     char   *type;
-    struct DICT *(*open) (const char *, int);
+    struct DICT *(*open) (const char *, int, int);
 } DICT_OPEN_INFO;
 
 static DICT_OPEN_INFO dict_open_info[] = {
@@ -138,13 +153,16 @@ static DICT_OPEN_INFO dict_open_info[] = {
 #endif
 #ifdef HAS_PCRE
     "pcre", dict_pcre_open,
+#endif
+#ifdef HAS_POSIX_REGEXP
+    "regexp", dict_regexp_open,
 #endif
     0,
 };
 
 /* dict_open - open dictionary */
 
-DICT   *dict_open(const char *dict_spec, int flags)
+DICT   *dict_open(const char *dict_spec, int open_flags, int dict_flags)
 {
     char   *saved_dict_spec = mystrdup(dict_spec);
     char   *dict_name;
@@ -153,7 +171,7 @@ DICT   *dict_open(const char *dict_spec, int flags)
     if ((dict_name = split_at(saved_dict_spec, ':')) == 0)
        msg_fatal("open dictionary: need \"type:name\" form: %s", dict_spec);
 
-    dict = dict_open3(saved_dict_spec, dict_name, flags);
+    dict = dict_open3(saved_dict_spec, dict_name, open_flags, dict_flags);
     myfree(saved_dict_spec);
     return (dict);
 }
@@ -161,7 +179,8 @@ DICT   *dict_open(const char *dict_spec, int flags)
 
 /* dict_open3 - open dictionary */
 
-DICT   *dict_open3(const char *dict_type, const char *dict_name, int flags)
+DICT   *dict_open3(const char *dict_type, const char *dict_name,
+                          int open_flags, int dict_flags)
 {
     char   *myname = "dict_open";
     DICT_OPEN_INFO *dp;
@@ -169,7 +188,7 @@ DICT   *dict_open3(const char *dict_type, const char *dict_name, int flags)
 
     for (dp = dict_open_info; dp->type; dp++) {
        if (strcasecmp(dp->type, dict_type) == 0) {
-           if ((dict = dp->open(dict_name, flags)) == 0)
+           if ((dict = dp->open(dict_name, open_flags, dict_flags)) == 0)
                msg_fatal("opening %s:%s %m", dict_type, dict_name);
            if (msg_verbose)
                msg_info("%s: %s:%s", myname, dict_type, dict_name);
@@ -207,7 +226,7 @@ main(int argc, char **argv)
     VSTRING *keybuf = vstring_alloc(1);
     DICT   *dict;
     char   *dict_name;
-    int     dict_flags;
+    int     open_flags;
     char   *key;
     const char *value;
 
@@ -215,15 +234,15 @@ main(int argc, char **argv)
     if (argc != 3)
        msg_fatal("usage: %s type:file read|write|create", argv[0]);
     if (strcasecmp(argv[2], "create") == 0)
-       dict_flags = O_CREAT | O_RDWR | O_TRUNC;
+       open_flags = O_CREAT | O_RDWR | O_TRUNC;
     else if (strcasecmp(argv[2], "write") == 0)
-       dict_flags = O_RDWR;
+       open_flags = O_RDWR;
     else if (strcasecmp(argv[2], "read") == 0)
-       dict_flags = O_RDONLY;
+       open_flags = O_RDONLY;
     else
        msg_fatal("unknown access mode: %s", argv[2]);
     dict_name = argv[1];
-    dict = dict_open(dict_name, dict_flags);
+    dict = dict_open(dict_name, open_flags, 0);
     while (vstring_fgets_nonl(keybuf, VSTREAM_IN)) {
        if ((key = strtok(vstring_str(keybuf), " =")) == 0)
            continue;
index ebfc770367fc2d4da489b0a00ead7ea8e7ffed1c..d2e6121db95883bcb42027a74e21fb24884e9556 100644 (file)
@@ -6,9 +6,10 @@
 /* SYNOPSIS
 /*     #include <dict_pcre.h>
 /*
-/*     DICT    *dict_pcre_open(name, flags)
+/*     DICT    *dict_pcre_open(name, dummy, dict_flags)
 /*     const char *name;
-/*     int     flags;
+/*     int     dummy;
+/*     int     dict_flags;
 /* DESCRIPTION
 /*     dict_pcre_open() opens the named file and compiles the contained
 /*     regular expressions.
 /*      The lookup interface will match only user@domain form addresses.
 /* SEE ALSO
 /*     dict(3) generic dictionary manager
-/* LICENSE
-/* .ad
-/* .fi
-/*     The Secure Mailer license must be distributed with this software.
 /* AUTHOR(S)
 /*     Andrew McNamara
 /*     andrewm@connect.com.au
@@ -261,12 +258,12 @@ DICT   *dict_pcre_open(const char *map, int unused_flags)
     dict_pcre->dict.close = dict_pcre_close;
     dict_pcre->dict.fd = -1;
     dict_pcre->map = mystrdup(map);
-    dict_pcre->flags = 0;
+    dict_pcre->dict.flags = dict_flags;
     dict_pcre->head = NULL;
 
     if (dict_pcre_init == 0) {
-       pcre_malloc = (void *(*)(size_t)) mymalloc;
-       pcre_free = (void (*)(void *)) myfree;
+       pcre_malloc = (void *(*) (size_t)) mymalloc;
+       pcre_free = (void (*) (void *)) myfree;
        dict_pcre_init = 1;
     }
     if ((map_fp = vstream_fopen(map, O_RDONLY, 0)) == 0) {
@@ -374,12 +371,12 @@ DICT   *dict_pcre_open(const char *map, int unused_flags)
        else
            pcre_list->next = pl;
        pcre_list = pl;
-}
+    }
 
-vstring_free(line_buffer);
-vstream_fclose(map_fp);
+    vstring_free(line_buffer);
+    vstream_fclose(map_fp);
 
-return (&dict_pcre->dict);
+    return (&dict_pcre->dict);
 }
 
 #endif                                 /* HAS_PCRE */
index 2c6c118a6347cd239ace17563833b66673a235c1..253c69e78f57acdfe0ee74d355b52aa4ff427eef 100644 (file)
@@ -19,7 +19,7 @@
  /*
   * External interface.
   */
-extern DICT *dict_pcre_open(const char *, int);
+extern DICT *dict_pcre_open(const char *, int, int);
 
 /* LICENSE
 /* .ad
diff --git a/postfix/util/dict_regexp.c b/postfix/util/dict_regexp.c
new file mode 100644 (file)
index 0000000..b3c4024
--- /dev/null
@@ -0,0 +1,408 @@
+/*++
+/* NAME
+/*     dict_regexp 3
+/* SUMMARY
+/*     dictionary manager interface to REGEXP regular expression library
+/* SYNOPSIS
+/*     #include <dict_regexp.h>
+/*
+/*     DICT    *dict_regexp_open(name, dummy, dict_flags)
+/*     const char *name;
+/*     int     dummy;
+/*     int     dict_flags;
+/* DESCRIPTION
+/*     dict_regexp_open() opens the named file and compiles the contained
+/*     regular expressions.
+/*
+/*      The lookup interface will match only user@domain form addresses.
+/* SEE ALSO
+/*     dict(3) generic dictionary manager
+/* AUTHOR(S)
+/*     LaMont Jones
+/*     lamont@hp.com
+/*
+/*     Based on PCRE dictionary contributed by Andrew McNamara
+/*     andrewm@connect.com.au
+/*     connect.com.au Pty. Ltd.
+/*     Level 3, 213 Miller St
+/*     North Sydney, NSW, Australia
+/*
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include "sys_defs.h"
+
+#ifdef HAS_POSIX_REGEXP
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+#include <regex.h>
+
+/* Utility library. */
+
+#include "mymalloc.h"
+#include "msg.h"
+#include "safe.h"
+#include "vstream.h"
+#include "vstring.h"
+#include "stringops.h"
+#include "readline.h"
+#include "dict.h"
+#include "dict_regexp.h"
+#include "mac_parse.h"
+
+typedef struct dict_regexp_list {
+    struct dict_regexp_list *next;     /* Next regexp in dict */
+    regex_t *expr[2];                  /* The compiled pattern(s) */
+    char   *replace;                   /* Replacement string */
+    int     lineno;                    /* Source file line number */
+} DICT_REGEXP_RULE;
+
+typedef struct {
+    DICT    dict;                      /* generic members */
+    char   *map;                       /* map name */
+    int     flags;                     /* unused at the moment */
+    regmatch_t *pmatch;                        /* Cut substrings */
+    int     nmatch;                    /* number of elements in pmatch */
+    DICT_REGEXP_RULE *head;            /* first rule */
+} DICT_REGEXP;
+
+/*
+ * Context for macro expansion callback.
+ */
+struct dict_regexp_context {
+    DICT_REGEXP *dict;                 /* the dictionary entry */
+    DICT_REGEXP_RULE *rule;            /* the rule we matched */
+    VSTRING *buf;                      /* target string buffer */
+    const char *subject;               /* str against which we match */
+};
+
+/*
+ *  dict_regexp_update - not supported
+ */
+static void dict_regexp_update(DICT *dict, const char *unused_name,
+                                      const char *unused_value)
+{
+    DICT_REGEXP *dict_regexp = (DICT_REGEXP *) dict;
+
+    msg_fatal("dict_regexp_update: attempt to update regexp map %s",
+             dict_regexp->map);
+}
+
+/*
+ * Macro expansion callback - replace $0-${99} with strings cut from
+ * matched string.
+ */
+static void dict_regexp_action(int type, VSTRING *buf, char *ptr)
+{
+    struct dict_regexp_context *ctxt = (struct dict_regexp_context *) ptr;
+    DICT_REGEXP_RULE *rule = ctxt->rule;
+    DICT_REGEXP *dict = ctxt->dict;
+    int     n;
+
+    if (type == MAC_PARSE_VARNAME) {
+       n = atoi(vstring_str(buf));
+       if (n >= dict->nmatch) {
+           msg_warn("regexp %s, line %d: replace index out of range",
+                    dict->map, rule->lineno);
+           return;
+       }
+       if (dict->pmatch[n].rm_so < 0 ||
+           dict->pmatch[n].rm_so == dict->pmatch[n].rm_eo) {
+           return;                             /* empty string or not
+                                                * matched */
+       }
+       vstring_strncat(ctxt->buf, ctxt->subject + dict->pmatch[n].rm_so,
+                       dict->pmatch[n].rm_eo - dict->pmatch[n].rm_so);
+    } else
+       /* Straight text - duplicate with no substitution */
+       vstring_strcat(ctxt->buf, vstring_str(buf));
+}
+
+/*
+ * Look up regexp dict and perform string substitution on matched
+ * strings.
+ */
+static const char *dict_regexp_lookup(DICT *dict, const char *name)
+{
+    DICT_REGEXP *dict_regexp = (DICT_REGEXP *) dict;
+    DICT_REGEXP_RULE *rule;
+    struct dict_regexp_context ctxt;
+    static VSTRING *buf;
+    char   *at;
+    int     error;
+
+    /* msg_info("dict_regexp_lookup: %s: %s", dict_regexp->map, name ); */
+
+    /*
+     * XXX Require user@domain, to defeat partial address matching for smtp
+     * access control, canonical and virtual mappings, and to prevent regexps
+     * from being used as alias databases because one might inadvertently
+     * copy "|command" or /file/name or :include: to the result.
+     */
+    if (name[0] == '@' || (at = strrchr(name, '@')) == 0 || at[1] == 0)
+       return (0);
+
+    /* Search for a matching expression */
+    for (rule = dict_regexp->head; rule; rule = rule->next) {
+       error = regexec(rule->expr[0], name, rule->expr[0]->re_nsub + 1,
+                       dict_regexp->pmatch, 0);
+       if (!error) {
+           if (rule->expr[1]) {
+               error = regexec(rule->expr[1], name, rule->expr[1]->re_nsub + 1,
+                      dict_regexp->pmatch + rule->expr[0]->re_nsub + 1, 0);
+               if (!error) {
+                   continue;
+               } else if (error != REG_NOMATCH) {
+                   char    errbuf[256];
+
+                   (void) regerror(error, rule->expr[1], errbuf, sizeof(errbuf));
+                   msg_fatal("regexp map %s, line %d: %s.",
+                             dict_regexp->map, rule->lineno, errbuf);
+               }
+           }
+
+           /*
+            * We found a match. Do some final initialization on the
+            * subexpression fields, and perform substitution on replacement
+            * string
+            */
+           if (!buf)
+               buf = vstring_alloc(10);
+           VSTRING_RESET(buf);
+           ctxt.buf = buf;
+           ctxt.subject = name;
+           ctxt.rule = rule;
+           ctxt.dict = dict_regexp;
+
+           mac_parse(rule->replace, dict_regexp_action, (char *) &ctxt);
+
+           VSTRING_TERMINATE(buf);
+           return (vstring_str(buf));
+       } else if (error && error != REG_NOMATCH) {
+           char    errbuf[256];
+
+           (void) regerror(error, rule->expr[0], errbuf, sizeof(errbuf));
+           msg_fatal("regexp map %s, line %d: %s.",
+                     dict_regexp->map, rule->lineno, errbuf);
+           return ((char *) 0);
+       }
+    }
+    return ((char *) 0);
+}
+
+/* dict_regexp_close - close regexp dictionary */
+
+static void dict_regexp_close(DICT *dict)
+{
+    DICT_REGEXP *dict_regexp = (DICT_REGEXP *) dict;
+    DICT_REGEXP_RULE *rule,
+           *next;
+    int     i;
+
+    for (rule = dict_regexp->head; rule; rule = next) {
+       next = rule->next;
+       for (i = 0; i < 2; i++) {
+           if (rule->expr[i]) {
+               regfree(rule->expr[i]);
+               myfree((char *) rule->expr[i]);
+           }
+       }
+       myfree((char *) rule->replace);
+       myfree((char *) rule);
+    }
+    myfree((char *) dict_regexp);
+}
+
+static regex_t *dict_regexp_get_expr(int lineno, char **bufp, VSTREAM *map_fp)
+{
+    char   *p = *bufp,
+           *regexp,
+            re_delim;
+    int     re_options,
+            error;
+    regex_t *expr;
+
+    re_delim = *p++;
+    regexp = p;
+
+    /* Search for second delimiter, handling backslash escape */
+    while (*p) {
+       if (*p == '\\') {
+           if (p[1])
+               p++;
+           else
+               break;
+       } else if (*p == re_delim) {
+           break;
+       }
+       ++p;
+    }
+    if (!*p) {
+       msg_warn("%s, line %d: no closing regexp delimiter: %c",
+                VSTREAM_PATH(map_fp), lineno, re_delim);
+       return NULL;
+    }
+    *p++ = '\0';                               /* Null term the regexp */
+
+    re_options = REG_EXTENDED | REG_ICASE;
+    while (*p) {
+       if (!*p || ISSPACE(*p) || (*p == '!' && p[1] == re_delim)) {
+           /* end of the regexp */
+           expr = (regex_t *) mymalloc(sizeof(*expr));
+           error = regcomp(expr, regexp, re_options);
+           if (error != 0) {
+               char    errbuf[256];
+
+               (void) regerror(error, expr, errbuf, sizeof(errbuf));
+               msg_warn("%s, line %d: error in regexp: %s.",
+                        VSTREAM_PATH(map_fp), lineno, errbuf);
+               myfree((char *) expr);
+               return NULL;
+           }
+           *bufp = p;
+           return expr;
+       } else {
+           switch (*p) {
+           case 'i':
+               re_options ^= REG_ICASE;
+               break;
+           case 'm':
+               re_options ^= REG_NEWLINE;
+               break;
+           case 'x':
+               re_options ^= REG_EXTENDED;
+               break;
+           default:
+               msg_warn("%s, line %d: unknown regexp option '%c'",
+                        VSTREAM_PATH(map_fp), lineno, *p);
+           }
+           ++p;
+       }
+    }
+    return NULL;
+}
+
+static DICT_REGEXP_RULE *dict_regexp_parseline(int lineno, char *line, int *nsub, VSTREAM *map_fp)
+{
+    DICT_REGEXP_RULE *rule;
+    char   *p,
+            re_delim;
+    regex_t *expr1,
+           *expr2;
+    int     total_nsub;
+
+    p = line;
+    re_delim = *p;
+
+    expr1 = dict_regexp_get_expr(lineno, &p, map_fp);
+    if (!expr1) {
+       return NULL;
+    } else if (*p == '!' && p[1] == re_delim) {
+       p++;
+       expr2 = dict_regexp_get_expr(lineno, &p, map_fp);
+       if (!expr2) {
+           myfree((char *) expr1);
+           return NULL;
+       }
+       total_nsub = expr1->re_nsub + expr2->re_nsub + 2;
+    } else {
+       expr2 = NULL;
+       total_nsub = expr1->re_nsub + 1;
+    }
+    if (nsub)
+       *nsub = total_nsub;
+
+    if (!ISSPACE(*p)) {
+       msg_warn("%s, line %d: Too many expressions.",
+                VSTREAM_PATH(map_fp), lineno);
+       myfree((char *) expr1);
+       if (expr2)
+           myfree((char *) expr2);
+       return NULL;
+    }
+    rule = (DICT_REGEXP_RULE *) mymalloc(sizeof(DICT_REGEXP_RULE));
+
+    while (*p && ISSPACE(*p))
+       ++p;
+
+    if (!*p) {
+       msg_warn("%s, line %d: no replacement text: using empty string",
+                VSTREAM_PATH(map_fp), lineno);
+       p = "";
+    }
+    rule->expr[0] = expr1;
+    rule->expr[1] = expr2;
+    rule->replace = mystrdup(p);
+    rule->lineno = lineno;
+    return rule;
+}
+
+/*
+ * dict_regexp_open - load and compile a file containing regular expressions
+ */
+DICT   *dict_regexp_open(const char *map, int unused_flags, int dict_flags)
+{
+    DICT_REGEXP *dict_regexp;
+    VSTREAM *map_fp;
+    VSTRING *line_buffer;
+    DICT_REGEXP_RULE *rule,
+           *last_rule = NULL;
+    int     lineno = 0;
+    int     max_nsub = 0;
+    int     nsub;
+    char   *p;
+
+    line_buffer = vstring_alloc(100);
+
+    dict_regexp = (DICT_REGEXP *) mymalloc(sizeof(*dict_regexp));
+    dict_regexp->dict.lookup = dict_regexp_lookup;
+    dict_regexp->dict.update = dict_regexp_update;
+    dict_regexp->dict.close = dict_regexp_close;
+    dict_regexp->dict.fd = -1;
+    dict_regexp->map = mystrdup(map);
+    dict_regexp->dict.flags = dict_flags;
+
+    if ((map_fp = vstream_fopen(map, O_RDONLY, 0)) == 0) {
+       msg_fatal("open %s: %m", map);
+    }
+    while (readline(line_buffer, map_fp, &lineno)) {
+       p = vstring_str(line_buffer);
+
+       if (*p == '#')                          /* Skip comments */
+           continue;
+
+       if (*p == 0)                            /* Skip blank lines */
+           continue;
+
+       rule = dict_regexp_parseline(lineno, p, &nsub, map_fp);
+       if (rule) {
+           if (nsub > max_nsub)
+               max_nsub = nsub;
+
+           if (last_rule == NULL)
+               dict_regexp->head = rule;
+           else
+               last_rule->next = rule;
+           last_rule = rule;
+       }
+    }
+    last_rule->next = NULL;
+
+    dict_regexp->pmatch = (regmatch_t *) mymalloc(sizeof(regmatch_t) * max_nsub);
+    dict_regexp->nmatch = max_nsub;
+
+    vstring_free(line_buffer);
+    vstream_fclose(map_fp);
+
+    return (&dict_regexp->dict);
+}
+
+#endif                                 /* NO_POSIX_REGEXP */
diff --git a/postfix/util/dict_regexp.h b/postfix/util/dict_regexp.h
new file mode 100644 (file)
index 0000000..f487bed
--- /dev/null
@@ -0,0 +1,40 @@
+#ifndef _DICT_REGEXP_H_INCLUDED_
+#define _DICT_REGEXP_H_INCLUDED_
+
+/*++
+/* NAME
+/*     dict_regexp 3h
+/* SUMMARY
+/*     dictionary manager interface to REGEXP regular expression library
+/* SYNOPSIS
+/*     #include <dict_regexp.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+  * Utility library.
+  */
+#include <dict.h>
+
+ /*
+  * External interface.
+  */
+extern DICT *dict_regexp_open(const char *, int, int);
+
+/* AUTHOR(S)
+/*     LaMont Jones
+/*     lamont@hp.com
+/*
+/*     Based on PCRE dictionary contributed by Andrew McNamara
+/*     andrewm@connect.com.au
+/*     connect.com.au Pty. Ltd.
+/*     Level 3, 213 Miller St
+/*     North Sydney, NSW, Australia
+/*
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+#endif
index 82f36b8050f23d414786a75ab4face251fbf83b5..efc94513047afc21a25a23168b20641361bcf033 100644 (file)
@@ -6,9 +6,10 @@
 /* SYNOPSIS
 /*     #include <dict_unix.h>
 /*
-/*     DICT    *dict_unix_open(map, dummy)
+/*     DICT    *dict_unix_open(map, dummy, dict_flags)
 /*     const char *map;
 /*     int     dummy;
+/*     int     dict_flags;
 /* DESCRIPTION
 /*     dict_unix_open() makes the specified UNIX table accessible via
 /*     the generic dictionary operations described in dict_open(3).
@@ -96,7 +97,7 @@ static void dict_unix_close(DICT *dict)
 
 /* dict_unix_open - open UNIX map */
 
-DICT   *dict_unix_open(const char *map, int unused_flags)
+DICT   *dict_unix_open(const char *map, int unused_flags, int dict_flags)
 {
     DICT_UNIX *dict_unix;
     struct dict_unix_lookup {
@@ -121,5 +122,6 @@ DICT   *dict_unix_open(const char *map, int unused_flags)
     dict_unix->dict.close = dict_unix_close;
     dict_unix->dict.fd = -1;
     dict_unix->map = mystrdup(map);
+    dict_unix->dict.flags = dict_flags;
     return (&dict_unix->dict);
 }
index c0cce81a58d7395e92dff07a4f0a757b65fc278e..b82a1ec8fee722ec58e206c67e344f7dfcca4340 100644 (file)
@@ -19,7 +19,7 @@
  /*
   * External interface.
   */
-extern DICT *dict_unix_open(const char *, int);
+extern DICT *dict_unix_open(const char *, int, int);
 
 /* LICENSE
 /* .ad
index f93f6d5919d886a51cbf46750c22d71e751b95b5..cec1a865cf0e98806846945a894a56c3c83f517c 100644 (file)
  /*
-  * The environ.c module from TCP Wrappers is not bundled with IBM's public
-  * release. It will be made available as contributed software from
-  * http://www.postfix.org/
+  * From: TCP Wrapper.
+  * 
+  * Many systems have putenv() but no setenv(). Other systems have setenv() but
+  * no putenv() (MIPS). Still other systems have neither (NeXT). This is a
+  * re-implementation that hopefully ends all problems.
+  * 
+  * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
   */
 #include "sys_defs.h"
 
 #ifdef MISSING_SETENV_PUTENV
-#error "This requires contributed software from http://www.postfix.org/"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+extern char **environ;
+
+static int addenv(char *);             /* append entry to environment */
+static int allocated = 0;              /* environ is, or is not, allocated */
+
+#define DO_CLOBBER      1
+
+/* namelength - determine length of name in "name=whatever" */
+
+static int namelength(const char *name)
+{
+    char   *equal;
+
+    equal = strchr(name, '=');
+    return ((equal == 0) ? strlen(name) : (equal - name));
+}
+
+/* findenv - given name, locate name=value */
+
+static char **findenv(const char *name, int len)
+{
+    char  **envp;
+
+    for (envp = environ; envp && *envp; envp++)
+       if (strncmp(name, *envp, len) == 0 && (*envp)[len] == '=')
+           return (envp);
+    return (0);
+}
+
+#if 0
+
+/* getenv - given name, locate value */
+
+char   *getenv(const char *name)
+{
+    int     len = namelength(name);
+    char  **envp = findenv(name, len);
+
+    return (envp ? *envp + len + 1 : 0);
+}
+
+/* putenv - update or append environment (name,value) pair */
+
+int     putenv(const char *nameval)
+{
+    char   *equal = strchr(nameval, '=');
+    char   *value = (equal ? equal : "");
+
+    return (setenv(nameval, value, DO_CLOBBER));
+}
+
+/* unsetenv - remove variable from environment */
+
+void    unsetenv(const char *name)
+{
+    char  **envp;
+
+    while ((envp = findenv(name, namelength(name))) != 0)
+       while (envp[0] = envp[1])
+           envp++;
+}
+
+#endif
+
+/* setenv - update or append environment (name,value) pair */
+
+int     setenv(const char *name, const char *value, int clobber)
+{
+    char   *destination;
+    char  **envp;
+    int     l_name;                    /* length of name part */
+    unsigned int l_nameval;            /* length of name=value */
+
+    /* Permit name= and =value. */
+
+    l_name = namelength(name);
+    envp = findenv(name, l_name);
+    if (envp != 0 && clobber == 0)
+       return (0);
+    if (*value == '=')
+       value++;
+    l_nameval = l_name + strlen(value) + 1;
+
+    /*
+     * Use available memory if the old value is long enough. Never free an
+     * old name=value entry because it may not be allocated.
+     */
+
+    destination = (envp != 0 && strlen(*envp) >= l_nameval) ?
+       *envp : malloc(l_nameval + 1);
+    if (destination == 0)
+       return (-1);
+    strncpy(destination, name, l_name);
+    destination[l_name] = '=';
+    strcpy(destination + l_name + 1, value);
+    return ((envp == 0) ? addenv(destination) : (*envp = destination, 0));
+}
+
+/* cmalloc - malloc and copy block of memory */
+
+static char *cmalloc(int new_len, char *old, int old_len)
+{
+    char   *new = malloc(new_len);
+
+    if (new != 0)
+       memcpy(new, old, old_len);
+    return (new);
+}
+
+/* addenv - append environment entry */
+
+static int addenv(char *nameval)
+{
+    char  **envp;
+    int     n_used;                    /* number of environment entries */
+    int     l_used;                    /* bytes used excl. terminator */
+    int     l_need;                    /* bytes needed incl. terminator */
+
+    for (envp = environ; envp && *envp; envp++)
+        /* void */ ;
+    n_used = envp - environ;
+    l_used = n_used * sizeof(*envp);
+    l_need = l_used + 2 * sizeof(*envp);
+
+    envp = allocated ?
+       (char **) realloc((char *) environ, l_need) :
+       (char **) cmalloc(l_need, (char *) environ, l_used);
+    if (envp == 0) {
+       return (-1);
+    } else {
+       allocated = 1;
+       environ = envp;
+       environ[n_used++] = nameval;            /* add new entry */
+       environ[n_used] = 0;                    /* terminate list */
+       return (0);
+    }
+}
+
 #endif
index 1ced1d8064c7cefe9212a4464caf8fd62cf5ecd0..22f0a16ba18a74e908f31556e2e56a63b4065a9c 100644 (file)
@@ -109,7 +109,7 @@ static ARGV *match_list_parse(ARGV *list, char *string)
        } else if (strchr(pattern, ':') != 0) { /* type:table */
            for (cp = pattern; *cp == '!'; cp++)
                 /* void */ ;
-           dict_register(pattern, dict_open(pattern, 0));
+           dict_register(pattern, dict_open(pattern, 0, 0));
            argv_add(list, pattern, (char *) 0);
        } else {                                /* other pattern */
            argv_add(list, pattern, (char *) 0);
index b7029ddb640021d251f88efc9cddfe4ffdce81a8..8ccddf0f790877934a84d5acd991725d390b966c 100644 (file)
- /*
-  * The NETXSTEP and OPENSTEP software is not bundled with IBM's public
-  * release. It will be made available as contributed software from
-  * http://www.postfix.org/
-  */
+/*++
+/* NAME
+/*     posix_signals 3
+/* SUMMARY
+/*     POSIX signal handling compatibility
+/* SYNOPSIS
+/*     #include <posix_signals.h>
+/*
+/*     int     sigemptyset(m)
+/*     sigset_t *m;
+/*
+/*     int     sigaddset(set, signum)
+/*     sigset_t *set;
+/*     int     signum;
+/*
+/*     int     sigprocmask(how, set, old)
+/*     int     how;
+/*     sigset_t *set;
+/*     sigset_t *old;
+/*
+/*     int     sigaction(sig, act, oact)
+/*     int     sig;
+/*     struct sigaction *act;
+/*     struct sigaction *oact;
+/* DESCRIPTION
+/*     These routines emulate the POSIX signal handling interface.
+/* AUTHOR(S)
+/*     Pieter Schoenmakers
+/*     Eindhoven University of Technology
+/*     P.O. Box 513
+/*     5600 MB Eindhoven
+/*     The Netherlands
+/*--*/
+
+/* System library. */
+
 #include "sys_defs.h"
+#include <signal.h>
+#include <errno.h>
+
+/* Utility library.*/
+
+#include "posix_signals.h"
 
 #ifdef MISSING_SIGSET_T
-#error "This requires contributed software from http://www.postfix.org/"
+
+int     sigemptyset(sigset_t *m)
+{
+    return *m = 0;
+}
+
+int     sigaddset(sigset_t *set, int signum)
+{
+    *set |= sigmask(signum);
+    return 0;
+}
+
+int     sigprocmask(int how, sigset_t *set, sigset_t *old)
+{
+    int previous;
+
+    if (how == SIG_BLOCK)
+       previous = sigblock(*set);
+    else if (how == SIG_SETMASK)
+       previous = sigsetmask(*set);
+    else if (how == SIG_UNBLOCK) {
+       int     m = sigblock(0);
+
+       previous = sigsetmask(m & ~*set);
+    } else {
+       errno = EINVAL;
+       return -1;
+    }
+
+    if (old)
+       *old = previous;
+    return 0;
+}
+
 #endif
 
 #ifdef MISSING_SIGACTION
-#error "This requires contributed software from http://www.postfix.org/"
-#endif
 
+static struct sigaction actions[NSIG] = {};
+
+static int sighandle(int signum)
+{
+    if (signum == SIGCHLD) {
+       /* XXX If the child is just stopped, don't invoke the handler.   */
+    }
+    actions[signum].sa_handler(signum);
+}
+
+int     sigaction(int sig, struct sigaction *act, struct sigaction *oact)
+{
+    static int initialized = 0;
+
+    if (!initialized) {
+       int     i;
+
+       for (i = 0; i < NSIG; i++)
+           actions[i].sa_handler = SIG_DFL;
+       initialized = 1;
+    }
+    if (sig <= 0 || sig >= NSIG) {
+       errno = EINVAL;
+       return -1;
+    }
+    if (oact)
+       *oact = actions[sig];
+
+    {
+       struct sigvec mine = {
+           sighandle, act->sa_mask,
+           act->sa_flags & SA_RESTART ? SV_INTERRUPT : 0
+       };
+
+       if (sigvec(sig, &mine, NULL))
+           return -1;
+    }
+
+    actions[sig] = *act;
+    return 0;
+}
+
+#endif
index a2f6bbf6fe0711d67daf9f9c4a7de3ae8c6b5a6e..12c1664dba179712bbf392d89abced7b9e5ab15f 100644 (file)
@@ -1,5 +1,59 @@
+#ifndef _POSIX_SIGNALS_H_INCLUDED_
+#define _POSIX_SIGNALS_H_INCLUDED_
+/*++
+/* NAME
+/*     posix_signals 3h
+/* SUMMARY
+/*     POSIX signal handling compatibility
+/* SYNOPSIS
+/*     #include <posix_signals.h>
+/* DESCRIPTION
+/* .nf
+
  /*
-  * The NETXSTEP and OPENSTEP software is not bundled with IBM's public
-  * release. It will be made available as contributed software from
-  * http://www.postfix.org/
+  * Compatibility interface.
   */
+
+#ifdef MISSING_SIGSET_T
+
+typedef int sigset_t;
+
+enum {
+    SIG_BLOCK,
+    SIG_UNBLOCK,
+    SIG_SETMASK
+};
+
+extern int sigemptyset(sigset_t *);
+extern int sigaddset(sigset_t *, int);
+extern int sigprocmask(int, sigset_t *, sigset_t *);
+
+#endif
+
+#ifdef MISSING_SIGACTION
+
+struct sigaction {
+    void    (*sa_handler) ();
+    sigset_t sa_mask;
+    int     sa_flags;
+};
+
+ /* Possible values for sa_flags.  Or them to set multiple.  */
+enum {
+    SA_RESTART,
+    SA_NOCLDSTOP = 4                   /* drop the = 4.  */
+};
+
+extern int sigaction(int, struct sigaction *, struct sigaction *);
+
+#endif
+
+/* AUTHOR(S)
+/*     Pieter Schoenmakers
+/*     Eindhoven University of Technology
+/*     P.O. Box 513
+/*     5600 MB Eindhoven
+/*     The Netherlands
+/*--*/
+
+#endif
index 3d5c4ad29f4c25c2f1531550adedf6d67e75c68f..f0bbee356f833447f10cbd75c1083360c3a68cde 100644 (file)
@@ -36,6 +36,7 @@
 #define ROOT_PATH      "/bin:/usr/bin:/sbin:/usr/sbin"
 #define USE_STATFS
 #define STATFS_IN_SYS_MOUNT_H
+#define HAS_POSIX_REGEXP
 #endif
 
 #if defined(OPENBSD2)
@@ -285,6 +286,7 @@ extern int initgroups(const char *, int);
 #define STATFS_IN_SYS_VFS_H
 #define UNIX_DOMAIN_CONNECT_BLOCKS_FOR_ACCEPT
 #define PREPEND_PLUS_TO_OPTSTRING
+#define HAS_POSIX_REGEXP
 #endif
 
  /*