*************************************************/
/* Copyright (c) University of Cambridge 1995 - 2018 */
*************************************************/
/* Copyright (c) University of Cambridge 1995 - 2018 */
/* See the file NOTICE for conditions of use and distribution. */
/* General functions concerned with transportation, and generic options for all
/* See the file NOTICE for conditions of use and distribution. */
/* General functions concerned with transportation, and generic options for all
data blocks and which therefore have the opt_public flag set. Note that there
are other options living inside this structure which can be set only from
certain transports. */
data blocks and which therefore have the opt_public flag set. Note that there
are other options living inside this structure which can be set only from
certain transports. */
optionlist optionlist_transports[] = {
/* name type value */
{ "*expand_group", opt_stringptr|opt_hidden|opt_public,
optionlist optionlist_transports[] = {
/* name type value */
{ "*expand_group", opt_stringptr|opt_hidden|opt_public,
ALARM(local_timeout);
rc = tpt_write(fd, block, len, more, tctx->options);
save_errno = errno;
ALARM(local_timeout);
rc = tpt_write(fd, block, len, more, tctx->options);
save_errno = errno;
return addr->address + Ustrlen(addr->prefix);
}
at = Ustrrchr(addr->address, '@');
return addr->address + Ustrlen(addr->prefix);
}
at = Ustrrchr(addr->address, '@');
slen = Ustrlen(addr->suffix);
return string_sprintf("%.*s@%s", (int)(at - addr->address - plen - slen),
slen = Ustrlen(addr->suffix);
return string_sprintf("%.*s@%s", (int)(at - addr->address - plen - slen),
- if (strncmpic(h->text, s, len) != 0) continue;
- ss = h->text + len;
- while (*ss == ' ' || *ss == '\t') ss++;
- if (*ss == ':') break;
+ if (len && s[len-1] == '*') /* trailing glob */
+ {
+ if (strncmpic(h->text, s, len-1) == 0) break;
+ }
+ else
+ {
+ if (strncmpic(h->text, s, len) != 0) continue;
+ ss = h->text + len;
+ while (*ss == ' ' || *ss == '\t') ss++;
+ if (*ss == ':') break;
+ }
-int rc, len, yield, fd_read, fd_write, save_errno;
+BOOL yield;
+int rc, len, fd_read, fd_write, save_errno;
filter_pid = child_open(USS transport_filter_argv, NULL, 077,
filter_pid = child_open(USS transport_filter_argv, NULL, 077,
- &fd_write, &fd_read, FALSE);
- (void)fcntl(tctx->u.fd, F_SETFD, bits & ~FD_CLOEXEC);
+ &fd_write, &fd_read, FALSE, US"transport-filter");
+ (void) fcntl(tctx->u.fd, F_SETFD, bits & ~FD_CLOEXEC);
smtp dots, or check string processing. */
if (pipe(pfd) != 0) goto TIDY_UP; /* errno set */
smtp dots, or check string processing. */
if (pipe(pfd) != 0) goto TIDY_UP; /* errno set */
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));
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 this record is full, write it out with a new name constructed
from the sequence number, increase the sequence number, and empty
/* If this record is full, write it out with a new name constructed
from the sequence number, increase the sequence number, and empty
if (host_record->count >= WAIT_NAME_MAX)
{
sprintf(CS buffer, "%.200s:%d", host->name, host_record->sequence);
dbfn_write(dbm_file, buffer, host_record, sizeof(dbdata_wait) + host_length);
if (host_record->count >= WAIT_NAME_MAX)
{
sprintf(CS buffer, "%.200s:%d", host->name, host_record->sequence);
dbfn_write(dbm_file, buffer, host_record, sizeof(dbdata_wait) + host_length);
local_message_max maximum number of messages down one connection
as set by the caller transport
new_message_id set to the message id of a waiting message
local_message_max maximum number of messages down one connection
as set by the caller transport
new_message_id set to the message id of a waiting message
oicf_func function to call to validate if it is ok to send
to this message_id from the current instance.
oicf_data opaque data for oicf_func
oicf_func function to call to validate if it is ok to send
to this message_id from the current instance.
oicf_data opaque data for oicf_func
- int local_message_max, uschar *new_message_id, BOOL *more, oicf oicf_func, void *oicf_data)
+ int local_message_max, uschar *new_message_id, oicf oicf_func, void *oicf_data)
DEBUG(D_transport)
{
debug_printf("transport_check_waiting entered\n");
debug_printf(" sequence=%d local_max=%d global_max=%d\n",
continue_sequence, local_message_max, connection_max_messages);
DEBUG(D_transport)
{
debug_printf("transport_check_waiting entered\n");
debug_printf(" sequence=%d local_max=%d global_max=%d\n",
continue_sequence, local_message_max, connection_max_messages);
}
/* Open the waiting information database. */
if (!(dbm_file = dbfn_open(string_sprintf("wait-%.200s", transport_name),
O_RDWR, &dbblock, TRUE, TRUE)))
}
/* Open the waiting information database. */
if (!(dbm_file = dbfn_open(string_sprintf("wait-%.200s", transport_name),
O_RDWR, &dbblock, TRUE, TRUE)))
/* See if there is a record for this host; if not, there's nothing to do. */
if (!(host_record = dbfn_read(dbm_file, hostname)))
{
dbfn_close(dbm_file);
/* See if there is a record for this host; if not, there's nothing to do. */
if (!(host_record = dbfn_read(dbm_file, hostname)))
{
dbfn_close(dbm_file);
dbfn_close(dbm_file);
log_write(0, LOG_MAIN|LOG_PANIC, "smtp-wait database entry for %s has bad "
"count=%d (max=%d)", hostname, host_record->count, WAIT_NAME_MAX);
dbfn_close(dbm_file);
log_write(0, LOG_MAIN|LOG_PANIC, "smtp-wait database entry for %s has bad "
"count=%d (max=%d)", hostname, host_record->count, WAIT_NAME_MAX);
for (i = 0; i < msgq_count; ++i)
if (Ustrcmp(msgq[i].message_id, message_id) == 0)
for (i = 0; i < msgq_count; ++i)
if (Ustrcmp(msgq[i].message_id, message_id) == 0)
dbfn_write(dbm_file, hostname, host_record, (int)sizeof(dbdata_wait) + host_length);
dbfn_write(dbm_file, hostname, host_record, (int)sizeof(dbdata_wait) + host_length);
transport_do_pass_socket(const uschar *transport_name, const uschar *hostname,
const uschar *hostaddress, uschar *id, int socket_fd)
{
transport_do_pass_socket(const uschar *transport_name, const uschar *hostname,
const uschar *hostaddress, uschar *id, int socket_fd)
{
argv[i++] = sending_ip_address;
argv[i++] = string_sprintf("%d", sending_port);
argv[i++] = tls_out.active.sock >= 0 ? tls_out.cipher : continue_proxy_cipher;
argv[i++] = sending_ip_address;
argv[i++] = string_sprintf("%d", sending_port);
argv[i++] = tls_out.active.sock >= 0 ? tls_out.cipher : continue_proxy_cipher;
{
/* Disconnect entirely from the parent process. If we are running in the
test harness, wait for a bit to allow the previous process time to finish,
write the log, etc., so that the output is always in the same order for
automatic comparison. */
{
/* Disconnect entirely from the parent process. If we are running in the
test harness, wait for a bit to allow the previous process time to finish,
write the log, etc., so that the output is always in the same order for
automatic comparison. */
testharness_pause_ms(1000);
transport_do_pass_socket(transport_name, hostname, hostaddress,
testharness_pause_ms(1000);
transport_do_pass_socket(transport_name, hostname, hostaddress,