* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2015 */
+/* Copyright (c) University of Cambridge 1995 - 2018 */
/* See the file NOTICE for conditions of use and distribution. */
int pipe_transport_options_count =
sizeof(pipe_transport_options)/sizeof(optionlist);
+
+#ifdef MACRO_PREDEF
+
+/* Dummy values */
+pipe_transport_options_block pipe_transport_option_defaults = {0};
+void pipe_transport_init(transport_instance *tblock) {}
+BOOL pipe_transport_entry(transport_instance *tblock, address_item *addr) {return FALSE;}
+
+#else /*!MACRO_PREDEF*/
+
+
/* Default private options block for the pipe transport. */
pipe_transport_options_block pipe_transport_option_defaults = {
/* We have to take special action to handle the special "variable" called
$pipe_addresses, which is not recognized by the normal expansion function. */
-DEBUG(D_transport)
- debug_printf("shell pipe command before expansion:\n %s\n", cmd);
-
if (expand_arguments)
{
- uschar *s = cmd;
- uschar *p = Ustrstr(cmd, "pipe_addresses");
+ uschar * p = Ustrstr(cmd, "pipe_addresses");
+ gstring * g = NULL;
+
+ DEBUG(D_transport)
+ debug_printf("shell pipe command before expansion:\n %s\n", cmd);
+
+ /* Allow $recipients in the expansion iff it comes from a system filter */
+
+ f.enable_dollar_recipients = addr && addr->parent &&
+ Ustrcmp(addr->parent->address, "system-filter") == 0;
if (p != NULL && (
(p > cmd && p[-1] == '$') ||
{
address_item *ad;
uschar *q = p + 14;
- int size = Ustrlen(cmd) + 64;
- int offset;
if (p[-1] == '{') { q++; p--; }
- s = store_get(size);
- offset = p - cmd - 1;
- Ustrncpy(s, cmd, offset);
+ g = string_get(Ustrlen(cmd) + 64);
+ g = string_catn(g, cmd, p - cmd - 1);
- for (ad = addr; ad != NULL; ad = ad->next)
+ for (ad = addr; ad; ad = ad->next)
{
/*XXX string_append_listele() ? */
- if (ad != addr) s = string_catn(s, &size, &offset, US" ", 1);
- s = string_cat(s, &size, &offset, ad->address);
+ if (ad != addr) g = string_catn(g, US" ", 1);
+ g = string_cat(g, ad->address);
}
- s = string_cat(s, &size, &offset, q);
- s[offset] = 0;
+ g = string_cat(g, q);
+ argv[2] = (cmd = string_from_gstring(g)) ? expand_string(cmd) : NULL;
}
+ else
+ argv[2] = expand_string(cmd);
- /* Allow $recipients in the expansion iff it comes from a system filter */
-
- enable_dollar_recipients = addr != NULL &&
- addr->parent != NULL &&
- Ustrcmp(addr->parent->address, "system-filter") == 0;
- argv[2] = expand_string(s);
- enable_dollar_recipients = FALSE;
+ f.enable_dollar_recipients = FALSE;
- if (argv[2] == NULL)
+ 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\" "
"in %s transport failed: %s",
cmd, tname, expand_string_message);
DEBUG(D_transport)
debug_printf("shell pipe command after expansion:\n %s\n", argv[2]);
}
-else argv[2] = cmd;
+else
+ {
+ DEBUG(D_transport)
+ debug_printf("shell pipe command (no expansion):\n %s\n", cmd);
+ argv[2] = cmd;
+ }
-argv[3] = (uschar *)0;
+argv[3] = US 0;
return TRUE;
}
uschar *cmd, *ss;
uschar *eol = ob->use_crlf ? US"\r\n" : US"\n";
transport_ctx tctx = {
- tblock,
- addr,
- ob->check_string,
- ob->escape_string,
- ob->options /* set at initialization time */
+ .tblock = tblock,
+ .addr = addr,
+ .check_string = ob->check_string,
+ .escape_string = ob->escape_string,
+ ob->options | topt_not_socket /* set at initialization time */
};
DEBUG(D_transport) debug_printf("%s transport entered\n", tblock->name);
{
if (ob->force_command)
{
- /* Enables expansion of $address_pipe into seperate arguments */
+ /* Enables expansion of $address_pipe into separate arguments */
setflag(addr, af_force_command);
cmd = ob->cmd;
expand_arguments = TRUE;
if (addr->host_list != NULL)
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)
envp[envcount++] = string_sprintf("TZ=%s", timezone_string);
}
}
-while ((ss = string_nextinlist(&envlist, &envsep, big_buffer, big_buffer_size))
- != NULL)
+while ((ss = string_nextinlist(&envlist, &envsep, big_buffer, big_buffer_size)))
{
- if (envcount > sizeof(envp)/sizeof(uschar *) - 2)
+ if (envcount > nelem(envp) - 2)
{
addr->transport_return = DEFER;
addr->message = string_sprintf("too many environment settings for "
/* If the -N option is set, can't do any more. */
-if (dont_deliver)
+if (f.dont_deliver)
{
DEBUG(D_transport)
debug_printf("*** delivery by %s transport bypassed by -N option",
strerror(errno));
return FALSE;
}
+tctx.u.fd = fd_in;
/* Now fork a process to handle the output that comes down the pipe. */
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.) */
-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");
uschar *prefix = expand_string(ob->message_prefix);
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 "
"transport) failed: %s", ob->message_prefix, tblock->name,
expand_string_message);
return FALSE;
}
- if (!transport_write_block(fd_in, prefix, Ustrlen(prefix)))
+ if (!transport_write_block(&tctx, prefix, Ustrlen(prefix), FALSE))
goto END_WRITE;
}
/* Now the actual message */
-if (!transport_write_message(fd_in, &tctx, 0))
+if (!transport_write_message(&tctx, 0))
goto END_WRITE;
/* Now any configured suffix */
uschar *suffix = expand_string(ob->message_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 "
"transport) failed: %s", ob->message_suffix, tblock->name,
expand_string_message);
return FALSE;
}
- if (!transport_write_block(fd_in, suffix, Ustrlen(suffix)))
+ if (!transport_write_block(&tctx, suffix, Ustrlen(suffix), FALSE))
goto END_WRITE;
}
if (errno == ETIMEDOUT)
{
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;
timeout = 1;
}
This prevents the transport_filter timeout message from getting overwritten
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);
kill(outpid, SIGKILL);
the command that was given is a non-existent path). By default this is
treated as just another failure, but if freeze_exec_fail is set, the reaction
is to freeze the message rather than bounce the address. Exim used to signal
- this failure with EX_UNAVAILABLE, which is definined in many systems as
+ this failure with EX_UNAVAILABLE, which is defined in many systems as
#define EX_UNAVAILABLE 69
else if (!ob->ignore_status)
{
uschar *ss;
- int size, ptr, i;
+ gstring * g;
+ int i;
- /* If temp_errors is "*" all codes are temporary. Initializion checks
+ /* If temp_errors is "*" all codes are temporary. Initialization checks
that it's either "*" or a list of numbers. If not "*", scan the list of
temporary failure codes; if any match, the result is DEFER. */
addr->message = string_sprintf("Child process of %s transport returned "
"%d", tblock->name, rc);
-
- ptr = Ustrlen(addr->message);
- size = ptr + 1;
+ g = string_cat(NULL, addr->message);
/* If the return code is > 128, it often means that a shell command
was terminated by a signal. */
if (*ss != 0)
{
- addr->message = string_catn(addr->message, &size, &ptr, US" ", 1);
- addr->message = string_cat (addr->message, &size, &ptr, ss);
+ g = string_catn(g, US" ", 1);
+ g = string_cat (g, ss);
}
/* Now add the command and arguments */
- addr->message = string_catn(addr->message, &size, &ptr,
- US" from command:", 14);
+ g = string_catn(g, US" from command:", 14);
for (i = 0; i < sizeof(argv)/sizeof(int *) && argv[i] != NULL; i++)
{
BOOL quote = FALSE;
- addr->message = string_catn(addr->message, &size, &ptr, US" ", 1);
+ g = string_catn(g, US" ", 1);
if (Ustrpbrk(argv[i], " \t") != NULL)
{
quote = TRUE;
- addr->message = string_catn(addr->message, &size, &ptr, US"\"", 1);
+ g = string_catn(g, US"\"", 1);
}
- addr->message = string_cat(addr->message, &size, &ptr, argv[i]);
+ g = string_cat(g, argv[i]);
if (quote)
- addr->message = string_catn(addr->message, &size, &ptr, US"\"", 1);
+ g = string_catn(g, US"\"", 1);
}
/* Add previous filter timeout message, if present. */
if (*tmsg)
- addr->message = string_cat(addr->message, &size, &ptr, tmsg);
+ g = string_cat(g, tmsg);
- addr->message[ptr] = 0; /* Ensure concatenated string terminated */
+ addr->message = string_from_gstring(g);
}
}
}
return FALSE;
}
+#endif /*!MACRO_PREDEF*/
/* End of transport/pipe.c */