]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
snapshot-20000823
authorWietse Venema <wietse@porcupine.org>
Wed, 23 Aug 2000 00:00:00 +0000 (00:00 +0000)
committerWietse Venema <wietse@porcupine.org>
Thu, 17 Jan 2013 23:12:19 +0000 (18:12 -0500)
postfix/HISTORY
postfix/global/mail_version.h
postfix/util/.indent.pro
postfix/util/Makefile.in
postfix/util/dict_open.c
postfix/util/dict_tcp.c [new file with mode: 0644]
postfix/util/dict_tcp.h [new file with mode: 0644]
postfix/util/hex_quote.c [new file with mode: 0644]
postfix/util/hex_quote.h [new file with mode: 0644]
postfix/util/sys_defs.h

index 6116015b312584877b58dc4c1c2a66d772b873e1..106f87a42690c97e0d300a619ea17e9f2d41ff27 100644 (file)
@@ -4147,3 +4147,12 @@ Apologies for any names omitted.
        that cannot be represented with the off_t type that is used
        by standard functions such as lseek(2). Problem reported
        by Blaz Zupan @ amis.net.
+
+20000823
+
+       Feature: all this discussion about when to reject mail and
+       when not made me decide to implement a TCP-based map type
+       so that it becomes relatively simple to implement dynamic
+       access controls, for example, hold off mail from an unknown
+       client or sender until we have completed some investigation,
+       after which we will either reject or accept.
index 79c4668324dd7b188f9d44af439a0d0bb3595ae7..64a3274c30d58e17924ffb9c09c24e63d5bf2aa7 100644 (file)
@@ -15,7 +15,7 @@
   * Version of this program.
   */
 #define VAR_MAIL_VERSION       "mail_version"
