X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/35af9f61534cba784c1718d804567043da64f2df..d7d7b7b91dd75cec636fc144da7e27eed860f971:/src/src/transports/pipe.c diff --git a/src/src/transports/pipe.c b/src/src/transports/pipe.c index d159186ba..cedce6fd9 100644 --- a/src/src/transports/pipe.c +++ b/src/src/transports/pipe.c @@ -1,10 +1,10 @@ -/* $Cambridge: exim/src/src/transports/pipe.c,v 1.2 2004/10/14 14:52:45 ph10 Exp $ */ +/* $Cambridge: exim/src/src/transports/pipe.c,v 1.9 2006/02/07 11:19:03 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) University of Cambridge 1995 - 2004 */ +/* Copyright (c) University of Cambridge 1995 - 2006 */ /* See the file NOTICE for conditions of use and distribution. */ @@ -65,6 +65,8 @@ optionlist pipe_transport_options[] = { (void *)offsetof(pipe_transport_options_block, temp_errors) }, { "timeout", opt_time, (void *)offsetof(pipe_transport_options_block, timeout) }, + { "timeout_defer", opt_bool, + (void *)offsetof(pipe_transport_options_block, timeout_defer) }, { "umask", opt_octint, (void *)offsetof(pipe_transport_options_block, umask) }, { "use_bsmtp", opt_bool, @@ -87,7 +89,7 @@ pipe_transport_options_block pipe_transport_option_defaults = { NULL, /* cmd */ NULL, /* allow_commands */ NULL, /* environment */ - US"/usr/bin", /* path */ + US"/bin:/usr/bin", /* path */ NULL, /* message_prefix (reset in init if not bsmtp) */ NULL, /* message_suffix (ditto) */ US mac_expanded_string(EX_TEMPFAIL) ":" /* temp_errors */ @@ -101,6 +103,7 @@ pipe_transport_options_block pipe_transport_option_defaults = { FALSE, /* freeze_exec_fail */ FALSE, /* ignore_status */ FALSE, /* restrict_to_path */ + FALSE, /* timeout_defer */ FALSE, /* use_shell */ FALSE, /* use_bsmtp */ FALSE /* use_crlf */ @@ -637,8 +640,8 @@ if ((outpid = fork()) < 0) addr->message = string_sprintf( "Failed to create process for handling output in %s transport", tblock->name); - close(fd_in); - close(fd_out); + (void)close(fd_in); + (void)close(fd_out); return FALSE; } @@ -651,7 +654,7 @@ the subprocess to fail. */ if (outpid == 0) { int count = 0; - close(fd_in); + (void)close(fd_in); set_process_info("reading output from |%s", cmd); while ((rc = read(fd_out, big_buffer, big_buffer_size)) > 0) { @@ -668,11 +671,11 @@ if (outpid == 0) break; } } - close(fd_out); + (void)close(fd_out); _exit(0); } -close(fd_out); /* Not used in this process */ +(void)close(fd_out); /* Not used in this process */ /* Carrying on now with the main parent process. Attempt to write the message @@ -786,21 +789,24 @@ the child process to 1 second. If the process at the far end of the pipe died without reading all of it, we expect an EPIPE error, which should be ignored. We used also to ignore WRITEINCOMPLETE but the writing function is now cleverer at handling OS where the death of a pipe doesn't give EPIPE immediately. See -comments therein. This change made 04-Sep-98. Clean up this code in a year or -so. */ +comments therein. */ if (!written_ok) { if (errno == ETIMEDOUT) + { + addr->message = string_sprintf("%stimeout while writing to pipe", + transport_filter_timed_out? "transport filter " : ""); + addr->transport_return = ob->timeout_defer? DEFER : FAIL; timeout = 1; - else if (errno == EPIPE /* || errno == ERRNO_WRITEINCOMPLETE */ ) + } + else if (errno == EPIPE) { - debug_printf("transport error %s ignored\n", - (errno == EPIPE)? "EPIPE" : "WRITEINCOMPLETE"); + debug_printf("transport error EPIPE ignored\n"); } else { - addr->transport_return = PANIC; + addr->transport_return = PANIC; addr->basic_errno = errno; if (errno == ERRNO_CHHEADER_FAIL) addr->message = @@ -824,6 +830,9 @@ above timed out. */ if ((rc = child_close(pid, timeout)) != 0) { + uschar *tmsg = (addr->message == NULL)? US"" : + string_sprintf(" (preceded by %s)", addr->message); + /* The process did not complete in time; kill its process group and fail the delivery. It appears to be necessary to kill the output process too, as otherwise it hangs on for some time if the actual pipe process is sleeping. @@ -834,8 +843,8 @@ if ((rc = child_close(pid, timeout)) != 0) { killpg(pid, SIGKILL); kill(outpid, SIGKILL); - addr->transport_return = FAIL; - addr->message = string_sprintf("pipe delivery process timed out"); + addr->transport_return = ob->timeout_defer? DEFER : FAIL; + addr->message = string_sprintf("pipe delivery process timed out%s", tmsg); } /* Wait() failed. */ @@ -844,7 +853,7 @@ if ((rc = child_close(pid, timeout)) != 0) { addr->transport_return = PANIC; addr->message = string_sprintf("Wait() failed for child process of %s " - "transport: %s", tblock->name, strerror(errno)); + "transport: %s%s", tblock->name, strerror(errno), tmsg); } /* Either the process completed, but yielded a non-zero (necessarily @@ -858,8 +867,8 @@ if ((rc = child_close(pid, timeout)) != 0) { addr->transport_return = FAIL; addr->message = string_sprintf("Child process of %s transport (running " - "command \"%s\") was terminated by signal %d (%s)", tblock->name, cmd, - -rc, os_strsignal(-rc)); + "command \"%s\") was terminated by signal %d (%s)%s", tblock->name, cmd, + -rc, os_strsignal(-rc), tmsg); } } @@ -911,8 +920,8 @@ if ((rc = child_close(pid, timeout)) != 0) { addr->transport_return = DEFER; addr->special_action = SPECIAL_FREEZE; - addr->message = string_sprintf("pipe process failed to exec \"%s\"", - cmd); + addr->message = string_sprintf("pipe process failed to exec \"%s\"%s", + cmd, tmsg); } /* Otherwise take action only if not ignoring status */ @@ -986,6 +995,13 @@ if ((rc = child_close(pid, timeout)) != 0) if (quote) addr->message = string_cat(addr->message, &size, &ptr, US"\"", 1); } + + /* Add previous filter timeout message, if present. */ + + if (*tmsg != 0) + addr->message = string_cat(addr->message, &size, &ptr, tmsg, + Ustrlen(tmsg)); + addr->message[ptr] = 0; /* Ensure concatenated string terminated */ } }