diff --git a/postfix/.indent.pro b/postfix/.indent.pro index a0d1c27f7..5e1656aa2 100644 --- a/postfix/.indent.pro +++ b/postfix/.indent.pro @@ -54,6 +54,7 @@ -THTABLE -THTABLE_INFO -TINET_ADDR_LIST +-TINTV -TINT_TABLE -TJMP_BUF_WRAPPER -TLMTP_ATTR diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index f6824de79..584ed2da1 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -15,7 +15,7 @@ * Version of this program. */ #define VAR_MAIL_VERSION "mail_version" -#define DEF_MAIL_VERSION "Snapshot-20011008" +#define DEF_MAIL_VERSION "Snapshot-20011010" extern char *var_mail_version; /* LICENSE diff --git a/postfix/src/master/multi_server.c b/postfix/src/master/multi_server.c index 0be6a6335..39aab4331 100644 --- a/postfix/src/master/multi_server.c +++ b/postfix/src/master/multi_server.c @@ -272,13 +272,16 @@ static void multi_server_enable_read(int unused_event, char *context) static void multi_server_wakeup(int fd) { VSTREAM *stream; - + char *tmp; if (msg_verbose) msg_info("connection established fd %d", fd); non_blocking(fd, BLOCKING); close_on_exec(fd, CLOSE_ON_EXEC); client_count++; stream = vstream_fdopen(fd, O_RDWR); + tmp = concatenate(multi_server_name, " socket", (char *) 0); + vstream_control(stream, VSTREAM_CTL_PATH, tmp, VSTREAM_CTL_END); + myfree(tmp); timed_ipc_setup(stream); if (multi_server_in_flow_delay && mail_flow_get(1) < 0) event_request_timer(multi_server_enable_read, (char *) stream, diff --git a/postfix/src/master/single_server.c b/postfix/src/master/single_server.c index 21079f8e9..d110e4010 100644 --- a/postfix/src/master/single_server.c +++ b/postfix/src/master/single_server.c @@ -221,6 +221,7 @@ static void single_server_timeout(int unused_event, char *unused_context) static void single_server_wakeup(int fd) { VSTREAM *stream; + char *tmp; /* * If the accept() succeeds, be sure to disable non-blocking I/O, because @@ -233,6 +234,9 @@ static void single_server_wakeup(int fd) non_blocking(fd, BLOCKING); close_on_exec(fd, CLOSE_ON_EXEC); stream = vstream_fdopen(fd, O_RDWR); + tmp = concatenate(single_server_name, " socket", (char *) 0); + vstream_control(stream, VSTREAM_CTL_PATH, tmp, VSTREAM_CTL_END); + myfree(tmp); timed_ipc_setup(stream); if (master_notify(var_pid, MASTER_STAT_TAKEN) < 0) single_server_abort(EVENT_NULL_TYPE, EVENT_NULL_CONTEXT); diff --git a/postfix/src/util/Makefile.in b/postfix/src/util/Makefile.in index dd2c91542..bf8ecebda 100644 --- a/postfix/src/util/Makefile.in +++ b/postfix/src/util/Makefile.in @@ -23,7 +23,8 @@ SRCS = argv.c argv_split.c attr.c basename.c binhash.c chroot_uid.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 dict_tcp.c \ hex_quote.c dict_alloc.c rand_sleep.c sane_time.c dict_debug.c \ - sane_socketpair.c myrand.c netstring.c ctable.c + sane_socketpair.c myrand.c netstring.c ctable.c attr_print.c intv.c \ + attr_scan.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 \ @@ -48,7 +49,8 @@ OBJS = argv.o argv_split.o attr.o basename.o binhash.o chroot_uid.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 dict_tcp.o \ hex_quote.o dict_alloc.o rand_sleep.o sane_time.o dict_debug.o \ - sane_socketpair.o myrand.o netstring.o ctable.o + sane_socketpair.o myrand.o netstring.o ctable.o attr_print.o intv.o \ + attr_scan.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 \ @@ -64,7 +66,8 @@ HDRS = argv.h attr.h binhash.h chroot_uid.h connect.h dict.h dict_db.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 dict_tcp.h hex_quote.h \ - sane_time.h sane_socketpair.h myrand.h netstring.h ctable.h + sane_time.h sane_socketpair.h myrand.h netstring.h ctable.h \ + attr_io.h intv.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 \ @@ -81,7 +84,7 @@ TESTPROG= dict_open dup2_pass_on_exec events exec_command fifo_open \ mystrtok sigdelay translit valid_hostname vstream_popen \ vstring vstring_vstream doze select_bug stream_test mac_expand \ watchdog unescape hex_quote name_mask rand_sleep sane_time ctable \ - inet_addr_list + inet_addr_list attr_print attr_scan LIB_DIR = ../../lib INC_DIR = ../../include @@ -285,6 +288,16 @@ inet_addr_list: $(LIB) $@.o $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS) mv junk $@.o +attr_print: $(LIB) $@.o + mv $@.o junk + $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS) + mv junk $@.o + +attr_scan: $(LIB) $@.o + 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 \ @@ -359,6 +372,21 @@ attr.o: sys_defs.h attr.o: mymalloc.h attr.o: htable.h attr.o: attr.h +attr_print.o: attr_print.c +attr_print.o: sys_defs.h +attr_print.o: vstream.h +attr_print.o: vbuf.h +attr_print.o: msg.h +attr_print.o: attr_io.h +attr_scan.o: attr_scan.c +attr_scan.o: sys_defs.h +attr_scan.o: vstream.h +attr_scan.o: vbuf.h +attr_scan.o: vstring.h +attr_scan.o: msg.h +attr_scan.o: argv.h +attr_scan.o: intv.h +attr_scan.o: attr_io.h basename.o: basename.c basename.o: sys_defs.h basename.o: stringops.h @@ -682,6 +710,11 @@ inet_util.o: sys_defs.h inet_util.o: mymalloc.h inet_util.o: split_at.h inet_util.o: inet_util.h +intv.o: intv.c +intv.o: sys_defs.h +intv.o: mymalloc.h +intv.o: msg.h +intv.o: intv.h line_wrap.o: line_wrap.c line_wrap.o: sys_defs.h line_wrap.o: line_wrap.h diff --git a/postfix/src/util/attr_io.h b/postfix/src/util/attr_io.h new file mode 100644 index 000000000..44c0bd311 --- /dev/null +++ b/postfix/src/util/attr_io.h @@ -0,0 +1,63 @@ +#ifndef _ATTR_PRINT_H_INCLUDED_ +#define _ATTR_PRINT_H_INCLUDED_ + +/*++ +/* NAME +/* attr_type 3h +/* SUMMARY +/* attribute list I/O +/* SYNOPSIS +/* #include "attr_type.h" + DESCRIPTION + .nf + + /* + * System library. + */ +#include + + /* + * Utility library. + */ +#include + + /* + * External interface. + */ +#define ATTR_TYPE_END 0 /* end of data */ +#define ATTR_TYPE_NUM 1 /* Unsigned integer */ +#define ATTR_TYPE_STR 2 /* Character string */ +#define ATTR_TYPE_NUM_ARRAY 3 /* Unsigned integer sequence */ +#define ATTR_TYPE_STR_ARRAY 4 /* Character string sequence */ + +#define ATTR_FLAG_MISSING (1<<0) /* Flag missing attribute */ +#define ATTR_FLAG_EXTRA (1<<1) /* Flag spurious attribute */ + +extern int attr_print(VSTREAM *,...); +extern int attr_vprint(VSTREAM *, va_list); +extern int attr_scan(VSTREAM *, int,...); +extern int attr_vscan(VSTREAM *, int, va_list); + + /* + * Attribute names for testing the compatibility of the read and write + * routines. + */ +#ifdef TEST +#define ATTR_NAME_NUM "number" +#define ATTR_NAME_STR "string" +#define ATTR_NAME_NUM_ARRAY "number_array" +#define ATTR_NAME_STR_ARRAY "string_array" +#endif + +/* 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/src/util/attr_print.c b/postfix/src/util/attr_print.c new file mode 100644 index 000000000..226a5cbf5 --- /dev/null +++ b/postfix/src/util/attr_print.c @@ -0,0 +1,175 @@ +/*++ +/* NAME +/* attr_print 3 +/* SUMMARY +/* send attributes over byte stream +/* SYNOPSIS +/* #include +/* +/* int attr_print(fp, type, name, ...) +/* VSTREAM fp; +/* int type; +/* char *name; +/* DESCRIPTION +/* attr_print() takes zero or more (name, value) simple attributes +/* or (name, count, value) list attributes, and converts its input +/* to a byte stream that can be recovered with attr_scan(). The stream +/* is not flushed. +/* +/* Attributes are sent in the requested order as specified with the +/* attr_print() argument list. This routine satisfies the formatting +/* rules as outlined in attr_scan(3). +/* +/* Arguments: +/* .IP fp +/* Stream to write the result to. +/* .IP type +/* The type determines the arguments that follow. +/* .RS +/* .IP "ATTR_TYPE_NUM (char *, int)" +/* This argument is followed by an attribute name and an integer. +/* .IP "ATTR_TYPE_STR (char *, char *)" +/* This argument is followed by an attribute name and a null-terminated +/* string. +/* .IP "ATTR_TYPE_NUM_ARRAY (char *, int, int *)" +/* This argument is followed by an attribute name, an integer array +/* element count, and a pointer to integer. +/* .IP "ATTR_TYPE_NUM_ARRAY (char *, int, char **)" +/* This argument is followed by an attribute name, an integer array +/* element count, and a pointer to a null-terminated array of +/* null-terminated strings. +/* .IP ATTR_TYPE_END +/* This terminates the attribute list. +/* .RE +/* DIAGNOSTICS +/* The result value is 0 in case of success, VSTREAM_EOF in case +/* of trouble. +/* +/* Panic: interface violation. All system call errors are fatal. +/* SEE ALSO +/* attr_scan(3) recover attributes from byte stream +/* 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 +#include + +/* Utility library. */ + +#include +#include +#include + +/* attr_fprintf - encode attribute information on the fly */ + +static void PRINTFLIKE(2, 3) attr_fprintf(VSTREAM *fp, const char *format,...) +{ + va_list ap; + + va_start(ap, format); + vstream_vfprintf(fp, format, ap); + va_end(ap); +} + +/* attr_vprint - send attribute list to stream */ + +int attr_vprint(VSTREAM *fp, va_list ap) +{ + const char *myname = "attr_print"; + int attr_type; + char *attr_name; + unsigned int_val; + char *str_val; + char **cpp_val; + unsigned *ip_val; + int count_val; + int i; + + /* + * Iterate over all (type, name, value) triples, and produce output on + * the fly. + */ + while ((attr_type = va_arg(ap, int)) != ATTR_TYPE_END) { + attr_name = va_arg(ap, char *); + attr_fprintf(fp, "%s", attr_name); + switch (attr_type) { + case ATTR_TYPE_NUM: + int_val = va_arg(ap, int); + attr_fprintf(fp, ":%u", (unsigned) int_val); + break; + case ATTR_TYPE_STR: + str_val = va_arg(ap, char *); + attr_fprintf(fp, ":%s", str_val); + break; + case ATTR_TYPE_NUM_ARRAY: + ip_val = va_arg(ap, int *); + count_val = va_arg(ap, int); + for (i = 0; i < count_val; i++) + attr_fprintf(fp, ":%u", (unsigned) *ip_val++); + break; + case ATTR_TYPE_STR_ARRAY: + cpp_val = va_arg(ap, char **); + count_val = va_arg(ap, int); + for (i = 0; i < count_val; i++) { + str_val = *cpp_val++; + attr_fprintf(fp, ":%s", str_val); + } + break; + default: + msg_panic("%s: unknown type code: %d", myname, attr_type); + } + VSTREAM_PUTC('\n', fp); + } + VSTREAM_PUTC('\n', fp); + return (vstream_ferror(fp)); +} + +int attr_print(VSTREAM *fp,...) +{ + va_list ap; + int ret; + + va_start(ap, fp); + ret = attr_vprint(fp, ap); + va_end(ap); + return (ret); +} + +#ifdef TEST + + /* + * Proof of concept test program. Mirror image of the attr_scan test + * program. + */ +#include + +int main(int argc, char **argv) +{ + static int int_array[] = {0, 1, 2, 3, 4, 5, 6, 7}; + static char *str_array[] = {"a", "b", "c", "d", "e", "f", "g", "h"}; + + msg_vstream_init(argv[0], VSTREAM_ERR); + attr_print(VSTREAM_OUT, + ATTR_TYPE_NUM, ATTR_NAME_NUM, 4711, + ATTR_TYPE_STR, ATTR_NAME_STR, "whoopee", + ATTR_TYPE_NUM_ARRAY, ATTR_NAME_NUM_ARRAY, + int_array, sizeof(int_array) / sizeof(int_array[0]), + ATTR_TYPE_STR_ARRAY, ATTR_NAME_STR_ARRAY, + str_array, sizeof(str_array) / sizeof(str_array[0]), + ATTR_TYPE_END); + if (vstream_fflush(VSTREAM_OUT) != 0) + msg_fatal("write error: %m"); + return (0); +} + +#endif diff --git a/postfix/src/util/attr_scan.c b/postfix/src/util/attr_scan.c new file mode 100644 index 000000000..c40d90665 --- /dev/null +++ b/postfix/src/util/attr_scan.c @@ -0,0 +1,369 @@ +/*++ +/* NAME +/* attr_scan 3 +/* SUMMARY +/* recover attributes from byte stream +/* SYNOPSIS +/* #include +/* +/* int attr_scan(fp, flags, type, name, ...) +/* VSTREAM fp; +/* int flags; +/* int type; +/* char *name; +/* DESCRIPTION +/* attr_scan() takes zero or more (name, value) scalar or array +/* attribute arguments, and recovers the attribute values from the +/* byte stream that was generated by attr_print(). +/* +/* The input stream is formatted as follows, where (item)* stands +/* for zero or more instances of the specified item, and where +/* (item1 | item2) stands for choice: +/* +/* .in +5 +/* attr-list :== (simple-attr | list-attr)* newline +/* .br +/* simple-attr :== attr-name colon attr-value newline +/* .br +/* list-attr :== attr-name (colon attr-value)* newline +/* .br +/* attr-name :== any base64 encoded string +/* .br +/* attr-value :== any base64 encoded string +/* .br +/* colon :== the ASCII colon character +/* .br +/* newline :== the ASCII newline character +/* .in +/* +/* All character values are 7-bit ASCII. All attribute names and +/* attribute values are sent as base64-encoded strings. The +/* formatting rules aim to make implementations in PERL and other +/* non-C languages easy. +/* +/* Attributes must be sent in the requested order as specified with +/* the attr_scan() argument list. The input stream may contain +/* additional attributes at any point in the input stream, including +/* additional instances of requested attributes. +/* +/* Additional attributes are silently skipped over, unless the +/* ATTR_FLAG_EXTRA processing flag is specified (see below). This +/* allows for some flexibility in the evolution of protocols while +/* still providing the option of being strict where desirable. +/* +/* Arguments: +/* .IP fp +/* Stream to recover the attributes from. +/* .IP flags +/* The bit-wise OR of zero or more of the following. +/* .RS +/* .IP ATTR_FLAG_MISSING +/* Log a warning when the input attribute list terminates before all +/* requested attributes are recovered. It is always an error when the +/* input stream ends without the newline attribute list terminator. +/* .IP ATTR_FLAG_EXTRA +/* Log a warning and stop attribute recovery when the input stream +/* contains an attribute that was not requested. +/* .RE +/* .IP type +/* The type determines the arguments that follow. +/* .RS +/* .IP "ATTR_TYPE_NUM (char *, int *)" +/* This argument is followed by an attribute name and an integer pointer. +/* This is used for recovering an integer attribute value. +/* .IP "ATTR_TYPE_STR (char *, VSTRING *)" +/* This argument is followed by an attribute name and a VSTRING pointer. +/* This is used for recovering a string attribute value. +/* .IP "ATTR_TYPE_NUM_ARRAY (char *, INTV *)" +/* This argument is followed by an attribute name and an INTV pointer. +/* This is used for recovering an integer array attribute value. +/* .IP "ATTR_TYPE_NUM_ARRAY (char *, ARGV *)" +/* This argument is followed by an attribute name and an ARGV pointer. +/* This is used for recovering a string array attribute value. +/* .IP ATTR_TYPE_END +/* This terminates the requested attribute list. +/* .RE +/* DIAGNOSTICS +/* The result value is the number of attributes that were successfully +/* recovered from the input stream (an array-valued attribute counts +/* as one attribute). +/* +/* Panic: interface violation. All system call errors are fatal. +/* SEE ALSO +/* attr_print(3) send attributes over byte stream. +/* 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 +#include +#include + +/* Utility library. */ + +#include +#include +#include +#include +#include +#include + +/* Application specific. */ + +extern int var_line_limit; /* XXX */ + +#define STR(x) vstring_str(x) +#define LEN(x) VSTRING_LEN(x) + +/* attr_scan_string - pull a string from the input stream */ + +static int attr_scan_string(VSTREAM *fp, VSTRING *plain_buf, const char *context) +{ + VSTRING *base64_buf = 0; + int limit = var_line_limit * 5 / 4; + int ch; + + if (base64_buf == 0) + base64_buf = vstring_alloc(10); + + VSTRING_RESET(base64_buf); + while ((ch = VSTREAM_GETC(fp)) != ':' && ch != '\n') { + if (ch == VSTREAM_EOF) { + msg_warn("premature end-of-input from %s while reading %s", + VSTREAM_PATH(fp), context); + return (-1); + } + if (LEN(base64_buf) > limit) { + msg_warn("string length > %d characters from %s while reading %s", + limit, VSTREAM_PATH(fp), context); + return (-1); + } + VSTRING_ADDCH(base64_buf, ch); + } + VSTRING_TERMINATE(base64_buf); + vstring_strcpy(plain_buf, STR(base64_buf)); + if (msg_verbose) + msg_info("%s: %s", context, STR(plain_buf)); + return (ch); +} + +/* attr_scan_number - pull a number from the input stream */ + +static int attr_scan_number(VSTREAM *fp, unsigned *ptr, VSTRING *str_buf, + const char *context) +{ + char junk = 0; + int ch; + + if ((ch = attr_scan_string(fp, str_buf, context)) < 0) + return (-1); + if (sscanf(STR(str_buf), "%u%c", ptr, &junk) != 1 || junk != 0) { + msg_warn("malformed numerical data from %s while %s: %.100s", + VSTREAM_PATH(fp), context, STR(str_buf)); + return (-1); + } + return (ch); +} + +/* attr_vscan - receive attribute list from stream */ + +int attr_vscan(VSTREAM *fp, int flags, va_list ap) +{ + const char *myname = "attr_scan"; + static VSTRING *str_buf = 0; + int wanted_type; + char *wanted_name; + int *number; + VSTRING *string; + INTV *number_array; + ARGV *string_array; + unsigned num_val; + int ch; + int conversions = 0; + + /* + * Initialize. + */ + if (str_buf == 0) + str_buf = vstring_alloc(10); + + /* + * Iterate over all (type, name, value) triples. + */ + for (;;) { + + /* + * Determine the next attribute name on the caller's wish list. + */ + wanted_type = va_arg(ap, int); + if (wanted_type == ATTR_TYPE_END) { + wanted_name = "attribute list terminator"; + } else { + wanted_name = va_arg(ap, char *); + } + + /* + * Locate the next attribute of interest in the input stream. + */ + for (;;) { + + /* + * Get the name of the next attribute. Hitting the end-of-input + * early is OK if the caller is prepared to deal with missing + * inputs. + */ + if ((ch = attr_scan_string(fp, str_buf, + "attribute name")) == VSTREAM_EOF) + return (conversions); + if (ch == '\n' && LEN(str_buf) == 0) { + if (wanted_type == ATTR_TYPE_END + || (flags & ATTR_FLAG_MISSING) == 0) + return (conversions); + msg_warn("missing attribute %s in input from %s", + wanted_name, VSTREAM_PATH(fp)); + return (conversions); + } + if (msg_verbose) + msg_info("want attribute %s, found attribute: %s", + wanted_name, STR(str_buf)); + + /* + * See if the caller asks for this attribute. + */ + if (wanted_type != ATTR_TYPE_END + && strcmp(wanted_name, STR(str_buf)) == 0) + break; + if ((flags & ATTR_FLAG_EXTRA) != 0) { + msg_warn("spurious attribute %s in input from %s", + STR(str_buf), VSTREAM_PATH(fp)); + return (conversions); + } + + /* + * Skip over this attribute. The caller does not ask for it. + */ + while ((ch = VSTREAM_GETC(fp)) != VSTREAM_EOF && ch != '\n') + /* void */ ; + } + + /* + * Do the requested conversion. If the target attribute is a + * non-array type, do not allow the sender to send a multi-valued + * attribute. If the target attribute is an array type, allow the + * sender to send a zero-element array. + */ + switch (wanted_type) { + case ATTR_TYPE_NUM: + number = va_arg(ap, int *); + if ((ch = attr_scan_number(fp, number, str_buf, + "attribute value")) < 0) + return (conversions); + if (ch != '\n') { + msg_warn("too many values for attribute %s from %s", + wanted_name, VSTREAM_PATH(fp)); + return (conversions); + } + break; + case ATTR_TYPE_STR: + string = va_arg(ap, VSTRING *); + if ((ch = attr_scan_string(fp, string, "attribute value")) < 0) + return (conversions); + if (ch != '\n') { + msg_warn("too many values for attribute %s from %s", + wanted_name, VSTREAM_PATH(fp)); + return (conversions); + } + break; + case ATTR_TYPE_NUM_ARRAY: + number_array = va_arg(ap, INTV *); + while (ch != '\n') { + if ((ch = attr_scan_number(fp, &num_val, str_buf, + "attribute value")) < 0) + return (conversions); + intv_add(number_array, 1, num_val); + } + break; + case ATTR_TYPE_STR_ARRAY: + string_array = va_arg(ap, ARGV *); + while (ch != '\n') { + if ((ch = attr_scan_string(fp, str_buf, "attribute value")) < 0) + return (conversions); + argv_add(string_array, STR(str_buf), (char *) 0); + } + break; + default: + msg_panic("%s: unknown type code: %d", myname, wanted_type); + } + conversions++; + } +} + +/* attr_scan - read attribute list from stream */ + +int attr_scan(VSTREAM *fp, int flags,...) +{ + va_list ap; + int ret; + + va_start(ap, flags); + ret = attr_vscan(fp, flags, ap); + va_end(ap); + return (ret); +} + +#ifdef TEST + + /* + * Proof of concept test program. Mirror image of the attr_scan test + * program. + */ +#include + +int var_line_limit = 2048; + +int main(int unused_argc, char **used_argv) +{ + INTV *intv = intv_alloc(1); + ARGV *argv = argv_alloc(1); + VSTRING *str_val = vstring_alloc(1); + int int_val; + int ret; + int i; + + msg_verbose = 1; + msg_vstream_init(used_argv[0], VSTREAM_ERR); + if ((ret = attr_scan(VSTREAM_IN, + ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA, + ATTR_TYPE_NUM, ATTR_NAME_NUM, &int_val, + ATTR_TYPE_STR, ATTR_NAME_STR, str_val, + ATTR_TYPE_NUM_ARRAY, ATTR_NAME_NUM_ARRAY, intv, + ATTR_TYPE_STR_ARRAY, ATTR_NAME_STR_ARRAY, argv, + ATTR_TYPE_END)) == 4) { + vstream_printf("%s %d\n", ATTR_NAME_NUM, int_val); + vstream_printf("%s %s\n", ATTR_NAME_STR, STR(str_val)); + vstream_printf("%s", ATTR_NAME_NUM_ARRAY); + for (i = 0; i < intv->intc; i++) + vstream_printf(" %d", intv->intv[i]); + vstream_printf("\n"); + vstream_printf("%s", ATTR_NAME_STR_ARRAY); + for (i = 0; i < argv->argc; i++) + vstream_printf(" %s", argv->argv[i]); + vstream_printf("\n"); + } else { + vstream_printf("return: %d\n", ret); + } + if (vstream_fflush(VSTREAM_OUT) != 0) + msg_fatal("write error: %m"); + return (0); +} + +#endif diff --git a/postfix/src/util/intv.c b/postfix/src/util/intv.c new file mode 100644 index 000000000..1d117fe02 --- /dev/null +++ b/postfix/src/util/intv.c @@ -0,0 +1,114 @@ +/*++ +/* NAME +/* intv 3 +/* SUMMARY +/* integer array utilities +/* SYNOPSIS +/* #include +/* +/* INTV *intv_alloc(len) +/* int len; +/* +/* INTV *intv_free(intvp) +/* INTV *intvp; +/* +/* void intv_add(intvp, count, arg, ...) +/* INTV *intvp; +/* int count; +/* int *arg; +/* DESCRIPTION +/* The functions in this module manipulate arrays of integers. +/* An INTV structure contains the following members: +/* .IP len +/* The actual length of the \fIintv\fR array. +/* .IP intc +/* The number of \fIintv\fR elements used. +/* .IP intv +/* An array of integer values. +/* .PP +/* intv_alloc() returns an empty integer array of the requested +/* length. The result is ready for use by intv_add(). +/* +/* intv_add() copies zero or more integers and adds them to the +/* specified integer array. +/* +/* intv_free() releases storage for an integer array, and conveniently +/* returns a null pointer. +/* SEE ALSO +/* msg(3) diagnostics interface +/* DIAGNOSTICS +/* Fatal errors: memory allocation problem. +/* 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 libraries. */ + +#include +#include /* 44BSD stdarg.h uses abort() */ +#include + +/* Application-specific. */ + +#include "mymalloc.h" +#include "msg.h" +#include "intv.h" + +/* intv_free - destroy integer array */ + +INTV *intv_free(INTV *intvp) +{ + myfree((char *) intvp->intv); + myfree((char *) intvp); + return (0); +} + +/* intv_alloc - initialize integer array */ + +INTV *intv_alloc(int len) +{ + INTV *intvp; + + /* + * Sanity check. + */ + if (len < 1) + msg_panic("intv_alloc: bad array length %d", len); + + /* + * Initialize. + */ + intvp = (INTV *) mymalloc(sizeof(*intvp)); + intvp->len = len; + intvp->intv = (int *) mymalloc(intvp->len * sizeof(intvp->intv[0])); + intvp->intc = 0; + return (intvp); +} + +/* intv_add - add integer to vector */ + +void intv_add(INTV *intvp, int count,...) +{ + va_list ap; + + /* + * Make sure that always intvp->intc < intvp->len. + */ + va_start(ap, count); + while (count-- > 0) { + if (intvp->intc >= intvp->len) { + intvp->len *= 2; + intvp->intv = (int *) myrealloc((char *) intvp->intv, + intvp->len * sizeof(int)); + } + intvp->intv[intvp->intc++] = va_arg(ap, int); + } + va_end(ap); +} diff --git a/postfix/src/util/intv.h b/postfix/src/util/intv.h new file mode 100644 index 000000000..d84c5b4b1 --- /dev/null +++ b/postfix/src/util/intv.h @@ -0,0 +1,38 @@ +#ifndef _INTV_H_INCLUDED_ +#define _INTV_H_INCLUDED_ + +/*++ +/* NAME +/* intv 3h +/* SUMMARY +/* string array utilities +/* SYNOPSIS +/* #include "intv.h" + DESCRIPTION + .nf + + /* + * External interface. + */ +typedef struct INTV { + int len; /* number of array elements */ + int intc; /* array elements in use */ + int *intv; /* integer array */ +} INTV; + +extern INTV *intv_alloc(int); +extern void intv_add(INTV *, int,...); +extern INTV *intv_free(INTV *); + +/* 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/src/util/sys_defs.h b/postfix/src/util/sys_defs.h index da8388d31..13b07c6f1 100644 --- a/postfix/src/util/sys_defs.h +++ b/postfix/src/util/sys_defs.h @@ -26,7 +26,7 @@ #if defined(FREEBSD2) || defined(FREEBSD3) || defined(FREEBSD4) \ || defined(FREEBSD5) \ || defined(BSDI2) || defined(BSDI3) || defined(BSDI4) \ - || defined(OPENBSD2) || defined(NETBSD1) + || defined(OPENBSD2) || defined(OPENBSD3) || defined(NETBSD1) #define SUPPORTED #include #include @@ -58,7 +58,8 @@ #define HAS_DUPLEX_PIPE #endif -#if defined(OPENBSD2) || defined(FREEBSD3) || defined(FREEBSD4) +#if defined(OPENBSD2) || defined(OPENBSD3) \ + || defined(FREEBSD3) || defined(FREEBSD4) #define HAS_ISSETUGID #endif