3
/* bounce_append_service 3
5
/* append record to bounce log, server side
7
/* #include "bounce_service.h"
9
/* int bounce_append_service(flags, queue_id, orig_rcpt, recipient,
10
/* status, action, why)
19
/* This module implements the server side of the bounce_append()
20
/* (append bounce log) request. This routine either succeeds or
21
/* it raises a fatal error.
23
/* Fatal errors: all file access errors; memory allocation errors.
26
/* bounce(3) basic bounce service client interface
30
/* The Secure Mailer license must be distributed with this software.
33
/* IBM T.J. Watson Research
35
/* Yorktown Heights, NY 10598, USA
47
#ifdef STRCASECMP_IN_STRINGS_H
51
/* Utility library. */
56
#include <stringops.h>
60
#include <mail_params.h>
61
#include <mail_queue.h>
62
#include <quote_822_local.h>
63
#include <deliver_flock.h>
64
#include <mail_proto.h>
66
/* Application-specific. */
68
#include "bounce_service.h"
70
/* bounce_append_service - append bounce log */
72
int bounce_append_service(int unused_flags, char *service, char *queue_id,
73
char *orig_rcpt, char *recipient,
74
long offset, char *status, char *action,
77
VSTRING *in_buf = vstring_alloc(100);
78
VSTRING *out_buf = vstring_alloc(100);
83
* This code is paranoid for a good reason. Once the bounce service takes
84
* responsibility, the mail system will make no further attempts to
85
* deliver this recipient. Whenever file access fails, assume that the
86
* system is under stress or that something has been mis-configured, and
87
* force a backoff by raising a fatal run-time error.
89
log = mail_queue_open(service, queue_id,
90
O_WRONLY | O_APPEND | O_CREAT, 0600);
92
msg_fatal("open file %s %s: %m", service, queue_id);
95
* Lock out other processes to avoid truncating someone else's data in
98
if (deliver_flock(vstream_fileno(log), INTERNAL_LOCK, (VSTRING *) 0) < 0)
99
msg_fatal("lock file %s %s: %m", service, queue_id);
102
* Now, go for it. Append a record. Truncate the log to the original
103
* length when the append operation fails. We use the plain stream-lf
104
* file format because we do not need anything more complicated. As a
105
* benefit, we can still recover some data when the file is a little
108
* XXX addresses in defer logfiles are in printable quoted form, while
109
* addresses in message envelope records are in raw unquoted form. This
110
* may change once we replace the present ad-hoc bounce/defer logfile
111
* format by one that is transparent for control etc. characters. See
112
* also: showq/showq.c.
114
* While migrating from old format to new format, allow backwards
115
* compatibility by writing an old-style record before the new-style
118
if ((orig_length = vstream_fseek(log, 0L, SEEK_END)) < 0)
119
msg_fatal("seek file %s %s: %m", service, queue_id);
121
vstream_fputs("\n", log);
122
if (var_oldlog_compat) {
123
vstream_fprintf(log, "<%s>: %s\n", *recipient == 0 ? "" :
124
printable(vstring_str(quote_822_local(in_buf, recipient)), '?'),
125
printable(why, '?'));
127
vstream_fprintf(log, "%s=%s\n", MAIL_ATTR_RECIP, *recipient ?
128
printable(vstring_str(quote_822_local(in_buf, recipient)), '?') :
130
if (*orig_rcpt && strcasecmp(recipient, orig_rcpt) != 0)
131
vstream_fprintf(log, "%s=%s\n", MAIL_ATTR_ORCPT,
132
printable(vstring_str(quote_822_local(in_buf, orig_rcpt)), '?'));
134
vstream_fprintf(log, "%s=%ld\n", MAIL_ATTR_OFFSET, offset);
135
vstream_fprintf(log, "%s=%s\n", MAIL_ATTR_STATUS, printable(status, '?'));
136
vstream_fprintf(log, "%s=%s\n", MAIL_ATTR_ACTION, printable(action, '?'));
137
vstream_fprintf(log, "%s=%s\n", MAIL_ATTR_WHY, printable(why, '?'));
138
vstream_fputs("\n", log);
140
if (vstream_fflush(log) != 0 || fsync(vstream_fileno(log)) < 0) {
142
if (ftruncate(vstream_fileno(log), (off_t) orig_length) < 0)
143
msg_fatal("truncate file %s %s: %m", service, queue_id);
145
msg_fatal("append file %s %s: %m", service, queue_id);
149
* Darn. If closing the log detects a problem, the only way to undo the
150
* damage is to open the log once more, and to truncate the log to the
151
* original length. But, this could happen only when the log is kept on a
152
* remote file system, and that is not recommended practice anyway.
154
if (vstream_fclose(log) != 0)
155
msg_warn("append file %s %s: %m", service, queue_id);
157
vstring_free(in_buf);
158
vstring_free(out_buf);