static void qmqpd_reply(QMQPD_STATE *state, int log_message, int status_code, const char *fmt,...) { va_list ap; /* * Optionally change hard errors into retryable ones. Send the reply and * optionally log it. Always insert a delay before reporting a problem. * This slows down software run-away conditions. */ if (status_code == QMQPD_STAT_HARD && var_soft_bounce) status_code = QMQPD_STAT_RETRY; VSTRING_RESET(state->buf); VSTRING_ADDCH(state->buf, status_code); va_start(ap, fmt); vstring_vsprintf_append(state->buf, fmt, ap); va_end(ap); NETSTRING_PUT_BUF(state->client, state->buf); if (log_message) (status_code == QMQPD_STAT_OK ? msg_info : msg_warn) ("%s: %s: %s", state->queue_id, state->namaddr, STR(state->buf) + 1); if (status_code != QMQPD_STAT_OK) sleep(var_qmqpd_err_sleep); netstring_fflush(state->client); }
VSTRING *vstring_sprintf_append(VSTRING *vp, const char *format,...) { va_list ap; va_start(ap, format); vp = vstring_vsprintf_append(vp, format, ap); va_end(ap); return (vp); }
VSTRING *vstring_sprintf_prepend(VSTRING *vp, const char *format,...) { va_list ap; ssize_t old_len = VSTRING_LEN(vp); ssize_t result_len; /* Construct: old|new|free */ va_start(ap, format); vp = vstring_vsprintf_append(vp, format, ap); va_end(ap); result_len = VSTRING_LEN(vp); /* Construct: old|new|old|free */ VSTRING_SPACE(vp, old_len); vstring_memcat(vp, vstring_str(vp), old_len); /* Construct: new|old|free */ memmove(vstring_str(vp), vstring_str(vp) + old_len, result_len); VSTRING_AT_OFFSET(vp, result_len); VSTRING_TERMINATE(vp); return (vp); }
static void vsmtp_fill_dsn(SMTP_STATE *state, const char *mta_name, const char *status, const char *reply, const char *format, va_list ap) { DSN_BUF *why = state->why; /* * We could avoid copying lots of strings into VSTRING buffers, because * this error information is given to us by a routine that terminates * AFTER the error is reported. However, this results in ugly kludges * when informal text needs to be formatted. So we maintain consistency * with other error reporting in the SMTP client even if we waste a few * cycles. */ VSTRING_RESET(why->reason); if (mta_name && status && status[0] != '4' && status[0] != '5') { vstring_strcpy(why->reason, "Protocol error: "); status = "5.5.0"; } vstring_vsprintf_append(why->reason, format, ap); dsb_formal(why, status, DSB_DEF_ACTION, mta_name ? DSB_MTYPE_DNS : DSB_MTYPE_NONE, mta_name, reply ? DSB_DTYPE_SMTP : DSB_DTYPE_NONE, reply); }