bounce_append_service.c [plain text]
#include <sys_defs.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <ctype.h>
#include <string.h>
#ifdef STRCASECMP_IN_STRINGS_H
#include <strings.h>
#endif
#include <msg.h>
#include <vstring.h>
#include <vstream.h>
#include <stringops.h>
#include <mail_params.h>
#include <mail_queue.h>
#include <quote_822_local.h>
#include <deliver_flock.h>
#include <mail_proto.h>
#include "bounce_service.h"
int bounce_append_service(int unused_flags, char *service, char *queue_id,
RECIPIENT *rcpt, DSN *dsn)
{
VSTRING *in_buf = vstring_alloc(100);
VSTREAM *log;
long orig_length;
log = mail_queue_open(service, queue_id,
O_WRONLY | O_APPEND | O_CREAT, 0600);
if (log == 0)
msg_fatal("open file %s %s: %m", service, queue_id);
if (deliver_flock(vstream_fileno(log), INTERNAL_LOCK, (VSTRING *) 0) < 0)
msg_fatal("lock file %s %s: %m", service, queue_id);
if ((orig_length = vstream_fseek(log, 0L, SEEK_END)) < 0)
msg_fatal("seek file %s %s: %m", service, queue_id);
#define NOT_NULL_EMPTY(s) ((s) != 0 && *(s) != 0)
#define STR(x) vstring_str(x)
vstream_fputs("\n", log);
if (var_oldlog_compat) {
vstream_fprintf(log, "<%s>: %s\n", *rcpt->address == 0 ? "" :
STR(quote_822_local(in_buf, rcpt->address)),
dsn->reason);
}
vstream_fprintf(log, "%s=%s\n", MAIL_ATTR_RECIP, *rcpt->address ?
STR(quote_822_local(in_buf, rcpt->address)) : "<>");
if (NOT_NULL_EMPTY(rcpt->orig_addr)
&& strcasecmp(rcpt->address, rcpt->orig_addr) != 0)
vstream_fprintf(log, "%s=%s\n", MAIL_ATTR_ORCPT,
STR(quote_822_local(in_buf, rcpt->orig_addr)));
if (rcpt->offset > 0)
vstream_fprintf(log, "%s=%ld\n", MAIL_ATTR_OFFSET, rcpt->offset);
if (NOT_NULL_EMPTY(rcpt->dsn_orcpt))
vstream_fprintf(log, "%s=%s\n", MAIL_ATTR_DSN_ORCPT, rcpt->dsn_orcpt);
if (rcpt->dsn_notify != 0)
vstream_fprintf(log, "%s=%d\n", MAIL_ATTR_DSN_NOTIFY, rcpt->dsn_notify);
if (NOT_NULL_EMPTY(dsn->status))
vstream_fprintf(log, "%s=%s\n", MAIL_ATTR_DSN_STATUS, dsn->status);
if (NOT_NULL_EMPTY(dsn->action))
vstream_fprintf(log, "%s=%s\n", MAIL_ATTR_DSN_ACTION, dsn->action);
if (NOT_NULL_EMPTY(dsn->dtype) && NOT_NULL_EMPTY(dsn->dtext)) {
vstream_fprintf(log, "%s=%s\n", MAIL_ATTR_DSN_DTYPE, dsn->dtype);
vstream_fprintf(log, "%s=%s\n", MAIL_ATTR_DSN_DTEXT, dsn->dtext);
}
if (NOT_NULL_EMPTY(dsn->mtype) && NOT_NULL_EMPTY(dsn->mname)) {
vstream_fprintf(log, "%s=%s\n", MAIL_ATTR_DSN_MTYPE, dsn->mtype);
vstream_fprintf(log, "%s=%s\n", MAIL_ATTR_DSN_MNAME, dsn->mname);
}
if (NOT_NULL_EMPTY(dsn->reason))
vstream_fprintf(log, "%s=%s\n", MAIL_ATTR_WHY, dsn->reason);
vstream_fputs("\n", log);
if (vstream_fflush(log) != 0 || fsync(vstream_fileno(log)) < 0) {
#ifndef NO_TRUNCATE
if (ftruncate(vstream_fileno(log), (off_t) orig_length) < 0)
msg_fatal("truncate file %s %s: %m", service, queue_id);
#endif
msg_fatal("append file %s %s: %m", service, queue_id);
}
if (vstream_fclose(log) != 0)
msg_warn("append file %s %s: %m", service, queue_id);
vstring_free(in_buf);
return (0);
}