int vverify_append(const char *queue_id, const char *orig_rcpt, const char *recipient, const char *relay, time_t entry, const char *status, int rcpt_stat, const char *fmt, va_list ap) { VSTRING *text = vstring_alloc(10); int req_stat; /* * Impedance adaptor between bounce/defer/sent and verify_clnt. */ vstring_vsprintf(text, fmt, ap); if (var_verify_neg_cache || rcpt_stat == DEL_RCPT_STAT_OK) { req_stat = verify_clnt_update(orig_rcpt, rcpt_stat, "%s", vstring_str(text)); if (req_stat == VRFY_STAT_OK && strcasecmp(recipient, orig_rcpt) != 0) req_stat = verify_clnt_update(recipient, rcpt_stat, "%s", vstring_str(text)); } else { status = "undeliverable-but-not-cached"; req_stat = VRFY_STAT_OK; } if (req_stat == VRFY_STAT_OK) { log_adhoc(queue_id, orig_rcpt, recipient, relay, entry, status, "%s", vstring_str(text)); req_stat = 0; } else { msg_warn("%s: %s service failure", queue_id, var_verify_service); req_stat = -1; } vstring_free(text); return (req_stat); }
int memcache_printf(VSTREAM *stream, const char *fmt,...) { va_list ap; int ret; va_start(ap, fmt); if (msg_verbose) { VSTRING *buf = vstring_alloc(100); va_list ap2; VA_COPY(ap2, ap); vstring_vsprintf(buf, fmt, ap2); va_end(ap2); msg_info("%s write: %s", VSTREAM_PATH(stream), STR(buf)); vstring_free(buf); } /* * Do the I/O. */ ret = memcache_vprintf(stream, fmt, ap); va_end(ap); return (ret); }
VSTRING *vstring_sprintf(VSTRING *vp, const char *format,...) { va_list ap; va_start(ap, format); vp = vstring_vsprintf(vp, format, ap); va_end(ap); return (vp); }
void msg_vprintf(int level, const char *format, va_list ap) { if (msg_vprintf_lock == 0) { msg_vprintf_lock = 1; /* On-the-fly initialization for debugging test programs only. */ if (msg_output_fn_count == 0) msg_vstream_init("unknown", VSTREAM_ERR); /* OK if terminating signal handler hijacks control before next stmt. */ vstring_vsprintf(msg_buffer, percentm(format, errno), ap); msg_text(level, vstring_str(msg_buffer)); msg_vprintf_lock = 0; } }
void smtp_chat_cmd(SMTP_SESSION *session, const char *fmt,...) { va_list ap; /* * Format the command, and update the transaction log. */ va_start(ap, fmt); vstring_vsprintf(session->buffer, fmt, ap); va_end(ap); smtp_chat_append(session, "Out: ", STR(session->buffer)); /* * Optionally log the command first, so we can see in the log what the * program is trying to do. */ if (msg_verbose) msg_info("> %s: %s", session->namaddrport, STR(session->buffer)); /* * Send the command to the SMTP server. */ smtp_fputs(STR(session->buffer), LEN(session->buffer), session->stream); /* * Force flushing of output does not belong here. It is done in the * smtp_loop() main protocol loop when reading the server response, and * in smtp_helo() when reading the EHLO response after sending the EHLO * command. * * If we do forced flush here, then we must longjmp() on error, and a * matching "prepare for disaster" error handler must be set up before * every smtp_chat_cmd() call. */ #if 0 /* * Flush unsent data to avoid timeouts after slow DNS lookups. */ if (time((time_t *) 0) - vstream_ftime(session->stream) > 10) vstream_fflush(session->stream); /* * Abort immediately if the connection is broken. */ if (vstream_ftimeout(session->stream)) vstream_longjmp(session->stream, SMTP_ERR_TIME); if (vstream_ferror(session->stream)) vstream_longjmp(session->stream, SMTP_ERR_EOF); #endif }
void pcf_print_line(VSTREAM *fp, int mode, const char *fmt,...) { va_list ap; static VSTRING *buf = 0; char *start; char *next; int line_len = 0; int word_len; /* * One-off initialization. */ if (buf == 0) buf = vstring_alloc(100); /* * Format the text. */ va_start(ap, fmt); vstring_vsprintf(buf, fmt, ap); va_end(ap); /* * Normalize the whitespace. We don't use the line_wrap() routine because * 1) that function does not normalize whitespace between words and 2) we * want to normalize whitespace even when not wrapping lines. * * XXX Some parameters preserve whitespace: for example, smtpd_banner and * smtpd_reject_footer. If we have to preserve whitespace between words, * then perhaps readlline() can be changed to canonicalize whitespace * that follows a newline. */ for (start = STR(buf); *(start += strspn(start, PCF_SEPARATORS)) != 0; start = next) { word_len = strcspn(start, PCF_SEPARATORS); if (*(next = start + word_len) != 0) *next++ = 0; if (word_len > 0 && line_len > 0) { if ((mode & PCF_FOLD_LINE) == 0 || line_len + word_len < PCF_LINE_LIMIT) { vstream_fputs(" ", fp); line_len += 1; } else { vstream_fputs("\n" PCF_INDENT_TEXT, fp); line_len = PCF_INDENT_LEN; } } vstream_fputs(start, fp); line_len += word_len; } vstream_fputs("\n", fp); }
static NORETURN PRINTFLIKE(1, 2) fatal_with_context(char *format,...) { const char *myname = "fatal_with_context"; VSTRING *vp = vstring_alloc(100); va_list ap; if (master_path == 0) msg_panic("%s: no configuration file specified", myname); va_start(ap, format); vstring_vsprintf(vp, format, ap); va_end(ap); msg_fatal("%s: %s", master_conf_context(), vstring_str(vp)); }
static NORETURN PRINTFLIKE(1, 2) pcf_fix_fatal(const char *fmt,...) { VSTRING *buf = vstring_alloc(100); va_list ap; /* * Replace newline with whitespace. */ va_start(ap, fmt); vstring_vsprintf(buf, fmt, ap); va_end(ap); translit(STR(buf), "\n", " "); msg_fatal("%s", STR(buf)); /* NOTREACHED */ }
void vlog_adhoc(const char *id, const char *orig_rcpt, const char *recipient, const char *relay, time_t entry, const char *status, const char *fmt, va_list ap) { VSTRING *why = vstring_alloc(100); int delay = time((time_t *) 0) - entry; vstring_vsprintf(why, fmt, ap); if (orig_rcpt && *orig_rcpt && strcasecmp(recipient, orig_rcpt) != 0) msg_info("%s: to=<%s>, orig_to=<%s>, relay=%s, delay=%d, status=%s (%s)", id, recipient, orig_rcpt, relay, delay, status, vstring_str(why)); else msg_info("%s: to=<%s>, relay=%s, delay=%d, status=%s (%s)", id, recipient, relay, delay, status, vstring_str(why)); vstring_free(why); }
static void smtpd_proxy_cmd_warn(SMTPD_STATE *state, const char *fmt, va_list ap) { SMTPD_PROXY *proxy = state->proxy; VSTRING *buf; /* * The command can be omitted at the start of an SMTP session. A null * format string is not documented as part of the official interface * because it is used only internally to this module. */ buf = vstring_alloc(100); vstring_vsprintf(buf, fmt == SMTPD_PROXY_CONN_FMT ? "connection request" : fmt, ap); msg_warn("proxy %s rejected \"%s\": \"%s\"", proxy->service_name, STR(buf), STR(proxy->buffer)); vstring_free(buf); }
static int match_error(MATCH_LIST *list, const char *fmt,...) { VSTRING *buf = vstring_alloc(100); va_list ap; /* * Report, and maybe return. */ va_start(ap, fmt); vstring_vsprintf(buf, fmt, ap); va_end(ap); if (list->flags & MATCH_FLAG_RETURN) { msg_warn("%s", vstring_str(buf)); } else { msg_fatal("%s", vstring_str(buf)); } vstring_free(buf); return (0); }
void pop3d_chat_reply(POP3D_STATE *state, char *format,...) { va_list ap; int delay = 0; va_start(ap, format); vstring_vsprintf(state->buffer, format, ap); va_end(ap); if (var_soft_bounce && STR(state->buffer)[0] == '5') STR(state->buffer)[0] = '4'; pop3_chat_append(state, "Out: "); if (msg_verbose) msg_info("> %s[%s]: %s", state->name, state->addr, STR(state->buffer)); /* * Slow down clients that make errors. Sleep-on-anything slows down * clients that make an excessive number of errors within a session. */ if (state->error_count >= var_pop3d_soft_erlim) sleep(delay = var_pop3d_err_sleep); pop3_fputs(STR(state->buffer), LEN(state->buffer), state->client); /* * Flush unsent output if no I/O happened for a while. This avoids * timeouts with pipelined POP3 sessions that have lots of server-side * delays (tarpit delays or DNS lookups for UCE restrictions). */ if (delay || time((time_t *) 0) - vstream_ftime(state->client) > 10) vstream_fflush(state->client); /* * Abort immediately if the connection is broken. */ if (vstream_ftimeout(state->client)) vstream_longjmp(state->client, POP3_ERR_TIME); if (vstream_ferror(state->client)) vstream_longjmp(state->client, POP3_ERR_EOF); }
static void command(VSTREAM *stream, char *fmt,...) { VSTRING *buf; va_list ap; /* * Optionally, log the command before actually sending, so we can see * what the program is trying to do. */ if (msg_verbose) { buf = vstring_alloc(100); va_start(ap, fmt); vstring_vsprintf(buf, fmt, ap); va_end(ap); msg_info("%s", vstring_str(buf)); vstring_free(buf); } va_start(ap, fmt); smtp_vprintf(stream, fmt, ap); va_end(ap); smtp_flush(stream); }
int been_here_check(BH_TABLE *dup_filter, const char *fmt,...) { VSTRING *buf = vstring_alloc(100); int status; va_list ap; /* * Construct the string to be checked. */ va_start(ap, fmt); vstring_vsprintf(buf, fmt, ap); va_end(ap); /* * Do the duplicate check. */ status = been_here_check_fixed(dup_filter, vstring_str(buf)); /* * Cleanup. */ vstring_free(buf); return (status); }
static int smtpd_proxy_cmd(SMTPD_STATE *state, int expect, const char *fmt,...) { SMTPD_PROXY *proxy = state->proxy; va_list ap; char *cp; int last_char; int err = 0; static VSTRING *buffer = 0; /* * Errors first. Be prepared for delayed errors from the DATA phase. */ if (vstream_ferror(proxy->service_stream) || vstream_feof(proxy->service_stream) || (err = vstream_setjmp(proxy->service_stream)) != 0) { return (smtpd_proxy_rdwr_error(state, err)); } /* * The command can be omitted at the start of an SMTP session. This is * not documented as part of the official interface because it is used * only internally to this module. */ if (fmt != SMTPD_PROXY_CONN_FMT) { /* * Format the command. */ va_start(ap, fmt); vstring_vsprintf(proxy->request, fmt, ap); va_end(ap); /* * Optionally log the command first, so that we can see in the log * what the program is trying to do. */ if (msg_verbose) msg_info("> %s: %s", proxy->service_name, STR(proxy->request)); /* * Send the command to the proxy server. Since we're going to read a * reply immediately, there is no need to flush buffers. */ smtp_fputs(STR(proxy->request), LEN(proxy->request), proxy->service_stream); } /* * Early return if we don't want to wait for a server reply (such as * after sending QUIT). */ if (expect == SMTPD_PROX_WANT_NONE) return (0); /* * Censor out non-printable characters in server responses and save * complete multi-line responses if possible. * * We can't parse or store input that exceeds var_line_limit, so we just * skip over it to simplify the remainder of the code below. */ VSTRING_RESET(proxy->reply); if (buffer == 0) buffer = vstring_alloc(10); for (;;) { last_char = smtp_get(buffer, proxy->service_stream, var_line_limit, SMTP_GET_FLAG_SKIP); printable(STR(buffer), '?'); if (last_char != '\n') msg_warn("%s: response longer than %d: %.30s...", proxy->service_name, var_line_limit, STR(buffer)); if (msg_verbose) msg_info("< %s: %.100s", proxy->service_name, STR(buffer)); /* * Defend against a denial of service attack by limiting the amount * of multi-line text that we are willing to store. */ if (LEN(proxy->reply) < var_line_limit) { if (VSTRING_LEN(proxy->reply)) vstring_strcat(proxy->reply, "\r\n"); vstring_strcat(proxy->reply, STR(buffer)); } /* * Parse the response into code and text. Ignore unrecognized * garbage. This means that any character except space (or end of * line) will have the same effect as the '-' line continuation * character. */ for (cp = STR(buffer); *cp && ISDIGIT(*cp); cp++) /* void */ ; if (cp - STR(buffer) == 3) { if (*cp == '-') continue; if (*cp == ' ' || *cp == 0) break; } msg_warn("received garbage from proxy %s: %.100s", proxy->service_name, STR(buffer)); } /* * Log a warning in case the proxy does not send the expected response. * Silently accept any response when the client expressed no expectation. * * Starting with Postfix 2.6 we don't pass through unexpected 2xx or 3xx * proxy replies. They are a source of support problems, so we replace * them by generic server error replies. */ if (expect != SMTPD_PROX_WANT_ANY && expect != *STR(proxy->reply)) { msg_warn("proxy %s rejected \"%s\": \"%s\"", proxy->service_name, fmt == SMTPD_PROXY_CONN_FMT ? "connection request" : STR(proxy->request), STR(proxy->reply)); if (*STR(proxy->reply) == SMTPD_PROX_WANT_OK || *STR(proxy->reply) == SMTPD_PROX_WANT_MORE) { smtpd_proxy_rdwr_error(state, 0); } return (-1); } else { return (0); } }