*************************************************/
/* Copyright (c) University of Cambridge 1995 - 2018 */
-/* Copyright (c) The Exim Maintainers 2020 */
+/* Copyright (c) The Exim Maintainers 2020 - 2021 */
/* See the file NOTICE for conditions of use and distribution. */
/* General functions concerned with transportation, and generic options for all
for(;;)
{
- fd_set fds;
/* This code makes use of alarm() in order to implement the timeout. This
isn't a very tidy way of doing things. Using non-blocking I/O with select()
provides a neater approach. However, I don't know how to do this when TLS is
if (rc >= 0 || errno != ENOTCONN || connretry <= 0)
break;
- FD_ZERO(&fds); FD_SET(fd, &fds);
- select(fd+1, NULL, &fds, NULL, NULL); /* could set timout? */
+ poll_one_fd(fd, POLLOUT, -1); /* could set timeout? retval check? */
connretry--;
}
for (ppp = *pdlist; ppp; ppp = ppp->next) if (p == ppp->ptr) return TRUE;
-ppp = store_get(sizeof(struct aci), FALSE);
+ppp = store_get(sizeof(struct aci), GET_UNTAINTED);
ppp->next = *pdlist;
*pdlist = ppp;
ppp->ptr = p;
/* Remember what we have output, and output it. */
-ppp = store_get(sizeof(struct aci), FALSE);
+ppp = store_get(sizeof(struct aci), GET_UNTAINTED);
ppp->next = *pplist;
*pplist = ppp;
ppp->ptr = pp;
yield = FALSE;
}
else if (!ok)
- {
+ { /* Try to drain the pipe; read fails are don't care */
int dummy = read(pfd[pipe_read], (void *)&save_errno, sizeof(int));
dummy = read(pfd[pipe_read], (void *)&tctx->addr->more_errno, sizeof(int));
dummy = read(pfd[pipe_read], (void *)&tctx->addr->delivery_time, sizeof(struct timeval));
if (!(host_record = dbfn_read(dbm_file, host->name)))
{
- host_record = store_get(sizeof(dbdata_wait) + MESSAGE_ID_LENGTH, FALSE);
+ host_record = store_get(sizeof(dbdata_wait) + MESSAGE_ID_LENGTH, GET_UNTAINTED);
host_record->count = host_record->sequence = 0;
}
else
{
dbdata_wait *newr =
- store_get(sizeof(dbdata_wait) + host_length + MESSAGE_ID_LENGTH, FALSE);
+ store_get(sizeof(dbdata_wait) + host_length + MESSAGE_ID_LENGTH, GET_UNTAINTED);
memcpy(newr, host_record, sizeof(dbdata_wait) + host_length);
host_record = newr;
}
/* create an array to read entire message queue into memory for processing */
- msgq = store_get(sizeof(msgq_t) * host_record->count, FALSE);
+ msgq = store_get(sizeof(msgq_t) * host_record->count, GET_UNTAINTED);
msgq_count = host_record->count;
msgq_actual = msgq_count;
DEBUG(D_exec) debug_print_argv(argv);
exim_nullstd(); /* Ensure std{out,err} exist */
+/* argv[0] should be untainted, from child_exec_exim() */
execv(CS argv[0], (char *const *)argv);
DEBUG(D_any) debug_printf("execv failed: %s\n", strerror(errno));
BOOL
transport_set_up_command(const uschar ***argvptr, uschar *cmd,
BOOL expand_arguments, int expand_failed, address_item *addr,
- uschar *etext, uschar **errptr)
+ const uschar * etext, uschar ** errptr)
{
const uschar **argv;
uschar *s, *ss;
for (address_item * ad = addr; ad; ad = ad->next) address_count++;
max_args = address_count + 60;
-*argvptr = argv = store_get((max_args+1)*sizeof(uschar *), FALSE);
+*argvptr = argv = store_get((max_args+1)*sizeof(uschar *), GET_UNTAINTED);
/* Split the command up into arguments terminated by white space. Lose
trailing space at the start and end. Double-quoted arguments can contain \\ and
s = cmd;
while (isspace(*s)) s++;
-for (; *s != 0 && argcount < max_args; argcount++)
+for (; *s && argcount < max_args; argcount++)
{
if (*s == '\'')
{
ss = s + 1;
- while (*ss != 0 && *ss != '\'') ss++;
- argv[argcount] = ss = store_get(ss - s++, is_tainted(cmd));
- while (*s != 0 && *s != '\'') *ss++ = *s++;
- if (*s != 0) s++;
+ while (*ss && *ss != '\'') ss++;
+ argv[argcount] = ss = store_get(ss - s++, cmd);
+ while (*s && *s != '\'') *ss++ = *s++;
+ if (*s) s++;
*ss++ = 0;
}
else
while (isspace(*s)) s++;
}
-argv[argcount] = US 0;
+argv[argcount] = NULL;
/* If *s != 0 we have run out of argument slots. */
-if (*s != 0)
+if (*s)
{
uschar *msg = string_sprintf("Too many arguments in command \"%s\" in "
"%s", cmd, etext);
if (expand_arguments)
{
- BOOL allow_dollar_recipients = addr != NULL &&
- addr->parent != NULL &&
- Ustrcmp(addr->parent->address, "system-filter") == 0;
+ BOOL allow_dollar_recipients = addr && addr->parent
+ && Ustrcmp(addr->parent->address, "system-filter") == 0;
- for (int i = 0; argv[i] != US 0; i++)
+ for (int i = 0; argv[i]; i++)
{
-
/* Handle special fudge for passing an address list */
- if (addr != NULL &&
+ if (addr &&
(Ustrcmp(argv[i], "$pipe_addresses") == 0 ||
Ustrcmp(argv[i], "${pipe_addresses}") == 0))
{
/* Handle special case of $address_pipe when af_force_command is set */
- else if (addr != NULL && testflag(addr,af_force_command) &&
+ else if (addr && testflag(addr,af_force_command) &&
(Ustrcmp(argv[i], "$address_pipe") == 0 ||
Ustrcmp(argv[i], "${address_pipe}") == 0))
{
int address_pipe_argcount = 0;
int address_pipe_max_args;
uschar **address_pipe_argv;
- BOOL tainted;
/* We can never have more then the argv we will be loading into */
address_pipe_max_args = max_args - argcount + 1;
debug_printf("address_pipe_max_args=%d\n", address_pipe_max_args);
/* We allocate an additional for (uschar *)0 */
- address_pipe_argv = store_get((address_pipe_max_args+1)*sizeof(uschar *), FALSE);
+ address_pipe_argv = store_get((address_pipe_max_args+1)*sizeof(uschar *), GET_UNTAINTED);
/* +1 because addr->local_part[0] == '|' since af_force_command is set */
s = expand_string(addr->local_part + 1);
- tainted = is_tainted(s);
- if (s == NULL || *s == '\0')
+ if (!s || !*s)
{
addr->transport_return = FAIL;
addr->message = string_sprintf("Expansion of \"%s\" "
while (isspace(*s)) s++; /* strip leading space */
- while (*s != 0 && address_pipe_argcount < address_pipe_max_args)
+ while (*s && address_pipe_argcount < address_pipe_max_args)
{
if (*s == '\'')
{
- ss = s + 1;
- while (*ss != 0 && *ss != '\'') ss++;
- address_pipe_argv[address_pipe_argcount++] = ss = store_get(ss - s++, tainted);
- while (*s != 0 && *s != '\'') *ss++ = *s++;
- if (*s != 0) s++;
+ int n;
+ for (ss = s + 1; *ss && *ss != '\''; ) ss++;
+ n = ss - s++;
+ address_pipe_argv[address_pipe_argcount++] = ss = store_get(n, s);
+ while (*s && *s != '\'') *ss++ = *s++;
+ if (*s) s++;
*ss++ = 0;
}
else address_pipe_argv[address_pipe_argcount++] =
while (isspace(*s)) s++; /* strip space after arg */
}
- address_pipe_argv[address_pipe_argcount] = US 0;
+ address_pipe_argv[address_pipe_argcount] = NULL;
/* If *s != 0 we have run out of argument slots. */
- if (*s != 0)
+ if (*s)
{
uschar *msg = string_sprintf("Too many arguments in $address_pipe "
"\"%s\" in %s", addr->local_part + 1, etext);
- if (addr != NULL)
+ if (addr)
{
addr->transport_return = FAIL;
addr->message = msg;
}
/* address_pipe_argcount - 1
- * because we are replacing $address_pipe in the argument list
- * with the first thing it expands to */
+ because we are replacing $address_pipe in the argument list
+ with the first thing it expands to */
+
if (argcount + address_pipe_argcount - 1 > max_args)
{
addr->transport_return = FAIL;
[argv 0][argv 1][argv 2=pipeargv[0]][argv 3=pipeargv[1]][old argv 3][0] */
for (int address_pipe_i = 0;
- address_pipe_argv[address_pipe_i] != US 0;
+ address_pipe_argv[address_pipe_i];
address_pipe_i++, argcount++)
argv[i++] = address_pipe_argv[address_pipe_i];
DEBUG(D_transport)
{
debug_printf("direct command after expansion:\n");
- for (int i = 0; argv[i] != US 0; i++)
+ for (int i = 0; argv[i]; i++)
debug_printf(" argv[%d] = %s\n", i, string_printing(argv[i]));
}
}
return TRUE;
}
+
+
+/* For error messages, a string describing the config location associated
+with current processing. NULL if we are not in a transport. */
+/* Name only, for now */
+
+uschar *
+transport_current_name(void)
+{
+if (!transport_name) return NULL;
+return string_sprintf(" (transport %s, %s %d)", transport_name, driver_srcfile, driver_srcline);
+}
+
#endif /*!MACRO_PREDEF*/
/* vi: aw ai sw=2
*/