xref: /netbsd-src/external/ibm-public/postfix/dist/src/cleanup/cleanup.c (revision 413d532bcc3f62d122e56d92e13ac64825a40baf)
1 /*	$NetBSD: cleanup.c,v 1.5 2013/09/25 19:12:35 tron Exp $	*/
2 
3 /*++
4 /* NAME
5 /*	cleanup 8
6 /* SUMMARY
7 /*	canonicalize and enqueue Postfix message
8 /* SYNOPSIS
9 /*	\fBcleanup\fR [generic Postfix daemon options]
10 /* DESCRIPTION
11 /*	The \fBcleanup\fR(8) daemon processes inbound mail, inserts it
12 /*	into the \fBincoming\fR mail queue, and informs the queue
13 /*	manager of its arrival.
14 /*
15 /*	The \fBcleanup\fR(8) daemon always performs the following transformations:
16 /* .IP \(bu
17 /*	Insert missing message headers: (\fBResent-\fR) \fBFrom:\fR,
18 /*	\fBTo:\fR, \fBMessage-Id:\fR, and \fBDate:\fR.
19 /* .IP \(bu
20 /*	Transform envelope and header addresses to the standard
21 /*	\fIuser@fully-qualified-domain\fR form that is expected by other
22 /*	Postfix programs.
23 /*	This task is delegated to the \fBtrivial-rewrite\fR(8) daemon.
24 /* .IP \(bu
25 /*	Eliminate duplicate envelope recipient addresses.
26 /* .PP
27 /*	The following address transformations are optional:
28 /* .IP \(bu
29 /*	Optionally, rewrite all envelope and header addresses according
30 /*	to the mappings specified in the \fBcanonical\fR(5) lookup tables.
31 /* .IP \(bu
32 /*	Optionally, masquerade envelope sender addresses and message
33 /*	header addresses (i.e. strip host or domain information below
34 /*	all domains listed in the \fBmasquerade_domains\fR parameter,
35 /*	except for user names listed in \fBmasquerade_exceptions\fR).
36 /*	By default, address masquerading does not affect envelope recipients.
37 /* .IP \(bu
38 /*	Optionally, expand envelope recipients according to information
39 /*	found in the \fBvirtual\fR(5) lookup tables.
40 /* .PP
41 /*	The \fBcleanup\fR(8) daemon performs sanity checks on the content of
42 /*	each message. When it finds a problem, by default it returns a
43 /*	diagnostic status to the client, and leaves it up to the client
44 /*	to deal with the problem. Alternatively, the client can request
45 /*	the \fBcleanup\fR(8) daemon to bounce the message back to the sender
46 /*	in case of trouble.
47 /* STANDARDS
48 /*	RFC 822 (ARPA Internet Text Messages)
49 /*	RFC 2045 (MIME: Format of Internet Message Bodies)
50 /*	RFC 2046 (MIME: Media Types)
51 /*	RFC 2822 (Internet Message Format)
52 /*	RFC 3463 (Enhanced Status Codes)
53 /*	RFC 3464 (Delivery status notifications)
54 /*	RFC 5322 (Internet Message Format)
55 /* DIAGNOSTICS
56 /*	Problems and transactions are logged to \fBsyslogd\fR(8).
57 /* BUGS
58 /*	Table-driven rewriting rules make it hard to express \fBif then
59 /*	else\fR and other logical relationships.
60 /* CONFIGURATION PARAMETERS
61 /* .ad
62 /* .fi
63 /*	Changes to \fBmain.cf\fR are picked up automatically, as
64 /*	\fBcleanup\fR(8)
65 /*	processes run for only a limited amount of time. Use the command
66 /*	"\fBpostfix reload\fR" to speed up a change.
67 /*
68 /*	The text below provides only a parameter summary. See
69 /*	\fBpostconf\fR(5) for more details including examples.
70 /* COMPATIBILITY CONTROLS
71 /* .ad
72 /* .fi
73 /* .IP "\fBundisclosed_recipients_header (see 'postconf -d' output)\fR"
74 /*	Message header that the Postfix \fBcleanup\fR(8) server inserts when a
75 /*	message contains no To: or Cc: message header.
76 /* .PP
77 /*	Available in Postfix version 2.1 only:
78 /* .IP "\fBenable_errors_to (no)\fR"
79 /*	Report mail delivery errors to the address specified with the
80 /*	non-standard Errors-To: message header, instead of the envelope
81 /*	sender address (this feature is removed with Postfix version 2.2, is
82 /*	turned off by default with Postfix version 2.1, and is always turned on
83 /*	with older Postfix versions).
84 /* .PP
85 /*	Available in Postfix version 2.6 and later:
86 /* .IP "\fBalways_add_missing_headers (no)\fR"
87 /*	Always add (Resent-) From:, To:, Date: or Message-ID: headers
88 /*	when not present.
89 /* .PP
90 /*	Available in Postfix version 2.9 and later:
91 /* .IP "\fBenable_long_queue_ids (no)\fR"
92 /*	Enable long, non-repeating, queue IDs (queue file names).
93 /* BUILT-IN CONTENT FILTERING CONTROLS
94 /* .ad
95 /* .fi
96 /*	Postfix built-in content filtering is meant to stop a flood of
97 /*	worms or viruses. It is not a general content filter.
98 /* .IP "\fBbody_checks (empty)\fR"
99 /*	Optional lookup tables for content inspection as specified in
100 /*	the \fBbody_checks\fR(5) manual page.
101 /* .IP "\fBheader_checks (empty)\fR"
102 /*	Optional lookup tables for content inspection of primary non-MIME
103 /*	message headers, as specified in the \fBheader_checks\fR(5) manual page.
104 /* .PP
105 /*	Available in Postfix version 2.0 and later:
106 /* .IP "\fBbody_checks_size_limit (51200)\fR"
107 /*	How much text in a message body segment (or attachment, if you
108 /*	prefer to use that term) is subjected to body_checks inspection.
109 /* .IP "\fBmime_header_checks ($header_checks)\fR"
110 /*	Optional lookup tables for content inspection of MIME related
111 /*	message headers, as described in the \fBheader_checks\fR(5) manual page.
112 /* .IP "\fBnested_header_checks ($header_checks)\fR"
113 /*	Optional lookup tables for content inspection of non-MIME message
114 /*	headers in attached messages, as described in the \fBheader_checks\fR(5)
115 /*	manual page.
116 /* .PP
117 /*	Available in Postfix version 2.3 and later:
118 /* .IP "\fBmessage_reject_characters (empty)\fR"
119 /*	The set of characters that Postfix will reject in message
120 /*	content.
121 /* .IP "\fBmessage_strip_characters (empty)\fR"
122 /*	The set of characters that Postfix will remove from message
123 /*	content.
124 /* BEFORE QUEUE MILTER CONTROLS
125 /* .ad
126 /* .fi
127 /*	As of version 2.3, Postfix supports the Sendmail version 8
128 /*	Milter (mail filter) protocol. When mail is not received via
129 /*	the smtpd(8) server, the cleanup(8) server will simulate
130 /*	SMTP events to the extent that this is possible. For details
131 /*	see the MILTER_README document.
132 /* .IP "\fBnon_smtpd_milters (empty)\fR"
133 /*	A list of Milter (mail filter) applications for new mail that
134 /*	does not arrive via the Postfix \fBsmtpd\fR(8) server.
135 /* .IP "\fBmilter_protocol (6)\fR"
136 /*	The mail filter protocol version and optional protocol extensions
137 /*	for communication with a Milter application; prior to Postfix 2.6
138 /*	the default protocol is 2.
139 /* .IP "\fBmilter_default_action (tempfail)\fR"
140 /*	The default action when a Milter (mail filter) application is
141 /*	unavailable or mis-configured.
142 /* .IP "\fBmilter_macro_daemon_name ($myhostname)\fR"
143 /*	The {daemon_name} macro value for Milter (mail filter) applications.
144 /* .IP "\fBmilter_macro_v ($mail_name $mail_version)\fR"
145 /*	The {v} macro value for Milter (mail filter) applications.
146 /* .IP "\fBmilter_connect_timeout (30s)\fR"
147 /*	The time limit for connecting to a Milter (mail filter)
148 /*	application, and for negotiating protocol options.
149 /* .IP "\fBmilter_command_timeout (30s)\fR"
150 /*	The time limit for sending an SMTP command to a Milter (mail
151 /*	filter) application, and for receiving the response.
152 /* .IP "\fBmilter_content_timeout (300s)\fR"
153 /*	The time limit for sending message content to a Milter (mail
154 /*	filter) application, and for receiving the response.
155 /* .IP "\fBmilter_connect_macros (see 'postconf -d' output)\fR"
156 /*	The macros that are sent to Milter (mail filter) applications
157 /*	after completion of an SMTP connection.
158 /* .IP "\fBmilter_helo_macros (see 'postconf -d' output)\fR"
159 /*	The macros that are sent to Milter (mail filter) applications
160 /*	after the SMTP HELO or EHLO command.
161 /* .IP "\fBmilter_mail_macros (see 'postconf -d' output)\fR"
162 /*	The macros that are sent to Milter (mail filter) applications
163 /*	after the SMTP MAIL FROM command.
164 /* .IP "\fBmilter_rcpt_macros (see 'postconf -d' output)\fR"
165 /*	The macros that are sent to Milter (mail filter) applications
166 /*	after the SMTP RCPT TO command.
167 /* .IP "\fBmilter_data_macros (see 'postconf -d' output)\fR"
168 /*	The macros that are sent to version 4 or higher Milter (mail
169 /*	filter) applications after the SMTP DATA command.
170 /* .IP "\fBmilter_unknown_command_macros (see 'postconf -d' output)\fR"
171 /*	The macros that are sent to version 3 or higher Milter (mail
172 /*	filter) applications after an unknown SMTP command.
173 /* .IP "\fBmilter_end_of_data_macros (see 'postconf -d' output)\fR"
174 /*	The macros that are sent to Milter (mail filter) applications
175 /*	after the message end-of-data.
176 /* .PP
177 /*	Available in Postfix version 2.5 and later:
178 /* .IP "\fBmilter_end_of_header_macros (see 'postconf -d' output)\fR"
179 /*	The macros that are sent to Milter (mail filter) applications
180 /*	after the end of the message header.
181 /* .PP
182 /*	Available in Postfix version 2.7 and later:
183 /* .IP "\fBmilter_header_checks (empty)\fR"
184 /*	Optional lookup tables for content inspection of message headers
185 /*	that are produced by Milter applications.
186 /* MIME PROCESSING CONTROLS
187 /* .ad
188 /* .fi
189 /*	Available in Postfix version 2.0 and later:
190 /* .IP "\fBdisable_mime_input_processing (no)\fR"
191 /*	Turn off MIME processing while receiving mail.
192 /* .IP "\fBmime_boundary_length_limit (2048)\fR"
193 /*	The maximal length of MIME multipart boundary strings.
194 /* .IP "\fBmime_nesting_limit (100)\fR"
195 /*	The maximal recursion level that the MIME processor will handle.
196 /* .IP "\fBstrict_8bitmime (no)\fR"
197 /*	Enable both strict_7bit_headers and strict_8bitmime_body.
198 /* .IP "\fBstrict_7bit_headers (no)\fR"
199 /*	Reject mail with 8-bit text in message headers.
200 /* .IP "\fBstrict_8bitmime_body (no)\fR"
201 /*	Reject 8-bit message body text without 8-bit MIME content encoding
202 /*	information.
203 /* .IP "\fBstrict_mime_encoding_domain (no)\fR"
204 /*	Reject mail with invalid Content-Transfer-Encoding: information
205 /*	for the message/* or multipart/* MIME content types.
206 /* .PP
207 /*	Available in Postfix version 2.5 and later:
208 /* .IP "\fBdetect_8bit_encoding_header (yes)\fR"
209 /*	Automatically detect 8BITMIME body content by looking at
210 /*	Content-Transfer-Encoding: message headers; historically, this
211 /*	behavior was hard-coded to be "always on".
212 /* AUTOMATIC BCC RECIPIENT CONTROLS
213 /* .ad
214 /* .fi
215 /*	Postfix can automatically add BCC (blind carbon copy)
216 /*	when mail enters the mail system:
217 /* .IP "\fBalways_bcc (empty)\fR"
218 /*	Optional address that receives a "blind carbon copy" of each message
219 /*	that is received by the Postfix mail system.
220 /* .PP
221 /*	Available in Postfix version 2.1 and later:
222 /* .IP "\fBsender_bcc_maps (empty)\fR"
223 /*	Optional BCC (blind carbon-copy) address lookup tables, indexed
224 /*	by sender address.
225 /* .IP "\fBrecipient_bcc_maps (empty)\fR"
226 /*	Optional BCC (blind carbon-copy) address lookup tables, indexed by
227 /*	recipient address.
228 /* ADDRESS TRANSFORMATION CONTROLS
229 /* .ad
230 /* .fi
231 /*	Address rewriting is delegated to the \fBtrivial-rewrite\fR(8) daemon.
232 /*	The \fBcleanup\fR(8) server implements table driven address mapping.
233 /* .IP "\fBempty_address_recipient (MAILER-DAEMON)\fR"
234 /*	The recipient of mail addressed to the null address.
235 /* .IP "\fBcanonical_maps (empty)\fR"
236 /*	Optional address mapping lookup tables for message headers and
237 /*	envelopes.
238 /* .IP "\fBrecipient_canonical_maps (empty)\fR"
239 /*	Optional address mapping lookup tables for envelope and header
240 /*	recipient addresses.
241 /* .IP "\fBsender_canonical_maps (empty)\fR"
242 /*	Optional address mapping lookup tables for envelope and header
243 /*	sender addresses.
244 /* .IP "\fBmasquerade_classes (envelope_sender, header_sender, header_recipient)\fR"
245 /*	What addresses are subject to address masquerading.
246 /* .IP "\fBmasquerade_domains (empty)\fR"
247 /*	Optional list of domains whose subdomain structure will be stripped
248 /*	off in email addresses.
249 /* .IP "\fBmasquerade_exceptions (empty)\fR"
250 /*	Optional list of user names that are not subjected to address
251 /*	masquerading, even when their address matches $masquerade_domains.
252 /* .IP "\fBpropagate_unmatched_extensions (canonical, virtual)\fR"
253 /*	What address lookup tables copy an address extension from the lookup
254 /*	key to the lookup result.
255 /* .PP
256 /*	Available before Postfix version 2.0:
257 /* .IP "\fBvirtual_maps (empty)\fR"
258 /*	Optional lookup tables with a) names of domains for which all
259 /*	addresses are aliased to addresses in other local or remote domains,
260 /*	and b) addresses that are aliased to addresses in other local or
261 /*	remote domains.
262 /* .PP
263 /*	Available in Postfix version 2.0 and later:
264 /* .IP "\fBvirtual_alias_maps ($virtual_maps)\fR"
265 /*	Optional lookup tables that alias specific mail addresses or domains
266 /*	to other local or remote address.
267 /* .PP
268 /*	Available in Postfix version 2.2 and later:
269 /* .IP "\fBcanonical_classes (envelope_sender, envelope_recipient, header_sender, header_recipient)\fR"
270 /*	What addresses are subject to canonical_maps address mapping.
271 /* .IP "\fBrecipient_canonical_classes (envelope_recipient, header_recipient)\fR"
272 /*	What addresses are subject to recipient_canonical_maps address
273 /*	mapping.
274 /* .IP "\fBsender_canonical_classes (envelope_sender, header_sender)\fR"
275 /*	What addresses are subject to sender_canonical_maps address
276 /*	mapping.
277 /* .IP "\fBremote_header_rewrite_domain (empty)\fR"
278 /*	Don't rewrite message headers from remote clients at all when
279 /*	this parameter is empty; otherwise, rewrite message headers and
280 /*	append the specified domain name to incomplete addresses.
281 /* RESOURCE AND RATE CONTROLS
282 /* .ad
283 /* .fi
284 /* .IP "\fBduplicate_filter_limit (1000)\fR"
285 /*	The maximal number of addresses remembered by the address
286 /*	duplicate filter for \fBaliases\fR(5) or \fBvirtual\fR(5) alias expansion, or
287 /*	for \fBshowq\fR(8) queue displays.
288 /* .IP "\fBheader_size_limit (102400)\fR"
289 /*	The maximal amount of memory in bytes for storing a message header.
290 /* .IP "\fBhopcount_limit (50)\fR"
291 /*	The maximal number of Received:  message headers that is allowed
292 /*	in the primary message headers.
293 /* .IP "\fBin_flow_delay (1s)\fR"
294 /*	Time to pause before accepting a new message, when the message
295 /*	arrival rate exceeds the message delivery rate.
296 /* .IP "\fBmessage_size_limit (10240000)\fR"
297 /*	The maximal size in bytes of a message, including envelope information.
298 /* .PP
299 /*	Available in Postfix version 2.0 and later:
300 /* .IP "\fBheader_address_token_limit (10240)\fR"
301 /*	The maximal number of address tokens are allowed in an address
302 /*	message header.
303 /* .IP "\fBmime_boundary_length_limit (2048)\fR"
304 /*	The maximal length of MIME multipart boundary strings.
305 /* .IP "\fBmime_nesting_limit (100)\fR"
306 /*	The maximal recursion level that the MIME processor will handle.
307 /* .IP "\fBqueue_file_attribute_count_limit (100)\fR"
308 /*	The maximal number of (name=value) attributes that may be stored
309 /*	in a Postfix queue file.
310 /* .PP
311 /*	Available in Postfix version 2.1 and later:
312 /* .IP "\fBvirtual_alias_expansion_limit (1000)\fR"
313 /*	The maximal number of addresses that virtual alias expansion produces
314 /*	from each original recipient.
315 /* .IP "\fBvirtual_alias_recursion_limit (1000)\fR"
316 /*	The maximal nesting depth of virtual alias expansion.
317 /* MISCELLANEOUS CONTROLS
318 /* .ad
319 /* .fi
320 /* .IP "\fBconfig_directory (see 'postconf -d' output)\fR"
321 /*	The default location of the Postfix main.cf and master.cf
322 /*	configuration files.
323 /* .IP "\fBdaemon_timeout (18000s)\fR"
324 /*	How much time a Postfix daemon process may take to handle a
325 /*	request before it is terminated by a built-in watchdog timer.
326 /* .IP "\fBdelay_logging_resolution_limit (2)\fR"
327 /*	The maximal number of digits after the decimal point when logging
328 /*	sub-second delay values.
329 /* .IP "\fBdelay_warning_time (0h)\fR"
330 /*	The time after which the sender receives a copy of the message
331 /*	headers of mail that is still queued.
332 /* .IP "\fBipc_timeout (3600s)\fR"
333 /*	The time limit for sending or receiving information over an internal
334 /*	communication channel.
335 /* .IP "\fBmax_idle (100s)\fR"
336 /*	The maximum amount of time that an idle Postfix daemon process waits
337 /*	for an incoming connection before terminating voluntarily.
338 /* .IP "\fBmax_use (100)\fR"
339 /*	The maximal number of incoming connections that a Postfix daemon
340 /*	process will service before terminating voluntarily.
341 /* .IP "\fBmyhostname (see 'postconf -d' output)\fR"
342 /*	The internet hostname of this mail system.
343 /* .IP "\fBmyorigin ($myhostname)\fR"
344 /*	The domain name that locally-posted mail appears to come
345 /*	from, and that locally posted mail is delivered to.
346 /* .IP "\fBprocess_id (read-only)\fR"
347 /*	The process ID of a Postfix command or daemon process.
348 /* .IP "\fBprocess_name (read-only)\fR"
349 /*	The process name of a Postfix command or daemon process.
350 /* .IP "\fBqueue_directory (see 'postconf -d' output)\fR"
351 /*	The location of the Postfix top-level queue directory.
352 /* .IP "\fBsoft_bounce (no)\fR"
353 /*	Safety net to keep mail queued that would otherwise be returned to
354 /*	the sender.
355 /* .IP "\fBsyslog_facility (mail)\fR"
356 /*	The syslog facility of Postfix logging.
357 /* .IP "\fBsyslog_name (see 'postconf -d' output)\fR"
358 /*	The mail system name that is prepended to the process name in syslog
359 /*	records, so that "smtpd" becomes, for example, "postfix/smtpd".
360 /* .PP
361 /*	Available in Postfix version 2.1 and later:
362 /* .IP "\fBenable_original_recipient (yes)\fR"
363 /*	Enable support for the X-Original-To message header.
364 /* FILES
365 /*	/etc/postfix/canonical*, canonical mapping table
366 /*	/etc/postfix/virtual*, virtual mapping table
367 /* SEE ALSO
368 /*	trivial-rewrite(8), address rewriting
369 /*	qmgr(8), queue manager
370 /*	header_checks(5), message header content inspection
371 /*	body_checks(5), body parts content inspection
372 /*	canonical(5), canonical address lookup table format
373 /*	virtual(5), virtual alias lookup table format
374 /*	postconf(5), configuration parameters
375 /*	master(5), generic daemon options
376 /*	master(8), process manager
377 /*	syslogd(8), system logging
378 /* README FILES
379 /* .ad
380 /* .fi
381 /*	Use "\fBpostconf readme_directory\fR" or
382 /*	"\fBpostconf html_directory\fR" to locate this information.
383 /* .na
384 /* .nf
385 /*	ADDRESS_REWRITING_README Postfix address manipulation
386 /*	CONTENT_INSPECTION_README content inspection
387 /* LICENSE
388 /* .ad
389 /* .fi
390 /*	The Secure Mailer license must be distributed with this software.
391 /* AUTHOR(S)
392 /*	Wietse Venema
393 /*	IBM T.J. Watson Research
394 /*	P.O. Box 704
395 /*	Yorktown Heights, NY 10598, USA
396 /*--*/
397 
398 /* System library. */
399 
400 #include <sys_defs.h>
401 #include <signal.h>
402 #include <unistd.h>
403 #include <stdlib.h>
404 
405 /* Utility library. */
406 
407 #include <msg.h>
408 #include <vstring.h>
409 #include <dict.h>
410 
411 /* Global library. */
412 
413 #include <mail_conf.h>
414 #include <cleanup_user.h>
415 #include <mail_proto.h>
416 #include <mail_params.h>
417 #include <record.h>
418 #include <rec_type.h>
419 #include <mail_version.h>
420 
421 /* Single-threaded server skeleton. */
422 
423 #include <mail_server.h>
424 
425 /* Application-specific. */
426 
427 #include "cleanup.h"
428 
429 /* cleanup_service - process one request to inject a message into the queue */
430 
431 static void cleanup_service(VSTREAM *src, char *unused_service, char **argv)
432 {
433     VSTRING *buf = vstring_alloc(100);
434     CLEANUP_STATE *state;
435     int     flags;
436     int     type = 0;
437     int     status;
438 
439     /*
440      * Sanity check. This service takes no command-line arguments.
441      */
442     if (argv[0])
443 	msg_fatal("unexpected command-line argument: %s", argv[0]);
444 
445     /*
446      * Open a queue file and initialize state.
447      */
448     state = cleanup_open(src);
449 
450     /*
451      * Send the queue id to the client. Read client processing options. If we
452      * can't read the client processing options we can pretty much forget
453      * about the whole operation.
454      */
455     attr_print(src, ATTR_FLAG_NONE,
456 	       ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, state->queue_id,
457 	       ATTR_TYPE_END);
458     if (attr_scan(src, ATTR_FLAG_STRICT,
459 		  ATTR_TYPE_INT, MAIL_ATTR_FLAGS, &flags,
460 		  ATTR_TYPE_END) != 1) {
461 	state->errs |= CLEANUP_STAT_BAD;
462 	flags = 0;
463     }
464     cleanup_control(state, flags);
465 
466     /*
467      * XXX Rely on the front-end programs to enforce record size limits.
468      *
469      * First, copy the envelope records to the queue file. Then, copy the
470      * message content (headers and body). Finally, attach any information
471      * extracted from message headers.
472      */
473     while (CLEANUP_OUT_OK(state)) {
474 	if ((type = rec_get_raw(src, buf, 0, REC_FLAG_NONE)) < 0) {
475 	    state->errs |= CLEANUP_STAT_BAD;
476 	    break;
477 	}
478 	if (REC_GET_HIDDEN_TYPE(type)) {
479 	    msg_warn("%s: record type %d not allowed - discarding this message",
480 		     state->queue_id, type);
481 	    state->errs |= CLEANUP_STAT_BAD;
482 	    break;
483 	}
484 	CLEANUP_RECORD(state, type, vstring_str(buf), VSTRING_LEN(buf));
485 	if (type == REC_TYPE_END)
486 	    break;
487     }
488 
489     /*
490      * Keep reading in case of problems, until the sender is ready to receive
491      * our status report.
492      */
493     if (CLEANUP_OUT_OK(state) == 0 && type > 0) {
494 	while (type != REC_TYPE_END
495 	       && (type = rec_get(src, buf, 0)) > 0) {
496 	    if (type == REC_TYPE_MILT_COUNT) {
497 		int     milter_count = atoi(vstring_str(buf));
498 
499 		/* Avoid deadlock. */
500 		if (milter_count >= 0)
501 		    cleanup_milter_receive(state, milter_count);
502 	    }
503 	}
504     }
505 
506     /*
507      * Log something to make timeout errors easier to debug.
508      */
509     if (vstream_ftimeout(src))
510 	msg_warn("%s: read timeout on %s",
511 		 state->queue_id, VSTREAM_PATH(src));
512 
513     /*
514      * Finish this message, and report the result status to the client.
515      */
516     status = cleanup_flush(state);		/* in case state is modified */
517     attr_print(src, ATTR_FLAG_NONE,
518 	       ATTR_TYPE_INT, MAIL_ATTR_STATUS, status,
519 	       ATTR_TYPE_STR, MAIL_ATTR_WHY,
520 	       (state->flags & CLEANUP_FLAG_SMTP_REPLY)
521 	       && state->smtp_reply ? state->smtp_reply :
522 	       state->reason ? state->reason : "",
523 	       ATTR_TYPE_END);
524     cleanup_free(state);
525 
526     /*
527      * Cleanup.
528      */
529     vstring_free(buf);
530 }
531 
532 /* pre_accept - see if tables have changed */
533 
534 static void pre_accept(char *unused_name, char **unused_argv)
535 {
536     const char *table;
537 
538     if ((table = dict_changed_name()) != 0) {
539 	msg_info("table %s has changed -- restarting", table);
540 	exit(0);
541     }
542 }
543 
544 MAIL_VERSION_STAMP_DECLARE;
545 
546 /* main - the main program */
547 
548 int     main(int argc, char **argv)
549 {
550 
551     /*
552      * Fingerprint executables and core dumps.
553      */
554     MAIL_VERSION_STAMP_ALLOCATE;
555 
556     /*
557      * Clean up an incomplete queue file in case of a fatal run-time error,
558      * or after receiving SIGTERM from the master at shutdown time.
559      */
560     signal(SIGTERM, cleanup_sig);
561     msg_cleanup(cleanup_all);
562 
563     /*
564      * Pass control to the single-threaded service skeleton.
565      */
566     single_server_main(argc, argv, cleanup_service,
567 		       MAIL_SERVER_BOOL_TABLE, cleanup_bool_table,
568 		       MAIL_SERVER_INT_TABLE, cleanup_int_table,
569 		       MAIL_SERVER_BOOL_TABLE, cleanup_bool_table,
570 		       MAIL_SERVER_STR_TABLE, cleanup_str_table,
571 		       MAIL_SERVER_TIME_TABLE, cleanup_time_table,
572 		       MAIL_SERVER_PRE_INIT, cleanup_pre_jail,
573 		       MAIL_SERVER_POST_INIT, cleanup_post_jail,
574 		       MAIL_SERVER_PRE_ACCEPT, pre_accept,
575 		       MAIL_SERVER_IN_FLOW_DELAY,
576 		       MAIL_SERVER_UNLIMITED,
577 		       0);
578 }
579