{ "local_part", vtype_stringptr, &deliver_localpart },
{ "local_part_data", vtype_stringptr, &deliver_localpart_data },
{ "local_part_prefix", vtype_stringptr, &deliver_localpart_prefix },
+ { "local_part_prefix_v", vtype_stringptr, &deliver_localpart_prefix_v },
{ "local_part_suffix", vtype_stringptr, &deliver_localpart_suffix },
+ { "local_part_suffix_v", vtype_stringptr, &deliver_localpart_suffix_v },
{ "local_part_verified", vtype_stringptr, &deliver_localpart_verified },
#ifdef HAVE_LOCAL_SCAN
{ "local_scan_data", vtype_stringptr, &local_scan_data },
#ifndef EXIM_HAVE_ABSTRACT_UNIX_SOCKETS
uschar * sname;
#endif
+fd_set fds;
+struct timeval tv;
if ((fd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0)
{
#endif
if (connect(fd, (const struct sockaddr *)&sa_un, len) < 0)
- { where = US"connect"; goto bad; }
+ { where = US"connect"; goto bad2; }
buf[0] = NOTIFY_QUEUE_SIZE_REQ;
if (send(fd, buf, 1, 0) < 0) { where = US"send"; goto bad; }
-if ((len = recv(fd, buf, sizeof(buf), 0)) < 0) { where = US"recv"; goto bad; }
+FD_ZERO(&fds); FD_SET(fd, &fds);
+tv.tv_sec = 2; tv.tv_usec = 0;
+if (select(fd + 1, (SELECT_ARG2_TYPE *)&fds, NULL, NULL, &tv) != 1)
+ {
+ DEBUG(D_expand) debug_printf("no daemon response; using local evaluation\n");
+ len = snprintf(CS buf, sizeof(buf), "%u", queue_count_cached());
+ }
+else if ((len = recv(fd, buf, sizeof(buf), 0)) < 0)
+ { where = US"recv"; goto bad2; }
close(fd);
#ifndef EXIM_HAVE_ABSTRACT_UNIX_SOCKETS
#endif
return string_copyn(buf, len);
+bad2:
+#ifndef EXIM_HAVE_ABSTRACT_UNIX_SOCKETS
+ Uunlink(sname);
+#endif
bad:
close(fd);
DEBUG(D_expand) debug_printf(" %s: %s\n", where, strerror(errno));
{
client_conn_ctx cctx;
int timeout = 5;
- int save_ptr = yield->ptr;
+ int save_ptr = gstring_length(yield);
FILE * fp = NULL;
uschar * arg;
uschar * sub_arg[4];
if (sigalrm_seen)
{
- yield->ptr = save_ptr;
+ if (yield) yield->ptr = save_ptr;
expand_string_message = US "socket read timed out";
goto SOCK_FAIL;
}
case EITEM_TR:
{
- int oldptr = yield->ptr;
+ int oldptr = gstring_length(yield);
int o2m;
uschar *sub[3];
case EITEM_REDUCE:
{
int sep = 0;
- int save_ptr = yield->ptr;
+ int save_ptr = gstring_length(yield);
uschar outsep[2] = { '\0', '\0' };
const uschar *list, *expr, *temp;
uschar *save_iterate_item = iterate_item;
item of the output list, add in a space if the new item begins with the
separator character, or is an empty string. */
- if (yield->ptr != save_ptr && (temp[0] == *outsep || temp[0] == 0))
+ if ( yield && yield->ptr != save_ptr
+ && (temp[0] == *outsep || temp[0] == 0))
yield = string_catn(yield, US" ", 1);
/* Add the string in "temp" to the output list that we are building,
the redundant final separator. Even though an empty item at the end of a
list does not count, this is tidier. */
- else if (yield->ptr != save_ptr) yield->ptr--;
+ else if (yield && yield->ptr != save_ptr) yield->ptr--;
/* Restore preserved $item */
{
uschar outsep[2] = { ':', '\0' };
uschar *address, *error;
- int save_ptr = yield->ptr;
+ int save_ptr = gstring_length(yield);
int start, end, domain; /* Not really used */
while (isspace(*sub)) sub++;
if (address)
{
- if (yield->ptr != save_ptr && address[0] == *outsep)
+ if (yield && yield->ptr != save_ptr && address[0] == *outsep)
yield = string_catn(yield, US" ", 1);
for (;;)
/* If we have generated anything, remove the redundant final
separator. */
- if (yield->ptr != save_ptr) yield->ptr--;
+ if (yield && yield->ptr != save_ptr) yield->ptr--;
f.parse_allow_group = FALSE;
continue;
}