X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/63955bf2d9be6412f7d1b77e46f56ccbaf4c816e..5a03bd24ee73e09f4bd086654d5ad1fa9b973996:/src/src/deliver.c diff --git a/src/src/deliver.c b/src/src/deliver.c index 78eb65bc6..c166d2601 100644 --- a/src/src/deliver.c +++ b/src/src/deliver.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/deliver.c,v 1.13 2005/04/07 15:40:50 ph10 Exp $ */ +/* $Cambridge: exim/src/src/deliver.c,v 1.22 2005/08/02 11:22:24 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -286,7 +286,7 @@ doesn't always get set automatically. */ 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"; @@ -798,7 +798,7 @@ if (addr->return_file >= 0 && addr->return_filename != NULL) log_write(0, LOG_MAIN, "<%s>: %s transport output: %s", addr->address, tb->name, s); } - fclose(f); + (void)fclose(f); } } @@ -829,7 +829,7 @@ if (addr->return_file >= 0 && addr->return_filename != NULL) 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 @@ -878,6 +878,11 @@ if (result == OK) if ((log_extra_selector & LX_sender_on_delivery) != 0) s = string_append(s, &size, &ptr, 3, US" F=<", sender_address, US">"); + #ifdef EXPERIMENTAL_SRS + if(addr->p.srs_sender) + s = string_append(s, &size, &ptr, 3, US" SRS=<", addr->p.srs_sender, US">"); + #endif + /* You might think that the return path must always be set for a successful delivery; indeed, I did for some time, until this statement crashed. The case when it is not set is for a delivery to /dev/null which is optimised by not @@ -1537,8 +1542,14 @@ transport_instance *tp = addr->transport; /* Set up the return path from the errors or sender address. If the transport has its own return path setting, expand it and replace the existing value. */ -return_path = (addr->p.errors_address != NULL)? - addr->p.errors_address : sender_address; +if(addr->p.errors_address != NULL) + return_path = addr->p.errors_address; +#ifdef EXPERIMENTAL_SRS +else if(addr->p.srs_sender != NULL) + return_path = addr->p.srs_sender; +#endif +else + return_path = sender_address; if (tp->return_path != NULL) { @@ -1717,8 +1728,8 @@ if ((pid = fork()) == 0) 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, @@ -1783,13 +1794,13 @@ if ((pid = fork()) == 0) 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 @@ -1798,8 +1809,8 @@ if ((pid = fork()) == 0) 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 */ @@ -1807,15 +1818,15 @@ if ((pid = fork()) == 0) 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); } @@ -1834,7 +1845,7 @@ on an empty pipe. We check that a status exists for each address before 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) { @@ -1884,7 +1895,7 @@ 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 @@ -1987,7 +1998,7 @@ if (addr->special_action == SPECIAL_WARN && /* Close and wait for child process to complete, without a timeout. */ - fclose(f); + (void)fclose(f); (void)child_close(pid, 0); } } @@ -2874,7 +2885,7 @@ if (!eop && !done) /* 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, @@ -3528,8 +3539,14 @@ for (delivery_count = 0; addr_remote != NULL; delivery_count++) /* Compute the return path, expanding a new one if required. The old one must be set first, as it might be referred to in the expansion. */ - return_path = (addr->p.errors_address != NULL)? - addr->p.errors_address : sender_address; + if(addr->p.errors_address != NULL) + return_path = addr->p.errors_address; +#ifdef EXPERIMENTAL_SRS + else if(addr->p.srs_sender != NULL) + return_path = addr->p.srs_sender; +#endif + else + return_path = sender_address; if (tp->return_path != NULL) { @@ -3656,9 +3673,9 @@ for (delivery_count = 0; addr_remote != NULL; delivery_count++) 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 @@ -3690,8 +3707,8 @@ for (delivery_count = 0; addr_remote != NULL; delivery_count++) 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; @@ -3731,13 +3748,13 @@ for (delivery_count = 0; addr_remote != NULL; delivery_count++) 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 @@ -3747,7 +3764,7 @@ for (delivery_count = 0; addr_remote != NULL; delivery_count++) 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); @@ -3758,7 +3775,7 @@ for (delivery_count = 0; addr_remote != NULL; delivery_count++) /* 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. */ @@ -3771,7 +3788,7 @@ for (delivery_count = 0; addr_remote != NULL; delivery_count++) 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); @@ -3800,7 +3817,7 @@ for (delivery_count = 0; addr_remote != NULL; delivery_count++) { 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 @@ -3810,7 +3827,7 @@ for (delivery_count = 0; addr_remote != NULL; delivery_count++) 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' @@ -3840,7 +3857,7 @@ for (delivery_count = 0; addr_remote != NULL; delivery_count++) sprintf(CS ptr, "%.512s", addr->peerdn); while(*ptr++); } - write(fd, big_buffer, ptr - big_buffer); + (void)write(fd, big_buffer, ptr - big_buffer); } #endif @@ -3860,7 +3877,7 @@ for (delivery_count = 0; addr_remote != NULL; delivery_count++) 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. */ @@ -3896,7 +3913,7 @@ for (delivery_count = 0; addr_remote != NULL; delivery_count++) 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 @@ -3906,20 +3923,20 @@ for (delivery_count = 0; addr_remote != NULL; delivery_count++) 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); @@ -4180,7 +4197,6 @@ if (addr->parent != NULL && testflag(addr, af_hide_child)) printed = US"an undisclosed address"; yield = FALSE; } - else if (!testflag(addr, af_pfr) || addr->parent == NULL) printed = addr->address; @@ -4217,7 +4233,6 @@ return yield; - /************************************************* * Print error for an address * *************************************************/ @@ -4227,53 +4242,62 @@ a bounce or a warning message. It tries to format the message reasonably by introducing newlines. All lines are indented by 4; the initial printing 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. + Arguments: - addr points to the address + addr the address f the FILE to print on + s some leading text Returns: nothing */ static void -print_address_error(address_item *addr, FILE *f) +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; -if (addr->basic_errno > 0) - { - fprintf(f, "%s%s", strerror(addr->basic_errno), - (s == NULL)? "" : ":\n "); - } -if (s == NULL) + +if (addr->user_message != NULL) + s = addr->user_message; +else { - if (addr->basic_errno <= 0) fprintf(f, "unknown error"); + if (!testflag(addr, af_pass_message) || addr->message == NULL) return; + s = addr->message; } -else + +fprintf(f, "\n %s", t); + +while (*s != 0) { - int count = 0; - while (*s != 0) + if (*s == '\\' && s[1] == 'n') { - if (*s == '\\' && s[1] == 'n') + fprintf(f, "\n "); + s += 2; + count = 0; + } + else + { + fputc(*s, f); + count++; + if (*s++ == ':' && isspace(*s) && count > 45) { - fprintf(f, "\n "); - s += 2; + fprintf(f, "\n "); /* sic (because space follows) */ count = 0; } - else - { - fputc(*s, f); - count++; - if (*s++ == ':' && isspace(*s) && count > 45) - { - fprintf(f, "\n "); /* sic (because space follows) */ - count = 0; - } - } } } } + + + /************************************************* * Check list of addresses for duplication * *************************************************/ @@ -4458,11 +4482,8 @@ if ((rc = spool_read_header(spoolname, TRUE, TRUE)) != spool_read_OK) sprintf(CS big_buffer, "%s/input/%s/%s", spool_directory, message_subdir, spoolname); if (Ustat(big_buffer, &statbuf) == 0) - { - int size = statbuf.st_size; /* Because might be a long */ - log_write(0, LOG_MAIN, "Format error in spool file %s: size=%d", - spoolname, 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 @@ -4496,7 +4517,7 @@ if ((rc = spool_read_header(spoolname, TRUE, TRUE)) != spool_read_OK) readconf_printtime(keep_malformed)); } - close(deliver_datafile); + (void)close(deliver_datafile); deliver_datafile = -1; return continue_closedown(); /* yields DELIVER_NOT_ATTEMPTED */ } @@ -4522,7 +4543,7 @@ if (jread != NULL) 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); } @@ -4537,7 +4558,7 @@ else if (errno != ENOENT) 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 */ @@ -4580,19 +4601,24 @@ if (deliver_freeze) 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 */ @@ -4727,7 +4753,7 @@ else if (system_filter != NULL && process_recipients != RECIP_FAIL_TIMEOUT) 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)); @@ -4994,6 +5020,7 @@ if (process_recipients != RECIP_IGNORE) case RECIP_FAIL_FILTER: new->message = (filter_message == NULL)? US"delivery cancelled" : filter_message; + setflag(new, af_pass_message); goto RECIP_QUEUE_FAILED; /* below */ @@ -5818,9 +5845,9 @@ if (addr_local != NULL || addr_remote != NULL) 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); } @@ -5829,6 +5856,15 @@ deliveries are done first, then remote ones. If ever the problems of how to 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) @@ -5925,11 +5961,29 @@ set_process_info("tidying up after delivering %s", message_id); 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)? @@ -6182,26 +6236,15 @@ wording. */ /* Process the addresses, leaving them on the msgchain if they have a file name for a return message. (There has already been a check in - post_process_one() for the existence of data in the message file.) */ + post_process_one() for the existence of data in the message file.) A TRUE + return from print_address_information() means that the address is not + hidden. */ paddr = &msgchain; for (addr = msgchain; addr != NULL; addr = *paddr) { if (print_address_information(addr, f, US" ", US"\n ", US"")) - { - /* A TRUE return from print_address_information() means that the - address is not hidden. If there is a return file, it has already - been checked to ensure it is not empty. Omit the bland "return - message generated" error, but otherwise include error information. */ - - if (addr->return_file < 0 || - addr->message == NULL || - Ustrcmp(addr->message, "return message generated") != 0) - { - fprintf(f, "\n "); - print_address_error(addr, f); - } - } + print_address_error(addr, f, US""); /* End the final line for the address */ @@ -6276,7 +6319,7 @@ wording. */ else { while ((ch = fgetc(fm)) != EOF) fputc(ch, f); - fclose(fm); + (void)fclose(fm); } Uunlink(addr->return_filename); @@ -6329,8 +6372,8 @@ wording. */ if (emf_text != NULL) fprintf(f, "%s", CS emf_text); else { fprintf(f, -"------ The body of the message is %d characters long; only the first\n" -"------ %d or so are included here.\n", (int)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); } } } @@ -6349,13 +6392,13 @@ wording. */ { 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. */ @@ -6703,21 +6746,15 @@ else if (addr_defer != (address_item *)(+1)) (addr_defer->next == NULL)? "is": "are"); } - /* List the addresses. For any that are hidden, don't give the delay - reason, because it might expose that which is hidden. Also, do not give - "retry time not reached" because that isn't helpful. */ + /* List the addresses, with error information if allowed */ fprintf(f, "\n"); while (addr_defer != NULL) { address_item *addr = addr_defer; addr_defer = addr->next; - if (print_address_information(addr, f, US" ", US"\n ", US"") && - addr->basic_errno > ERRNO_RETRY_BASE) - { - fprintf(f, "\n Delay reason: "); - print_address_error(addr, f); - } + if (print_address_information(addr, f, US" ", US"\n ", US"")) + print_address_error(addr, f, US"Delay reason: "); fprintf(f, "\n"); } fprintf(f, "\n"); @@ -6728,7 +6765,7 @@ else if (addr_defer != (address_item *)(+1)) { wmf_text = next_emf(wmf, US"final"); if (wmf_text != NULL) fprintf(f, "%s", CS wmf_text); - fclose(wmf); + (void)fclose(wmf); } else { @@ -6742,7 +6779,7 @@ else if (addr_defer != (address_item *)(+1)) /* 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; @@ -6825,7 +6862,7 @@ else if (addr_defer != (address_item *)(+1)) /* 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 @@ -6839,7 +6876,7 @@ the remove_journal flag. When the journal is left, we also don't move the 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) { @@ -6860,7 +6897,7 @@ 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);