-/* $Cambridge: exim/src/src/deliver.c,v 1.16 2005/06/07 15:20:56 ph10 Exp $ */
+/* $Cambridge: exim/src/src/deliver.c,v 1.30 2006/03/01 16:07:16 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2005 */
+/* Copyright (c) University of Cambridge 1995 - 2006 */
/* See the file NOTICE for conditions of use and distribution. */
/* The main code for delivering a message. */
if (fd >= 0)
{
- fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
+ (void)fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
if (fchown(fd, exim_uid, exim_gid) < 0)
{
*error = US"chown";
log_write(0, LOG_MAIN, "<%s>: %s transport output: %s",
addr->address, tb->name, s);
}
- fclose(f);
+ (void)fclose(f);
}
}
addr->return_file = -1;
}
- close(addr->return_file);
+ (void)close(addr->return_file);
}
/* Create the address string for logging. Must not do this earlier, because
}
}
+/* If the transport did not set a group, see if the router did. */
+
+if (!gid_set && testflag(addr, af_gid_set))
+ {
+ *gidp = addr->gid;
+ gid_set = TRUE;
+ }
+
/* Pick up a uid from the transport if one is set. */
if (tp->uid_set) *uidp = tp->uid;
}
}
-/* Otherwise see if the address specifies the uid and if so, take its
-initgroups flag. The gid from the address is taken only if the transport hasn't
-set it. In other words, a gid on the transport overrides the gid on the
-address. */
+/* Otherwise see if the address specifies the uid and if so, take it and its
+initgroups flag. */
else if (testflag(addr, af_uid_set))
{
*uidp = addr->uid;
*igfp = testflag(addr, af_initgroups);
- if (!gid_set)
- {
- *gidp = addr->gid;
- gid_set = TRUE;
- }
}
/* Nothing has specified the uid - default to the Exim user, and group if the
}
}
-/* If no gid is set, it is a disaster. */
+/* If no gid is set, it is a disaster. We default to the Exim gid only if
+defaulting to the Exim uid. In other words, if the configuration has specified
+a uid, it must also provide a gid. */
if (!gid_set)
{
+/******************************************************
+* Check for a given header in a header string *
+******************************************************/
+
+/* This function is used when generating quota warnings. The configuration may
+specify any header lines it likes in quota_warn_message. If certain of them are
+missing, defaults are inserted, so we need to be able to test for the presence
+of a given header.
+
+Arguments:
+ hdr the required header name
+ hstring the header string
+
+Returns: TRUE the header is in the string
+ FALSE the header is not in the string
+*/
+
+static BOOL
+contains_header(uschar *hdr, uschar *hstring)
+{
+int len = Ustrlen(hdr);
+uschar *p = hstring;
+while (*p != 0)
+ {
+ if (strncmpic(p, hdr, len) == 0)
+ {
+ p += len;
+ while (*p == ' ' || *p == '\t') p++;
+ if (*p == ':') return TRUE;
+ }
+ while (*p != 0 && *p != '\n') p++;
+ if (*p == '\n') p++;
+ }
+return FALSE;
+}
+
+
+
/*************************************************
* Perform a local delivery *
if (addr->transport->setup != NULL)
{
- switch((addr->transport->setup)(addr->transport, addr, NULL,
+ switch((addr->transport->setup)(addr->transport, addr, NULL, uid, gid,
&(addr->message)))
{
case DEFER:
half - for transports that exec things (e.g. pipe). Then set the required
gid/uid. */
- close(pfd[pipe_read]);
- fcntl(pfd[pipe_write], F_SETFD, fcntl(pfd[pipe_write], F_GETFD) |
+ (void)close(pfd[pipe_read]);
+ (void)fcntl(pfd[pipe_write], F_SETFD, fcntl(pfd[pipe_write], F_GETFD) |
FD_CLOEXEC);
exim_setugid(uid, gid, use_initgroups,
string_sprintf("local delivery to %s <%s> transport=%s", addr->local_part,
int local_part_length = Ustrlen(addr2->local_part);
uschar *s;
- write(pfd[pipe_write], (void *)&(addr2->transport_return), sizeof(int));
- write(pfd[pipe_write], (void *)&transport_count, sizeof(transport_count));
- write(pfd[pipe_write], (void *)&(addr2->flags), sizeof(addr2->flags));
- write(pfd[pipe_write], (void *)&(addr2->basic_errno), sizeof(int));
- write(pfd[pipe_write], (void *)&(addr2->more_errno), sizeof(int));
- write(pfd[pipe_write], (void *)&(addr2->special_action), sizeof(int));
- write(pfd[pipe_write], (void *)&(addr2->transport),
+ (void)write(pfd[pipe_write], (void *)&(addr2->transport_return), sizeof(int));
+ (void)write(pfd[pipe_write], (void *)&transport_count, sizeof(transport_count));
+ (void)write(pfd[pipe_write], (void *)&(addr2->flags), sizeof(addr2->flags));
+ (void)write(pfd[pipe_write], (void *)&(addr2->basic_errno), sizeof(int));
+ (void)write(pfd[pipe_write], (void *)&(addr2->more_errno), sizeof(int));
+ (void)write(pfd[pipe_write], (void *)&(addr2->special_action), sizeof(int));
+ (void)write(pfd[pipe_write], (void *)&(addr2->transport),
sizeof(transport_instance *));
/* For a file delivery, pass back the local part, in case the original
if (testflag(addr2, af_file))
{
- write(pfd[pipe_write], (void *)&local_part_length, sizeof(int));
- write(pfd[pipe_write], addr2->local_part, local_part_length);
+ (void)write(pfd[pipe_write], (void *)&local_part_length, sizeof(int));
+ (void)write(pfd[pipe_write], addr2->local_part, local_part_length);
}
/* Now any messages */
for (i = 0, s = addr2->message; i < 2; i++, s = addr2->user_message)
{
int message_length = (s == NULL)? 0 : Ustrlen(s) + 1;
- write(pfd[pipe_write], (void *)&message_length, sizeof(int));
- if (message_length > 0) write(pfd[pipe_write], s, message_length);
+ (void)write(pfd[pipe_write], (void *)&message_length, sizeof(int));
+ if (message_length > 0) (void)write(pfd[pipe_write], s, message_length);
}
}
/* OK, this process is now done. Free any cached resources that it opened,
and close the pipe we were writing down before exiting. */
- close(pfd[pipe_write]);
+ (void)close(pfd[pipe_write]);
search_tidyup();
exit(EXIT_SUCCESS);
}
overwriting the address structure. If data is missing, the default DEFER status
will remain. Afterwards, close the reading end. */
-close(pfd[pipe_write]);
+(void)close(pfd[pipe_write]);
for (addr2 = addr; addr2 != NULL; addr2 = addr2->next)
{
}
}
-close(pfd[pipe_read]);
+(void)close(pfd[pipe_read]);
/* Unless shadowing, write all successful addresses immediately to the journal
file, to ensure they are recorded asap. For homonymic addresses, use the base
if (pid > 0)
{
FILE *f = fdopen(fd, "wb");
-
- if (errors_reply_to != NULL)
+ if (errors_reply_to != NULL &&
+ !contains_header(US"Reply-To", warn_message))
fprintf(f, "Reply-To: %s\n", errors_reply_to);
- fprintf(f, "Auto-Submitted: auto-generated\n");
- fprintf(f, "From: Mail Delivery System <Mailer-Daemon@%s>\n",
- qualify_domain_sender);
+ fprintf(f, "Auto-Submitted: auto-replied\n");
+ if (!contains_header(US"From", warn_message))
+ fprintf(f, "From: Mail Delivery System <Mailer-Daemon@%s>\n",
+ qualify_domain_sender);
fprintf(f, "%s", CS warn_message);
/* Close and wait for child process to complete, without a timeout. */
- fclose(f);
+ (void)fclose(f);
(void)child_close(pid, 0);
}
}
DEBUG(D_retry)
{
- debug_printf("retry record exists: age=%d (max=%d)\n",
- (int)(now - retry_record->time_stamp), retry_data_expire);
- debug_printf(" time to retry = %d expired = %d\n",
- (int)(now - retry_record->next_try), retry_record->expired);
+ debug_printf("retry record exists: age=%s ",
+ readconf_printtime(now - retry_record->time_stamp));
+ debug_printf("(max %s)\n", readconf_printtime(retry_data_expire));
+ debug_printf(" time to retry = %s expired = %d\n",
+ readconf_printtime(retry_record->next_try - now),
+ retry_record->expired);
}
if (queue_running && !deliver_force)
for (last_rule = retry->rules;
last_rule->next != NULL;
last_rule = last_rule->next);
+ DEBUG(D_deliver|D_retry)
+ debug_printf("now=%d received_time=%d diff=%d timeout=%d\n",
+ (int)now, received_time, (int)now - received_time,
+ last_rule->timeout);
if (now - received_time > last_rule->timeout) ok = TRUE;
}
- else ok = TRUE; /* No rule => timed out */
+ else
+ {
+ DEBUG(D_deliver|D_retry)
+ debug_printf("no retry rule found: assume timed out\n");
+ ok = TRUE; /* No rule => timed out */
+ }
DEBUG(D_deliver|D_retry)
{
/* Close our end of the pipe, to prevent deadlock if the far end is still
pushing stuff into it. */
-close(fd);
+(void)close(fd);
p->fd = -1;
/* If we have finished without error, but haven't had data for every address,
else return_path = new_return_path;
}
+ /* Find the uid, gid, and use_initgroups setting for this transport. Failure
+ logs and sets up error messages, so we just post-process and continue with
+ the next address. */
+
+ if (!findugid(addr, tp, &uid, &gid, &use_initgroups))
+ {
+ remote_post_process(addr, LOG_MAIN|LOG_PANIC, NULL, fallback);
+ continue;
+ }
+
/* If this transport has a setup function, call it now so that it gets
run in this process and not in any subprocess. That way, the results of
- any setup that are retained by the transport can be reusable. */
+ any setup that are retained by the transport can be reusable. One of the
+ things the setup does is to set the fallback host lists in the addresses.
+ That is why it is called at this point, before the continue delivery
+ processing, because that might use the fallback hosts. */
if (tp->setup != NULL)
- (void)((tp->setup)(addr->transport, addr, NULL, NULL));
+ (void)((tp->setup)(addr->transport, addr, NULL, uid, gid, NULL));
/* If this is a run to continue delivery down an already-established
channel, check that this set of addresses matches the transport and
transport_filter_argv = NULL;
- /* Find the uid, gid, and use_initgroups setting for this transport. Failure
- logs and sets up error messages, so we just post-process and continue with
- the next address. */
-
- if (!findugid(addr, tp, &uid, &gid, &use_initgroups))
- {
- remote_post_process(addr, LOG_MAIN|LOG_PANIC, NULL, fallback);
- continue;
- }
-
/* Create the pipe for inter-process communication. If pipe creation
fails, it is probably because the value of remote_max_parallel is so
large that too many file descriptors for pipes have been created. Arrange
distinguishes between EOF and no-more-data. */
#ifdef O_NONBLOCK
- fcntl(pfd[pipe_read], F_SETFL, O_NONBLOCK);
+ (void)fcntl(pfd[pipe_read], F_SETFL, O_NONBLOCK);
#else
- fcntl(pfd[pipe_read], F_SETFL, O_NDELAY);
+ (void)fcntl(pfd[pipe_read], F_SETFL, O_NDELAY);
#endif
/* If the maximum number of subprocesses already exist, wait for a process
if (poffset >= remote_max_parallel)
{
- close(pfd[pipe_write]);
- close(pfd[pipe_read]);
+ (void)close(pfd[pipe_write]);
+ (void)close(pfd[pipe_read]);
remote_post_process(addr, LOG_MAIN|LOG_PANIC,
US"Unexpectedly no free subprocess slot", fallback);
continue;
a new process that may be forked to do another delivery down the same
SMTP connection. */
- fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
+ (void)fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
/* Close open file descriptors for the pipes of other processes
that are running in parallel. */
for (poffset = 0; poffset < remote_max_parallel; poffset++)
- if (parlist[poffset].pid != 0) close(parlist[poffset].fd);
+ if (parlist[poffset].pid != 0) (void)close(parlist[poffset].fd);
/* This process has inherited a copy of the file descriptor
for the data file, but its file pointer is shared with all the
the parent process. There doesn't seem to be any way of doing
a dup-with-new-file-pointer. */
- close(deliver_datafile);
+ (void)close(deliver_datafile);
sprintf(CS spoolname, "%s/input/%s/%s-D", spool_directory, message_subdir,
message_id);
deliver_datafile = Uopen(spoolname, O_RDWR | O_APPEND, 0);
/* Set the close-on-exec flag */
- fcntl(deliver_datafile, F_SETFD, fcntl(deliver_datafile, F_GETFD) |
+ (void)fcntl(deliver_datafile, F_SETFD, fcntl(deliver_datafile, F_GETFD) |
FD_CLOEXEC);
/* Set the uid/gid of this process; bombs out on failure. */
and run the transport. Afterwards, transport_count will contain the number
of bytes written. */
- close(pfd[pipe_read]);
+ (void)close(pfd[pipe_read]);
set_process_info("delivering %s using %s", message_id, tp->name);
debug_print_string(tp->debug_string);
if (!(tp->info->code)(addr->transport, addr)) replicate_status(addr);
{
if (h->address == NULL || h->status < hstatus_unusable) continue;
sprintf(CS big_buffer, "H%c%c%s", h->status, h->why, h->address);
- write(fd, big_buffer, Ustrlen(big_buffer+3) + 4);
+ (void)write(fd, big_buffer, Ustrlen(big_buffer+3) + 4);
}
/* The number of bytes written. This is the same for each address. Even
big_buffer[0] = 'S';
memcpy(big_buffer+1, &transport_count, sizeof(transport_count));
- write(fd, big_buffer, sizeof(transport_count) + 1);
+ (void)write(fd, big_buffer, sizeof(transport_count) + 1);
/* Information about what happened to each address. Three item types are
used: an optional 'X' item first, for TLS information, followed by 'R'
sprintf(CS ptr, "%.512s", addr->peerdn);
while(*ptr++);
}
- write(fd, big_buffer, ptr - big_buffer);
+ (void)write(fd, big_buffer, ptr - big_buffer);
}
#endif
sprintf(CS ptr, "%.512s", r->message);
while(*ptr++);
}
- write(fd, big_buffer, ptr - big_buffer);
+ (void)write(fd, big_buffer, ptr - big_buffer);
}
/* The rest of the information goes in an 'A' item. */
memcpy(ptr, &(addr->host_used->port), sizeof(addr->host_used->port));
ptr += sizeof(addr->host_used->port);
}
- write(fd, big_buffer, ptr - big_buffer);
+ (void)write(fd, big_buffer, ptr - big_buffer);
}
/* Add termination flag, close the pipe, and that's it. The character
big_buffer[0] = 'Z';
big_buffer[1] = (continue_transport == NULL)? '0' : '1';
- write(fd, big_buffer, 2);
- close(fd);
+ (void)write(fd, big_buffer, 2);
+ (void)close(fd);
exit(EXIT_SUCCESS);
}
/* Back in the mainline: close the unwanted half of the pipe. */
- close(pfd[pipe_write]);
+ (void)close(pfd[pipe_write]);
/* Fork failed; defer with error message */
if (pid < 0)
{
- close(pfd[pipe_read]);
+ (void)close(pfd[pipe_read]);
remote_post_process(addr, LOG_MAIN|LOG_PANIC,
string_sprintf("fork failed for remote delivery to %s: %s",
addr->domain, strerror(errno)), fallback);
position must be set before calling.
This function used always to print the error. Nowadays we want to restrict it
-to cases such as SMTP errors from a remote host, and errors from :fail: and
-filter "fail". We no longer pass other information willy-nilly in bounce and
-warning messages. Text in user_message is always output; text in message only
-if the af_pass_message flag is set.
+to cases such as LMTP/SMTP errors from a remote host, and errors from :fail:
+and filter "fail". We no longer pass other information willy-nilly in bounce
+and warning messages. Text in user_message is always output; text in message
+only if the af_pass_message flag is set.
Arguments:
addr the address
f the FILE to print on
- s some leading text
+ t some leading text
Returns: nothing
*/
print_address_error(address_item *addr, FILE *f, uschar *t)
{
int count = Ustrlen(t);
-uschar *s = (addr->user_message != NULL)? addr->user_message : addr->message;
+uschar *s = testflag(addr, af_pass_message)? addr->message : NULL;
-if (addr->user_message != NULL)
- s = addr->user_message;
-else
+if (s == NULL)
{
- if (!testflag(addr, af_pass_message) || addr->message == NULL) return;
- s = addr->message;
+ if (addr->user_message != NULL) s = addr->user_message; else return;
}
fprintf(f, "\n %s", t);
sprintf(CS big_buffer, "%s/input/%s/%s", spool_directory, message_subdir,
spoolname);
if (Ustat(big_buffer, &statbuf) == 0)
- log_write(0, LOG_MAIN, "Format error in spool file %s: size=%.30g",
- spoolname, (double)statbuf.st_size);
+ log_write(0, LOG_MAIN, "Format error in spool file %s: "
+ "size=" OFF_T_FMT, spoolname, statbuf.st_size);
else log_write(0, LOG_MAIN, "Format error in spool file %s", spoolname);
}
else
readconf_printtime(keep_malformed));
}
- close(deliver_datafile);
+ (void)close(deliver_datafile);
deliver_datafile = -1;
return continue_closedown(); /* yields DELIVER_NOT_ATTEMPTED */
}
DEBUG(D_deliver) debug_printf("Previously delivered address %s taken from "
"journal file\n", big_buffer);
}
- fclose(jread);
+ (void)fclose(jread);
/* Panic-dies on error */
(void)spool_write_header(message_id, SW_DELIVERING, NULL);
}
if (recipients_list == NULL)
{
- close(deliver_datafile);
+ (void)close(deliver_datafile);
deliver_datafile = -1;
log_write(0, LOG_MAIN, "Spool error: no recipients for %s", spoolname);
return continue_closedown(); /* yields DELIVER_NOT_ATTEMPTED */
log_write(0, LOG_MAIN, "Unfrozen by errmsg timer");
}
- /* If there's no auto thaw, or we haven't reached the auto thaw time yet, and
- this delivery is not forced by an admin user, do not attempt delivery of this
- message. Note that forced is set for continuing messages down the same
- channel, in order to skip load checking and ignore hold domains, but we
- don't want unfreezing in that case. */
+ /* If this is a bounce message, or there's no auto thaw, or we haven't
+ reached the auto thaw time yet, and this delivery is not forced by an admin
+ user, do not attempt delivery of this message. Note that forced is set for
+ continuing messages down the same channel, in order to skip load checking and
+ ignore hold domains, but we don't want unfreezing in that case. */
else
{
- if ((auto_thaw <= 0 || now <= deliver_frozen_at + auto_thaw) &&
- (!forced || !deliver_force_thaw || !admin_user ||
- continue_hostname != NULL))
+ if ((sender_address[0] == 0 ||
+ auto_thaw <= 0 ||
+ now <= deliver_frozen_at + auto_thaw
+ )
+ &&
+ (!forced || !deliver_force_thaw || !admin_user ||
+ continue_hostname != NULL
+ ))
{
- close(deliver_datafile);
+ (void)close(deliver_datafile);
deliver_datafile = -1;
log_write(L_skip_delivery, LOG_MAIN, "Message is frozen");
return continue_closedown(); /* yields DELIVER_NOT_ATTEMPTED */
if (rc == FF_ERROR || rc == FF_NONEXIST)
{
- close(deliver_datafile);
+ (void)close(deliver_datafile);
deliver_datafile = -1;
log_write(0, LOG_MAIN|LOG_PANIC, "Error in system filter: %s",
string_printing(filter_message));
if (testflag(addr, af_pfr))
{
- int offset = testflag(addr->parent, af_homonym)? 3:0;
+ /* If an autoreply in a filter could not generate a syntactically valid
+ address, give up forthwith. Set af_ignore_error so that we don't try to
+ generate a bounce. */
+
+ if (testflag(addr, af_bad_reply))
+ {
+ addr->basic_errno = ERRNO_BADADDRESS2;
+ addr->local_part = addr->address;
+ addr->message =
+ US"filter autoreply generated syntactically invalid recipient";
+ setflag(addr, af_ignore_error);
+ (void)post_process_one(addr, FAIL, LOG_MAIN, DTYPE_ROUTER, 0);
+ continue; /* with the next new address */
+ }
/* If two different users specify delivery to the same pipe or file or
autoreply, there should be two different deliveries, so build a unique
duplicate testing and recording delivery, and also for retrying. */
addr->unique =
- string_sprintf("%s:%s", addr->address, addr->parent->unique + offset);
+ string_sprintf("%s:%s", addr->address, addr->parent->unique +
+ (testflag(addr->parent, af_homonym)? 3:0));
addr->address_retry_key = addr->domain_retry_key =
string_sprintf("T:%s", addr->unique);
that the mode is correct - the group setting doesn't always seem to get
set automatically. */
- fcntl(journal_fd, F_SETFD, fcntl(journal_fd, F_GETFD) | FD_CLOEXEC);
- fchown(journal_fd, exim_uid, exim_gid);
- fchmod(journal_fd, SPOOL_MODE);
+ (void)fcntl(journal_fd, F_SETFD, fcntl(journal_fd, F_GETFD) | FD_CLOEXEC);
+ (void)fchown(journal_fd, exim_uid, exim_gid);
+ (void)fchmod(journal_fd, SPOOL_MODE);
}
handle fallback transports are figured out, this section can be put into a loop
for handling fallbacks, though the uid switching will have to be revised. */
+/* Precompile a regex that is used to recognize a parameter in response
+to an LHLO command, if is isn't already compiled. This may be used on both
+local and remote LMTP deliveries. */
+
+if (regex_IGNOREQUOTA == NULL) regex_IGNOREQUOTA =
+ regex_must_compile(US"\\n250[\\s\\-]IGNOREQUOTA(\\s|\\n|$)", FALSE, TRUE);
+
+/* Handle local deliveries */
+
if (addr_local != NULL)
{
DEBUG(D_deliver|D_transport)
signal(SIGTERM, SIG_IGN);
/* When we are acting as an MUA wrapper, the smtp transport will either have
-succeeded for all addresses, or failed them all. We do not ever want to retry,
-nor do we want to send a bounce message. */
+succeeded for all addresses, or failed them all in normal cases. However, there
+are some setup situations (e.g. when a named port does not exist) that cause an
+immediate exit with deferral of all addresses. Convert those into failures. We
+do not ever want to retry, nor do we want to send a bounce message. */
if (mua_wrapper)
{
+ if (addr_defer != NULL)
+ {
+ address_item *addr, *nextaddr;
+ for (addr = addr_defer; addr != NULL; addr = nextaddr)
+ {
+ log_write(0, LOG_MAIN, "** %s mua_wrapper forced failure for deferred "
+ "delivery", addr->address);
+ nextaddr = addr->next;
+ addr->next = addr_failed;
+ addr_failed = addr;
+ }
+ addr_defer = NULL;
+ }
+
+ /* Now all should either have succeeded or failed. */
+
if (addr_failed == NULL) final_yield = DELIVER_MUA_SUCCEEDED; else
{
uschar *s = (addr_failed->user_message != NULL)?
if (errors_reply_to != NULL)
fprintf(f, "Reply-To: %s\n", errors_reply_to);
- fprintf(f, "Auto-Submitted: auto-generated\n");
+ fprintf(f, "Auto-Submitted: auto-replied\n");
fprintf(f, "From: Mail Delivery System <Mailer-Daemon@%s>\n",
qualify_domain_sender);
fprintf(f, "To: %s\n", bounce_recipient);
else
{
while ((ch = fgetc(fm)) != EOF) fputc(ch, f);
- fclose(fm);
+ (void)fclose(fm);
}
Uunlink(addr->return_filename);
if (emf_text != NULL) fprintf(f, "%s", CS emf_text); else
{
fprintf(f,
-"------ The body of the message is %.30g characters long; only the first\n"
-"------ %d or so are included here.\n", (double)statbuf.st_size, max);
+"------ The body of the message is " OFF_T_FMT " characters long; only the first\n"
+"------ %d or so are included here.\n", statbuf.st_size, max);
}
}
}
{
emf_text = next_emf(emf, US"final");
if (emf_text != NULL) fprintf(f, "%s", CS emf_text);
- fclose(emf);
+ (void)fclose(emf);
}
/* Close the file, which should send an EOF to the child process
that is receiving the message. Wait for it to finish. */
- fclose(f);
+ (void)fclose(f);
rc = child_close(pid, 0); /* Waits for child to close, no timeout */
/* In the test harness, let the child do it's thing first. */
if (errors_reply_to != NULL)
fprintf(f, "Reply-To: %s\n", errors_reply_to);
- fprintf(f, "Auto-Submitted: auto-generated\n");
+ fprintf(f, "Auto-Submitted: auto-replied\n");
fprintf(f, "From: Mail Delivery System <Mailer-Daemon@%s>\n",
qualify_domain_sender);
fprintf(f, "To: %s\n", recipients);
{
wmf_text = next_emf(wmf, US"final");
if (wmf_text != NULL) fprintf(f, "%s", CS wmf_text);
- fclose(wmf);
+ (void)fclose(wmf);
}
else
{
/* Close and wait for child process to complete, without a timeout.
If there's an error, don't update the count. */
- fclose(f);
+ (void)fclose(f);
if (child_close(pid, 0) == 0)
{
warning_count = count;
/* Finished with the message log. If the message is complete, it will have
been unlinked or renamed above. */
-if (message_logs) fclose(message_log);
+if (message_logs) (void)fclose(message_log);
/* Now we can close and remove the journal file. Its only purpose is to record
successfully completed deliveries asap so that this information doesn't get
message off the main spool if frozen and the option is set. It should get moved
at the next attempt, after the journal has been inspected. */
-if (journal_fd >= 0) close(journal_fd);
+if (journal_fd >= 0) (void)close(journal_fd);
if (remove_journal)
{
will go away. Otherwise the message becomes available for another process
to try delivery. */
-close(deliver_datafile);
+(void)close(deliver_datafile);
deliver_datafile = -1;
DEBUG(D_deliver) debug_printf("end delivery of %s\n", id);