-#define DEF_MAIL_VERSION       "Snapshot-20000822"
+#define DEF_MAIL_VERSION       "Snapshot-20000823"
 extern char *var_mail_version;
 
 /* LICENSE
index 5fbb816dfa66fee712b7105066d31c289803f23c..15931a7c1d3bf558b8eb14bafdeecc0db114dfcf 100644 (file)
@@ -32,6 +32,7 @@
 -TDICT_PCRE
 -TDICT_REGEXP
 -TDICT_REGEXP_RULE
+-TDICT_TCP
 -TDICT_UNIX
 -TDNS_FIXED
 -TDNS_REPLY
index 89023fd456f2b6c8d6af93d4f386a6e9ca43c4a8..9ce340a7e63d0f9ecdcf5441a39e80d8bc77810f 100644 (file)
@@ -21,7 +21,8 @@ SRCS  = argv.c argv_split.c attr.c basename.c binhash.c chroot_uid.c \
        write_buf.c write_wait.c dict_unix.c dict_pcre.c stream_listen.c \
        stream_connect.c stream_trigger.c dict_regexp.c mac_expand.c \
        clean_env.c watchdog.c spawn_command.c duplex_pipe.c sane_rename.c \
-       sane_link.c unescape.c timed_read.c timed_write.c 
+       sane_link.c unescape.c timed_read.c timed_write.c dict_tcp.c \
+       hex_quote.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_mysql.o dict_ni.o dict_nis.o \
@@ -44,7 +45,8 @@ OBJS  = argv.o argv_split.o attr.o basename.o binhash.o chroot_uid.o \
        write_buf.o write_wait.o dict_unix.o dict_pcre.o stream_listen.o \
        stream_connect.o stream_trigger.o dict_regexp.o mac_expand.o \
        clean_env.o watchdog.o spawn_command.o duplex_pipe.o sane_rename.o \
-       sane_link.o unescape.o timed_read.o timed_write.o 
+       sane_link.o unescape.o timed_read.o timed_write.o dict_tcp.o \
+       hex_quote.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_mysql.h \
        dict_ni.h dict_nis.h dict_nisplus.h dir_forest.h events.h \
@@ -59,7 +61,7 @@ HDRS  = argv.h attr.h binhash.h chroot_uid.h connect.h dict.h dict_db.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_regexp.h mac_expand.h clean_env.h \
-       watchdog.h spawn_command.h sane_fsops.h 
+       watchdog.h spawn_command.h sane_fsops.h dict_tcp.h hex_quote.h
 TESTSRC        = fifo_open.c fifo_rdwr_bug.c fifo_rdonly_bug.c select_bug.c \
        stream_test.c dup2_pass_on_exec.c
 WARN   = -W -Wformat -Wimplicit -Wmissing-prototypes \
@@ -75,7 +77,7 @@ TESTPROG= dict_open dup2_pass_on_exec events exec_command fifo_open \
        inet_addr_host inet_addr_local mac_parse make_dirs msg_syslog \
        mystrtok sigdelay translit valid_hostname vstream_popen \
        vstring vstring_vstream doze select_bug stream_test mac_expand \
-       watchdog unescape
+       watchdog unescape hex_quote
 
 LIB_DIR        = ../lib
 INC_DIR        = ../include
@@ -249,6 +251,11 @@ unescape: $(LIB)
        $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS)
        mv junk $@.o
 
+hex_quote: $(LIB)
+       mv $@.o junk
+       $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS)
+       mv junk $@.o
+
 depend: $(MAKES)
        (sed '1,/^# do not edit/!d' Makefile.in; \
        set -e; for i in [a-z][a-z0-9]*.c; do \
@@ -260,7 +267,8 @@ depend: $(MAKES)
 stream_test: stream_test.c $(LIB)
        $(CC) $(CFLAGS)  -o $@ $@.c $(LIB) $(SYSLIBS)
 
-tests: valid_hostname_test mac_expand_test dict_test unescape_test
+tests: valid_hostname_test mac_expand_test dict_test unescape_test \
+       hex_quote_test
 
 valid_hostname_test: valid_hostname valid_hostname.in valid_hostname.ref
        ./valid_hostname <valid_hostname.in 2>valid_hostname.tmp
@@ -277,6 +285,12 @@ unescape_test: unescape unescape.in unescape.ref
        diff -b unescape.ref unescape.tmp
        rm -f unescape.tmp
 
+hex_quote_test: hex_quote
+       ./hex_quote <hex_quote.c | od -cb >hex_quote.tmp
+       od -cb <hex_quote.c >hex_quote.ref
+       cmp hex_quote.ref hex_quote.tmp
+       rm -f hex_quote.ref hex_quote.tmp
+
 DB_TYPE        = `../postconf/postconf -h default_database_type`
 
 dict_test: dict_open testdb dict_test.in dict_test.ref
@@ -416,6 +430,7 @@ dict_open.o: vstream.h
 dict_open.o: vbuf.h
 dict_open.o: dict_env.h
 dict_open.o: dict_unix.h
+dict_open.o: dict_tcp.h
 dict_open.o: dict_dbm.h
 dict_open.o: dict_db.h
 dict_open.o: dict_nis.h
@@ -445,6 +460,20 @@ dict_regexp.o: dict.h
 dict_regexp.o: argv.h
 dict_regexp.o: dict_regexp.h
 dict_regexp.o: mac_parse.h
+dict_tcp.o: dict_tcp.c
+dict_tcp.o: sys_defs.h
+dict_tcp.o: msg.h
+dict_tcp.o: mymalloc.h
+dict_tcp.o: vstring.h
+dict_tcp.o: vbuf.h
+dict_tcp.o: vstream.h
+dict_tcp.o: vstring_vstream.h
+dict_tcp.o: connect.h
+dict_tcp.o: iostuff.h
+dict_tcp.o: hex_quote.h
+dict_tcp.o: dict.h
+dict_tcp.o: argv.h
+dict_tcp.o: dict_tcp.h
 dict_unix.o: dict_unix.c
 dict_unix.o: sys_defs.h
 dict_unix.o: msg.h
@@ -465,6 +494,7 @@ doze.o: doze.c
 doze.o: sys_defs.h
 doze.o: msg.h
 doze.o: iostuff.h
+dup2_pass_on_exec.o: dup2_pass_on_exec.c
 duplex_pipe.o: duplex_pipe.c
 duplex_pipe.o: sys_defs.h
 duplex_pipe.o: iostuff.h
@@ -526,6 +556,12 @@ get_hostname.o: mymalloc.h
 get_hostname.o: msg.h
 get_hostname.o: valid_hostname.h
 get_hostname.o: get_hostname.h
+hex_quote.o: hex_quote.c
+hex_quote.o: sys_defs.h
+hex_quote.o: msg.h
+hex_quote.o: vstring.h
+hex_quote.o: vbuf.h
+hex_quote.o: hex_quote.h
 htable.o: htable.c
 htable.o: sys_defs.h
 htable.o: mymalloc.h
@@ -948,6 +984,7 @@ vstring_vstream.o: vstream.h
 vstring_vstream.o: vstring_vstream.h
 watchdog.o: watchdog.c
 watchdog.o: sys_defs.h
+watchdog.o: posix_signals.h
 watchdog.o: msg.h
 watchdog.o: mymalloc.h
 watchdog.o: watchdog.h
index 1eb2471aedcecb4234de25bd2a50b01caa41ed18..69a4071e8a1e30faa1a7726a5fab96cbdd3a830f 100644 (file)
 #include <dict.h>
 #include <dict_env.h>
 #include <dict_unix.h>
+#include <dict_tcp.h>
 #include <dict_dbm.h>
 #include <dict_db.h>
 #include <dict_nis.h>
@@ -180,6 +181,7 @@ typedef struct {
 static DICT_OPEN_INFO dict_open_info[] = {
     "environ", dict_env_open,
     "unix", dict_unix_open,
+    "tcp", dict_tcp_open,
 #ifdef HAS_DBM
     "dbm", dict_dbm_open,
 #endif
@@ -318,6 +320,7 @@ ARGV   *dict_mapnames()
 #include <stdlib.h>
 #include <fcntl.h>
 #include <unistd.h>
+#include <signal.h>
 
 /* Utility library. */
 
