mirror of
https://github.com/vdukhovni/postfix
synced 2025-09-01 22:55:29 +00:00
snapshot-20011014
This commit is contained in:
committed by
Viktor Dukhovni
parent
1ef3a9a63a
commit
6f7a3806f8
1
postfix/.indent.pro
vendored
1
postfix/.indent.pro
vendored
@@ -1,6 +1,7 @@
|
|||||||
-TABOUNCE
|
-TABOUNCE
|
||||||
-TALIAS_TOKEN
|
-TALIAS_TOKEN
|
||||||
-TARGV
|
-TARGV
|
||||||
|
-TATTR_TABLE
|
||||||
-TBH_TABLE
|
-TBH_TABLE
|
||||||
-TBINATTR
|
-TBINATTR
|
||||||
-TBINATTR_INFO
|
-TBINATTR_INFO
|
||||||
|
@@ -5487,6 +5487,11 @@ Apologies for any names omitted.
|
|||||||
Bugfix: there was a minute memory leak when an smtpd access
|
Bugfix: there was a minute memory leak when an smtpd access
|
||||||
restriction is misconfigured. File: smtpd/smtpd_check.c.
|
restriction is misconfigured. File: smtpd/smtpd_check.c.
|
||||||
|
|
||||||
|
20011010-14
|
||||||
|
|
||||||
|
Replaced the internal protocols by (name,value) attribute
|
||||||
|
lists. This is more extensible.
|
||||||
|
|
||||||
Open problems:
|
Open problems:
|
||||||
|
|
||||||
Minor: The $process_id_directory setting is not used anywhere
|
Minor: The $process_id_directory setting is not used anywhere
|
||||||
|
@@ -161,6 +161,13 @@ home_mailbox =
|
|||||||
# mailbox_command = /some/where/procmail -a "$EXTENSION"
|
# mailbox_command = /some/where/procmail -a "$EXTENSION"
|
||||||
mailbox_command =
|
mailbox_command =
|
||||||
|
|
||||||
|
# The mailbox_command_maps allows you to specify a per-user mailbox
|
||||||
|
# command. The maps are keyed by username (not including the domain).
|
||||||
|
# Specify one or more maps. If this feature is used then every user
|
||||||
|
# must have a matching entry.
|
||||||
|
#
|
||||||
|
# mailbox_command_maps = hash:/etc/postfix/mailbox_commands
|
||||||
|
|
||||||
# The mailbox_transport specifies the optional transport in master.cf
|
# The mailbox_transport specifies the optional transport in master.cf
|
||||||
# to use after processing aliases and .forward files. This parameter
|
# to use after processing aliases and .forward files. This parameter
|
||||||
# has precedence over the mailbox_command, fallback_transport and
|
# has precedence over the mailbox_command, fallback_transport and
|
||||||
|
@@ -142,8 +142,11 @@ static int bounce_append_proto(char *service_name, VSTREAM *client)
|
|||||||
/*
|
/*
|
||||||
* Read the and validate the client request.
|
* Read the and validate the client request.
|
||||||
*/
|
*/
|
||||||
if (mail_command_read(client, "%d %s %s %s",
|
if (mail_command_server(client, "%d %s %s %s",
|
||||||
&flags, queue_id, recipient, why) != 4) {
|
ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, &flags,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue_name,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_RECIP, recipient,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_WHY, why, 0) != 4) {
|
||||||
msg_warn("malformed request");
|
msg_warn("malformed request");
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
@@ -178,8 +181,11 @@ static int bounce_notify_proto(char *service_name, VSTREAM *client, int flush)
|
|||||||
/*
|
/*
|
||||||
* Read and validate the client request.
|
* Read and validate the client request.
|
||||||
*/
|
*/
|
||||||
if (mail_command_read(client, "%d %s %s %s",
|
if (mail_command_server(client, ATTR_FLAG_MISSING,
|
||||||
&flags, queue_name, queue_id, sender) != 4) {
|
ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, &flags,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue_name,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, queue_id,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender, 0) != 4) {
|
||||||
msg_warn("malformed request");
|
msg_warn("malformed request");
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
@@ -213,15 +219,18 @@ static int bounce_notify_proto(char *service_name, VSTREAM *client, int flush)
|
|||||||
|
|
||||||
static int bounce_verp_proto(char *service_name, VSTREAM *client, int flush)
|
static int bounce_verp_proto(char *service_name, VSTREAM *client, int flush)
|
||||||
{
|
{
|
||||||
char *myname="bounce_verp_proto";
|
char *myname = "bounce_verp_proto";
|
||||||
int flags;
|
int flags;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Read and validate the client request.
|
* Read and validate the client request.
|
||||||
*/
|
*/
|
||||||
if (mail_command_read(client, "%d %s %s %s %s",
|
if (attr_scan(client, ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA,
|
||||||
&flags, queue_name, queue_id,
|
ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, &flags,
|
||||||
sender, verp_delims) != 5) {
|
ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue_name,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, queue_id,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_VERPDL, verp_delims, 0) != 5) {
|
||||||
msg_warn("malformed request");
|
msg_warn("malformed request");
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
@@ -287,7 +296,8 @@ static void bounce_service(VSTREAM *client, char *service_name, char **argv)
|
|||||||
#define REALLY_BOUNCE 1
|
#define REALLY_BOUNCE 1
|
||||||
#define JUST_WARN 0
|
#define JUST_WARN 0
|
||||||
|
|
||||||
if (mail_scan(client, "%d", &command) != 1) {
|
if (attr_scan(client, ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA | ATTR_FLAG_MORE,
|
||||||
|
ATTR_TYPE_NUM, MAIL_ATTR_NREQ, &command, 0) != 1) {
|
||||||
msg_warn("malformed request");
|
msg_warn("malformed request");
|
||||||
status = -1;
|
status = -1;
|
||||||
} else if (command == BOUNCE_CMD_VERP) {
|
} else if (command == BOUNCE_CMD_VERP) {
|
||||||
@@ -307,7 +317,9 @@ static void bounce_service(VSTREAM *client, char *service_name, char **argv)
|
|||||||
* When the request has completed, send the completion status to the
|
* When the request has completed, send the completion status to the
|
||||||
* client.
|
* client.
|
||||||
*/
|
*/
|
||||||
mail_print(client, "%d", status);
|
attr_print(client, ATTR_FLAG_NONE,
|
||||||
|
ATTR_TYPE_NUM, MAIL_ATTR_STATUS, status,
|
||||||
|
ATTR_TYPE_END);
|
||||||
vstream_fflush(client);
|
vstream_fflush(client);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -191,8 +191,11 @@ static void cleanup_service(VSTREAM *src, char *unused_service, char **argv)
|
|||||||
* can't read the client processing options we can pretty much forget
|
* can't read the client processing options we can pretty much forget
|
||||||
* about the whole operation.
|
* about the whole operation.
|
||||||
*/
|
*/
|
||||||
mail_print(src, "%s", state->queue_id);
|
attr_print(src, ATTR_FLAG_NONE,
|
||||||
if (mail_scan(src, "%d", &flags) != 1) {
|
ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, state->queue_id,
|
||||||
|
ATTR_TYPE_END);
|
||||||
|
if (attr_scan(src, ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA,
|
||||||
|
ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, &flags) != 1) {
|
||||||
state->errs |= CLEANUP_STAT_BAD;
|
state->errs |= CLEANUP_STAT_BAD;
|
||||||
flags = 0;
|
flags = 0;
|
||||||
}
|
}
|
||||||
@@ -230,7 +233,10 @@ static void cleanup_service(VSTREAM *src, char *unused_service, char **argv)
|
|||||||
/*
|
/*
|
||||||
* Finish this message, and report the result status to the client.
|
* Finish this message, and report the result status to the client.
|
||||||
*/
|
*/
|
||||||
mail_print(src, "%d", cleanup_close(state));
|
attr_print(src, ATTR_FLAG_NONE,
|
||||||
|
ATTR_TYPE_NUM, MAIL_ATTR_STATUS, cleanup_close(state),
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_WHY, "",
|
||||||
|
ATTR_TYPE_END);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Cleanup.
|
* Cleanup.
|
||||||
|
@@ -540,31 +540,48 @@ static void flush_service(VSTREAM *client_stream, char *unused_service,
|
|||||||
* All connection-management stuff is handled by the common code in
|
* All connection-management stuff is handled by the common code in
|
||||||
* single_server.c.
|
* single_server.c.
|
||||||
*/
|
*/
|
||||||
if (mail_scan(client_stream, "%s", request) == 1) {
|
if (attr_scan(client_stream, ATTR_FLAG_MORE | ATTR_FLAG_EXTRA | ATTR_FLAG_MISSING,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_REQ, request,
|
||||||
|
ATTR_TYPE_END) == 1) {
|
||||||
if (STREQ(STR(request), FLUSH_REQ_ADD)) {
|
if (STREQ(STR(request), FLUSH_REQ_ADD)) {
|
||||||
site = vstring_alloc(10);
|
site = vstring_alloc(10);
|
||||||
queue_id = vstring_alloc(10);
|
queue_id = vstring_alloc(10);
|
||||||
if (mail_command_read(client_stream, "%s %s", site, queue_id) == 2
|
if (attr_scan(client_stream, ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_SITE, site, ATTR_FLAG_MISSING,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_SITE, queue_id,
|
||||||
|
ATTR_TYPE_END) == 2
|
||||||
&& mail_queue_id_ok(STR(queue_id)))
|
&& mail_queue_id_ok(STR(queue_id)))
|
||||||
status = flush_add_service(lowercase(STR(site)), STR(queue_id));
|
status = flush_add_service(lowercase(STR(site)), STR(queue_id));
|
||||||
mail_print(client_stream, "%d", status);
|
attr_print(client_stream, ATTR_FLAG_NONE,
|
||||||
|
ATTR_TYPE_NUM, MAIL_ATTR_STATUS, status,
|
||||||
|
ATTR_TYPE_END);
|
||||||
} else if (STREQ(STR(request), FLUSH_REQ_SEND)) {
|
} else if (STREQ(STR(request), FLUSH_REQ_SEND)) {
|
||||||
site = vstring_alloc(10);
|
site = vstring_alloc(10);
|
||||||
if (mail_command_read(client_stream, "%s", site) == 1)
|
if (attr_scan(client_stream, ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_SITE, site,
|
||||||
|
ATTR_TYPE_END) == 1)
|
||||||
status = flush_send_service(lowercase(STR(site)));
|
status = flush_send_service(lowercase(STR(site)));
|
||||||
mail_print(client_stream, "%d", status);
|
attr_print(client_stream, ATTR_FLAG_NONE,
|
||||||
|
ATTR_TYPE_NUM, MAIL_ATTR_STATUS, status,
|
||||||
|
ATTR_TYPE_END);
|
||||||
} else if (STREQ(STR(request), FLUSH_REQ_REFRESH)
|
} else if (STREQ(STR(request), FLUSH_REQ_REFRESH)
|
||||||
|| STREQ(STR(request), wakeup)) {
|
|| STREQ(STR(request), wakeup)) {
|
||||||
mail_print(client_stream, "%d", FLUSH_STAT_OK);
|
attr_print(client_stream, ATTR_FLAG_NONE,
|
||||||
|
ATTR_TYPE_NUM, MAIL_ATTR_STATUS, FLUSH_STAT_OK,
|
||||||
|
ATTR_TYPE_END);
|
||||||
vstream_fflush(client_stream);
|
vstream_fflush(client_stream);
|
||||||
(void) flush_refresh_service(var_fflush_refresh);
|
(void) flush_refresh_service(var_fflush_refresh);
|
||||||
} else if (STREQ(STR(request), FLUSH_REQ_PURGE)) {
|
} else if (STREQ(STR(request), FLUSH_REQ_PURGE)) {
|
||||||
mail_print(client_stream, "%d", FLUSH_STAT_OK);
|
attr_print(client_stream, ATTR_FLAG_NONE,
|
||||||
|
ATTR_TYPE_NUM, MAIL_ATTR_STATUS, FLUSH_STAT_OK,
|
||||||
|
ATTR_TYPE_END);
|
||||||
vstream_fflush(client_stream);
|
vstream_fflush(client_stream);
|
||||||
(void) flush_refresh_service(0);
|
(void) flush_refresh_service(0);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
mail_print(client_stream, "%d", status);
|
attr_print(client_stream, ATTR_FLAG_NONE,
|
||||||
|
ATTR_TYPE_NUM, MAIL_ATTR_STATUS, status,
|
||||||
|
ATTR_TYPE_END);
|
||||||
vstring_free(request);
|
vstring_free(request);
|
||||||
if (site)
|
if (site)
|
||||||
vstring_free(site);
|
vstring_free(site);
|
||||||
|
@@ -4,11 +4,11 @@ SRCS = been_here.c bounce.c canon_addr.c cleanup_strerror.c clnt_stream.c \
|
|||||||
deliver_flock.c deliver_pass.c deliver_request.c domain_list.c \
|
deliver_flock.c deliver_pass.c deliver_request.c domain_list.c \
|
||||||
dot_lockfile.c dot_lockfile_as.c ext_prop.c file_id.c \
|
dot_lockfile.c dot_lockfile_as.c ext_prop.c file_id.c \
|
||||||
header_opts.c is_header.c mail_addr.c mail_addr_crunch.c \
|
header_opts.c is_header.c mail_addr.c mail_addr_crunch.c \
|
||||||
mail_addr_find.c mail_addr_map.c mail_command_read.c \
|
mail_addr_find.c mail_addr_map.c mail_command_server.c \
|
||||||
mail_command_write.c mail_conf.c mail_conf_bool.c mail_conf_int.c \
|
mail_command_client.c mail_conf.c mail_conf_bool.c mail_conf_int.c \
|
||||||
mail_conf_raw.c mail_conf_str.c mail_connect.c mail_copy.c \
|
mail_conf_raw.c mail_conf_str.c mail_connect.c mail_copy.c \
|
||||||
mail_date.c mail_error.c mail_flush.c mail_open_ok.c mail_params.c \
|
mail_date.c mail_error.c mail_flush.c mail_open_ok.c mail_params.c \
|
||||||
mail_pathname.c mail_print.c mail_queue.c mail_run.c mail_scan.c \
|
mail_pathname.c mail_queue.c mail_run.c \
|
||||||
mail_scan_dir.c mail_stream.c mail_task.c mail_trigger.c maps.c \
|
mail_scan_dir.c mail_stream.c mail_task.c mail_trigger.c maps.c \
|
||||||
mark_corrupt.c mkmap_db.c mkmap_dbm.c mkmap_open.c mynetworks.c \
|
mark_corrupt.c mkmap_db.c mkmap_dbm.c mkmap_open.c mynetworks.c \
|
||||||
mypwd.c namadr_list.c off_cvt.c opened.c own_inet_addr.c \
|
mypwd.c namadr_list.c off_cvt.c opened.c own_inet_addr.c \
|
||||||
@@ -25,11 +25,11 @@ OBJS = been_here.o bounce.o canon_addr.o cleanup_strerror.o clnt_stream.o \
|
|||||||
deliver_flock.o deliver_pass.o deliver_request.o domain_list.o \
|
deliver_flock.o deliver_pass.o deliver_request.o domain_list.o \
|
||||||
dot_lockfile.o dot_lockfile_as.o ext_prop.o file_id.o \
|
dot_lockfile.o dot_lockfile_as.o ext_prop.o file_id.o \
|
||||||
header_opts.o is_header.o mail_addr.o mail_addr_crunch.o \
|
header_opts.o is_header.o mail_addr.o mail_addr_crunch.o \
|
||||||
mail_addr_find.o mail_addr_map.o mail_command_read.o \
|
mail_addr_find.o mail_addr_map.o mail_command_server.o \
|
||||||
mail_command_write.o mail_conf.o mail_conf_bool.o mail_conf_int.o \
|
mail_command_client.o mail_conf.o mail_conf_bool.o mail_conf_int.o \
|
||||||
mail_conf_raw.o mail_conf_str.o mail_connect.o mail_copy.o \
|
mail_conf_raw.o mail_conf_str.o mail_connect.o mail_copy.o \
|
||||||
mail_date.o mail_error.o mail_flush.o mail_open_ok.o mail_params.o \
|
mail_date.o mail_error.o mail_flush.o mail_open_ok.o mail_params.o \
|
||||||
mail_pathname.o mail_print.o mail_queue.o mail_run.o mail_scan.o \
|
mail_pathname.o mail_queue.o mail_run.o \
|
||||||
mail_scan_dir.o mail_stream.o mail_task.o mail_trigger.o maps.o \
|
mail_scan_dir.o mail_stream.o mail_task.o mail_trigger.o maps.o \
|
||||||
mark_corrupt.o mkmap_db.o mkmap_dbm.o mkmap_open.o mynetworks.o \
|
mark_corrupt.o mkmap_db.o mkmap_dbm.o mkmap_open.o mynetworks.o \
|
||||||
mypwd.o namadr_list.o off_cvt.o opened.o own_inet_addr.o \
|
mypwd.o namadr_list.o off_cvt.o opened.o own_inet_addr.o \
|
||||||
@@ -254,6 +254,8 @@ abounce.o: ../../include/vstream.h
|
|||||||
abounce.o: ../../include/vbuf.h
|
abounce.o: ../../include/vbuf.h
|
||||||
abounce.o: mail_proto.h
|
abounce.o: mail_proto.h
|
||||||
abounce.o: ../../include/iostuff.h
|
abounce.o: ../../include/iostuff.h
|
||||||
|
abounce.o: ../../include/attr.h
|
||||||
|
abounce.o: ../../include/htable.h
|
||||||
abounce.o: abounce.h
|
abounce.o: abounce.h
|
||||||
abounce.o: bounce.h
|
abounce.o: bounce.h
|
||||||
been_here.o: been_here.c
|
been_here.o: been_here.c
|
||||||
@@ -274,6 +276,8 @@ bounce.o: mail_params.h
|
|||||||
bounce.o: mail_proto.h
|
bounce.o: mail_proto.h
|
||||||
bounce.o: ../../include/vstream.h
|
bounce.o: ../../include/vstream.h
|
||||||
bounce.o: ../../include/iostuff.h
|
bounce.o: ../../include/iostuff.h
|
||||||
|
bounce.o: ../../include/attr.h
|
||||||
|
bounce.o: ../../include/htable.h
|
||||||
bounce.o: defer.h
|
bounce.o: defer.h
|
||||||
bounce.o: bounce.h
|
bounce.o: bounce.h
|
||||||
bounce_log.o: bounce_log.c
|
bounce_log.o: bounce_log.c
|
||||||
@@ -308,6 +312,8 @@ clnt_stream.o: ../../include/vbuf.h
|
|||||||
clnt_stream.o: ../../include/events.h
|
clnt_stream.o: ../../include/events.h
|
||||||
clnt_stream.o: ../../include/iostuff.h
|
clnt_stream.o: ../../include/iostuff.h
|
||||||
clnt_stream.o: mail_proto.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: mail_params.h
|
||||||
clnt_stream.o: clnt_stream.h
|
clnt_stream.o: clnt_stream.h
|
||||||
debug_peer.o: debug_peer.c
|
debug_peer.o: debug_peer.c
|
||||||
@@ -331,6 +337,8 @@ defer.o: mail_queue.h
|
|||||||
defer.o: ../../include/vstream.h
|
defer.o: ../../include/vstream.h
|
||||||
defer.o: mail_proto.h
|
defer.o: mail_proto.h
|
||||||
defer.o: ../../include/iostuff.h
|
defer.o: ../../include/iostuff.h
|
||||||
|
defer.o: ../../include/attr.h
|
||||||
|
defer.o: ../../include/htable.h
|
||||||
defer.o: flush_clnt.h
|
defer.o: flush_clnt.h
|
||||||
defer.o: bounce.h
|
defer.o: bounce.h
|
||||||
defer.o: defer.h
|
defer.o: defer.h
|
||||||
@@ -365,6 +373,8 @@ deliver_pass.o: deliver_request.h
|
|||||||
deliver_pass.o: recipient_list.h
|
deliver_pass.o: recipient_list.h
|
||||||
deliver_pass.o: mail_proto.h
|
deliver_pass.o: mail_proto.h
|
||||||
deliver_pass.o: ../../include/iostuff.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: deliver_request.c
|
||||||
deliver_request.o: ../../include/sys_defs.h
|
deliver_request.o: ../../include/sys_defs.h
|
||||||
deliver_request.o: ../../include/msg.h
|
deliver_request.o: ../../include/msg.h
|
||||||
@@ -376,6 +386,8 @@ deliver_request.o: ../../include/iostuff.h
|
|||||||
deliver_request.o: ../../include/myflock.h
|
deliver_request.o: ../../include/myflock.h
|
||||||
deliver_request.o: mail_queue.h
|
deliver_request.o: mail_queue.h
|
||||||
deliver_request.o: mail_proto.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: mail_open_ok.h
|
||||||
deliver_request.o: recipient_list.h
|
deliver_request.o: recipient_list.h
|
||||||
deliver_request.o: deliver_request.h
|
deliver_request.o: deliver_request.h
|
||||||
@@ -419,6 +431,8 @@ flush_clnt.o: ../../include/vstream.h
|
|||||||
flush_clnt.o: ../../include/vbuf.h
|
flush_clnt.o: ../../include/vbuf.h
|
||||||
flush_clnt.o: mail_proto.h
|
flush_clnt.o: mail_proto.h
|
||||||
flush_clnt.o: ../../include/iostuff.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: mail_flush.h
|
||||||
flush_clnt.o: flush_clnt.h
|
flush_clnt.o: flush_clnt.h
|
||||||
flush_clnt.o: mail_params.h
|
flush_clnt.o: mail_params.h
|
||||||
@@ -477,19 +491,22 @@ mail_addr_map.o: mail_addr_find.h
|
|||||||
mail_addr_map.o: maps.h
|
mail_addr_map.o: maps.h
|
||||||
mail_addr_map.o: mail_addr_crunch.h
|
mail_addr_map.o: mail_addr_crunch.h
|
||||||
mail_addr_map.o: mail_addr_map.h
|
mail_addr_map.o: mail_addr_map.h
|
||||||
mail_command_read.o: mail_command_read.c
|
mail_command_client.o: mail_command_client.c
|
||||||
mail_command_read.o: ../../include/sys_defs.h
|
mail_command_client.o: ../../include/sys_defs.h
|
||||||
mail_command_read.o: ../../include/vstring.h
|
mail_command_client.o: ../../include/vstream.h
|
||||||
mail_command_read.o: ../../include/vbuf.h
|
mail_command_client.o: ../../include/vbuf.h
|
||||||
mail_command_read.o: ../../include/vstream.h
|
mail_command_client.o: mail_proto.h
|
||||||
mail_command_read.o: mail_proto.h
|
mail_command_client.o: ../../include/iostuff.h
|
||||||
mail_command_read.o: ../../include/iostuff.h
|
mail_command_client.o: ../../include/attr.h
|
||||||
mail_command_write.o: mail_command_write.c
|
mail_command_client.o: ../../include/htable.h
|
||||||
mail_command_write.o: ../../include/sys_defs.h
|
mail_command_server.o: mail_command_server.c
|
||||||
mail_command_write.o: ../../include/vstream.h
|
mail_command_server.o: ../../include/sys_defs.h
|
||||||
mail_command_write.o: ../../include/vbuf.h
|
mail_command_server.o: ../../include/vstream.h
|
||||||
mail_command_write.o: mail_proto.h
|
mail_command_server.o: ../../include/vbuf.h
|
||||||
mail_command_write.o: ../../include/iostuff.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_conf.o: mail_conf.c
|
mail_conf.o: mail_conf.c
|
||||||
mail_conf.o: ../../include/sys_defs.h
|
mail_conf.o: ../../include/sys_defs.h
|
||||||
mail_conf.o: ../../include/msg.h
|
mail_conf.o: ../../include/msg.h
|
||||||
@@ -553,6 +570,8 @@ mail_connect.o: ../../include/iostuff.h
|
|||||||
mail_connect.o: ../../include/mymalloc.h
|
mail_connect.o: ../../include/mymalloc.h
|
||||||
mail_connect.o: timed_ipc.h
|
mail_connect.o: timed_ipc.h
|
||||||
mail_connect.o: mail_proto.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: mail_copy.c
|
||||||
mail_copy.o: ../../include/sys_defs.h
|
mail_copy.o: ../../include/sys_defs.h
|
||||||
mail_copy.o: ../../include/msg.h
|
mail_copy.o: ../../include/msg.h
|
||||||
@@ -585,6 +604,8 @@ mail_flush.o: mail_proto.h
|
|||||||
mail_flush.o: ../../include/vstream.h
|
mail_flush.o: ../../include/vstream.h
|
||||||
mail_flush.o: ../../include/vbuf.h
|
mail_flush.o: ../../include/vbuf.h
|
||||||
mail_flush.o: ../../include/iostuff.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_flush.o: mail_flush.h
|
||||||
mail_open_ok.o: mail_open_ok.c
|
mail_open_ok.o: mail_open_ok.c
|
||||||
mail_open_ok.o: ../../include/sys_defs.h
|
mail_open_ok.o: ../../include/sys_defs.h
|
||||||
@@ -610,6 +631,8 @@ mail_params.o: mail_version.h
|
|||||||
mail_params.o: mail_proto.h
|
mail_params.o: mail_proto.h
|
||||||
mail_params.o: ../../include/vstream.h
|
mail_params.o: ../../include/vstream.h
|
||||||
mail_params.o: ../../include/iostuff.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: verp_sender.h
|
||||||
mail_params.o: mail_params.h
|
mail_params.o: mail_params.h
|
||||||
mail_pathname.o: mail_pathname.c
|
mail_pathname.o: mail_pathname.c
|
||||||
@@ -620,6 +643,8 @@ mail_pathname.o: ../../include/vbuf.h
|
|||||||
mail_pathname.o: mail_proto.h
|
mail_pathname.o: mail_proto.h
|
||||||
mail_pathname.o: ../../include/vstream.h
|
mail_pathname.o: ../../include/vstream.h
|
||||||
mail_pathname.o: ../../include/iostuff.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: mail_print.c
|
||||||
mail_print.o: ../../include/sys_defs.h
|
mail_print.o: ../../include/sys_defs.h
|
||||||
mail_print.o: ../../include/msg.h
|
mail_print.o: ../../include/msg.h
|
||||||
@@ -628,6 +653,8 @@ mail_print.o: ../../include/vstream.h
|
|||||||
mail_print.o: ../../include/vbuf.h
|
mail_print.o: ../../include/vbuf.h
|
||||||
mail_print.o: mail_proto.h
|
mail_print.o: mail_proto.h
|
||||||
mail_print.o: ../../include/iostuff.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: mail_queue.c
|
||||||
mail_queue.o: ../../include/sys_defs.h
|
mail_queue.o: ../../include/sys_defs.h
|
||||||
mail_queue.o: ../../include/msg.h
|
mail_queue.o: ../../include/msg.h
|
||||||
@@ -663,6 +690,8 @@ mail_scan.o: ../../include/vstring_vstream.h
|
|||||||
mail_scan.o: ../../include/mymalloc.h
|
mail_scan.o: ../../include/mymalloc.h
|
||||||
mail_scan.o: mail_proto.h
|
mail_scan.o: mail_proto.h
|
||||||
mail_scan.o: ../../include/iostuff.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: mail_scan_dir.c
|
||||||
mail_scan_dir.o: ../../include/sys_defs.h
|
mail_scan_dir.o: ../../include/sys_defs.h
|
||||||
mail_scan_dir.o: ../../include/scan_dir.h
|
mail_scan_dir.o: ../../include/scan_dir.h
|
||||||
@@ -679,6 +708,8 @@ mail_stream.o: ../../include/argv.h
|
|||||||
mail_stream.o: cleanup_user.h
|
mail_stream.o: cleanup_user.h
|
||||||
mail_stream.o: mail_proto.h
|
mail_stream.o: mail_proto.h
|
||||||
mail_stream.o: ../../include/iostuff.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: mail_queue.h
|
||||||
mail_stream.o: opened.h
|
mail_stream.o: opened.h
|
||||||
mail_stream.o: mail_params.h
|
mail_stream.o: mail_params.h
|
||||||
@@ -701,6 +732,8 @@ mail_trigger.o: mail_params.h
|
|||||||
mail_trigger.o: mail_proto.h
|
mail_trigger.o: mail_proto.h
|
||||||
mail_trigger.o: ../../include/vstream.h
|
mail_trigger.o: ../../include/vstream.h
|
||||||
mail_trigger.o: ../../include/vbuf.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
|
mail_version.o: mail_version.c
|
||||||
maps.o: maps.c
|
maps.o: maps.c
|
||||||
maps.o: ../../include/sys_defs.h
|
maps.o: ../../include/sys_defs.h
|
||||||
@@ -860,6 +893,8 @@ post_mail.o: record.h
|
|||||||
post_mail.o: rec_type.h
|
post_mail.o: rec_type.h
|
||||||
post_mail.o: mail_proto.h
|
post_mail.o: mail_proto.h
|
||||||
post_mail.o: ../../include/iostuff.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: cleanup_user.h
|
||||||
post_mail.o: post_mail.h
|
post_mail.o: post_mail.h
|
||||||
post_mail.o: mail_date.h
|
post_mail.o: mail_date.h
|
||||||
@@ -927,6 +962,8 @@ resolve_clnt.o: ../../include/vstring_vstream.h
|
|||||||
resolve_clnt.o: ../../include/events.h
|
resolve_clnt.o: ../../include/events.h
|
||||||
resolve_clnt.o: ../../include/iostuff.h
|
resolve_clnt.o: ../../include/iostuff.h
|
||||||
resolve_clnt.o: mail_proto.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: mail_params.h
|
||||||
resolve_clnt.o: clnt_stream.h
|
resolve_clnt.o: clnt_stream.h
|
||||||
resolve_clnt.o: resolve_clnt.h
|
resolve_clnt.o: resolve_clnt.h
|
||||||
@@ -949,6 +986,8 @@ rewrite_clnt.o: ../../include/events.h
|
|||||||
rewrite_clnt.o: ../../include/iostuff.h
|
rewrite_clnt.o: ../../include/iostuff.h
|
||||||
rewrite_clnt.o: quote_822_local.h
|
rewrite_clnt.o: quote_822_local.h
|
||||||
rewrite_clnt.o: mail_proto.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: mail_params.h
|
||||||
rewrite_clnt.o: clnt_stream.h
|
rewrite_clnt.o: clnt_stream.h
|
||||||
rewrite_clnt.o: rewrite_clnt.h
|
rewrite_clnt.o: rewrite_clnt.h
|
||||||
|
@@ -171,7 +171,9 @@ static void abounce_event(int unused_event, char *context)
|
|||||||
int status;
|
int status;
|
||||||
|
|
||||||
event_disable_readwrite(vstream_fileno(ap->fp));
|
event_disable_readwrite(vstream_fileno(ap->fp));
|
||||||
abounce_done(ap, mail_scan(ap->fp, "%d", &status) == 1 ? status : -1);
|
abounce_done(ap, attr_scan(ap->fp, ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA,
|
||||||
|
ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &status,
|
||||||
|
ATTR_TYPE_END) == 1 ? status : -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* abounce_request_verp - suspend pseudo thread until server reply event */
|
/* abounce_request_verp - suspend pseudo thread until server reply event */
|
||||||
@@ -197,8 +199,14 @@ static void abounce_request_verp(const char *class, const char *service,
|
|||||||
ap->context = context;
|
ap->context = context;
|
||||||
ap->fp = mail_connect_wait(class, service);
|
ap->fp = mail_connect_wait(class, service);
|
||||||
|
|
||||||
if (mail_print(ap->fp, "%d %d %s %s %s %s %s", command,
|
if (attr_print(ap->fp, ATTR_FLAG_NONE,
|
||||||
flags, queue, id, sender, verp, MAIL_EOF) == 0
|
ATTR_TYPE_NUM, MAIL_ATTR_NREQ, command,
|
||||||
|
ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_VERPDL, verp,
|
||||||
|
ATTR_TYPE_END) == 0
|
||||||
&& vstream_fflush(ap->fp) == 0) {
|
&& vstream_fflush(ap->fp) == 0) {
|
||||||
event_enable_read(vstream_fileno(ap->fp), abounce_event, (char *) ap);
|
event_enable_read(vstream_fileno(ap->fp), abounce_event, (char *) ap);
|
||||||
} else {
|
} else {
|
||||||
@@ -251,8 +259,13 @@ static void abounce_request(const char *class, const char *service,
|
|||||||
ap->context = context;
|
ap->context = context;
|
||||||
ap->fp = mail_connect_wait(class, service);
|
ap->fp = mail_connect_wait(class, service);
|
||||||
|
|
||||||
if (mail_print(ap->fp, "%d %d %s %s %s %s", command,
|
if (attr_print(ap->fp, ATTR_FLAG_NONE,
|
||||||
flags, queue, id, sender, MAIL_EOF) == 0
|
ATTR_TYPE_NUM, MAIL_ATTR_NREQ, command,
|
||||||
|
ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender,
|
||||||
|
ATTR_TYPE_END) == 0
|
||||||
&& vstream_fflush(ap->fp) == 0) {
|
&& vstream_fflush(ap->fp) == 0) {
|
||||||
event_enable_read(vstream_fileno(ap->fp), abounce_event, (char *) ap);
|
event_enable_read(vstream_fileno(ap->fp), abounce_event, (char *) ap);
|
||||||
} else {
|
} else {
|
||||||
|
@@ -142,10 +142,14 @@ int vbounce_append(int flags, const char *id, const char *recipient,
|
|||||||
why = vstring_alloc(100);
|
why = vstring_alloc(100);
|
||||||
delay = time((time_t *) 0) - entry;
|
delay = time((time_t *) 0) - entry;
|
||||||
vstring_vsprintf(why, fmt, ap);
|
vstring_vsprintf(why, fmt, ap);
|
||||||
if (mail_command_write(MAIL_CLASS_PRIVATE, var_soft_bounce ?
|
if (mail_command_client(MAIL_CLASS_PRIVATE, var_soft_bounce ?
|
||||||
MAIL_SERVICE_DEFER : MAIL_SERVICE_BOUNCE,
|
MAIL_SERVICE_DEFER : MAIL_SERVICE_BOUNCE,
|
||||||
"%d %d %s %s %s", BOUNCE_CMD_APPEND,
|
ATTR_TYPE_NUM, MAIL_ATTR_REQ, BOUNCE_CMD_APPEND,
|
||||||
flags, id, recipient, vstring_str(why)) == 0) {
|
ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_RECIP, recipient,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_WHY, vstring_str(why),
|
||||||
|
ATTR_TYPE_END) == 0) {
|
||||||
msg_info("%s: to=<%s>, relay=%s, delay=%d, status=%s (%s)",
|
msg_info("%s: to=<%s>, relay=%s, delay=%d, status=%s (%s)",
|
||||||
id, recipient, relay, delay, var_soft_bounce ? "deferred" :
|
id, recipient, relay, delay, var_soft_bounce ? "deferred" :
|
||||||
"bounced", vstring_str(why));
|
"bounced", vstring_str(why));
|
||||||
@@ -172,9 +176,13 @@ int bounce_flush(int flags, const char *queue, const char *id,
|
|||||||
*/
|
*/
|
||||||
if (var_soft_bounce)
|
if (var_soft_bounce)
|
||||||
return (-1);
|
return (-1);
|
||||||
if (mail_command_write(MAIL_CLASS_PRIVATE, MAIL_SERVICE_BOUNCE,
|
if (mail_command_client(MAIL_CLASS_PRIVATE, MAIL_SERVICE_BOUNCE,
|
||||||
"%d %d %s %s %s", BOUNCE_CMD_FLUSH,
|
ATTR_TYPE_NUM, MAIL_ATTR_REQ, BOUNCE_CMD_FLUSH,
|
||||||
flags, queue, id, sender) == 0) {
|
ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender,
|
||||||
|
ATTR_TYPE_END) == 0) {
|
||||||
return (0);
|
return (0);
|
||||||
} else if ((flags & BOUNCE_FLAG_CLEAN) == 0) {
|
} else if ((flags & BOUNCE_FLAG_CLEAN) == 0) {
|
||||||
msg_info("%s: status=deferred (bounce failed)", id);
|
msg_info("%s: status=deferred (bounce failed)", id);
|
||||||
|
@@ -145,9 +145,13 @@ int vdefer_append(int flags, const char *id, const char *recipient,
|
|||||||
const char *rcpt_domain;
|
const char *rcpt_domain;
|
||||||
|
|
||||||
vstring_vsprintf(why, fmt, ap);
|
vstring_vsprintf(why, fmt, ap);
|
||||||
if (mail_command_write(MAIL_CLASS_PRIVATE, MAIL_SERVICE_DEFER,
|
if (mail_command_client(MAIL_CLASS_PRIVATE, MAIL_SERVICE_DEFER,
|
||||||
"%d %d %s %s %s", BOUNCE_CMD_APPEND,
|
ATTR_TYPE_NUM, MAIL_ATTR_REQ, BOUNCE_CMD_APPEND,
|
||||||
flags, id, recipient, vstring_str(why)) != 0)
|
ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_RECIP, recipient,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_WHY, vstring_str(why),
|
||||||
|
ATTR_TYPE_END) != 0)
|
||||||
msg_warn("%s: defer service failure", id);
|
msg_warn("%s: defer service failure", id);
|
||||||
msg_info("%s: to=<%s>, relay=%s, delay=%d, status=deferred (%s)",
|
msg_info("%s: to=<%s>, relay=%s, delay=%d, status=deferred (%s)",
|
||||||
id, recipient, relay, delay, vstring_str(why));
|
id, recipient, relay, delay, vstring_str(why));
|
||||||
@@ -175,9 +179,13 @@ int vdefer_append(int flags, const char *id, const char *recipient,
|
|||||||
int defer_flush(int flags, const char *queue, const char *id,
|
int defer_flush(int flags, const char *queue, const char *id,
|
||||||
const char *sender)
|
const char *sender)
|
||||||
{
|
{
|
||||||
if (mail_command_write(MAIL_CLASS_PRIVATE, MAIL_SERVICE_DEFER,
|
if (mail_command_client(MAIL_CLASS_PRIVATE, MAIL_SERVICE_DEFER,
|
||||||
"%d %d %s %s %s", BOUNCE_CMD_FLUSH,
|
ATTR_TYPE_NUM, MAIL_ATTR_REQ, BOUNCE_CMD_FLUSH,
|
||||||
flags, queue, id, sender) == 0) {
|
ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender,
|
||||||
|
ATTR_TYPE_END) == 0) {
|
||||||
return (0);
|
return (0);
|
||||||
} else {
|
} else {
|
||||||
return (-1);
|
return (-1);
|
||||||
@@ -190,9 +198,13 @@ int defer_flush(int flags, const char *queue, const char *id,
|
|||||||
int defer_warn(int flags, const char *queue, const char *id,
|
int defer_warn(int flags, const char *queue, const char *id,
|
||||||
const char *sender)
|
const char *sender)
|
||||||
{
|
{
|
||||||
if (mail_command_write(MAIL_CLASS_PRIVATE, MAIL_SERVICE_DEFER,
|
if (mail_command_client(MAIL_CLASS_PRIVATE, MAIL_SERVICE_DEFER,
|
||||||
"%d %d %s %s %s", BOUNCE_CMD_WARN,
|
ATTR_TYPE_NUM, MAIL_ATTR_REQ, BOUNCE_CMD_WARN,
|
||||||
flags, queue, id, sender) == 0) {
|
ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender,
|
||||||
|
ATTR_TYPE_END) == 0) {
|
||||||
return (0);
|
return (0);
|
||||||
} else {
|
} else {
|
||||||
return (-1);
|
return (-1);
|
||||||
|
@@ -77,7 +77,9 @@ static int deliver_pass_initial_reply(VSTREAM *stream)
|
|||||||
{
|
{
|
||||||
int stat;
|
int stat;
|
||||||
|
|
||||||
if (mail_scan(stream, "%d", &stat) != 1) {
|
if (attr_scan(stream, ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA,
|
||||||
|
ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &stat,
|
||||||
|
ATTR_TYPE_END) != 1) {
|
||||||
msg_warn("%s: malformed response", VSTREAM_PATH(stream));
|
msg_warn("%s: malformed response", VSTREAM_PATH(stream));
|
||||||
stat = -1;
|
stat = -1;
|
||||||
}
|
}
|
||||||
@@ -91,14 +93,21 @@ static int deliver_pass_send_request(VSTREAM *stream, DELIVER_REQUEST *request,
|
|||||||
{
|
{
|
||||||
int stat;
|
int stat;
|
||||||
|
|
||||||
mail_print(stream, "%d %s %s %ld %ld %s %s %s %s %ld %ld %s %s",
|
attr_print(stream, ATTR_FLAG_NONE,
|
||||||
request->flags,
|
ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, request->flags,
|
||||||
request->queue_name, request->queue_id,
|
ATTR_TYPE_STR, MAIL_ATTR_QUEUE, request->queue_name,
|
||||||
request->data_offset, request->data_size,
|
ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, request->queue_id,
|
||||||
nexthop, request->sender,
|
ATTR_TYPE_NUM, MAIL_ATTR_OFFSET, request->data_offset,
|
||||||
request->errors_to, request->return_receipt,
|
ATTR_TYPE_NUM, MAIL_ATTR_SIZE, request->data_size,
|
||||||
request->arrival_time,
|
ATTR_TYPE_STR, MAIL_ATTR_NEXTHOP, nexthop,
|
||||||
offs, addr, "0");
|
ATTR_TYPE_STR, MAIL_ATTR_SENDER, request->sender,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_ERRTO, request->errors_to,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_RRCPT, request->return_receipt,
|
||||||
|
ATTR_TYPE_NUM, MAIL_ATTR_TIME, request->arrival_time,
|
||||||
|
ATTR_TYPE_NUM, MAIL_ATTR_OFFSET, offs,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_RECIP, addr,
|
||||||
|
ATTR_TYPE_NUM, MAIL_ATTR_OFFSET, 0,
|
||||||
|
ATTR_TYPE_END);
|
||||||
|
|
||||||
if (vstream_fflush(stream)) {
|
if (vstream_fflush(stream)) {
|
||||||
msg_warn("%s: bad write: %m", VSTREAM_PATH(stream));
|
msg_warn("%s: bad write: %m", VSTREAM_PATH(stream));
|
||||||
@@ -115,7 +124,10 @@ static int deliver_pass_final_reply(VSTREAM *stream, VSTRING *reason)
|
|||||||
{
|
{
|
||||||
int stat;
|
int stat;
|
||||||
|
|
||||||
if (mail_scan(stream, "%s %d", reason, &stat) != 2) {
|
if (attr_scan(stream, ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_WHY, reason,
|
||||||
|
ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &stat,
|
||||||
|
ATTR_TYPE_END) != 2) {
|
||||||
msg_warn("%s: malformed response", VSTREAM_PATH(stream));
|
msg_warn("%s: malformed response", VSTREAM_PATH(stream));
|
||||||
stat = -1;
|
stat = -1;
|
||||||
}
|
}
|
||||||
|
@@ -67,7 +67,7 @@
|
|||||||
/* Warnings: bad data sent by the client. Fatal errors: out of
|
/* Warnings: bad data sent by the client. Fatal errors: out of
|
||||||
/* memory, queue file open errors.
|
/* memory, queue file open errors.
|
||||||
/* SEE ALSO
|
/* SEE ALSO
|
||||||
/* mail_scan(3) low-level intra-mail input routines
|
/* attr_scan(3) low-level intra-mail input routines
|
||||||
/* LICENSE
|
/* LICENSE
|
||||||
/* .ad
|
/* .ad
|
||||||
/* .fi
|
/* .fi
|
||||||
@@ -118,7 +118,9 @@ static int deliver_request_initial(VSTREAM *stream)
|
|||||||
*/
|
*/
|
||||||
if (msg_verbose)
|
if (msg_verbose)
|
||||||
msg_info("deliver_request_initial: send initial status");
|
msg_info("deliver_request_initial: send initial status");
|
||||||
mail_print(stream, "%d", 0);
|
attr_print(stream, ATTR_FLAG_NONE,
|
||||||
|
ATTR_TYPE_NUM, MAIL_ATTR_STATUS, 0,
|
||||||
|
ATTR_TYPE_END);
|
||||||
if ((err = vstream_fflush(stream)) != 0)
|
if ((err = vstream_fflush(stream)) != 0)
|
||||||
if (msg_verbose)
|
if (msg_verbose)
|
||||||
msg_warn("send initial status: %m");
|
msg_warn("send initial status: %m");
|
||||||
@@ -138,7 +140,10 @@ static int deliver_request_final(VSTREAM *stream, char *reason, int status)
|
|||||||
reason = "";
|
reason = "";
|
||||||
if (msg_verbose)
|
if (msg_verbose)
|
||||||
msg_info("deliver_request_final: send: \"%s\" %d", reason, status);
|
msg_info("deliver_request_final: send: \"%s\" %d", reason, status);
|
||||||
mail_print(stream, "%s %d", reason, status);
|
attr_print(stream, ATTR_FLAG_NONE,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_WHY, reason,
|
||||||
|
ATTR_TYPE_NUM, MAIL_ATTR_STATUS, status,
|
||||||
|
ATTR_TYPE_END);
|
||||||
if ((err = vstream_fflush(stream)) != 0)
|
if ((err = vstream_fflush(stream)) != 0)
|
||||||
if (msg_verbose)
|
if (msg_verbose)
|
||||||
msg_warn("send final status: %m");
|
msg_warn("send final status: %m");
|
||||||
@@ -187,11 +192,18 @@ static int deliver_request_get(VSTREAM *stream, DELIVER_REQUEST *request)
|
|||||||
* Extract the queue file name, data offset, and sender address. Abort
|
* Extract the queue file name, data offset, and sender address. Abort
|
||||||
* the conversation when they send bad information.
|
* the conversation when they send bad information.
|
||||||
*/
|
*/
|
||||||
if (mail_scan(stream, "%d %s %s %ld %ld %s %s %s %s %ld",
|
if (attr_scan(stream, ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA | ATTR_FLAG_MORE,
|
||||||
&request->flags,
|
ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, &request->flags,
|
||||||
queue_name, queue_id, &request->data_offset,
|
ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue_name,
|
||||||
&request->data_size, nexthop, address,
|
ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, queue_id,
|
||||||
errors_to, return_receipt, &request->arrival_time) != 10)
|
ATTR_TYPE_NUM, MAIL_ATTR_OFFSET, &request->data_offset,
|
||||||
|
ATTR_TYPE_NUM, MAIL_ATTR_SIZE, &request->data_size,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_NEXTHOP, nexthop,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_SENDER, address,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_ERRTO, errors_to,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_RRCPT, return_receipt,
|
||||||
|
ATTR_TYPE_NUM, MAIL_ATTR_TIME, &request->arrival_time,
|
||||||
|
ATTR_TYPE_END) != 10)
|
||||||
return (-1);
|
return (-1);
|
||||||
if (mail_open_ok(vstring_str(queue_name),
|
if (mail_open_ok(vstring_str(queue_name),
|
||||||
vstring_str(queue_id), &st, &path) == 0)
|
vstring_str(queue_id), &st, &path) == 0)
|
||||||
@@ -205,14 +217,19 @@ static int deliver_request_get(VSTREAM *stream, DELIVER_REQUEST *request)
|
|||||||
request->return_receipt = mystrdup(vstring_str(return_receipt));
|
request->return_receipt = mystrdup(vstring_str(return_receipt));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Extract the recipient offset and address list.
|
* Extract the recipient offset and address list. Skip over any
|
||||||
|
* attributes from the sender that we do not understand.
|
||||||
*/
|
*/
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (mail_scan(stream, "%ld", &offset) != 1)
|
if (attr_scan(stream, ATTR_FLAG_MORE | ATTR_FLAG_EXTRA,
|
||||||
|
ATTR_TYPE_NUM, MAIL_ATTR_OFFSET, &offset,
|
||||||
|
ATTR_TYPE_END) != 1)
|
||||||
return (-1);
|
return (-1);
|
||||||
if (offset == 0)
|
if (offset == 0)
|
||||||
break;
|
break;
|
||||||
if (mail_scan(stream, "%s", address) != 1)
|
if (attr_scan(stream, ATTR_FLAG_MORE | ATTR_FLAG_EXTRA,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_RECIP, address,
|
||||||
|
ATTR_TYPE_END) != 1)
|
||||||
return (-1);
|
return (-1);
|
||||||
recipient_list_add(&request->rcpt_list, offset, vstring_str(address));
|
recipient_list_add(&request->rcpt_list, offset, vstring_str(address));
|
||||||
}
|
}
|
||||||
|
@@ -100,8 +100,9 @@ int flush_purge(void)
|
|||||||
if (*var_fflush_domains == 0)
|
if (*var_fflush_domains == 0)
|
||||||
status = FLUSH_STAT_DENY;
|
status = FLUSH_STAT_DENY;
|
||||||
else
|
else
|
||||||
status = mail_command_write(MAIL_CLASS_PRIVATE, MAIL_SERVICE_FLUSH,
|
status = mail_command_client(MAIL_CLASS_PRIVATE, MAIL_SERVICE_FLUSH,
|
||||||
"%s", FLUSH_REQ_PURGE);
|
ATTR_TYPE_STR, MAIL_ATTR_REQ, FLUSH_REQ_PURGE,
|
||||||
|
ATTR_TYPE_END);
|
||||||
|
|
||||||
if (msg_verbose)
|
if (msg_verbose)
|
||||||
msg_info("%s: status %d", myname, status);
|
msg_info("%s: status %d", myname, status);
|
||||||
@@ -125,8 +126,9 @@ int flush_refresh(void)
|
|||||||
if (*var_fflush_domains == 0)
|
if (*var_fflush_domains == 0)
|
||||||
status = FLUSH_STAT_DENY;
|
status = FLUSH_STAT_DENY;
|
||||||
else
|
else
|
||||||
status = mail_command_write(MAIL_CLASS_PRIVATE, MAIL_SERVICE_FLUSH,
|
status = mail_command_client(MAIL_CLASS_PRIVATE, MAIL_SERVICE_FLUSH,
|
||||||
"%s", FLUSH_REQ_REFRESH);
|
ATTR_TYPE_STR, MAIL_ATTR_REQ, FLUSH_REQ_REFRESH,
|
||||||
|
ATTR_TYPE_END);
|
||||||
|
|
||||||
if (msg_verbose)
|
if (msg_verbose)
|
||||||
msg_info("%s: status %d", myname, status);
|
msg_info("%s: status %d", myname, status);
|
||||||
@@ -150,8 +152,10 @@ int flush_send(const char *site)
|
|||||||
if (*var_fflush_domains == 0)
|
if (*var_fflush_domains == 0)
|
||||||
status = FLUSH_STAT_DENY;
|
status = FLUSH_STAT_DENY;
|
||||||
else
|
else
|
||||||
status = mail_command_write(MAIL_CLASS_PRIVATE, MAIL_SERVICE_FLUSH,
|
status = mail_command_client(MAIL_CLASS_PRIVATE, MAIL_SERVICE_FLUSH,
|
||||||
"%s %s", FLUSH_REQ_SEND, site);
|
ATTR_TYPE_STR, MAIL_ATTR_REQ, FLUSH_REQ_SEND,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_SITE, site,
|
||||||
|
ATTR_TYPE_END);
|
||||||
|
|
||||||
if (msg_verbose)
|
if (msg_verbose)
|
||||||
msg_info("%s: site %s status %d", myname, site, status);
|
msg_info("%s: site %s status %d", myname, site, status);
|
||||||
@@ -175,8 +179,11 @@ int flush_add(const char *site, const char *queue_id)
|
|||||||
if (*var_fflush_domains == 0)
|
if (*var_fflush_domains == 0)
|
||||||
status = FLUSH_STAT_DENY;
|
status = FLUSH_STAT_DENY;
|
||||||
else
|
else
|
||||||
status = mail_command_write(MAIL_CLASS_PRIVATE, MAIL_SERVICE_FLUSH,
|
status = mail_command_client(MAIL_CLASS_PRIVATE, MAIL_SERVICE_FLUSH,
|
||||||
"%s %s %s", FLUSH_REQ_ADD, site, queue_id);
|
ATTR_TYPE_STR, MAIL_ATTR_REQ, FLUSH_REQ_ADD,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_SITE, site,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, queue_id,
|
||||||
|
ATTR_TYPE_END);
|
||||||
|
|
||||||
if (msg_verbose)
|
if (msg_verbose)
|
||||||
msg_info("%s: site %s id %s status %d", myname, site, queue_id,
|
msg_info("%s: site %s id %s status %d", myname, site, queue_id,
|
||||||
|
@@ -1,15 +1,16 @@
|
|||||||
/*++
|
/*++
|
||||||
/* NAME
|
/* NAME
|
||||||
/* mail_command_write 3
|
/* mail_command_client 3
|
||||||
/* SUMMARY
|
/* SUMMARY
|
||||||
/* single-command client
|
/* single-command client
|
||||||
/* SYNOPSIS
|
/* SYNOPSIS
|
||||||
/* #include <mail_proto.h>
|
/* #include <mail_proto.h>
|
||||||
/*
|
/*
|
||||||
/* int mail_command_write(class, name, format, ...)
|
/* int mail_command_client(class, name, type, attr, ...)
|
||||||
/* const char *class;
|
/* const char *class;
|
||||||
/* const char *name;
|
/* const char *name;
|
||||||
/* const char *format;
|
/* int type;
|
||||||
|
/* const char *attr;
|
||||||
/* DESCRIPTION
|
/* DESCRIPTION
|
||||||
/* This module implements a client interface for single-command
|
/* This module implements a client interface for single-command
|
||||||
/* clients: a client that sends a single command and expects
|
/* clients: a client that sends a single command and expects
|
||||||
@@ -20,16 +21,17 @@
|
|||||||
/* Service type: MAIL_CLASS_PUBLIC or MAIL_CLASS_PRIVATE
|
/* Service type: MAIL_CLASS_PUBLIC or MAIL_CLASS_PRIVATE
|
||||||
/* .IP name
|
/* .IP name
|
||||||
/* Service name (master.cf).
|
/* Service name (master.cf).
|
||||||
/* .IP format
|
/* .IP "type, attr, ..."
|
||||||
/* Format string understood by mail_print(3).
|
/* Attribute information as defined in attr_print(3).
|
||||||
/* DIAGNOSTICS
|
/* DIAGNOSTICS
|
||||||
/* The result is -1 if the request could not be sent, otherwise
|
/* The result is -1 if the request could not be sent, otherwise
|
||||||
/* the result is the status reported by the server.
|
/* the result is the status reported by the server.
|
||||||
/* Warnings: problems connecting to the requested service.
|
/* Warnings: problems connecting to the requested service.
|
||||||
/* Fatal: out of memory.
|
/* Fatal: out of memory.
|
||||||
/* SEE ALSO
|
/* SEE ALSO
|
||||||
/* mail_command_read(3), server interface
|
/* attr_print(3), send attributes over byte stream
|
||||||
/* mail_proto(5h), client-server protocol
|
/* mail_command_server(3), server interface
|
||||||
|
/* mail_proto(3h), client-server protocol
|
||||||
/* LICENSE
|
/* LICENSE
|
||||||
/* .ad
|
/* .ad
|
||||||
/* .fi
|
/* .fi
|
||||||
@@ -53,12 +55,11 @@
|
|||||||
|
|
||||||
/* Global library. */
|
/* Global library. */
|
||||||
|
|
||||||
#include "mail_proto.h"
|
#include <mail_proto.h>
|
||||||
|
|
||||||
/* mail_command_write - single-command transaction with completion status */
|
/* mail_command_client - single-command transaction with completion status */
|
||||||
|
|
||||||
int mail_command_write(const char *class, const char *name,
|
int mail_command_client(const char *class, const char *name,...)
|
||||||
const char *fmt,...)
|
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
VSTREAM *stream;
|
VSTREAM *stream;
|
||||||
@@ -69,13 +70,12 @@ int mail_command_write(const char *class, const char *name,
|
|||||||
*/
|
*/
|
||||||
if ((stream = mail_connect(class, name, BLOCKING)) == 0)
|
if ((stream = mail_connect(class, name, BLOCKING)) == 0)
|
||||||
return (-1);
|
return (-1);
|
||||||
va_start(ap, fmt);
|
va_start(ap, name);
|
||||||
status = mail_vprint(stream, fmt, ap);
|
status = attr_vprint(stream, ATTR_FLAG_NONE, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
if (status != 0
|
if (status != 0
|
||||||
|| mail_print(stream, "%s", MAIL_EOF) != 0
|
|| attr_scan(stream, ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA,
|
||||||
|| vstream_fflush(stream) != 0
|
ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &status, 0) != 1)
|
||||||
|| mail_scan(stream, "%d", &status) != 1)
|
|
||||||
status = -1;
|
status = -1;
|
||||||
(void) vstream_fclose(stream);
|
(void) vstream_fclose(stream);
|
||||||
return (status);
|
return (status);
|
@@ -1,14 +1,15 @@
|
|||||||
/*++
|
/*++
|
||||||
/* NAME
|
/* NAME
|
||||||
/* mail_command_read 3
|
/* mail_command_server 3
|
||||||
/* SUMMARY
|
/* SUMMARY
|
||||||
/* single-command server
|
/* single-command server
|
||||||
/* SYNOPSIS
|
/* SYNOPSIS
|
||||||
/* #include <mail_proto.h>
|
/* #include <mail_proto.h>
|
||||||
/*
|
/*
|
||||||
/* int mail_command_read(stream, format, ...)
|
/* int mail_command_server(stream, type, name, ...)
|
||||||
/* VSTREAM *stream;
|
/* VSTREAM *stream;
|
||||||
/* char *format;
|
/* int type;
|
||||||
|
/* const char *name;
|
||||||
/* DESCRIPTION
|
/* DESCRIPTION
|
||||||
/* This module implements the server interface for single-command
|
/* This module implements the server interface for single-command
|
||||||
/* requests: a clients sends a single command and expects a single
|
/* requests: a clients sends a single command and expects a single
|
||||||
@@ -17,13 +18,15 @@
|
|||||||
/* Arguments:
|
/* Arguments:
|
||||||
/* .IP stream
|
/* .IP stream
|
||||||
/* Server endpoint.
|
/* Server endpoint.
|
||||||
/* .IP format
|
/* .IP "type, name, ..."
|
||||||
/* Format string understood by mail_print(3) and mail_scan(3).
|
/* Attribute list as defined in attr_scan(3).
|
||||||
/* DIAGNOSTICS
|
/* DIAGNOSTICS
|
||||||
/* Fatal: out of memory.
|
/* Fatal: out of memory.
|
||||||
/* SEE ALSO
|
/* SEE ALSO
|
||||||
/* mail_scan(3)
|
/* attr_scan(3)
|
||||||
/* mail_command_write(3) client interface
|
/* mail_command_client(3) client interface
|
||||||
|
/* mail_proto(3h), client-server protocol
|
||||||
|
#include <mail_proto.h>
|
||||||
/* LICENSE
|
/* LICENSE
|
||||||
/* .ad
|
/* .ad
|
||||||
/* .fi
|
/* .fi
|
||||||
@@ -44,26 +47,21 @@
|
|||||||
|
|
||||||
/* Utility library. */
|
/* Utility library. */
|
||||||
|
|
||||||
#include <vstring.h>
|
|
||||||
#include <vstream.h>
|
#include <vstream.h>
|
||||||
|
|
||||||
/* Global library. */
|
/* Global library. */
|
||||||
|
|
||||||
#include "mail_proto.h"
|
#include "mail_proto.h"
|
||||||
|
|
||||||
/* mail_command_read - read single-command request */
|
/* mail_command_server - read single-command request */
|
||||||
|
|
||||||
int mail_command_read(VSTREAM *stream, char *fmt,...)
|
int mail_command_server(VSTREAM *stream,...)
|
||||||
{
|
{
|
||||||
VSTRING *eof = vstring_alloc(10);
|
|
||||||
va_list ap;
|
va_list ap;
|
||||||
int count;
|
int count;
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, stream);
|
||||||
count = mail_vscan(stream, fmt, ap);
|
count = attr_vscan(stream, ATTR_FLAG_MISSING, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
if (mail_scan(stream, "%s", eof) != 1 || strcmp(vstring_str(eof), MAIL_EOF))
|
|
||||||
count = -1;
|
|
||||||
vstring_free(eof);
|
|
||||||
return (count);
|
return (count);
|
||||||
}
|
}
|
@@ -373,6 +373,10 @@ extern char *var_home_mailbox;
|
|||||||
#define DEF_MAILBOX_COMMAND ""
|
#define DEF_MAILBOX_COMMAND ""
|
||||||
extern char *var_mailbox_command;
|
extern char *var_mailbox_command;
|
||||||
|
|
||||||
|
#define VAR_MAILBOX_CMD_MAPS "mailbox_command_maps"
|
||||||
|
#define DEF_MAILBOX_CMD_MAPS ""
|
||||||
|
extern char *var_mailbox_cmd_maps;
|
||||||
|
|
||||||
#define VAR_MAILBOX_TRANSP "mailbox_transport"
|
#define VAR_MAILBOX_TRANSP "mailbox_transport"
|
||||||
#define DEF_MAILBOX_TRANSP ""
|
#define DEF_MAILBOX_TRANSP ""
|
||||||
extern char *var_mailbox_transport;
|
extern char *var_mailbox_transport;
|
||||||
|
@@ -21,6 +21,7 @@
|
|||||||
*/
|
*/
|
||||||
#include <vstream.h>
|
#include <vstream.h>
|
||||||
#include <iostuff.h>
|
#include <iostuff.h>
|
||||||
|
#include <attr.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Names of services: these are the names if INET ports, UNIX-domain sockets
|
* Names of services: these are the names if INET ports, UNIX-domain sockets
|
||||||
@@ -83,8 +84,8 @@ extern int mail_scan(VSTREAM *, const char *,...);
|
|||||||
extern void mail_scan_register(int, const char *, MAIL_SCAN_FN);
|
extern void mail_scan_register(int, const char *, MAIL_SCAN_FN);
|
||||||
extern void mail_print_register(int, const char *, MAIL_PRINT_FN);
|
extern void mail_print_register(int, const char *, MAIL_PRINT_FN);
|
||||||
extern int PRINTFLIKE(2, 3) mail_print(VSTREAM *, const char *,...);
|
extern int PRINTFLIKE(2, 3) mail_print(VSTREAM *, const char *,...);
|
||||||
extern int PRINTFLIKE(3, 4) mail_command_write(const char *, const char *, const char *,...);
|
extern int mail_command_client(const char *, const char *,...);
|
||||||
extern int mail_command_read(VSTREAM *, char *,...);
|
extern int mail_command_server(VSTREAM *,...);
|
||||||
extern int mail_trigger(const char *, const char *, const char *, int);
|
extern int mail_trigger(const char *, const char *, const char *, int);
|
||||||
extern char *mail_pathname(const char *, const char *);
|
extern char *mail_pathname(const char *, const char *);
|
||||||
|
|
||||||
@@ -94,6 +95,31 @@ extern char *mail_pathname(const char *, const char *);
|
|||||||
extern int mail_vprint(VSTREAM *, const char *, va_list);
|
extern int mail_vprint(VSTREAM *, const char *, va_list);
|
||||||
extern int mail_vscan(VSTREAM *, const char *, va_list);
|
extern int mail_vscan(VSTREAM *, const char *, va_list);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Attribute names.
|
||||||
|
*/
|
||||||
|
#define MAIL_ATTR_REQ "request"
|
||||||
|
#define MAIL_ATTR_NREQ "nrequest"
|
||||||
|
#define MAIL_ATTR_STATUS "status"
|
||||||
|
|
||||||
|
#define MAIL_ATTR_FLAGS "flags"
|
||||||
|
#define MAIL_ATTR_QUEUE "queue_name"
|
||||||
|
#define MAIL_ATTR_QUEUEID "queue_id"
|
||||||
|
#define MAIL_ATTR_SENDER "sender"
|
||||||
|
#define MAIL_ATTR_RECIP "recipient"
|
||||||
|
#define MAIL_ATTR_WHY "reason"
|
||||||
|
#define MAIL_ATTR_VERPDL "verp_delimiters"
|
||||||
|
#define MAIL_ATTR_SITE "site"
|
||||||
|
#define MAIL_ATTR_OFFSET "offset"
|
||||||
|
#define MAIL_ATTR_SIZE "size"
|
||||||
|
#define MAIL_ATTR_ERRTO "errors-to"
|
||||||
|
#define MAIL_ATTR_RRCPT "return-receipt"
|
||||||
|
#define MAIL_ATTR_TIME "time"
|
||||||
|
#define MAIL_ATTR_RULE "rule"
|
||||||
|
#define MAIL_ATTR_ADDR "address"
|
||||||
|
#define MAIL_ATTR_TRANSPORT "transport"
|
||||||
|
#define MAIL_ATTR_NEXTHOP "nexthop"
|
||||||
|
|
||||||
/* LICENSE
|
/* LICENSE
|
||||||
/* .ad
|
/* .ad
|
||||||
/* .fi
|
/* .fi
|
||||||
|
@@ -168,7 +168,8 @@ static int mail_stream_finish_ipc(MAIL_STREAM * info)
|
|||||||
/*
|
/*
|
||||||
* Receive the peer's completion status.
|
* Receive the peer's completion status.
|
||||||
*/
|
*/
|
||||||
if (mail_scan(info->stream, "%d", &status) != 1)
|
if (attr_scan(info->stream, ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA,
|
||||||
|
ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &status, 0) != 1)
|
||||||
status = CLEANUP_STAT_WRITE;
|
status = CLEANUP_STAT_WRITE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -218,7 +219,8 @@ MAIL_STREAM *mail_stream_service(const char *class, const char *name)
|
|||||||
id_buf = vstring_alloc(10);
|
id_buf = vstring_alloc(10);
|
||||||
|
|
||||||
stream = mail_connect_wait(class, name);
|
stream = mail_connect_wait(class, name);
|
||||||
if (mail_scan(stream, "%s", id_buf) != 1) {
|
if (attr_scan(stream, ATTR_FLAG_MISSING,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id_buf, 0) != 1) {
|
||||||
vstream_fclose(stream);
|
vstream_fclose(stream);
|
||||||
return (0);
|
return (0);
|
||||||
} else {
|
} else {
|
||||||
@@ -264,7 +266,8 @@ MAIL_STREAM *mail_stream_command(const char *command)
|
|||||||
}
|
}
|
||||||
argv_free(export_env);
|
argv_free(export_env);
|
||||||
|
|
||||||
if (mail_scan(stream, "%s", id_buf) != 1) {
|
if (attr_scan(stream, ATTR_FLAG_MISSING,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id_buf, 0) != 1) {
|
||||||
vstream_pclose(stream);
|
vstream_pclose(stream);
|
||||||
return (0);
|
return (0);
|
||||||
} else {
|
} else {
|
||||||
|
@@ -15,7 +15,7 @@
|
|||||||
* Version of this program.
|
* Version of this program.
|
||||||
*/
|
*/
|
||||||
#define VAR_MAIL_VERSION "mail_version"
|
#define VAR_MAIL_VERSION "mail_version"
|
||||||
#define DEF_MAIL_VERSION "Snapshot-20011010"
|
#define DEF_MAIL_VERSION "Snapshot-20011014"
|
||||||
extern char *var_mail_version;
|
extern char *var_mail_version;
|
||||||
|
|
||||||
/* LICENSE
|
/* LICENSE
|
||||||
|
@@ -139,8 +139,12 @@ static void post_mail_init(VSTREAM *stream, const char *sender,
|
|||||||
/*
|
/*
|
||||||
* Negotiate with the cleanup service. Give up if we can't agree.
|
* Negotiate with the cleanup service. Give up if we can't agree.
|
||||||
*/
|
*/
|
||||||
if (mail_scan(stream, "%s", id) != 1
|
if (attr_scan(stream, ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA,
|
||||||
|| mail_print(stream, "%d", flags) != 0)
|
ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id,
|
||||||
|
ATTR_TYPE_END) != 1
|
||||||
|
|| attr_print(stream, ATTR_FLAG_NONE,
|
||||||
|
ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags,
|
||||||
|
ATTR_TYPE_END) != 0)
|
||||||
msg_fatal("unable to contact the %s service", MAIL_SERVICE_CLEANUP);
|
msg_fatal("unable to contact the %s service", MAIL_SERVICE_CLEANUP);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -232,7 +236,9 @@ int post_mail_fclose(VSTREAM *cleanup)
|
|||||||
} else {
|
} else {
|
||||||
rec_fputs(cleanup, REC_TYPE_XTRA, "");
|
rec_fputs(cleanup, REC_TYPE_XTRA, "");
|
||||||
rec_fputs(cleanup, REC_TYPE_END, "");
|
rec_fputs(cleanup, REC_TYPE_END, "");
|
||||||
if (vstream_fflush(cleanup) || mail_scan(cleanup, "%d", &status) != 1)
|
if (vstream_fflush(cleanup) || attr_scan(cleanup, ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA,
|
||||||
|
ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &status,
|
||||||
|
ATTR_TYPE_END) != 1)
|
||||||
status = CLEANUP_STAT_WRITE;
|
status = CLEANUP_STAT_WRITE;
|
||||||
}
|
}
|
||||||
(void) vstream_fclose(cleanup);
|
(void) vstream_fclose(cleanup);
|
||||||
|
@@ -156,13 +156,20 @@ void resolve_clnt_query(const char *addr, RESOLVE_REPLY *reply)
|
|||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
stream = clnt_stream_access(rewrite_clnt_stream);
|
stream = clnt_stream_access(rewrite_clnt_stream);
|
||||||
if (mail_print(stream, "%s %s", RESOLVE_ADDR, addr)
|
if (attr_print(stream, ATTR_FLAG_NONE,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_REQ, RESOLVE_ADDR,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_ADDR, addr,
|
||||||
|
ATTR_TYPE_END)
|
||||||
|| vstream_fflush(stream)) {
|
|| vstream_fflush(stream)) {
|
||||||
if (msg_verbose || (errno != EPIPE && errno != ENOENT))
|
if (msg_verbose || (errno != EPIPE && errno != ENOENT))
|
||||||
msg_warn("%s: bad write: %m", myname);
|
msg_warn("%s: bad write: %m", myname);
|
||||||
} else if (mail_scan(stream, "%s %s %s %d",
|
} else if (attr_scan(stream, ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA,
|
||||||
reply->transport, reply->nexthop,
|
ATTR_TYPE_STR, MAIL_ATTR_TRANSPORT, reply->transport,
|
||||||
reply->recipient, &reply->flags) != 4) {
|
ATTR_TYPE_STR, MAIL_ATTR_NEXTHOP, reply->nexthop,
|
||||||
|
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_RECIP, reply->recipient,
|
||||||
|
ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, &reply->flags,
|
||||||
|
ATTR_TYPE_END) != 4) {
|
||||||
if (msg_verbose || (errno != EPIPE && errno != ENOENT))
|
if (msg_verbose || (errno != EPIPE && errno != ENOENT))
|
||||||
msg_warn("%s: bad read: %m", myname);
|
msg_warn("%s: bad read: %m", myname);
|
||||||
} else {
|
} else {
|
||||||
|
@@ -123,11 +123,17 @@ VSTRING *rewrite_clnt(const char *rule, const char *addr, VSTRING *result)
|
|||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
stream = clnt_stream_access(rewrite_clnt_stream);
|
stream = clnt_stream_access(rewrite_clnt_stream);
|
||||||
if (mail_print(stream, "%s %s %s", REWRITE_ADDR, rule, addr),
|
if (attr_print(stream, ATTR_FLAG_NONE,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_REQ, REWRITE_ADDR,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_RULE, rule,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_ADDR, addr,
|
||||||
|
ATTR_TYPE_END),
|
||||||
vstream_fflush(stream)) {
|
vstream_fflush(stream)) {
|
||||||
if (msg_verbose || (errno != EPIPE && errno != ENOENT))
|
if (msg_verbose || (errno != EPIPE && errno != ENOENT))
|
||||||
msg_warn("%s: bad write: %m", myname);
|
msg_warn("%s: bad write: %m", myname);
|
||||||
} else if (mail_scan(stream, "%s", result) != 1) {
|
} else if (attr_scan(stream, ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_ADDR, result,
|
||||||
|
ATTR_TYPE_END) != 1) {
|
||||||
if (msg_verbose || (errno != EPIPE && errno != ENOENT))
|
if (msg_verbose || (errno != EPIPE && errno != ENOENT))
|
||||||
msg_warn("%s: bad read: %m", myname);
|
msg_warn("%s: bad read: %m", myname);
|
||||||
} else {
|
} else {
|
||||||
|
@@ -9,7 +9,7 @@
|
|||||||
/* int deliver_command(state, usr_attr, command)
|
/* int deliver_command(state, usr_attr, command)
|
||||||
/* LOCAL_STATE state;
|
/* LOCAL_STATE state;
|
||||||
/* USER_ATTR exp_attr;
|
/* USER_ATTR exp_attr;
|
||||||
/* char *command;
|
/* const char *command;
|
||||||
/* DESCRIPTION
|
/* DESCRIPTION
|
||||||
/* deliver_command() runs a command with a message as standard
|
/* deliver_command() runs a command with a message as standard
|
||||||
/* input. A limited amount of standard output and standard error
|
/* input. A limited amount of standard output and standard error
|
||||||
@@ -79,7 +79,7 @@
|
|||||||
|
|
||||||
/* deliver_command - deliver to shell command */
|
/* deliver_command - deliver to shell command */
|
||||||
|
|
||||||
int deliver_command(LOCAL_STATE state, USER_ATTR usr_attr, char *command)
|
int deliver_command(LOCAL_STATE state, USER_ATTR usr_attr, const char *command)
|
||||||
{
|
{
|
||||||
char *myname = "deliver_command";
|
char *myname = "deliver_command";
|
||||||
VSTRING *why;
|
VSTRING *why;
|
||||||
@@ -112,6 +112,7 @@ int deliver_command(LOCAL_STATE state, USER_ATTR usr_attr, char *command)
|
|||||||
* Do we permit mail to shell commands? Allow delivery via mailbox_command.
|
* Do we permit mail to shell commands? Allow delivery via mailbox_command.
|
||||||
*/
|
*/
|
||||||
if (command != var_mailbox_command
|
if (command != var_mailbox_command
|
||||||
|
&& command != map_command /* XXX */
|
||||||
&& (local_cmd_deliver_mask & state.msg_attr.exp_type) == 0)
|
&& (local_cmd_deliver_mask & state.msg_attr.exp_type) == 0)
|
||||||
return (bounce_append(BOUNCE_FLAG_KEEP, BOUNCE_ATTR(state.msg_attr),
|
return (bounce_append(BOUNCE_FLAG_KEEP, BOUNCE_ATTR(state.msg_attr),
|
||||||
"mail to command is restricted"));
|
"mail to command is restricted"));
|
||||||
|
@@ -125,7 +125,9 @@ static FORWARD_INFO *forward_open(char *sender)
|
|||||||
if (cleanup == 0)
|
if (cleanup == 0)
|
||||||
return (0);
|
return (0);
|
||||||
close_on_exec(vstream_fileno(cleanup), CLOSE_ON_EXEC);
|
close_on_exec(vstream_fileno(cleanup), CLOSE_ON_EXEC);
|
||||||
if (mail_scan(cleanup, "%s", buffer) != 1) {
|
if (attr_scan(cleanup, ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, buffer,
|
||||||
|
ATTR_TYPE_END) != 1) {
|
||||||
vstream_fclose(cleanup);
|
vstream_fclose(cleanup);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
@@ -133,7 +135,9 @@ static FORWARD_INFO *forward_open(char *sender)
|
|||||||
info->cleanup = cleanup;
|
info->cleanup = cleanup;
|
||||||
info->queue_id = mystrdup(vstring_str(buffer));
|
info->queue_id = mystrdup(vstring_str(buffer));
|
||||||
info->posting_time = time((time_t *) 0);
|
info->posting_time = time((time_t *) 0);
|
||||||
mail_print(cleanup, "%d", CLEANUP_FLAG_BOUNCE);
|
attr_print(cleanup, ATTR_FLAG_NONE,
|
||||||
|
ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, CLEANUP_FLAG_BOUNCE,
|
||||||
|
ATTR_TYPE_END);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Send initial message envelope information. For bounces, set the
|
* Send initial message envelope information. For bounces, set the
|
||||||
@@ -233,7 +237,9 @@ static int forward_send(FORWARD_INFO *info, DELIVER_ATTR attr, char *delivered)
|
|||||||
*/
|
*/
|
||||||
if (status == 0)
|
if (status == 0)
|
||||||
if (vstream_fflush(info->cleanup)
|
if (vstream_fflush(info->cleanup)
|
||||||
|| mail_scan(info->cleanup, "%d", &status) != 1)
|
|| attr_scan(info->cleanup, ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA,
|
||||||
|
ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &status,
|
||||||
|
ATTR_TYPE_END) != 1)
|
||||||
status = 1;
|
status = 1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -307,6 +307,9 @@
|
|||||||
/* External command to use for mailbox delivery. The command executes
|
/* External command to use for mailbox delivery. The command executes
|
||||||
/* with the recipient privileges (exception: root). The string is subject
|
/* with the recipient privileges (exception: root). The string is subject
|
||||||
/* to $name expansions.
|
/* to $name expansions.
|
||||||
|
/* .IP \fBmailbox_command_maps\fR
|
||||||
|
/* Lookup tables with per-recipient external commands to use for mailbox
|
||||||
|
/* delivery. Behavior is as with \fBmailbox_command\fR.
|
||||||
/* .IP \fBmailbox_transport\fR
|
/* .IP \fBmailbox_transport\fR
|
||||||
/* Message transport to use for mailbox delivery to all local
|
/* Message transport to use for mailbox delivery to all local
|
||||||
/* recipients, whether or not they are found in the UNIX passwd database.
|
/* recipients, whether or not they are found in the UNIX passwd database.
|
||||||
@@ -446,6 +449,7 @@ int var_dup_filter_limit;
|
|||||||
int var_command_maxtime;
|
int var_command_maxtime;
|
||||||
char *var_home_mailbox;
|
char *var_home_mailbox;
|
||||||
char *var_mailbox_command;
|
char *var_mailbox_command;
|
||||||
|
char *var_mailbox_cmd_maps;
|
||||||
char *var_rcpt_fdelim;
|
char *var_rcpt_fdelim;
|
||||||
char *var_local_cmd_shell;
|
char *var_local_cmd_shell;
|
||||||
char *var_luser_relay;
|
char *var_luser_relay;
|
||||||
@@ -695,6 +699,7 @@ int main(int argc, char **argv)
|
|||||||
static CONFIG_RAW_TABLE raw_table[] = {
|
static CONFIG_RAW_TABLE raw_table[] = {
|
||||||
VAR_FORWARD_PATH, DEF_FORWARD_PATH, &var_forward_path, 0, 0,
|
VAR_FORWARD_PATH, DEF_FORWARD_PATH, &var_forward_path, 0, 0,
|
||||||
VAR_MAILBOX_COMMAND, DEF_MAILBOX_COMMAND, &var_mailbox_command, 0, 0,
|
VAR_MAILBOX_COMMAND, DEF_MAILBOX_COMMAND, &var_mailbox_command, 0, 0,
|
||||||
|
VAR_MAILBOX_CMD_MAPS, DEF_MAILBOX_CMD_MAPS, &var_mailbox_cmd_maps, 0, 0,
|
||||||
VAR_LUSER_RELAY, DEF_LUSER_RELAY, &var_luser_relay, 0, 0,
|
VAR_LUSER_RELAY, DEF_LUSER_RELAY, &var_luser_relay, 0, 0,
|
||||||
0,
|
0,
|
||||||
};
|
};
|
||||||
|
@@ -152,12 +152,14 @@ extern int deliver_resolve_addr(LOCAL_STATE, USER_ATTR, char *);
|
|||||||
* "leaf" nodes of the delivery graph.
|
* "leaf" nodes of the delivery graph.
|
||||||
*/
|
*/
|
||||||
extern int deliver_mailbox(LOCAL_STATE, USER_ATTR, int *);
|
extern int deliver_mailbox(LOCAL_STATE, USER_ATTR, int *);
|
||||||
extern int deliver_command(LOCAL_STATE, USER_ATTR, char *);
|
extern int deliver_command(LOCAL_STATE, USER_ATTR, const char *);
|
||||||
extern int deliver_file(LOCAL_STATE, USER_ATTR, char *);
|
extern int deliver_file(LOCAL_STATE, USER_ATTR, char *);
|
||||||
extern int deliver_indirect(LOCAL_STATE);
|
extern int deliver_indirect(LOCAL_STATE);
|
||||||
extern int deliver_maildir(LOCAL_STATE, USER_ATTR, char *);
|
extern int deliver_maildir(LOCAL_STATE, USER_ATTR, char *);
|
||||||
extern int deliver_unknown(LOCAL_STATE, USER_ATTR);
|
extern int deliver_unknown(LOCAL_STATE, USER_ATTR);
|
||||||
|
|
||||||
|
extern const char *map_command; /* XXX */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Restrictions on delivery to sensitive destinations.
|
* Restrictions on delivery to sensitive destinations.
|
||||||
*/
|
*/
|
||||||
|
@@ -72,6 +72,7 @@
|
|||||||
#include <mail_params.h>
|
#include <mail_params.h>
|
||||||
#include <deliver_pass.h>
|
#include <deliver_pass.h>
|
||||||
#include <mbox_open.h>
|
#include <mbox_open.h>
|
||||||
|
#include <maps.h>
|
||||||
|
|
||||||
#ifndef EDQUOT
|
#ifndef EDQUOT
|
||||||
#define EDQUOT EFBIG
|
#define EDQUOT EFBIG
|
||||||
@@ -85,6 +86,8 @@
|
|||||||
#define YES 1
|
#define YES 1
|
||||||
#define NO 0
|
#define NO 0
|
||||||
|
|
||||||
|
const char *map_command; /* XXX */
|
||||||
|
|
||||||
/* deliver_mailbox_file - deliver to recipient mailbox */
|
/* deliver_mailbox_file - deliver to recipient mailbox */
|
||||||
|
|
||||||
static int deliver_mailbox_file(LOCAL_STATE state, USER_ATTR usr_attr)
|
static int deliver_mailbox_file(LOCAL_STATE state, USER_ATTR usr_attr)
|
||||||
@@ -233,6 +236,7 @@ int deliver_mailbox(LOCAL_STATE state, USER_ATTR usr_attr, int *statusp)
|
|||||||
int status;
|
int status;
|
||||||
struct mypasswd *mbox_pwd;
|
struct mypasswd *mbox_pwd;
|
||||||
char *path;
|
char *path;
|
||||||
|
static MAPS *cmd_maps;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Make verbose logging easier to understand.
|
* Make verbose logging easier to understand.
|
||||||
@@ -280,9 +284,21 @@ int deliver_mailbox(LOCAL_STATE state, USER_ATTR usr_attr, int *statusp)
|
|||||||
*/
|
*/
|
||||||
#define LAST_CHAR(s) (s[strlen(s) - 1])
|
#define LAST_CHAR(s) (s[strlen(s) - 1])
|
||||||
|
|
||||||
if (*var_mailbox_command)
|
if (*var_mailbox_cmd_maps) {
|
||||||
|
if (cmd_maps == 0)
|
||||||
|
cmd_maps = maps_create(VAR_MAILBOX_CMD_MAPS, var_mailbox_cmd_maps,
|
||||||
|
DICT_FLAG_LOCK);
|
||||||
|
if ((map_command = maps_find(cmd_maps, state.msg_attr.user,
|
||||||
|
DICT_FLAG_FIXED)) != 0) {
|
||||||
|
status = deliver_command(state, usr_attr, map_command);
|
||||||
|
} else {
|
||||||
|
msg_warn("user %s not found in %s",
|
||||||
|
state.msg_attr.user, var_mailbox_cmd_maps);
|
||||||
|
return (NO);
|
||||||
|
}
|
||||||
|
} else if (*var_mailbox_command) {
|
||||||
status = deliver_command(state, usr_attr, var_mailbox_command);
|
status = deliver_command(state, usr_attr, var_mailbox_command);
|
||||||
else if (*var_home_mailbox && LAST_CHAR(var_home_mailbox) == '/') {
|
} else if (*var_home_mailbox && LAST_CHAR(var_home_mailbox) == '/') {
|
||||||
path = concatenate(usr_attr.home, "/", var_home_mailbox, (char *) 0);
|
path = concatenate(usr_attr.home, "/", var_home_mailbox, (char *) 0);
|
||||||
status = deliver_maildir(state, usr_attr, path);
|
status = deliver_maildir(state, usr_attr, path);
|
||||||
myfree(path);
|
myfree(path);
|
||||||
|
@@ -92,7 +92,9 @@ static int qmgr_deliver_initial_reply(VSTREAM *stream)
|
|||||||
if (peekfd(vstream_fileno(stream)) < 0) {
|
if (peekfd(vstream_fileno(stream)) < 0) {
|
||||||
msg_warn("%s: premature disconnect", VSTREAM_PATH(stream));
|
msg_warn("%s: premature disconnect", VSTREAM_PATH(stream));
|
||||||
return (DELIVER_STAT_CRASH);
|
return (DELIVER_STAT_CRASH);
|
||||||
} else if (mail_scan(stream, "%d", &stat) != 1) {
|
} else if (attr_scan(stream, ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA,
|
||||||
|
ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &stat,
|
||||||
|
ATTR_TYPE_END) != 1) {
|
||||||
msg_warn("%s: malformed response", VSTREAM_PATH(stream));
|
msg_warn("%s: malformed response", VSTREAM_PATH(stream));
|
||||||
return (DELIVER_STAT_CRASH);
|
return (DELIVER_STAT_CRASH);
|
||||||
} else {
|
} else {
|
||||||
@@ -109,7 +111,10 @@ static int qmgr_deliver_final_reply(VSTREAM *stream, VSTRING *reason)
|
|||||||
if (peekfd(vstream_fileno(stream)) < 0) {
|
if (peekfd(vstream_fileno(stream)) < 0) {
|
||||||
msg_warn("%s: premature disconnect", VSTREAM_PATH(stream));
|
msg_warn("%s: premature disconnect", VSTREAM_PATH(stream));
|
||||||
return (DELIVER_STAT_CRASH);
|
return (DELIVER_STAT_CRASH);
|
||||||
} else if (mail_scan(stream, "%s %d", reason, &stat) != 2) {
|
} else if (attr_scan(stream, ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_WHY, reason,
|
||||||
|
ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &stat,
|
||||||
|
ATTR_TYPE_END) != 2) {
|
||||||
msg_warn("%s: malformed response", VSTREAM_PATH(stream));
|
msg_warn("%s: malformed response", VSTREAM_PATH(stream));
|
||||||
return (DELIVER_STAT_CRASH);
|
return (DELIVER_STAT_CRASH);
|
||||||
} else {
|
} else {
|
||||||
@@ -127,6 +132,8 @@ static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream)
|
|||||||
char *cp;
|
char *cp;
|
||||||
VSTRING *sender_buf = 0;
|
VSTRING *sender_buf = 0;
|
||||||
char *sender;
|
char *sender;
|
||||||
|
int flags;
|
||||||
|
char *nexthop;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If variable envelope return path is requested, change prefix+@origin
|
* If variable envelope return path is requested, change prefix+@origin
|
||||||
@@ -148,19 +155,32 @@ static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream)
|
|||||||
* concurrency limits. However, the delivery agent protocol expects
|
* concurrency limits. However, the delivery agent protocol expects
|
||||||
* nexthop only, so we must strip off the recipient local part.
|
* nexthop only, so we must strip off the recipient local part.
|
||||||
*/
|
*/
|
||||||
mail_print(stream, "%d %s %s %ld %ld %s %s %s %s %ld",
|
flags = message->inspect_xport ?
|
||||||
message->inspect_xport ? DEL_REQ_FLAG_BOUNCE : DEL_REQ_FLAG_DEFLT,
|
DEL_REQ_FLAG_BOUNCE : DEL_REQ_FLAG_DEFLT;
|
||||||
message->queue_name, message->queue_id,
|
nexthop = (cp = strrchr(entry->queue->name, '@')) != 0 && cp[1] ?
|
||||||
message->data_offset, message->data_size,
|
cp + 1 : entry->queue->name;
|
||||||
(cp = strrchr(entry->queue->name, '@')) != 0 && cp[1] ? cp + 1 :
|
attr_print(stream, ATTR_FLAG_MORE,
|
||||||
entry->queue->name, sender,
|
ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags,
|
||||||
message->errors_to, message->return_receipt,
|
ATTR_TYPE_STR, MAIL_ATTR_QUEUE, message->queue_name,
|
||||||
message->arrival_time);
|
ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, message->queue_id,
|
||||||
|
ATTR_TYPE_NUM, MAIL_ATTR_OFFSET, message->data_offset,
|
||||||
|
ATTR_TYPE_NUM, MAIL_ATTR_SIZE, message->data_size,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_NEXTHOP, nexthop,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_ERRTO, message->errors_to,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_RRCPT, message->return_receipt,
|
||||||
|
ATTR_TYPE_NUM, MAIL_ATTR_TIME, message->arrival_time,
|
||||||
|
ATTR_TYPE_END);
|
||||||
if (sender_buf != 0)
|
if (sender_buf != 0)
|
||||||
vstring_free(sender_buf);
|
vstring_free(sender_buf);
|
||||||
for (recipient = list.info; recipient < list.info + list.len; recipient++)
|
for (recipient = list.info; recipient < list.info + list.len; recipient++)
|
||||||
mail_print(stream, "%ld %s", recipient->offset, recipient->address);
|
attr_print(stream, ATTR_FLAG_MORE,
|
||||||
mail_print(stream, "%s", "0");
|
ATTR_TYPE_NUM, MAIL_ATTR_OFFSET, recipient->offset,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_RECIP, recipient->address,
|
||||||
|
ATTR_TYPE_END);
|
||||||
|
attr_print(stream, ATTR_FLAG_NONE,
|
||||||
|
ATTR_TYPE_NUM, MAIL_ATTR_OFFSET, 0,
|
||||||
|
ATTR_TYPE_END);
|
||||||
if (vstream_fflush(stream) != 0) {
|
if (vstream_fflush(stream) != 0) {
|
||||||
msg_warn("write to process (%s): %m", entry->queue->transport->name);
|
msg_warn("write to process (%s): %m", entry->queue->transport->name);
|
||||||
return (-1);
|
return (-1);
|
||||||
@@ -220,7 +240,7 @@ static void qmgr_deliver_update(int unused_event, char *context)
|
|||||||
*/
|
*/
|
||||||
if (status == DELIVER_STAT_CRASH) {
|
if (status == DELIVER_STAT_CRASH) {
|
||||||
message->flags |= DELIVER_STAT_DEFER;
|
message->flags |= DELIVER_STAT_DEFER;
|
||||||
qmgr_transport_throttle(transport, "unknown mail transport error");
|
qmgr_transport_throttle(transport, "unknown mail transport error -- see a previous warning/fatal/panic record for the problem description");
|
||||||
qmgr_defer_transport(transport, transport->reason);
|
qmgr_defer_transport(transport, transport->reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -295,7 +295,9 @@ static int pickup_copy(VSTREAM *qfile, VSTREAM *cleanup,
|
|||||||
* bounce, the cleanup service can report only soft errors here.
|
* bounce, the cleanup service can report only soft errors here.
|
||||||
*/
|
*/
|
||||||
rec_fputs(cleanup, REC_TYPE_END, "");
|
rec_fputs(cleanup, REC_TYPE_END, "");
|
||||||
if (mail_scan(cleanup, "%d", &status) != 1)
|
if (attr_scan(cleanup, ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA,
|
||||||
|
ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &status,
|
||||||
|
ATTR_TYPE_END) != 1)
|
||||||
return (cleanup_service_error(info, CLEANUP_STAT_WRITE));
|
return (cleanup_service_error(info, CLEANUP_STAT_WRITE));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -365,8 +367,12 @@ static int pickup_file(PICKUP_INFO *info)
|
|||||||
|
|
||||||
buf = vstring_alloc(100);
|
buf = vstring_alloc(100);
|
||||||
cleanup = mail_connect_wait(MAIL_CLASS_PRIVATE, MAIL_SERVICE_CLEANUP);
|
cleanup = mail_connect_wait(MAIL_CLASS_PRIVATE, MAIL_SERVICE_CLEANUP);
|
||||||
if (mail_scan(cleanup, "%s", buf) != 1
|
if (attr_scan(cleanup, ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA,
|
||||||
|| mail_print(cleanup, "%d", PICKUP_CLEANUP_FLAGS) != 0) {
|
ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, buf,
|
||||||
|
ATTR_TYPE_END) != 1
|
||||||
|
|| attr_print(cleanup, ATTR_FLAG_NONE,
|
||||||
|
ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, PICKUP_CLEANUP_FLAGS,
|
||||||
|
ATTR_TYPE_END) != 0) {
|
||||||
status = KEEP_MESSAGE_FILE;
|
status = KEEP_MESSAGE_FILE;
|
||||||
} else {
|
} else {
|
||||||
info->id = mystrdup(vstring_str(buf));
|
info->id = mystrdup(vstring_str(buf));
|
||||||
|
@@ -241,7 +241,9 @@ int main(int argc, char **argv)
|
|||||||
*/
|
*/
|
||||||
dst = mail_stream_file(MAIL_QUEUE_MAILDROP, MAIL_CLASS_PUBLIC,
|
dst = mail_stream_file(MAIL_QUEUE_MAILDROP, MAIL_CLASS_PUBLIC,
|
||||||
MAIL_SERVICE_PICKUP);
|
MAIL_SERVICE_PICKUP);
|
||||||
mail_print(VSTREAM_OUT, "%s", dst->id);
|
attr_print(VSTREAM_OUT, ATTR_FLAG_NONE,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, dst->id,
|
||||||
|
ATTR_TYPE_END);
|
||||||
vstream_fflush(VSTREAM_OUT);
|
vstream_fflush(VSTREAM_OUT);
|
||||||
postdrop_path = mystrdup(VSTREAM_PATH(dst->stream));
|
postdrop_path = mystrdup(VSTREAM_PATH(dst->stream));
|
||||||
|
|
||||||
@@ -302,7 +304,9 @@ int main(int argc, char **argv)
|
|||||||
/*
|
/*
|
||||||
* Send the completion status to the caller and terminate.
|
* Send the completion status to the caller and terminate.
|
||||||
*/
|
*/
|
||||||
mail_print(VSTREAM_OUT, "%d", status);
|
attr_print(VSTREAM_OUT, ATTR_FLAG_NONE,
|
||||||
|
ATTR_TYPE_NUM, MAIL_ATTR_STATUS, status,
|
||||||
|
ATTR_TYPE_END);
|
||||||
vstream_fflush(VSTREAM_OUT);
|
vstream_fflush(VSTREAM_OUT);
|
||||||
exit(status);
|
exit(status);
|
||||||
}
|
}
|
||||||
|
@@ -87,7 +87,9 @@ static int qmgr_deliver_initial_reply(VSTREAM *stream)
|
|||||||
if (peekfd(vstream_fileno(stream)) < 0) {
|
if (peekfd(vstream_fileno(stream)) < 0) {
|
||||||
msg_warn("%s: premature disconnect", VSTREAM_PATH(stream));
|
msg_warn("%s: premature disconnect", VSTREAM_PATH(stream));
|
||||||
return (DELIVER_STAT_CRASH);
|
return (DELIVER_STAT_CRASH);
|
||||||
} else if (mail_scan(stream, "%d", &stat) != 1) {
|
} else if (attr_scan(stream, ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA,
|
||||||
|
ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &stat,
|
||||||
|
ATTR_TYPE_END) != 1) {
|
||||||
msg_warn("%s: malformed response", VSTREAM_PATH(stream));
|
msg_warn("%s: malformed response", VSTREAM_PATH(stream));
|
||||||
return (DELIVER_STAT_CRASH);
|
return (DELIVER_STAT_CRASH);
|
||||||
} else {
|
} else {
|
||||||
@@ -104,7 +106,10 @@ static int qmgr_deliver_final_reply(VSTREAM *stream, VSTRING *reason)
|
|||||||
if (peekfd(vstream_fileno(stream)) < 0) {
|
if (peekfd(vstream_fileno(stream)) < 0) {
|
||||||
msg_warn("%s: premature disconnect", VSTREAM_PATH(stream));
|
msg_warn("%s: premature disconnect", VSTREAM_PATH(stream));
|
||||||
return (DELIVER_STAT_CRASH);
|
return (DELIVER_STAT_CRASH);
|
||||||
} else if (mail_scan(stream, "%s %d", reason, &stat) != 2) {
|
} else if (attr_scan(stream, ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_WHY, reason,
|
||||||
|
ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &stat,
|
||||||
|
ATTR_TYPE_END) != 2) {
|
||||||
msg_warn("%s: malformed response", VSTREAM_PATH(stream));
|
msg_warn("%s: malformed response", VSTREAM_PATH(stream));
|
||||||
return (DELIVER_STAT_CRASH);
|
return (DELIVER_STAT_CRASH);
|
||||||
} else {
|
} else {
|
||||||
@@ -122,6 +127,8 @@ static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream)
|
|||||||
char *cp;
|
char *cp;
|
||||||
VSTRING *sender_buf = 0;
|
VSTRING *sender_buf = 0;
|
||||||
char *sender;
|
char *sender;
|
||||||
|
int flags;
|
||||||
|
char *nexthop;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If variable envelope return path is requested, change prefix+@origin
|
* If variable envelope return path is requested, change prefix+@origin
|
||||||
@@ -143,19 +150,32 @@ static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream)
|
|||||||
* concurrency limits. However, the delivery agent protocol expects
|
* concurrency limits. However, the delivery agent protocol expects
|
||||||
* nexthop only, so we must strip off the recipient local part.
|
* nexthop only, so we must strip off the recipient local part.
|
||||||
*/
|
*/
|
||||||
mail_print(stream, "%d %s %s %ld %ld %s %s %s %s %ld",
|
flags = message->inspect_xport ?
|
||||||
message->inspect_xport ? DEL_REQ_FLAG_BOUNCE : DEL_REQ_FLAG_DEFLT,
|
DEL_REQ_FLAG_BOUNCE : DEL_REQ_FLAG_DEFLT;
|
||||||
message->queue_name, message->queue_id,
|
nexthop = (cp = strrchr(entry->queue->name, '@')) != 0 && cp[1] ?
|
||||||
message->data_offset, message->data_size,
|
cp + 1 : entry->queue->name;
|
||||||
(cp = strrchr(entry->queue->name, '@')) != 0 && cp[1] ? cp + 1 :
|
attr_print(stream, ATTR_FLAG_MORE,
|
||||||
entry->queue->name, sender,
|
ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags,
|
||||||
message->errors_to, message->return_receipt,
|
ATTR_TYPE_STR, MAIL_ATTR_QUEUE, message->queue_name,
|
||||||
message->arrival_time);
|
ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, message->queue_id,
|
||||||
|
ATTR_TYPE_NUM, MAIL_ATTR_OFFSET, message->data_offset,
|
||||||
|
ATTR_TYPE_NUM, MAIL_ATTR_SIZE, message->data_size,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_NEXTHOP, nexthop,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_ERRTO, message->errors_to,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_RRCPT, message->return_receipt,
|
||||||
|
ATTR_TYPE_NUM, MAIL_ATTR_TIME, message->arrival_time,
|
||||||
|
ATTR_TYPE_END);
|
||||||
if (sender_buf != 0)
|
if (sender_buf != 0)
|
||||||
vstring_free(sender_buf);
|
vstring_free(sender_buf);
|
||||||
for (recipient = list.info; recipient < list.info + list.len; recipient++)
|
for (recipient = list.info; recipient < list.info + list.len; recipient++)
|
||||||
mail_print(stream, "%ld %s", recipient->offset, recipient->address);
|
attr_print(stream, ATTR_FLAG_MORE,
|
||||||
mail_print(stream, "%s", "0");
|
ATTR_TYPE_NUM, MAIL_ATTR_OFFSET, recipient->offset,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_RECIP, recipient->address,
|
||||||
|
ATTR_TYPE_END);
|
||||||
|
attr_print(stream, ATTR_FLAG_NONE,
|
||||||
|
ATTR_TYPE_NUM, MAIL_ATTR_OFFSET, 0,
|
||||||
|
ATTR_TYPE_END);
|
||||||
if (vstream_fflush(stream) != 0) {
|
if (vstream_fflush(stream) != 0) {
|
||||||
msg_warn("write to process (%s): %m", entry->queue->transport->name);
|
msg_warn("write to process (%s): %m", entry->queue->transport->name);
|
||||||
return (-1);
|
return (-1);
|
||||||
@@ -215,7 +235,7 @@ static void qmgr_deliver_update(int unused_event, char *context)
|
|||||||
*/
|
*/
|
||||||
if (status == DELIVER_STAT_CRASH) {
|
if (status == DELIVER_STAT_CRASH) {
|
||||||
message->flags |= DELIVER_STAT_DEFER;
|
message->flags |= DELIVER_STAT_DEFER;
|
||||||
qmgr_transport_throttle(transport, "unknown mail transport error");
|
qmgr_transport_throttle(transport, "unknown mail transport error -- see a previous warning/fatal/panic record for the problem description");
|
||||||
qmgr_defer_transport(transport, transport->reason);
|
qmgr_defer_transport(transport, transport->reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -181,7 +181,9 @@ static void qmqpd_open_file(QMQPD_STATE *state)
|
|||||||
*/
|
*/
|
||||||
state->dest = mail_stream_service(MAIL_CLASS_PRIVATE, MAIL_SERVICE_CLEANUP);
|
state->dest = mail_stream_service(MAIL_CLASS_PRIVATE, MAIL_SERVICE_CLEANUP);
|
||||||
if (state->dest == 0
|
if (state->dest == 0
|
||||||
|| mail_print(state->dest->stream, "%d", CLEANUP_FLAG_FILTER) != 0)
|
|| attr_print(state->dest->stream, ATTR_FLAG_NONE,
|
||||||
|
ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, CLEANUP_FLAG_FILTER,
|
||||||
|
ATTR_TYPE_END) != 0)
|
||||||
msg_fatal("unable to connect to the %s %s service",
|
msg_fatal("unable to connect to the %s %s service",
|
||||||
MAIL_CLASS_PRIVATE, MAIL_SERVICE_CLEANUP);
|
MAIL_CLASS_PRIVATE, MAIL_SERVICE_CLEANUP);
|
||||||
state->cleanup = state->dest->stream;
|
state->cleanup = state->dest->stream;
|
||||||
|
@@ -515,7 +515,9 @@ static void mail_open_stream(SMTPD_STATE *state)
|
|||||||
state->dest = mail_stream_service(MAIL_CLASS_PRIVATE,
|
state->dest = mail_stream_service(MAIL_CLASS_PRIVATE,
|
||||||
MAIL_SERVICE_CLEANUP);
|
MAIL_SERVICE_CLEANUP);
|
||||||
if (state->dest == 0
|
if (state->dest == 0
|
||||||
|| mail_print(state->dest->stream, "%d", CLEANUP_FLAG_FILTER) != 0)
|
|| attr_print(state->dest->stream, ATTR_FLAG_NONE,
|
||||||
|
ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, CLEANUP_FLAG_FILTER,
|
||||||
|
ATTR_TYPE_END) != 0)
|
||||||
msg_fatal("unable to connect to the %s %s service",
|
msg_fatal("unable to connect to the %s %s service",
|
||||||
MAIL_CLASS_PRIVATE, MAIL_SERVICE_CLEANUP);
|
MAIL_CLASS_PRIVATE, MAIL_SERVICE_CLEANUP);
|
||||||
}
|
}
|
||||||
|
@@ -257,7 +257,9 @@ int resolve_proto(VSTREAM *stream)
|
|||||||
{
|
{
|
||||||
int flags;
|
int flags;
|
||||||
|
|
||||||
if (mail_scan(stream, "%s", query) != 1)
|
if (attr_scan(stream, ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_ADDR, query,
|
||||||
|
ATTR_TYPE_END) != 1)
|
||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
resolve_addr(STR(query), channel, nexthop, nextrcpt, &flags);
|
resolve_addr(STR(query), channel, nexthop, nextrcpt, &flags);
|
||||||
@@ -266,8 +268,12 @@ int resolve_proto(VSTREAM *stream)
|
|||||||
msg_info("%s -> (`%s' `%s' `%s' `%d')", STR(query), STR(channel),
|
msg_info("%s -> (`%s' `%s' `%s' `%d')", STR(query), STR(channel),
|
||||||
STR(nexthop), STR(nextrcpt), flags);
|
STR(nexthop), STR(nextrcpt), flags);
|
||||||
|
|
||||||
mail_print(stream, "%s %s %s %d",
|
attr_print(stream, ATTR_FLAG_NONE,
|
||||||
STR(channel), STR(nexthop), STR(nextrcpt), flags);
|
ATTR_TYPE_STR, MAIL_ATTR_TRANSPORT, STR(channel),
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_NEXTHOP, STR(nexthop),
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_RECIP, STR(nextrcpt),
|
||||||
|
ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags,
|
||||||
|
ATTR_TYPE_END);
|
||||||
|
|
||||||
if (vstream_fflush(stream) != 0) {
|
if (vstream_fflush(stream) != 0) {
|
||||||
msg_warn("write resolver reply: %m");
|
msg_warn("write resolver reply: %m");
|
||||||
|
@@ -203,7 +203,10 @@ void rewrite_addr(char *ruleset, char *addr, VSTRING *result)
|
|||||||
|
|
||||||
int rewrite_proto(VSTREAM *stream)
|
int rewrite_proto(VSTREAM *stream)
|
||||||
{
|
{
|
||||||
if (mail_scan(stream, "%s %s", ruleset, address) != 2)
|
if (attr_scan(stream, ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_RULE, ruleset,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_ADDR, address,
|
||||||
|
ATTR_TYPE_END) != 2)
|
||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
rewrite_addr(vstring_str(ruleset), vstring_str(address), result);
|
rewrite_addr(vstring_str(ruleset), vstring_str(address), result);
|
||||||
@@ -212,7 +215,9 @@ int rewrite_proto(VSTREAM *stream)
|
|||||||
msg_info("`%s' `%s' -> `%s'", vstring_str(ruleset),
|
msg_info("`%s' `%s' -> `%s'", vstring_str(ruleset),
|
||||||
vstring_str(address), vstring_str(result));
|
vstring_str(address), vstring_str(result));
|
||||||
|
|
||||||
mail_print(stream, "%s", vstring_str(result));
|
attr_print(stream, ATTR_FLAG_NONE,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_ADDR, vstring_str(result),
|
||||||
|
ATTR_TYPE_END);
|
||||||
|
|
||||||
if (vstream_fflush(stream) != 0) {
|
if (vstream_fflush(stream) != 0) {
|
||||||
msg_warn("write rewrite reply: %m");
|
msg_warn("write rewrite reply: %m");
|
||||||
|
@@ -181,7 +181,9 @@ static void rewrite_service(VSTREAM *stream, char *unused_service, char **argv)
|
|||||||
* dedicated to address rewriting. All connection-management stuff is
|
* dedicated to address rewriting. All connection-management stuff is
|
||||||
* handled by the common code in multi_server.c.
|
* handled by the common code in multi_server.c.
|
||||||
*/
|
*/
|
||||||
if (mail_scan(stream, "%s", command) == 1) {
|
if (attr_scan(stream, ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA | ATTR_FLAG_MORE,
|
||||||
|
ATTR_TYPE_STR, MAIL_ATTR_REQ, command,
|
||||||
|
ATTR_TYPE_END) == 1) {
|
||||||
if (strcmp(vstring_str(command), REWRITE_ADDR) == 0) {
|
if (strcmp(vstring_str(command), REWRITE_ADDR) == 0) {
|
||||||
status = rewrite_proto(stream);
|
status = rewrite_proto(stream);
|
||||||
} else if (strcmp(vstring_str(command), RESOLVE_ADDR) == 0) {
|
} else if (strcmp(vstring_str(command), RESOLVE_ADDR) == 0) {
|
||||||
|
@@ -24,7 +24,7 @@ SRCS = argv.c argv_split.c attr.c basename.c binhash.c chroot_uid.c \
|
|||||||
sane_link.c unescape.c timed_read.c timed_write.c dict_tcp.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 \
|
hex_quote.c dict_alloc.c rand_sleep.c sane_time.c dict_debug.c \
|
||||||
sane_socketpair.c myrand.c netstring.c ctable.c attr_print.c intv.c \
|
sane_socketpair.c myrand.c netstring.c ctable.c attr_print.c intv.c \
|
||||||
attr_scan.c
|
attr_scan.c attr_table.c
|
||||||
OBJS = argv.o argv_split.o attr.o basename.o binhash.o chroot_uid.o \
|
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 \
|
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 \
|
dict_env.o dict_ht.o dict_ldap.o dict_mysql.o dict_ni.o dict_nis.o \
|
||||||
@@ -50,7 +50,7 @@ OBJS = argv.o argv_split.o attr.o basename.o binhash.o chroot_uid.o \
|
|||||||
sane_link.o unescape.o timed_read.o timed_write.o dict_tcp.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 \
|
hex_quote.o dict_alloc.o rand_sleep.o sane_time.o dict_debug.o \
|
||||||
sane_socketpair.o myrand.o netstring.o ctable.o attr_print.o intv.o \
|
sane_socketpair.o myrand.o netstring.o ctable.o attr_print.o intv.o \
|
||||||
attr_scan.o
|
attr_scan.o attr_table.o
|
||||||
HDRS = argv.h attr.h binhash.h chroot_uid.h connect.h dict.h dict_db.h \
|
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_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 \
|
dict_ni.h dict_nis.h dict_nisplus.h dir_forest.h events.h \
|
||||||
@@ -67,7 +67,7 @@ HDRS = argv.h attr.h binhash.h chroot_uid.h connect.h dict.h dict_db.h \
|
|||||||
dict_unix.h dict_pcre.h dict_regexp.h mac_expand.h clean_env.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 \
|
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
|
intv.h
|
||||||
TESTSRC = fifo_open.c fifo_rdwr_bug.c fifo_rdonly_bug.c select_bug.c \
|
TESTSRC = fifo_open.c fifo_rdwr_bug.c fifo_rdonly_bug.c select_bug.c \
|
||||||
stream_test.c dup2_pass_on_exec.c
|
stream_test.c dup2_pass_on_exec.c
|
||||||
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
|
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
|
||||||
@@ -84,7 +84,7 @@ TESTPROG= dict_open dup2_pass_on_exec events exec_command fifo_open \
|
|||||||
mystrtok sigdelay translit valid_hostname vstream_popen \
|
mystrtok sigdelay translit valid_hostname vstream_popen \
|
||||||
vstring vstring_vstream doze select_bug stream_test mac_expand \
|
vstring vstring_vstream doze select_bug stream_test mac_expand \
|
||||||
watchdog unescape hex_quote name_mask rand_sleep sane_time ctable \
|
watchdog unescape hex_quote name_mask rand_sleep sane_time ctable \
|
||||||
inet_addr_list attr_print attr_scan
|
inet_addr_list attr_print attr_scan attr_table
|
||||||
|
|
||||||
LIB_DIR = ../../lib
|
LIB_DIR = ../../lib
|
||||||
INC_DIR = ../../include
|
INC_DIR = ../../include
|
||||||
@@ -298,6 +298,11 @@ attr_scan: $(LIB) $@.o
|
|||||||
$(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS)
|
$(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS)
|
||||||
mv junk $@.o
|
mv junk $@.o
|
||||||
|
|
||||||
|
attr_table: $(LIB) $@.o
|
||||||
|
mv $@.o junk
|
||||||
|
$(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS)
|
||||||
|
mv junk $@.o
|
||||||
|
|
||||||
depend: $(MAKES)
|
depend: $(MAKES)
|
||||||
(sed '1,/^# do not edit/!d' Makefile.in; \
|
(sed '1,/^# do not edit/!d' Makefile.in; \
|
||||||
set -e; for i in [a-z][a-z0-9]*.c; do \
|
set -e; for i in [a-z][a-z0-9]*.c; do \
|
||||||
@@ -369,24 +374,43 @@ argv_split.o: vbuf.h
|
|||||||
argv_split.o: argv.h
|
argv_split.o: argv.h
|
||||||
attr.o: attr.c
|
attr.o: attr.c
|
||||||
attr.o: sys_defs.h
|
attr.o: sys_defs.h
|
||||||
|
attr.o: msg.h
|
||||||
attr.o: mymalloc.h
|
attr.o: mymalloc.h
|
||||||
attr.o: htable.h
|
attr.o: htable.h
|
||||||
attr.o: attr.h
|
attr.o: attr.h
|
||||||
|
attr.o: vstream.h
|
||||||
|
attr.o: vbuf.h
|
||||||
attr_print.o: attr_print.c
|
attr_print.o: attr_print.c
|
||||||
attr_print.o: sys_defs.h
|
attr_print.o: sys_defs.h
|
||||||
|
attr_print.o: msg.h
|
||||||
|
attr_print.o: mymalloc.h
|
||||||
attr_print.o: vstream.h
|
attr_print.o: vstream.h
|
||||||
attr_print.o: vbuf.h
|
attr_print.o: vbuf.h
|
||||||
attr_print.o: msg.h
|
attr_print.o: htable.h
|
||||||
attr_print.o: attr_io.h
|
attr_print.o: attr.h
|
||||||
attr_scan.o: attr_scan.c
|
attr_scan.o: attr_scan.c
|
||||||
attr_scan.o: sys_defs.h
|
attr_scan.o: sys_defs.h
|
||||||
|
attr_scan.o: msg.h
|
||||||
|
attr_scan.o: mymalloc.h
|
||||||
attr_scan.o: vstream.h
|
attr_scan.o: vstream.h
|
||||||
attr_scan.o: vbuf.h
|
attr_scan.o: vbuf.h
|
||||||
attr_scan.o: vstring.h
|
attr_scan.o: vstring.h
|
||||||
attr_scan.o: msg.h
|
|
||||||
attr_scan.o: argv.h
|
attr_scan.o: argv.h
|
||||||
attr_scan.o: intv.h
|
attr_scan.o: intv.h
|
||||||
attr_scan.o: attr_io.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
|
||||||
basename.o: basename.c
|
basename.o: basename.c
|
||||||
basename.o: sys_defs.h
|
basename.o: sys_defs.h
|
||||||
basename.o: stringops.h
|
basename.o: stringops.h
|
||||||
|
@@ -2,38 +2,60 @@
|
|||||||
/* NAME
|
/* NAME
|
||||||
/* attr 3
|
/* attr 3
|
||||||
/* SUMMARY
|
/* SUMMARY
|
||||||
/* attribute list manager
|
/* simple attribute list manager
|
||||||
/* SYNOPSIS
|
/* SYNOPSIS
|
||||||
/* #include <htable.h>
|
|
||||||
/* #include <attr.h>
|
/* #include <attr.h>
|
||||||
/*
|
/*
|
||||||
/* void attr_enter(attr, name, value)
|
/* void attr_enter(table, flags, name, value, ..., (char *) 0)
|
||||||
/* HTABLE *attr;
|
/* HTABLE *table;
|
||||||
|
/* int flags;
|
||||||
/* const char *name;
|
/* const char *name;
|
||||||
/* const char *value;
|
/* const char *value;
|
||||||
/*
|
/*
|
||||||
/* const char *attr_find(attr, name)
|
/* int attr_find(table, flags, name, value, ..., (char *) 0)
|
||||||
/* HTABLE *attr;
|
/* HTABLE *table;
|
||||||
|
/* int flags;
|
||||||
/* const char *name;
|
/* const char *name;
|
||||||
/*
|
/* const char **vptr;
|
||||||
/* void attr_free(attr)
|
|
||||||
/* HTABLE *attr;
|
|
||||||
/* DESCRIPTION
|
/* DESCRIPTION
|
||||||
/* This module maintains open attribute lists of string-valued
|
/* This module maintains open attribute lists of string-valued
|
||||||
/* names and values. The module is built on top of the generic
|
/* names and values. The module is built on top of the generic
|
||||||
/* htable(3) hash table manager.
|
/* htable(3) hash table manager.
|
||||||
/*
|
/*
|
||||||
/* attr_enter() adds a new attribute or updates an existing one.
|
/* attr_enter() adds or updates zero or more attribute-value pairs.
|
||||||
/* Both the name and the value are copied.
|
/* Both the name and the value are copied. The argument list is
|
||||||
|
/* terminated with a null character pointer.
|
||||||
/*
|
/*
|
||||||
/* attr_find() looks up the named attribute. It returns the
|
/* attr_find() looks up zero or more named attribute values. The
|
||||||
/* corresponding value if one is found, a null pointer otherwise.
|
/* result value is the number of attributes found; the search
|
||||||
|
/* stops at the first error. The values are not copied out; it
|
||||||
|
/* is up to the caller to save copies of values where needed.
|
||||||
/*
|
/*
|
||||||
/* attr_free() destroys the named attribute list and makes its
|
/* Arguments:
|
||||||
/* memory available for reuse.
|
/* .IP table
|
||||||
/* BUGS
|
/* Pointer to hash table.
|
||||||
/* This module cannot store null pointer values. If that is a
|
/* .IP flags
|
||||||
/* problem, use the raw hash table management routines instead.
|
/* Bit-wise OR of the following:
|
||||||
|
/* .RS
|
||||||
|
/* .IP ATTR_FLAG_MISSING
|
||||||
|
/* Log a warning when attr_find() cannot find an attribute. The
|
||||||
|
/* search always terminates when a request cannot be satisfied.
|
||||||
|
/* .IP ATTR_FLAG_EXTRA
|
||||||
|
/* Log a warning and return immediately when attr_enter() finds
|
||||||
|
/* that a specified attribute already exists in the table.
|
||||||
|
/* By default, attr_enter() replaces an existing attribute value
|
||||||
|
/* by the specified one.
|
||||||
|
/* .IP ATTR_FLAG_NONE
|
||||||
|
/* For convenience, this value requests none of the above.
|
||||||
|
/* .RE
|
||||||
|
/* .IP name
|
||||||
|
/* Attribute name. Specify a null character pointer to terminate
|
||||||
|
/* the argument list.
|
||||||
|
/* .IP value
|
||||||
|
/* Attribute value. attr_enter() makes a copy.
|
||||||
|
/* .IP vptr
|
||||||
|
/* Pointer to character pointer. attr_find() makes no copy of the
|
||||||
|
/* value.
|
||||||
/* LICENSE
|
/* LICENSE
|
||||||
/* .ad
|
/* .ad
|
||||||
/* .fi
|
/* .fi
|
||||||
@@ -47,32 +69,61 @@
|
|||||||
|
|
||||||
/* System library. */
|
/* System library. */
|
||||||
|
|
||||||
#include "sys_defs.h"
|
#include <sys_defs.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
/* Utility library. */
|
/* Utility library. */
|
||||||
|
|
||||||
#include "mymalloc.h"
|
#include <msg.h>
|
||||||
#include "htable.h"
|
#include <mymalloc.h>
|
||||||
#include "attr.h"
|
#include <htable.h>
|
||||||
|
#include <attr.h>
|
||||||
|
|
||||||
/* attr_enter - add or replace attribute */
|
/* attr_enter - add or update attribute values */
|
||||||
|
|
||||||
void attr_enter(HTABLE *attr, const char *name, const char *value)
|
void attr_enter(HTABLE *table, int flags,...)
|
||||||
{
|
{
|
||||||
|
const char *myname = "attr_enter";
|
||||||
HTABLE_INFO *ht;
|
HTABLE_INFO *ht;
|
||||||
|
va_list ap;
|
||||||
|
const char *name;
|
||||||
|
const char *value;
|
||||||
|
|
||||||
if ((ht = htable_locate(attr, name)) != 0) {/* replace attribute */
|
va_start(ap, flags);
|
||||||
|
while ((name = va_arg(ap, char *)) != 0) {
|
||||||
|
value = va_arg(ap, char *);
|
||||||
|
if ((ht = htable_locate(table, name)) != 0) { /* replace */
|
||||||
|
if ((flags & ATTR_FLAG_EXTRA) != 0) {
|
||||||
|
msg_warn("%s: duplicate attribute %s in table", myname, name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
myfree(ht->value);
|
myfree(ht->value);
|
||||||
ht->value = mystrdup(value);
|
ht->value = mystrdup(value);
|
||||||
} else { /* add attribute */
|
} else { /* add attribute */
|
||||||
(void) htable_enter(attr, name, mystrdup(value));
|
(void) htable_enter(table, name, mystrdup(value));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
va_end(ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* attr_free - destroy attribute list */
|
/* attr_enter - look up attribute values */
|
||||||
|
|
||||||
void attr_free(HTABLE *attr)
|
int attr_find(HTABLE *table, int flags,...)
|
||||||
{
|
{
|
||||||
htable_free(attr, myfree);
|
const char *myname = "attr_find";
|
||||||
}
|
va_list ap;
|
||||||
|
const char *name;
|
||||||
|
const char **vptr;
|
||||||
|
int attr_count;
|
||||||
|
|
||||||
|
va_start(ap, flags);
|
||||||
|
for (attr_count = 0; (name = va_arg(ap, char *)) != 0; attr_count++) {
|
||||||
|
vptr = va_arg(ap, const char **);
|
||||||
|
if ((*vptr = htable_find(table, name)) == 0) {
|
||||||
|
if ((flags & ATTR_FLAG_MISSING) != 0)
|
||||||
|
msg_warn("%s: missing attribute %s in table", myname, name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (attr_count);
|
||||||
|
}
|
||||||
|
@@ -1,23 +1,87 @@
|
|||||||
#ifndef _ATTR_H_INCLUDED_
|
#ifndef _ATTR_PRINT_H_INCLUDED_
|
||||||
#define _ATTR_H_INCLUDED_
|
#define _ATTR_PRINT_H_INCLUDED_
|
||||||
|
|
||||||
/*++
|
/*++
|
||||||
/* NAME
|
/* NAME
|
||||||
/* attr 3h
|
/* attr 3h
|
||||||
/* SUMMARY
|
/* SUMMARY
|
||||||
/* attribute list manager
|
/* attribute list manipulations
|
||||||
/* SYNOPSIS
|
/* SYNOPSIS
|
||||||
/* #include <attr.h>
|
/* #include "attr.h"
|
||||||
/* DESCRIPTION
|
DESCRIPTION
|
||||||
/* .nf
|
.nf
|
||||||
|
|
||||||
|
/*
|
||||||
|
* System library.
|
||||||
|
*/
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Utility library.
|
||||||
|
*/
|
||||||
|
#include <vstream.h>
|
||||||
|
#include <htable.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* External interface.
|
* External interface.
|
||||||
*/
|
*/
|
||||||
extern void attr_enter(HTABLE *, const char *, const char *);
|
#define ATTR_TYPE_END 0 /* end of data */
|
||||||
extern void attr_free(HTABLE *);
|
#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_find(table, name) htable_find((table), (name))
|
#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_ALL (07)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* attr_print.c.
|
||||||
|
*/
|
||||||
|
extern int attr_print(VSTREAM *, int,...);
|
||||||
|
extern int attr_vprint(VSTREAM *, int, va_list);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* attr_scan.c.
|
||||||
|
*/
|
||||||
|
extern int attr_scan(VSTREAM *, int,...);
|
||||||
|
extern int attr_vscan(VSTREAM *, int, va_list);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* attr_table.c.
|
||||||
|
*/
|
||||||
|
typedef HTABLE ATTR_TABLE;
|
||||||
|
|
||||||
|
extern ATTR_TABLE *attr_table_create(int);
|
||||||
|
extern void attr_table_free(ATTR_TABLE *);
|
||||||
|
extern int attr_table_read(ATTR_TABLE *, int, VSTREAM *);
|
||||||
|
extern int attr_table_get(ATTR_TABLE *, int,...);
|
||||||
|
extern int attr_table_vget(ATTR_TABLE *, int, va_list);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* attr.c.
|
||||||
|
*/
|
||||||
|
extern void attr_enter(HTABLE *, int,...);
|
||||||
|
extern int attr_find(HTABLE *, int,...);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Testing.
|
||||||
|
*/
|
||||||
|
#define BASE64_DECODE(buf, str, len) vstring_strncpy((buf), (str), (len))
|
||||||
|
|
||||||
/* LICENSE
|
/* LICENSE
|
||||||
/* .ad
|
/* .ad
|
||||||
|
@@ -1,63 +0,0 @@
|
|||||||
#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 <stdarg.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Utility library.
|
|
||||||
*/
|
|
||||||
#include <vstream.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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
|
|
@@ -4,18 +4,27 @@
|
|||||||
/* SUMMARY
|
/* SUMMARY
|
||||||
/* send attributes over byte stream
|
/* send attributes over byte stream
|
||||||
/* SYNOPSIS
|
/* SYNOPSIS
|
||||||
/* #include <attr_io.h>
|
/* #include <attr.h>
|
||||||
/*
|
/*
|
||||||
/* int attr_print(fp, type, name, ...)
|
/* int attr_print(fp, flags, type, name, ...)
|
||||||
/* VSTREAM fp;
|
/* VSTREAM fp;
|
||||||
|
/* int flags;
|
||||||
/* int type;
|
/* int type;
|
||||||
/* char *name;
|
/* char *name;
|
||||||
|
/*
|
||||||
|
/* int attr_vprint(fp, flags, ap)
|
||||||
|
/* VSTREAM fp;
|
||||||
|
/* int flags;
|
||||||
|
/* va_list ap;
|
||||||
/* DESCRIPTION
|
/* DESCRIPTION
|
||||||
/* attr_print() takes zero or more (name, value) simple attributes
|
/* attr_print() takes zero or more (name, value) simple attributes
|
||||||
/* or (name, count, value) list attributes, and converts its input
|
/* or (name, count, value) list attributes, and converts its input
|
||||||
/* to a byte stream that can be recovered with attr_scan(). The stream
|
/* to a byte stream that can be recovered with attr_scan(). The stream
|
||||||
/* is not flushed.
|
/* is not flushed.
|
||||||
/*
|
/*
|
||||||
|
/* attr_vprint() provides an alternate interface that is convenient
|
||||||
|
/* for calling from within variadoc functions.
|
||||||
|
/*
|
||||||
/* Attributes are sent in the requested order as specified with the
|
/* Attributes are sent in the requested order as specified with the
|
||||||
/* attr_print() argument list. This routine satisfies the formatting
|
/* attr_print() argument list. This routine satisfies the formatting
|
||||||
/* rules as outlined in attr_scan(3).
|
/* rules as outlined in attr_scan(3).
|
||||||
@@ -23,6 +32,16 @@
|
|||||||
/* Arguments:
|
/* Arguments:
|
||||||
/* .IP fp
|
/* .IP fp
|
||||||
/* Stream to write the result to.
|
/* Stream to write the result to.
|
||||||
|
/* .IP flags
|
||||||
|
/* The bit-wise OR of zero or more of the following.
|
||||||
|
/* .RS
|
||||||
|
/* .IP ATTR_FLAG_MORE
|
||||||
|
/* After sending the requested attributes, leave the output stream in
|
||||||
|
/* a state that is usable for more attribute sending operations on
|
||||||
|
/* the same output attribute list.
|
||||||
|
/* By default, attr_print() automatically appends an attribute list
|
||||||
|
/* terminator when it has sent the last requested attribute.
|
||||||
|
/* .RE
|
||||||
/* .IP type
|
/* .IP type
|
||||||
/* The type determines the arguments that follow.
|
/* The type determines the arguments that follow.
|
||||||
/* .RS
|
/* .RS
|
||||||
@@ -38,6 +57,9 @@
|
|||||||
/* This argument is followed by an attribute name, an integer array
|
/* This argument is followed by an attribute name, an integer array
|
||||||
/* element count, and a pointer to a null-terminated array of
|
/* element count, and a pointer to a null-terminated array of
|
||||||
/* null-terminated strings.
|
/* 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.
|
||||||
/* .IP ATTR_TYPE_END
|
/* .IP ATTR_TYPE_END
|
||||||
/* This terminates the attribute list.
|
/* This terminates the attribute list.
|
||||||
/* .RE
|
/* .RE
|
||||||
@@ -66,9 +88,11 @@
|
|||||||
|
|
||||||
/* Utility library. */
|
/* Utility library. */
|
||||||
|
|
||||||
#include <vstream.h>
|
|
||||||
#include <msg.h>
|
#include <msg.h>
|
||||||
#include <attr_io.h>
|
#include <mymalloc.h>
|
||||||
|
#include <vstream.h>
|
||||||
|
#include <htable.h>
|
||||||
|
#include <attr.h>
|
||||||
|
|
||||||
/* attr_fprintf - encode attribute information on the fly */
|
/* attr_fprintf - encode attribute information on the fly */
|
||||||
|
|
||||||
@@ -83,7 +107,7 @@ static void PRINTFLIKE(2, 3) attr_fprintf(VSTREAM *fp, const char *format,...)
|
|||||||
|
|
||||||
/* attr_vprint - send attribute list to stream */
|
/* attr_vprint - send attribute list to stream */
|
||||||
|
|
||||||
int attr_vprint(VSTREAM *fp, va_list ap)
|
int attr_vprint(VSTREAM *fp, int flags, va_list ap)
|
||||||
{
|
{
|
||||||
const char *myname = "attr_print";
|
const char *myname = "attr_print";
|
||||||
int attr_type;
|
int attr_type;
|
||||||
@@ -94,53 +118,89 @@ int attr_vprint(VSTREAM *fp, va_list ap)
|
|||||||
unsigned *ip_val;
|
unsigned *ip_val;
|
||||||
int count_val;
|
int count_val;
|
||||||
int i;
|
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);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Iterate over all (type, name, value) triples, and produce output on
|
* Iterate over all (type, name, value) triples, and produce output on
|
||||||
* the fly.
|
* the fly.
|
||||||
*/
|
*/
|
||||||
while ((attr_type = va_arg(ap, int)) != ATTR_TYPE_END) {
|
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) {
|
switch (attr_type) {
|
||||||
case ATTR_TYPE_NUM:
|
case ATTR_TYPE_NUM:
|
||||||
|
attr_name = va_arg(ap, char *);
|
||||||
|
attr_fprintf(fp, "%s", attr_name);
|
||||||
int_val = va_arg(ap, int);
|
int_val = va_arg(ap, int);
|
||||||
attr_fprintf(fp, ":%u", (unsigned) int_val);
|
attr_fprintf(fp, ":%u", (unsigned) int_val);
|
||||||
|
if (msg_verbose)
|
||||||
|
msg_info("send attr name %s value %u", attr_name, int_val);
|
||||||
break;
|
break;
|
||||||
case ATTR_TYPE_STR:
|
case ATTR_TYPE_STR:
|
||||||
|
attr_name = va_arg(ap, char *);
|
||||||
|
attr_fprintf(fp, "%s", attr_name);
|
||||||
str_val = va_arg(ap, char *);
|
str_val = va_arg(ap, char *);
|
||||||
attr_fprintf(fp, ":%s", str_val);
|
attr_fprintf(fp, ":%s", str_val);
|
||||||
|
if (msg_verbose)
|
||||||
|
msg_info("send attr name %s value %s", attr_name, str_val);
|
||||||
break;
|
break;
|
||||||
case ATTR_TYPE_NUM_ARRAY:
|
case ATTR_TYPE_NUM_ARRAY:
|
||||||
|
attr_name = va_arg(ap, char *);
|
||||||
|
attr_fprintf(fp, "%s", attr_name);
|
||||||
ip_val = va_arg(ap, int *);
|
ip_val = va_arg(ap, int *);
|
||||||
count_val = va_arg(ap, int);
|
count_val = va_arg(ap, int);
|
||||||
for (i = 0; i < count_val; i++)
|
for (i = 0; i < count_val; i++)
|
||||||
attr_fprintf(fp, ":%u", (unsigned) *ip_val++);
|
attr_fprintf(fp, ":%u", (unsigned) *ip_val++);
|
||||||
|
if (msg_verbose)
|
||||||
|
msg_info("send attr name %s values %d", attr_name, count_val);
|
||||||
break;
|
break;
|
||||||
case ATTR_TYPE_STR_ARRAY:
|
case ATTR_TYPE_STR_ARRAY:
|
||||||
|
attr_name = va_arg(ap, char *);
|
||||||
|
attr_fprintf(fp, "%s", attr_name);
|
||||||
cpp_val = va_arg(ap, char **);
|
cpp_val = va_arg(ap, char **);
|
||||||
count_val = va_arg(ap, int);
|
count_val = va_arg(ap, int);
|
||||||
for (i = 0; i < count_val; i++) {
|
for (i = 0; i < count_val; i++) {
|
||||||
str_val = *cpp_val++;
|
str_val = *cpp_val++;
|
||||||
attr_fprintf(fp, ":%s", str_val);
|
attr_fprintf(fp, ":%s", str_val);
|
||||||
}
|
}
|
||||||
|
if (msg_verbose)
|
||||||
|
msg_info("send attr name %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++) {
|
||||||
|
attr_fprintf(fp, "%s:%s", ht[0]->key, ht[0]->value);
|
||||||
|
if (msg_verbose)
|
||||||
|
msg_info("send attr name %s value %s",
|
||||||
|
ht[0]->key, ht[0]->value);
|
||||||
|
if (ht[1] != 0)
|
||||||
|
VSTREAM_PUTC('\n', fp);
|
||||||
|
}
|
||||||
|
myfree((char *) ht_info_list);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
msg_panic("%s: unknown type code: %d", myname, attr_type);
|
msg_panic("%s: unknown type code: %d", myname, attr_type);
|
||||||
}
|
}
|
||||||
VSTREAM_PUTC('\n', fp);
|
VSTREAM_PUTC('\n', fp);
|
||||||
}
|
}
|
||||||
|
if ((flags & ATTR_FLAG_MORE) == 0)
|
||||||
VSTREAM_PUTC('\n', fp);
|
VSTREAM_PUTC('\n', fp);
|
||||||
return (vstream_ferror(fp));
|
return (vstream_ferror(fp));
|
||||||
}
|
}
|
||||||
|
|
||||||
int attr_print(VSTREAM *fp,...)
|
int attr_print(VSTREAM *fp, int flags,...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
va_start(ap, fp);
|
va_start(ap, flags);
|
||||||
ret = attr_vprint(fp, ap);
|
ret = attr_vprint(fp, flags, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
return (ret);
|
return (ret);
|
||||||
}
|
}
|
||||||
@@ -157,9 +217,21 @@ int main(int argc, char **argv)
|
|||||||
{
|
{
|
||||||
static int int_array[] = {0, 1, 2, 3, 4, 5, 6, 7};
|
static int int_array[] = {0, 1, 2, 3, 4, 5, 6, 7};
|
||||||
static char *str_array[] = {"a", "b", "c", "d", "e", "f", "g", "h"};
|
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_vstream_init(argv[0], VSTREAM_ERR);
|
||||||
attr_print(VSTREAM_OUT,
|
htable_enter(table, "foo-name", "foo-value");
|
||||||
|
htable_enter(table, "bar-name", "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_NUM, ATTR_NAME_NUM, 4711,
|
||||||
ATTR_TYPE_STR, ATTR_NAME_STR, "whoopee",
|
ATTR_TYPE_STR, ATTR_NAME_STR, "whoopee",
|
||||||
ATTR_TYPE_NUM_ARRAY, ATTR_NAME_NUM_ARRAY,
|
ATTR_TYPE_NUM_ARRAY, ATTR_NAME_NUM_ARRAY,
|
||||||
|
@@ -4,18 +4,26 @@
|
|||||||
/* SUMMARY
|
/* SUMMARY
|
||||||
/* recover attributes from byte stream
|
/* recover attributes from byte stream
|
||||||
/* SYNOPSIS
|
/* SYNOPSIS
|
||||||
/* #include <attr_io.h>
|
/* #include <attr.h>
|
||||||
/*
|
/*
|
||||||
/* int attr_scan(fp, flags, type, name, ...)
|
/* int attr_scan(fp, flags, type, name, ...)
|
||||||
/* VSTREAM fp;
|
/* VSTREAM fp;
|
||||||
/* int flags;
|
/* int flags;
|
||||||
/* int type;
|
/* int type;
|
||||||
/* char *name;
|
/* char *name;
|
||||||
|
/*
|
||||||
|
/* int attr_vscan(fp, flags, ap)
|
||||||
|
/* VSTREAM fp;
|
||||||
|
/* int flags;
|
||||||
|
/* va_list ap;
|
||||||
/* DESCRIPTION
|
/* DESCRIPTION
|
||||||
/* attr_scan() takes zero or more (name, value) scalar or array
|
/* attr_scan() takes zero or more (name, value) scalar or array
|
||||||
/* attribute arguments, and recovers the attribute values from the
|
/* attribute arguments, and recovers the attribute values from the
|
||||||
/* byte stream that was generated by attr_print().
|
/* byte stream that was generated by attr_print().
|
||||||
/*
|
/*
|
||||||
|
/* attr_vscan() provides an alternative interface that is convenient
|
||||||
|
/* for calling from within a variadic function.
|
||||||
|
/*
|
||||||
/* The input stream is formatted as follows, where (item)* stands
|
/* The input stream is formatted as follows, where (item)* stands
|
||||||
/* for zero or more instances of the specified item, and where
|
/* for zero or more instances of the specified item, and where
|
||||||
/* (item1 | item2) stands for choice:
|
/* (item1 | item2) stands for choice:
|
||||||
@@ -63,30 +71,49 @@
|
|||||||
/* input stream ends without the newline attribute list terminator.
|
/* input stream ends without the newline attribute list terminator.
|
||||||
/* .IP ATTR_FLAG_EXTRA
|
/* .IP ATTR_FLAG_EXTRA
|
||||||
/* Log a warning and stop attribute recovery when the input stream
|
/* Log a warning and stop attribute recovery when the input stream
|
||||||
/* contains an attribute that was not requested.
|
/* contains an attribute that was not requested. This includes multiple
|
||||||
|
/* instances of the same attribute when only one instance is requested.
|
||||||
|
/* .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
|
||||||
|
/* same input attribute list.
|
||||||
|
/* By default, attr_scan() skips forward past the attribute list
|
||||||
|
/* terminator.
|
||||||
|
/* .IP ATTR_FLAG_NONE
|
||||||
|
/* For convenience, this value requests none of the above.
|
||||||
/* .RE
|
/* .RE
|
||||||
/* .IP type
|
/* .IP type
|
||||||
/* The type determines the arguments that follow.
|
/* The type determines the arguments that follow.
|
||||||
/* .RS
|
/* .RS
|
||||||
/* .IP "ATTR_TYPE_NUM (char *, int *)"
|
/* .IP "ATTR_TYPE_NUM (char *, int *)"
|
||||||
/* This argument is followed by an attribute name and an integer pointer.
|
/* This argument is followed by an attribute name and an integer pointer.
|
||||||
/* This is used for recovering an integer attribute value.
|
/* This is used for recovering one simple integer attribute value.
|
||||||
/* .IP "ATTR_TYPE_STR (char *, VSTRING *)"
|
/* .IP "ATTR_TYPE_STR (char *, VSTRING *)"
|
||||||
/* This argument is followed by an attribute name and a VSTRING pointer.
|
/* This argument is followed by an attribute name and a VSTRING pointer.
|
||||||
/* This is used for recovering a string attribute value.
|
/* This is used for recovering one simple string attribute value.
|
||||||
/* .IP "ATTR_TYPE_NUM_ARRAY (char *, INTV *)"
|
/* .IP "ATTR_TYPE_NUM_ARRAY (char *, INTV *)"
|
||||||
/* This argument is followed by an attribute name and an INTV pointer.
|
/* This argument is followed by an attribute name and an INTV pointer.
|
||||||
/* This is used for recovering an integer array attribute value.
|
/* 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 *)"
|
/* .IP "ATTR_TYPE_NUM_ARRAY (char *, ARGV *)"
|
||||||
/* This argument is followed by an attribute name and an ARGV pointer.
|
/* This argument is followed by an attribute name and an ARGV pointer.
|
||||||
/* This is used for recovering a string array attribute value.
|
/* 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 attributes are stored into the given hash table as simple
|
||||||
|
/* string-valued attributes, under keys equal to the attribute name.
|
||||||
|
/* Values from the input stream are added to the hash table, but existing
|
||||||
|
/* hash table entries are not replaced.
|
||||||
|
/* .sp
|
||||||
|
/* N.B. This must be followed by an ATTR_TYPE_END argument.
|
||||||
/* .IP ATTR_TYPE_END
|
/* .IP ATTR_TYPE_END
|
||||||
/* This terminates the requested attribute list.
|
/* This terminates the requested attribute list.
|
||||||
/* .RE
|
/* .RE
|
||||||
/* DIAGNOSTICS
|
/* DIAGNOSTICS
|
||||||
/* The result value is the number of attributes that were successfully
|
/* The result value is the number of attributes that were successfully
|
||||||
/* recovered from the input stream (an array-valued attribute counts
|
/* recovered from the input stream (an array-valued attribute counts
|
||||||
/* as one attribute).
|
/* as one attribute; a hash table counts as the number of entries in
|
||||||
|
/* the table).
|
||||||
/*
|
/*
|
||||||
/* Panic: interface violation. All system call errors are fatal.
|
/* Panic: interface violation. All system call errors are fatal.
|
||||||
/* SEE ALSO
|
/* SEE ALSO
|
||||||
@@ -110,17 +137,16 @@
|
|||||||
|
|
||||||
/* Utility library. */
|
/* Utility library. */
|
||||||
|
|
||||||
|
#include <msg.h>
|
||||||
|
#include <mymalloc.h>
|
||||||
#include <vstream.h>
|
#include <vstream.h>
|
||||||
#include <vstring.h>
|
#include <vstring.h>
|
||||||
#include <msg.h>
|
|
||||||
#include <argv.h>
|
#include <argv.h>
|
||||||
#include <intv.h>
|
#include <intv.h>
|
||||||
#include <attr_io.h>
|
#include <attr.h>
|
||||||
|
|
||||||
/* Application specific. */
|
/* Application specific. */
|
||||||
|
|
||||||
extern int var_line_limit; /* XXX */
|
|
||||||
|
|
||||||
#define STR(x) vstring_str(x)
|
#define STR(x) vstring_str(x)
|
||||||
#define LEN(x) VSTRING_LEN(x)
|
#define LEN(x) VSTRING_LEN(x)
|
||||||
|
|
||||||
@@ -128,7 +154,8 @@ extern int var_line_limit; /* XXX */
|
|||||||
|
|
||||||
static int attr_scan_string(VSTREAM *fp, VSTRING *plain_buf, const char *context)
|
static int attr_scan_string(VSTREAM *fp, VSTRING *plain_buf, const char *context)
|
||||||
{
|
{
|
||||||
VSTRING *base64_buf = 0;
|
static VSTRING *base64_buf = 0;
|
||||||
|
extern int var_line_limit; /* XXX */
|
||||||
int limit = var_line_limit * 5 / 4;
|
int limit = var_line_limit * 5 / 4;
|
||||||
int ch;
|
int ch;
|
||||||
|
|
||||||
@@ -142,15 +169,19 @@ static int attr_scan_string(VSTREAM *fp, VSTRING *plain_buf, const char *context
|
|||||||
VSTREAM_PATH(fp), context);
|
VSTREAM_PATH(fp), context);
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
VSTRING_ADDCH(base64_buf, ch);
|
||||||
if (LEN(base64_buf) > limit) {
|
if (LEN(base64_buf) > limit) {
|
||||||
msg_warn("string length > %d characters from %s while reading %s",
|
msg_warn("string length > %d characters from %s while reading %s",
|
||||||
limit, VSTREAM_PATH(fp), context);
|
limit, VSTREAM_PATH(fp), context);
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
VSTRING_ADDCH(base64_buf, ch);
|
|
||||||
}
|
}
|
||||||
VSTRING_TERMINATE(base64_buf);
|
VSTRING_TERMINATE(base64_buf);
|
||||||
vstring_strcpy(plain_buf, STR(base64_buf));
|
if (BASE64_DECODE(plain_buf, STR(base64_buf), LEN(base64_buf)) == 0) {
|
||||||
|
msg_warn("malformed base64 data from %s: %.100s",
|
||||||
|
VSTREAM_PATH(fp), STR(base64_buf));
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
if (msg_verbose)
|
if (msg_verbose)
|
||||||
msg_info("%s: %s", context, STR(plain_buf));
|
msg_info("%s: %s", context, STR(plain_buf));
|
||||||
return (ch);
|
return (ch);
|
||||||
@@ -180,36 +211,63 @@ int attr_vscan(VSTREAM *fp, int flags, va_list ap)
|
|||||||
{
|
{
|
||||||
const char *myname = "attr_scan";
|
const char *myname = "attr_scan";
|
||||||
static VSTRING *str_buf = 0;
|
static VSTRING *str_buf = 0;
|
||||||
int wanted_type;
|
static VSTRING *name_buf = 0;
|
||||||
|
int wanted_type = -1;
|
||||||
char *wanted_name;
|
char *wanted_name;
|
||||||
int *number;
|
int *number;
|
||||||
VSTRING *string;
|
VSTRING *string;
|
||||||
INTV *number_array;
|
INTV *number_array;
|
||||||
ARGV *string_array;
|
ARGV *string_array;
|
||||||
|
HTABLE *hash_table;
|
||||||
unsigned num_val;
|
unsigned num_val;
|
||||||
int ch;
|
int ch;
|
||||||
int conversions = 0;
|
int conversions;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sanity check.
|
||||||
|
*/
|
||||||
|
if (flags & ~ATTR_FLAG_ALL)
|
||||||
|
msg_panic("%s: bad flags: 0x%x",
|
||||||
|
myname, flags);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize.
|
* Initialize.
|
||||||
*/
|
*/
|
||||||
if (str_buf == 0)
|
if (str_buf == 0) {
|
||||||
str_buf = vstring_alloc(10);
|
str_buf = vstring_alloc(10);
|
||||||
|
name_buf = vstring_alloc(10);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Iterate over all (type, name, value) triples.
|
* Iterate over all (type, name, value) triples.
|
||||||
*/
|
*/
|
||||||
for (;;) {
|
for (conversions = 0; /* void */ ; conversions++) {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Determine the next attribute name on the caller's wish list.
|
* Determine the next attribute type and attribute name on the
|
||||||
|
* caller's wish list.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
*/
|
*/
|
||||||
|
if (wanted_type != ATTR_TYPE_HASH) {
|
||||||
wanted_type = va_arg(ap, int);
|
wanted_type = va_arg(ap, int);
|
||||||
if (wanted_type == ATTR_TYPE_END) {
|
if (wanted_type == ATTR_TYPE_END) {
|
||||||
|
if ((flags & ATTR_FLAG_MORE) != 0)
|
||||||
|
return (conversions);
|
||||||
wanted_name = "attribute list terminator";
|
wanted_name = "attribute list terminator";
|
||||||
|
} else if (wanted_type == ATTR_TYPE_HASH) {
|
||||||
|
wanted_name = "any attribute name";
|
||||||
|
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",
|
||||||
|
myname);
|
||||||
} else {
|
} else {
|
||||||
wanted_name = va_arg(ap, char *);
|
wanted_name = va_arg(ap, char *);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Locate the next attribute of interest in the input stream.
|
* Locate the next attribute of interest in the input stream.
|
||||||
@@ -221,30 +279,32 @@ int attr_vscan(VSTREAM *fp, int flags, va_list ap)
|
|||||||
* early is OK if the caller is prepared to deal with missing
|
* early is OK if the caller is prepared to deal with missing
|
||||||
* inputs.
|
* inputs.
|
||||||
*/
|
*/
|
||||||
if ((ch = attr_scan_string(fp, str_buf,
|
if ((ch = attr_scan_string(fp, name_buf,
|
||||||
"attribute name")) == VSTREAM_EOF)
|
"attribute name")) == VSTREAM_EOF)
|
||||||
return (conversions);
|
return (conversions);
|
||||||
if (ch == '\n' && LEN(str_buf) == 0) {
|
if (ch == '\n' && LEN(name_buf) == 0) {
|
||||||
if (wanted_type == ATTR_TYPE_END
|
if (wanted_type == ATTR_TYPE_END
|
||||||
|| (flags & ATTR_FLAG_MISSING) == 0)
|
|| wanted_type == ATTR_TYPE_HASH)
|
||||||
return (conversions);
|
return (conversions);
|
||||||
|
if ((flags & ATTR_FLAG_MISSING) != 0)
|
||||||
msg_warn("missing attribute %s in input from %s",
|
msg_warn("missing attribute %s in input from %s",
|
||||||
wanted_name, VSTREAM_PATH(fp));
|
wanted_name, VSTREAM_PATH(fp));
|
||||||
return (conversions);
|
return (conversions);
|
||||||
}
|
}
|
||||||
if (msg_verbose)
|
if (msg_verbose)
|
||||||
msg_info("want attribute %s, found attribute: %s",
|
msg_info("want attribute %s, found attribute: %s",
|
||||||
wanted_name, STR(str_buf));
|
wanted_name, STR(name_buf));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* See if the caller asks for this attribute.
|
* See if the caller asks for this attribute.
|
||||||
*/
|
*/
|
||||||
if (wanted_type != ATTR_TYPE_END
|
if (wanted_type == ATTR_TYPE_HASH
|
||||||
&& strcmp(wanted_name, STR(str_buf)) == 0)
|
|| (wanted_type != ATTR_TYPE_END
|
||||||
|
&& strcmp(wanted_name, STR(name_buf)) == 0))
|
||||||
break;
|
break;
|
||||||
if ((flags & ATTR_FLAG_EXTRA) != 0) {
|
if ((flags & ATTR_FLAG_EXTRA) != 0) {
|
||||||
msg_warn("spurious attribute %s in input from %s",
|
msg_warn("spurious attribute %s in input from %s",
|
||||||
STR(str_buf), VSTREAM_PATH(fp));
|
STR(name_buf), VSTREAM_PATH(fp));
|
||||||
return (conversions);
|
return (conversions);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -257,32 +317,68 @@ int attr_vscan(VSTREAM *fp, int flags, va_list ap)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Do the requested conversion. If the target attribute is a
|
* Do the requested conversion. If the target attribute is a
|
||||||
* non-array type, do not allow the sender to send a multi-valued
|
* non-array type, disallow sending a multi-valued attribute, and
|
||||||
* attribute. If the target attribute is an array type, allow the
|
* disallow sending no value. If the target attribute is an array
|
||||||
* sender to send a zero-element array.
|
* type, allow the sender to send a zero-element array (i.e. no value
|
||||||
|
* at all). XXX Need to impose a bound on the number of array
|
||||||
|
* elements.
|
||||||
*/
|
*/
|
||||||
switch (wanted_type) {
|
switch (wanted_type) {
|
||||||
case ATTR_TYPE_NUM:
|
case ATTR_TYPE_NUM:
|
||||||
|
if (ch != ':') {
|
||||||
|
msg_warn("missing value for number attribute %s from %s",
|
||||||
|
STR(name_buf), VSTREAM_PATH(fp));
|
||||||
|
return (conversions);
|
||||||
|
}
|
||||||
number = va_arg(ap, int *);
|
number = va_arg(ap, int *);
|
||||||
if ((ch = attr_scan_number(fp, number, str_buf,
|
if ((ch = attr_scan_number(fp, number, str_buf,
|
||||||
"attribute value")) < 0)
|
"attribute value")) < 0)
|
||||||
return (conversions);
|
return (conversions);
|
||||||
if (ch != '\n') {
|
if (ch != '\n') {
|
||||||
msg_warn("too many values for attribute %s from %s",
|
msg_warn("too many values for number attribute %s from %s",
|
||||||
wanted_name, VSTREAM_PATH(fp));
|
STR(name_buf), VSTREAM_PATH(fp));
|
||||||
return (conversions);
|
return (conversions);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ATTR_TYPE_STR:
|
case ATTR_TYPE_STR:
|
||||||
|
if (ch != ':') {
|
||||||
|
msg_warn("missing value for string attribute %s from %s",
|
||||||
|
STR(name_buf), VSTREAM_PATH(fp));
|
||||||
|
return (conversions);
|
||||||
|
}
|
||||||
string = va_arg(ap, VSTRING *);
|
string = va_arg(ap, VSTRING *);
|
||||||
if ((ch = attr_scan_string(fp, string, "attribute value")) < 0)
|
if ((ch = attr_scan_string(fp, string, "attribute value")) < 0)
|
||||||
return (conversions);
|
return (conversions);
|
||||||
if (ch != '\n') {
|
if (ch != '\n') {
|
||||||
msg_warn("too many values for attribute %s from %s",
|
msg_warn("too many values for string attribute %s from %s",
|
||||||
wanted_name, VSTREAM_PATH(fp));
|
STR(name_buf), VSTREAM_PATH(fp));
|
||||||
return (conversions);
|
return (conversions);
|
||||||
}
|
}
|
||||||
break;
|
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);
|
||||||
|
}
|
||||||
|
if ((ch = attr_scan_string(fp, str_buf, "attribute value")) < 0)
|
||||||
|
return (conversions);
|
||||||
|
if (ch != '\n') {
|
||||||
|
msg_warn("too many values for string attribute %s from %s",
|
||||||
|
STR(name_buf), VSTREAM_PATH(fp));
|
||||||
|
return (conversions);
|
||||||
|
}
|
||||||
|
if (htable_locate(hash_table, STR(name_buf)) != 0) {
|
||||||
|
if ((flags & ATTR_FLAG_EXTRA) != 0) {
|
||||||
|
msg_warn("duplicate attribute %s in input from %s",
|
||||||
|
STR(name_buf), VSTREAM_PATH(fp));
|
||||||
|
return (conversions);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
htable_enter(hash_table, STR(name_buf),
|
||||||
|
mystrdup(STR(str_buf)));
|
||||||
|
}
|
||||||
|
break;
|
||||||
case ATTR_TYPE_NUM_ARRAY:
|
case ATTR_TYPE_NUM_ARRAY:
|
||||||
number_array = va_arg(ap, INTV *);
|
number_array = va_arg(ap, INTV *);
|
||||||
while (ch != '\n') {
|
while (ch != '\n') {
|
||||||
@@ -303,7 +399,6 @@ int attr_vscan(VSTREAM *fp, int flags, va_list ap)
|
|||||||
default:
|
default:
|
||||||
msg_panic("%s: unknown type code: %d", myname, wanted_type);
|
msg_panic("%s: unknown type code: %d", myname, wanted_type);
|
||||||
}
|
}
|
||||||
conversions++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -335,12 +430,40 @@ int main(int unused_argc, char **used_argv)
|
|||||||
INTV *intv = intv_alloc(1);
|
INTV *intv = intv_alloc(1);
|
||||||
ARGV *argv = argv_alloc(1);
|
ARGV *argv = argv_alloc(1);
|
||||||
VSTRING *str_val = vstring_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 int_val;
|
||||||
int ret;
|
int ret;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
msg_verbose = 1;
|
msg_verbose = 1;
|
||||||
msg_vstream_init(used_argv[0], VSTREAM_ERR);
|
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_HASH, table,
|
||||||
|
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");
|
||||||
|
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);
|
||||||
|
myfree((char *) ht_info_list);
|
||||||
|
} else {
|
||||||
|
vstream_printf("return: %d\n", ret);
|
||||||
|
}
|
||||||
if ((ret = attr_scan(VSTREAM_IN,
|
if ((ret = attr_scan(VSTREAM_IN,
|
||||||
ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA,
|
ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA,
|
||||||
ATTR_TYPE_NUM, ATTR_NAME_NUM, &int_val,
|
ATTR_TYPE_NUM, ATTR_NAME_NUM, &int_val,
|
||||||
@@ -358,11 +481,21 @@ int main(int unused_argc, char **used_argv)
|
|||||||
for (i = 0; i < argv->argc; i++)
|
for (i = 0; i < argv->argc; i++)
|
||||||
vstream_printf(" %s", argv->argv[i]);
|
vstream_printf(" %s", argv->argv[i]);
|
||||||
vstream_printf("\n");
|
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);
|
||||||
|
myfree((char *) ht_info_list);
|
||||||
} else {
|
} else {
|
||||||
vstream_printf("return: %d\n", ret);
|
vstream_printf("return: %d\n", ret);
|
||||||
}
|
}
|
||||||
if (vstream_fflush(VSTREAM_OUT) != 0)
|
if (vstream_fflush(VSTREAM_OUT) != 0)
|
||||||
msg_fatal("write error: %m");
|
msg_fatal("write error: %m");
|
||||||
|
|
||||||
|
intv_free(intv);
|
||||||
|
argv_free(argv);
|
||||||
|
vstring_free(str_val);
|
||||||
|
htable_free(table, myfree);
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
439
postfix/src/util/attr_table.c
Normal file
439
postfix/src/util/attr_table.c
Normal file
@@ -0,0 +1,439 @@
|
|||||||
|
/*++
|
||||||
|
/* NAME
|
||||||
|
/* attr_table 3
|
||||||
|
/* SUMMARY
|
||||||
|
/* recover attributes from byte stream
|
||||||
|
/* SYNOPSIS
|
||||||
|
/* #include <attr.h>
|
||||||
|
/*
|
||||||
|
/* ATTR_TABLE *attr_table_create(size)
|
||||||
|
/* int size;
|
||||||
|
/*
|
||||||
|
/* void attr_table_free(attr)
|
||||||
|
/* ATTR_TABLE *attr;
|
||||||
|
/*
|
||||||
|
/* int attr_table_read(attr, flags, fp)
|
||||||
|
/* ATTR_TABLE *attr;
|
||||||
|
/* int flags;
|
||||||
|
/* VSTREAM fp;
|
||||||
|
/*
|
||||||
|
/* int attr_table_get(attr, flags, type, name, ...)
|
||||||
|
/* ATTR_TABLE *attr;
|
||||||
|
/* int flags;
|
||||||
|
/* int type;
|
||||||
|
/* char *name;
|
||||||
|
/* DESCRIPTION
|
||||||
|
/* This module provides an alternative process for recovering
|
||||||
|
/* attribute lists from a byte stream. The process involves the
|
||||||
|
/* storage in an intermediate attribute table that is subsequently
|
||||||
|
/* queried. This procedure gives more control to the application,
|
||||||
|
/* at the cost of complexity and of memory resources.
|
||||||
|
/*
|
||||||
|
/* attr_table_create() creates an empty table for storage of
|
||||||
|
/* the intermediate result from attr_table_read().
|
||||||
|
/*
|
||||||
|
/* attr_table_free() destroys its argument.
|
||||||
|
/*
|
||||||
|
/* attr_table_read() reads an attribute list from a byte stream
|
||||||
|
/* and stores the intermediate result into a table that can be
|
||||||
|
/* queried with attr_table_get().
|
||||||
|
/*
|
||||||
|
/* attr_table_get() takes zero or more (name, value) scalar or array
|
||||||
|
/* attribute arguments, and recovers the attribute values from the
|
||||||
|
/* intermediate attribute table produced by attr_table_read().
|
||||||
|
/*
|
||||||
|
/* 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.
|
||||||
|
/* This flag has no effect with attr_table_read().
|
||||||
|
/* .IP ATTR_FLAG_EXTRA
|
||||||
|
/* Log a warning and stop attribute recovery when the input stream
|
||||||
|
/* contains multiple instances of an attribute.
|
||||||
|
/* This flag has no effect with attr_table_get().
|
||||||
|
/* .IP ATTR_FLAG_NONE
|
||||||
|
/* For convenience, this value requests none of the above.
|
||||||
|
/* .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 from attr_table_read() and from attr_table_get()
|
||||||
|
/* 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 <sys_defs.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/* Utility library. */
|
||||||
|
|
||||||
|
#include <msg.h>
|
||||||
|
#include <htable.h>
|
||||||
|
#include <mymalloc.h>
|
||||||
|
#include <vstring.h>
|
||||||
|
#include <vstream.h>
|
||||||
|
#include <vstring_vstream.h>
|
||||||
|
#include <argv.h>
|
||||||
|
#include <intv.h>
|
||||||
|
#include <attr.h>
|
||||||
|
|
||||||
|
/* Application-specific. */
|
||||||
|
|
||||||
|
#define STR(x) vstring_str(x)
|
||||||
|
#define LEN(x) VSTRING_LEN(x)
|
||||||
|
|
||||||
|
static VSTRING *base64_buf;
|
||||||
|
static VSTRING *plain_buf;
|
||||||
|
|
||||||
|
/* attr_table_create - create attribute table */
|
||||||
|
|
||||||
|
ATTR_TABLE *attr_table_create(int size)
|
||||||
|
{
|
||||||
|
return (htable_create(size));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* attr_table_free - destroy attribute table */
|
||||||
|
|
||||||
|
void attr_table_free(ATTR_TABLE *table)
|
||||||
|
{
|
||||||
|
htable_free(table, myfree);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* attr_table_read - read attribute stream into table */
|
||||||
|
|
||||||
|
int attr_table_read(ATTR_TABLE *table, int flags, VSTREAM *stream)
|
||||||
|
{
|
||||||
|
char *attr_value;
|
||||||
|
int attr_count;
|
||||||
|
int ch;
|
||||||
|
|
||||||
|
if (base64_buf == 0) {
|
||||||
|
base64_buf = vstring_alloc(10);
|
||||||
|
plain_buf = vstring_alloc(10);
|
||||||
|
}
|
||||||
|
for (attr_count = 0; /* void */ ; attr_count++) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Unexpected end-of-file is always an error.
|
||||||
|
*/
|
||||||
|
if ((ch = vstring_get_nonl(base64_buf, stream)) == VSTREAM_EOF) {
|
||||||
|
msg_warn("unexpected EOF while reading attributes from %s",
|
||||||
|
VSTREAM_PATH(stream));
|
||||||
|
return (attr_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A legitimate end of attribute list is OK.
|
||||||
|
*/
|
||||||
|
if (LEN(base64_buf) == 0)
|
||||||
|
return (attr_count);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Split into name and value, but keep the ':' separator so that we
|
||||||
|
* can distinguish between no value or a zero-length value; decode
|
||||||
|
* the name but keep the value in one piece, so that we can process
|
||||||
|
* array-valued attributes.
|
||||||
|
*/
|
||||||
|
if ((attr_value = strchr(STR(base64_buf), ':')) != 0)
|
||||||
|
*attr_value = 0;
|
||||||
|
if (BASE64_DECODE(plain_buf, STR(base64_buf), attr_value ?
|
||||||
|
(attr_value - STR(base64_buf)) : LEN(base64_buf)) == 0) {
|
||||||
|
msg_warn("malformed base64 data from %s: %.100s",
|
||||||
|
VSTREAM_PATH(stream), STR(base64_buf));
|
||||||
|
return (attr_count);
|
||||||
|
}
|
||||||
|
if (attr_value != 0)
|
||||||
|
*attr_value = ':';
|
||||||
|
else
|
||||||
|
attr_value = "";
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Stop if there are multiple instances of the same attribute name
|
||||||
|
* and extra attributes are to be treated as an error. We can
|
||||||
|
* remember only one instance.
|
||||||
|
*/
|
||||||
|
if (htable_locate(table, STR(plain_buf)) != 0) {
|
||||||
|
if (flags & ATTR_FLAG_EXTRA) {
|
||||||
|
msg_warn("multiple instances of attribute %s from %s",
|
||||||
|
STR(plain_buf), VSTREAM_PATH(stream));
|
||||||
|
return (attr_count);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
htable_enter(table, STR(plain_buf), mystrdup(attr_value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* attr_conv_string - convert attribute value field to string */
|
||||||
|
|
||||||
|
static int attr_conv_string(char **src, VSTRING *plain_buf,
|
||||||
|
const char *attr_name)
|
||||||
|
{
|
||||||
|
char *myname = "attr_table_get";
|
||||||
|
extern int var_line_limit;
|
||||||
|
int limit = var_line_limit * 5 / 4;
|
||||||
|
char *cp = *src;
|
||||||
|
int len = 0;
|
||||||
|
int ch;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
if ((ch = *(unsigned char *) cp) == 0)
|
||||||
|
break;
|
||||||
|
cp++;
|
||||||
|
if (ch == ':')
|
||||||
|
break;
|
||||||
|
len++;
|
||||||
|
if (len > limit) {
|
||||||
|
msg_warn("%s: string length > %d characters in attribute %s",
|
||||||
|
myname, limit, attr_name);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (BASE64_DECODE(plain_buf, *src, len) == 0) {
|
||||||
|
msg_warn("%s: malformed base64 data in attribute %s: %.*s",
|
||||||
|
myname, attr_name, len > 100 ? 100 : len, *src);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
if (msg_verbose)
|
||||||
|
msg_info("%s: name %s value %s", myname, attr_name, STR(plain_buf));
|
||||||
|
|
||||||
|
*src = cp;
|
||||||
|
return (ch);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* attr_conv_number - convert attribute value field to number */
|
||||||
|
|
||||||
|
static int attr_conv_number(char **src, unsigned *dst, VSTRING *plain_buf,
|
||||||
|
const char *attr_name)
|
||||||
|
{
|
||||||
|
char *myname = "attr_table_get";
|
||||||
|
char junk = 0;
|
||||||
|
int ch;
|
||||||
|
|
||||||
|
if ((ch = attr_conv_string(src, plain_buf, attr_name)) < 0)
|
||||||
|
return (-1);
|
||||||
|
if (sscanf(STR(plain_buf), "%u%c", dst, &junk) != 1 || junk != 0) {
|
||||||
|
msg_warn("%s: malformed numerical data in attribute %s: %.100s",
|
||||||
|
myname, attr_name, STR(plain_buf));
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
return (ch);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* attr_table_vget - recover attributes from table */
|
||||||
|
|
||||||
|
int attr_table_vget(ATTR_TABLE *attr, int flags, va_list ap)
|
||||||
|
{
|
||||||
|
char *myname = "attr_table_get";
|
||||||
|
int attr_count;
|
||||||
|
char *attr_name;
|
||||||
|
char *attr_value;
|
||||||
|
int attr_type;
|
||||||
|
int *number;
|
||||||
|
VSTRING *string;
|
||||||
|
INTV *number_array;
|
||||||
|
ARGV *string_array;
|
||||||
|
unsigned num_val;
|
||||||
|
int ch;
|
||||||
|
|
||||||
|
if (base64_buf == 0) {
|
||||||
|
base64_buf = vstring_alloc(10);
|
||||||
|
plain_buf = vstring_alloc(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Iterate over all (type, name, value) triples.
|
||||||
|
*/
|
||||||
|
for (attr_count = 0; /* void */ ; attr_count++) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Determine the next attribute name on the caller's wish list.
|
||||||
|
*/
|
||||||
|
attr_type = va_arg(ap, int);
|
||||||
|
if (attr_type == ATTR_TYPE_END)
|
||||||
|
return (attr_count);
|
||||||
|
attr_name = va_arg(ap, char *);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Look up the attribute value. Peel off, but keep, the separator
|
||||||
|
* between name and value.
|
||||||
|
*/
|
||||||
|
if ((attr_value = htable_find(attr, attr_name)) == 0) {
|
||||||
|
if (attr_type != ATTR_TYPE_END
|
||||||
|
&& (flags & ATTR_FLAG_MISSING) != 0)
|
||||||
|
msg_warn("%s: missing attribute %s", myname, attr_name);
|
||||||
|
return (attr_count);
|
||||||
|
}
|
||||||
|
if ((ch = *(unsigned char *) attr_value) != 0)
|
||||||
|
attr_value++;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Do the requested conversion. If the target attribute is a
|
||||||
|
* non-array type, disallow sending a multi-valued attribute, and
|
||||||
|
* disallow sending no value. If the target attribute is an array
|
||||||
|
* type, allow the sender to send a zero-element array (i.e. no value
|
||||||
|
* at all). XXX Need to impose a bound on the number of array
|
||||||
|
* elements.
|
||||||
|
*/
|
||||||
|
switch (attr_type) {
|
||||||
|
case ATTR_TYPE_NUM:
|
||||||
|
if (ch != ':') {
|
||||||
|
msg_warn("%s: missing value for attribute %s",
|
||||||
|
myname, attr_name);
|
||||||
|
return (attr_count);
|
||||||
|
}
|
||||||
|
number = va_arg(ap, int *);
|
||||||
|
if ((ch = attr_conv_number(&attr_value, number, plain_buf, attr_name)) < 0)
|
||||||
|
return (attr_count);
|
||||||
|
if (ch != '\0') {
|
||||||
|
msg_warn("%s: too many values for attribute %s",
|
||||||
|
myname, attr_name);
|
||||||
|
return (attr_count);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ATTR_TYPE_STR:
|
||||||
|
if (ch != ':') {
|
||||||
|
msg_warn("%s: missing value for attribute %s",
|
||||||
|
myname, attr_name);
|
||||||
|
return (attr_count);
|
||||||
|
}
|
||||||
|
string = va_arg(ap, VSTRING *);
|
||||||
|
if ((ch = attr_conv_string(&attr_value, string, attr_name)) < 0)
|
||||||
|
return (attr_count);
|
||||||
|
if (ch != '\0') {
|
||||||
|
msg_warn("%s: too many values for attribute %s",
|
||||||
|
myname, attr_name);
|
||||||
|
return (attr_count);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ATTR_TYPE_NUM_ARRAY:
|
||||||
|
number_array = va_arg(ap, INTV *);
|
||||||
|
while (ch != '\0') {
|
||||||
|
if ((ch = attr_conv_number(&attr_value, &num_val, plain_buf, attr_name)) < 0)
|
||||||
|
return (attr_count);
|
||||||
|
intv_add(number_array, 1, num_val);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ATTR_TYPE_STR_ARRAY:
|
||||||
|
string_array = va_arg(ap, ARGV *);
|
||||||
|
while (ch != '\0') {
|
||||||
|
if ((ch = attr_conv_string(&attr_value, plain_buf, attr_name)) < 0)
|
||||||
|
return (attr_count);
|
||||||
|
argv_add(string_array, STR(plain_buf), (char *) 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
msg_panic("%s: unknown type code: %d", myname, attr_type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* attr_table_get - recover attributes from table */
|
||||||
|
|
||||||
|
int attr_table_get(ATTR_TABLE *attr, int flags,...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
va_start(ap, flags);
|
||||||
|
ret = attr_table_vget(attr, flags, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef TEST
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Proof of concept test program. Mirror image of the attr_scan test
|
||||||
|
* program.
|
||||||
|
*/
|
||||||
|
#include <msg_vstream.h>
|
||||||
|
|
||||||
|
int var_line_limit = 2048;
|
||||||
|
|
||||||
|
int main(int unused_argc, char **used_argv)
|
||||||
|
{
|
||||||
|
ATTR_TABLE *attr;
|
||||||
|
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);
|
||||||
|
attr = attr_table_create(1);
|
||||||
|
if (attr_table_read(attr, ATTR_FLAG_EXTRA, VSTREAM_IN) > 0
|
||||||
|
&& (ret = attr_table_get(attr,
|
||||||
|
ATTR_FLAG_MISSING,
|
||||||
|
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");
|
||||||
|
|
||||||
|
attr_table_free(attr);
|
||||||
|
intv_free(intv);
|
||||||
|
argv_free(argv);
|
||||||
|
vstring_free(str_val);
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
Reference in New Issue
Block a user