20011010-14
- Replaced the internal protocols by (name,value) attribute
- lists. This gives better error detection when we start
- making changes to internal protocols, and allows new
- attributes to be introduced without breaking protocols.
+ Replaced the ugly mail_print() and mail-scan() protocols
+ by (name,value) attribute lists. This gives better error
+ detection when we start making changes to internal protocols,
+ and allows new attributes to be introduced without breaking
+ everything immediately.
20011015
with fractional hours (-03-30 instead of -0330). Fix by
Chad House, greyfirst.ca.
+20011102
+
+ Feature: new -f option to postmap and postalias (do not
+ lowercase the lookup key while creating a table). Files:
+ util/dict.h postmap/postmap.c postalias/postalias.c.
+
+ Code cleanup: simplified the attribute print/scan routines,
+ and removed the never-used support for sending and receiving
+ integer arrays and string arrays. Files: util/attr_print.c,
+ util/attr_scan.c.
+
+ Bugfix: qmqpd could read past the end of a string while
+ looking for the VERP magic token in the envelope sender
+ address. File: qmqpd/qmqpd.c.
+
Open problems:
Medium: need in-process caching for map lookups.
- Minor: The $process_id_directory setting is not used anywhere
+ Low: The $process_id_directory setting is not used anywhere
in Postfix. Problem reported by Michael Smith, texas.net.
This should either be documented, or better, the code should
warn about attempts to set a read-only parameter.
- Medium: address rewriting should be on/off configurable
- for envelopes and/or headers.
+ Medium: make address rewriting on/off configurable for
+ envelopes and/or headers.
Medium: smtpd access maps don't understand the recipient
delimiter setting.
In order to port software to a new platform:
-- Choose a SYSTEMTYPE name for the new system. Please use a name
-that includes the major version of the operating system (such as
-SUNOS4 or LINUX2), so that different releases of the same system
-can be supported without confusion.
+- Each system type needs to be identified by a unique name. Examples:
+SUNOS5, FREEBSD4, and so on. Choose a SYSTEMTYPE name for the new
+system. You must use a name that includes at least the major version
+of the operating system (such as SUNOS4 or LINUX2), so that different
+releases of the same system can be supported without confusion.
- Add a case statement to the "makedefs" shell script in the
top-level directory that recognizes the new system reliably, and
+This release introduces a negligible amount of features and is all
+about revision of Postfix internals. With more than 70 pages of
+context diffs compared to the previous snapshot, this release is
+a baseline for upcoming feature changes.
+
+Major changes with snapshot-20011102
+====================================
+
+The protocol between Postfix daemons was replaced by something that
+can be extended without breaking everything after each change, and
+that can also be used to talk to non-Postfix programs. The format
+of the protocols is described in src/util/attr_scan.c.
+
+In header/body_check files, REJECT can now be followed by text that
+is sent to the originator. That feature was stuck waiting for the
+internal protocol revision.
+
Incompatible changes with snapshot-20011008
===========================================
is used while auth_mx_backup_networks is not configured. [This
change was undone with a later release].
-The protocol between Postfix master and child processes has changed.
You must stop and start Postfix in order to switch between Snapshot
-20010808 and releases that implement the older protocol.
+20010808 and earlier releases. The protocol between Postfix master
+and child processes has changed.
Major changes with snapshot-20010808
====================================
postalias - Postfix alias database maintenance
<b>SYNOPSIS</b>
- <b>postalias</b> [<b>-Ninrvw</b>] [<b>-c</b> <i>config_dir</i>] [<b>-d</b> <i>key</i>] [<b>-q</b> <i>key</i>]
+ <b>postalias</b> [<b>-Nfinrvw</b>] [<b>-c</b> <i>config_dir</i>] [<b>-d</b> <i>key</i>] [<b>-q</b> <i>key</i>]
[<i>file_type</i>:]<i>file_name</i> ...
<b>DESCRIPTION</b>
status is zero when at least one of the requested
keys was found.
- <b>-i</b> Incremental mode. Read entries from standard input
+ <b>-f</b> Do not fold the lookup key to lower case while cre-
+ ating a map.
+
+ <b>-i</b> Incremental mode. Read entries from standard input
and do not truncate an existing database. By
- default, <b>postalias</b> creates a new database from the
+ default, <b>postalias</b> creates a new database from the
entries in <b>file</b><i>_</i><b>name</b>.
- <b>-n</b> Don't include the terminating null character that
- terminates lookup keys and values. By default,
- Postfix does whatever is the default for the host
+ <b>-n</b> Don't include the terminating null character that
+ terminates lookup keys and values. By default,
+ Postfix does whatever is the default for the host
operating system.
- <b>-q</b> <i>key</i> Search the specified maps for <i>key</i> and print the
- first value found on the standard output stream.
+ <b>-q</b> <i>key</i> Search the specified maps for <i>key</i> and print the
+ first value found on the standard output stream.
The exit status is zero when the requested informa-
tion was found.
If a key value of <b>-</b> is specified, the program reads
- key values from the standard input stream and
- prints one line of <i>key:</i> <i>value</i> output for each key
- that was found. The exit status is zero when at
+ key values from the standard input stream and
+ prints one line of <i>key:</i> <i>value</i> output for each key
+ that was found. The exit status is zero when at
least one of the requested keys was found.
- <b>-r</b> When updating a table, do not warn about duplicate
+ <b>-r</b> When updating a table, do not warn about duplicate
entries; silently replace them.
<b>-v</b> Enable verbose logging for debugging purposes. Mul-
- tiple <b>-v</b> options make the software increasingly
+ tiple <b>-v</b> options make the software increasingly
verbose.
- <b>-w</b> When updating a table, do not warn about duplicate
+ <b>-w</b> When updating a table, do not warn about duplicate
entries; silently ignore them.
Arguments:
<i>file_type</i>
The type of database to be produced.
- <b>btree</b> The output is a btree file, named
- <i>file_name</i><b>.db</b>. This is available only on
+ <b>btree</b> The output is a btree file, named
+ <i>file_name</i><b>.db</b>. This is available only on
systems with support for <b>db</b> databases.
- <b>dbm</b> The output consists of two files, named
- <i>file_name</i><b>.pag</b> and <i>file_name</i><b>.dir</b>. This is
- available only on systems with support for
+ <b>dbm</b> The output consists of two files, named
+ <i>file_name</i><b>.pag</b> and <i>file_name</i><b>.dir</b>. This is
+ available only on systems with support for
<b>dbm</b> databases.
- <b>hash</b> The output is a hashed file, named
- <i>file_name</i><b>.db</b>. This is available only on
+ <b>hash</b> The output is a hashed file, named
+ <i>file_name</i><b>.db</b>. This is available only on
systems with support for <b>db</b> databases.
- When no <i>file_type</i> is specified, the software uses
- the database type specified via the <b>database</b><i>_</i><b>type</b>
- configuration parameter. The default value for
+ When no <i>file_type</i> is specified, the software uses
+ the database type specified via the <b>database</b><i>_</i><b>type</b>
+ configuration parameter. The default value for
this parameter depends on the host environment.
<i>file_name</i>
- The name of the alias database source file when
+ The name of the alias database source file when
rebuilding a database.
<b>DIAGNOSTICS</b>
- Problems are logged to the standard error stream. No out-
+ Problems are logged to the standard error stream. No out-
put means no problems were detected. Duplicate entries are
skipped and are flagged with a warning.
<b>postalias</b> terminates with zero exit status in case of suc-
- cess (including successful <b>postmap</b> <b>-q</b> lookup) and termi-
+ cess (including successful <b>postmap</b> <b>-q</b> lookup) and termi-
nates with non-zero exit status in case of failure.
<b>ENVIRONMENT</b>
Enable verbose logging for debugging purposes.
<b>CONFIGURATION</b> <b>PARAMETERS</b>
- The following <b>main.cf</b> parameters are especially relevant
- to this program. See the Postfix <b>main.cf</b> file for syntax
+ The following <b>main.cf</b> parameters are especially relevant
+ to this program. See the Postfix <b>main.cf</b> file for syntax
details and for default values.
<b>database</b><i>_</i><b>type</b>
- Default alias database type. On many UNIX systems,
+ Default alias database type. On many UNIX systems,
the default type is either <b>dbm</b> or <b>hash</b>.
<b>STANDARDS</b>
<a href="sendmail.1.html">sendmail(1)</a> mail posting and compatibility interface.
<b>LICENSE</b>
- The Secure Mailer license must be distributed with this
+ The Secure Mailer license must be distributed with this
software.
<b>AUTHOR(S)</b>
postmap - Postfix lookup table management
<b>SYNOPSIS</b>
- <b>postmap</b> [<b>-Ninrvw</b>] [<b>-c</b> <i>config_dir</i>] [<b>-d</b> <i>key</i>] [<b>-q</b> <i>key</i>]
+ <b>postmap</b> [<b>-Nfinrvw</b>] [<b>-c</b> <i>config_dir</i>] [<b>-d</b> <i>key</i>] [<b>-q</b> <i>key</i>]
[<i>file_type</i>:]<i>file_name</i> ...
<b>DESCRIPTION</b>
status is zero when at least one of the requested
keys was found.
- <b>-i</b> Incremental mode. Read entries from standard input
+ <b>-f</b> Do not fold the lookup key to lower case while cre-
+ ating a map.
+
+ <b>-i</b> Incremental mode. Read entries from standard input
and do not truncate an existing database. By
- default, <b>postmap</b> creates a new database from the
+ default, <b>postmap</b> creates a new database from the
entries in <b>file</b><i>_</i><b>name</b>.
- <b>-n</b> Don't include the terminating null character that
- terminates lookup keys and values. By default,
- Postfix does whatever is the default for the host
+ <b>-n</b> Don't include the terminating null character that
+ terminates lookup keys and values. By default,
+ Postfix does whatever is the default for the host
operating system.
- <b>-q</b> <i>key</i> Search the specified maps for <i>key</i> and print the
- first value found on the standard output stream.
+ <b>-q</b> <i>key</i> Search the specified maps for <i>key</i> and print the
+ first value found on the standard output stream.
The exit status is zero when the requested informa-
tion was found.
If a key value of <b>-</b> is specified, the program reads
- key values from the standard input stream and
- prints one line of <i>key</i> <i>value</i> output for each key
- that was found. The exit status is zero when at
+ key values from the standard input stream and
+ prints one line of <i>key</i> <i>value</i> output for each key
+ that was found. The exit status is zero when at
least one of the requested keys was found.
- <b>-r</b> When updating a table, do not warn about duplicate
+ <b>-r</b> When updating a table, do not warn about duplicate
entries; silently replace them.
<b>-v</b> Enable verbose logging for debugging purposes. Mul-
- tiple <b>-v</b> options make the software increasingly
+ tiple <b>-v</b> options make the software increasingly
verbose.
- <b>-w</b> When updating a table, do not warn about duplicate
+ <b>-w</b> When updating a table, do not warn about duplicate
entries; silently ignore them.
Arguments:
<i>file_type</i>
The type of database to be produced.
- <b>btree</b> The output file is a btree file, named
- <i>file_name</i><b>.db</b>. This is available only on
+ <b>btree</b> The output file is a btree file, named
+ <i>file_name</i><b>.db</b>. This is available only on
systems with support for <b>db</b> databases.
- <b>dbm</b> The output consists of two files, named
- <i>file_name</i><b>.pag</b> and <i>file_name</i><b>.dir</b>. This is
- available only on systems with support for
+ <b>dbm</b> The output consists of two files, named
+ <i>file_name</i><b>.pag</b> and <i>file_name</i><b>.dir</b>. This is
+ available only on systems with support for
<b>dbm</b> databases.
- <b>hash</b> The output file is a hashed file, named
- <i>file_name</i><b>.db</b>. This is available only on
+ <b>hash</b> The output file is a hashed file, named
+ <i>file_name</i><b>.db</b>. This is available only on
systems with support for <b>db</b> databases.
- When no <i>file_type</i> is specified, the software uses
- the database type specified via the <b>database</b><i>_</i><b>type</b>
+ When no <i>file_type</i> is specified, the software uses
+ the database type specified via the <b>database</b><i>_</i><b>type</b>
configuration parameter.
<i>file_name</i>
- The name of the lookup table source file when
+ The name of the lookup table source file when
rebuilding a database.
<b>DIAGNOSTICS</b>
stream. No output means no problems. Duplicate entries are
skipped and are flagged with a warning.
- <b>postmap</b> terminates with zero exit status in case of suc-
- cess (including successful <b>postmap</b> <b>-q</b> lookup) and termi-
+ <b>postmap</b> terminates with zero exit status in case of suc-
+ cess (including successful <b>postmap</b> <b>-q</b> lookup) and termi-
nates with non-zero exit status in case of failure.
<b>ENVIRONMENT</b>
<b>CONFIGURATION</b> <b>PARAMETERS</b>
<b>database</b><i>_</i><b>type</b>
- Default output database type. On many UNIX sys-
- tems, the default database type is either <b>hash</b> or
+ Default output database type. On many UNIX sys-
+ tems, the default database type is either <b>hash</b> or
<b>dbm</b>.
<b>LICENSE</b>
- The Secure Mailer license must be distributed with this
+ The Secure Mailer license must be distributed with this
software.
<b>AUTHOR(S)</b>
.na
.nf
.fi
-\fBpostalias\fR [\fB-Ninrvw\fR] [\fB-c \fIconfig_dir\fR]
+\fBpostalias\fR [\fB-Nfinrvw\fR] [\fB-c \fIconfig_dir\fR]
[\fB-d \fIkey\fR] [\fB-q \fIkey\fR]
[\fIfile_type\fR:]\fIfile_name\fR ...
.SH DESCRIPTION
If a key value of \fB-\fR is specified, the program reads key
values from the standard input stream. The exit status is zero
when at least one of the requested keys was found.
+.IP \fB-f\fR
+Do not fold the lookup key to lower case while creating a map.
.IP \fB-i\fR
Incremental mode. Read entries from standard input and do not
truncate an existing database. By default, \fBpostalias\fR creates
.na
.nf
.fi
-\fBpostmap\fR [\fB-Ninrvw\fR] [\fB-c \fIconfig_dir\fR] [\fB-d \fIkey\fR]
-[\fB-q \fIkey\fR] [\fIfile_type\fR:]\fIfile_name\fR ...
+\fBpostmap\fR [\fB-Nfinrvw\fR] [\fB-c \fIconfig_dir\fR]
+[\fB-d \fIkey\fR] [\fB-q \fIkey\fR]
+[\fIfile_type\fR:]\fIfile_name\fR ...
.SH DESCRIPTION
.ad
.fi
If a key value of \fB-\fR is specified, the program reads key
values from the standard input stream. The exit status is zero
when at least one of the requested keys was found.
+.IP \fB-f\fR
+Do not fold the lookup key to lower case while creating a map.
.IP \fB-i\fR
Incremental mode. Read entries from standard input and do not
truncate an existing database. By default, \fBpostmap\fR creates
bounce.o: ../../include/mail_proto.h
bounce.o: ../../include/iostuff.h
bounce.o: ../../include/attr.h
-bounce.o: ../../include/htable.h
bounce.o: ../../include/mail_queue.h
bounce.o: ../../include/mail_params.h
bounce.o: ../../include/mail_conf.h
#define REALLY_BOUNCE 1
#define JUST_WARN 0
- if (attr_scan(client, ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA | ATTR_FLAG_MORE,
+ if (attr_scan(client, ATTR_FLAG_STRICT | ATTR_FLAG_MORE,
ATTR_TYPE_NUM, MAIL_ATTR_NREQ, &command, 0) != 1) {
msg_warn("malformed request");
status = -1;
cleanup.o: ../../include/mail_proto.h
cleanup.o: ../../include/iostuff.h
cleanup.o: ../../include/attr.h
-cleanup.o: ../../include/htable.h
cleanup.o: ../../include/mail_params.h
cleanup.o: ../../include/record.h
cleanup.o: ../../include/rec_type.h
cleanup_api.o: ../../include/mail_proto.h
cleanup_api.o: ../../include/iostuff.h
cleanup_api.o: ../../include/attr.h
-cleanup_api.o: ../../include/htable.h
cleanup_api.o: ../../include/bounce.h
cleanup_api.o: ../../include/mail_params.h
cleanup_api.o: ../../include/mail_stream.h
attr_print(src, ATTR_FLAG_NONE,
ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, state->queue_id,
ATTR_TYPE_END);
- if (attr_scan(src, ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA,
+ if (attr_scan(src, ATTR_FLAG_STRICT,
ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, &flags) != 1) {
state->errs |= CLEANUP_STAT_BAD;
flags = 0;
if (bounce_append(BOUNCE_FLAG_CLEAN, state->queue_id,
state->recip ? state->recip : "unknown",
"cleanup", state->time,
- "Message processing aborted: %s", state->reason ?
- state->reason : cleanup_strerror(state->errs)) == 0
+ "%s", state->reason ? state->reason :
+ cleanup_strerror(state->errs)) == 0
&& bounce_flush(BOUNCE_FLAG_CLEAN, MAIL_QUEUE_INCOMING,
state->queue_id, state->sender) == 0) {
state->errs = 0;
* routine that takes an error code and an optional text.
*/
if (strncasecmp(value, "REJECT", reason - value) == 0) {
- if (state->reason == 0)
+ if (state->reason == 0) {
+ while (*reason && ISSPACE(*reason))
+ reason++;
state->reason = mystrdup(*reason ? reason :
cleanup_strerror(CLEANUP_STAT_CONT));
+ }
state->errs |= CLEANUP_STAT_CONT;
return (1);
} else {
if (peekfd(vstream_fileno(client_stream)) <= 2 ?
(vstring_get_null(request, client_stream) != VSTREAM_EOF) :
(attr_scan(client_stream,
- ATTR_FLAG_MORE | ATTR_FLAG_EXTRA | ATTR_FLAG_MISSING,
+ ATTR_FLAG_MORE | ATTR_FLAG_STRICT,
ATTR_TYPE_STR, MAIL_ATTR_REQ, request,
ATTR_TYPE_END) == 1)) {
if (STREQ(STR(request), FLUSH_REQ_ADD)) {
site = vstring_alloc(10);
queue_id = vstring_alloc(10);
- if (attr_scan(client_stream, ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA,
+ if (attr_scan(client_stream, ATTR_FLAG_STRICT,
ATTR_TYPE_STR, MAIL_ATTR_SITE, site,
ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, queue_id,
ATTR_TYPE_END) == 2
ATTR_TYPE_END);
} else if (STREQ(STR(request), FLUSH_REQ_SEND)) {
site = vstring_alloc(10);
- if (attr_scan(client_stream, ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA,
+ if (attr_scan(client_stream, ATTR_FLAG_STRICT,
ATTR_TYPE_STR, MAIL_ATTR_SITE, site,
ATTR_TYPE_END) == 1)
status = flush_send_service(lowercase(STR(site)));
abounce.o: mail_proto.h
abounce.o: ../../include/iostuff.h
abounce.o: ../../include/attr.h
-abounce.o: ../../include/htable.h
abounce.o: abounce.h
abounce.o: bounce.h
been_here.o: been_here.c
been_here.o: ../../include/vbuf.h
been_here.o: ../../include/stringops.h
been_here.o: been_here.h
-been_here_level.o: been_here_level.c
-been_here_level.o: ../../include/sys_defs.h
-been_here_level.o: ../../include/msg.h
-been_here_level.o: ../../include/mymalloc.h
-been_here_level.o: ../../include/htable.h
-been_here_level.o: ../../include/vstring.h
-been_here_level.o: ../../include/vbuf.h
-been_here_level.o: ../../include/stringops.h
-been_here_level.o: been_here.h
bounce.o: bounce.c
bounce.o: ../../include/sys_defs.h
bounce.o: ../../include/msg.h
bounce.o: ../../include/vstream.h
bounce.o: ../../include/iostuff.h
bounce.o: ../../include/attr.h
-bounce.o: ../../include/htable.h
bounce.o: defer.h
bounce.o: bounce.h
bounce_log.o: bounce_log.c
clnt_stream.o: ../../include/iostuff.h
clnt_stream.o: mail_proto.h
clnt_stream.o: ../../include/attr.h
-clnt_stream.o: ../../include/htable.h
clnt_stream.o: mail_params.h
clnt_stream.o: clnt_stream.h
debug_peer.o: debug_peer.c
defer.o: mail_proto.h
defer.o: ../../include/iostuff.h
defer.o: ../../include/attr.h
-defer.o: ../../include/htable.h
defer.o: flush_clnt.h
defer.o: bounce.h
defer.o: defer.h
deliver_pass.o: mail_proto.h
deliver_pass.o: ../../include/iostuff.h
deliver_pass.o: ../../include/attr.h
-deliver_pass.o: ../../include/htable.h
deliver_request.o: deliver_request.c
deliver_request.o: ../../include/sys_defs.h
deliver_request.o: ../../include/msg.h
deliver_request.o: mail_queue.h
deliver_request.o: mail_proto.h
deliver_request.o: ../../include/attr.h
-deliver_request.o: ../../include/htable.h
deliver_request.o: mail_open_ok.h
deliver_request.o: recipient_list.h
deliver_request.o: deliver_request.h
flush_clnt.o: mail_proto.h
flush_clnt.o: ../../include/iostuff.h
flush_clnt.o: ../../include/attr.h
-flush_clnt.o: ../../include/htable.h
flush_clnt.o: mail_flush.h
flush_clnt.o: flush_clnt.h
flush_clnt.o: mail_params.h
mail_command_client.o: mail_proto.h
mail_command_client.o: ../../include/iostuff.h
mail_command_client.o: ../../include/attr.h
-mail_command_client.o: ../../include/htable.h
-mail_command_read.o: mail_command_read.c
-mail_command_read.o: ../../include/sys_defs.h
-mail_command_read.o: ../../include/vstring.h
-mail_command_read.o: ../../include/vbuf.h
-mail_command_read.o: ../../include/vstream.h
-mail_command_read.o: mail_proto.h
-mail_command_read.o: ../../include/iostuff.h
-mail_command_read.o: ../../include/attr.h
-mail_command_read.o: ../../include/htable.h
mail_command_server.o: mail_command_server.c
mail_command_server.o: ../../include/sys_defs.h
mail_command_server.o: ../../include/vstream.h
mail_command_server.o: mail_proto.h
mail_command_server.o: ../../include/iostuff.h
mail_command_server.o: ../../include/attr.h
-mail_command_server.o: ../../include/htable.h
-mail_command_write.o: mail_command_write.c
-mail_command_write.o: ../../include/sys_defs.h
-mail_command_write.o: ../../include/vstream.h
-mail_command_write.o: ../../include/vbuf.h
-mail_command_write.o: mail_proto.h
-mail_command_write.o: ../../include/iostuff.h
-mail_command_write.o: ../../include/attr.h
-mail_command_write.o: ../../include/htable.h
mail_conf.o: mail_conf.c
mail_conf.o: ../../include/sys_defs.h
mail_conf.o: ../../include/msg.h
mail_connect.o: timed_ipc.h
mail_connect.o: mail_proto.h
mail_connect.o: ../../include/attr.h
-mail_connect.o: ../../include/htable.h
mail_copy.o: mail_copy.c
mail_copy.o: ../../include/sys_defs.h
mail_copy.o: ../../include/msg.h
mail_flush.o: ../../include/vbuf.h
mail_flush.o: ../../include/iostuff.h
mail_flush.o: ../../include/attr.h
-mail_flush.o: ../../include/htable.h
mail_flush.o: mail_flush.h
mail_open_ok.o: mail_open_ok.c
mail_open_ok.o: ../../include/sys_defs.h
mail_params.o: ../../include/vstream.h
mail_params.o: ../../include/iostuff.h
mail_params.o: ../../include/attr.h
-mail_params.o: ../../include/htable.h
mail_params.o: verp_sender.h
mail_params.o: mail_params.h
mail_pathname.o: mail_pathname.c
mail_pathname.o: ../../include/vstream.h
mail_pathname.o: ../../include/iostuff.h
mail_pathname.o: ../../include/attr.h
-mail_pathname.o: ../../include/htable.h
-mail_print.o: mail_print.c
-mail_print.o: ../../include/sys_defs.h
-mail_print.o: ../../include/msg.h
-mail_print.o: ../../include/mymalloc.h
-mail_print.o: ../../include/vstream.h
-mail_print.o: ../../include/vbuf.h
-mail_print.o: mail_proto.h
-mail_print.o: ../../include/iostuff.h
-mail_print.o: ../../include/attr.h
-mail_print.o: ../../include/htable.h
mail_queue.o: mail_queue.c
mail_queue.o: ../../include/sys_defs.h
mail_queue.o: ../../include/msg.h
mail_run.o: ../../include/mymalloc.h
mail_run.o: mail_params.h
mail_run.o: mail_run.h
-mail_scan.o: mail_scan.c
-mail_scan.o: ../../include/sys_defs.h
-mail_scan.o: ../../include/msg.h
-mail_scan.o: ../../include/vstring.h
-mail_scan.o: ../../include/vbuf.h
-mail_scan.o: ../../include/vstream.h
-mail_scan.o: ../../include/vstring_vstream.h
-mail_scan.o: ../../include/mymalloc.h
-mail_scan.o: mail_proto.h
-mail_scan.o: ../../include/iostuff.h
-mail_scan.o: ../../include/attr.h
-mail_scan.o: ../../include/htable.h
mail_scan_dir.o: mail_scan_dir.c
mail_scan_dir.o: ../../include/sys_defs.h
mail_scan_dir.o: ../../include/scan_dir.h
mail_stream.o: mail_proto.h
mail_stream.o: ../../include/iostuff.h
mail_stream.o: ../../include/attr.h
-mail_stream.o: ../../include/htable.h
mail_stream.o: mail_queue.h
mail_stream.o: opened.h
mail_stream.o: mail_params.h
mail_trigger.o: ../../include/vstream.h
mail_trigger.o: ../../include/vbuf.h
mail_trigger.o: ../../include/attr.h
-mail_trigger.o: ../../include/htable.h
mail_version.o: mail_version.c
maps.o: maps.c
maps.o: ../../include/sys_defs.h
post_mail.o: mail_proto.h
post_mail.o: ../../include/iostuff.h
post_mail.o: ../../include/attr.h
-post_mail.o: ../../include/htable.h
post_mail.o: cleanup_user.h
post_mail.o: post_mail.h
post_mail.o: mail_date.h
resolve_clnt.o: ../../include/iostuff.h
resolve_clnt.o: mail_proto.h
resolve_clnt.o: ../../include/attr.h
-resolve_clnt.o: ../../include/htable.h
resolve_clnt.o: mail_params.h
resolve_clnt.o: clnt_stream.h
resolve_clnt.o: resolve_clnt.h
rewrite_clnt.o: quote_822_local.h
rewrite_clnt.o: mail_proto.h
rewrite_clnt.o: ../../include/attr.h
-rewrite_clnt.o: ../../include/htable.h
rewrite_clnt.o: mail_params.h
rewrite_clnt.o: clnt_stream.h
rewrite_clnt.o: rewrite_clnt.h
int status;
event_disable_readwrite(vstream_fileno(ap->fp));
- abounce_done(ap, attr_scan(ap->fp, ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA,
+ abounce_done(ap, attr_scan(ap->fp, ATTR_FLAG_STRICT,
ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &status,
ATTR_TYPE_END) == 1 ? status : -1);
}
{
int stat;
- if (attr_scan(stream, ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA,
+ if (attr_scan(stream, ATTR_FLAG_STRICT,
ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &stat,
ATTR_TYPE_END) != 1) {
msg_warn("%s: malformed response", VSTREAM_PATH(stream));
{
int stat;
- if (attr_scan(stream, ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA,
+ if (attr_scan(stream, ATTR_FLAG_STRICT,
ATTR_TYPE_STR, MAIL_ATTR_WHY, reason,
ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &stat,
ATTR_TYPE_END) != 2) {
* Extract the queue file name, data offset, and sender address. Abort
* the conversation when they send bad information.
*/
- if (attr_scan(stream, ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA | ATTR_FLAG_MORE,
+ if (attr_scan(stream, ATTR_FLAG_STRICT | ATTR_FLAG_MORE,
ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, &request->flags,
ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue_name,
ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, queue_id,
* attributes from the sender that we do not understand.
*/
for (;;) {
- if (attr_scan(stream, ATTR_FLAG_MORE | ATTR_FLAG_EXTRA,
+ if (attr_scan(stream, ATTR_FLAG_MORE | ATTR_FLAG_STRICT,
ATTR_TYPE_NUM, MAIL_ATTR_OFFSET, &offset,
ATTR_TYPE_END) != 1)
return (-1);
if (offset == 0)
break;
- if (attr_scan(stream, ATTR_FLAG_MORE | ATTR_FLAG_EXTRA,
+ if (attr_scan(stream, ATTR_FLAG_MORE | ATTR_FLAG_STRICT,
ATTR_TYPE_STR, MAIL_ATTR_RECIP, address,
ATTR_TYPE_END) != 1)
return (-1);
status = attr_vprint(stream, ATTR_FLAG_NONE, ap);
va_end(ap);
if (status != 0
- || attr_scan(stream, ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA,
+ || attr_scan(stream, ATTR_FLAG_STRICT,
ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &status, 0) != 1)
status = -1;
(void) vstream_fclose(stream);
+++ /dev/null
-/*++
-/* NAME
-/* mail_command_read 3
-/* SUMMARY
-/* single-command server
-/* SYNOPSIS
-/* #include <mail_proto.h>
-/*
-/* int mail_command_read(stream, format, ...)
-/* VSTREAM *stream;
-/* char *format;
-/* DESCRIPTION
-/* This module implements the server interface for single-command
-/* requests: a clients sends a single command and expects a single
-/* completion status code.
-/*
-/* Arguments:
-/* .IP stream
-/* Server endpoint.
-/* .IP format
-/* Format string understood by mail_print(3) and mail_scan(3).
-/* DIAGNOSTICS
-/* Fatal: out of memory.
-/* SEE ALSO
-/* mail_scan(3)
-/* mail_command_write(3) client interface
-/* 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 <stdlib.h> /* 44BSD stdarg.h uses abort() */
-#include <stdarg.h>
-#include <string.h>
-
-/* Utility library. */
-
-#include <vstring.h>
-#include <vstream.h>
-
-/* Global library. */
-
-#include "mail_proto.h"
-
-/* mail_command_read - read single-command request */
-
-int mail_command_read(VSTREAM *stream, char *fmt,...)
-{
- VSTRING *eof = vstring_alloc(10);
- va_list ap;
- int count;
-
- va_start(ap, fmt);
- count = mail_vscan(stream, fmt, ap);
- va_end(ap);
- if (mail_scan(stream, "%s", eof) != 1 || strcmp(vstring_str(eof), MAIL_EOF))
- count = -1;
- vstring_free(eof);
- return (count);
-}
+++ /dev/null
-/*++
-/* NAME
-/* mail_command_write 3
-/* SUMMARY
-/* single-command client
-/* SYNOPSIS
-/* #include <mail_proto.h>
-/*
-/* int mail_command_write(class, name, format, ...)
-/* const char *class;
-/* const char *name;
-/* const char *format;
-/* DESCRIPTION
-/* This module implements a client interface for single-command
-/* clients: a client that sends a single command and expects
-/* a single completion status code.
-/*
-/* Arguments:
-/* .IP class
-/* Service type: MAIL_CLASS_PUBLIC or MAIL_CLASS_PRIVATE
-/* .IP name
-/* Service name (master.cf).
-/* .IP format
-/* Format string understood by mail_print(3).
-/* DIAGNOSTICS
-/* The result is -1 if the request could not be sent, otherwise
-/* the result is the status reported by the server.
-/* Warnings: problems connecting to the requested service.
-/* Fatal: out of memory.
-/* SEE ALSO
-/* mail_command_read(3), server interface
-/* mail_proto(5h), client-server protocol
-/* 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 <stdlib.h> /* 44BSD stdarg.h uses abort() */
-#include <stdarg.h>
-
-/* Utility library. */
-
-#include <vstream.h>
-
-/* Global library. */
-
-#include "mail_proto.h"
-
-/* mail_command_write - single-command transaction with completion status */
-
-int mail_command_write(const char *class, const char *name,
- const char *fmt,...)
-{
- va_list ap;
- VSTREAM *stream;
- int status;
-
- /*
- * Talk a little protocol with the specified service.
- */
- if ((stream = mail_connect(class, name, BLOCKING)) == 0)
- return (-1);
- va_start(ap, fmt);
- status = mail_vprint(stream, fmt, ap);
- va_end(ap);
- if (status != 0
- || mail_print(stream, "%s", MAIL_EOF) != 0
- || vstream_fflush(stream) != 0
- || mail_scan(stream, "%d", &status) != 1)
- status = -1;
- (void) vstream_fclose(stream);
- return (status);
-}
msg_info("connect to subsystem %s", path);
stream = vstream_fdopen(fd, O_RDWR);
timed_ipc_setup(stream);
- sock_name = concatenate("socket ", path, (char *) 0);
+ sock_name = concatenate(path, " socket", (char *) 0);
vstream_control(stream,
VSTREAM_CTL_PATH, sock_name,
VSTREAM_CTL_END);
+++ /dev/null
-/*++
-/* NAME
-/* mail_print 3
-/* SUMMARY
-/* intra-mail system write routine
-/* SYNOPSIS
-/* #include <mail_proto.h>
-/*
-/* int mail_print(stream, format, ...)
-/* VSTREAM *stream;
-/* const char *format;
-/*
-/* int mail_vprint(stream, format, ap)
-/* VSTREAM *stream;
-/* const char *format;
-/* va_list ap;
-/*
-/* void mail_print_register(letter, name, print_fn)
-/* int letter;
-/* const char *name;
-/* void (*print_fn)(VSTREAM *stream, const char *data);
-/* DESCRIPTION
-/* mail_print() prints one or more null-delimited strings to
-/* the named stream, each string being converted according to the
-/* contents of the \fIformat\fR argument.
-/*
-/* mail_vprint() provides an alternative interface.
-/*
-/* mail_print_register() registers the named print function for
-/* the specified letter, for the named type.
-/*
-/* Arguments:
-/* .IP stream
-/* The stream to print to.
-/* .IP format
-/* Format string, which is interpreted as follows:
-/* .RS
-/* .IP "white space"
-/* White space in the format string is ignored.
-/* .IP %s
-/* The corresponding argument has type (char *).
-/* .IP %d
-/* The corresponding argument has type (int).
-/* .IP %ld
-/* The corresponding argument has type (long).
-/* .IP %letter
-/* Call the print routine that was registered for the specified letter.
-/* .PP
-/* Anything else in a format string is a fatal error.
-/* .RE
-/* .IP letter
-/* Format letter that is bound to the \fIprint_fn\fR print function.
-/* .IP name
-/* Descriptive string for verbose logging.
-/* .IP print_fn
-/* A print function. It takes as arguments:
-/* .RS
-/* .IP stream
-/* The stream to print to.
-/* .IP data
-/* A generic data pointer. It is up to the function
-/* to do any necessary casts to the data-specific type.
-/* .RE
-/* 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 <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <ctype.h>
-
-/* Utility library. */
-
-#include <msg.h>
-#include <mymalloc.h>
-#include <vstream.h>
-
-/* Global library. */
-
-#include "mail_proto.h"
-
- /*
- * Provision for the user to register type-specific scanners for
- * applications with unusual requirements.
- */
-typedef struct {
- int letter;
- char *name;
- MAIL_PRINT_FN print_fn;
-} MAIL_PRINT;
-
-MAIL_PRINT *mail_print_tab = 0;
-int mail_print_tablen = 0;
-
-/* mail_print_register - register printer function */
-
-void mail_print_register(int letter, const char *name, MAIL_PRINT_FN print_fn)
-{
- MAIL_PRINT *tp;
-
- for (tp = 0; tp < mail_print_tab + mail_print_tablen; tp++)
- if (tp->letter == letter)
- msg_panic("mail_print_register: redefined letter: %c", letter);
-
- /*
- * Tight fit allocation. We're not registering lots of characters.
- */
- if (mail_print_tab == 0) {
- mail_print_tablen = 1;
- mail_print_tab = (MAIL_PRINT *)
- mymalloc(sizeof(*mail_print_tab) * mail_print_tablen);
- } else {
- mail_print_tablen++;
- mail_print_tab = (MAIL_PRINT *)
- myrealloc((char *) mail_print_tab,
- sizeof(*mail_print_tab) * mail_print_tablen);
- }
- tp = mail_print_tab + mail_print_tablen - 1;
- tp->letter = letter;
- tp->name = mystrdup(name);
- tp->print_fn = print_fn;
-}
-
-/* mail_vprint - print null-delimited data to stream */
-
-int mail_vprint(VSTREAM *stream, const char *fmt, va_list ap)
-{
- const char *cp;
- int lflag;
- char *sval;
- int ival;
- long lval;
- int error;
- MAIL_PRINT *tp;
-
- for (cp = fmt; (error = vstream_ferror(stream)) == 0 && *cp != 0; cp++) {
- if (ISSPACE(*cp))
- continue;
- if (*cp != '%')
- msg_fatal("mail_vprint: bad format: %.*s>%c<%s",
- (int) (cp - fmt), fmt, *cp, cp + 1);
- if ((lflag = (*++cp == 'l')) != 0)
- cp++;
-
- switch (*cp) {
- case 's':
- sval = va_arg(ap, char *);
- if (msg_verbose)
- msg_info("print string: %s", sval);
- vstream_fputs(sval, stream);
- VSTREAM_PUTC(0, stream);
- break;
- case 'd':
- if (lflag) {
- lval = va_arg(ap, long);
- if (msg_verbose)
- msg_info("print long: %ld", lval);
- vstream_fprintf(stream, "%ld", lval);
- } else {
- ival = va_arg(ap, int);
- if (msg_verbose)
- msg_info("print int: %d", ival);
- vstream_fprintf(stream, "%d", ival);
- }
- VSTREAM_PUTC(0, stream);
- break;
- default:
- for (tp = mail_print_tab; tp < mail_print_tab + mail_print_tablen; tp++)
- if (tp->letter == *cp) {
- if (msg_verbose)
- msg_info("print %s", tp->name);
- tp->print_fn(stream, va_arg(ap, char *));
- break;
- }
- if (tp >= mail_print_tab + mail_print_tablen)
- msg_fatal("mail_vprint: bad format: %.*s>%c<%s",
- (int) (cp - fmt), fmt, *cp, cp + 1);
- }
- }
- return (error);
-}
-
-/* mail_print - print null-delimited data to stream */
-
-int mail_print(VSTREAM *stream, const char *fmt,...)
-{
- int status;
- va_list ap;
-
- va_start(ap, fmt);
- status = mail_vprint(stream, fmt, ap);
- va_end(ap);
- return (status);
-}
#define MAIL_CLASS_PUBLIC "public"
#define MAIL_CLASS_PRIVATE "private"
- /*
- * When sending across a list of objects, this is how we signal the list
- * end.
- */
-#define MAIL_EOF "@"
-
/*
* Generic triggers.
*/
/*
* Functional interface.
*/
-#define MAIL_SCAN_MORE 0
-#define MAIL_SCAN_DONE 1
-#define MAIL_SCAN_ERROR -1
-
-typedef int (*MAIL_SCAN_FN) (const char *, char *);
-typedef void (*MAIL_PRINT_FN) (VSTREAM *, const char *);
extern VSTREAM *mail_connect(const char *, const char *, int);
extern VSTREAM *mail_connect_wait(const char *, const char *);
-extern int mail_scan(VSTREAM *, const char *,...);
-extern void mail_scan_register(int, const char *, MAIL_SCAN_FN);
-extern void mail_print_register(int, const char *, MAIL_PRINT_FN);
-extern int PRINTFLIKE(2, 3) mail_print(VSTREAM *, const char *,...);
extern int mail_command_client(const char *, const char *,...);
extern int mail_command_server(VSTREAM *,...);
extern int mail_trigger(const char *, const char *, const char *, int);
extern char *mail_pathname(const char *, const char *);
- /*
- * Stuff that needs <stdarg.h>
- */
-extern int mail_vprint(VSTREAM *, const char *, va_list);
-extern int mail_vscan(VSTREAM *, const char *, va_list);
-
/*
* Attribute names.
*/
+++ /dev/null
-/*++
-/* NAME
-/* mail_scan 3
-/* SUMMARY
-/* intra-mail read routine
-/* SYNOPSIS
-/* #include <mail_proto.h>
-/*
-/* int mail_scan(stream, format, ...)
-/* VSTREAM *stream;
-/* const char *format;
-/*
-/* void mail_scan_register(letter, name, scan_fn)
-/* int letter;
-/* const char *name;
-/* int (*scan_fn)(const char *string, char *result);
-/* DESCRIPTION
-/* mail_scan() reads one or more null-delimited strings from
-/* the named stream, each string being converted according to the
-/* contents of the \fIformat\fR argument.
-/* The result value is the number of successful conversions.
-/*
-/* mail_scan_register() registers an input conversion function
-/* for the specified letter.
-/*
-/* Arguments:
-/* .IP stream
-/* Stream to read from.
-/* .IP format
-/* Format string, which is interpreted as follows:
-/* .RS
-/* .IP "white space"
-/* White space in the format string is ignored.
-/* .IP %s
-/* The corresponding argument has type (VSTRING *).
-/* .IP %d
-/* The corresponding argument has type (int *).
-/* .IP %ld
-/* The corresponding argument has type (long *).
-/* .IP %letter
-/* Call the input conversion routine that was registered for
-/* the specified letter.
-/* .PP
-/* Anything else in a format string is a fatal error.
-/* .RE
-/* .IP letter
-/* Format letter that is bound to the \fIscan_fn\fR input
-/* conversion function.
-/* .IP name
-/* Descriptive string for verbose logging.
-/* .IP scan_fn
-/* An input conversion function. It takes as arguments:
-/* .RS
-/* .IP string
-/* The null-terminated string to be converted.
-/* .IP result
-/* A character pointer to the result. It is up to the function
-/* to do any necessary casts to the data-specific type.
-/* .RE
-/* .PP
-/* The function result values are as follows:
-/* .RS
-/* .IP MAIL_SCAN_ERROR
-/* The expected input could not be read.
-/* .IP MAIL_SCAN_DONE
-/* The operation completed successfully.
-/* .IP MAIL_SCAN_MORE
-/* More input is expected.
-/* .RE
-/* 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 <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <ctype.h>
-
-/* Utility library. */
-
-#include <msg.h>
-#include <vstring.h>
-#include <vstream.h>
-#include <vstring_vstream.h>
-#include <mymalloc.h>
-
-/* Global library. */
-
-#include "mail_proto.h"
-
- /*
- * Provision for the user to register type-specific input conversion
- * routines for applications with unusual requirements.
- */
-typedef struct {
- int letter;
- char *name;
- MAIL_SCAN_FN scanner;
-} MAIL_SCAN;
-
-MAIL_SCAN *mail_scan_tab = 0;
-int mail_scan_tablen = 0;
-
-/* mail_scan_register - register scanner function */
-
-void mail_scan_register(int letter, const char *name, MAIL_SCAN_FN scanner)
-{
- MAIL_SCAN *tp;
-
- for (tp = 0; tp < mail_scan_tab + mail_scan_tablen; tp++)
- if (tp->letter == letter)
- msg_panic("mail_scan_register: redefined letter: %c", letter);
-
- /*
- * Tight fit allocation (as in: Robin Hood and the men that wear tights).
- */
- if (mail_scan_tab == 0) {
- mail_scan_tablen = 1;
- mail_scan_tab = (MAIL_SCAN *)
- mymalloc(sizeof(*mail_scan_tab) * mail_scan_tablen);
- } else {
- mail_scan_tablen++;
- mail_scan_tab = (MAIL_SCAN *)
- myrealloc((char *) mail_scan_tab,
- sizeof(*mail_scan_tab) * mail_scan_tablen);
- }
- tp = mail_scan_tab + mail_scan_tablen - 1;
- tp->letter = letter;
- tp->name = mystrdup(name);
- tp->scanner = scanner;
-}
-
-/* mail_scan_any - read one null-delimited string from stream */
-
-static int mail_scan_any(VSTREAM *stream, VSTRING *vp, char *what)
-{
- if (vstring_fgets_null(vp, stream) == 0) {
- msg_warn("end of input while receiving %s data from service %s",
- what, VSTREAM_PATH(stream));
- return (-1);
- }
- if (msg_verbose)
- msg_info("mail_scan_any: read %s: %s", what, vstring_str(vp));
- return (0);
-}
-
-/* mail_scan_other - read user-defined type from stream */
-
-static int mail_scan_other(VSTREAM *stream, VSTRING *vp,
- MAIL_SCAN *tp, char *result)
-{
- int ret;
-
- while ((ret = mail_scan_any(stream, vp, tp->name)) == 0) {
- switch (tp->scanner(vstring_str(vp), result)) {
- case MAIL_SCAN_MORE:
- break;
- case MAIL_SCAN_DONE:
- return (0);
- case MAIL_SCAN_ERROR:
- return (-1);
- }
- }
- return (ret);
-}
-
-/* mail_scan_long - read long integer from stream */
-
-static int mail_scan_long(VSTREAM *stream, VSTRING *vp, long *lp)
-{
- int ret;
- char junk;
-
- if ((ret = mail_scan_any(stream, vp, "long integer")) == 0) {
- if (sscanf(vstring_str(vp), "%ld%c", lp, &junk) != 1) {
- msg_warn("mail_scan_long: bad long long: %s", vstring_str(vp));
- ret = -1;
- }
- }
- return (ret);
-}
-
-/* mail_scan_int - read integer from stream */
-
-static int mail_scan_int(VSTREAM *stream, VSTRING *vp, int *lp)
-{
- int ret;
- char junk;
-
- if ((ret = mail_scan_any(stream, vp, "integer")) == 0) {
- if (sscanf(vstring_str(vp), "%d%c", lp, &junk) != 1) {
- msg_warn("mail_scan_int: bad integer: %s", vstring_str(vp));
- ret = -1;
- }
- }
- return (ret);
-}
-
-/* mail_scan - read null-delimited data from stream */
-
-int mail_scan(VSTREAM *stream, const char *fmt,...)
-{
- va_list ap;
- int count;
-
- va_start(ap, fmt);
- count = mail_vscan(stream, fmt, ap);
- va_end(ap);
- return (count);
-}
-
-/* mail_vscan - read null-delimited data from stream */
-
-int mail_vscan(VSTREAM *stream, const char *fmt, va_list ap)
-{
- const char *cp;
- int lflag;
- int count;
- int error;
- static VSTRING *tmp;
- MAIL_SCAN *tp;
-
- if (tmp == 0)
- tmp = vstring_alloc(100);
-
- for (count = 0, error = 0, cp = fmt; error == 0 && *cp != 0; cp++) {
- if (ISSPACE(*cp))
- continue;
- if (*cp != '%')
- msg_fatal("mail_scan: bad format: %.*s>%c<%s",
- (int) (cp - fmt), fmt, *cp, cp + 1);
- if ((lflag = (*++cp == 'l')) != 0)
- cp++;
-
- switch (*cp) {
- case 's':
- error = mail_scan_any(stream, va_arg(ap, VSTRING *), "string");
- break;
- case 'd':
- if (lflag)
- error = mail_scan_long(stream, tmp, va_arg(ap, long *));
- else
- error = mail_scan_int(stream, tmp, va_arg(ap, int *));
- break;
- default:
- for (tp = mail_scan_tab; tp < mail_scan_tab + mail_scan_tablen; tp++)
- if (tp->letter == *cp) {
- if (msg_verbose)
- msg_info("mail_scan: %s", tp->name);
- error = mail_scan_other(stream, tmp, tp, va_arg(ap, char *));
- break;
- }
- if (tp >= mail_scan_tab + mail_scan_tablen)
- msg_fatal("mail_scan: bad format: %.*s>%c<%s",
- (int) (cp - fmt), fmt, *cp, cp + 1);
- }
- if (error == 0)
- count++;
- }
- return (count);
-}
/*
* Receive the peer's completion status.
*/
- if ((why && attr_scan(info->stream, ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA,
+ if ((why && attr_scan(info->stream, ATTR_FLAG_STRICT,
ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &status,
ATTR_TYPE_STR, MAIL_ATTR_WHY, why,
ATTR_TYPE_END) != 2)
* Version of this program.
*/
#define VAR_MAIL_VERSION "mail_version"
-#define DEF_MAIL_VERSION "Snapshot-20011101"
+#define DEF_MAIL_VERSION "Snapshot-20011102"
extern char *var_mail_version;
/* LICENSE
/*
* Negotiate with the cleanup service. Give up if we can't agree.
*/
- if (attr_scan(stream, ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA,
+ if (attr_scan(stream, ATTR_FLAG_STRICT,
ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id,
ATTR_TYPE_END) != 1
|| attr_print(stream, ATTR_FLAG_NONE,
|| vstream_fflush(stream)) {
if (msg_verbose || (errno != EPIPE && errno != ENOENT))
msg_warn("%s: bad write: %m", myname);
- } else if (attr_scan(stream, ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA,
+ } else if (attr_scan(stream, ATTR_FLAG_STRICT,
ATTR_TYPE_STR, MAIL_ATTR_TRANSPORT, reply->transport,
ATTR_TYPE_STR, MAIL_ATTR_NEXTHOP, reply->nexthop,
vstream_fflush(stream)) {
if (msg_verbose || (errno != EPIPE && errno != ENOENT))
msg_warn("%s: bad write: %m", myname);
- } else if (attr_scan(stream, ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA,
+ } else if (attr_scan(stream, ATTR_FLAG_STRICT,
ATTR_TYPE_STR, MAIL_ATTR_ADDR, result,
ATTR_TYPE_END) != 1) {
if (msg_verbose || (errno != EPIPE && errno != ENOENT))
lmtp_connect.o: ../../include/mail_params.h
lmtp_connect.o: ../../include/mail_proto.h
lmtp_connect.o: ../../include/attr.h
-lmtp_connect.o: ../../include/htable.h
lmtp_connect.o: ../../include/dns.h
lmtp_connect.o: lmtp.h
lmtp_connect.o: ../../include/argv.h
unknown.o: ../../include/vstream.h
unknown.o: ../../include/iostuff.h
unknown.o: ../../include/attr.h
-unknown.o: ../../include/htable.h
unknown.o: ../../include/bounce.h
unknown.o: local.h
+unknown.o: ../../include/htable.h
unknown.o: ../../include/tok822.h
unknown.o: ../../include/resolve_clnt.h
unknown.o: ../../include/deliver_request.h
if (cleanup == 0)
return (0);
close_on_exec(vstream_fileno(cleanup), CLOSE_ON_EXEC);
- if (attr_scan(cleanup, ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA,
+ if (attr_scan(cleanup, ATTR_FLAG_STRICT,
ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, buffer,
ATTR_TYPE_END) != 1) {
vstream_fclose(cleanup);
master_ent.o: ../../include/mail_proto.h
master_ent.o: ../../include/iostuff.h
master_ent.o: ../../include/attr.h
-master_ent.o: ../../include/htable.h
master_ent.o: ../../include/mail_params.h
master_ent.o: ../../include/own_inet_addr.h
master_ent.o: master_proto.h
master_wakeup.o: ../../include/vbuf.h
master_wakeup.o: ../../include/iostuff.h
master_wakeup.o: ../../include/attr.h
-master_wakeup.o: ../../include/htable.h
master_wakeup.o: mail_server.h
master_wakeup.o: master.h
multi_server.o: multi_server.c
qmgr.o: ../../include/mail_proto.h
qmgr.o: ../../include/iostuff.h
qmgr.o: ../../include/attr.h
-qmgr.o: ../../include/htable.h
qmgr.o: ../../include/mail_flow.h
qmgr.o: ../../include/master_proto.h
qmgr.o: ../../include/mail_server.h
qmgr_deliver.o: ../../include/mail_queue.h
qmgr_deliver.o: ../../include/mail_proto.h
qmgr_deliver.o: ../../include/attr.h
-qmgr_deliver.o: ../../include/htable.h
qmgr_deliver.o: ../../include/recipient_list.h
qmgr_deliver.o: ../../include/mail_params.h
qmgr_deliver.o: ../../include/deliver_request.h
if (peekfd(vstream_fileno(stream)) < 0) {
msg_warn("%s: premature disconnect", VSTREAM_PATH(stream));
return (DELIVER_STAT_CRASH);
- } else if (attr_scan(stream, ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA,
+ } else if (attr_scan(stream, ATTR_FLAG_STRICT,
ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &stat,
ATTR_TYPE_END) != 1) {
msg_warn("%s: malformed response", VSTREAM_PATH(stream));
if (peekfd(vstream_fileno(stream)) < 0) {
msg_warn("%s: premature disconnect", VSTREAM_PATH(stream));
return (DELIVER_STAT_CRASH);
- } else if (attr_scan(stream, ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA,
+ } else if (attr_scan(stream, ATTR_FLAG_STRICT,
ATTR_TYPE_STR, MAIL_ATTR_WHY, reason,
ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &stat,
ATTR_TYPE_END) != 2) {
pickup.o: ../../include/mail_proto.h
pickup.o: ../../include/iostuff.h
pickup.o: ../../include/attr.h
-pickup.o: ../../include/htable.h
pickup.o: ../../include/cleanup_user.h
pickup.o: ../../include/mail_date.h
pickup.o: ../../include/mail_params.h
buf = vstring_alloc(100);
cleanup = mail_connect_wait(MAIL_CLASS_PRIVATE, MAIL_SERVICE_CLEANUP);
- if (attr_scan(cleanup, ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA,
+ if (attr_scan(cleanup, ATTR_FLAG_STRICT,
ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, buf,
ATTR_TYPE_END) != 1
|| attr_print(cleanup, ATTR_FLAG_NONE,
/* Postfix alias database maintenance
/* SYNOPSIS
/* .fi
-/* \fBpostalias\fR [\fB-Ninrvw\fR] [\fB-c \fIconfig_dir\fR]
+/* \fBpostalias\fR [\fB-Nfinrvw\fR] [\fB-c \fIconfig_dir\fR]
/* [\fB-d \fIkey\fR] [\fB-q \fIkey\fR]
/* [\fIfile_type\fR:]\fIfile_name\fR ...
/* DESCRIPTION
/* If a key value of \fB-\fR is specified, the program reads key
/* values from the standard input stream. The exit status is zero
/* when at least one of the requested keys was found.
+/* .IP \fB-f\fR
+/* Do not fold the lookup key to lower case while creating a map.
/* .IP \fB-i\fR
/* Incremental mode. Read entries from standard input and do not
/* truncate an existing database. By default, \fBpostalias\fR creates
/*
* Store the value under a case-insensitive key.
*/
- lowercase(STR(key_buffer));
+ if (dict_flags & DICT_FLAG_FOLD_KEY)
+ lowercase(STR(key_buffer));
mkmap_append(mkmap, STR(key_buffer), STR(value_buffer));
}
static NORETURN usage(char *myname)
{
- msg_fatal("usage: %s [-Ninrvw] [-c config_dir] [-d key] [-q key] [map_type:]file...",
+ msg_fatal("usage: %s [-Nfinrvw] [-c config_dir] [-d key] [-q key] [map_type:]file...",
myname);
}
char *slash;
struct stat st;
int open_flags = O_RDWR | O_CREAT | O_TRUNC;
- int dict_flags = DICT_FLAG_DUP_WARN;
+ int dict_flags = DICT_FLAG_DUP_WARN | DICT_FLAG_FOLD_KEY;
char *query = 0;
char *delkey = 0;
int found;
/*
* Parse JCL.
*/
- while ((ch = GETOPT(argc, argv, "Nc:d:inq:rvw")) > 0) {
+ while ((ch = GETOPT(argc, argv, "Nc:d:finq:rvw")) > 0) {
switch (ch) {
default:
usage(argv[0]);
msg_fatal("specify only one of -q or -d");
delkey = optarg;
break;
+ case 'f':
+ dict_flags &= ~DICT_FLAG_FOLD_KEY;
+ break;
case 'i':
open_flags &= ~O_TRUNC;
break;
postdrop.o: ../../include/mail_proto.h
postdrop.o: ../../include/iostuff.h
postdrop.o: ../../include/attr.h
-postdrop.o: ../../include/htable.h
postdrop.o: ../../include/mail_queue.h
postdrop.o: ../../include/mail_params.h
postdrop.o: ../../include/mail_conf.h
postkick.o: ../../include/mail_proto.h
postkick.o: ../../include/iostuff.h
postkick.o: ../../include/attr.h
-postkick.o: ../../include/htable.h
postkick.o: ../../include/mail_params.h
postkick.o: ../../include/mail_conf.h
/* Postfix lookup table management
/* SYNOPSIS
/* .fi
-/* \fBpostmap\fR [\fB-Ninrvw\fR] [\fB-c \fIconfig_dir\fR] [\fB-d \fIkey\fR]
-/* [\fB-q \fIkey\fR] [\fIfile_type\fR:]\fIfile_name\fR ...
+/* \fBpostmap\fR [\fB-Nfinrvw\fR] [\fB-c \fIconfig_dir\fR]
+/* [\fB-d \fIkey\fR] [\fB-q \fIkey\fR]
+/* [\fIfile_type\fR:]\fIfile_name\fR ...
/* DESCRIPTION
/* The \fBpostmap\fR command creates or queries one or more Postfix
/* lookup tables, or updates an existing one. The input and output
/* If a key value of \fB-\fR is specified, the program reads key
/* values from the standard input stream. The exit status is zero
/* when at least one of the requested keys was found.
+/* .IP \fB-f\fR
+/* Do not fold the lookup key to lower case while creating a map.
/* .IP \fB-i\fR
/* Incremental mode. Read entries from standard input and do not
/* truncate an existing database. By default, \fBpostmap\fR creates
/*
* Store the value under a case-insensitive key.
*/
- lowercase(key);
+ if (dict_flags & DICT_FLAG_FOLD_KEY)
+ lowercase(key);
mkmap_append(mkmap, key, value);
}
static NORETURN usage(char *myname)
{
- msg_fatal("usage: %s [-Ninrvw] [-c config_dir] [-d key] [-q key] [map_type:]file...",
+ msg_fatal("usage: %s [-Nfinrvw] [-c config_dir] [-d key] [-q key] [map_type:]file...",
myname);
}
char *slash;
struct stat st;
int open_flags = O_RDWR | O_CREAT | O_TRUNC;
- int dict_flags = DICT_FLAG_DUP_WARN;
+ int dict_flags = DICT_FLAG_DUP_WARN | DICT_FLAG_FOLD_KEY;
char *query = 0;
char *delkey = 0;
int found;
/*
* Parse JCL.
*/
- while ((ch = GETOPT(argc, argv, "Nc:d:inq:rvw")) > 0) {
+ while ((ch = GETOPT(argc, argv, "Nc:d:finq:rvw")) > 0) {
switch (ch) {
default:
usage(argv[0]);
msg_fatal("specify only one of -q or -d");
delkey = optarg;
break;
+ case 'f':
+ dict_flags &= ~DICT_FLAG_FOLD_KEY;
+ break;
case 'i':
open_flags &= ~O_TRUNC;
break;
qmgr.o: ../../include/mail_proto.h
qmgr.o: ../../include/iostuff.h
qmgr.o: ../../include/attr.h
-qmgr.o: ../../include/htable.h
qmgr.o: ../../include/mail_flow.h
qmgr.o: ../../include/master_proto.h
qmgr.o: ../../include/mail_server.h
qmgr_deliver.o: ../../include/mail_queue.h
qmgr_deliver.o: ../../include/mail_proto.h
qmgr_deliver.o: ../../include/attr.h
-qmgr_deliver.o: ../../include/htable.h
qmgr_deliver.o: ../../include/recipient_list.h
qmgr_deliver.o: ../../include/mail_params.h
qmgr_deliver.o: ../../include/deliver_request.h
if (peekfd(vstream_fileno(stream)) < 0) {
msg_warn("%s: premature disconnect", VSTREAM_PATH(stream));
return (DELIVER_STAT_CRASH);
- } else if (attr_scan(stream, ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA,
+ } else if (attr_scan(stream, ATTR_FLAG_STRICT,
ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &stat,
ATTR_TYPE_END) != 1) {
msg_warn("%s: malformed response", VSTREAM_PATH(stream));
if (peekfd(vstream_fileno(stream)) < 0) {
msg_warn("%s: premature disconnect", VSTREAM_PATH(stream));
return (DELIVER_STAT_CRASH);
- } else if (attr_scan(stream, ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA,
+ } else if (attr_scan(stream, ATTR_FLAG_STRICT,
ATTR_TYPE_STR, MAIL_ATTR_WHY, reason,
ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &stat,
ATTR_TYPE_END) != 2) {
qmqpd.o: ../../include/mail_proto.h
qmqpd.o: ../../include/iostuff.h
qmqpd.o: ../../include/attr.h
-qmqpd.o: ../../include/htable.h
qmqpd.o: ../../include/cleanup_user.h
qmqpd.o: ../../include/mail_date.h
qmqpd.o: ../../include/mail_conf.h
*/
state->where = "receiving sender address";
netstring_get(state->client, state->buf, var_line_limit);
+ VSTRING_TERMINATE(state->buf);
verp_requested = ((end_prefix = strstr(STR(state->buf), "-@")) != 0
&& (end_origin = strstr(end_prefix + 2, "-@")) != 0
&& strncmp(end_origin + 2, "[]", 2) == 0
sendmail.o: ../../include/mail_queue.h
sendmail.o: ../../include/mail_proto.h
sendmail.o: ../../include/attr.h
-sendmail.o: ../../include/htable.h
sendmail.o: ../../include/mail_params.h
sendmail.o: ../../include/record.h
sendmail.o: ../../include/rec_type.h
smtp.o: ../../include/mail_proto.h
smtp.o: ../../include/iostuff.h
smtp.o: ../../include/attr.h
-smtp.o: ../../include/htable.h
smtp.o: ../../include/mail_server.h
smtp.o: smtp.h
smtp.o: smtp_sasl.h
smtpd.o: ../../include/mail_proto.h
smtpd.o: ../../include/iostuff.h
smtpd.o: ../../include/attr.h
-smtpd.o: ../../include/htable.h
smtpd.o: ../../include/cleanup_user.h
smtpd.o: ../../include/mail_date.h
smtpd.o: ../../include/mail_conf.h
smtpd_chat.o: ../../include/mail_proto.h
smtpd_chat.o: ../../include/iostuff.h
smtpd_chat.o: ../../include/attr.h
-smtpd_chat.o: ../../include/htable.h
smtpd_chat.o: ../../include/mail_params.h
smtpd_chat.o: ../../include/mail_addr.h
smtpd_chat.o: ../../include/post_mail.h
smtpd_sasl_proto.o: ../../include/vbuf.h
smtpd_sasl_proto.o: ../../include/iostuff.h
smtpd_sasl_proto.o: ../../include/attr.h
-smtpd_sasl_proto.o: ../../include/htable.h
smtpd_sasl_proto.o: ../../include/mail_error.h
smtpd_sasl_proto.o: ../../include/name_mask.h
smtpd_sasl_proto.o: smtpd.h
resolve.o: ../../include/mail_proto.h
resolve.o: ../../include/iostuff.h
resolve.o: ../../include/attr.h
-resolve.o: ../../include/htable.h
resolve.o: ../../include/mail_addr.h
resolve.o: ../../include/rewrite_clnt.h
resolve.o: ../../include/resolve_local.h
rewrite.o: ../../include/mail_proto.h
rewrite.o: ../../include/iostuff.h
rewrite.o: ../../include/attr.h
-rewrite.o: ../../include/htable.h
rewrite.o: ../../include/resolve_local.h
rewrite.o: ../../include/tok822.h
rewrite.o: ../../include/resolve_clnt.h
trivial-rewrite.o: ../../include/mail_proto.h
trivial-rewrite.o: ../../include/iostuff.h
trivial-rewrite.o: ../../include/attr.h
-trivial-rewrite.o: ../../include/htable.h
trivial-rewrite.o: ../../include/resolve_local.h
trivial-rewrite.o: ../../include/mail_conf.h
trivial-rewrite.o: ../../include/resolve_clnt.h
{
int flags;
- if (attr_scan(stream, ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA,
+ if (attr_scan(stream, ATTR_FLAG_STRICT,
ATTR_TYPE_STR, MAIL_ATTR_ADDR, query,
ATTR_TYPE_END) != 1)
return (-1);
int rewrite_proto(VSTREAM *stream)
{
- if (attr_scan(stream, ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA,
+ if (attr_scan(stream, ATTR_FLAG_STRICT,
ATTR_TYPE_STR, MAIL_ATTR_RULE, ruleset,
ATTR_TYPE_STR, MAIL_ATTR_ADDR, address,
ATTR_TYPE_END) != 2)
* dedicated to address rewriting. All connection-management stuff is
* handled by the common code in multi_server.c.
*/
- if (attr_scan(stream, ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA | ATTR_FLAG_MORE,
+ if (attr_scan(stream, ATTR_FLAG_STRICT | ATTR_FLAG_MORE,
ATTR_TYPE_STR, MAIL_ATTR_REQ, command,
ATTR_TYPE_END) == 1) {
if (strcmp(vstring_str(command), REWRITE_ADDR) == 0) {
$(CC) $(CFLAGS) -o $@ $@.c $(LIB) $(SYSLIBS)
tests: valid_hostname_test mac_expand_test dict_test unescape_test \
- hex_quote_test ctable_test inet_addr_list_test base64_code_test
+ hex_quote_test ctable_test inet_addr_list_test base64_code_test \
+ attr_scan_test
valid_hostname_test: valid_hostname valid_hostname.in valid_hostname.ref
./valid_hostname <valid_hostname.in 2>valid_hostname.tmp
base64_code_test: base64_code
./base64_code
+attr_scan_test: attr_print attr_scan attr_scan.ref
+ (./attr_print 2>&3 | (sleep 1; ./attr_scan)) >attr_scan.tmp 2>&1 3>&1
+ diff attr_scan.ref attr_scan.tmp
+ rm -f attr_scan.tmp
+
DB_TYPE = `../postconf/postconf -h default_database_type`
dict_test: dict_open testdb dict_test.in dict_test.ref
argv_split.o: vstring.h
argv_split.o: vbuf.h
argv_split.o: argv.h
-attr.o: attr.c
-attr.o: sys_defs.h
-attr.o: msg.h
-attr.o: mymalloc.h
-attr.o: htable.h
-attr.o: attr.h
-attr.o: vstream.h
-attr.o: vbuf.h
attr_print.o: attr_print.c
attr_print.o: sys_defs.h
attr_print.o: msg.h
attr_scan.o: vstream.h
attr_scan.o: vbuf.h
attr_scan.o: vstring.h
-attr_scan.o: argv.h
-attr_scan.o: intv.h
+attr_scan.o: htable.h
attr_scan.o: base64_code.h
attr_scan.o: attr.h
-attr_scan.o: htable.h
-attr_table.o: attr_table.c
-attr_table.o: sys_defs.h
-attr_table.o: msg.h
-attr_table.o: htable.h
-attr_table.o: mymalloc.h
-attr_table.o: vstring.h
-attr_table.o: vbuf.h
-attr_table.o: vstream.h
-attr_table.o: vstring_vstream.h
-attr_table.o: argv.h
-attr_table.o: intv.h
-attr_table.o: attr.h
base64_code.o: base64_code.c
base64_code.o: sys_defs.h
base64_code.o: msg.h
-#ifndef _ATTR_PRINT_H_INCLUDED_
-#define _ATTR_PRINT_H_INCLUDED_
+#ifndef _ATTR_H_INCLUDED_
+#define _ATTR_H_INCLUDED_
/*++
/* NAME
* Utility library.
*/
#include <vstream.h>
-#include <htable.h>
/*
- * External interface.
+ * Attribute types. See attr_scan(3) for documentation.
*/
#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_TYPE_HASH 5 /* Hash table */
+#define ATTR_TYPE_HASH 3 /* Hash table */
+ /*
+ * Flags that control processing. See attr_scan(3) for documentation.
+ */
#define ATTR_FLAG_NONE 0
#define ATTR_FLAG_MISSING (1<<0) /* Flag missing attribute */
#define ATTR_FLAG_EXTRA (1<<1) /* Flag spurious attribute */
#define ATTR_FLAG_MORE (1<<2) /* Don't skip or terminate */
+
+#define ATTR_FLAG_STRICT (ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA)
#define ATTR_FLAG_ALL (07)
/*
#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
/* .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_HASH (HTABLE *)"
/* The content of the hash table is sent as a sequence of string-valued
/* attributes with names equal to the hash table lookup key.
char *attr_name;
unsigned int_val;
char *str_val;
- char **cpp_val;
- unsigned *ip_val;
- int count_val;
- int i;
HTABLE_INFO **ht_info_list;
HTABLE_INFO **ht;
* Sanity check.
*/
if (flags & ~ATTR_FLAG_ALL)
- msg_panic("%s: bad flags: 0x%x",
- myname, flags);
+ msg_panic("%s: bad flags: 0x%x", myname, flags);
/*
* Iterate over all (type, name, value) triples, and produce output on
if (msg_verbose)
msg_info("send attr %s = %s", attr_name, str_val);
break;
- case ATTR_TYPE_NUM_ARRAY:
- attr_name = va_arg(ap, char *);
- attr_print_str(fp, attr_name, strlen(attr_name));
- ip_val = va_arg(ap, unsigned int *);
- count_val = va_arg(ap, int);
- for (i = 0; i < count_val; i++) {
- VSTREAM_PUTC(':', fp);
- attr_print_num(fp, (unsigned) *ip_val++);}
- if (msg_verbose)
- msg_info("send attr %s values %d", attr_name, count_val);
- break;
- case ATTR_TYPE_STR_ARRAY:
- attr_name = va_arg(ap, char *);
- attr_print_str(fp, attr_name, strlen(attr_name));
- cpp_val = va_arg(ap, char **);
- count_val = va_arg(ap, int);
- for (i = 0; i < count_val; i++) {
- str_val = *cpp_val++;
- VSTREAM_PUTC(':', fp);
- attr_print_str(fp, str_val, strlen(str_val));
- }
- if (msg_verbose)
- msg_info("send attr %s values %d", attr_name, count_val);
- break;
case ATTR_TYPE_HASH:
ht_info_list = htable_list(va_arg(ap, HTABLE *));
for (ht = ht_info_list; *ht; ht++) {
*/
#include <msg_vstream.h>
-int main(int argc, char **argv)
+int main(int unused_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"};
HTABLE *table = htable_create(1);
msg_vstream_init(argv[0], VSTREAM_ERR);
+ msg_verbose = 1;
htable_enter(table, "foo-name", mystrdup("foo-value"));
htable_enter(table, "bar-name", mystrdup("bar-value"));
attr_print(VSTREAM_OUT, ATTR_FLAG_NONE,
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_HASH, table,
ATTR_TYPE_END);
attr_print(VSTREAM_OUT, ATTR_FLAG_NONE,
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");
/* int flags;
/* va_list ap;
/* 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().
+/* attr_scan() takes zero or more (name, value) request attributes
+/* and recovers the attribute values from the byte stream that was
+/* possibly generated by attr_print().
/*
/* attr_vscan() provides an alternative interface that is convenient
/* for calling from within a variadic function.
/* (item1 | item2) stands for choice:
/*
/* .in +5
-/* input :== attr-list
-/* .br
-/* attr-list :== (simple-attr | list-attr)* newline
+/* attr-list :== simple-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
/* 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.
+/* All attribute names and attribute values are sent as base64-encoded
+/* strings. Each base64-encoded must be no longer than 2*var_line_limit
+/* characters. The formatting rules aim to make implementations in PERL
+/* and other 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.
+/* Normally, attributes must be received in the sequence 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.
+/* Additional input attributes or input attribute instances 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
+/* this is desirable.
/*
/* Arguments:
/* .IP fp
-/* Stream to recover the attributes from.
+/* Stream to recover the input attributes from.
/* .IP flags
/* The bit-wise OR of zero or more of the following.
/* .RS
/* 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. This includes multiple
-/* instances of the same attribute when only one instance is requested.
+/* contains an attribute that was not requested. This includes the
+/* case of additional instances of a requested attribute.
/* .IP ATTR_FLAG_MORE
/* After recovering the requested attributes, leave the input stream
-/* in a state that is usable for more recovery operations on the
+/* in a state that is usable for more attr_scan() operations from the
/* same input attribute list.
-/* By default, attr_scan() skips forward past the attribute list
+/* By default, attr_scan() skips forward past the input attribute list
/* terminator.
+/* .IP ATTR_FLAG_STRICT
+/* For convenience, this value combines both ATTR_FLAG_MISSING and
+/* ATTR_FLAG_EXTRA.
/* .IP ATTR_FLAG_NONE
/* For convenience, this value requests none of the above.
/* .RE
/* .RS
/* .IP "ATTR_TYPE_NUM (char *, int *)"
/* This argument is followed by an attribute name and an integer pointer.
-/* This is used for recovering one simple 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 one simple 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.
-/* Values from the input stream are appended to the array.
-/* .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.
-/* Values from the input stream are appended to the array.
/* .IP "ATTR_TYPE_HASH (HTABLE *)"
-/* All further input attributes are required to be simple string or
-/* integer attributes.
-/* Their string values are stored in the specified hash table under
+/* All further input attributes are processed as string attributes.
+/* In this case, no specific attribute sequence is enforced.
+/* .sp
+/* The attribute string values are stored in the hash table under
/* keys equal to the attribute name (obtained from the input stream).
-/* Values from the input stream are added to the hash table, but existing
+/* Values from the input stream are added to the hash table. Existing
/* hash table entries are not replaced.
/* .sp
/* N.B. This construct must be followed by an ATTR_TYPE_END argument.
/* This argument terminates the requested attribute list.
/* .RE
/* BUGS
-/* ATTR_TYPE_HASH accepts attributes with arbitrary names from an
+/* ATTR_TYPE_HASH accepts attributes with arbitrary names from an
/* untrusted source. This is safe only if the resulting table is
-/* queried for specific names.
+/* queried only with known to be good attribute names.
/* 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; a hash table counts as the number of entries in
-/* the table).
+/* attr_scan() and attr_vscan() return -1 when malformed input is
+/* detected (string too long, incomplete line, missing end marker).
+/* Otherwise, the result value is the number of attributes that were
+/* successfully recovered from the input stream (a hash table counts
+/* as the number of entries stored into the table).
/*
/* Panic: interface violation. All system call errors are fatal.
/* SEE ALSO
#include <mymalloc.h>
#include <vstream.h>
#include <vstring.h>
-#include <argv.h>
-#include <intv.h>
+#include <htable.h>
#include <base64_code.h>
#include <attr.h>
static int attr_scan_string(VSTREAM *fp, VSTRING *plain_buf, const char *context)
{
static VSTRING *base64_buf = 0;
-
-#if 0
extern int var_line_limit; /* XXX */
- int limit = var_line_limit * 5 / 4;
-
-#endif
+ int limit = var_line_limit * 2;
int ch;
if (base64_buf == 0)
return (-1);
}
VSTRING_ADDCH(base64_buf, ch);
-#if 0
if (LEN(base64_buf) > limit) {
msg_warn("string length > %d characters from %s while reading %s",
limit, VSTREAM_PATH(fp), context);
return (-1);
}
-#endif
}
VSTRING_TERMINATE(base64_buf);
if (base64_decode(plain_buf, STR(base64_buf), LEN(base64_buf)) == 0) {
return (-1);
}
if (msg_verbose)
- msg_info("%s: %s", context, STR(plain_buf));
+ msg_info("%s: %s", context, *STR(plain_buf) ? STR(plain_buf) : "(end)");
return (ch);
}
char *wanted_name;
unsigned int *number;
VSTRING *string;
- INTV *number_array;
- ARGV *string_array;
HTABLE *hash_table;
- unsigned num_val;
int ch;
int conversions;
* Sanity check.
*/
if (flags & ~ATTR_FLAG_ALL)
- msg_panic("%s: bad flags: 0x%x",
- myname, flags);
+ msg_panic("%s: bad flags: 0x%x", myname, flags);
/*
* Initialize.
* If we're reading into a hash table, we already know that the
* attribute value is string-valued, and we get the attribute name
* from the input stream instead. This is secure only when the
- * resulting table is queried with explicitly named attributes.
+ * resulting table is queried with known to be good attribute names.
*/
if (wanted_type != ATTR_TYPE_HASH) {
wanted_type = va_arg(ap, int);
if (wanted_type == ATTR_TYPE_END) {
if ((flags & ATTR_FLAG_MORE) != 0)
return (conversions);
- wanted_name = "attribute list terminator";
+ wanted_name = "list terminator";
} else if (wanted_type == ATTR_TYPE_HASH) {
- wanted_name = "any attribute name";
+ wanted_name = "(any attribute name or list terminator)";
hash_table = va_arg(ap, HTABLE *);
if (va_arg(ap, int) !=ATTR_TYPE_END)
msg_panic("%s: ATTR_TYPE_HASH not followed by ATTR_TYPE_END",
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.
+ * Get the name of the next attribute. Hitting EOF is always bad.
+ * Hitting the end-of-input early is OK if the caller is prepared
+ * to deal with missing inputs.
*/
+ if (msg_verbose)
+ msg_info("%s: wanted attribute: %s",
+ VSTREAM_PATH(fp), wanted_name);
if ((ch = attr_scan_string(fp, name_buf,
- "attribute name")) == VSTREAM_EOF)
- return (conversions);
+ "input attribute name")) == VSTREAM_EOF)
+ return (-1);
if (ch == '\n' && LEN(name_buf) == 0) {
if (wanted_type == ATTR_TYPE_END
|| wanted_type == ATTR_TYPE_HASH)
wanted_name, VSTREAM_PATH(fp));
return (conversions);
}
- if (msg_verbose)
- msg_info("want attribute %s, found attribute: %s",
- wanted_name, STR(name_buf));
/*
* See if the caller asks for this attribute.
if (ch != ':') {
msg_warn("missing value for number attribute %s from %s",
STR(name_buf), VSTREAM_PATH(fp));
- return (conversions);
+ return (-1);
}
number = va_arg(ap, unsigned int *);
if ((ch = attr_scan_number(fp, number, str_buf,
- "attribute value")) < 0)
- return (conversions);
+ "input attribute value")) < 0)
+ return (-1);
if (ch != '\n') {
msg_warn("multiple values for attribute %s from %s",
STR(name_buf), VSTREAM_PATH(fp));
- return (conversions);
+ return (-1);
}
break;
case ATTR_TYPE_STR:
if (ch != ':') {
msg_warn("missing value for string attribute %s from %s",
STR(name_buf), VSTREAM_PATH(fp));
- return (conversions);
+ return (-1);
}
string = va_arg(ap, VSTRING *);
- if ((ch = attr_scan_string(fp, string, "attribute value")) < 0)
- return (conversions);
+ if ((ch = attr_scan_string(fp, string,
+ "input attribute value")) < 0)
+ return (-1);
if (ch != '\n') {
msg_warn("multiple values for attribute %s from %s",
STR(name_buf), VSTREAM_PATH(fp));
- return (conversions);
+ return (-1);
}
break;
case ATTR_TYPE_HASH:
if (ch != ':') {
msg_warn("missing value for string attribute %s from %s",
STR(name_buf), VSTREAM_PATH(fp));
- return (conversions);
+ return (-1);
}
- if ((ch = attr_scan_string(fp, str_buf, "attribute value")) < 0)
- return (conversions);
+ if ((ch = attr_scan_string(fp, str_buf,
+"input attribute value")) < 0)
+ return (-1);
if (ch != '\n') {
msg_warn("multiple values for attribute %s from %s",
STR(name_buf), VSTREAM_PATH(fp));
- return (conversions);
+ return (-1);
}
if (htable_locate(hash_table, STR(name_buf)) != 0) {
if ((flags & ATTR_FLAG_EXTRA) != 0) {
mystrdup(STR(str_buf)));
}
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);
}
int main(int unused_argc, char **used_argv)
{
- INTV *intv = intv_alloc(1);
- ARGV *argv = argv_alloc(1);
VSTRING *str_val = vstring_alloc(1);
HTABLE *table = htable_create(1);
HTABLE_INFO **ht_info_list;
HTABLE_INFO **ht;
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_FLAG_STRICT,
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_HASH, table,
- ATTR_TYPE_END)) > 4) {
+ ATTR_TYPE_END)) > 2) {
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");
ht_info_list = htable_list(table);
for (ht = ht_info_list; *ht; ht++)
vstream_printf("(hash) %s %s\n", ht[0]->key, ht[0]->value);
vstream_printf("return: %d\n", ret);
}
if ((ret = attr_scan(VSTREAM_IN,
- ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA,
+ ATTR_FLAG_STRICT,
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) {
+ ATTR_TYPE_END)) == 2) {
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");
ht_info_list = htable_list(table);
for (ht = ht_info_list; *ht; ht++)
vstream_printf("(hash) %s %s\n", ht[0]->key, ht[0]->value);
if (vstream_fflush(VSTREAM_OUT) != 0)
msg_fatal("write error: %m");
- intv_free(intv);
- argv_free(argv);
vstring_free(str_val);
htable_free(table, myfree);
--- /dev/null
+./attr_print: send attr number = 4711
+./attr_print: send attr string = whoopee
+./attr_print: send attr name foo-name value foo-value
+./attr_print: send attr name bar-name value bar-value
+./attr_print: send attr number = 4711
+./attr_print: send attr string = whoopee
+./attr_scan: unknown_stream: wanted attribute: number
+./attr_scan: input attribute name: number
+./attr_scan: input attribute value: 4711
+./attr_scan: unknown_stream: wanted attribute: string
+./attr_scan: input attribute name: string
+./attr_scan: attribute value: whoopee
+./attr_scan: unknown_stream: wanted attribute: (any attribute name or list terminator)
+./attr_scan: input attribute name: foo-name
+./attr_scan: attribute value: foo-value
+./attr_scan: unknown_stream: wanted attribute: (any attribute name or list terminator)
+./attr_scan: input attribute name: bar-name
+./attr_scan: attribute value: bar-value
+./attr_scan: unknown_stream: wanted attribute: (any attribute name or list terminator)
+./attr_scan: input attribute name: (end)
+./attr_scan: unknown_stream: wanted attribute: number
+./attr_scan: input attribute name: number
+./attr_scan: input attribute value: 4711
+./attr_scan: unknown_stream: wanted attribute: string
+./attr_scan: input attribute name: string
+./attr_scan: attribute value: whoopee
+./attr_scan: unknown_stream: wanted attribute: list terminator
+./attr_scan: input attribute name: (end)
+number 4711
+string whoopee
+(hash) foo-name foo-value
+(hash) bar-name bar-value
+number 4711
+string whoopee
+(hash) foo-name foo-value
+(hash) bar-name bar-value
VSTRING *b2 = vstring_alloc(1);
char *test = "this is a test";
-#define DECODE(b,s,l) { \
- if (base64_decode((b),(s),(l)) == 0) \
- msg_panic("bad base64: %s", (s)); \
+#define DECODE(b,x,l) { \
+ if (base64_decode((b),(x),(l)) == 0) \
+ msg_panic("bad base64: %s", (x)); \
}
#define VERIFY(b,t) { \
if (strcmp((b), (t)) != 0) \
#define DICT_FLAG_DUP_REPLACE (1<<7) /* if file, replace dups */
#define DICT_FLAG_SYNC_UPDATE (1<<8) /* if file, sync updates */
#define DICT_FLAG_DEBUG (1<<9) /* log access */
+#define DICT_FLAG_FOLD_KEY (1<<10) /* lowercase the lookup key */
extern int dict_unknown_allowed;
extern int dict_errno;
/* .IP DICT_FLAG_SYNC_UPDATE
/* With file-based maps, flush I/O buffers to file after each update.
/* Thus feature is not supported with some file-based dictionaries.
+/* .IP DICT_FLAG_FOLD_KEY
+/* Fold the lookup key to lower case.
/* .PP
/* The dictionary types are as follows:
/* .IP environ