@@ -343,6 +346,8 @@ main(int argc, char **argv)
     const char *value;
     int     ch;
 
+    signal(SIGPIPE, SIG_IGN);
+
     msg_vstream_init(argv[0], VSTREAM_ERR);
     while ((ch = GETOPT(argc, argv, "v")) > 0) {
        switch (ch) {
@@ -380,7 +385,9 @@ main(int argc, char **argv)
                vstream_printf("%s: deleted\n", key);
        } else if (strcmp(cmd, "get") == 0 && key && !value) {
            if ((value = dict_get(dict, key)) == 0) {
-               vstream_printf("%s: not found\n", key);
+               vstream_printf("%s: %s\n", key,
+                              dict_errno == DICT_ERR_RETRY ?
+                              "soft error" : "not found");
            } else {
                vstream_printf("%s=%s\n", key, value);
            }
@@ -388,7 +395,7 @@ main(int argc, char **argv)
            dict_put(dict, key, value);
            vstream_printf("%s=%s\n", key, value);
        } else {
-           vstream_printf("usage: del key|get key|put key=value");
+           vstream_printf("usage: del key|get key|put key=value\n");
        }
        vstream_fflush(VSTREAM_OUT);
     }
diff --git a/postfix/util/dict_tcp.c b/postfix/util/dict_tcp.c
new file mode 100644 (file)
index 0000000..1cb4b15
--- /dev/null
@@ -0,0 +1,191 @@
+/*++
+/* NAME
+/*     dict_tcp 3
+/* SUMMARY
+/*     dictionary manager interface to tcp-based lookup tables
+/* SYNOPSIS
+/*     #include <dict_tcp.h>
+/*
+/*     DICT    *dict_tcp_open(map, dummy, dict_flags)
+/*     const char *map;
+/*     int     dummy;
+/*     int     dict_flags;
+/* DESCRIPTION
+/*     dict_tcp_open() makes a TCP server accessible via the generic
+/*     dictionary operations described in dict_open(3).
+/*     The \fIdummy\fR argument is not used. Server access is read-only
+/*     (i.e., only lookups are implemented).
+/*
+/*     Map names have the form host:port.
+/*
+/*     The map implements a very simple protocol: the query is sent as
+/*     one line of text, and the reply is sent back in the same format.
+/*     Data is sent as a newline-terminated string. % and non-printable
+/*     characters are replaced by %xx, xx being the corresponding
+/*     hexadecimal value.
+/* SEE ALSO
+/*     dict(3) generic dictionary manager
+/* DIAGNOSTICS
+/*     Fatal errors: out of memory, unknown host or service name,
+/*     attempt to update map.
+/* LICENSE
+/* .ad
+/* .fi
+/*     The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include "sys_defs.h"
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+/* Utility library. */
+
+#include "msg.h"
+#include "mymalloc.h"
+#include "vstring.h"
+#include "vstream.h"
+#include "vstring_vstream.h"
+#include "connect.h"
+#include "hex_quote.h"
+#include "dict.h"
+#include "dict_tcp.h"
+
+/* Application-specific. */
+
+typedef struct {
+    DICT    dict;                      /* generic members */
+    char   *map;                       /* server host:port */
+    VSTRING *raw_buf;                  /* raw buffer */
+    VSTRING *hex_buf;                  /* hexified buffer */
+    VSTREAM *fp;                       /* I/O stream */
+} DICT_TCP;
+
+#define DICT_TCP_MAXTRY        10
+#define DICT_TCP_TMOUT 100
+
+#define STR(x)         vstring_str(x)
+
+/* dict_tcp_lookup - query TCP server */
+
+static const char *dict_tcp_lookup(DICT *dict, const char *key)
+{
+    DICT_TCP *dict_tcp = (DICT_TCP *) dict;
+    int     fd;
+    int     i;
+
+    dict_errno = 0;
+
+    for (i = 0; /* see below */ ; i++) {
+
+       /*
+        * Try to connect a few times before giving up.
+        */
+       if (i >= DICT_TCP_MAXTRY) {
+           dict_errno = DICT_ERR_RETRY;
+           return (0);
+       }
+
+       /*
+        * Sleep between connection attempts.
+        */
+       if (i > 0)
+           sleep(1);
+
+       /*
+        * Try to connect to the server.
+        */
+       if (dict_tcp->fp == 0) {
+           if ((fd = inet_connect(dict_tcp->map, BLOCKING, 0)) < 0) {
+               msg_warn("connect to TCP map %s: %m", dict_tcp->map);
+               continue;
+           }
+           dict_tcp->fp = vstream_fdopen(fd, O_RDWR);
+           vstream_control(dict_tcp->fp,
+                           VSTREAM_CTL_TIMEOUT, DICT_TCP_TMOUT,
+                           VSTREAM_CTL_END);
+       }
+
+       /*
+        * Allocate per-map buffers on the fly.
+        */
+       if (dict_tcp->raw_buf == 0) {
+           dict_tcp->raw_buf = vstring_alloc(10);
+           dict_tcp->hex_buf = vstring_alloc(10);
+       }
+
+       /*
+        * Send query and receive response. Both are %XX quoted and both are
+        * terminated by newline.
+        */
+       hex_quote(dict_tcp->hex_buf, key);
+       vstream_fprintf(dict_tcp->fp, "%s\n", STR(dict_tcp->hex_buf));
+       errno = 0;
+       if (vstring_get_nonl(dict_tcp->hex_buf, dict_tcp->fp) == VSTREAM_EOF) {
+           msg_warn("read TCP map reply from %s: %m", dict_tcp->map);
+       } else if (!hex_unquote(dict_tcp->raw_buf, STR(dict_tcp->hex_buf))) {
+           msg_warn("read TCP map reply from %s: malformed reply %.100s",
+                    dict_tcp->map, STR(dict_tcp->hex_buf));
+       } else {
+           return (STR(dict_tcp->raw_buf));
+       }
+
+       /*
+        * That did not work. Clean up and try again.
+        */
+       (void) vstream_fclose(dict_tcp->fp);
+       dict_tcp->fp = 0;
+    }
+}
+
+/* dict_tcp_update - add or update table entry */
+
+static void dict_tcp_update(DICT *dict, const char *unused_name, const char *unused_value)
+{
+    DICT_TCP *dict_tcp = (DICT_TCP *) dict;
+
+    msg_fatal("dict_tcp_update: attempt to update map %s", dict_tcp->map);
+}
+
+/* dict_tcp_close - close TCP map */
+
+static void dict_tcp_close(DICT *dict)
+{
+    DICT_TCP *dict_tcp = (DICT_TCP *) dict;
+
+    if (dict_tcp->fp)
+       (void) vstream_fclose(dict_tcp->fp);
+    if (dict_tcp->raw_buf)
+       vstring_free(dict_tcp->raw_buf);
+    if (dict_tcp->hex_buf)
+       vstring_free(dict_tcp->hex_buf);
+    myfree(dict_tcp->map);
+    myfree((char *) dict_tcp);
+}
+
+/* dict_tcp_open - open TCP map */
+
+DICT   *dict_tcp_open(const char *map, int unused_flags, int dict_flags)
+{
+    DICT_TCP *dict_tcp;
+
+    dict_errno = 0;
+
+    dict_tcp = (DICT_TCP *) mymalloc(sizeof(*dict_tcp));
+    dict_tcp->fp = 0;
+    dict_tcp->raw_buf = dict_tcp->hex_buf = 0;
+    dict_tcp->dict.lookup = dict_tcp_lookup;
+    dict_tcp->dict.update = dict_tcp_update;
+    dict_tcp->dict.close = dict_tcp_close;
+    dict_tcp->dict.fd = -1;
+    dict_tcp->map = mystrdup(map);
+    dict_tcp->dict.flags = dict_flags | DICT_FLAG_FIXED;
+    return (&dict_tcp->dict);
+}
diff --git a/postfix/util/dict_tcp.h b/postfix/util/dict_tcp.h
new file mode 100644 (file)
index 0000000..4b31eda
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef _DICT_TCP_H_INCLUDED_
+#define _DICT_TCP_H_INCLUDED_
+
+/*++
+/* NAME
+/*     dict_tcp 3h
+/* SUMMARY
+/*     dictionary manager interface to tcp-based lookup tables
+/* SYNOPSIS
+/*     #include <dict_tcp.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+  * Utility library.
+  */
+#include <dict.h>
+
+ /*
+  * External interface.
+  */
+extern DICT *dict_tcp_open(const char *, int, int);
+
+/* LICENSE
+/* .ad
+/* .fi
+/*     The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+#endif
diff --git a/postfix/util/hex_quote.c b/postfix/util/hex_quote.c
new file mode 100644 (file)
index 0000000..4ed0e73
--- /dev/null
@@ -0,0 +1,148 @@
+/*++
+/* NAME
+/*     hex_quote 3
+/* SUMMARY
+/*     quote/unquote text, HTTP style.
+/* SYNOPSIS
+/*     #include <hex_quote.h>
+/*
+/*     VSTRING *hex_quote(hex, raw)
+/*     VSTRING *hex;
+/*     const char *raw;
+/*
+/*     VSTRING *hex_unquote(raw, hex)
+/*     VSTRING *raw;
+/*     const char *hex;
+/* DESCRIPTION
+/*     hex_quote() takes a null-terminated string and replaces non-printable
+/*     characters and % by %XX, XX being the two-digit hexadecimal equivalent.
+/*     The hexadecimal codes are produced as upper-case characters. The result
+/*     value is the hex argument.
+/*
+/*     hex_unquote() performs the opposite transformation. This function
+/*     understands lowercase and uppercase %XX sequences. The result
+/*     value is the raw argument in case of success, a null pointer otherwise.
+/* BUGS
+/*     Cannot process null characters.
+/* LICENSE
+/* .ad
+/* .fi
+/*     The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include "sys_defs.h"
+#include <ctype.h>
+
+/* Utility library. */
+
+#include "msg.h"
+#include "vstring.h"
+#include "hex_quote.h"
+
+/* Application-specific. */
+
+#define STR(x) vstring_str(x)
+#define LEN(x) VSTRING_LEN(x)
+
+/* hex_quote - raw data to quoted */
+
+VSTRING *hex_quote(VSTRING *hex, const char *raw)
+{
+    const char *cp;
+    int     ch;
+
+    VSTRING_RESET(hex);
+    for (cp = raw; (ch = *(unsigned const char *) cp) != 0; cp++) {
+       if (ch != '%' && ISPRINT(ch)) {
+           VSTRING_ADDCH(hex, ch);
+       } else {
+           vstring_sprintf_append(hex, "%%%02X", ch);
+       }
+    }
+    VSTRING_TERMINATE(hex);
+    return (hex);
+}
+
+/* hex_unquote - quoted data to raw */
+
+VSTRING *hex_unquote(VSTRING *raw, const char *hex)
+{
+    const char *cp;
+    int     ch;
+
+    VSTRING_RESET(raw);
+    for (cp = hex; (ch = *cp) != 0; cp++) {
+       if (ch == '%') {
+           if (ISDIGIT(cp[1]))
+               ch = (cp[1] - '0') << 4;
+           else if (cp[1] >= 'a' && cp[1] <= 'f')
+               ch = (cp[1] - 'a' + 10) << 4;
+           else if (cp[1] >= 'A' && cp[1] <= 'F')
+               ch = (cp[1] - 'A' + 10) << 4;
+           else
+               return (0);
+           if (ISDIGIT(cp[2]))
+               ch |= (cp[2] - '0');
+           else if (cp[2] >= 'a' && cp[2] <= 'f')
+               ch |= (cp[2] - 'a' + 10);
+           else if (cp[2] >= 'A' && cp[2] <= 'F')
+               ch |= (cp[2] - 'A' + 10);
+           else
+               return (0);
+           cp += 2;
+       }
+       VSTRING_ADDCH(raw, ch);
+    }
+    VSTRING_TERMINATE(raw);
+    return (raw);
+}
+
+#ifdef TEST
+
+ /*
+  * Proof-of-concept test program: convert to hex and back.
+  */
+#include <vstream.h>
+
+#define BUFLEN 1024
+
+static int read_buf(VSTREAM *fp, VSTRING *buf)
+{
+    int     len;
+
+    VSTRING_RESET(buf);
+    len = vstream_fread(fp, STR(buf), vstring_avail(buf));
+    VSTRING_AT_OFFSET(buf, len);               /* XXX */
+    VSTRING_TERMINATE(buf);
+    return (len);
+}
+
+main(int unused_argc, char **unused_argv)
+{
+    VSTRING *raw = vstring_alloc(BUFLEN);
+    VSTRING *hex = vstring_alloc(100);
+    int     len;
+
+    while ((len = read_buf(VSTREAM_IN, raw)) > 0) {
+       hex_quote(hex, STR(raw));
+       if (hex_unquote(raw, STR(hex)) == 0)
+           msg_fatal("bad input: %.100s", STR(hex));
+       if (LEN(raw) != len)
+           msg_fatal("len %d != raw len %d", len, LEN(raw));
+       if (vstream_fwrite(VSTREAM_OUT, STR(raw), LEN(raw)) != LEN(raw))
+           msg_fatal("write error: %m");
+    }
+    vstream_fflush(VSTREAM_OUT);
+    vstring_free(raw);
+    vstring_free(hex);
+    return (0);
+}
+
+#endif
diff --git a/postfix/util/hex_quote.h b/postfix/util/hex_quote.h
new file mode 100644 (file)
index 0000000..d72ec57
--- /dev/null
@@ -0,0 +1,36 @@
+#ifndef _HEX_QUOTE_H_INCLUDED_
+#define _HEX_QUOTE_H_INCLUDED_
+
+/*++
+/* NAME
+/*     hex_quote 3h
+/* SUMMARY
+/*     quote/unquote text, HTTP style.
+/* SYNOPSIS
+/*     #include <hex_quote.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+  * Utility library.
+ */
+#include <vstring.h>
+
+ /*
+  * External interface.
+  */
+extern VSTRING *hex_quote(VSTRING *, const char *);
+extern VSTRING *hex_unquote(VSTRING *, const char *);
+
+/* LICENSE
+/* .ad
+/* .fi
+/*     The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+#endif
index 2a4f73abad88c7ce3ae97c54b112089ef648bf07..99e8762b3559e8772f4e87e1da2460c90105431a 100644 (file)
@@ -825,7 +825,7 @@ typedef int pid_t;
 #if __GNUC__ == 2 && __GNUC_MINOR__ >= 7
 #define PRINTFLIKE(x,y) __attribute__ ((format (printf, (x), (y))))
 #else
-#define PRINTFLIKE
+#define PRINTFLIKE(x,y)
 #endif
 #endif