No empty .Rs/.Re
[netbsd-mini2440.git] / external / ibm-public / postfix / dist / src / global / verify_clnt.c
blobf2f9fe800e205d7aef747a1118b9a046a6bbf386
1 /* $NetBSD$ */
3 /*++
4 /* NAME
5 /* verify_clnt 3
6 /* SUMMARY
7 /* address verification client interface
8 /* SYNOPSIS
9 /* #include <verify_clnt.h>
11 /* int verify_clnt_query(addr, status, why)
12 /* const char *addr;
13 /* int *status;
14 /* VSTRING *why;
16 /* int verify_clnt_update(addr, status, why)
17 /* const char *addr;
18 /* int status;
19 /* const char *why;
20 /* DESCRIPTION
21 /* verify_clnt_query() requests information about the given address.
22 /* The result value is one of the valid status values (see
23 /* status description below).
24 /* In all cases the \fBwhy\fR argument provides additional
25 /* information.
27 /* verify_clnt_update() requests that the status of the specified
28 /* address be updated. The result status is DEL_REQ_RCPT_STAT_OK upon
29 /* success, DEL_REQ_RCPT_STAT_DEFER upon failure.
31 /* Arguments
32 /* .IP addr
33 /* The email address in question.
34 /* .IP status
35 /* One of the following status codes:
36 /* .RS
37 /* .IP DEL_REQ_RCPT_STAT_OK
38 /* The mail system did not detect any problems.
39 /* .IP DEL_REQ_RCPT_STAT_DEFER
40 /* The status of the address is indeterminate.
41 /* .IP DEL_REQ_RCPT_STAT_BOUNCE
42 /* The address is permanently undeliverable.
43 /* .RE
44 /* .IP why
45 /* textual description of the status.
46 /* DIAGNOSTICS
47 /* These functions return VRFY_STAT_OK in case of success,
48 /* VRFY_STAT_BAD in case of a malformed request, and
49 /* VRFY_STAT_FAIL when the operation failed.
50 /* SEE ALSO
51 /* verify(8) Postfix address verification server
52 /* LICENSE
53 /* .ad
54 /* .fi
55 /* The Secure Mailer license must be distributed with this software.
56 /* AUTHOR(S)
57 /* Wietse Venema
58 /* IBM T.J. Watson Research
59 /* P.O. Box 704
60 /* Yorktown Heights, NY 10598, USA
61 /*--*/
63 /* System library. */
65 #include <sys_defs.h>
66 #include <unistd.h>
67 #include <errno.h>
69 /* Utility library. */
71 #include <msg.h>
72 #include <vstream.h>
73 #include <vstring.h>
74 #include <attr.h>
76 /* Global library. */
78 #include <mail_params.h>
79 #include <mail_proto.h>
80 #include <clnt_stream.h>
81 #include <verify_clnt.h>
83 CLNT_STREAM *vrfy_clnt;
85 /* verify_clnt_init - initialize */
87 static void verify_clnt_init(void)
89 if (vrfy_clnt != 0)
90 msg_panic("verify_clnt_init: multiple initialization");
91 vrfy_clnt = clnt_stream_create(MAIL_CLASS_PRIVATE, var_verify_service,
92 var_ipc_idle_limit, var_ipc_ttl_limit);
95 /* verify_clnt_query - request address verification status */
97 int verify_clnt_query(const char *addr, int *addr_status, VSTRING *why)
99 VSTREAM *stream;
100 int request_status;
101 int count = 0;
104 * Do client-server plumbing.
106 if (vrfy_clnt == 0)
107 verify_clnt_init();
110 * Request status for this address.
112 for (;;) {
113 stream = clnt_stream_access(vrfy_clnt);
114 errno = 0;
115 count += 1;
116 if (attr_print(stream, ATTR_FLAG_NONE,
117 ATTR_TYPE_STR, MAIL_ATTR_REQ, VRFY_REQ_QUERY,
118 ATTR_TYPE_STR, MAIL_ATTR_ADDR, addr,
119 ATTR_TYPE_END) != 0
120 || vstream_fflush(stream)
121 || attr_scan(stream, ATTR_FLAG_MISSING,
122 ATTR_TYPE_INT, MAIL_ATTR_STATUS, &request_status,
123 ATTR_TYPE_INT, MAIL_ATTR_ADDR_STATUS, addr_status,
124 ATTR_TYPE_STR, MAIL_ATTR_WHY, why,
125 ATTR_TYPE_END) != 3) {
126 if (msg_verbose || count > 1 || (errno && errno != EPIPE && errno != ENOENT))
127 msg_warn("problem talking to service %s: %m",
128 var_verify_service);
129 } else {
130 break;
132 sleep(1);
133 clnt_stream_recover(vrfy_clnt);
135 return (request_status);
138 /* verify_clnt_update - request address status update */
140 int verify_clnt_update(const char *addr, int addr_status, const char *why)
142 VSTREAM *stream;
143 int request_status;
146 * Do client-server plumbing.
148 if (vrfy_clnt == 0)
149 verify_clnt_init();
152 * Send status for this address. Supply a default status if the address
153 * verification service is unavailable.
155 for (;;) {
156 stream = clnt_stream_access(vrfy_clnt);
157 errno = 0;
158 if (attr_print(stream, ATTR_FLAG_NONE,
159 ATTR_TYPE_STR, MAIL_ATTR_REQ, VRFY_REQ_UPDATE,
160 ATTR_TYPE_STR, MAIL_ATTR_ADDR, addr,
161 ATTR_TYPE_INT, MAIL_ATTR_ADDR_STATUS, addr_status,
162 ATTR_TYPE_STR, MAIL_ATTR_WHY, why,
163 ATTR_TYPE_END) != 0
164 || attr_scan(stream, ATTR_FLAG_MISSING,
165 ATTR_TYPE_INT, MAIL_ATTR_STATUS, &request_status,
166 ATTR_TYPE_END) != 1) {
167 if (msg_verbose || (errno != EPIPE && errno != ENOENT))
168 msg_warn("problem talking to service %s: %m",
169 var_verify_service);
170 } else {
171 break;
173 sleep(1);
174 clnt_stream_recover(vrfy_clnt);
176 return (request_status);
180 * Proof-of-concept test client program.
182 #ifdef TEST
184 #include <stdlib.h>
185 #include <ctype.h>
186 #include <stdlib.h>
187 #include <unistd.h>
188 #include <signal.h>
189 #include <msg_vstream.h>
190 #include <stringops.h>
191 #include <vstring_vstream.h>
192 #include <mail_conf.h>
194 #define STR(x) vstring_str(x)
196 static NORETURN usage(char *myname)
198 msg_fatal("usage: %s [-v]", myname);
201 static void query(char *query, VSTRING *buf)
203 int status;
205 switch (verify_clnt_query(query, &status, buf)) {
206 case VRFY_STAT_OK:
207 vstream_printf("%-10s %d\n", "status", status);
208 vstream_printf("%-10s %s\n", "text", STR(buf));
209 vstream_fflush(VSTREAM_OUT);
210 break;
211 case VRFY_STAT_BAD:
212 msg_warn("bad request format");
213 break;
214 case VRFY_STAT_FAIL:
215 msg_warn("request failed");
216 break;
220 static void update(char *query)
222 char *addr;
223 char *status_text;
224 char *cp = query;
226 if ((addr = mystrtok(&cp, " \t\r\n")) == 0
227 || (status_text = mystrtok(&cp, " \t\r\n")) == 0) {
228 msg_warn("bad request format");
229 return;
231 while (*cp && ISSPACE(*cp))
232 cp++;
233 if (*cp == 0) {
234 msg_warn("bad request format");
235 return;
237 switch (verify_clnt_update(query, atoi(status_text), cp)) {
238 case VRFY_STAT_OK:
239 vstream_printf("OK\n");
240 vstream_fflush(VSTREAM_OUT);
241 break;
242 case VRFY_STAT_BAD:
243 msg_warn("bad request format");
244 break;
245 case VRFY_STAT_FAIL:
246 msg_warn("request failed");
247 break;
251 int main(int argc, char **argv)
253 VSTRING *buffer = vstring_alloc(1);
254 char *cp;
255 int ch;
256 char *command;
258 signal(SIGPIPE, SIG_IGN);
260 msg_vstream_init(argv[0], VSTREAM_ERR);
262 mail_conf_read();
263 msg_info("using config files in %s", var_config_dir);
264 if (chdir(var_queue_dir) < 0)
265 msg_fatal("chdir %s: %m", var_queue_dir);
267 while ((ch = GETOPT(argc, argv, "v")) > 0) {
268 switch (ch) {
269 case 'v':
270 msg_verbose++;
271 break;
272 default:
273 usage(argv[0]);
276 if (argc - optind > 1)
277 usage(argv[0]);
279 while (vstring_fgets_nonl(buffer, VSTREAM_IN)) {
280 cp = STR(buffer);
281 if ((command = mystrtok(&cp, " \t\r\n")) == 0)
282 continue;
283 if (strcmp(command, "query") == 0)
284 query(cp, buffer);
285 else if (strcmp(command, "update") == 0)
286 update(cp);
287 else
288 msg_warn("unrecognized command: %s", command);
290 vstring_free(buffer);
291 return (0);
294 #endif