git://git.exim.org
/
exim.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
Merge branch 'CHUNKING'
[exim.git]
/
src
/
src
/
transports
/
pipe.c
diff --git
a/src/src/transports/pipe.c
b/src/src/transports/pipe.c
index a681bc42d46960fd3720839bda54a4db072e7ba8..d3841e05021332fcb26a75b2b8d19136bc992dc7 100644
(file)
--- a/
src/src/transports/pipe.c
+++ b/
src/src/transports/pipe.c
@@
-1,10
+1,8
@@
-/* $Cambridge: exim/src/src/transports/pipe.c,v 1.15 2010/06/05 10:04:44 pdp Exp $ */
-
/*************************************************
* Exim - an Internet mail transport agent *
*************************************************/
/*************************************************
* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 20
09
*/
+/* Copyright (c) University of Cambridge 1995 - 20
15
*/
/* See the file NOTICE for conditions of use and distribution. */
/* See the file NOTICE for conditions of use and distribution. */
@@
-39,6
+37,8
@@
optionlist pipe_transport_options[] = {
(void *)offsetof(pipe_transport_options_block, environment) },
{ "escape_string", opt_stringptr,
(void *)offsetof(pipe_transport_options_block, escape_string) },
(void *)offsetof(pipe_transport_options_block, environment) },
{ "escape_string", opt_stringptr,
(void *)offsetof(pipe_transport_options_block, escape_string) },
+ { "force_command", opt_bool,
+ (void *)offsetof(pipe_transport_options_block, force_command) },
{ "freeze_exec_fail", opt_bool,
(void *)offsetof(pipe_transport_options_block, freeze_exec_fail) },
{ "freeze_signal", opt_bool,
{ "freeze_exec_fail", opt_bool,
(void *)offsetof(pipe_transport_options_block, freeze_exec_fail) },
{ "freeze_signal", opt_bool,
@@
-112,6
+112,7
@@
pipe_transport_options_block pipe_transport_option_defaults = {
20480, /* max_output */
60*60, /* timeout */
0, /* options */
20480, /* max_output */
60*60, /* timeout */
0, /* options */
+ FALSE, /* force_command */
FALSE, /* freeze_exec_fail */
FALSE, /* freeze_signal */
FALSE, /* ignore_status */
FALSE, /* freeze_exec_fail */
FALSE, /* freeze_signal */
FALSE, /* ignore_status */
@@
-188,7
+189,7
@@
if (ob->permit_coredump)
if (errno != ENOSYS && errno != ENOTSUP)
#endif
log_write(0, LOG_MAIN,
if (errno != ENOSYS && errno != ENOTSUP)
#endif
log_write(0, LOG_MAIN,
- "delivery setrlimit(RLIMIT_CORE, RLIM
I
_INFINITY) failed: %s",
+ "delivery setrlimit(RLIMIT_CORE, RLIM_INFINITY) failed: %s",
strerror(errno));
}
}
strerror(errno));
}
}
@@
-325,12
+326,12
@@
Returns: TRUE if all went well; otherwise an error will be
*/
static BOOL
*/
static BOOL
-set_up_direct_command(
uschar ***argvptr, uschar *cmd, BOOL expand_arguments
,
- int expand_fail, address_item *addr, uschar *tname,
+set_up_direct_command(
const uschar ***argvptr, uschar *cmd
,
+
BOOL expand_arguments,
int expand_fail, address_item *addr, uschar *tname,
pipe_transport_options_block *ob)
{
BOOL permitted = FALSE;
pipe_transport_options_block *ob)
{
BOOL permitted = FALSE;
-uschar **argv;
+
const
uschar **argv;
uschar buffer[64];
/* Set up "transport <name>" to be put in any error messages, and then
uschar buffer[64];
/* Set up "transport <name>" to be put in any error messages, and then
@@
-352,11
+353,11
@@
argv = *argvptr;
if (ob->allow_commands != NULL)
{
int sep = 0;
if (ob->allow_commands != NULL)
{
int sep = 0;
- uschar *s, *p;
+ const uschar *s;
+ uschar *p;
uschar buffer[256];
uschar buffer[256];
- s = expand_string(ob->allow_commands);
- if (s == NULL)
+ if (!(s = expand_string(ob->allow_commands)))
{
addr->transport_return = DEFER;
addr->message = string_sprintf("failed to expand string \"%s\" "
{
addr->transport_return = DEFER;
addr->message = string_sprintf("failed to expand string \"%s\" "
@@
-364,10
+365,8
@@
if (ob->allow_commands != NULL)
return FALSE;
}
return FALSE;
}
- while ((p = string_nextinlist(&s, &sep, buffer, sizeof(buffer))) != NULL)
- {
+ while ((p = string_nextinlist(&s, &sep, buffer, sizeof(buffer))))
if (Ustrcmp(p, argv[0]) == 0) { permitted = TRUE; break; }
if (Ustrcmp(p, argv[0]) == 0) { permitted = TRUE; break; }
- }
}
/* If permitted is TRUE it means the command was found in the allowed list, and
}
/* If permitted is TRUE it means the command was found in the allowed list, and
@@
-406,7
+405,7
@@
if (argv[0][0] != '/')
{
int sep = 0;
uschar *p;
{
int sep = 0;
uschar *p;
- uschar *listptr = ob->path;
+
const
uschar *listptr = ob->path;
uschar buffer[1024];
while ((p = string_nextinlist(&listptr, &sep, buffer, sizeof(buffer))) != NULL)
uschar buffer[1024];
while ((p = string_nextinlist(&listptr, &sep, buffer, sizeof(buffer))) != NULL)
@@
-452,10
+451,10
@@
Returns: TRUE if all went well; otherwise an error will be
*/
static BOOL
*/
static BOOL
-set_up_shell_command(
uschar ***argvptr, uschar *cmd, BOOL expand_arguments
,
- int expand_fail, address_item *addr, uschar *tname)
+set_up_shell_command(
const uschar ***argvptr, uschar *cmd
,
+
BOOL expand_arguments,
int expand_fail, address_item *addr, uschar *tname)
{
{
-uschar **argv;
+
const
uschar **argv;
*argvptr = argv = store_get((4)*sizeof(uschar *));
*argvptr = argv = store_get((4)*sizeof(uschar *));
@@
-490,11
+489,12
@@
if (expand_arguments)
for (ad = addr; ad != NULL; ad = ad->next)
{
for (ad = addr; ad != NULL; ad = ad->next)
{
- if (ad != addr) string_cat(s, &size, &offset, US" ", 1);
- string_cat(s, &size, &offset, ad->address, Ustrlen(ad->address));
+ /*XXX string_append_listele() ? */
+ if (ad != addr) s = string_catn(s, &size, &offset, US" ", 1);
+ s = string_cat(s, &size, &offset, ad->address);
}
}
- s
tring_cat(s, &size, &offset, q, Ustrlen(q)
);
+ s
= string_cat(s, &size, &offset, q
);
s[offset] = 0;
}
s[offset] = 0;
}
@@
-550,11
+550,18
@@
pipe_transport_options_block *ob =
int timeout = ob->timeout;
BOOL written_ok = FALSE;
BOOL expand_arguments;
int timeout = ob->timeout;
BOOL written_ok = FALSE;
BOOL expand_arguments;
-uschar **argv;
+
const
uschar **argv;
uschar *envp[50];
uschar *envp[50];
-uschar *envlist = ob->environment;
+
const
uschar *envlist = ob->environment;
uschar *cmd, *ss;
uschar *cmd, *ss;
-uschar *eol = (ob->use_crlf)? US"\r\n" : US"\n";
+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 */
+};
DEBUG(D_transport) debug_printf("%s transport entered\n", tblock->name);
DEBUG(D_transport) debug_printf("%s transport entered\n", tblock->name);
@@
-571,10
+578,21
@@
options. */
if (testflag(addr, af_pfr) && addr->local_part[0] == '|')
{
if (testflag(addr, af_pfr) && addr->local_part[0] == '|')
{
- cmd = addr->local_part + 1;
- while (isspace(*cmd)) cmd++;
- expand_arguments = testflag(addr, af_expand_pipe);
- expand_fail = FAIL;
+ if (ob->force_command)
+ {
+ /* Enables expansion of $address_pipe into seperate arguments */
+ setflag(addr, af_force_command);
+ cmd = ob->cmd;
+ expand_arguments = TRUE;
+ expand_fail = PANIC;
+ }
+ else
+ {
+ cmd = addr->local_part + 1;
+ while (isspace(*cmd)) cmd++;
+ expand_arguments = testflag(addr, af_expand_pipe);
+ expand_fail = FAIL;
+ }
}
else
{
}
else
{
@@
-583,9
+601,12
@@
else
expand_fail = PANIC;
}
expand_fail = PANIC;
}
-/* If no command has been supplied, we are in trouble. */
+/* If no command has been supplied, we are in trouble.
+ * We also check for an empty string since it may be
+ * coming from addr->local_part[0] == '|'
+ */
-if (cmd == NULL)
+if (cmd == NULL
|| *cmd == '\0'
)
{
addr->transport_return = DEFER;
addr->message = string_sprintf("no command specified for %s transport",
{
addr->transport_return = DEFER;
addr->message = string_sprintf("no command specified for %s transport",
@@
-654,9
+675,9
@@
else if (timezone_string != NULL && timezone_string[0] != 0)
/* Add any requested items */
/* Add any requested items */
-if (envlist
!= NULL
)
+if (envlist)
{
{
- envlist = expand_string(envlist);
+ envlist = expand_
c
string(envlist);
if (envlist == NULL)
{
addr->transport_return = DEFER;
if (envlist == NULL)
{
addr->transport_return = DEFER;
@@
-714,7
+735,7
@@
reading of the output pipe. */
uid/gid and current directory. Request that the new process be a process group
leader, so we can kill it and all its children on a timeout. */
uid/gid and current directory. Request that the new process be a process group
leader, so we can kill it and all its children on a timeout. */
-if ((pid = child_open(argv, envp, ob->umask, &fd_in, &fd_out, TRUE)) < 0)
+if ((pid = child_open(
USS
argv, envp, ob->umask, &fd_in, &fd_out, TRUE)) < 0)
{
addr->transport_return = DEFER;
addr->message = string_sprintf(
{
addr->transport_return = DEFER;
addr->message = string_sprintf(
@@
-751,14
+772,19
@@
if (outpid == 0)
while ((rc = read(fd_out, big_buffer, big_buffer_size)) > 0)
{
if (addr->return_file >= 0)
while ((rc = read(fd_out, big_buffer, big_buffer_size)) > 0)
{
if (addr->return_file >= 0)
- write(addr->return_file, big_buffer, rc);
+ if(write(addr->return_file, big_buffer, rc) != rc)
+ DEBUG(D_transport) debug_printf("Problem writing to return_file\n");
count += rc;
if (count > ob->max_output)
{
count += rc;
if (count > ob->max_output)
{
- uschar *message = US"\n\n*** Too much output - remainder discarded ***\n";
DEBUG(D_transport) debug_printf("Too much output from pipe - killed\n");
if (addr->return_file >= 0)
DEBUG(D_transport) debug_printf("Too much output from pipe - killed\n");
if (addr->return_file >= 0)
- write(addr->return_file, message, Ustrlen(message));
+ {
+ uschar *message = US"\n\n*** Too much output - remainder discarded ***\n";
+ rc = Ustrlen(message);
+ if(write(addr->return_file, message, rc) != rc)
+ DEBUG(D_transport) debug_printf("Problem writing to return_file\n");
+ }
killpg(pid, SIGKILL);
break;
}
killpg(pid, SIGKILL);
break;
}
@@
-823,23
+849,19
@@
if (ob->use_bsmtp)
if (!transport_write_string(fd_in, "MAIL FROM:<%s>%s", return_path, eol))
goto END_WRITE;
if (!transport_write_string(fd_in, "MAIL FROM:<%s>%s", return_path, eol))
goto END_WRITE;
- for (a = addr; a != NULL; a = a->next)
- {
+ for (a = addr; a; a = a->next)
if (!transport_write_string(fd_in,
"RCPT TO:<%s>%s",
transport_rcpt_address(a, tblock->rcpt_include_affixes),
eol))
goto END_WRITE;
if (!transport_write_string(fd_in,
"RCPT TO:<%s>%s",
transport_rcpt_address(a, tblock->rcpt_include_affixes),
eol))
goto END_WRITE;
- }
if (!transport_write_string(fd_in, "DATA%s", eol)) goto END_WRITE;
}
if (!transport_write_string(fd_in, "DATA%s", eol)) goto END_WRITE;
}
-/* Now the actual message
- the options were set at initialization time
*/
+/* Now the actual message */
-if (!transport_write_message(addr, fd_in, ob->options, 0, tblock->add_headers,
- tblock->remove_headers, ob->check_string, ob->escape_string,
- tblock->rewrite_rules, tblock->rewrite_existflags))
+if (!transport_write_message(fd_in, &tctx, 0))
goto END_WRITE;
/* Now any configured suffix */
goto END_WRITE;
/* Now any configured suffix */
@@
-1053,16
+1075,14
@@
if ((rc = child_close(pid, timeout)) != 0)
else
{
else
{
- uschar *s = ob->temp_errors;
+
const
uschar *s = ob->temp_errors;
uschar *p;
uschar buffer[64];
int sep = 0;
addr->transport_return = FAIL;
uschar *p;
uschar buffer[64];
int sep = 0;
addr->transport_return = FAIL;
- while ((p = string_nextinlist(&s,&sep,buffer,sizeof(buffer))) != NULL)
- {
+ while ((p = string_nextinlist(&s,&sep,buffer,sizeof(buffer))))
if (rc == Uatoi(p)) { addr->transport_return = DEFER; break; }
if (rc == Uatoi(p)) { addr->transport_return = DEFER; break; }
- }
}
/* Ensure the message contains the expanded command and arguments. This
}
/* Ensure the message contains the expanded command and arguments. This
@@
-1084,36
+1104,33
@@
if ((rc = child_close(pid, timeout)) != 0)
if (*ss != 0)
{
if (*ss != 0)
{
- addr->message = string_cat(addr->message, &size, &ptr, US" ", 1);
- addr->message = string_cat(addr->message, &size, &ptr,
- ss, Ustrlen(ss));
+ addr->message = string_catn(addr->message, &size, &ptr, US" ", 1);
+ addr->message = string_cat (addr->message, &size, &ptr, ss);
}
/* Now add the command and arguments */
}
/* Now add the command and arguments */
- addr->message = string_cat(addr->message, &size, &ptr,
+ addr->message = string_cat
n
(addr->message, &size, &ptr,
US" from command:", 14);
for (i = 0; i < sizeof(argv)/sizeof(int *) && argv[i] != NULL; i++)
{
BOOL quote = FALSE;
US" from command:", 14);
for (i = 0; i < sizeof(argv)/sizeof(int *) && argv[i] != NULL; i++)
{
BOOL quote = FALSE;
- addr->message = string_cat(addr->message, &size, &ptr, US" ", 1);
+ addr->message = string_cat
n
(addr->message, &size, &ptr, US" ", 1);
if (Ustrpbrk(argv[i], " \t") != NULL)
{
quote = TRUE;
if (Ustrpbrk(argv[i], " \t") != NULL)
{
quote = TRUE;
- addr->message = string_cat(addr->message, &size, &ptr, US"\"", 1);
+ addr->message = string_cat
n
(addr->message, &size, &ptr, US"\"", 1);
}
}
- addr->message = string_cat(addr->message, &size, &ptr, argv[i],
- Ustrlen(argv[i]));
+ addr->message = string_cat(addr->message, &size, &ptr, argv[i]);
if (quote)
if (quote)
- addr->message = string_cat(addr->message, &size, &ptr, US"\"", 1);
+ addr->message = string_cat
n
(addr->message, &size, &ptr, US"\"", 1);
}
/* Add previous filter timeout message, if present. */
}
/* Add previous filter timeout message, if present. */
- if (*tmsg != 0)
- addr->message = string_cat(addr->message, &size, &ptr, tmsg,
- Ustrlen(tmsg));
+ if (*tmsg)
+ addr->message = string_cat(addr->message, &size, &ptr, tmsg);
addr->message[ptr] = 0; /* Ensure concatenated string terminated */
}
addr->message[ptr] = 0; /* Ensure concatenated string terminated */
}