{ "received_ip_address", vtype_stringptr, &interface_address },
{ "received_port", vtype_int, &interface_port },
{ "received_protocol", vtype_stringptr, &received_protocol },
- { "received_time", vtype_int, &received_time },
+ { "received_time", vtype_int, &received_time.tv_sec },
{ "recipient_data", vtype_stringptr, &recipient_data },
{ "recipient_verify_failure",vtype_stringptr,&recipient_verify_failure },
{ "recipients", vtype_string_func, &fn_recipients },
{ "smtp_active_hostname", vtype_stringptr, &smtp_active_hostname },
{ "smtp_command", vtype_stringptr, &smtp_cmd_buffer },
{ "smtp_command_argument", vtype_stringptr, &smtp_cmd_argument },
+ { "smtp_command_history", vtype_string_func, &smtp_cmd_hist },
{ "smtp_count_at_connection_start", vtype_int, &smtp_accept_count },
{ "smtp_notquit_reason", vtype_stringptr, &smtp_notquit_reason },
{ "sn0", vtype_filter_int, &filter_sn[0] },
/* If value2 is unset, just compute one number */
if (value2 < 0)
- {
s = string_sprintf("%d", total % value1);
- }
/* Otherwise do a div/mod hash */
int size = 0;
header_line *h;
- for (h = header_list; size < header_insert_maxlen && h != NULL; h = h->next)
- {
- if (h->type != htype_old && h->text != NULL) /* NULL => Received: placeholder */
- {
- if (name == NULL || (len <= h->slen && strncmpic(name, h->text, len) == 0))
+ for (h = header_list; size < header_insert_maxlen && h; h = h->next)
+ if (h->type != htype_old && h->text) /* NULL => Received: placeholder */
+ if (!name || (len <= h->slen && strncmpic(name, h->text, len) == 0))
{
int ilen;
uschar *t;
that contains an address list, except when asked for raw headers. Only
need to do this once. */
- if (!want_raw && name != NULL && comma == 0 &&
+ if (!want_raw && name && comma == 0 &&
Ustrchr("BCFRST", h->type) != NULL)
comma = 1;
}
}
}
- }
- }
/* At end of first pass, return NULL if no header found. Then truncate size
if necessary, and get the buffer to hold the data, returning the buffer size.
/* That's all we do for raw header expansion. */
if (want_raw)
- {
*ptr = 0;
- }
/* Otherwise, remove a final newline and a redundant added comma. Then we do
RFC 2047 decoding, translating the charset if requested. The rfc2047_decode2()
case vtype_msgbody: /* Pointer to msgbody string */
case vtype_msgbody_end: /* Ditto, the end of the msg */
ss = (uschar **)(val);
- if (*ss == NULL && deliver_datafile >= 0) /* Read body when needed */
+ if (!*ss && deliver_datafile >= 0) /* Read body when needed */
{
uschar *body;
off_t start_offset = SPOOL_DATA_START_OFFSET;
{ if (body[--len] == '\n' || body[len] == 0) body[len] = ' '; }
}
}
- return (*ss == NULL)? US"" : *ss;
+ return *ss ? *ss : US"";
case vtype_todbsdin: /* BSD inbox time of day */
return tod_stamp(tod_bsdin);
while (isspace(*s)) s++;
if (*s == '}')
{
- if (!skipping)
- if (type[0] == 'i')
- {
- if (yes) *yieldptr = string_catn(*yieldptr, sizeptr, ptrptr, US"true", 4);
- }
- else
- {
- if (yes && lookup_value)
- *yieldptr = string_cat(*yieldptr, sizeptr, ptrptr, lookup_value);
- lookup_value = save_lookup;
- }
+ if (type[0] == 'i')
+ {
+ if (yes && !skipping)
+ *yieldptr = string_catn(*yieldptr, sizeptr, ptrptr, US"true", 4);
+ }
+ else
+ {
+ if (yes && lookup_value && !skipping)
+ *yieldptr = string_cat(*yieldptr, sizeptr, ptrptr, lookup_value);
+ lookup_value = save_lookup;
+ }
s++;
goto RETURN;
}
expand_level++;
DEBUG(D_expand)
- debug_printf_indent("/%s: %s\n", skipping ? " scanning" : "considering", string);
+ debug_printf_indent(UTF8_DOWN_RIGHT "%s: %s\n",
+ skipping
+ ? UTF8_HORIZ UTF8_HORIZ UTF8_HORIZ "scanning"
+ : "considering",
+ string);
expand_string_forcedfail = FALSE;
expand_string_message = US"";
DEBUG(D_expand)
{
- debug_printf_indent("|__condition: %.*s\n", (int)(next_s - s), s);
- debug_printf_indent("|_____result: %s\n", cond ? "true" : "false");
+ debug_printf_indent(UTF8_VERT_RIGHT UTF8_HORIZ UTF8_HORIZ
+ "condition: %.*s\n",
+ (int)(next_s - s), s);
+ debug_printf_indent(UTF8_VERT_RIGHT UTF8_HORIZ UTF8_HORIZ
+ UTF8_HORIZ UTF8_HORIZ UTF8_HORIZ
+ "result: %s\n",
+ cond ? "true" : "false");
}
s = next_s;
struct sockaddr_un sockun; /* don't call this "sun" ! */
uschar *arg;
uschar *sub_arg[4];
+ BOOL do_shutdown = TRUE;
- if ((expand_forbid & RDO_READSOCK) != 0)
+ if (expand_forbid & RDO_READSOCK)
{
expand_string_message = US"socket insertions are not permitted";
goto EXPAND_FAILED;
case 3: goto EXPAND_FAILED;
}
- /* Sort out timeout, if given */
+ /* Sort out timeout, if given. The second arg is a list with the first element
+ being a time value. Any more are options of form "name=value". Currently the
+ only option recognised is "shutdown". */
- if (sub_arg[2] != NULL)
+ if (sub_arg[2])
{
- timeout = readconf_readtime(sub_arg[2], 0, FALSE);
- if (timeout < 0)
+ const uschar * list = sub_arg[2];
+ uschar * item;
+ int sep = 0;
+
+ item = string_nextinlist(&list, &sep, NULL, 0);
+ if ((timeout = readconf_readtime(item, 0, FALSE)) < 0)
{
- expand_string_message = string_sprintf("bad time value %s",
- sub_arg[2]);
+ expand_string_message = string_sprintf("bad time value %s", item);
goto EXPAND_FAILED;
}
+
+ while ((item = string_nextinlist(&list, &sep, NULL, 0)))
+ if (Ustrncmp(item, US"shutdown=", 9) == 0)
+ if (Ustrcmp(item + 9, US"no") == 0)
+ do_shutdown = FALSE;
}
else sub_arg[3] = NULL; /* No eol if no timeout */
recognise that it is their turn to do some work. Just in case some
system doesn't have this function, make it conditional. */
- #ifdef SHUT_WR
- shutdown(fd, SHUT_WR);
- #endif
+#ifdef SHUT_WR
+ if (do_shutdown) shutdown(fd, SHUT_WR);
+#endif
if (running_in_test_harness) millisleep(100);
while (isspace(*s)) s++;
}
- readsock_done:
+ READSOCK_DONE:
if (*s++ != '}')
{
expand_string_message = US"missing '}' closing readsocket";
socket, or timeout on reading. If another substring follows, expand and
use it. Otherwise, those conditions give expand errors. */
- SOCK_FAIL:
+ SOCK_FAIL:
if (*s != '{') goto EXPAND_FAILED;
DEBUG(D_any) debug_printf("%s\n", expand_string_message);
if (!(arg = expand_string_internal(s+1, TRUE, &s, FALSE, TRUE, &resetok)))
goto EXPAND_FAILED_CURLY;
}
while (isspace(*s)) s++;
- goto readsock_done;
+ goto READSOCK_DONE;
}
/* Handle "run" to execute a program. */
processing for real, we perform the iteration. */
if (skipping) continue;
- while ((iterate_item = string_nextinlist(&list, &sep, NULL, 0)) != NULL)
+ while ((iterate_item = string_nextinlist(&list, &sep, NULL, 0)))
{
*outsep = (uschar)sep; /* Separator as a string */
- DEBUG(D_expand) debug_printf_indent("%s: $item = \"%s\"\n", name, iterate_item);
+ DEBUG(D_expand) debug_printf_indent("%s: $item = '%s' $value = '%s'\n",
+ name, iterate_item, lookup_value);
if (item_type == EITEM_FILTER)
{
{
uschar * dstitem;
uschar * newlist = NULL;
+ int size = 0, len = 0;
uschar * newkeylist = NULL;
+ int ksize = 0, klen = 0;
uschar * srcfield;
DEBUG(D_expand) debug_printf_indent("%s: $item = \"%s\"\n", name, srcitem);
/* New-item sorts before this dst-item. Append new-item,
then dst-item, then remainder of dst list. */
- newlist = string_append_listele(newlist, sep, srcitem);
- newkeylist = string_append_listele(newkeylist, sep, srcfield);
+ newlist = string_append_listele(newlist, &size, &len, sep, srcitem);
+ newkeylist = string_append_listele(newkeylist, &ksize, &klen, sep, srcfield);
srcitem = NULL;
- newlist = string_append_listele(newlist, sep, dstitem);
- newkeylist = string_append_listele(newkeylist, sep, dstfield);
+ newlist = string_append_listele(newlist, &size, &len, sep, dstitem);
+ newkeylist = string_append_listele(newkeylist, &ksize, &klen, sep, dstfield);
while ((dstitem = string_nextinlist(&dstlist, &sep, NULL, 0)))
{
if (!(dstfield = string_nextinlist(&dstkeylist, &sep, NULL, 0)))
goto sort_mismatch;
- newlist = string_append_listele(newlist, sep, dstitem);
- newkeylist = string_append_listele(newkeylist, sep, dstfield);
+ newlist = string_append_listele(newlist, &size, &len, sep, dstitem);
+ newkeylist = string_append_listele(newkeylist, &ksize, &klen, sep, dstfield);
}
break;
}
- newlist = string_append_listele(newlist, sep, dstitem);
- newkeylist = string_append_listele(newkeylist, sep, dstfield);
+ newlist = string_append_listele(newlist, &size, &len, sep, dstitem);
+ newkeylist = string_append_listele(newkeylist, &ksize, &klen, sep, dstfield);
}
/* If we ran out of dstlist without consuming srcitem, append it */
if (srcitem)
{
- newlist = string_append_listele(newlist, sep, srcitem);
- newkeylist = string_append_listele(newkeylist, sep, srcfield);
+ newlist = string_append_listele(newlist, &size, &len, sep, srcitem);
+ newkeylist = string_append_listele(newkeylist, &ksize, &klen, sep, srcfield);
}
dstlist = newlist;
blob b;
char st[3];
- if (!exim_sha_init(&h, HASH_SHA256))
+ if (!exim_sha_init(&h, HASH_SHA2_256))
{
expand_string_message = US"unrecognised sha256 variant";
goto EXPAND_FAILED;
char * cp;
char tok[3];
tok[0] = sep; tok[1] = ':'; tok[2] = 0;
- while ((cp= strpbrk((const char *)item, tok)))
+ while ((cp= strpbrk(CCS item, tok)))
{
- yield = string_catn(yield, &size, &ptr, item, cp-(char *)item);
+ yield = string_catn(yield, &size, &ptr, item, cp-CS item);
if (*cp++ == ':') /* colon in a non-colon-sep list item, needs doubling */
{
yield = string_catn(yield, &size, &ptr, US"::", 2);
- item = (uschar *)cp;
+ item = US cp;
}
else /* sep in item; should already be doubled; emit once */
{
- yield = string_catn(yield, &size, &ptr, (uschar *)tok, 1);
+ yield = string_catn(yield, &size, &ptr, US tok, 1);
if (*cp == sep) cp++;
- item = (uschar *)cp;
+ item = US cp;
}
}
}
DEBUG(D_expand)
{
- debug_printf_indent("|__expanding: %.*s\n", (int)(s - string), string);
- debug_printf_indent("%s_____result: %s\n", skipping ? "|" : "\\", yield);
- if (skipping) debug_printf_indent("\\___skipping: result is not used\n");
+ debug_printf_indent(UTF8_VERT_RIGHT UTF8_HORIZ UTF8_HORIZ
+ "expanding: %.*s\n",
+ (int)(s - string), string);
+ debug_printf_indent("%s"
+ UTF8_HORIZ UTF8_HORIZ UTF8_HORIZ UTF8_HORIZ UTF8_HORIZ
+ "result: %s\n",
+ skipping ? UTF8_VERT_RIGHT : UTF8_UP_RIGHT,
+ yield);
+ if (skipping)
+ debug_printf_indent(UTF8_UP_RIGHT UTF8_HORIZ UTF8_HORIZ UTF8_HORIZ
+ "skipping: result is not used\n");
}
expand_level--;
return yield;
if (left != NULL) *left = s;
DEBUG(D_expand)
{
- debug_printf_indent("|failed to expand: %s\n", string);
- debug_printf_indent("%s___error message: %s\n",
- expand_string_forcedfail ? "|" : "\\", expand_string_message);
- if (expand_string_forcedfail) debug_printf_indent("\\failure was forced\n");
+ debug_printf_indent(UTF8_VERT_RIGHT "failed to expand: %s\n",
+ string);
+ debug_printf_indent("%s" UTF8_HORIZ UTF8_HORIZ UTF8_HORIZ
+ "error message: %s\n",
+ expand_string_forcedfail ? UTF8_VERT_RIGHT : UTF8_UP_RIGHT,
+ expand_string_message);
+ if (expand_string_forcedfail)
+ debug_printf_indent(UTF8_UP_RIGHT "failure was forced\n");
}
if (resetok_p) *resetok_p = resetok;
expand_level--;