File: deliver_pass.c

package info (click to toggle)
postfix 0.0.19991231pl11-2
  • links: PTS
  • area: main
  • in suites: potato
  • size: 5,044 kB
  • ctags: 4,401
  • sloc: ansic: 33,767; makefile: 5,099; sh: 1,790; awk: 19
file content (172 lines) | stat: -rw-r--r-- 4,531 bytes parent folder | download
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);
}