1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
|
/*++
/* NAME
/* deliver_pass 3
/* SUMMARY
/* deliver request pass_through
/* SYNOPSIS
/* #include <deliver_request.h>
/*
/* int deliver_pass(class, service, request, address, offset)
/* const char *class;
/* const char *service;
/* DELIVER_REQUEST *request;
/* const char *address;
/* long offset;
/*
/* int deliver_pass_all(class, service, request)
/* const char *class;
/* const char *service;
/* DELIVER_REQUEST *request;
/* DESCRIPTION
/* This module implements the client side of the `queue manager
/* to delivery agent' protocol, passing one recipient on from
/* one delivery agent to another.
/*
/* deliver_pass() delegates delivery of the named recipient.
/*
/* deliver_pass_all() delegates an entire delivery request.
/*
/* Arguments:
/* .IP class
/* Destination delivery agent service class
/* .IP service
/* Destination delivery agent service name.
/* .IP request
/* Delivery request with queue file information.
/* .IP address
/* Recipient envelope address.
/* .IP offset
/* Recipient offset in queue file.
/* DIAGNOSTICS
/* LICENSE
/* .ad
/* .fi
/* The Secure Mailer license must be distributed with this software.
/* BUGS
/* One recipient at a time; this is OK for mailbox deliveries.
/*
/* Hop status information cannot be passed back.
/* AUTHOR(S)
/* Wietse Venema
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*--*/
/* System library. */
#include <sys_defs.h>
/* Utility library. */
#include <msg.h>
#include <vstring.h>
#include <vstream.h>
/* Global library. */
#include <deliver_pass.h>
/* deliver_pass_initial_reply - retrieve initial delivery process response */
static int deliver_pass_initial_reply(VSTREAM *stream)
{
int stat;
if (mail_scan(stream, "%d", &stat) != 1) {
msg_warn("%s: malformed response", VSTREAM_PATH(stream));
stat = -1;
}
return (stat);
}
/* deliver_pass_send_request - send delivery request to delivery process */
static int deliver_pass_send_request(VSTREAM *stream, DELIVER_REQUEST *request,
const char *addr, long offs)
{
int stat;
mail_print(stream, "%s %s %ld %ld %s %s %s %s %ld %ld %s %s",
request->queue_name, request->queue_id,
request->data_offset, request->data_size,
addr, request->sender,
request->errors_to, request->return_receipt,
request->arrival_time,
offs, addr, "0");
if (vstream_fflush(stream)) {
msg_warn("%s: bad write: %m", VSTREAM_PATH(stream));
stat = -1;
} else {
stat = 0;
}
return (stat);
}
/* deliver_pass_final_reply - retrieve final delivery status response */
static int deliver_pass_final_reply(VSTREAM *stream, VSTRING *reason)
{
int stat;
if (mail_scan(stream, "%s %d", reason, &stat) != 2) {
msg_warn("%s: malformed response", VSTREAM_PATH(stream));
stat = -1;
}
return (stat);
}
/* deliver_pass - deliver one per-site queue entry */
int deliver_pass(const char *class, const char *service,
DELIVER_REQUEST *request, const char *addr, long offs)
{
VSTREAM *stream;
VSTRING *reason;
int status;
/*
* Initialize.
*/
stream = mail_connect_wait(class, service);
reason = vstring_alloc(1);
/*
* Get the delivery process initial response. Send the queue file info
* and recipient info to the delivery process. Retrieve the delivery
* agent status report. The numerical status code indicates if delivery
* should be tried again. The reason text is sent only when a destination
* should be avoided for a while, so that the queue manager can log why
* it does not even try to schedule delivery to the affected recipients.
* XXX Can't pass back hop status info because the problem is with a
* different transport.
*/
if ((status = deliver_pass_initial_reply(stream)) == 0
&& (status = deliver_pass_send_request(stream, request, addr, offs)) == 0)
status = deliver_pass_final_reply(stream, reason);
/*
* Clean up.
*/
vstream_fclose(stream);
vstring_free(reason);
return (status);
}
/* deliver_pass_all - pass entire delivery request */
int deliver_pass_all(const char *class, const char *service,
DELIVER_REQUEST *request)
{
RECIPIENT_LIST *list;
RECIPIENT *rcpt;
int status = 0;
list = &request->rcpt_list;
for (rcpt = list->info; rcpt < list->info + list->len; rcpt++)
status |= deliver_pass(class, service, request,
rcpt->address, rcpt->offset);
return (status);
}
|