routines that can't handle file descriptors >= FD_SETSIZE.
Files: *qmgr/qmgr_transport.c, util/vstream.[hc]
+20070215
+
+ Bugfix (introduced 20070114 with Milter body edit support):
+ the cleanup server terminated with a fatal error when SMTP
+ mail exceeded the message size limit, instead of handling
+ it as a non-fatal error. Files: cleanup/cleanup_extracted.c,
+ cleanup/cleanup_final.c, cleanup/cleanup_bounce.c,
+ cleanup/cleanup_api.c.
+
Wish list:
Update message content length when adding/removing headers.
cleanup_map11.c cleanup_map1n.c cleanup_masquerade.c \
cleanup_out_recipient.c cleanup_init.c cleanup_api.c \
cleanup_addr.c cleanup_bounce.c cleanup_milter.c \
- cleanup_body_edit.c cleanup_region.c
+ cleanup_body_edit.c cleanup_region.c cleanup_final.c
OBJS = cleanup.o cleanup_out.o cleanup_envelope.o cleanup_message.o \
cleanup_extracted.o cleanup_state.o cleanup_rewrite.o \
cleanup_map11.o cleanup_map1n.o cleanup_masquerade.o \
cleanup_out_recipient.o cleanup_init.o cleanup_api.o \
cleanup_addr.o cleanup_bounce.o cleanup_milter.o \
- cleanup_body_edit.o cleanup_region.o
+ cleanup_body_edit.o cleanup_region.o cleanup_final.o
HDRS =
TESTSRC =
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
cleanup_extracted.o: ../../include/vstring.h
cleanup_extracted.o: cleanup.h
cleanup_extracted.o: cleanup_extracted.c
+cleanup_final.o: ../../include/argv.h
+cleanup_final.o: ../../include/been_here.h
+cleanup_final.o: ../../include/cleanup_user.h
+cleanup_final.o: ../../include/dict.h
+cleanup_final.o: ../../include/header_opts.h
+cleanup_final.o: ../../include/htable.h
+cleanup_final.o: ../../include/mail_conf.h
+cleanup_final.o: ../../include/mail_stream.h
+cleanup_final.o: ../../include/maps.h
+cleanup_final.o: ../../include/match_list.h
+cleanup_final.o: ../../include/match_ops.h
+cleanup_final.o: ../../include/milter.h
+cleanup_final.o: ../../include/mime_state.h
+cleanup_final.o: ../../include/msg.h
+cleanup_final.o: ../../include/mymalloc.h
+cleanup_final.o: ../../include/nvtable.h
+cleanup_final.o: ../../include/rec_type.h
+cleanup_final.o: ../../include/resolve_clnt.h
+cleanup_final.o: ../../include/string_list.h
+cleanup_final.o: ../../include/sys_defs.h
+cleanup_final.o: ../../include/tok822.h
+cleanup_final.o: ../../include/vbuf.h
+cleanup_final.o: ../../include/vstream.h
+cleanup_final.o: ../../include/vstring.h
+cleanup_final.o: cleanup.h
+cleanup_final.o: cleanup_final.c
cleanup_init.o: ../../include/argv.h
cleanup_init.o: ../../include/been_here.h
cleanup_init.o: ../../include/cleanup_user.h
*/
extern void cleanup_extracted(CLEANUP_STATE *, int, const char *, ssize_t);
+ /*
+ * cleanup_final.c
+ */
+extern void cleanup_final(CLEANUP_STATE *);
+
/*
* cleanup_rewrite.c
*/
int cleanup_flush(CLEANUP_STATE *state)
{
- const char *myname = "cleanup_flush";
int status;
char *junk;
VSTRING *trace_junk;
/*
* Update the preliminary message size and count fields with the actual
* values.
- *
- * XXX This ugly code was moved up here from a lower-level module.
*/
- if (vstream_fseek(state->dst, 0L, SEEK_SET) < 0)
- msg_fatal("%s: vstream_fseek %s: %m", myname, cleanup_path);
- cleanup_out_format(state, REC_TYPE_SIZE, REC_TYPE_SIZE_FORMAT,
- (REC_TYPE_SIZE_CAST1) (state->xtra_offset - state->data_offset),
- (REC_TYPE_SIZE_CAST2) state->data_offset,
- (REC_TYPE_SIZE_CAST3) state->rcpt_count,
- (REC_TYPE_SIZE_CAST4) state->qmgr_opts,
- (REC_TYPE_SIZE_CAST5) state->cont_length);
+ if (CLEANUP_OUT_OK(state))
+ cleanup_final(state);
/*
* If there was an error that requires us to generate a bounce message
* expand the recipient count by virtual_alias_expansion_limit (default:
* 1000) times.
*
- * After a queue file size error, purge any unwritten data (so that
+ * After a queue file write error, purge any unwritten data (so that
* vstream_fseek() won't fail while trying to flush it) and reset the
* stream error flags to avoid false alarms.
*/
- if (state->errs & CLEANUP_STAT_SIZE) {
+ if (vstream_ferror(state->dst) || vstream_fflush(state->dst)) {
(void) vstream_fpurge(state->dst, VSTREAM_PURGE_BOTH);
vstream_clearerr(state->dst);
}
/* DESCRIPTION
/* This module processes message records with information extracted
/* from message content, or with recipients that are stored after the
-/* message content. It updates recipient records, and writes extracted
-/* information records to the output.
+/* message content. It updates recipient records, writes extracted
+/* information records to the output, and writes the queue
+/* file end marker. The queue file is left in a state that
+/* is suitable for Milter inspection, but the size record still
+/* contains dummy values.
/*
/* Arguments:
/* .IP state
* Terminate the extracted segment.
*/
cleanup_out_string(state, REC_TYPE_END, "");
-
- /*
- * vstream_fseek() would flush the buffer anyway, but the code just reads
- * better if we flush first, because it makes seek error handling more
- * straightforward.
- */
- if (vstream_fflush(state->dst)) {
- if (errno == EFBIG) {
- msg_warn("%s: queue file size limit exceeded", state->queue_id);
- state->errs |= CLEANUP_STAT_SIZE;
- } else {
- msg_warn("%s: write queue file: %m", state->queue_id);
- state->errs |= CLEANUP_STAT_WRITE;
- }
- return;
- }
}
--- /dev/null
+/*++
+/* NAME
+/* cleanup_final 3
+/* SUMMARY
+/* finalize queue file
+/* SYNOPSIS
+/* #include "cleanup.h"
+/*
+/* void cleanup_final(state)
+/* CLEANUP_STATE *state;
+/* DESCRIPTION
+/* cleanup_final() performs final queue file content (not
+/* attribute) updates so that the file is ready to be closed.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+#include <errno.h>
+
+/* Utility library. */
+
+#include <msg.h>
+
+/* Global library. */
+
+#include <cleanup_user.h>
+#include <rec_type.h>
+
+/* Application-specific. */
+
+#include "cleanup.h"
+
+/* cleanup_final - final queue file content updates */
+
+void cleanup_final(CLEANUP_STATE *state)
+{
+ const char *myname = "cleanup_final";
+
+ /*
+ * vstream_fseek() would flush the buffer anyway, but the code just reads
+ * better if we flush first, because it makes seek error handling more
+ * straightforward.
+ */
+ if (vstream_fflush(state->dst)) {
+ if (errno == EFBIG) {
+ msg_warn("%s: queue file size limit exceeded", state->queue_id);
+ state->errs |= CLEANUP_STAT_SIZE;
+ } else {
+ msg_warn("%s: write queue file: %m", state->queue_id);
+ state->errs |= CLEANUP_STAT_WRITE;
+ }
+ return;
+ }
+
+ /*
+ * Update the preliminary message size and count fields with the actual
+ * values.
+ */
+ if (vstream_fseek(state->dst, 0L, SEEK_SET) < 0)
+ msg_fatal("%s: vstream_fseek %s: %m", myname, cleanup_path);
+ cleanup_out_format(state, REC_TYPE_SIZE, REC_TYPE_SIZE_FORMAT,
+ (REC_TYPE_SIZE_CAST1) (state->xtra_offset - state->data_offset),
+ (REC_TYPE_SIZE_CAST2) state->data_offset,
+ (REC_TYPE_SIZE_CAST3) state->rcpt_count,
+ (REC_TYPE_SIZE_CAST4) state->qmgr_opts,
+ (REC_TYPE_SIZE_CAST5) state->cont_length);
+}
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
-#define MAIL_RELEASE_DATE "20070214"
+#define MAIL_RELEASE_DATE "20070215"
#define MAIL_VERSION_NUMBER "2.4"
#ifdef SNAPSHOT
/*
/* vstream_ferror() returns non-zero when a previous operation on the
/* specified stream caused a non-EOF error condition, including timeout.
-/* After a non-EOF, non-timeout, error on a stream, no I/O request will
+/* After a non-EOF error on a stream, no I/O request will
/* complete until after vstream_clearerr() is called for that stream.
/*
/* vstream_ftimeout() returns non-zero when a previous operation on the
-/* specified stream caused a timeout error condition.
-/* Although further I/O requests after timeout may complete
-/* succesfully, vstream_ftimeout() will keep returning non-zero
-/* until vstream_clearerr() is called for that stream.
+/* specified stream caused a timeout error condition. See
+/* vstream_ferror() for error persistence details.
/*
/* vstream_clearerr() resets the timeout, error and end-of-file indication
/* of the specified stream, and returns no useful result.