"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "src/transports/pipe.c" between
exim-4.91.tar.xz and exim-4.92.tar.xz

About: Exim is a message transfer agent (MTA).

pipe.c  (exim-4.91.tar.xz):pipe.c  (exim-4.92.tar.xz)
skipping to change at line 472 skipping to change at line 472
if (expand_arguments) if (expand_arguments)
{ {
uschar * p = Ustrstr(cmd, "pipe_addresses"); uschar * p = Ustrstr(cmd, "pipe_addresses");
gstring * g = NULL; gstring * g = NULL;
DEBUG(D_transport) DEBUG(D_transport)
debug_printf("shell pipe command before expansion:\n %s\n", cmd); debug_printf("shell pipe command before expansion:\n %s\n", cmd);
/* Allow $recipients in the expansion iff it comes from a system filter */ /* Allow $recipients in the expansion iff it comes from a system filter */
enable_dollar_recipients = addr && addr->parent && f.enable_dollar_recipients = addr && addr->parent &&
Ustrcmp(addr->parent->address, "system-filter") == 0; Ustrcmp(addr->parent->address, "system-filter") == 0;
if (p != NULL && ( if (p != NULL && (
(p > cmd && p[-1] == '$') || (p > cmd && p[-1] == '$') ||
(p > cmd + 1 && p[-2] == '$' && p[-1] == '{' && p[14] == '}'))) (p > cmd + 1 && p[-2] == '$' && p[-1] == '{' && p[14] == '}')))
{ {
address_item *ad; address_item *ad;
uschar *q = p + 14; uschar *q = p + 14;
if (p[-1] == '{') { q++; p--; } if (p[-1] == '{') { q++; p--; }
skipping to change at line 500 skipping to change at line 500
if (ad != addr) g = string_catn(g, US" ", 1); if (ad != addr) g = string_catn(g, US" ", 1);
g = string_cat(g, ad->address); g = string_cat(g, ad->address);
} }
g = string_cat(g, q); g = string_cat(g, q);
argv[2] = (cmd = string_from_gstring(g)) ? expand_string(cmd) : NULL; argv[2] = (cmd = string_from_gstring(g)) ? expand_string(cmd) : NULL;
} }
else else
argv[2] = expand_string(cmd); argv[2] = expand_string(cmd);
enable_dollar_recipients = FALSE; f.enable_dollar_recipients = FALSE;
if (!argv[2]) if (!argv[2])
{ {
addr->transport_return = search_find_defer ? DEFER : expand_fail; addr->transport_return = f.search_find_defer ? DEFER : expand_fail;
addr->message = string_sprintf("Expansion of command \"%s\" " addr->message = string_sprintf("Expansion of command \"%s\" "
"in %s transport failed: %s", "in %s transport failed: %s",
cmd, tname, expand_string_message); cmd, tname, expand_string_message);
return FALSE; return FALSE;
} }
DEBUG(D_transport) DEBUG(D_transport)
debug_printf("shell pipe command after expansion:\n %s\n", argv[2]); debug_printf("shell pipe command after expansion:\n %s\n", argv[2]);
} }
else else
skipping to change at line 667 skipping to change at line 667
envp[envcount++] = string_sprintf("RECIPIENT=%#s%#s%#s@%#s", envp[envcount++] = string_sprintf("RECIPIENT=%#s%#s%#s@%#s",
deliver_localpart_prefix, deliver_localpart, deliver_localpart_suffix, deliver_localpart_prefix, deliver_localpart, deliver_localpart_suffix,
deliver_domain); deliver_domain);
envp[envcount++] = string_sprintf("QUALIFY_DOMAIN=%s", qualify_domain_sender); envp[envcount++] = string_sprintf("QUALIFY_DOMAIN=%s", qualify_domain_sender);
envp[envcount++] = string_sprintf("SENDER=%s", sender_address); envp[envcount++] = string_sprintf("SENDER=%s", sender_address);
envp[envcount++] = US"SHELL=/bin/sh"; envp[envcount++] = US"SHELL=/bin/sh";
if (addr->host_list != NULL) if (addr->host_list != NULL)
envp[envcount++] = string_sprintf("HOST=%s", addr->host_list->name); envp[envcount++] = string_sprintf("HOST=%s", addr->host_list->name);
if (timestamps_utc) envp[envcount++] = US"TZ=UTC"; if (f.timestamps_utc) envp[envcount++] = US"TZ=UTC";
else if (timezone_string != NULL && timezone_string[0] != 0) else if (timezone_string != NULL && timezone_string[0] != 0)
envp[envcount++] = string_sprintf("TZ=%s", timezone_string); envp[envcount++] = string_sprintf("TZ=%s", timezone_string);
/* Add any requested items */ /* Add any requested items */
if (envlist) if (envlist)
{ {
envlist = expand_cstring(envlist); envlist = expand_cstring(envlist);
if (envlist == NULL) if (envlist == NULL)
{ {
skipping to change at line 702 skipping to change at line 702
"%s transport", tblock->name); "%s transport", tblock->name);
return FALSE; return FALSE;
} }
envp[envcount++] = string_copy(ss); envp[envcount++] = string_copy(ss);
} }
envp[envcount] = NULL; envp[envcount] = NULL;
/* If the -N option is set, can't do any more. */ /* If the -N option is set, can't do any more. */
if (dont_deliver) if (f.dont_deliver)
{ {
DEBUG(D_transport) DEBUG(D_transport)
debug_printf("*** delivery by %s transport bypassed by -N option", debug_printf("*** delivery by %s transport bypassed by -N option",
tblock->name); tblock->name);
return FALSE; return FALSE;
} }
/* Handling the output from the pipe is tricky. If a file for catching this /* Handling the output from the pipe is tricky. If a file for catching this
output is provided, we could in theory just hand that fd over to the process, output is provided, we could in theory just hand that fd over to the process,
but this isn't very safe because it might loop and carry on writing for but this isn't very safe because it might loop and carry on writing for
skipping to change at line 799 skipping to change at line 799
(void)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 /* Carrying on now with the main parent process. Attempt to write the message
to it down the pipe. It is a fallacy to think that you can detect write errors to it down the pipe. It is a fallacy to think that you can detect write errors
when the sub-process fails to read the pipe. The parent process may complete when the sub-process fails to read the pipe. The parent process may complete
writing and close the pipe before the sub-process completes. We could sleep a writing and close the pipe before the sub-process completes. We could sleep a
bit here to let the sub-process get going, but it may still not complete. So we bit here to let the sub-process get going, but it may still not complete. So we
ignore all writing errors. (When in the test harness, we do do a short sleep so ignore all writing errors. (When in the test harness, we do do a short sleep so
any debugging output is likely to be in the same order.) */ any debugging output is likely to be in the same order.) */
if (running_in_test_harness) millisleep(500); if (f.running_in_test_harness) millisleep(500);
DEBUG(D_transport) debug_printf("Writing message to pipe\n"); DEBUG(D_transport) debug_printf("Writing message to pipe\n");
/* Arrange to time out writes if there is a timeout set. */ /* Arrange to time out writes if there is a timeout set. */
if (timeout > 0) if (timeout > 0)
{ {
sigalrm_seen = FALSE; sigalrm_seen = FALSE;
transport_write_timeout = timeout; transport_write_timeout = timeout;
} }
skipping to change at line 822 skipping to change at line 822
transport_count = 0; transport_count = 0;
/* First write any configured prefix information */ /* First write any configured prefix information */
if (ob->message_prefix != NULL) if (ob->message_prefix != NULL)
{ {
uschar *prefix = expand_string(ob->message_prefix); uschar *prefix = expand_string(ob->message_prefix);
if (prefix == NULL) if (prefix == NULL)
{ {
addr->transport_return = search_find_defer? DEFER : PANIC; addr->transport_return = f.search_find_defer? DEFER : PANIC;
addr->message = string_sprintf("Expansion of \"%s\" (prefix for %s " addr->message = string_sprintf("Expansion of \"%s\" (prefix for %s "
"transport) failed: %s", ob->message_prefix, tblock->name, "transport) failed: %s", ob->message_prefix, tblock->name,
expand_string_message); expand_string_message);
return FALSE; return FALSE;
} }
if (!transport_write_block(&tctx, prefix, Ustrlen(prefix), FALSE)) if (!transport_write_block(&tctx, prefix, Ustrlen(prefix), FALSE))
goto END_WRITE; goto END_WRITE;
} }
/* If the use_bsmtp option is set, we need to write SMTP prefix information. /* If the use_bsmtp option is set, we need to write SMTP prefix information.
skipping to change at line 866 skipping to change at line 866
if (!transport_write_message(&tctx, 0)) if (!transport_write_message(&tctx, 0))
goto END_WRITE; goto END_WRITE;
/* Now any configured suffix */ /* Now any configured suffix */
if (ob->message_suffix) if (ob->message_suffix)
{ {
uschar *suffix = expand_string(ob->message_suffix); uschar *suffix = expand_string(ob->message_suffix);
if (!suffix) if (!suffix)
{ {
addr->transport_return = search_find_defer? DEFER : PANIC; addr->transport_return = f.search_find_defer? DEFER : PANIC;
addr->message = string_sprintf("Expansion of \"%s\" (suffix for %s " addr->message = string_sprintf("Expansion of \"%s\" (suffix for %s "
"transport) failed: %s", ob->message_suffix, tblock->name, "transport) failed: %s", ob->message_suffix, tblock->name,
expand_string_message); expand_string_message);
return FALSE; return FALSE;
} }
if (!transport_write_block(&tctx, suffix, Ustrlen(suffix), FALSE)) if (!transport_write_block(&tctx, suffix, Ustrlen(suffix), FALSE))
goto END_WRITE; goto END_WRITE;
} }
/* If local_smtp, write the terminating dot. */ /* If local_smtp, write the terminating dot. */
skipping to change at line 905 skipping to change at line 905
without reading all of it, we expect an EPIPE error, which should be ignored. 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 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 at handling OS where the death of a pipe doesn't give EPIPE immediately. See
comments therein. */ comments therein. */
if (!written_ok) if (!written_ok)
{ {
if (errno == ETIMEDOUT) if (errno == ETIMEDOUT)
{ {
addr->message = string_sprintf("%stimeout while writing to pipe", addr->message = string_sprintf("%stimeout while writing to pipe",
transport_filter_timed_out? "transport filter " : ""); f.transport_filter_timed_out ? "transport filter " : "");
addr->transport_return = ob->timeout_defer? DEFER : FAIL; addr->transport_return = ob->timeout_defer? DEFER : FAIL;
timeout = 1; timeout = 1;
} }
else if (errno == EPIPE) else if (errno == EPIPE)
{ {
debug_printf("transport error EPIPE ignored\n"); debug_printf("transport error EPIPE ignored\n");
} }
else else
{ {
addr->transport_return = PANIC; addr->transport_return = PANIC;
skipping to change at line 971 skipping to change at line 971
addr->message = string_sprintf("Wait() failed for child process of %s " addr->message = string_sprintf("Wait() failed for child process of %s "
"transport: %s%s", tblock->name, strerror(errno), tmsg); "transport: %s%s", tblock->name, strerror(errno), tmsg);
} }
/* Since the transport_filter timed out we assume it has sent the child proces s /* Since the transport_filter timed out we assume it has sent the child proces s
a malformed or incomplete data stream. Kill off the child process a malformed or incomplete data stream. Kill off the child process
and prevent checking its exit status as it will has probably exited in error. and prevent checking its exit status as it will has probably exited in error.
This prevents the transport_filter timeout message from getting overwritten This prevents the transport_filter timeout message from getting overwritten
by the exit error which is not the cause of the problem. */ by the exit error which is not the cause of the problem. */
else if (transport_filter_timed_out) else if (f.transport_filter_timed_out)
{ {
killpg(pid, SIGKILL); killpg(pid, SIGKILL);
kill(outpid, SIGKILL); kill(outpid, SIGKILL);
} }
/* Either the process completed, but yielded a non-zero (necessarily /* Either the process completed, but yielded a non-zero (necessarily
positive) status, or the process was terminated by a signal (rc will contain positive) status, or the process was terminated by a signal (rc will contain
the negation of the signal number). Treat killing by signal as failure unless the negation of the signal number). Treat killing by signal as failure unless
status is being ignored. By default, the message is bounced back, unless status is being ignored. By default, the message is bounced back, unless
freeze_signal is set, in which case it is frozen instead. */ freeze_signal is set, in which case it is frozen instead. */
 End of changes. 10 change blocks. 
10 lines changed or deleted 10 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)