static void verify_clnt_init(void) { if (vrfy_clnt != 0) msg_panic("verify_clnt_init: multiple initialization"); vrfy_clnt = clnt_stream_create(MAIL_CLASS_PRIVATE, var_verify_service, var_ipc_idle_limit, var_ipc_ttl_limit); }
VSTRING *rewrite_clnt(const char *rule, const char *addr, VSTRING *result) { VSTREAM *stream; int server_flags; int count = 0; /* * One-entry cache. */ if (last_addr == 0) { last_rule = vstring_alloc(10); last_addr = vstring_alloc(100); last_result = vstring_alloc(100); } /* * Sanity check. An address must be in externalized form. The result must * not clobber the input, because we may have to retransmit the query. */ #define STR vstring_str if (*addr == 0) addr = ""; if (addr == STR(result)) msg_panic("rewrite_clnt: result clobbers input"); /* * Peek at the cache. */ if (time((time_t *) 0) < last_expire && strcmp(addr, STR(last_addr)) == 0 && strcmp(rule, STR(last_rule)) == 0) { vstring_strcpy(result, STR(last_result)); if (msg_verbose) msg_info("rewrite_clnt: cached: %s: %s -> %s", rule, addr, vstring_str(result)); return (result); } /* * Keep trying until we get a complete response. The rewrite service is * CPU bound and making the client asynchronous would just complicate the * code. */ if (rewrite_clnt_stream == 0) rewrite_clnt_stream = clnt_stream_create(MAIL_CLASS_PRIVATE, var_rewrite_service, var_ipc_idle_limit, var_ipc_ttl_limit); for (;;) { stream = clnt_stream_access(rewrite_clnt_stream); errno = 0; count += 1; 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) != 0 || vstream_fflush(stream) || attr_scan(stream, ATTR_FLAG_STRICT, ATTR_TYPE_INT, MAIL_ATTR_FLAGS, &server_flags, ATTR_TYPE_STR, MAIL_ATTR_ADDR, result, ATTR_TYPE_END) != 2) { if (msg_verbose || count > 1 || (errno && errno != EPIPE && errno != ENOENT)) msg_warn("problem talking to service %s: %m", var_rewrite_service); } else { if (msg_verbose) msg_info("rewrite_clnt: %s: %s -> %s", rule, addr, vstring_str(result)); /* Server-requested disconnect. */ if (server_flags != 0) clnt_stream_recover(rewrite_clnt_stream); break; } sleep(1); /* XXX make configurable */ clnt_stream_recover(rewrite_clnt_stream); } /* * Update the cache. */ vstring_strcpy(last_rule, rule); vstring_strcpy(last_addr, addr); vstring_strcpy(last_result, STR(result)); last_expire = time((time_t *) 0) + 30; /* XXX make configurable */ return (result); }