PP/04 Documentation: current string operators work on bytes, not codepoints.
+JH/21 Change as many as possible of the global flags into one-bit bitfields; these
+ should pack well giving a smaller memory footprint so better caching and
+ therefore performance. Group the declarations where this can't be done so
+ that the byte-sized flag variables are not interspersed among pointer
+ variables, giving a better chance of good packing by the compiler.
+
Exim version 4.91
-----------------
int dsn_ret = 0;
uschar *dsn_envid = NULL;
+struct global_flags f = {
+ .sender_local = FALSE,
+};
+
#ifdef WITH_CONTENT_SCAN
int fake_response = OK;
#endif
uschar *sender_host_name = NULL;
int sender_host_port = 0;
uschar *sender_ident = NULL;
-BOOL sender_local = FALSE;
BOOL sender_set_untrusted = FALSE;
uschar *smtp_active_hostname = NULL;
if (sender_address != NULL)
{
- text_showf(text, "%s sender: <%s>\n", sender_local? "Local" : "Remote",
+ text_showf(text, "%s sender: <%s>\n", f.sender_local ? "Local" : "Remote",
sender_address);
}
}
else
{
- deliver_freeze = FALSE;
+ f.deliver_freeze = FALSE;
sender_address = msg;
recipients_count = 0;
}
/* Now set up the remaining data. */
-q->frozen = deliver_freeze;
+q->frozen = f.deliver_freeze;
-if (sender_set_untrusted)
+if (f.sender_set_untrusted)
{
if (sender_address[0] == 0)
{
/* We can test the result of optional HELO verification that might have
occurred earlier. If not, we can attempt the verification now. */
- if (!helo_verified && !helo_verify_failed) smtp_verify_helo();
- return helo_verified ? OK : FAIL;
+ if (!f.helo_verified && !f.helo_verify_failed) smtp_verify_helo();
+ return f.helo_verified ? OK : FAIL;
case VERIFY_CSA:
/* Do Client SMTP Authorization checks in a separate function, and turn the
{
if (!*user_msgptr && *log_msgptr)
*user_msgptr = string_sprintf("Rejected after DATA: %s", *log_msgptr);
- if (rc == DEFER) acl_temp_details = TRUE;
+ if (rc == DEFER) f.acl_temp_details = TRUE;
}
}
}
addr2.user_message : addr2.message;
/* Allow details for temporary error if the address is so flagged. */
- if (testflag((&addr2), af_pass_message)) acl_temp_details = TRUE;
+ if (testflag((&addr2), af_pass_message)) f.acl_temp_details = TRUE;
/* Make $address_data visible */
deliver_address_data = addr2.prop.address_data;
arg = cb->arg;
else if (!(arg = expand_string(cb->arg)))
{
- if (expand_string_forcedfail) continue;
+ if (f.expand_string_forcedfail) continue;
*log_msgptr = string_sprintf("failed to expand ACL string \"%s\": %s",
cb->arg, expand_string_message);
- return search_find_defer ? DEFER : ERROR;
+ return f.search_find_defer ? DEFER : ERROR;
}
/* Show condition, and expanded condition if it's different */
switch(control_type)
{
case CONTROL_AUTH_UNADVERTISED:
- allow_auth_unadvertised = TRUE;
+ f.allow_auth_unadvertised = TRUE;
break;
#ifdef EXPERIMENTAL_BRIGHTMAIL
#ifndef DISABLE_DKIM
case CONTROL_DKIM_VERIFY:
- dkim_disable_verify = TRUE;
+ f.dkim_disable_verify = TRUE;
#ifdef EXPERIMENTAL_DMARC
/* Since DKIM was blocked, skip DMARC too */
- dmarc_disable_verify = TRUE;
- dmarc_enable_forensic = FALSE;
+ f.dmarc_disable_verify = TRUE;
+ f.dmarc_enable_forensic = FALSE;
#endif
break;
#endif
#ifdef EXPERIMENTAL_DMARC
case CONTROL_DMARC_VERIFY:
- dmarc_disable_verify = TRUE;
+ f.dmarc_disable_verify = TRUE;
break;
case CONTROL_DMARC_FORENSIC:
- dmarc_enable_forensic = TRUE;
+ f.dmarc_enable_forensic = TRUE;
break;
#endif
#ifdef WITH_CONTENT_SCAN
case CONTROL_NO_MBOX_UNSPOOL:
- no_mbox_unspool = TRUE;
+ f.no_mbox_unspool = TRUE;
break;
#endif
case CONTROL_NO_MULTILINE:
- no_multiline_responses = TRUE;
+ f.no_multiline_responses = TRUE;
break;
case CONTROL_NO_PIPELINING:
- pipelining_enable = FALSE;
+ f.pipelining_enable = FALSE;
break;
case CONTROL_NO_DELAY_FLUSH:
- disable_delay_flush = TRUE;
+ f.disable_delay_flush = TRUE;
break;
case CONTROL_NO_CALLOUT_FLUSH:
- disable_callout_flush = TRUE;
+ f.disable_callout_flush = TRUE;
break;
case CONTROL_FAKEREJECT:
break;
case CONTROL_FREEZE:
- deliver_freeze = TRUE;
+ f.deliver_freeze = TRUE;
deliver_frozen_at = time(NULL);
freeze_tell = freeze_tell_config; /* Reset to configured value */
if (Ustrncmp(p, "/no_tell", 8) == 0)
break;
case CONTROL_QUEUE_ONLY:
- queue_only_policy = TRUE;
+ f.queue_only_policy = TRUE;
cancel_cutthrough_connection(TRUE, US"queueing forced");
break;
#endif
case CONTROL_SUBMISSION:
originator_name = US"";
- submission_mode = TRUE;
+ f.submission_mode = TRUE;
while (*p == '/')
{
if (Ustrncmp(p, "/sender_retain", 14) == 0)
{
p += 14;
- active_local_sender_retain = TRUE;
- active_local_from_check = FALSE;
+ f.active_local_sender_retain = TRUE;
+ f.active_local_from_check = FALSE;
}
else if (Ustrncmp(p, "/domain=", 8) == 0)
{
break;
case CONTROL_SUPPRESS_LOCAL_FIXUPS:
- suppress_local_fixups = TRUE;
+ f.suppress_local_fixups = TRUE;
break;
case CONTROL_CUTTHROUGH_DELIVERY:
ignored = US"PRDR active";
else
{
- if (deliver_freeze)
+ if (f.deliver_freeze)
ignored = US"frozen";
- else if (queue_only_policy)
+ else if (f.queue_only_policy)
ignored = US"queue-only";
else if (fake_response == FAIL)
ignored = US"fakereject";
else
{
- if (smtp_out != NULL && !disable_delay_flush)
+ if (smtp_out != NULL && !f.disable_delay_flush)
mac_smtp_fflush();
#if !defined(NO_POLL_H) && defined (POLLRDHUP)
#ifdef EXPERIMENTAL_DMARC
case ACLC_DMARC_STATUS:
- if (!dmarc_has_been_checked)
+ if (!f.dmarc_has_been_checked)
dmarc_process();
- dmarc_has_been_checked = TRUE;
+ f.dmarc_has_been_checked = TRUE;
/* used long way of dmarc_exim_expand_query() in case we need more
* view into the process in the future. */
rc = match_isinlist(dmarc_exim_expand_query(DMARC_VERIFY_STATUS),
expmessage = expand_string(user_message);
if (!expmessage)
{
- if (!expand_string_forcedfail)
+ if (!f.expand_string_forcedfail)
log_write(0, LOG_MAIN|LOG_PANIC, "failed to expand ACL message \"%s\": %s",
user_message, expand_string_message);
}
expmessage = expand_string(log_message);
if (!expmessage)
{
- if (!expand_string_forcedfail)
+ if (!f.expand_string_forcedfail)
log_write(0, LOG_MAIN|LOG_PANIC, "failed to expand ACL message \"%s\": %s",
log_message, expand_string_message);
}
{
if (!(ss = expand_string(s)))
{
- if (expand_string_forcedfail) return OK;
+ if (f.expand_string_forcedfail) return OK;
*log_msgptr = string_sprintf("failed to expand ACL string \"%s\": %s", s,
expand_string_message);
return ERROR;
&& (where == ACL_WHERE_QUIT || where == ACL_WHERE_NOTQUIT);
*log_msgptr = *user_msgptr = NULL;
- acl_temp_details = FALSE;
+ f.acl_temp_details = FALSE;
HDEBUG(D_acl) debug_printf_indent("processing \"%s\"\n", verbs[acl->verb]);
{
if (search_error_message != NULL && *search_error_message != 0)
*log_msgptr = search_error_message;
- if (smtp_return_error_details) acl_temp_details = TRUE;
+ if (smtp_return_error_details) f.acl_temp_details = TRUE;
}
else
- {
- acl_temp_details = TRUE;
- }
+ f.acl_temp_details = TRUE;
if (acl->verb != ACL_WARN) return DEFER;
break;
{
HDEBUG(D_acl) debug_printf_indent("end of %s: DEFER\n", acl_name);
if (acl_quit_check) goto badquit;
- acl_temp_details = TRUE;
+ f.acl_temp_details = TRUE;
return DEFER;
}
break;
return ret;
bad:
-if (expand_string_forcedfail) return ERROR;
+if (f.expand_string_forcedfail) return ERROR;
*log_msgptr = string_sprintf("failed to expand ACL string \"%s\": %s",
tmp, expand_string_message);
-return search_find_defer?DEFER:ERROR;
+return f.search_find_defer ? DEFER : ERROR;
}
case ACL_WHERE_PRDR:
#endif
- if (host_checking_callout) /* -bhc mode */
+ if (f.host_checking_callout) /* -bhc mode */
cancel_cutthrough_connection(TRUE, US"host-checking mode");
else if ( rc == OK
while (*s) s++;
do --s; while (!isdigit(*s));
if (*--s && isdigit(*s) && *--s && isdigit(*s)) *user_msgptr = s;
- acl_temp_details = TRUE;
+ f.acl_temp_details = TRUE;
}
else
{
if (cond == NULL)
{
- if (expand_string_forcedfail) return FAIL;
+ if (f.expand_string_forcedfail) return FAIL;
auth_defer_msg = expand_string_message;
return DEFER;
}
/* If we are running in the test harness, always send the same challenge,
an example string taken from the RFC. */
-if (running_in_test_harness)
+if (f.running_in_test_harness)
challenge = US"<1896.697170952@postoffice.reston.mci.net>";
/* No data should have been sent with the AUTH command */
if (secret == NULL)
{
- if (expand_string_forcedfail) return FAIL;
+ if (f.expand_string_forcedfail) return FAIL;
auth_defer_msg = expand_string_message;
return DEFER;
}
if (!secret || !name)
{
- if (expand_string_forcedfail)
+ if (f.expand_string_forcedfail)
{
*buffer = 0; /* No message */
return CANCELLED;
tmps = CS expand_string(ob->server_password);
if (tmps == NULL) {
- sasl_error_should_defer = expand_string_forcedfail ? FALSE : TRUE;
+ sasl_error_should_defer = f.expand_string_forcedfail ? FALSE : TRUE;
HDEBUG(D_auth) debug_printf("server_password expansion failed, so "
"can't tell GNU SASL library the password for %s\n", auth_vars[0]);
return GSASL_AUTHENTICATION_ERROR;
if (smtp_write_command(outblock, SCMD_FLUSH, "*\r\n") >= 0)
(void) smtp_read_response(inblock, US buffer, buffsize, '2', timeout);
}
- if (expand_string_forcedfail)
+ if (f.expand_string_forcedfail)
{
*buffer = 0; /* No message */
return CANCELLED;
clearpass = expand_string(ob->spa_serverpassword);
if (clearpass == NULL)
{
- if (expand_string_forcedfail)
+ if (f.expand_string_forcedfail)
{
DEBUG(D_auth) debug_printf("auth_spa_server(): forced failure while "
"expanding spa_serverpassword\n");
if (!(username = CS expand_string(ob->spa_username)))
{
- if (expand_string_forcedfail) return CANCELLED;
+ if (f.expand_string_forcedfail) return CANCELLED;
string_format(buffer, buffsize, "expansion of \"%s\" failed in %s "
"authenticator: %s", ob->spa_username, ablock->name,
expand_string_message);
if (!(password = CS expand_string(ob->spa_password)))
{
- if (expand_string_forcedfail) return CANCELLED;
+ if (f.expand_string_forcedfail) return CANCELLED;
string_format(buffer, buffsize, "expansion of \"%s\" failed in %s "
"authenticator: %s", ob->spa_password, ablock->name,
expand_string_message);
{
if (!(domain = CS expand_string(ob->spa_domain)))
{
- if (expand_string_forcedfail) return CANCELLED;
+ if (f.expand_string_forcedfail) return CANCELLED;
string_format(buffer, buffsize, "expansion of \"%s\" failed in %s "
"authenticator: %s", ob->spa_domain, ablock->name,
expand_string_message);
memcpy(argv + n, clmacros, clmacro_count * sizeof(uschar *));
n += clmacro_count;
}
-if (config_changed)
+if (f.config_changed)
{
argv[n++] = US"-C";
argv[n++] = config_main_filename;
if (debug_selector != 0)
argv[n++] = string_sprintf("-d=0x%x", debug_selector);
}
- if (dont_deliver) argv[n++] = US"-N";
- if (queue_smtp) argv[n++] = US"-odqs";
- if (synchronous_delivery) argv[n++] = US"-odi";
+ if (f.dont_deliver) argv[n++] = US"-N";
+ if (f.queue_smtp) argv[n++] = US"-odqs";
+ if (f.synchronous_delivery) argv[n++] = US"-odi";
if (connection_max_messages >= 0)
argv[n++] = string_sprintf("-oB%d", connection_max_messages);
if (*queue_name)
force_fd(pfd[pipe_read], 0);
(void)close(pfd[pipe_write]);
if (debug_fd > 0) force_fd(debug_fd, 2);
- if (running_in_test_harness && !queue_only)
+ if (f.running_in_test_harness && !queue_only)
{
if (sender_authentication != NULL)
child_exec_exim(CEE_EXEC_EXIT, FALSE, NULL, FALSE, 9,
uschar *expanded = expand_string(smtp_accept_max_per_host);
if (expanded == NULL)
{
- if (!expand_string_forcedfail)
+ if (!f.expand_string_forcedfail)
log_write(0, LOG_MAIN|LOG_PANIC, "expansion of smtp_accept_max_per_host "
"failed for %s: %s", whofrom->s, expand_string_message);
}
uschar * nah = expand_string(raw_active_hostname);
if (!nah)
{
- if (!expand_string_forcedfail)
+ if (!f.expand_string_forcedfail)
{
log_write(0, LOG_MAIN|LOG_PANIC, "failed to expand \"%s\" "
"(smtp_active_hostname): %s", raw_active_hostname,
finding the id, but turn it on again afterwards so that information about the
incoming connection is output. */
- if (debug_daemon) debug_selector = 0;
+ if (f.debug_daemon) debug_selector = 0;
verify_get_ident(IDENT_PORT);
host_build_sender_fullhost();
debug_selector = save_debug_selector;
/* Now disable debugging permanently if it's required only for the daemon
process. */
- if (debug_daemon) debug_selector = 0;
+ if (f.debug_daemon) debug_selector = 0;
/* If there are too many child processes for immediate delivery,
set the session_local_queue_only flag, which is initialized from the
{
int r = receive_messagecount;
- BOOL q = queue_only_policy;
+ BOOL q = f.queue_only_policy;
smtp_reset(reset_point);
- queue_only_policy = q;
+ f.queue_only_policy = q;
receive_messagecount = r;
}
If we are not root, we have to re-exec exim unless deliveries are being
done unprivileged. */
- else if (!queue_only_policy && !deliver_freeze)
+ else if (!f.queue_only_policy && !f.deliver_freeze)
{
pid_t dpid;
DEBUG(D_any|D_v) debug_selector |= D_pid;
-if (inetd_wait_mode)
+if (f.inetd_wait_mode)
{
listen_socket_count = 1;
listen_sockets = store_get(sizeof(int));
}
-if (inetd_wait_mode || daemon_listen)
+if (f.inetd_wait_mode || f.daemon_listen)
{
/* If any option requiring a load average to be available during the
reception of a message is set, call os_getloadavg() while we are root
first, so that we can return non-zero if there are any syntax errors, and also
write to stderr. */
-if (daemon_listen && !inetd_wait_mode)
+if (f.daemon_listen && !f.inetd_wait_mode)
{
int *default_smtp_port;
int sep;
} /* daemon_listen but not inetd_wait_mode */
-if (daemon_listen)
+if (f.daemon_listen)
{
/* Do a sanity check on the max connects value just to save us from getting
setsid() for getting rid of the controlling terminal. For any OS that doesn't,
setsid() can be #defined as a no-op, or as something else. */
-if (background_daemon || inetd_wait_mode)
+if (f.background_daemon || f.inetd_wait_mode)
{
log_close_all(); /* Just in case anything was logged earlier */
search_tidyup(); /* Just in case any were used in reading the config. */
log_stderr = NULL; /* So no attempt to copy paniclog output */
}
-if (background_daemon)
+if (f.background_daemon)
{
/* If the parent process of this one has pid == 1, we are re-initializing the
daemon as the result of a SIGHUP. In this case, there is no need to do
/* We are now in the disconnected, daemon process (unless debugging). Set up
the listening sockets if required. */
-if (daemon_listen && !inetd_wait_mode)
+if (f.daemon_listen && !f.inetd_wait_mode)
{
int sk;
ip_address_item *ipa;
listen() stage instead. */
#ifdef TCP_FASTOPEN
- tcp_fastopen_ok = TRUE;
+ f.tcp_fastopen_ok = TRUE;
#endif
for(;;)
{
&smtp_connect_backlog, sizeof(smtp_connect_backlog)))
{
DEBUG(D_any) debug_printf("setsockopt FASTOPEN: %s\n", strerror(errno));
- tcp_fastopen_ok = FALSE;
+ f.tcp_fastopen_ok = FALSE;
}
#endif
The variable daemon_write_pid is used to control this. */
-if (running_in_test_harness || write_pid)
+if (f.running_in_test_harness || write_pid)
{
FILE *f;
/* Log the start up of a daemon - at least one of listening or queue running
must be set up. */
-if (inetd_wait_mode)
+if (f.inetd_wait_mode)
{
uschar *p = big_buffer;
sigalrm_seen = 1;
}
-else if (daemon_listen)
+else if (f.daemon_listen)
{
int i, j;
int smtp_ports = 0;
leave the above message, because it ties up with the "child ended"
debugging messages. */
- if (debug_daemon) debug_selector = 0;
+ if (f.debug_daemon) debug_selector = 0;
/* Close any open listening sockets in the child */
signal(SIGALRM, SIG_DFL);
*p++ = '-';
*p++ = 'q';
- if (queue_2stage) *p++ = 'q';
- if (queue_run_first_delivery) *p++ = 'i';
- if (queue_run_force) *p++ = 'f';
- if (deliver_force_thaw) *p++ = 'f';
- if (queue_run_local) *p++ = 'l';
+ if (f.queue_2stage) *p++ = 'q';
+ if (f.queue_run_first_delivery) *p++ = 'i';
+ if (f.queue_run_force) *p++ = 'f';
+ if (f.deliver_force_thaw) *p++ = 'f';
+ if (f.queue_run_local) *p++ = 'l';
*p = 0;
extra[0] = queue_name
? string_sprintf("%sG%s", opt, queue_name) : opt;
if (deliver_selectstring)
{
- extra[extracount++] = deliver_selectstring_regex ? US"-Rr" : US"-R";
+ extra[extracount++] = f.deliver_selectstring_regex ? US"-Rr" : US"-R";
extra[extracount++] = deliver_selectstring;
}
if (deliver_selectstring_sender)
{
- extra[extracount++] = deliver_selectstring_sender_regex
+ extra[extracount++] = f.deliver_selectstring_sender_regex
? US"-Sr" : US"-S";
extra[extracount++] = deliver_selectstring_sender;
}
new OS. In fact, the later addition of listening on specific interfaces only
requires this way of working anyway. */
- if (daemon_listen)
+ if (f.daemon_listen)
{
int sk, lcount, select_errno;
int max_socket = 0;
gettimeofday(&now, NULL);
tmp = now.tv_sec;
- t = timestamps_utc ? gmtime(&tmp) : localtime(&tmp);
+ t = f.timestamps_utc ? gmtime(&tmp) : localtime(&tmp);
debug_ptr += sprintf(CS debug_ptr,
LOGGING(millisec) ? "%02d:%02d:%02d.%03d " : "%02d:%02d:%02d ",
t->tm_hour, t->tm_min, t->tm_sec, (int)(now.tv_usec/1000));
/* Log the deferment in the message log, but don't clutter it
up with retry-time defers after the first delivery attempt. */
-if (deliver_firsttime || addr->basic_errno > ERRNO_RETRY_BASE)
+if (f.deliver_firsttime || addr->basic_errno > ERRNO_RETRY_BASE)
deliver_msglog("%s %s\n", now, g->s);
/* Write the main log and reset the store.
{
driver_name = addr->transport->name;
driver_kind = US" transport";
- disable_logging = addr->transport->disable_logging;
+ f.disable_logging = addr->transport->disable_logging;
}
else driver_kind = US"transporting";
}
{
driver_name = addr->router->name;
driver_kind = US" router";
- disable_logging = addr->router->disable_logging;
+ f.disable_logging = addr->router->disable_logging;
}
else driver_kind = US"routing";
}
if (addr->special_action == SPECIAL_FREEZE)
{
- deliver_freeze = TRUE;
+ f.deliver_freeze = TRUE;
deliver_frozen_at = time(NULL);
update_spool = TRUE;
}
/* If doing a 2-stage queue run, we skip writing to either the message
log or the main log for SMTP defers. */
- if (!queue_2stage || addr->basic_errno != 0)
+ if (!f.queue_2stage || addr->basic_errno != 0)
deferral_log(addr, now, logflags, driver_name, driver_kind);
}
{
frozen_info = addr->special_action == SPECIAL_FREEZE
? US""
- : sender_local && !local_error_message
+ : f.sender_local && !f.local_error_message
? US" (message created with -f <>)"
: US" (delivery error message)";
- deliver_freeze = TRUE;
+ f.deliver_freeze = TRUE;
deliver_frozen_at = time(NULL);
update_spool = TRUE;
/* Ensure logging is turned on again in all cases */
-disable_logging = FALSE;
+f.disable_logging = FALSE;
}
uschar *new_return_path = expand_string(tp->return_path);
if (!new_return_path)
{
- if (!expand_string_forcedfail)
+ if (!f.expand_string_forcedfail)
{
common_error(TRUE, addr, ERRNO_EXPANDFAIL,
US"Failed to expand return path \"%s\" in %s transport: %s",
/* In the test harness, wait just a bit to let the subprocess finish off
any debug output etc first. */
- if (running_in_test_harness) millisleep(300);
+ if (f.running_in_test_harness) millisleep(300);
DEBUG(D_deliver) debug_printf("journalling %s", big_buffer);
len = Ustrlen(big_buffer);
struct timeval deliver_time;
address_item *addr2, *addr3, *nextaddr;
int logflags = LOG_MAIN;
- int logchar = dont_deliver? '*' : '=';
+ int logchar = f.dont_deliver? '*' : '=';
transport_instance *tp;
uschar * serialize_key = NULL;
if (!(tp = addr->transport))
{
logflags |= LOG_PANIC;
- disable_logging = FALSE; /* Jic */
+ f.disable_logging = FALSE; /* Jic */
addr->message = addr->router
? string_sprintf("No transport set by %s router", addr->router->name)
: string_sprintf("No transport set by system filter");
/* There are weird cases where logging is disabled */
- disable_logging = tp->disable_logging;
+ f.disable_logging = tp->disable_logging;
/* Check for batched addresses and possible amalgamation. Skip all the work
if either batch_max <= 1 or there aren't any other addresses for local
retry_record->expired);
}
- if (queue_running && !deliver_force)
+ if (f.queue_running && !f.deliver_force)
{
ok = (now - retry_record->time_stamp > retry_data_expire)
|| (now >= retry_record->next_try)
if (!(tp = addr->transport))
{
- disable_logging = FALSE; /* Jic */
+ f.disable_logging = FALSE; /* Jic */
panicmsg = US"No transport set by router";
goto panic_continue;
}
uschar *new_return_path = expand_string(tp->return_path);
if (new_return_path)
return_path = new_return_path;
- else if (!expand_string_forcedfail)
+ else if (!f.expand_string_forcedfail)
{
panicmsg = string_sprintf("Failed to expand return path \"%s\": %s",
tp->return_path, expand_string_message);
we must check that the continue host is on the list. Otherwise, the
host is set in the transport. */
- continue_more = FALSE; /* In case got set for the last lot */
+ f.continue_more = FALSE; /* In case got set for the last lot */
if (continue_transport)
{
BOOL ok = Ustrcmp(continue_transport, tp->name) == 0;
connected to is too hard to manage. Perhaps we need a finer-grain
interface to the transport. */
- for (next = addr_remote; next && !continue_more; next = next->next)
+ for (next = addr_remote; next && !f.continue_more; next = next->next)
{
host_item *h;
for (h = next->host_list; h; h = h->next)
if (Ustrcmp(h->name, continue_hostname) == 0)
- { continue_more = TRUE; break; }
+ { f.continue_more = TRUE; break; }
}
}
transport_name = tp->name;
/* There are weird circumstances in which logging is disabled */
- disable_logging = tp->disable_logging;
+ f.disable_logging = tp->disable_logging;
/* Show pids on debug output if parallelism possible */
predictable settings for each delivery process, so do something explicit
here rather they rely on the fixed reset in the random number function. */
- random_seed = running_in_test_harness ? 42 + 2*delivery_count : 0;
+ random_seed = f.running_in_test_harness ? 42 + 2*delivery_count : 0;
/* Set close-on-exec on the pipe so that it doesn't get passed on to
a new process that may be forked to do another delivery down the same
newly created process get going before we create another process. This should
ensure repeatability in the tests. We only need to wait a tad. */
- else if (running_in_test_harness) millisleep(500);
+ else if (f.running_in_test_harness) millisleep(500);
continue;
known to be a valid message id. */
Ustrcpy(message_id, id);
-deliver_force = forced;
+f.deliver_force = forced;
return_count = 0;
message_size = 0;
can happen, but in the default situation, unless forced, no delivery is
attempted. */
-if (deliver_freeze)
+if (f.deliver_freeze)
{
#ifdef SUPPORT_MOVE_FROZEN_MESSAGES
/* Moving to another directory removes the message from Exim's view. Other
|| auto_thaw <= 0
|| now <= deliver_frozen_at + auto_thaw
)
- && ( !forced || !deliver_force_thaw
- || !admin_user || continue_hostname
+ && ( !forced || !f.deliver_force_thaw
+ || !f.admin_user || continue_hostname
) )
{
(void)close(deliver_datafile);
if (forced)
{
- deliver_manual_thaw = TRUE;
+ f.deliver_manual_thaw = TRUE;
log_write(0, LOG_MAIN, "Unfrozen by forced delivery");
}
else log_write(0, LOG_MAIN, "Unfrozen by auto-thaw");
/* We get here if any of the rules for unfreezing have triggered. */
- deliver_freeze = FALSE;
+ f.deliver_freeze = FALSE;
update_spool = TRUE;
}
}
return_path = sender_address;
- enable_dollar_recipients = TRUE; /* Permit $recipients in system filter */
- system_filtering = TRUE;
+ f.enable_dollar_recipients = TRUE; /* Permit $recipients in system filter */
+ f.system_filtering = TRUE;
/* Any error in the filter file causes a delivery to be abandoned. */
/* Reset things. If the filter message is an empty string, which can happen
for a filter "fail" or "freeze" command with no text, reset it to NULL. */
- system_filtering = FALSE;
- enable_dollar_recipients = FALSE;
+ f.system_filtering = FALSE;
+ f.enable_dollar_recipients = FALSE;
if (filter_message && filter_message[0] == 0) filter_message = NULL;
/* Save the values of the system filter variables so that user filters
unset "delivered", which is forced by the "freeze" command to make -bF
work properly. */
- else if (rc == FF_FREEZE && !deliver_manual_thaw)
+ else if (rc == FF_FREEZE && !f.deliver_manual_thaw)
{
- deliver_freeze = TRUE;
+ f.deliver_freeze = TRUE;
deliver_frozen_at = time(NULL);
process_recipients = RECIP_DEFER;
frozen_info = string_sprintf(" by the system filter%s%s",
. If new addresses have been generated by the routers, da capo.
*/
-header_rewritten = FALSE; /* No headers rewritten yet */
+f.header_rewritten = FALSE; /* No headers rewritten yet */
while (addr_new) /* Loop until all addresses dealt with */
{
address_item *addr, *parent;
which keep the retry record fresh, which can lead to us perpetually
deferring messages. */
- else if ( ( queue_running && !deliver_force
+ else if ( ( f.queue_running && !f.deliver_force
|| continue_hostname
)
&& ( ( domain_retry_record
those domains. During queue runs, queue_domains is forced to be unset.
Optimize by skipping this pass through the addresses if nothing is set. */
- if (!deliver_force && queue_domains)
+ if (!f.deliver_force && queue_domains)
{
address_item *okaddr = NULL;
while (addr_route)
there is only address to be delivered - if it succeeds the spool write need not
happen. */
-if ( header_rewritten
+if ( f.header_rewritten
&& ( addr_local && (addr_local->next || addr_remote)
|| addr_remote && addr_remote->next
) )
{
/* Panic-dies on error */
(void)spool_write_header(message_id, SW_DELIVERING, NULL);
- header_rewritten = FALSE;
+ f.header_rewritten = FALSE;
}
DEBUG(D_deliver|D_transport)
debug_printf(">>>>>>>>>>>>>>>> Local deliveries >>>>>>>>>>>>>>>>\n");
do_local_deliveries();
- disable_logging = FALSE;
+ f.disable_logging = FALSE;
}
/* If queue_run_local is set, we do not want to attempt any remote deliveries,
so just queue them all. */
-if (queue_run_local)
+if (f.queue_run_local)
while (addr_remote)
{
address_item *addr = addr_remote;
if (remote_sort_domains) sort_remote_deliveries();
do_remote_deliveries(TRUE);
}
- disable_logging = FALSE;
+ f.disable_logging = FALSE;
}
updating of the database if the -N flag is set, which is a debugging thing that
prevents actual delivery. */
-else if (!dont_deliver)
+else if (!f.dont_deliver)
retry_update(&addr_defer, &addr_failed, &addr_succeed);
/* Send DSN for successful messages if requested */
/* There are weird cases when logging is disabled in the transport. However,
there may not be a transport (address failed by a router). */
- disable_logging = FALSE;
+ f.disable_logging = FALSE;
if (addr_failed->transport)
- disable_logging = addr_failed->transport->disable_logging;
+ f.disable_logging = addr_failed->transport->disable_logging;
DEBUG(D_deliver)
debug_printf("processing failed address %s\n", addr_failed->address);
int filecount = 0;
int rcount = 0;
uschar *bcc, *emf_text;
- FILE *f = fdopen(fd, "wb");
- FILE *emf = NULL;
+ FILE * fp = fdopen(fd, "wb");
+ FILE * emf = NULL;
BOOL to_sender = strcmpic(sender_address, bounce_recipient) == 0;
int max = (bounce_return_size_limit/DELIVER_IN_BUFFER_SIZE + 1) *
DELIVER_IN_BUFFER_SIZE;
if (testflag(addr, af_hide_child)) continue;
if (rcount >= 50)
{
- fprintf(f, "\n");
+ fprintf(fp, "\n");
rcount = 0;
}
- fprintf(f, "%s%s",
+ fprintf(fp, "%s%s",
rcount++ == 0
? "X-Failed-Recipients: "
: ",\n ",
? string_printing(addr->parent->address)
: string_printing(addr->address));
}
- if (rcount > 0) fprintf(f, "\n");
+ if (rcount > 0) fprintf(fp, "\n");
/* Output the standard headers */
if (errors_reply_to)
- fprintf(f, "Reply-To: %s\n", errors_reply_to);
- fprintf(f, "Auto-Submitted: auto-replied\n");
- moan_write_from(f);
- fprintf(f, "To: %s\n", bounce_recipient);
+ fprintf(fp, "Reply-To: %s\n", errors_reply_to);
+ fprintf(fp, "Auto-Submitted: auto-replied\n");
+ moan_write_from(fp);
+ fprintf(fp, "To: %s\n", bounce_recipient);
/* generate boundary string and output MIME-Headers */
bound = string_sprintf(TIME_T_FMT "-eximdsn-%d", time(NULL), rand());
- fprintf(f, "Content-Type: multipart/report;"
+ fprintf(fp, "Content-Type: multipart/report;"
" report-type=delivery-status; boundary=%s\n"
"MIME-Version: 1.0\n",
bound);
/* Quietly copy to configured additional addresses if required. */
if ((bcc = moan_check_errorcopy(bounce_recipient)))
- fprintf(f, "Bcc: %s\n", bcc);
+ fprintf(fp, "Bcc: %s\n", bcc);
/* The texts for the message can be read from a template file; if there
isn't one, or if it is too short, built-in texts are used. The first
emf text is a Subject: and any other headers. */
if ((emf_text = next_emf(emf, US"header")))
- fprintf(f, "%s\n", emf_text);
+ fprintf(fp, "%s\n", emf_text);
else
- fprintf(f, "Subject: Mail delivery failed%s\n\n",
+ fprintf(fp, "Subject: Mail delivery failed%s\n\n",
to_sender? ": returning message to sender" : "");
/* output human readable part as text/plain section */
- fprintf(f, "--%s\n"
+ fprintf(fp, "--%s\n"
"Content-type: text/plain; charset=us-ascii\n\n",
bound);
if ((emf_text = next_emf(emf, US"intro")))
- fprintf(f, "%s", CS emf_text);
+ fprintf(fp, "%s", CS emf_text);
else
{
- fprintf(f,
+ fprintf(fp,
/* This message has been reworded several times. It seems to be confusing to
somebody, however it is worded. I have retreated to the original, simple
wording. */
"This message was created automatically by mail delivery software.\n");
if (bounce_message_text)
- fprintf(f, "%s", CS bounce_message_text);
+ fprintf(fp, "%s", CS bounce_message_text);
if (to_sender)
- fprintf(f,
+ fprintf(fp,
"\nA message that you sent could not be delivered to one or more of its\n"
"recipients. This is a permanent error. The following address(es) failed:\n");
else
- fprintf(f,
+ fprintf(fp,
"\nA message sent by\n\n <%s>\n\n"
"could not be delivered to one or more of its recipients. The following\n"
"address(es) failed:\n", sender_address);
}
- fputc('\n', f);
+ fputc('\n', fp);
/* Process the addresses, leaving them on the msgchain if they have a
file name for a return message. (There has already been a check in
paddr = &msgchain;
for (addr = msgchain; addr; addr = *paddr)
{
- if (print_address_information(addr, f, US" ", US"\n ", US""))
- print_address_error(addr, f, US"");
+ if (print_address_information(addr, fp, US" ", US"\n ", US""))
+ print_address_error(addr, fp, US"");
/* End the final line for the address */
- fputc('\n', f);
+ fputc('\n', fp);
/* Leave on msgchain if there's a return file. */
}
}
- fputc('\n', f);
+ fputc('\n', fp);
/* Get the next text, whether we need it or not, so as to be
positioned for the one after. */
address_item *nextaddr;
if (emf_text)
- fprintf(f, "%s", CS emf_text);
+ fprintf(fp, "%s", CS emf_text);
else
- fprintf(f,
+ fprintf(fp,
"The following text was generated during the delivery "
"attempt%s:\n", (filecount > 1)? "s" : "");
/* List all the addresses that relate to this file */
- fputc('\n', f);
+ fputc('\n', fp);
while(addr) /* Insurance */
{
- print_address_information(addr, f, US"------ ", US"\n ",
+ print_address_information(addr, fp, US"------ ", US"\n ",
US" ------\n");
if (addr->return_filename) break;
addr = addr->next;
}
- fputc('\n', f);
+ fputc('\n', fp);
/* Now copy the file */
if (!(fm = Ufopen(addr->return_filename, "rb")))
- fprintf(f, " +++ Exim error... failed to open text file: %s\n",
+ fprintf(fp, " +++ Exim error... failed to open text file: %s\n",
strerror(errno));
else
{
- while ((ch = fgetc(fm)) != EOF) fputc(ch, f);
+ while ((ch = fgetc(fm)) != EOF) fputc(ch, fp);
(void)fclose(fm);
}
Uunlink(addr->return_filename);
addr->next = handled_addr;
handled_addr = topaddr;
}
- fputc('\n', f);
+ fputc('\n', fp);
}
/* output machine readable part */
#ifdef SUPPORT_I18N
if (message_smtputf8)
- fprintf(f, "--%s\n"
+ fprintf(fp, "--%s\n"
"Content-type: message/global-delivery-status\n\n"
"Reporting-MTA: dns; %s\n",
bound, smtp_active_hostname);
else
#endif
- fprintf(f, "--%s\n"
+ fprintf(fp, "--%s\n"
"Content-type: message/delivery-status\n\n"
"Reporting-MTA: dns; %s\n",
bound, smtp_active_hostname);
/* must be decoded from xtext: see RFC 3461:6.3a */
uschar *xdec_envid;
if (auth_xtextdecode(dsn_envid, &xdec_envid) > 0)
- fprintf(f, "Original-Envelope-ID: %s\n", dsn_envid);
+ fprintf(fp, "Original-Envelope-ID: %s\n", dsn_envid);
else
- fprintf(f, "X-Original-Envelope-ID: error decoding xtext formatted ENVID\n");
+ fprintf(fp, "X-Original-Envelope-ID: error decoding xtext formatted ENVID\n");
}
- fputc('\n', f);
+ fputc('\n', fp);
for (addr = handled_addr; addr; addr = addr->next)
{
host_item * hu;
- fprintf(f, "Action: failed\n"
+ fprintf(fp, "Action: failed\n"
"Final-Recipient: rfc822;%s\n"
"Status: 5.0.0\n",
addr->address);
if ((hu = addr->host_used) && hu->name)
{
- fprintf(f, "Remote-MTA: dns; %s\n", hu->name);
+ fprintf(fp, "Remote-MTA: dns; %s\n", hu->name);
#ifdef EXPERIMENTAL_DSN_INFO
{
const uschar * s;
{
uschar * p = hu->port == 25
? US"" : string_sprintf(":%d", hu->port);
- fprintf(f, "Remote-MTA: X-ip; [%s]%s\n", hu->address, p);
+ fprintf(fp, "Remote-MTA: X-ip; [%s]%s\n", hu->address, p);
}
if ((s = addr->smtp_greeting) && *s)
- fprintf(f, "X-Remote-MTA-smtp-greeting: X-str; %s\n", s);
+ fprintf(fp, "X-Remote-MTA-smtp-greeting: X-str; %s\n", s);
if ((s = addr->helo_response) && *s)
- fprintf(f, "X-Remote-MTA-helo-response: X-str; %s\n", s);
+ fprintf(fp, "X-Remote-MTA-helo-response: X-str; %s\n", s);
if ((s = addr->message) && *s)
- fprintf(f, "X-Exim-Diagnostic: X-str; %s\n", s);
+ fprintf(fp, "X-Exim-Diagnostic: X-str; %s\n", s);
}
#endif
- print_dsn_diagnostic_code(addr, f);
+ print_dsn_diagnostic_code(addr, fp);
}
- fputc('\n', f);
+ fputc('\n', fp);
}
/* Now copy the message, trying to give an intelligible comment if
bounce_return_size_limit is always honored.
*/
- fprintf(f, "--%s\n", bound);
+ fprintf(fp, "--%s\n", bound);
dsnlimitmsg = US"X-Exim-DSN-Information: Due to administrative limits only headers are returned";
dsnnotifyhdr = NULL;
if (message_smtputf8)
fputs(topt & topt_no_body ? "Content-type: message/global-headers\n\n"
: "Content-type: message/global\n\n",
- f);
+ fp);
else
#endif
fputs(topt & topt_no_body ? "Content-type: text/rfc822-headers\n\n"
: "Content-type: message/rfc822\n\n",
- f);
+ fp);
- fflush(f);
+ fflush(fp);
transport_filter_argv = NULL; /* Just in case */
return_path = sender_address; /* In case not previously set */
{ /* Dummy transport for headers add */
transport_ctx tctx = {{0}};
transport_instance tb = {0};
- tctx.u.fd = fileno(f);
+ tctx.u.fd = fileno(fp);
tctx.tblock = &tb;
tctx.options = topt;
tb.add_headers = dsnnotifyhdr;
transport_write_message(&tctx, 0);
}
- fflush(f);
+ fflush(fp);
/* we never add the final text. close the file */
if (emf)
(void)fclose(emf);
- fprintf(f, "\n--%s--\n", bound);
+ fprintf(fp, "\n--%s--\n", bound);
/* Close the file, which should send an EOF to the child process
that is receiving the message. Wait for it to finish. */
- (void)fclose(f);
+ (void)fclose(fp);
rc = child_close(pid, 0); /* Waits for child to close, no timeout */
/* In the test harness, let the child do it's thing first. */
- if (running_in_test_harness) millisleep(500);
+ if (f.running_in_test_harness) millisleep(500);
/* If the process failed, there was some disaster in setting up the
error message. Unless the message is very old, ensure that addr_defer
if (now - received_time.tv_sec < retry_maximum_timeout && !addr_defer)
{
addr_defer = (address_item *)(+1);
- deliver_freeze = TRUE;
+ f.deliver_freeze = TRUE;
deliver_frozen_at = time(NULL);
/* Panic-dies on error */
(void)spool_write_header(message_id, SW_DELIVERING, NULL);
}
}
-disable_logging = FALSE; /* In case left set */
+f.disable_logging = FALSE; /* In case left set */
/* Come here from the mua_wrapper case if routing goes wrong */
log_write(0, LOG_MAIN, "Completed");
/* Unset deliver_freeze so that we won't try to move the spool files further down */
- deliver_freeze = FALSE;
+ f.deliver_freeze = FALSE;
#ifndef DISABLE_EVENT
(void) event_raise(event_action, US"msg:complete", NULL);
is not sent. Another attempt will be made at the next delivery attempt (if
it also defers). */
- if ( !queue_2stage
+ if ( !f.queue_2stage
&& delivery_attempted
&& ( ((addr_defer->dsn_flags & rf_dsnflags) == 0)
|| (addr_defer->dsn_flags & rf_notify_delay) == rf_notify_delay
time off the list. In queue runs, the list pointer gets updated in the
calling process. */
- if (running_in_test_harness && fudged_queue_times[0] != 0)
+ if (f.running_in_test_harness && fudged_queue_times[0] != 0)
{
int qt = readconf_readtime(fudged_queue_times, '/', FALSE);
if (qt >= 0)
/* If this was a first delivery attempt, unset the first time flag, and
ensure that the spool gets updated. */
- if (deliver_firsttime)
+ if (f.deliver_firsttime)
{
- deliver_firsttime = FALSE;
+ f.deliver_firsttime = FALSE;
update_spool = TRUE;
}
For the "tell" message, we turn \n back into newline. Also, insert a newline
near the start instead of the ": " string. */
- if (deliver_freeze)
+ if (f.deliver_freeze)
{
- if (freeze_tell && freeze_tell[0] != 0 && !local_error_message)
+ if (freeze_tell && freeze_tell[0] != 0 && !f.local_error_message)
{
uschar *s = string_copy(frozen_info);
uschar *ss = Ustrstr(s, " by the system filter: ");
DEBUG(D_deliver)
debug_printf("delivery deferred: update_spool=%d header_rewritten=%d\n",
- update_spool, header_rewritten);
+ update_spool, f.header_rewritten);
- if (update_spool || header_rewritten)
+ if (update_spool || f.header_rewritten)
/* Panic-dies on error */
(void)spool_write_header(message_id, SW_DELIVERING, NULL);
}
/* Move the message off the spool if requested */
#ifdef SUPPORT_MOVE_FROZEN_MESSAGES
- if (deliver_freeze && move_frozen_messages)
+ if (f.deliver_freeze && move_frozen_messages)
(void)spool_move_message(id, message_subdir, US"", US"F");
#endif
}
#ifdef EXIM_TFO_PROBE
tfo_probe();
#else
-tcp_fastopen_ok = TRUE;
+f.tcp_fastopen_ok = TRUE;
#endif
int rc;
uschar * new_sender_address,
* save_sender_address;
-BOOL save_qr = queue_running;
+BOOL save_qr = f.queue_running;
uschar * spoolname;
/* make spool_open_datafile non-noisy on fail */
-queue_running = TRUE;
+f.queue_running = TRUE;
/* Side effect: message_subdir is set for the (possibly split) spool directory */
deliver_datafile = spool_open_datafile(id);
-queue_running = save_qr;
+f.queue_running = save_qr;
if (deliver_datafile < 0)
return NULL;
else if (pid == 0) /* child: fork again to totally disconnect */
{
- if (running_in_test_harness) millisleep(100); /* let parent debug out */
+ if (f.running_in_test_harness) millisleep(100); /* let parent debug out */
/* does not return */
smtp_proxy_tls(cutthrough.cctx.tls_ctx, big_buffer, big_buffer_size,
pfd, 5*60);
log_write(0, LOG_MAIN,
"DKIM: Error during validation, disabling signature verification: %.100s",
dkim_collect_error);
- dkim_disable_verify = TRUE;
+ f.dkim_disable_verify = TRUE;
goto out;
}
dkim_verify_reason = US"";
dkim_cur_signer = id;
-if (dkim_disable_verify || !id || !dkim_verify_ctx)
+if (f.dkim_disable_verify || !id || !dkim_verify_ctx)
return OK;
/* Find signatures to run ACL on */
uschar *
dkim_exim_expand_query(int what)
{
-if (!dkim_verify_ctx || dkim_disable_verify || !dkim_cur_sig)
+if (!dkim_verify_ctx || f.dkim_disable_verify || !dkim_cur_sig)
return dkim_exim_expand_defaults(what);
switch (what)
{
int save_fd = tctx->u.fd;
int save_options = tctx->options;
-BOOL save_wireformat = spool_file_wireformat;
+BOOL save_wireformat = f.spool_file_wireformat;
uschar * hdrs;
gstring * dkim_signature;
int hsize;
/* The dotstuffed status of the datafile depends on whether it was stored
in wireformat. */
-dkim->dot_stuffed = spool_file_wireformat;
+dkim->dot_stuffed = f.spool_file_wireformat;
if (!(dkim_signature = dkim_exim_sign(deliver_datafile, SPOOL_DATA_START_OFFSET,
hdrs, dkim, &errstr)))
if (!(rc = dkt_sign_fail(dkim, &errno)))
temporarily set the marker for possible already-CRLF input. */
tctx->options &= ~topt_escape_headers;
-spool_file_wireformat = TRUE;
+f.spool_file_wireformat = TRUE;
transport_write_reset(0);
if ( ( dkim_signature
&& dkim_signature->ptr > 0
)
return FALSE;
-spool_file_wireformat = save_wireformat;
+f.spool_file_wireformat = save_wireformat;
tctx->options = save_options | topt_no_headers | topt_continuation;
if (!(transport_write_message(tctx, 0)))
dmarc_abort = FALSE;
dmarc_pass_fail = US"skipped";
dmarc_used_domain = US"";
-dmarc_has_been_checked = FALSE;
+f.dmarc_has_been_checked = FALSE;
header_from_sender = NULL;
spf_sender_domain = NULL;
spf_human_readable = NULL;
/* ACLs have "control=dmarc_disable_verify" */
-if (dmarc_disable_verify == TRUE)
+if (f.dmarc_disable_verify == TRUE)
return OK;
(void) memset(&dmarc_ctx, '\0', sizeof dmarc_ctx);
dmarc_store_data(header_line *hdr)
{
/* No debug output because would change every test debug output */
-if (!dmarc_disable_verify)
+if (!f.dmarc_disable_verify)
from_header = hdr;
return OK;
}
FILE *message_file = NULL;
/* Earlier ACL does not have *required* control=dmarc_enable_forensic */
-if (!dmarc_enable_forensic)
+if (!f.dmarc_enable_forensic)
return;
if ( dmarc_policy == DMARC_POLICY_REJECT && action == DMARC_RESULT_REJECT
recipient += 7;
DEBUG(D_receive)
debug_printf("DMARC forensic report to %s%s\n", recipient,
- (host_checking || running_in_test_harness) ? " (not really)" : "");
- if (host_checking || running_in_test_harness)
+ (host_checking || f.running_in_test_harness) ? " (not really)" : "");
+ if (host_checking || f.running_in_test_harness)
continue;
save_sender = sender_address;
u_char **ruf; /* forensic report addressees, if called for */
/* ACLs have "control=dmarc_disable_verify" */
-if (dmarc_disable_verify)
+if (f.dmarc_disable_verify)
return OK;
/* Store the header From: sender domain for this part of DMARC.
uschar * p;
uschar saveend;
- parse_allow_group = TRUE;
+ f.parse_allow_group = TRUE;
p = parse_find_address_end(from_header->text, FALSE);
saveend = *p; *p = '\0';
if ((header_from_sender = parse_extract_address(from_header->text, &errormsg,
/* shut down libopendmarc */
if (dmarc_pctx)
(void) opendmarc_policy_connect_shutdown(dmarc_pctx);
-if (!dmarc_disable_verify)
+if (!f.dmarc_disable_verify)
(void) opendmarc_policy_library_shutdown(&dmarc_ctx);
return OK;
/* Write the contents to the history file */
DEBUG(D_receive)
debug_printf("DMARC logging history data for opendmarc reporting%s\n",
- (host_checking || running_in_test_harness) ? " (not really)" : "");
-if (host_checking || running_in_test_harness)
+ (host_checking || f.running_in_test_harness) ? " (not really)" : "");
+if (host_checking || f.running_in_test_harness)
{
DEBUG(D_receive)
debug_printf("DMARC history data for debugging:\n%s", history_buffer);
uschar *
dmarc_exim_expand_query(int what)
{
-if (dmarc_disable_verify || !dmarc_pctx)
+if (f.dmarc_disable_verify || !dmarc_pctx)
return dmarc_exim_expand_defaults(what);
if (what == DMARC_VERIFY_STATUS)
dmarc_exim_expand_defaults(int what)
{
if (what == DMARC_VERIFY_STATUS)
- return dmarc_disable_verify ? US"off" : US"none";
+ return f.dmarc_disable_verify ? US"off" : US"none";
return US"";
}
gstring *
authres_dmarc(gstring * g)
{
-if (dmarc_has_been_checked)
+if (f.dmarc_has_been_checked)
{
g = string_append(g, 2, US";\n\tdmarc=", dmarc_pass_fail);
if (header_from_sender)
DEBUG(D_dns)
debug_printf("DNS name '%s' utf8 conversion to alabel failed: %s\n", name,
errstr);
- host_find_failed_syntax = TRUE;
+ f.host_find_failed_syntax = TRUE;
return DNS_NOMATCH;
}
name = alabel;
DEBUG(D_dns)
debug_printf("DNS name syntax check failed: %s (%s)\n", name,
dns_text_type(type));
- host_find_failed_syntax = TRUE;
+ f.host_find_failed_syntax = TRUE;
return DNS_NOMATCH;
}
}
(res_search), we call fakens_search(), which recognizes certain special
domains, and interfaces to a fake nameserver for certain special zones. */
-dnsa->answerlen = running_in_test_harness
+dnsa->answerlen = f.running_in_test_harness
? fakens_search(name, type, dnsa->answer, sizeof(dnsa->answer))
: res_search(CCS name, C_IN, type, dnsa->answer, sizeof(dnsa->answer));
DEBUG(D_transport|D_receive)
{
- if (!running_in_test_harness)
+ if (!f.running_in_test_harness)
{
debug_printf("tick check: " TIME_T_FMT ".%06lu " TIME_T_FMT ".%06lu\n",
then_tv->tv_sec, (long) then_tv->tv_usec,
if ((debug_selector & D_resolver) == 0) (void)close(1); /* stdout */
if (debug_selector == 0) /* stderr */
{
- if (!synchronous_delivery)
+ if (!f.synchronous_delivery)
{
(void)close(2);
log_stderr = NULL;
*/
static void
-show_whats_supported(FILE * f)
+show_whats_supported(FILE * fp)
{
auth_info * authi;
-DEBUG(D_any) {} else show_db_version(f);
+DEBUG(D_any) {} else show_db_version(fp);
-fprintf(f, "Support for:");
+fprintf(fp, "Support for:");
#ifdef SUPPORT_CRYPTEQ
- fprintf(f, " crypteq");
+ fprintf(fp, " crypteq");
#endif
#if HAVE_ICONV
- fprintf(f, " iconv()");
+ fprintf(fp, " iconv()");
#endif
#if HAVE_IPV6
- fprintf(f, " IPv6");
+ fprintf(fp, " IPv6");
#endif
#ifdef HAVE_SETCLASSRESOURCES
- fprintf(f, " use_setclassresources");
+ fprintf(fp, " use_setclassresources");
#endif
#ifdef SUPPORT_PAM
- fprintf(f, " PAM");
+ fprintf(fp, " PAM");
#endif
#ifdef EXIM_PERL
- fprintf(f, " Perl");
+ fprintf(fp, " Perl");
#endif
#ifdef EXPAND_DLFUNC
- fprintf(f, " Expand_dlfunc");
+ fprintf(fp, " Expand_dlfunc");
#endif
#ifdef USE_TCP_WRAPPERS
- fprintf(f, " TCPwrappers");
+ fprintf(fp, " TCPwrappers");
#endif
#ifdef SUPPORT_TLS
# ifdef USE_GNUTLS
- fprintf(f, " GnuTLS");
+ fprintf(fp, " GnuTLS");
# else
- fprintf(f, " OpenSSL");
+ fprintf(fp, " OpenSSL");
# endif
#endif
#ifdef SUPPORT_TRANSLATE_IP_ADDRESS
- fprintf(f, " translate_ip_address");
+ fprintf(fp, " translate_ip_address");
#endif
#ifdef SUPPORT_MOVE_FROZEN_MESSAGES
- fprintf(f, " move_frozen_messages");
+ fprintf(fp, " move_frozen_messages");
#endif
#ifdef WITH_CONTENT_SCAN
- fprintf(f, " Content_Scanning");
+ fprintf(fp, " Content_Scanning");
#endif
#ifdef SUPPORT_DANE
- fprintf(f, " DANE");
+ fprintf(fp, " DANE");
#endif
#ifndef DISABLE_DKIM
- fprintf(f, " DKIM");
+ fprintf(fp, " DKIM");
#endif
#ifndef DISABLE_DNSSEC
- fprintf(f, " DNSSEC");
+ fprintf(fp, " DNSSEC");
#endif
#ifndef DISABLE_EVENT
- fprintf(f, " Event");
+ fprintf(fp, " Event");
#endif
#ifdef SUPPORT_I18N
- fprintf(f, " I18N");
+ fprintf(fp, " I18N");
#endif
#ifndef DISABLE_OCSP
- fprintf(f, " OCSP");
+ fprintf(fp, " OCSP");
#endif
#ifndef DISABLE_PRDR
- fprintf(f, " PRDR");
+ fprintf(fp, " PRDR");
#endif
#ifdef SUPPORT_PROXY
- fprintf(f, " PROXY");
+ fprintf(fp, " PROXY");
#endif
#ifdef SUPPORT_SOCKS
- fprintf(f, " SOCKS");
+ fprintf(fp, " SOCKS");
#endif
#ifdef SUPPORT_SPF
- fprintf(f, " SPF");
+ fprintf(fp, " SPF");
#endif
#ifdef TCP_FASTOPEN
deliver_init();
- if (tcp_fastopen_ok) fprintf(f, " TCP_Fast_Open");
+ if (f.tcp_fastopen_ok) fprintf(fp, " TCP_Fast_Open");
#endif
#ifdef EXPERIMENTAL_LMDB
- fprintf(f, " Experimental_LMDB");
+ fprintf(fp, " Experimental_LMDB");
#endif
#ifdef EXPERIMENTAL_QUEUEFILE
- fprintf(f, " Experimental_QUEUEFILE");
+ fprintf(fp, " Experimental_QUEUEFILE");
#endif
#ifdef EXPERIMENTAL_SRS
- fprintf(f, " Experimental_SRS");
+ fprintf(fp, " Experimental_SRS");
#endif
#ifdef EXPERIMENTAL_ARC
- fprintf(f, " Experimental_ARC");
+ fprintf(fp, " Experimental_ARC");
#endif
#ifdef EXPERIMENTAL_BRIGHTMAIL
- fprintf(f, " Experimental_Brightmail");
+ fprintf(fp, " Experimental_Brightmail");
#endif
#ifdef EXPERIMENTAL_DCC
- fprintf(f, " Experimental_DCC");
+ fprintf(fp, " Experimental_DCC");
#endif
#ifdef EXPERIMENTAL_DMARC
- fprintf(f, " Experimental_DMARC");
+ fprintf(fp, " Experimental_DMARC");
#endif
#ifdef EXPERIMENTAL_DSN_INFO
- fprintf(f, " Experimental_DSN_info");
+ fprintf(fp, " Experimental_DSN_info");
#endif
#ifdef EXPERIMENTAL_REQUIRETLS
- fprintf(f, " Experimental_REQUIRETLS");
+ fprintf(fp, " Experimental_REQUIRETLS");
#endif
-fprintf(f, "\n");
+fprintf(fp, "\n");
-fprintf(f, "Lookups (built-in):");
+fprintf(fp, "Lookups (built-in):");
#if defined(LOOKUP_LSEARCH) && LOOKUP_LSEARCH!=2
- fprintf(f, " lsearch wildlsearch nwildlsearch iplsearch");
+ fprintf(fp, " lsearch wildlsearch nwildlsearch iplsearch");
#endif
#if defined(LOOKUP_CDB) && LOOKUP_CDB!=2
- fprintf(f, " cdb");
+ fprintf(fp, " cdb");
#endif
#if defined(LOOKUP_DBM) && LOOKUP_DBM!=2
- fprintf(f, " dbm dbmjz dbmnz");
+ fprintf(fp, " dbm dbmjz dbmnz");
#endif
#if defined(LOOKUP_DNSDB) && LOOKUP_DNSDB!=2
- fprintf(f, " dnsdb");
+ fprintf(fp, " dnsdb");
#endif
#if defined(LOOKUP_DSEARCH) && LOOKUP_DSEARCH!=2
- fprintf(f, " dsearch");
+ fprintf(fp, " dsearch");
#endif
#if defined(LOOKUP_IBASE) && LOOKUP_IBASE!=2
- fprintf(f, " ibase");
+ fprintf(fp, " ibase");
#endif
#if defined(LOOKUP_LDAP) && LOOKUP_LDAP!=2
- fprintf(f, " ldap ldapdn ldapm");
+ fprintf(fp, " ldap ldapdn ldapm");
#endif
#ifdef EXPERIMENTAL_LMDB
- fprintf(f, " lmdb");
+ fprintf(fp, " lmdb");
#endif
#if defined(LOOKUP_MYSQL) && LOOKUP_MYSQL!=2
- fprintf(f, " mysql");
+ fprintf(fp, " mysql");
#endif
#if defined(LOOKUP_NIS) && LOOKUP_NIS!=2
- fprintf(f, " nis nis0");
+ fprintf(fp, " nis nis0");
#endif
#if defined(LOOKUP_NISPLUS) && LOOKUP_NISPLUS!=2
- fprintf(f, " nisplus");
+ fprintf(fp, " nisplus");
#endif
#if defined(LOOKUP_ORACLE) && LOOKUP_ORACLE!=2
- fprintf(f, " oracle");
+ fprintf(fp, " oracle");
#endif
#if defined(LOOKUP_PASSWD) && LOOKUP_PASSWD!=2
- fprintf(f, " passwd");
+ fprintf(fp, " passwd");
#endif
#if defined(LOOKUP_PGSQL) && LOOKUP_PGSQL!=2
- fprintf(f, " pgsql");
+ fprintf(fp, " pgsql");
#endif
#if defined(LOOKUP_REDIS) && LOOKUP_REDIS!=2
- fprintf(f, " redis");
+ fprintf(fp, " redis");
#endif
#if defined(LOOKUP_SQLITE) && LOOKUP_SQLITE!=2
- fprintf(f, " sqlite");
+ fprintf(fp, " sqlite");
#endif
#if defined(LOOKUP_TESTDB) && LOOKUP_TESTDB!=2
- fprintf(f, " testdb");
+ fprintf(fp, " testdb");
#endif
#if defined(LOOKUP_WHOSON) && LOOKUP_WHOSON!=2
- fprintf(f, " whoson");
+ fprintf(fp, " whoson");
#endif
-fprintf(f, "\n");
+fprintf(fp, "\n");
-auth_show_supported(f);
-route_show_supported(f);
-transport_show_supported(f);
+auth_show_supported(fp);
+route_show_supported(fp);
+transport_show_supported(fp);
#ifdef WITH_CONTENT_SCAN
-malware_show_supported(f);
+malware_show_supported(fp);
#endif
if (fixed_never_users[0] > 0)
{
int i;
- fprintf(f, "Fixed never_users: ");
+ fprintf(fp, "Fixed never_users: ");
for (i = 1; i <= (int)fixed_never_users[0] - 1; i++)
- fprintf(f, "%d:", (unsigned int)fixed_never_users[i]);
- fprintf(f, "%d\n", (unsigned int)fixed_never_users[i]);
+ fprintf(fp, "%d:", (unsigned int)fixed_never_users[i]);
+ fprintf(fp, "%d\n", (unsigned int)fixed_never_users[i]);
}
-fprintf(f, "Configure owner: %d:%d\n", config_uid, config_gid);
+fprintf(fp, "Configure owner: %d:%d\n", config_uid, config_gid);
-fprintf(f, "Size of off_t: " SIZE_T_FMT "\n", sizeof(off_t));
+fprintf(fp, "Size of off_t: " SIZE_T_FMT "\n", sizeof(off_t));
/* Everything else is details which are only worth reporting when debugging.
Perhaps the tls_version_report should move into this too. */
/* clang defines __GNUC__ (at least, for me) so test for it first */
#if defined(__clang__)
- fprintf(f, "Compiler: CLang [%s]\n", __clang_version__);
+ fprintf(fp, "Compiler: CLang [%s]\n", __clang_version__);
#elif defined(__GNUC__)
- fprintf(f, "Compiler: GCC [%s]\n",
+ fprintf(fp, "Compiler: GCC [%s]\n",
# ifdef __VERSION__
__VERSION__
# else
# endif
);
#else
- fprintf(f, "Compiler: <unknown>\n");
+ fprintf(fp, "Compiler: <unknown>\n");
#endif
#if defined(__GLIBC__) && !defined(__UCLIBC__)
- fprintf(f, "Library version: Glibc: Compile: %d.%d\n",
+ fprintf(fp, "Library version: Glibc: Compile: %d.%d\n",
__GLIBC__, __GLIBC_MINOR__);
if (__GLIBC_PREREQ(2, 1))
- fprintf(f, " Runtime: %s\n",
+ fprintf(fp, " Runtime: %s\n",
gnu_get_libc_version());
#endif
-show_db_version(f);
+show_db_version(fp);
#ifdef SUPPORT_TLS
- tls_version_report(f);
+ tls_version_report(fp);
#endif
#ifdef SUPPORT_I18N
- utf8_version_report(f);
+ utf8_version_report(fp);
#endif
for (authi = auths_available; *authi->driver_name != '\0'; ++authi)
if (authi->version_report)
- (*authi->version_report)(f);
+ (*authi->version_report)(fp);
/* PCRE_PRERELEASE is either defined and empty or a bare sequence of
characters; unless it's an ancient version of PCRE in which case it
#endif
#define QUOTE(X) #X
#define EXPAND_AND_QUOTE(X) QUOTE(X)
- fprintf(f, "Library version: PCRE: Compile: %d.%d%s\n"
+ fprintf(fp, "Library version: PCRE: Compile: %d.%d%s\n"
" Runtime: %s\n",
PCRE_MAJOR, PCRE_MINOR,
EXPAND_AND_QUOTE(PCRE_PRERELEASE) "",
init_lookup_list();
for (i = 0; i < lookup_list_count; i++)
if (lookup_list[i]->version_report)
- lookup_list[i]->version_report(f);
+ lookup_list[i]->version_report(fp);
#ifdef WHITELIST_D_MACROS
- fprintf(f, "WHITELIST_D_MACROS: \"%s\"\n", WHITELIST_D_MACROS);
+ fprintf(fp, "WHITELIST_D_MACROS: \"%s\"\n", WHITELIST_D_MACROS);
#else
- fprintf(f, "WHITELIST_D_MACROS unset\n");
+ fprintf(fp, "WHITELIST_D_MACROS unset\n");
#endif
#ifdef TRUSTED_CONFIG_LIST
- fprintf(f, "TRUSTED_CONFIG_LIST: \"%s\"\n", TRUSTED_CONFIG_LIST);
+ fprintf(fp, "TRUSTED_CONFIG_LIST: \"%s\"\n", TRUSTED_CONFIG_LIST);
#else
- fprintf(f, "TRUSTED_CONFIG_LIST unset\n");
+ fprintf(fp, "TRUSTED_CONFIG_LIST unset\n");
#endif
} while (0);
/* Check a field which is patched when we are running Exim within its
testing harness; do a fast initial check, and then the whole thing. */
-running_in_test_harness =
+f.running_in_test_harness =
*running_status == '<' && Ustrcmp(running_status, "<<<testing>>>") == 0;
-if (running_in_test_harness)
+if (f.running_in_test_harness)
debug_store = TRUE;
/* The C standard says that the equivalent of setlocale(LC_ALL, "C") is obeyed
if ((namelen == 5 && Ustrcmp(argv[0], "rmail") == 0) ||
(namelen > 5 && Ustrncmp(argv[0] + namelen - 6, "/rmail", 6) == 0))
{
- dot_ends = FALSE;
+ f.dot_ends = FALSE;
called_as = US"-rmail";
errors_sender_rc = EXIT_SUCCESS;
}
{
switchchar = arg[3];
argrest += 2;
- queue_2stage = TRUE;
+ f.queue_2stage = TRUE;
}
/* Make -r synonymous with -f, since it is a documented alias */
if (*argrest == 'd')
{
- daemon_listen = TRUE;
- if (*(++argrest) == 'f') background_daemon = FALSE;
+ f.daemon_listen = TRUE;
+ if (*(++argrest) == 'f') f.background_daemon = FALSE;
else if (*argrest != 0) { badarg = TRUE; break; }
}
{
if (++i >= argc) { badarg = TRUE; break; }
sender_host_address = argv[i];
- host_checking = checking = log_testing_mode = TRUE;
- host_checking_callout = argrest[1] == 'c';
+ host_checking = checking = f.log_testing_mode = TRUE;
+ f.host_checking_callout = argrest[1] == 'c';
message_logs = FALSE;
}
else if (Ustrcmp(argrest, "nq") == 0)
{
- allow_unqualified_sender = FALSE;
- allow_unqualified_recipient = FALSE;
+ f.allow_unqualified_sender = FALSE;
+ f.allow_unqualified_recipient = FALSE;
}
/* -bpxx: List the contents of the mail queue, in various forms. If
/* -bt: address testing mode */
else if (Ustrcmp(argrest, "t") == 0)
- address_test_mode = checking = log_testing_mode = TRUE;
+ f.address_test_mode = checking = f.log_testing_mode = TRUE;
/* -bv: verify addresses */
else if (Ustrcmp(argrest, "v") == 0)
- verify_address_mode = checking = log_testing_mode = TRUE;
+ verify_address_mode = checking = f.log_testing_mode = TRUE;
/* -bvs: verify sender addresses */
else if (Ustrcmp(argrest, "vs") == 0)
{
- verify_address_mode = checking = log_testing_mode = TRUE;
+ verify_address_mode = checking = f.log_testing_mode = TRUE;
verify_as_sender = TRUE;
}
printf("%s\n", CS version_copyright);
version_printed = TRUE;
show_whats_supported(stdout);
- log_testing_mode = TRUE;
+ f.log_testing_mode = TRUE;
}
/* -bw: inetd wait mode, accept a listening socket as stdin */
else if (*argrest == 'w')
{
- inetd_wait_mode = TRUE;
- background_daemon = FALSE;
- daemon_listen = TRUE;
+ f.inetd_wait_mode = TRUE;
+ f.background_daemon = FALSE;
+ f.daemon_listen = TRUE;
if (*(++argrest) != '\0')
{
inetd_wait_timeout = readconf_readtime(argrest, 0, FALSE);
&& real_uid != config_uid
#endif
)
- trusted_config = FALSE;
+ f.trusted_config = FALSE;
else
{
FILE *trust_list = Ufopen(TRUSTED_CONFIG_LIST, "rb");
) || /* or */
(statbuf.st_mode & 2) != 0) /* world writeable */
{
- trusted_config = FALSE;
+ f.trusted_config = FALSE;
fclose(trust_list);
}
else
int sep = 0;
const uschar *list = argrest;
uschar *filename;
- while (trusted_config && (filename = string_nextinlist(&list,
+ while (f.trusted_config && (filename = string_nextinlist(&list,
&sep, big_buffer, big_buffer_size)) != NULL)
{
for (i=0; i < nr_configs; i++)
}
if (i == nr_configs)
{
- trusted_config = FALSE;
+ f.trusted_config = FALSE;
break;
}
}
else
{
/* No valid prefixes found in trust_list file. */
- trusted_config = FALSE;
+ f.trusted_config = FALSE;
}
}
}
else
{
/* Could not open trust_list file. */
- trusted_config = FALSE;
+ f.trusted_config = FALSE;
}
}
#else
/* Not root; don't trust config */
- trusted_config = FALSE;
+ f.trusted_config = FALSE;
#endif
}
config_main_filelist = argrest;
- config_changed = TRUE;
+ f.config_changed = TRUE;
}
break;
debug_file = NULL;
if (*argrest == 'd')
{
- debug_daemon = TRUE;
+ f.debug_daemon = TRUE;
argrest++;
}
if (*argrest != 0)
message_reference at it, for logging. */
case 'E':
- local_error_message = TRUE;
+ f.local_error_message = TRUE;
if (mac_ismsgid(argrest)) message_reference = argrest;
break;
{ badarg = TRUE; break; }
}
originator_name = argrest;
- sender_name_forced = TRUE;
+ f.sender_name_forced = TRUE;
break;
return EXIT_FAILURE;
}
}
- sender_address_forced = TRUE;
+ f.sender_address_forced = TRUE;
}
break;
not to be documented for sendmail but mailx (at least) uses it) */
case 'i':
- if (*argrest == 0) dot_ends = FALSE; else badarg = TRUE;
+ if (*argrest == 0) f.dot_ends = FALSE; else badarg = TRUE;
break;
return EXIT_FAILURE;
}
- if (running_in_test_harness) millisleep(500);
+ if (f.running_in_test_harness) millisleep(500);
break;
}
precedes -MC (see above). The flag indicates that the host to which
Exim is connected has accepted an AUTH sequence. */
- case 'A': smtp_authenticated = TRUE; break;
+ case 'A': f.smtp_authenticated = TRUE; break;
/* -MCD: set the smtp_use_dsn flag; this indicates that the host
that exim is connected to supports the esmtp extension DSN */
else if (*argrest == 0)
{
msg_action = MSG_DELIVER;
- forced_delivery = deliver_force_thaw = TRUE;
+ forced_delivery = f.deliver_force_thaw = TRUE;
}
else if (Ustrcmp(argrest, "ar") == 0)
{
case 'N':
if (*argrest == 0)
{
- dont_deliver = TRUE;
+ f.dont_deliver = TRUE;
debug_selector |= D_v;
debug_file = stderr;
}
else if (Ustrcmp(argrest, "db") == 0)
{
- synchronous_delivery = FALSE;
+ f.synchronous_delivery = FALSE;
arg_queue_only = FALSE;
queue_only_set = TRUE;
}
else if (Ustrcmp(argrest, "df") == 0 || Ustrcmp(argrest, "di") == 0)
{
- synchronous_delivery = TRUE;
+ f.synchronous_delivery = TRUE;
arg_queue_only = FALSE;
queue_only_set = TRUE;
}
else if (Ustrcmp(argrest, "dq") == 0)
{
- synchronous_delivery = FALSE;
+ f.synchronous_delivery = FALSE;
arg_queue_only = TRUE;
queue_only_set = TRUE;
}
else if (Ustrcmp(argrest, "dqs") == 0)
{
- queue_smtp = TRUE;
+ f.queue_smtp = TRUE;
arg_queue_only = FALSE;
queue_only_set = TRUE;
}
else if (Ustrcmp(argrest, "i") == 0 ||
Ustrcmp(argrest, "itrue") == 0)
- dot_ends = FALSE;
+ f.dot_ends = FALSE;
/* -oM*: Set various characteristics for an incoming message; actually
acted on for trusted callers only. */
fprintf(stderr,"-oMm must be a valid message ID\n");
exit(EXIT_FAILURE);
}
- if (!trusted_config)
+ if (!f.trusted_config)
{
fprintf(stderr,"-oMm must be called by a trusted user/config\n");
exit(EXIT_FAILURE);
if (*argrest == 'q')
{
- queue_2stage = TRUE;
+ f.queue_2stage = TRUE;
argrest++;
}
if (*argrest == 'i')
{
- queue_run_first_delivery = TRUE;
+ f.queue_run_first_delivery = TRUE;
argrest++;
}
if (*argrest == 'f')
{
- queue_run_force = TRUE;
+ f.queue_run_force = TRUE;
if (*++argrest == 'f')
{
- deliver_force_thaw = TRUE;
+ f.deliver_force_thaw = TRUE;
argrest++;
}
}
if (*argrest == 'l')
{
- queue_run_local = TRUE;
+ f.queue_run_local = TRUE;
argrest++;
}
for (i = 0; i < nelem(rsopts); i++)
if (Ustrcmp(argrest, rsopts[i]) == 0)
{
- if (i != 2) queue_run_force = TRUE;
- if (i >= 2) deliver_selectstring_regex = TRUE;
- if (i == 1 || i == 4) deliver_force_thaw = TRUE;
+ if (i != 2) f.queue_run_force = TRUE;
+ if (i >= 2) f.deliver_selectstring_regex = TRUE;
+ if (i == 1 || i == 4) f.deliver_force_thaw = TRUE;
argrest += Ustrlen(rsopts[i]);
}
}
for (i = 0; i < nelem(rsopts); i++)
if (Ustrcmp(argrest, rsopts[i]) == 0)
{
- if (i != 2) queue_run_force = TRUE;
- if (i >= 2) deliver_selectstring_sender_regex = TRUE;
- if (i == 1 || i == 4) deliver_force_thaw = TRUE;
+ if (i != 2) f.queue_run_force = TRUE;
+ if (i >= 2) f.deliver_selectstring_sender_regex = TRUE;
+ if (i == 1 || i == 4) f.deliver_force_thaw = TRUE;
argrest += Ustrlen(rsopts[i]);
}
}
tested. Otherwise variability of clock ticks etc. cause problems. */
case 'T':
- if (running_in_test_harness && Ustrcmp(argrest, "qt") == 0)
+ if (f.running_in_test_harness && Ustrcmp(argrest, "qt") == 0)
fudged_queue_times = argv[++i];
else badarg = TRUE;
break;
else if (Ustrcmp(argrest, "i") == 0)
{
extract_recipients = TRUE;
- dot_ends = FALSE;
+ f.dot_ends = FALSE;
}
/* -tls-on-connect: don't wait for STARTTLS (for old clients) */
/* Arguments have been processed. Check for incompatibilities. */
if ((
(smtp_input || extract_recipients || recipients_arg < argc) &&
- (daemon_listen || queue_interval >= 0 || bi_option ||
+ (f.daemon_listen || queue_interval >= 0 || bi_option ||
test_retry_arg >= 0 || test_rewrite_arg >= 0 ||
filter_test != FTEST_NONE || (msg_action_arg > 0 && !one_msg_action))
) ||
(
msg_action_arg > 0 &&
- (daemon_listen || queue_interval > 0 || list_options ||
+ (f.daemon_listen || queue_interval > 0 || list_options ||
(checking && msg_action != MSG_LOAD) ||
bi_option || test_retry_arg >= 0 || test_rewrite_arg >= 0)
) ||
(
- (daemon_listen || queue_interval > 0) &&
+ (f.daemon_listen || queue_interval > 0) &&
(sender_address != NULL || list_options || list_queue || checking ||
bi_option)
) ||
(
- daemon_listen && queue_interval == 0
+ f.daemon_listen && queue_interval == 0
) ||
(
- inetd_wait_mode && queue_interval >= 0
+ f.inetd_wait_mode && queue_interval >= 0
) ||
(
list_options &&
) ||
(
verify_address_mode &&
- (address_test_mode || smtp_input || extract_recipients ||
+ (f.address_test_mode || smtp_input || extract_recipients ||
filter_test != FTEST_NONE || bi_option)
) ||
(
- address_test_mode && (smtp_input || extract_recipients ||
+ f.address_test_mode && (smtp_input || extract_recipients ||
filter_test != FTEST_NONE || bi_option)
) ||
(
{
debug_file = stderr;
debug_fd = fileno(debug_file);
- background_daemon = FALSE;
- if (running_in_test_harness) millisleep(100); /* lets caller finish */
+ f.background_daemon = FALSE;
+ if (f.running_in_test_harness) millisleep(100); /* lets caller finish */
if (debug_selector != D_v) /* -v only doesn't show this */
{
debug_printf("Exim version %s uid=%ld gid=%ld pid=%d D=%x\n",
configuration file changes and macro definitions haven't happened. */
if (( /* EITHER */
- (!trusted_config || /* Config changed, or */
+ (!f.trusted_config || /* Config changed, or */
!macros_trusted(opt_D_used)) && /* impermissible macros and */
real_uid != root_uid && /* Not root, and */
- !running_in_test_harness /* Not fudged */
+ !f.running_in_test_harness /* Not fudged */
) || /* OR */
expansion_test /* expansion testing */
|| /* OR */
this causes unlogged successful deliveries. */
if ((log_stderr != NULL) && (real_uid != exim_uid))
- really_exim = FALSE;
+ f.really_exim = FALSE;
}
/* Privilege is to be retained for the moment. It may be dropped later,
init_lookup_list();
#ifdef SUPPORT_I18N
-if (running_in_test_harness) smtputf8_advertise_hosts = NULL;
+if (f.running_in_test_harness) smtputf8_advertise_hosts = NULL;
#endif
/* Read the main runtime configuration data; this gives up if there
for later interrogation. */
if (real_uid == root_uid || real_uid == exim_uid || real_gid == exim_gid)
- admin_user = TRUE;
+ f.admin_user = TRUE;
else
{
int i, j;
- for (i = 0; i < group_count && !admin_user; i++)
+ for (i = 0; i < group_count && !f.admin_user; i++)
if (group_list[i] == exim_gid)
- admin_user = TRUE;
+ f.admin_user = TRUE;
else if (admin_groups)
- for (j = 1; j <= (int)admin_groups[0] && !admin_user; j++)
+ for (j = 1; j <= (int)admin_groups[0] && !f.admin_user; j++)
if (admin_groups[j] == group_list[i])
- admin_user = TRUE;
+ f.admin_user = TRUE;
}
/* Another group of privileged users are the trusted users. These are root,
other message parameters as well. */
if (real_uid == root_uid || real_uid == exim_uid)
- trusted_caller = TRUE;
+ f.trusted_caller = TRUE;
else
{
int i, j;
if (trusted_users)
- for (i = 1; i <= (int)trusted_users[0] && !trusted_caller; i++)
+ for (i = 1; i <= (int)trusted_users[0] && !f.trusted_caller; i++)
if (trusted_users[i] == real_uid)
- trusted_caller = TRUE;
+ f.trusted_caller = TRUE;
if (trusted_groups)
- for (i = 1; i <= (int)trusted_groups[0] && !trusted_caller; i++)
+ for (i = 1; i <= (int)trusted_groups[0] && !f.trusted_caller; i++)
if (trusted_groups[i] == real_gid)
- trusted_caller = TRUE;
- else for (j = 0; j < group_count && !trusted_caller; j++)
+ f.trusted_caller = TRUE;
+ else for (j = 0; j < group_count && !f.trusted_caller; j++)
if (trusted_groups[i] == group_list[j])
- trusted_caller = TRUE;
+ f.trusted_caller = TRUE;
}
/* At this point, we know if the user is privileged and some command-line
options become possibly impermissible, depending upon the configuration file. */
-if (checking && commandline_checks_require_admin && !admin_user) {
+if (checking && commandline_checks_require_admin && !f.admin_user) {
fprintf(stderr, "exim: those command-line flags are set to require admin\n");
exit(EXIT_FAILURE);
}
if (cmdline_syslog_name != NULL)
{
- if (admin_user)
+ if (f.admin_user)
{
syslog_processname = cmdline_syslog_name;
log_file_path = string_copy(CUS"syslog");
"syslog_processname is longer than 32 chars: aborting");
if (log_oneline)
- if (admin_user)
+ if (f.admin_user)
{
log_write(0, LOG_MAIN, "%s", log_oneline);
return EXIT_SUCCESS;
timestamps_utc is set, because then all times are in UTC anyway. */
if (timezone_string && strcmpic(timezone_string, US"UTC") == 0)
- timestamps_utc = TRUE;
+ f.timestamps_utc = TRUE;
else
{
uschar *envtz = US getenv("TZ");
trusted configuration file (when deliver_drop_privilege is false). */
if ( removed_privilege
- && (!trusted_config || opt_D_used)
+ && (!f.trusted_config || opt_D_used)
&& real_uid == exim_uid)
if (deliver_drop_privilege)
- really_exim = TRUE; /* let logging work normally */
+ f.really_exim = TRUE; /* let logging work normally */
else
log_write(0, LOG_MAIN|LOG_PANIC,
"exim user lost privilege for using %s option",
- trusted_config? "-D" : "-C");
+ f.trusted_config? "-D" : "-C");
/* Start up Perl interpreter if Perl support is configured and there is a
perl_startup option, and the configuration or the command line specifies
verifying/testing addresses or expansions. */
if ( (debug_selector & D_any || LOGGING(arguments))
- && really_exim && !list_options && !checking)
+ && f.really_exim && !list_options && !checking)
{
int i;
uschar *p = big_buffer;
configuration file. We leave these prints here to ensure that syslog setup,
logfile setup, and so on has already happened. */
-if (trusted_caller) DEBUG(D_any) debug_printf("trusted user\n");
-if (admin_user) DEBUG(D_any) debug_printf("admin user\n");
+if (f.trusted_caller) DEBUG(D_any) debug_printf("trusted user\n");
+if (f.admin_user) DEBUG(D_any) debug_printf("admin user\n");
/* Only an admin user may start the daemon or force a queue run in the default
configuration, but the queue run restriction can be relaxed. Only an admin
count. Only an admin user can use the test interface to scan for email
(because Exim will be in the spool dir and able to look at mails). */
-if (!admin_user)
+if (!f.admin_user)
{
BOOL debugset = (debug_selector & ~D_v) != 0;
- if (deliver_give_up || daemon_listen || malware_test_file ||
+ if (deliver_give_up || f.daemon_listen || malware_test_file ||
(count_queue && queue_list_requires_admin) ||
(list_queue && queue_list_requires_admin) ||
(queue_interval >= 0 && prod_requires_admin) ||
- (debugset && !running_in_test_harness))
+ (debugset && !f.running_in_test_harness))
{
fprintf(stderr, "exim:%s permission denied\n", debugset? " debugging" : "");
exit(EXIT_FAILURE);
if (real_uid != root_uid && real_uid != exim_uid &&
(continue_hostname != NULL ||
- (dont_deliver &&
- (queue_interval >= 0 || daemon_listen || msg_action_arg > 0)
- )) && !running_in_test_harness)
+ (f.dont_deliver &&
+ (queue_interval >= 0 || f.daemon_listen || msg_action_arg > 0)
+ )) && !f.running_in_test_harness)
{
fprintf(stderr, "exim: Permission denied\n");
return EXIT_FAILURE;
Note that authority for performing certain actions on messages is tested in the
queue_action() function. */
-if (!trusted_caller && !checking)
+if (!f.trusted_caller && !checking)
{
sender_host_name = sender_host_address = interface_address =
sender_ident = received_protocol = NULL;
/* If the caller is trusted, then they can use -G to suppress_local_fixups. */
if (flag_G)
{
- if (trusted_caller)
+ if (f.trusted_caller)
{
- suppress_local_fixups = suppress_local_fixups_default = TRUE;
+ f.suppress_local_fixups = f.suppress_local_fixups_default = TRUE;
DEBUG(D_acl) debug_printf("suppress_local_fixups forced on by -G\n");
}
else
if (real_uid == root_uid || real_uid == exim_uid || interface_port < 1024)
{
- is_inetd = TRUE;
+ f.is_inetd = TRUE;
sender_host_address = host_ntoa(-1, (struct sockaddr *)(&inetd_sock),
NULL, &sender_host_port);
if (mua_wrapper) log_write(0, LOG_MAIN|LOG_PANIC_DIE, "Input from "
#ifdef LOAD_AVG_NEEDS_ROOT
if (receiving_message &&
(queue_only_load >= 0 ||
- (is_inetd && smtp_load_reserve >= 0)
+ (f.is_inetd && smtp_load_reserve >= 0)
))
{
load_average = OS_GETLOADAVG();
if (!unprivileged && /* originally had root AND */
!removed_privilege && /* still got root AND */
- !daemon_listen && /* not starting the daemon */
+ !f.daemon_listen && /* not starting the daemon */
queue_interval <= 0 && /* (either kind of daemon) */
( /* AND EITHER */
deliver_drop_privilege || /* requested unprivileged */
queue_interval < 0 && /* not running the queue */
(msg_action_arg < 0 || /* and */
msg_action != MSG_DELIVER) && /* not delivering and */
- (!checking || !address_test_mode) /* not address checking */
+ (!checking || !f.address_test_mode) /* not address checking */
) ) )
exim_setugid(exim_uid, exim_gid, TRUE, US"privilege not needed");
}
/* We used to set up here to skip reading the ACL section, on
- (msg_action_arg > 0 || (queue_interval == 0 && !daemon_listen)
+ (msg_action_arg > 0 || (queue_interval == 0 && !f.daemon_listen)
Now, since the intro of the ${acl } expansion, ACL definitions may be
needed in transports so we lost the optimisation. */
if (msg_action_arg > 0 && msg_action != MSG_LOAD)
{
- if (prod_requires_admin && !admin_user)
+ if (prod_requires_admin && !f.admin_user)
{
fprintf(stderr, "exim: Permission denied\n");
exim_exit(EXIT_FAILURE, US"main");
}
set_process_info("delivering specified messages");
- if (deliver_give_up) forced_delivery = deliver_force_thaw = TRUE;
+ if (deliver_give_up) forced_delivery = f.deliver_force_thaw = TRUE;
for (i = msg_action_arg; i < argc; i++)
{
int status;
/* If only a single queue run is requested, without SMTP listening, we can just
turn into a queue runner, with an optional starting message id. */
-if (queue_interval == 0 && !daemon_listen)
+if (queue_interval == 0 && !f.daemon_listen)
{
DEBUG(D_queue_run) debug_printf("Single queue run%s%s%s%s\n",
(start_queue_run_id == NULL)? US"" : US" starting at ",
if (!originator_name)
{
- if (!sender_address || (!trusted_caller && filter_test == FTEST_NONE))
+ if (!sender_address || (!f.trusted_caller && filter_test == FTEST_NONE))
{
uschar *name = US pw->pw_gecos;
uschar *amp = Ustrchr(name, '&');
configuration specifies something to use. When running in the test harness,
any setting of unknown_login overrides the actual name. */
-if (originator_login == NULL || running_in_test_harness)
+if (originator_login == NULL || f.running_in_test_harness)
{
if (unknown_login != NULL)
{
for incoming messages via the daemon. The daemon cannot be run in mua_wrapper
mode. */
-if (daemon_listen || inetd_wait_mode || queue_interval > 0)
+if (f.daemon_listen || f.inetd_wait_mode || queue_interval > 0)
{
if (mua_wrapper)
{
if (test_rewrite_arg >= 0)
{
- really_exim = FALSE;
+ f.really_exim = FALSE;
if (test_rewrite_arg >= argc)
{
printf("-brw needs an address argument\n");
message via SMTP (inetd invocation or otherwise). */
if ((sender_address == NULL && !smtp_input) ||
- (!trusted_caller && filter_test == FTEST_NONE))
+ (!f.trusted_caller && filter_test == FTEST_NONE))
{
- sender_local = TRUE;
+ f.sender_local = TRUE;
/* A trusted caller can supply authenticated_sender and authenticated_id
via -oMas and -oMai and if so, they will already be set. Otherwise, force
!checking)) /* Not running tests, including filter tests */
{
sender_address = originator_login;
- sender_address_forced = FALSE;
+ f.sender_address_forced = FALSE;
sender_address_domain = 0;
}
}
/* Remember whether an untrusted caller set the sender address */
-sender_set_untrusted = sender_address != originator_login && !trusted_caller;
+f.sender_set_untrusted = sender_address != originator_login && !f.trusted_caller;
/* Ensure that the sender address is fully qualified unless it is the empty
address, which indicates an error message, or doesn't exist (root caller, smtp
stdin. Set debug_level to at least D_v to get full output for address testing.
*/
-if (verify_address_mode || address_test_mode)
+if (verify_address_mode || f.address_test_mode)
{
int exit_value = 0;
int flags = vopt_qualify;
if (msg_action_arg > 0 && msg_action == MSG_LOAD)
{
uschar spoolname[256]; /* Not big_buffer; used in spool_read_header() */
- if (!admin_user)
+ if (!f.admin_user)
{
fprintf(stderr, "exim: permission denied\n");
exit(EXIT_FAILURE);
/* Only admin users may see config-file macros this way */
- if (!admin_user) macros_user = macros = mlast = NULL;
+ if (!f.admin_user) macros_user = macros = mlast = NULL;
/* Allow $recipients for this testing */
- enable_dollar_recipients = TRUE;
+ f.enable_dollar_recipients = TRUE;
/* Expand command line items */
uschar *nah = expand_string(raw_active_hostname);
if (nah == NULL)
{
- if (!expand_string_forcedfail)
+ if (!f.expand_string_forcedfail)
log_write(0, LOG_MAIN|LOG_PANIC_DIE, "failed to expand \"%s\" "
"(smtp_active_hostname): %s", raw_active_hostname,
expand_string_message);
if (!sender_ident_set)
{
sender_ident = NULL;
- if (running_in_test_harness && sender_host_port != 0 &&
+ if (f.running_in_test_harness && sender_host_port != 0 &&
interface_address != NULL && interface_port != 0)
verify_get_ident(1413);
}
smtp_input = TRUE;
smtp_in = stdin;
smtp_out = stdout;
- sender_local = FALSE;
- sender_host_notsocket = TRUE;
+ f.sender_local = FALSE;
+ f.sender_host_notsocket = TRUE;
debug_file = stderr;
debug_fd = fileno(debug_file);
fprintf(stdout, "\n**** SMTP testing session as if from host %s\n"
if (mua_wrapper)
{
- synchronous_delivery = TRUE;
+ f.synchronous_delivery = TRUE;
arg_error_handling = ERRORS_STDERR;
remote_max_parallel = 1;
deliver_drop_privilege = TRUE;
- queue_smtp = FALSE;
+ f.queue_smtp = FALSE;
queue_smtp_domains = NULL;
#ifdef SUPPORT_I18N
message_utf8_downconvert = -1; /* convert-if-needed */
logging being sent down the socket and make an identd call to get the
sender_ident. */
-else if (is_inetd)
+else if (f.is_inetd)
{
(void)fclose(stderr);
exim_nullstd(); /* Re-open to /dev/null */
host_build_sender_fullhost();
set_process_info("handling incoming connection from %s via -oMa",
sender_fullhost);
- sender_host_notsocket = TRUE;
+ f.sender_host_notsocket = TRUE;
}
/* Otherwise, set the sender host as unknown except for inetd calls. This
prevents host checking in the case of -bs not from inetd and also for -bS. */
-else if (!is_inetd) sender_host_unknown = TRUE;
+else if (!f.is_inetd) f.sender_host_unknown = TRUE;
/* If stdout does not exist, then dup stdin to stdout. This can happen
if exim is started from inetd. In this case fd 0 will be set to the socket,
if (smtp_input)
{
- if (!is_inetd) set_process_info("accepting a local %sSMTP message from <%s>",
+ if (!f.is_inetd) set_process_info("accepting a local %sSMTP message from <%s>",
smtp_batched_input? "batched " : "",
(sender_address!= NULL)? sender_address : originator_login);
}
As a consequence of this, the waitpid() below is now excluded if we are sure
that SIG_IGN works. */
-if (!synchronous_delivery)
+if (!f.synchronous_delivery)
{
#ifdef SA_NOCLDWAIT
struct sigaction act;
if (smtp_batched_input && acl_not_smtp_start != NULL)
{
uschar *user_msg, *log_msg;
- enable_dollar_recipients = TRUE;
+ f.enable_dollar_recipients = TRUE;
(void)acl_check(ACL_WHERE_NOTSMTP_START, NULL, acl_not_smtp_start,
&user_msg, &log_msg);
- enable_dollar_recipients = FALSE;
+ f.enable_dollar_recipients = FALSE;
}
/* Now get the data for the message */
/* These options cannot be changed dynamically for non-SMTP messages */
- active_local_sender_retain = local_sender_retain;
- active_local_from_check = local_from_check;
+ f.active_local_sender_retain = local_sender_retain;
+ f.active_local_from_check = local_from_check;
/* Save before any rewriting */
allow_utf8_domains = b;
}
#endif
- if (domain == 0 && !allow_unqualified_recipient)
+ if (domain == 0 && !f.allow_unqualified_recipient)
{
recipient = NULL;
errmess = US"unqualified recipient address not allowed";
if (acl_not_smtp_start)
{
uschar *user_msg, *log_msg;
- enable_dollar_recipients = TRUE;
+ f.enable_dollar_recipients = TRUE;
(void)acl_check(ACL_WHERE_NOTSMTP_START, NULL, acl_not_smtp_start,
&user_msg, &log_msg);
- enable_dollar_recipients = FALSE;
+ f.enable_dollar_recipients = FALSE;
}
/* Pause for a while waiting for input. If none received in that time,
are ignored. */
if (mua_wrapper)
- local_queue_only = queue_only_policy = deliver_freeze = FALSE;
+ local_queue_only = f.queue_only_policy = f.deliver_freeze = FALSE;
/* Log the queueing here, when it will get a message id attached, but
not if queue_only is set (case 0). Case 1 doesn't happen here (too many
}
}
- else if (queue_only_policy || deliver_freeze)
+ else if (f.queue_only_policy || f.deliver_freeze)
cancel_cutthrough_connection(TRUE, US"no delivery; queueing");
/* Else do the delivery unless the ACL or local_scan() called for queue only
/* In the parent, wait if synchronous delivery is required. This will
always be the case in MUA wrapper mode. */
- if (synchronous_delivery)
+ if (f.synchronous_delivery)
{
int status;
while (wait(&status) != pid);
uschar *ss = expand_string(condition);
if (ss == NULL)
{
- if (!expand_string_forcedfail && !search_find_defer)
+ if (!f.expand_string_forcedfail && !f.search_find_defer)
log_write(0, LOG_MAIN|LOG_PANIC, "failed to expand condition \"%s\" "
"for %s %s: %s", condition, m1, m2, expand_string_message);
return FALSE;
static gstring *
authres_local(gstring * g, const uschar * sysname)
{
-if (!authentication_local)
+if (!f.authentication_local)
return g;
g = string_append(g, 3, US";\n\tlocal=pass (non-smtp, ", sysname, US")");
if (authenticated_id) g = string_append(g, 2, " u=", authenticated_id);
gstring * g = NULL;
int i;
-if (!enable_dollar_recipients) return NULL;
+if (!f.enable_dollar_recipients) return NULL;
for (i = 0; i < recipients_count; i++)
{
switch (vp->type)
{
case vtype_filter_int:
- if (!filter_running) return NULL;
+ if (!f.filter_running) return NULL;
/* Fall through */
/* VVVVVVVVVVVV */
case vtype_int:
/* first_delivery tests for first delivery attempt */
case ECOND_FIRST_DELIVERY:
- if (yield != NULL) *yield = deliver_firsttime == testfor;
+ if (yield != NULL) *yield = f.deliver_firsttime == testfor;
return s;
break;
case DEFER:
- expand_string_forcedfail = TRUE;
+ f.expand_string_forcedfail = TRUE;
/*FALLTHROUGH*/
default:
expand_string_message = string_sprintf("error from acl \"%s\"", sub[0]);
be the case if we were already skipping). */
sub1 = expand_string_internal(s, TRUE, &s, !yes, TRUE, resetok);
-if (sub1 == NULL && (yes || !expand_string_forcedfail)) goto FAILED;
-expand_string_forcedfail = FALSE;
+if (sub1 == NULL && (yes || !f.expand_string_forcedfail)) goto FAILED;
+f.expand_string_forcedfail = FALSE;
if (*s++ != '}')
{
errwhere = US"'yes' part did not end with '}'";
if (*s == '{')
{
sub2 = expand_string_internal(s+1, TRUE, &s, yes || skipping, TRUE, resetok);
- if (sub2 == NULL && (!yes || !expand_string_forcedfail)) goto FAILED;
- expand_string_forcedfail = FALSE;
+ if (sub2 == NULL && (!yes || !f.expand_string_forcedfail)) goto FAILED;
+ f.expand_string_forcedfail = FALSE;
if (*s++ != '}')
{
errwhere = US"'no' part did not start with '{'";
}
expand_string_message =
string_sprintf("\"%s\" failed and \"fail\" requested", type);
- expand_string_forcedfail = TRUE;
+ f.expand_string_forcedfail = TRUE;
goto FAILED;
}
}
: "considering",
string);
-expand_string_forcedfail = FALSE;
+f.expand_string_forcedfail = FALSE;
expand_string_message = US"";
while (*s != 0)
continue;
case DEFER:
- expand_string_forcedfail = TRUE;
+ f.expand_string_forcedfail = TRUE;
/*FALLTHROUGH*/
default:
expand_string_message = string_sprintf("error from acl \"%s\"", sub[0]);
}
lookup_value = search_find(handle, filename, key, partial, affix,
affixlen, starflags, &expand_setup);
- if (search_find_defer)
+ if (f.search_find_defer)
{
expand_string_message =
string_sprintf("lookup of \"%s\" gave DEFER: %s",
expand_string_message =
string_sprintf("Perl subroutine \"%s\" returned undef to force "
"failure", sub_arg[0]);
- expand_string_forcedfail = TRUE;
+ f.expand_string_forcedfail = TRUE;
}
goto EXPAND_FAILED;
}
/* Yield succeeded. Ensure forcedfail is unset, just in case it got
set during a callback from Perl. */
- expand_string_forcedfail = FALSE;
+ f.expand_string_forcedfail = FALSE;
yield = new_yield;
continue;
}
int fd;
int timeout = 5;
int save_ptr = yield->ptr;
- FILE *f;
+ FILE * fp;
uschar * arg;
uschar * sub_arg[4];
uschar * server_name = NULL;
#endif
/* Allow sequencing of test actions */
- if (running_in_test_harness) millisleep(100);
+ if (f.running_in_test_harness) millisleep(100);
/* Write the request string, if not empty or already done */
if (!tls_ctx && do_shutdown) shutdown(fd, SHUT_WR);
#endif
- if (running_in_test_harness) millisleep(100);
+ if (f.running_in_test_harness) millisleep(100);
/* Now we need to read from the socket, under a timeout. The function
that reads a file can be used. */
if (!tls_ctx)
- f = fdopen(fd, "rb");
+ fp = fdopen(fd, "rb");
sigalrm_seen = FALSE;
alarm(timeout);
yield =
#ifdef SUPPORT_TLS
tls_ctx ? cat_file_tls(tls_ctx, yield, sub_arg[3]) :
#endif
- cat_file(f, yield, sub_arg[3]);
+ cat_file(fp, yield, sub_arg[3]);
alarm(0);
#ifdef SUPPORT_TLS
}
else
#endif
- (void)fclose(f);
+ (void)fclose(fp);
/* After a timeout, we restore the pointer in the result, that is,
make sure we add nothing from the socket. */
else
{
expand_string_message = result == NULL ? US"(no message)" : result;
- if(status == FAIL_FORCED) expand_string_forcedfail = TRUE;
+ if(status == FAIL_FORCED) f.expand_string_forcedfail = TRUE;
else if(status != FAIL)
log_write(0, LOG_MAIN|LOG_PANIC, "dlfunc{%s}{%s} failed (%d): %s",
argv[0], argv[1], status, expand_string_message);
"missing in expanding ${addresses:%s}", --sub);
goto EXPAND_FAILED;
}
- parse_allow_group = TRUE;
+ f.parse_allow_group = TRUE;
for (;;)
{
separator. */
if (yield->ptr != save_ptr) yield->ptr--;
- parse_allow_group = FALSE;
+ f.parse_allow_group = FALSE;
continue;
}
string);
debug_printf_indent("%s" UTF8_HORIZ UTF8_HORIZ UTF8_HORIZ
"error message: %s\n",
- expand_string_forcedfail ? UTF8_VERT_RIGHT : UTF8_UP_RIGHT,
+ f.expand_string_forcedfail ? UTF8_VERT_RIGHT : UTF8_UP_RIGHT,
expand_string_message);
- if (expand_string_forcedfail)
+ if (f.expand_string_forcedfail)
debug_printf_indent(UTF8_UP_RIGHT "failure was forced\n");
}
if (resetok_p && !resetok) *resetok_p = FALSE;
int old_pool = store_pool;
uschar * s;
- search_find_defer = FALSE;
+ f.search_find_defer = FALSE;
malformed_header = FALSE;
store_pool = POOL_MAIN;
s = expand_string_internal(string, FALSE, NULL, FALSE, TRUE, NULL);
expanded = expand_string(svalue);
if (expanded == NULL)
{
- if (expand_string_forcedfail)
+ if (f.expand_string_forcedfail)
{
DEBUG(dbg_opt) debug_printf("expansion of \"%s\" forced failure\n", oname);
*rvalue = bvalue;
}
else
{
- if (search_find_defer) printf("search_find deferred\n");
+ if (f.search_find_defer) printf("search_find deferred\n");
printf("Failed: %s\n", expand_string_message);
- if (expand_string_forcedfail) printf("Forced failure\n");
+ if (f.expand_string_forcedfail) printf("Forced failure\n");
printf("\n");
}
}
yield = FALSE;
}
- if (!system_filtering && second_argument.b != TRUE_UNSET)
+ if (!f.system_filtering && second_argument.b != TRUE_UNSET)
{
*error_pointer = string_sprintf("header addition and removal is "
"available only in system filters: near line %d of filter file",
scan Cc: (hence the FALSE argument). */
case cond_personal:
- yield = system_filtering? FALSE : filter_personal(c->left.a, FALSE);
+ yield = f.system_filtering? FALSE : filter_personal(c->left.a, FALSE);
break;
case cond_delivered:
and filter testing and verification. */
case cond_firsttime:
- yield = filter_test != FTEST_NONE || message_id[0] == 0 || deliver_firsttime;
+ yield = filter_test != FTEST_NONE || message_id[0] == 0 || f.deliver_firsttime;
break;
/* Only TRUE if a message is actually being processed; FALSE for address
testing and verification. */
case cond_manualthaw:
- yield = message_id[0] != 0 && deliver_manual_thaw;
+ yield = message_id[0] != 0 && f.deliver_manual_thaw;
break;
/* The foranyaddress condition loops through a list of addresses */
}
yield = FALSE;
- parse_allow_group = TRUE; /* Allow group syntax */
+ f.parse_allow_group = TRUE; /* Allow group syntax */
while (*pp != 0)
{
pp = p + 1;
}
- parse_allow_group = FALSE; /* Reset group syntax flags */
- parse_found_group = FALSE;
+ f.parse_allow_group = FALSE; /* Reset group syntax flags */
+ f.parse_found_group = FALSE;
break;
/* All other conditions have left and right values that need expanding;
s = expargs[1];
- if (s != NULL && !system_filtering)
+ if (s != NULL && !f.system_filtering)
{
uschar *ownaddress = expand_string(US"$local_part@$domain");
if (strcmpic(ownaddress, s) != 0)
expect_endif = 0;
output_indent = 0;
-filter_running = TRUE;
+f.filter_running = TRUE;
for (i = 0; i < FILTER_VARIABLE_COUNT; i++) filter_n[i] = 0;
/* To save having to pass certain values about all the time, make them static.
if (log_fd >= 0) (void)close(log_fd);
expand_nmax = -1;
-filter_running = FALSE;
+f.filter_running = FALSE;
headers_charset = save_headers_charset;
DEBUG(D_route) debug_printf("Filter: end of processing\n");
if (!dot_ended && !feof(stdin))
{
- if (!dot_ends)
+ if (!f.dot_ends)
{
while ((ch = getc(stdin)) != EOF)
{
if (is_system)
{
- system_filtering = TRUE;
- enable_dollar_recipients = TRUE; /* Permit $recipients in system filter */
+ f.system_filtering = TRUE;
+ f.enable_dollar_recipients = TRUE; /* Permit $recipients in system filter */
yield = filter_interpret
(filebuf,
RDO_DEFER|RDO_FAIL|RDO_FILTER|RDO_FREEZE|RDO_REWRITE, &generated, &error);
- enable_dollar_recipients = FALSE;
- system_filtering = FALSE;
+ f.enable_dollar_recipients = FALSE;
+ f.system_filtering = FALSE;
}
else
{
int address_expansions_count = sizeof(address_expansions)/sizeof(uschar **);
-/* General global variables */
+/******************************************************************************/
+/* General global variables. Boolean flags are done as a group
+so that only one bit each is needed, packed, for all those we never
+need to take a pointer - and only a char for the rest.
+This means a struct, unfortunately since it clutters the sourcecode. */
+
+struct global_flags f =
+{
+ .acl_temp_details = FALSE,
+ .active_local_from_check = FALSE,
+ .active_local_sender_retain = FALSE,
+ .address_test_mode = FALSE,
+ .admin_user = FALSE,
+ .allow_auth_unadvertised= FALSE,
+ .allow_unqualified_recipient = TRUE, /* For local messages */
+ .allow_unqualified_sender = TRUE, /* Reset for SMTP */
+ .authentication_local = FALSE,
+
+ .background_daemon = TRUE,
+
+ .chunking_offered = FALSE,
+ .config_changed = FALSE,
+ .continue_more = FALSE,
+
+ .daemon_listen = FALSE,
+ .debug_daemon = FALSE,
+ .deliver_firsttime = FALSE,
+ .deliver_force = FALSE,
+ .deliver_freeze = FALSE,
+ .deliver_force_thaw = FALSE,
+ .deliver_manual_thaw = FALSE,
+ .deliver_selectstring_regex = FALSE,
+ .deliver_selectstring_sender_regex = FALSE,
+ .disable_callout_flush = FALSE,
+ .disable_delay_flush = FALSE,
+ .disable_logging = FALSE,
+#ifndef DISABLE_DKIM
+ .dkim_disable_verify = FALSE,
+#endif
+#ifdef EXPERIMENTAL_DMARC
+ .dmarc_has_been_checked = FALSE,
+ .dmarc_disable_verify = FALSE,
+ .dmarc_enable_forensic = FALSE,
+#endif
+ .dont_deliver = FALSE,
+ .dot_ends = TRUE,
+
+ .enable_dollar_recipients = FALSE,
+ .expand_string_forcedfail = FALSE,
+
+ .filter_running = FALSE,
+
+ .header_rewritten = FALSE,
+ .helo_verified = FALSE,
+ .helo_verify_failed = FALSE,
+ .host_checking_callout = FALSE,
+ .host_find_failed_syntax= FALSE,
+
+ .inetd_wait_mode = FALSE,
+ .is_inetd = FALSE,
+
+ .local_error_message = FALSE,
+ .log_testing_mode = FALSE,
+
+#ifdef WITH_CONTENT_SCAN
+ .no_mbox_unspool = FALSE,
+#endif
+ .no_multiline_responses = FALSE,
+
+ .parse_allow_group = FALSE,
+ .parse_found_group = FALSE,
+ .pipelining_enable = TRUE,
+#if defined(SUPPORT_PROXY) || defined(SUPPORT_SOCKS)
+ .proxy_session_failed = FALSE,
+#endif
+
+ .queue_2stage = FALSE,
+ .queue_only_policy = FALSE,
+ .queue_run_first_delivery = FALSE,
+ .queue_run_force = FALSE,
+ .queue_run_local = FALSE,
+ .queue_running = FALSE,
+ .queue_smtp = FALSE,
+
+ .really_exim = TRUE,
+ .receive_call_bombout = FALSE,
+ .recipients_discarded = FALSE,
+/* BOOL rfc821_domains = FALSE; <<< on the way out */
+ .running_in_test_harness = FALSE,
+
+ .search_find_defer = FALSE,
+ .sender_address_forced = FALSE,
+ .sender_host_notsocket = FALSE,
+ .sender_host_unknown = FALSE,
+ .sender_local = FALSE,
+ .sender_name_forced = FALSE,
+ .sender_set_untrusted = FALSE,
+/* BOOL sender_verified_responded = FALSE; /* never used? */
+ .smtp_authenticated = FALSE,
+ .smtp_in_pipelining_advertised = FALSE,
+ .smtp_in_pipelining_used = FALSE,
+ .spool_file_wireformat = FALSE,
+ .submission_mode = FALSE,
+ .suppress_local_fixups = FALSE,
+ .suppress_local_fixups_default = FALSE,
+ .synchronous_delivery = FALSE,
+ .system_filtering = FALSE,
+
+ .tcp_fastopen_ok = FALSE,
+ .tcp_in_fastopen = FALSE,
+ .tcp_in_fastopen_logged = FALSE,
+ .tcp_out_fastopen_logged= FALSE,
+ .timestamps_utc = FALSE,
+ .transport_filter_timed_out = FALSE,
+ .trusted_caller = FALSE,
+ .trusted_config = TRUE,
+};
+
+/******************************************************************************/
+/* These are the flags which are either variables or mainsection options,
+so an address is needed for access, or are exported to local_scan. */
+
+BOOL accept_8bitmime = TRUE; /* deliberately not RFC compliant */
+BOOL allow_domain_literals = FALSE;
+BOOL allow_mx_to_ip = FALSE;
+BOOL allow_utf8_domains = FALSE;
+BOOL authentication_failed = FALSE;
+
+BOOL bounce_return_body = TRUE;
+BOOL bounce_return_message = TRUE;
+BOOL check_rfc2047_length = TRUE;
+BOOL commandline_checks_require_admin = FALSE;
+
+#ifdef EXPERIMENTAL_DCC
+BOOL dcc_direct_add_header = FALSE;
+#endif
+BOOL debug_store = FALSE;
+BOOL delivery_date_remove = TRUE;
+BOOL deliver_drop_privilege = FALSE;
+#ifdef ENABLE_DISABLE_FSYNC
+BOOL disable_fsync = FALSE;
+#endif
+BOOL disable_ipv6 = FALSE;
+BOOL dns_csa_use_reverse = TRUE;
+BOOL drop_cr = FALSE; /* No longer used */
+
+BOOL envelope_to_remove = TRUE;
+BOOL exim_gid_set = TRUE; /* This gid is always set */
+BOOL exim_uid_set = TRUE; /* This uid is always set */
+BOOL extract_addresses_remove_arguments = TRUE;
+
+BOOL host_checking = FALSE;
+BOOL host_lookup_deferred = FALSE;
+BOOL host_lookup_failed = FALSE;
+BOOL ignore_fromline_local = FALSE;
+
+BOOL local_from_check = TRUE;
+BOOL local_sender_retain = FALSE;
+BOOL log_timezone = FALSE;
+BOOL message_body_newlines = FALSE;
+BOOL message_logs = TRUE;
+#ifdef SUPPORT_I18N
+BOOL message_smtputf8 = FALSE;
+#endif
+BOOL mua_wrapper = FALSE;
+
+BOOL preserve_message_logs = FALSE;
+BOOL print_topbitchars = FALSE;
+BOOL prod_requires_admin = TRUE;
+#if defined(SUPPORT_PROXY) || defined(SUPPORT_SOCKS)
+BOOL proxy_session = FALSE;
+#endif
+
+BOOL queue_list_requires_admin = TRUE;
+BOOL queue_only = FALSE;
+BOOL queue_only_load_latch = TRUE;
+BOOL queue_only_override = TRUE;
+BOOL queue_run_in_order = FALSE;
+BOOL recipients_max_reject = FALSE;
+BOOL return_path_remove = TRUE;
+
+BOOL smtp_batched_input = FALSE;
+BOOL sender_helo_dnssec = FALSE;
+BOOL sender_host_dnssec = FALSE;
+BOOL smtp_accept_keepalive = TRUE;
+BOOL smtp_check_spool_space = TRUE;
+BOOL smtp_enforce_sync = TRUE;
+BOOL smtp_etrn_serialize = TRUE;
+BOOL smtp_input = FALSE;
+BOOL smtp_return_error_details = FALSE;
+#ifdef SUPPORT_SPF
+BOOL spf_result_guessed = FALSE;
+#endif
+BOOL split_spool_directory = FALSE;
+BOOL spool_wireformat = FALSE;
+#ifdef EXPERIMENTAL_SRS
+BOOL srs_usehash = TRUE;
+BOOL srs_usetimestamp = TRUE;
+#endif
+BOOL strict_acl_vars = FALSE;
+BOOL strip_excess_angle_brackets = FALSE;
+BOOL strip_trailing_dot = FALSE;
+BOOL syslog_duplication = TRUE;
+BOOL syslog_pid = TRUE;
+BOOL syslog_timestamp = TRUE;
+BOOL system_filter_gid_set = FALSE;
+BOOL system_filter_uid_set = FALSE;
+
+BOOL tcp_nodelay = TRUE;
+BOOL write_rejectlog = TRUE;
+
+/******************************************************************************/
header_line *acl_added_headers = NULL;
tree_node *acl_anchor = NULL;
uschar *acl_smtp_starttls = NULL;
uschar *acl_smtp_vrfy = NULL;
-BOOL acl_temp_details = FALSE;
tree_node *acl_var_c = NULL;
tree_node *acl_var_m = NULL;
uschar *acl_verify_message = NULL;
US"0" /* unknown; not relevant */
};
-BOOL active_local_from_check = FALSE;
-BOOL active_local_sender_retain = FALSE;
-BOOL accept_8bitmime = TRUE; /* deliberately not RFC compliant */
uschar *add_environment = NULL;
address_item *addr_duplicate = NULL;
uschar *address_file = NULL;
uschar *address_pipe = NULL;
-BOOL address_test_mode = FALSE;
tree_node *addresslist_anchor = NULL;
int addresslist_count = 0;
gid_t *admin_groups = NULL;
-BOOL admin_user = FALSE;
-BOOL allow_auth_unadvertised= FALSE;
-BOOL allow_domain_literals = FALSE;
-BOOL allow_mx_to_ip = FALSE;
-BOOL allow_unqualified_recipient = TRUE; /* For local messages */
-BOOL allow_unqualified_sender = TRUE; /* Reset for SMTP */
-BOOL allow_utf8_domains = FALSE;
#ifdef EXPERIMENTAL_ARC
struct arc_set *arc_received = NULL;
uschar *authenticated_fail_id = NULL;
uschar *authenticated_id = NULL;
uschar *authenticated_sender = NULL;
-BOOL authentication_failed = FALSE;
-BOOL authentication_local = FALSE;
auth_instance *auths = NULL;
uschar *auth_advertise_hosts = US"*";
auth_instance auth_defaults = {
uschar *auth_vars[AUTH_VARS];
int auto_thaw = 0;
#ifdef WITH_CONTENT_SCAN
-BOOL av_failed = FALSE;
+int av_failed = FALSE; /* boolean but accessed as vtype_int*/
uschar *av_scanner = US"sophie:/var/run/sophie"; /* AV scanner */
#endif
-BOOL background_daemon = TRUE;
-
#if BASE_62 == 62
uschar *base62_chars=
US"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
uschar *bounce_message_file = NULL;
uschar *bounce_message_text = NULL;
uschar *bounce_recipient = NULL;
-BOOL bounce_return_body = TRUE;
int bounce_return_linesize_limit = 998;
-BOOL bounce_return_message = TRUE;
int bounce_return_size_limit = 100*1024;
uschar *bounce_sender_authentication = NULL;
uschar *check_dns_names_pattern= US"(?i)^(?>(?(1)\\.|())[^\\W](?>[a-z0-9/_-]*[^\\W])?)+(\\.?)$";
int check_log_inodes = 100;
int check_log_space = 10*1024; /* 10K Kbyte == 10MB */
-BOOL check_rfc2047_length = TRUE;
int check_spool_inodes = 100;
int check_spool_space = 10*1024; /* 10K Kbyte == 10MB */
uschar *chunking_advertise_hosts = US"*";
unsigned chunking_datasize = 0;
unsigned chunking_data_left = 0;
-BOOL chunking_offered = FALSE;
chunking_state_t chunking_state= CHUNKING_NOT_OFFERED;
const pcre *regex_CHUNKING = NULL;
uschar *client_authenticated_sender = NULL;
int clmacro_count = 0;
uschar *clmacros[MAX_CLMACROS];
-BOOL commandline_checks_require_admin = FALSE;
-BOOL config_changed = FALSE;
FILE *config_file = NULL;
const uschar *config_filename = NULL;
int config_lineno = 0;
uschar *continue_proxy_cipher = NULL;
uschar *continue_hostname = NULL;
uschar *continue_host_address = NULL;
-BOOL continue_more = FALSE;
int continue_sequence = 1;
uschar *continue_transport = NULL;
.nrcpt = 0, /* number of addresses */
};
-BOOL daemon_listen = FALSE;
uschar *daemon_smtp_port = US"smtp";
int daemon_startup_retries = 9;
int daemon_startup_sleep = 30;
#ifdef EXPERIMENTAL_DCC
-BOOL dcc_direct_add_header = FALSE;
uschar *dcc_header = NULL;
uschar *dcc_result = NULL;
uschar *dccifd_address = US"/usr/local/dcc/var/dccifd";
uschar *dccifd_options = US"header";
#endif
-BOOL debug_daemon = FALSE;
int debug_fd = -1;
FILE *debug_file = NULL;
int debug_notall[] = {
int debug_options_count = nelem(debug_options);
unsigned int debug_selector = 0;
-BOOL debug_store = FALSE;
int delay_warning[DELAY_WARNING_SIZE] = { DELAY_WARNING_SIZE, 1, 24*60*60 };
uschar *delay_warning_condition=
US"${if or {"
"{ match{$h_precedence:}{(?i)bulk|list|junk} }"
"{ match{$h_auto-submitted:}{(?i)auto-generated|auto-replied} }"
"} {no}{yes}}";
-BOOL delivery_date_remove = TRUE;
uschar *deliver_address_data = NULL;
int deliver_datafile = -1;
const uschar *deliver_domain = NULL;
uschar *deliver_domain_data = NULL;
const uschar *deliver_domain_orig = NULL;
const uschar *deliver_domain_parent = NULL;
-BOOL deliver_drop_privilege = FALSE;
-BOOL deliver_firsttime = FALSE;
-BOOL deliver_force = FALSE;
-BOOL deliver_freeze = FALSE;
time_t deliver_frozen_at = 0;
uschar *deliver_home = NULL;
const uschar *deliver_host = NULL;
uschar *deliver_localpart_parent = NULL;
uschar *deliver_localpart_prefix = NULL;
uschar *deliver_localpart_suffix = NULL;
-BOOL deliver_force_thaw = FALSE;
-BOOL deliver_manual_thaw = FALSE;
uschar *deliver_out_buffer = NULL;
int deliver_queue_load_max = -1;
address_item *deliver_recipients = NULL;
uschar *deliver_selectstring = NULL;
-BOOL deliver_selectstring_regex = FALSE;
uschar *deliver_selectstring_sender = NULL;
-BOOL deliver_selectstring_sender_regex = FALSE;
-BOOL disable_callout_flush = FALSE;
-BOOL disable_delay_flush = FALSE;
-#ifdef ENABLE_DISABLE_FSYNC
-BOOL disable_fsync = FALSE;
-#endif
-BOOL disable_ipv6 = FALSE;
-BOOL disable_logging = FALSE;
#ifndef DISABLE_DKIM
unsigned dkim_collect_input = 0;
uschar *dkim_cur_signer = NULL;
-BOOL dkim_disable_verify = FALSE;
int dkim_key_length = 0;
void *dkim_signatures = NULL;
uschar *dkim_signers = NULL;
uschar *dkim_verify_reason = NULL;
#endif
#ifdef EXPERIMENTAL_DMARC
-BOOL dmarc_has_been_checked = FALSE;
uschar *dmarc_domain_policy = NULL;
uschar *dmarc_forensic_sender = NULL;
uschar *dmarc_history_file = NULL;
uschar *dmarc_status_text = NULL;
uschar *dmarc_tld_file = NULL;
uschar *dmarc_used_domain = NULL;
-BOOL dmarc_disable_verify = FALSE;
-BOOL dmarc_enable_forensic = FALSE;
#endif
uschar *dns_again_means_nonexist = NULL;
int dns_csa_search_limit = 5;
-BOOL dns_csa_use_reverse = TRUE;
int dns_cname_loops = 1;
#ifdef SUPPORT_DANE
int dns_dane_ok = -1;
uschar *dnslist_value = NULL;
tree_node *domainlist_anchor = NULL;
int domainlist_count = 0;
-BOOL dont_deliver = FALSE;
-BOOL dot_ends = TRUE;
-BOOL drop_cr = FALSE; /* No longer used */
uschar *dsn_from = US DEFAULT_DSN_FROM;
-BOOL enable_dollar_recipients = FALSE;
-BOOL envelope_to_remove = TRUE;
int errno_quota = ERRNO_QUOTA;
uschar *errors_copy = NULL;
int error_handling = ERRORS_SENDER;
gid_t exim_gid = EXIM_GID;
-BOOL exim_gid_set = TRUE; /* This gid is always set */
uschar *exim_path = US BIN_DIRECTORY "/exim"
"\0<---------------Space to patch exim_path->";
uid_t exim_uid = EXIM_UID;
-BOOL exim_uid_set = TRUE; /* This uid is always set */
int expand_level = 0; /* Nesting depth, indent for debug */
int expand_forbid = 0;
int expand_nlength[EXPAND_MAXN+1];
int expand_nmax = -1;
uschar *expand_nstring[EXPAND_MAXN+1];
-BOOL expand_string_forcedfail = FALSE;
uschar *expand_string_message;
-BOOL extract_addresses_remove_arguments = TRUE;
uschar *extra_local_interfaces = NULL;
int fake_response = OK;
"legitimate message, it may still be "
"delivered to the target recipient(s).";
int filter_n[FILTER_VARIABLE_COUNT];
-BOOL filter_running = FALSE;
int filter_sn[FILTER_VARIABLE_COUNT];
int filter_test = FTEST_NONE;
uschar *filter_test_sfile = NULL;
int header_names_size = nelem(header_names);
-BOOL header_rewritten = FALSE;
uschar *helo_accept_junk_hosts = NULL;
uschar *helo_allow_chars = US"";
uschar *helo_lookup_domains = US"@ : @[]";
uschar *helo_try_verify_hosts = NULL;
-BOOL helo_verified = FALSE;
-BOOL helo_verify_failed = FALSE;
uschar *helo_verify_hosts = NULL;
const uschar *hex_digits = CUS"0123456789abcdef";
uschar *hold_domains = NULL;
-BOOL host_checking = FALSE;
-BOOL host_checking_callout = FALSE;
uschar *host_data = NULL;
-BOOL host_find_failed_syntax= FALSE;
uschar *host_lookup = NULL;
-BOOL host_lookup_deferred = FALSE;
-BOOL host_lookup_failed = FALSE;
uschar *host_lookup_order = US"bydns:byaddr";
uschar *host_lookup_msg = US"";
int host_number = 0;
uschar *hosts_connection_nolog = NULL;
int ignore_bounce_errors_after = 10*7*24*60*60; /* 10 weeks */
-BOOL ignore_fromline_local = FALSE;
uschar *ignore_fromline_hosts = NULL;
-BOOL inetd_wait_mode = FALSE;
int inetd_wait_timeout = -1;
uschar *initial_cwd = NULL;
uschar *interface_address = NULL;
int interface_port = -1;
-BOOL is_inetd = FALSE;
uschar *iterate_item = NULL;
int journal_fd = -1;
uschar *eldap_dn = NULL;
int load_average = -2;
-BOOL local_error_message = FALSE;
-BOOL local_from_check = TRUE;
uschar *local_from_prefix = NULL;
uschar *local_from_suffix = NULL;
uschar *local_scan_data = NULL;
int local_scan_timeout = 5*60;
#endif
-BOOL local_sender_retain = FALSE;
gid_t local_user_gid = (gid_t)(-1);
uid_t local_user_uid = (uid_t)(-1);
unsigned int log_selector[log_selector_size]; /* initialized in main() */
uschar *log_selector_string = NULL;
FILE *log_stderr = NULL;
-BOOL log_testing_mode = FALSE;
-BOOL log_timezone = FALSE;
uschar *login_sender_address = NULL;
uschar *lookup_dnssec_authenticated = NULL;
int lookup_open_max = 25;
int message_age = 0;
uschar *message_body = NULL;
uschar *message_body_end = NULL;
-BOOL message_body_newlines = FALSE;
int message_body_size = 0;
int message_body_visible = 500;
int message_ended = END_NOTSTARTED;
uschar message_id_option[MESSAGE_ID_LENGTH + 3];
uschar *message_id_external;
int message_linecount = 0;
-BOOL message_logs = TRUE;
int message_size = 0;
uschar *message_size_limit = US"50M";
#ifdef SUPPORT_I18N
-BOOL message_smtputf8 = FALSE;
int message_utf8_downconvert = 0; /* -1 ifneeded; 0 never; 1 always */
#endif
uschar message_subdir[2] = { 0, 0 };
int mime_part_count = -1;
#endif
-BOOL mua_wrapper = FALSE;
-
uid_t *never_users = NULL;
-#ifdef WITH_CONTENT_SCAN
-BOOL no_mbox_unspool = FALSE;
-#endif
-BOOL no_multiline_responses = FALSE;
const int on = 1; /* for setsockopt */
const int off = 0;
uschar *override_local_interfaces = NULL;
uschar *override_pid_file_path = NULL;
-BOOL parse_allow_group = FALSE;
-BOOL parse_found_group = FALSE;
uschar *percent_hack_domains = NULL;
uschar *pid_file_path = US PID_FILE_PATH
"\0<--------------Space to patch pid_file_path->";
-BOOL pipelining_enable = TRUE;
uschar *pipelining_advertise_hosts = US"*";
-BOOL preserve_message_logs = FALSE;
uschar *primary_hostname = NULL;
-BOOL print_topbitchars = FALSE;
uschar process_info[PROCESS_INFO_SIZE];
int process_info_len = 0;
uschar *process_log_path = NULL;
-BOOL prod_requires_admin = TRUE;
#if defined(SUPPORT_PROXY) || defined(SUPPORT_SOCKS)
uschar *hosts_proxy = US"";
int proxy_external_port = 0;
uschar *proxy_local_address = US"";
int proxy_local_port = 0;
-BOOL proxy_session = FALSE;
-BOOL proxy_session_failed = FALSE;
#endif
uschar *prvscheck_address = NULL;
const uschar *qualify_domain_recipient = NULL;
uschar *qualify_domain_sender = NULL;
-BOOL queue_2stage = FALSE;
uschar *queue_domains = NULL;
int queue_interval = -1;
-BOOL queue_list_requires_admin = TRUE;
uschar *queue_name = US"";
-BOOL queue_only = FALSE;
uschar *queue_only_file = NULL;
int queue_only_load = -1;
-BOOL queue_only_load_latch = TRUE;
-BOOL queue_only_override = TRUE;
-BOOL queue_only_policy = FALSE;
-BOOL queue_run_first_delivery = FALSE;
-BOOL queue_run_force = FALSE;
-BOOL queue_run_in_order = FALSE;
-BOOL queue_run_local = FALSE;
uschar *queue_run_max = US"5";
pid_t queue_run_pid = (pid_t)0;
int queue_run_pipe = -1;
-BOOL queue_running = FALSE;
-BOOL queue_smtp = FALSE;
uschar *queue_smtp_domains = NULL;
unsigned int random_seed = 0;
int rcpt_defer_count = 0;
gid_t real_gid;
uid_t real_uid;
-BOOL really_exim = TRUE;
-BOOL receive_call_bombout = FALSE;
int receive_linecount = 0;
int receive_messagecount = 0;
int receive_timeout = 0;
uschar *recipient_unqualified_hosts = NULL;
uschar *recipient_verify_failure = NULL;
int recipients_count = 0;
-BOOL recipients_discarded = FALSE;
recipient_item *recipients_list = NULL;
int recipients_list_max = 0;
int recipients_max = 0;
-BOOL recipients_max_reject = FALSE;
const pcre *regex_AUTH = NULL;
const pcre *regex_check_dns_names = NULL;
const pcre *regex_From = NULL;
int retry_maximum_timeout = 0; /* set from retry config */
retry_config *retries = NULL;
uschar *return_path = NULL;
-BOOL return_path_remove = TRUE;
int rewrite_existflags = 0;
uschar *rfc1413_hosts = US"@[]";
int rfc1413_query_timeout = 0;
-/* BOOL rfc821_domains = FALSE; <<< on the way out */
uid_t root_gid = ROOT_GID;
uid_t root_uid = ROOT_UID;
uschar *router_name = NULL;
ip_address_item *running_interfaces = NULL;
-BOOL running_in_test_harness = FALSE;
/* This is a weird one. The following string gets patched in the binary by the
script that sets up a copy of Exim for running in the test harness. It seems
int runrc = 0;
uschar *search_error_message = NULL;
-BOOL search_find_defer = FALSE;
uschar *self_hostname = NULL;
uschar *sender_address = NULL;
unsigned int sender_address_cache[(MAX_NAMED_LIST * 2)/32];
uschar *sender_address_data = NULL;
-BOOL sender_address_forced = FALSE;
uschar *sender_address_unrewritten = NULL;
uschar *sender_data = NULL;
unsigned int sender_domain_cache[(MAX_NAMED_LIST * 2)/32];
uschar *sender_fullhost = NULL;
-BOOL sender_helo_dnssec = FALSE;
uschar *sender_helo_name = NULL;
uschar **sender_host_aliases = &no_aliases;
uschar *sender_host_address = NULL;
uschar *sender_host_authenticated = NULL;
uschar *sender_host_auth_pubname = NULL;
unsigned int sender_host_cache[(MAX_NAMED_LIST * 2)/32];
-BOOL sender_host_dnssec = FALSE;
uschar *sender_host_name = NULL;
int sender_host_port = 0;
-BOOL sender_host_notsocket = FALSE;
-BOOL sender_host_unknown = FALSE;
uschar *sender_ident = NULL;
-BOOL sender_local = FALSE;
-BOOL sender_name_forced = FALSE;
uschar *sender_rate = NULL;
uschar *sender_rate_limit = NULL;
uschar *sender_rate_period = NULL;
uschar *sender_rcvhost = NULL;
-BOOL sender_set_untrusted = FALSE;
uschar *sender_unqualified_hosts = NULL;
uschar *sender_verify_failure = NULL;
address_item *sender_verified_list = NULL;
address_item *sender_verified_failed = NULL;
int sender_verified_rc = -1;
-BOOL sender_verified_responded = FALSE;
uschar *sending_ip_address = NULL;
int sending_port = -1;
SIGNAL_BOOL sigalrm_seen = FALSE;
uschar **sighup_argv = NULL;
int slow_lookup_log = 0; /* millisecs, zero disables */
int smtp_accept_count = 0;
-BOOL smtp_accept_keepalive = TRUE;
int smtp_accept_max = 20;
int smtp_accept_max_nonmail= 10;
uschar *smtp_accept_max_nonmail_hosts = US"*";
int smtp_accept_queue_per_connection = 10;
int smtp_accept_reserve = 0;
uschar *smtp_active_hostname = NULL;
-BOOL smtp_authenticated = FALSE;
uschar *smtp_banner = US"$smtp_active_hostname ESMTP "
"Exim $version_number $tod_full"
"\0<---------------Space to patch smtp_banner->";
-BOOL smtp_batched_input = FALSE;
-BOOL smtp_check_spool_space = TRUE;
int smtp_ch_index = 0;
uschar *smtp_cmd_argument = NULL;
uschar *smtp_cmd_buffer = NULL;
int smtp_connect_backlog = 20;
double smtp_delay_mail = 0.0;
double smtp_delay_rcpt = 0.0;
-BOOL smtp_enforce_sync = TRUE;
FILE *smtp_in = NULL;
-BOOL smtp_in_pipelining_advertised = FALSE;
-BOOL smtp_in_pipelining_used = FALSE;
-BOOL smtp_input = FALSE;
int smtp_load_reserve = -1;
int smtp_mailcmd_count = 0;
FILE *smtp_out = NULL;
uschar *smtp_etrn_command = NULL;
-BOOL smtp_etrn_serialize = TRUE;
int smtp_max_synprot_errors= 3;
int smtp_max_unknown_commands = 3;
uschar *smtp_notquit_reason = NULL;
int smtp_receive_timeout = 5*60;
uschar *smtp_receive_timeout_s = NULL;
uschar *smtp_reserve_hosts = NULL;
-BOOL smtp_return_error_details = FALSE;
int smtp_rlm_base = 0;
double smtp_rlm_factor = 0.0;
int smtp_rlm_limit = 0;
uschar *spf_header_comment = NULL;
uschar *spf_received = NULL;
uschar *spf_result = NULL;
-BOOL spf_result_guessed = FALSE;
uschar *spf_smtp_comment = NULL;
#endif
-BOOL split_spool_directory = FALSE;
FILE *spool_data_file = NULL;
uschar *spool_directory = US SPOOL_DIRECTORY
"\0<--------------Space to patch spool_directory->";
-BOOL spool_file_wireformat = FALSE;
-BOOL spool_wireformat = FALSE;
#ifdef EXPERIMENTAL_SRS
uschar *srs_config = NULL;
uschar *srs_db_address = NULL;
uschar *srs_recipient = NULL;
uschar *srs_secrets = NULL;
uschar *srs_status = NULL;
-BOOL srs_usehash = TRUE;
-BOOL srs_usetimestamp = TRUE;
#endif
-BOOL strict_acl_vars = FALSE;
int string_datestamp_offset= -1;
int string_datestamp_length= 0;
int string_datestamp_type = -1;
-BOOL strip_excess_angle_brackets = FALSE;
-BOOL strip_trailing_dot = FALSE;
uschar *submission_domain = NULL;
-BOOL submission_mode = FALSE;
uschar *submission_name = NULL;
-BOOL suppress_local_fixups = FALSE;
-BOOL suppress_local_fixups_default = FALSE;
-BOOL synchronous_delivery = FALSE;
-BOOL syslog_duplication = TRUE;
int syslog_facility = LOG_MAIL;
-BOOL syslog_pid = TRUE;
uschar *syslog_processname = US"exim";
-BOOL syslog_timestamp = TRUE;
uschar *system_filter = NULL;
uschar *system_filter_directory_transport = NULL;
uschar *system_filter_reply_transport = NULL;
gid_t system_filter_gid = 0;
-BOOL system_filter_gid_set = FALSE;
uid_t system_filter_uid = (uid_t)-1;
-BOOL system_filter_uid_set = FALSE;
-BOOL system_filtering = FALSE;
-BOOL tcp_fastopen_ok = FALSE;
blob tcp_fastopen_nodata = { .data = NULL, .len = 0 };
-BOOL tcp_in_fastopen = FALSE;
-BOOL tcp_in_fastopen_logged = FALSE;
-BOOL tcp_nodelay = TRUE;
int tcp_out_fastopen = 0;
-BOOL tcp_out_fastopen_logged= FALSE;
#ifdef USE_TCP_WRAPPERS
uschar *tcp_wrappers_daemon_name = US TCP_WRAPPERS_DAEMON_NAME;
#endif
int test_harness_load_avg = 0;
int thismessage_size_limit = 0;
int timeout_frozen_after = 0;
-BOOL timestamps_utc = FALSE;
transport_instance *transports = NULL;
int transport_newlines;
const uschar **transport_filter_argv = NULL;
int transport_filter_timeout;
-BOOL transport_filter_timed_out = FALSE;
int transport_write_timeout= 0;
tree_node *tree_dns_fails = NULL;
tree_node *tree_nonrecipients = NULL;
tree_node *tree_unusable = NULL;
-BOOL trusted_caller = FALSE;
-BOOL trusted_config = TRUE;
gid_t *trusted_groups = NULL;
uid_t *trusted_users = NULL;
uschar *timezone_string = US TIMEZONE_DEFAULT;
int warning_count = 0;
uschar *warnmsg_delay = NULL;
uschar *warnmsg_recipients = NULL;
-BOOL write_rejectlog = TRUE;
/* End of globals.c */
extern const uschar **address_expansions[ADDRESS_EXPANSIONS_COUNT];
+/* Flags for which we don't need an address ever so can use a bitfield */
+
+extern struct global_flags {
+ BOOL acl_temp_details :1; /* TRUE to give details for 4xx error */
+ BOOL active_local_from_check :1; /* For adding Sender: (switchable) */
+ BOOL active_local_sender_retain :1; /* For keeping Sender: (switchable) */
+ BOOL address_test_mode :1; /* True for -bt */
+ BOOL admin_user :1; /* True if caller can do admin */
+ BOOL allow_auth_unadvertised :1; /* As it says */
+ BOOL allow_unqualified_recipient :1; /* For local messages */ /* As it says */
+ BOOL allow_unqualified_sender :1; /* Reset for SMTP */ /* Ditto */
+ BOOL authentication_local :1; /* TRUE if non-smtp (implicit authentication) */
+
+ BOOL background_daemon :1; /* Set FALSE to keep in foreground */
+
+ BOOL chunking_offered :1;
+ BOOL config_changed :1; /* True if -C used */
+ BOOL continue_more :1; /* Flag more addresses waiting */
+
+ BOOL daemon_listen :1; /* True if listening required */
+ BOOL debug_daemon :1; /* Debug the daemon process only */
+ BOOL deliver_firsttime :1; /* True for first delivery attempt */
+ BOOL deliver_force :1; /* TRUE if delivery was forced */
+ BOOL deliver_freeze :1; /* TRUE if delivery is frozen */
+ BOOL deliver_force_thaw :1; /* TRUE to force thaw in queue run */
+ BOOL deliver_manual_thaw :1; /* TRUE if manually thawed */
+ BOOL deliver_selectstring_regex :1; /* String is regex */
+ BOOL deliver_selectstring_sender_regex :1; /* String is regex */
+ BOOL disable_callout_flush :1; /* Don't flush before callouts */
+ BOOL disable_delay_flush :1; /* Don't flush before "delay" in ACL */
+ BOOL disable_logging :1; /* Disables log writing when TRUE */
+#ifndef DISABLE_DKIM
+ BOOL dkim_disable_verify :1; /* Set via ACL control statement. When set, DKIM verification is disabled for the current message */
+#endif
+#ifdef EXPERIMENTAL_DMARC
+ BOOL dmarc_has_been_checked :1; /* Global variable to check if test has been called yet */
+ BOOL dmarc_disable_verify :1; /* Set via ACL control statement. When set, DMARC verification is disabled for the current message */
+ BOOL dmarc_enable_forensic :1; /* Set via ACL control statement. When set, DMARC forensic reports are enabled for the current message */
+#endif
+ BOOL dont_deliver :1; /* TRUE for -N option */
+ BOOL dot_ends :1; /* TRUE if "." ends non-SMTP input */
+
+ BOOL enable_dollar_recipients :1; /* Make $recipients available */
+ BOOL expand_string_forcedfail :1; /* TRUE if failure was "expected" */
+
+ BOOL filter_running :1; /* TRUE while running a filter */
+
+ BOOL header_rewritten :1; /* TRUE if header changed by router */
+ BOOL helo_verified :1; /* True if HELO verified */
+ BOOL helo_verify_failed :1; /* True if attempt failed */
+ BOOL host_checking_callout :1; /* TRUE if real callout wanted */
+ BOOL host_find_failed_syntax :1; /* DNS syntax check failure */
+
+ BOOL inetd_wait_mode :1; /* Whether running in inetd wait mode */
+ BOOL is_inetd :1; /* True for inetd calls */
+
+ BOOL local_error_message :1; /* True if handling one of these */
+ BOOL log_testing_mode :1; /* TRUE in various testing modes */
+
+#ifdef WITH_CONTENT_SCAN
+ BOOL no_mbox_unspool :1; /* don't unlink files in /scan directory */
+#endif
+ BOOL no_multiline_responses :1; /* For broken clients */
+
+ BOOL parse_allow_group :1; /* Allow group syntax */
+ BOOL parse_found_group :1; /* In the middle of a group */
+ BOOL pipelining_enable :1; /* As it says */
+#if defined(SUPPORT_PROXY) || defined(SUPPORT_SOCKS)
+ BOOL proxy_session_failed :1; /* TRUE if required proxy negotiation failed */
+#endif
+
+ BOOL queue_2stage :1; /* Run queue in 2-stage manner */
+ BOOL queue_only_policy :1; /* ACL or local_scan wants queue_only */
+ BOOL queue_run_first_delivery :1; /* If TRUE, first deliveries only */
+ BOOL queue_run_force :1; /* TRUE to force during queue run */
+ BOOL queue_run_local :1; /* Local deliveries only in queue run */
+ BOOL queue_running :1; /* TRUE for queue running process and */
+ BOOL queue_smtp :1; /* Disable all immediate SMTP (-odqs)*/
+
+ BOOL really_exim :1; /* FALSE in utilities */
+ BOOL receive_call_bombout :1; /* Flag for crashing log */
+ BOOL recipients_discarded :1; /* By an ACL */
+ BOOL running_in_test_harness :1; /*TRUE when running_status is patched */
+
+ BOOL search_find_defer :1; /* Set TRUE if lookup deferred */
+ BOOL sender_address_forced :1; /* Set by -f */
+ BOOL sender_host_notsocket :1; /* Set for -bs and -bS */
+ BOOL sender_host_unknown :1; /* TRUE for -bs and -bS except inetd */
+ BOOL sender_local :1; /* TRUE for local senders */
+ BOOL sender_name_forced :1; /* Set by -F */
+ BOOL sender_set_untrusted :1; /* Sender set by untrusted caller */
+ BOOL smtp_authenticated :1; /* Sending client has authenticated */
+ BOOL smtp_in_pipelining_advertised :1; /* server advertised PIPELINING */
+ BOOL smtp_in_pipelining_used :1; /* server noted client using PIPELINING */
+ BOOL spool_file_wireformat :1; /* current -D file has CRLF rather than NL */
+ BOOL submission_mode :1; /* Can be forced from ACL */
+ BOOL suppress_local_fixups :1; /* Can be forced from ACL */
+ BOOL suppress_local_fixups_default :1; /* former is reset to this; override with -G */
+ BOOL synchronous_delivery :1; /* TRUE if -odi is set */
+ BOOL system_filtering :1; /* TRUE when running system filter */
+
+ BOOL tcp_fastopen_ok :1; /* appears to be supported by kernel */
+ BOOL tcp_in_fastopen :1; /* conn usefully used fastopen */
+ BOOL tcp_in_fastopen_logged :1; /* one-time logging */
+ BOOL tcp_out_fastopen_logged :1; /* one-time logging */
+ BOOL timestamps_utc :1; /* Use UTC for all times */
+ BOOL transport_filter_timed_out :1; /* True if it did */
+ BOOL trusted_caller :1; /* Caller is trusted */
+ BOOL trusted_config :1; /* Configuration file is trusted */
+} f;
+
+
/* General global variables */
extern BOOL accept_8bitmime; /* Allow *BITMIME incoming */
extern uschar *acl_smtp_rcpt; /* ACL run for RCPT */
extern uschar *acl_smtp_starttls; /* ACL run for STARTTLS */
extern uschar *acl_smtp_vrfy; /* ACL run for VRFY */
-extern BOOL acl_temp_details; /* TRUE to give details for 4xx error */
extern tree_node *acl_var_c; /* ACL connection variables */
extern tree_node *acl_var_m; /* ACL message variables */
extern uschar *acl_verify_message; /* User message for verify failure */
extern string_item *acl_warn_logged; /* Logged lines */
extern uschar *acl_wherecodes[]; /* Response codes for ACL fails */
extern uschar *acl_wherenames[]; /* Names for messages */
-extern BOOL active_local_from_check;/* For adding Sender: (switchable) */
-extern BOOL active_local_sender_retain; /* For keeping Sender: (switchable) */
extern address_item *addr_duplicate; /* Duplicate address list */
extern address_item address_defaults; /* Default data for address item */
extern uschar *address_file; /* Name of file when delivering to one */
extern uschar *address_pipe; /* Pipe command when delivering to one */
-extern BOOL address_test_mode; /* True for -bt */
extern tree_node *addresslist_anchor; /* Tree of defined address lists */
extern int addresslist_count; /* Number defined */
extern gid_t *admin_groups; /* List of admin groups */
-extern BOOL admin_user; /* True if caller can do admin */
-extern BOOL allow_auth_unadvertised;/* As it says */
extern BOOL allow_domain_literals; /* As it says */
extern BOOL allow_mx_to_ip; /* Allow MX records to -> ip address */
-extern BOOL allow_unqualified_recipient; /* As it says */
-extern BOOL allow_unqualified_sender; /* Ditto */
#ifdef EXPERIMENTAL_ARC
struct arc_set *arc_received; /* highest ARC instance evaluation struct */
extern int arc_received_instance; /* highest ARC instance number in headers */
extern uschar *authenticated_id; /* ID that was authenticated */
extern uschar *authenticated_sender; /* From AUTH on MAIL */
extern BOOL authentication_failed; /* TRUE if AUTH was tried and failed */
-extern BOOL authentication_local; /* TRUE if non-smtp (implicit authentication) */
extern uschar *auth_advertise_hosts; /* Only advertise to these */
extern auth_info auths_available[]; /* Vector of available auth mechanisms */
extern auth_instance *auths; /* Chain of instantiated auths */
extern uschar *auth_vars[]; /* $authn variables */
extern int auto_thaw; /* Auto-thaw interval */
#ifdef WITH_CONTENT_SCAN
-extern BOOL av_failed; /* TRUE if the AV process failed */
+extern int av_failed; /* TRUE if the AV process failed */
extern uschar *av_scanner; /* AntiVirus scanner to use for the malware condition */
#endif
-extern BOOL background_daemon; /* Set FALSE to keep in foreground */
extern uschar *base62_chars; /* Table of base-62 characters */
extern uschar *bi_command; /* Command for -bi option */
extern uschar *big_buffer; /* Used for various temp things */
extern uschar *chunking_advertise_hosts; /* RFC 3030 CHUNKING */
extern unsigned chunking_datasize;
extern unsigned chunking_data_left;
-extern BOOL chunking_offered;
extern chunking_state_t chunking_state;
extern uschar *client_authenticator; /* Authenticator name used for smtp delivery */
extern uschar *client_authenticated_id; /* "login" name used for SMTP AUTH */
extern uschar *clmacros[]; /* Copy of them, for re-exec */
extern BOOL commandline_checks_require_admin; /* belt and braces for insecure setups */
extern int connection_max_messages;/* Max down one SMTP connection */
-extern BOOL config_changed; /* True if -C used */
extern FILE *config_file; /* Configuration file */
extern const uschar *config_filename; /* Configuration file name */
extern gid_t config_gid; /* Additional group owner */
extern uschar *continue_proxy_cipher; /* TLS cipher for proxied continued delivery */
extern uschar *continue_hostname; /* Host for continued delivery */
extern uschar *continue_host_address; /* IP address for ditto */
-extern BOOL continue_more; /* Flag more addresses waiting */
extern int continue_sequence; /* Sequence num for continued delivery */
extern uschar *continue_transport; /* Transport for continued delivery */
} cut_t;
extern cut_t cutthrough; /* Deliver-concurrently */
-extern BOOL daemon_listen; /* True if listening required */
extern uschar *daemon_smtp_port; /* Can be a list of ports */
extern int daemon_startup_retries; /* Number of times to retry */
extern int daemon_startup_sleep; /* Sleep between retries */
extern uschar *dccifd_options; /* options for the dccifd daemon */
#endif
-extern BOOL debug_daemon; /* Debug the daemon process only */
extern int debug_fd; /* The fd for debug_file */
extern FILE *debug_file; /* Where to write debugging info */
extern int debug_notall[]; /* Debug options excluded from +all */
extern const uschar *deliver_domain_orig; /* The original local domain for delivery */
extern const uschar *deliver_domain_parent; /* The parent domain for delivery */
extern BOOL deliver_drop_privilege; /* TRUE for unprivileged delivery */
-extern BOOL deliver_firsttime; /* True for first delivery attempt */
-extern BOOL deliver_force; /* TRUE if delivery was forced */
-extern BOOL deliver_freeze; /* TRUE if delivery is frozen */
extern time_t deliver_frozen_at; /* Time of freezing */
extern uschar *deliver_home; /* Home directory for pipes */
extern const uschar *deliver_host; /* (First) host for routed local deliveries */
extern uschar *deliver_localpart_parent; /* The parent local part for delivery */
extern uschar *deliver_localpart_prefix; /* The stripped prefix, if any */
extern uschar *deliver_localpart_suffix; /* The stripped suffix, if any */
-extern BOOL deliver_force_thaw; /* TRUE to force thaw in queue run */
-extern BOOL deliver_manual_thaw; /* TRUE if manually thawed */
extern uschar *deliver_out_buffer; /* Buffer for copying file */
extern int deliver_queue_load_max; /* Different value for queue running */
extern address_item *deliver_recipients; /* Current set of addresses */
extern uschar *deliver_selectstring; /* For selecting by recipient */
-extern BOOL deliver_selectstring_regex; /* String is regex */
extern uschar *deliver_selectstring_sender; /* For selecting by sender */
-extern BOOL deliver_selectstring_sender_regex; /* String is regex */
-extern BOOL disable_callout_flush; /* Don't flush before callouts */
-extern BOOL disable_delay_flush; /* Don't flush before "delay" in ACL */
#ifdef ENABLE_DISABLE_FSYNC
extern BOOL disable_fsync; /* Not for normal use */
#endif
extern BOOL disable_ipv6; /* Don't do any IPv6 things */
-extern BOOL disable_logging; /* Disables log writing when TRUE */
#ifndef DISABLE_DKIM
extern unsigned dkim_collect_input; /* Runtime count of dkim signtures; tracks wether SMTP input is fed to DKIM validation */
extern uschar *dkim_cur_signer; /* Expansion variable, holds the current "signer" domain or identity during a acl_smtp_dkim run */
-extern BOOL dkim_disable_verify; /* Set via ACL control statement. When set, DKIM verification is disabled for the current message */
extern int dkim_key_length; /* Expansion variable, length of signing key in bits */
extern void *dkim_signatures; /* Actually a (pdkim_signature *) but most files do not need to know */
extern uschar *dkim_signers; /* Expansion variable, holds colon-separated list of domains and identities that have signed a message */
extern uschar *dkim_verify_reason; /* result for this signature */
#endif
#ifdef EXPERIMENTAL_DMARC
-extern BOOL dmarc_has_been_checked; /* Global variable to check if test has been called yet */
extern uschar *dmarc_domain_policy; /* Expansion for declared policy of used domain */
extern uschar *dmarc_forensic_sender; /* Set sender address for forensic reports */
extern uschar *dmarc_history_file; /* Expansion variable, file to store dmarc results */
extern uschar *dmarc_status_text; /* Expansion variable, human readable value */
extern uschar *dmarc_tld_file; /* Mozilla TLDs text file */
extern uschar *dmarc_used_domain; /* Expansion variable, domain libopendmarc chose for DMARC policy lookup */
-extern BOOL dmarc_disable_verify; /* Set via ACL control statement. When set, DMARC verification is disabled for the current message */
-extern BOOL dmarc_enable_forensic; /* Set via ACL control statement. When set, DMARC forensic reports are enabled for the current message */
#endif
extern uschar *dns_again_means_nonexist; /* Domains that are badly set up */
extern uschar *dnslist_value; /* DNS (black) list IP address */
extern tree_node *domainlist_anchor; /* Tree of defined domain lists */
extern int domainlist_count; /* Number defined */
-extern BOOL dont_deliver; /* TRUE for -N option */
-extern BOOL dot_ends; /* TRUE if "." ends non-SMTP input */
/* This option is now a no-opt, retained for compatibility */
extern BOOL drop_cr; /* For broken local MUAs */
extern uschar *dsn_from; /* From: string for DSNs */
-extern BOOL enable_dollar_recipients; /* Make $recipients available */
extern BOOL envelope_to_remove; /* Remove envelope_to_headers */
extern int errno_quota; /* Quota errno in this OS */
extern int error_handling; /* Error handling style */
extern int expand_nlength[]; /* Lengths of numbered strings */
extern int expand_nmax; /* Max numerical value */
extern uschar *expand_nstring[]; /* Numbered strings */
-extern BOOL expand_string_forcedfail; /* TRUE if failure was "expected" */
extern BOOL extract_addresses_remove_arguments; /* Controls -t behaviour */
extern uschar *extra_local_interfaces; /* Local, non-listen interfaces */
extern int fake_response; /* Fake FAIL or DEFER response to data */
extern uschar *fake_response_text; /* User defined message for the above. Default is in globals.c. */
extern int filter_n[FILTER_VARIABLE_COUNT]; /* filter variables */
-extern BOOL filter_running; /* TRUE while running a filter */
extern int filter_sn[FILTER_VARIABLE_COUNT]; /* variables set by system filter */
extern int filter_test; /* Filter test type */
extern uschar *filter_test_sfile; /* System filter test file */
extern int header_line_maxsize; /* Max for an individual line */
extern header_name header_names[]; /* Table of header names */
extern int header_names_size; /* Number of entries */
-extern BOOL header_rewritten; /* TRUE if header changed by router */
extern uschar *helo_accept_junk_hosts; /* Allowed to use junk arg */
extern uschar *helo_allow_chars; /* Rogue chars to allow in HELO/EHLO */
extern uschar *helo_lookup_domains; /* If these given, lookup host name */
extern uschar *helo_try_verify_hosts; /* Soft check HELO argument for these */
-extern BOOL helo_verified; /* True if HELO verified */
-extern BOOL helo_verify_failed; /* True if attempt failed */
extern uschar *helo_verify_hosts; /* Hard check HELO argument for these */
extern const uschar *hex_digits; /* Used in several places */
extern uschar *hold_domains; /* Hold up deliveries to these */
-extern BOOL host_find_failed_syntax;/* DNS syntax check failure */
-extern BOOL host_checking_callout; /* TRUE if real callout wanted */
extern uschar *host_data; /* Obtained from lookup in ACL */
extern uschar *host_lookup; /* For which IP addresses are always looked up */
extern BOOL host_lookup_deferred; /* TRUE if lookup deferred */
extern int ignore_bounce_errors_after; /* Keep them for this time. */
extern BOOL ignore_fromline_local; /* Local SMTP ignore fromline */
extern uschar *ignore_fromline_hosts; /* Hosts permitted to send "From " */
-extern BOOL inetd_wait_mode; /* Whether running in inetd wait mode */
extern int inetd_wait_timeout; /* Timeout for inetd wait mode */
extern uschar *initial_cwd; /* The directory we where in at startup */
-extern BOOL is_inetd; /* True for inetd calls */
extern uschar *iterate_item; /* Item from iterate list */
extern int journal_fd; /* Fd for journal file */
extern uschar *eldap_dn; /* Where LDAP DNs are left */
extern int load_average; /* Most recently read load average */
-extern BOOL local_error_message; /* True if handling one of these */
extern BOOL local_from_check; /* For adding Sender: (global value) */
extern uschar *local_from_prefix; /* Permitted prefixes */
extern uschar *local_from_suffix; /* Permitted suffixes */
extern unsigned int log_selector[]; /* Bit map of logging options */
extern uschar *log_selector_string; /* As supplied in the config */
extern FILE *log_stderr; /* Copy of stderr for log use, or NULL */
-extern BOOL log_testing_mode; /* TRUE in various testing modes */
extern BOOL log_timezone; /* TRUE to include the timezone in log lines */
extern uschar *login_sender_address; /* The actual sender address */
extern lookup_info **lookup_list; /* Array of pointers to available lookups */
extern uid_t *never_users; /* List of uids never to be used */
#ifdef WITH_CONTENT_SCAN
-extern BOOL no_mbox_unspool; /* don't unlink files in /scan directory */
#endif
-extern BOOL no_multiline_responses; /* For broken clients */
extern const int on; /* For setsockopt */
extern const int off;
extern uschar *override_local_interfaces; /* Value of -oX argument */
extern uschar *override_pid_file_path; /* Value of -oP argument */
-extern BOOL parse_allow_group; /* Allow group syntax */
-extern BOOL parse_found_group; /* In the middle of a group */
extern uschar *percent_hack_domains; /* Local domains for which '% operates */
extern uschar *pid_file_path; /* For writing daemon pids */
extern uschar *pipelining_advertise_hosts; /* As it says */
-extern BOOL pipelining_enable; /* As it says */
#ifndef DISABLE_PRDR
extern BOOL prdr_enable; /* As it says */
extern BOOL prdr_requested; /* Connecting mail server wants PRDR */
extern uschar *proxy_local_address; /* IP of local interface of proxy */
extern int proxy_local_port; /* Port on local interface of proxy */
extern BOOL proxy_session; /* TRUE if receiving mail from valid proxy */
-extern BOOL proxy_session_failed; /* TRUE if required proxy negotiation failed */
#endif
extern uschar *prvscheck_address; /* Set during prvscheck expansion item */
extern const uschar *qualify_domain_recipient; /* Domain to qualify recipients with */
extern uschar *qualify_domain_sender; /* Domain to qualify senders with */
-extern BOOL queue_2stage; /* Run queue in 2-stage manner */
extern uschar *queue_domains; /* Queue these domains */
extern BOOL queue_list_requires_admin; /* TRUE if -bp requires admin */
-extern BOOL queue_run_first_delivery; /* If TRUE, first deliveries only */
-extern BOOL queue_run_force; /* TRUE to force during queue run */
-extern BOOL queue_run_local; /* Local deliveries only in queue run */
-extern BOOL queue_running; /* TRUE for queue running process and */
/* immediate children */
extern pid_t queue_run_pid; /* PID of the queue running process or 0 */
extern int queue_run_pipe; /* Pipe for synchronizing */
extern BOOL queue_only_load_latch; /* Latch queue_only_load TRUE */
extern uschar *queue_only_file; /* Queue if file exists/not-exists */
extern BOOL queue_only_override; /* Allow override from command line */
-extern BOOL queue_only_policy; /* ACL or local_scan wants queue_only */
extern BOOL queue_run_in_order; /* As opposed to random */
extern uschar *queue_run_max; /* Max queue runners */
-extern BOOL queue_smtp; /* Disable all immediate SMTP (-odqs)*/
extern uschar *queue_smtp_domains; /* Ditto, for these domains */
extern unsigned int random_seed; /* Seed for random numbers */
extern int rcpt_defer_count; /* Those that got 4xx */
extern gid_t real_gid; /* Real gid */
extern uid_t real_uid; /* Real user running program */
-extern BOOL really_exim; /* FALSE in utilities */
-extern BOOL receive_call_bombout; /* Flag for crashing log */
extern int receive_linecount; /* Mainly for BSMTP errors */
extern int receive_messagecount; /* Mainly for BSMTP errors */
extern int receive_timeout; /* For non-SMTP acceptance */
extern uschar *recipient_data; /* lookup data for recipients */
extern uschar *recipient_unqualified_hosts; /* Permitted unqualified recipients */
extern uschar *recipient_verify_failure; /* What went wrong */
-extern BOOL recipients_discarded; /* By an ACL */
extern int recipients_list_max; /* Maximum number fitting in list */
extern int recipients_max; /* Max permitted */
extern BOOL recipients_max_reject; /* If TRUE, reject whole message */
extern router_instance *routers; /* Chain of instantiated routers */
extern router_instance router_defaults;/* Default values */
extern uschar *router_name; /* Name of router last started */
-extern BOOL running_in_test_harness; /*TRUE when running_status is patched */
extern ip_address_item *running_interfaces; /* Host's running interfaces */
extern uschar *running_status; /* Flag string for testing */
extern int runrc; /* rc from ${run} */
extern uschar *search_error_message; /* Details of lookup problem */
-extern BOOL search_find_defer; /* Set TRUE if lookup deferred */
extern uschar *self_hostname; /* Self host after routing->directors */
extern unsigned int sender_address_cache[(MAX_NAMED_LIST * 2)/32]; /* Cache bits for sender */
extern uschar *sender_address_data; /* address_data from sender verify */
-extern BOOL sender_address_forced; /* Set by -f */
extern uschar *sender_address_unrewritten; /* Set if rewritten by verify */
extern uschar *sender_data; /* lookup result for senders */
extern unsigned int sender_domain_cache[(MAX_NAMED_LIST * 2)/32]; /* Cache bits for sender domain */
extern uschar *sender_host_auth_pubname; /* Public-name of authentication method */
extern unsigned int sender_host_cache[(MAX_NAMED_LIST * 2)/32]; /* Cache bits for incoming host */
extern BOOL sender_host_dnssec; /* true if sender_host_name verified in DNSSEC */
-extern BOOL sender_host_notsocket; /* Set for -bs and -bS */
-extern BOOL sender_host_unknown; /* TRUE for -bs and -bS except inetd */
extern uschar *sender_ident; /* Sender identity via RFC 1413 */
-extern BOOL sender_local; /* TRUE for local senders */
-extern BOOL sender_name_forced; /* Set by -F */
extern uschar *sender_rate; /* Sender rate computed by ACL */
extern uschar *sender_rate_limit; /* Configured rate limit */
extern uschar *sender_rate_period; /* Configured smoothing period */
extern uschar *sender_rcvhost; /* Host data for Received: */
-extern BOOL sender_set_untrusted; /* Sender set by untrusted caller */
extern uschar *sender_unqualified_hosts; /* Permitted unqualified senders */
extern uschar *sender_verify_failure; /* What went wrong */
extern address_item *sender_verified_list; /* Saved chain of sender verifies */
extern int smtp_accept_queue_per_connection; /* Queue after so many msgs */
extern int smtp_accept_reserve; /* Reserve these SMTP connections */
extern uschar *smtp_active_hostname; /* Hostname for this message */
-extern BOOL smtp_authenticated; /* Sending client has authenticated */
extern uschar *smtp_banner; /* Banner string (to be expanded) */
extern BOOL smtp_check_spool_space; /* TRUE to check SMTP SIZE value */
extern int smtp_ch_index; /* Index in smtp_connection_had */
extern uschar *smtp_etrn_command; /* Command to run */
extern BOOL smtp_etrn_serialize; /* Only one at once */
extern FILE *smtp_in; /* Incoming SMTP input file */
-extern BOOL smtp_in_pipelining_advertised; /* server advertised PIPELINING */
-extern BOOL smtp_in_pipelining_used; /* server noted client using PIPELINING */
extern int smtp_load_reserve; /* Only from reserved if load > this */
extern int smtp_mailcmd_count; /* Count of MAIL commands */
extern int smtp_max_synprot_errors;/* Max syntax/protocol errors */
extern BOOL split_spool_directory; /* TRUE to use multiple subdirs */
extern FILE *spool_data_file; /* handle for -D file */
extern uschar *spool_directory; /* Name of spool directory */
-extern BOOL spool_file_wireformat; /* current -D file has CRLF rather than NL */
extern BOOL spool_wireformat; /* can write wireformat -D files */
#ifdef EXPERIMENTAL_SRS
extern uschar *srs_config; /* SRS config secret:max age:hash length:use timestamp:use hash */
extern BOOL strip_excess_angle_brackets; /* Surrounding route-addrs */
extern BOOL strip_trailing_dot; /* Remove dots at ends of domains */
extern uschar *submission_domain; /* Domain for submission mode */
-extern BOOL submission_mode; /* Can be forced from ACL */
extern uschar *submission_name; /* User name set from ACL */
-extern BOOL suppress_local_fixups; /* Can be forced from ACL */
-extern BOOL suppress_local_fixups_default; /* former is reset to this; override with -G */
-extern BOOL synchronous_delivery; /* TRUE if -odi is set */
extern BOOL syslog_duplication; /* FALSE => no duplicate logging */
extern int syslog_facility; /* As defined by Syslog.h */
extern BOOL syslog_pid; /* TRUE if PID on syslogs */
extern BOOL system_filter_gid_set; /* TRUE if gid set */
extern uid_t system_filter_uid; /* Uid for running system filter */
extern BOOL system_filter_uid_set; /* TRUE if uid set */
-extern BOOL system_filtering; /* TRUE when running system filter */
-extern BOOL tcp_fastopen_ok; /* appears to be supported by kernel */
extern blob tcp_fastopen_nodata; /* for zero-data TFO connect requests */
-extern BOOL tcp_in_fastopen; /* conn usefully used fastopen */
-extern BOOL tcp_in_fastopen_logged; /* one-time logging */
extern BOOL tcp_nodelay; /* Controls TCP_NODELAY on daemon */
extern int tcp_out_fastopen; /* 0: no 1: conn used 2: useful */
-extern BOOL tcp_out_fastopen_logged; /* one-time logging */
#ifdef USE_TCP_WRAPPERS
extern uschar *tcp_wrappers_daemon_name; /* tcpwrappers daemon lookup name */
#endif
extern int test_harness_load_avg; /* For use when testing */
extern int thismessage_size_limit; /* Limit for this message */
extern int timeout_frozen_after; /* Max time to keep frozen messages */
-extern BOOL timestamps_utc; /* Use UTC for all times */
extern uschar *transport_name; /* Name of transport last started */
extern int transport_count; /* Count of bytes transported */
extern int transport_newlines; /* Accurate count of number of newline chars transported */
extern const uschar **transport_filter_argv; /* For on-the-fly filtering */
extern int transport_filter_timeout; /* Timeout for same */
-extern BOOL transport_filter_timed_out; /* True if it did */
extern transport_info transports_available[]; /* Vector of available transports */
extern transport_instance *transports; /* Chain of instantiated transports */
extern tree_node *tree_nonrecipients; /* Tree of nonrecipient addresses */
extern tree_node *tree_unusable; /* Tree of unusable addresses */
-extern BOOL trusted_caller; /* Caller is trusted */
-extern BOOL trusted_config; /* Configuration file is trusted */
extern gid_t *trusted_groups; /* List of trusted groups */
extern uid_t *trusted_users; /* List of trusted users */
extern uschar *timezone_string; /* Required timezone setting */
return 0;
if (random_seed == 0)
{
- if (running_in_test_harness) random_seed = 42; else
+ if (f.running_in_test_harness) random_seed = 42; else
{
int p = (int)getpid();
random_seed = (int)time(NULL) ^ ((p << 16) | p);
/* For testing the case when a lookup does not complete, we have a special
reserved IP address. */
-if (running_in_test_harness &&
+if (f.running_in_test_harness &&
Ustrcmp(sender_host_address, "99.99.99.99") == 0)
{
HDEBUG(D_host_lookup)
if (sender_host_name == NULL)
{
- if (host_checking || !log_testing_mode)
+ if (host_checking || !f.log_testing_mode)
log_write(L_host_lookup_failed, LOG_MAIN, "no host name found for IP "
"address %s", sender_host_address);
host_lookup_msg = US" (failed to find host name from IP address)";
/* Initialize the flag that gets set for DNS syntax check errors, so that the
interface to this function can be similar to host_find_bydns. */
-host_find_failed_syntax = FALSE;
+f.host_find_failed_syntax = FALSE;
/* Loop to look up both kinds of address in an IPv6 world */
if (slow_lookup_log) time_msec = get_time_in_ms();
#if HAVE_IPV6
- if (running_in_test_harness)
+ if (f.running_in_test_harness)
hostdata = host_fake_gethostbyname(host->name, af, &error_num);
else
{
}
#else /* not HAVE_IPV6 */
- if (running_in_test_harness)
+ if (f.running_in_test_harness)
hostdata = host_fake_gethostbyname(host->name, AF_INET, &error_num);
else
{
HDEBUG(D_host_lookup) debug_printf("%s\n", msg);
if (temp_error) goto RETURN_AGAIN;
- if (host_checking || !log_testing_mode)
+ if (host_checking || !f.log_testing_mode)
log_write(L_host_lookup_failed, LOG_MAIN, "%s", msg);
return HOST_FIND_FAILED;
}
dns_init((whichrrs & HOST_FIND_QUALIFY_SINGLE) != 0,
(whichrrs & HOST_FIND_SEARCH_PARENTS) != 0,
dnssec_request);
-host_find_failed_syntax = FALSE;
+f.host_find_failed_syntax = FALSE;
/* First, if requested, look for SRV records. The service name is given; we
assume TCP protocol. DNS domain names are constrained to a maximum of 256
else if (Ustrcmp(buffer, "require_dnssec") == 0) require_dnssec = TRUE;
else if (Ustrcmp(buffer, "no_require_dnssec") == 0) require_dnssec = FALSE;
else if (Ustrcmp(buffer, "test_harness") == 0)
- running_in_test_harness = !running_in_test_harness;
+ f.running_in_test_harness = !f.running_in_test_harness;
else if (Ustrcmp(buffer, "ipv6") == 0) disable_ipv6 = !disable_ipv6;
else if (Ustrcmp(buffer, "res_debug") == 0)
{
if ( (sock = socket(SOCK_STREAM, AF_INET, 0)) < 0
&& setsockopt(sock, IPPROTO_TCP, TCP_FASTOPEN, &backlog, sizeof(backlog))
)
- tcp_fastopen_ok = TRUE;
+ f.tcp_fastopen_ok = TRUE;
close(sock);
# endif
}
not checked. I think MacOS has a "connectx" call for this purpose,
rather than using "sendto" ? */
-if (fastopen_blob && tcp_fastopen_ok)
+if (fastopen_blob && f.tcp_fastopen_ok)
{
if ((rc = sendto(sock, fastopen_blob->data, fastopen_blob->len,
MSG_FASTOPEN | MSG_DONTWAIT, s_ptr, s_len)) >= 0)
can't think of any other way of doing this. It converts a connection refused
into a timeout if the timeout is set to 999999. */
-if (running_in_test_harness && save_errno == ECONNREFUSED && timeout == 999999)
+if (f.running_in_test_harness && save_errno == ECONNREFUSED && timeout == 999999)
{
rc = -1;
save_errno = EINTR;
len = Ustrlen(s);
#ifndef NO_OPENLOG
-if (!syslog_open && !running_in_test_harness)
+if (!syslog_open && !f.running_in_test_harness)
{
# ifdef SYSLOG_LOG_PID
openlog(CS syslog_processname, LOG_PID|LOG_CONS, syslog_facility);
if (pass == 0)
linecount++;
- else if (running_in_test_harness)
+ else if (f.running_in_test_harness)
if (linecount == 1)
fprintf(stderr, "SYSLOG: '%.*s'\n", plen, ss);
else
if (log_stderr && log_stderr != debug_file)
fprintf(log_stderr, "%s\n", s1);
}
-if (receive_call_bombout) receive_bomb_out(NULL, s2); /* does not return */
+if (f.receive_call_bombout) receive_bomb_out(NULL, s2); /* does not return */
if (smtp_input) smtp_closedown(s2);
exim_exit(EXIT_FAILURE, NULL);
}
/* There are some weird circumstances in which logging is disabled. */
-if (disable_logging)
+if (f.disable_logging)
{
DEBUG(D_any) debug_printf("log writing disabled\n");
return;
if (!syslog_pid) pid_position[1] = ptr - log_buffer; /* … and end+1 of the PID */
}
-if (really_exim && message_id[0] != 0)
+if (f.really_exim && message_id[0] != 0)
ptr += sprintf(CS ptr, "%s ", message_id);
if (flags & LOG_CONFIG) ptr = log_config_info(ptr, flags);
Write to log_stderr unless debugging (when it will already have been written),
or unless there is no log_stderr (expn called from daemon, for example). */
-if (!really_exim || log_testing_mode)
+if (!f.really_exim || f.log_testing_mode)
{
if ( !debug_selector
&& log_stderr
/* When running in the test harness, the load average is fudged. */
#define OS_GETLOADAVG() \
- (running_in_test_harness? (test_harness_load_avg += 10) : os_getloadavg())
+ (f.running_in_test_harness? (test_harness_load_avg += 10) : os_getloadavg())
/* The address_item structure has a struct full of 1-bit flags. These macros
return_path = US"";
recipients_list = NULL;
receive_add_recipient(US"malware-victim@example.net", -1);
-enable_dollar_recipients = TRUE;
+f.enable_dollar_recipients = TRUE;
ret = malware_internal(US"*", eml_filename, 0);
for; partial matching is all handled inside search_find(). Note that there is
no search_close() because of the caching arrangements. */
-handle = search_open(filename, search_type, 0, NULL, NULL);
-if (handle == NULL) log_write(0, LOG_MAIN|LOG_PANIC_DIE, "%s",
- search_error_message);
+if (!(handle = search_open(filename, search_type, 0, NULL, NULL)))
+ log_write(0, LOG_MAIN|LOG_PANIC_DIE, "%s", search_error_message);
result = search_find(handle, filename, keyquery, partial, affix, affixlen,
starflags, &expand_setup);
-if (result == NULL) return search_find_defer? DEFER : FAIL;
-if (valueptr != NULL) *valueptr = result;
+if (!result) return f.search_find_defer? DEFER : FAIL;
+if (valueptr) *valueptr = result;
expand_nmax = expand_setup;
return OK;
if (!list)
{
- if (expand_string_forcedfail)
+ if (f.expand_string_forcedfail)
{
HDEBUG(D_lists) debug_printf("expansion of \"%s\" forced failure: "
"assume not in this list\n", *listptr);
int status;
int count = 0;
int size_limit = bounce_return_size_limit;
-FILE *f;
+FILE * fp;
int pid = child_open_exim(&fd);
/* Creation of child failed */
/* Creation of child succeeded */
-f = fdopen(fd, "wb");
-if (errors_reply_to) fprintf(f, "Reply-To: %s\n", errors_reply_to);
-fprintf(f, "Auto-Submitted: auto-replied\n");
-moan_write_from(f);
-fprintf(f, "To: %s\n", recipient);
+fp = fdopen(fd, "wb");
+if (errors_reply_to) fprintf(fp, "Reply-To: %s\n", errors_reply_to);
+fprintf(fp, "Auto-Submitted: auto-replied\n");
+moan_write_from(fp);
+fprintf(fp, "To: %s\n", recipient);
switch(ident)
{
case ERRMESS_BADARGADDRESS:
- fprintf(f,
+ fprintf(fp,
"Subject: Mail failure - malformed recipient address\n\n");
- fprintf(f,
+ fprintf(fp,
"A message that you sent contained a recipient address that was incorrectly\n"
"constructed:\n\n");
- fprintf(f, " %s %s\n", eblock->text1, eblock->text2);
+ fprintf(fp, " %s %s\n", eblock->text1, eblock->text2);
count = Ustrlen(eblock->text1);
if (count > 0 && eblock->text1[count-1] == '.')
- fprintf(f,
+ fprintf(fp,
"\nRecipient addresses must not end with a '.' character.\n");
- fprintf(f,
+ fprintf(fp,
"\nThe message has not been delivered to any recipients.\n");
break;
case ERRMESS_BADNOADDRESS:
case ERRMESS_BADADDRESS:
- fprintf(f,
+ fprintf(fp,
"Subject: Mail failure - malformed recipient address\n\n");
- fprintf(f,
+ fprintf(fp,
"A message that you sent contained one or more recipient addresses that were\n"
"incorrectly constructed:\n\n");
while (eblock != NULL)
{
- fprintf(f, " %s: %s\n", eblock->text1, eblock->text2);
+ fprintf(fp, " %s: %s\n", eblock->text1, eblock->text2);
count++;
eblock = eblock->next;
}
- fprintf(f, (count == 1)? "\nThis address has been ignored. " :
+ fprintf(fp, (count == 1)? "\nThis address has been ignored. " :
"\nThese addresses have been ignored. ");
- fprintf(f, (ident == ERRMESS_BADADDRESS)?
+ fprintf(fp, (ident == ERRMESS_BADADDRESS)?
"The other addresses in the message were\n"
"syntactically valid and have been passed on for an attempt at delivery.\n" :
break;
case ERRMESS_IGADDRESS:
- fprintf(f, "Subject: Mail failure - no recipient addresses\n\n");
- fprintf(f,
+ fprintf(fp, "Subject: Mail failure - no recipient addresses\n\n");
+ fprintf(fp,
"A message that you sent using the -t command line option contained no\n"
"addresses that were not also on the command line, and were therefore\n"
"suppressed. This left no recipient addresses, and so no delivery could\n"
break;
case ERRMESS_NOADDRESS:
- fprintf(f, "Subject: Mail failure - no recipient addresses\n\n");
- fprintf(f,
+ fprintf(fp, "Subject: Mail failure - no recipient addresses\n\n");
+ fprintf(fp,
"A message that you sent contained no recipient addresses, and therefore no\n"
"delivery could be attempted.\n");
break;
case ERRMESS_IOERR:
- fprintf(f, "Subject: Mail failure - system failure\n\n");
- fprintf(f,
+ fprintf(fp, "Subject: Mail failure - system failure\n\n");
+ fprintf(fp,
"A system failure was encountered while processing a message that you sent,\n"
"so it has not been possible to deliver it. The error was:\n\n%s\n",
eblock->text1);
break;
case ERRMESS_VLONGHEADER:
- fprintf(f, "Subject: Mail failure - overlong header section\n\n");
- fprintf(f,
+ fprintf(fp, "Subject: Mail failure - overlong header section\n\n");
+ fprintf(fp,
"A message that you sent contained a header section that was excessively\n"
"long and could not be handled by the mail transmission software. The\n"
"message has not been delivered to any recipients.\n");
break;
case ERRMESS_VLONGHDRLINE:
- fprintf(f, "Subject: Mail failure - overlong header line\n\n");
- fprintf(f,
+ fprintf(fp, "Subject: Mail failure - overlong header line\n\n");
+ fprintf(fp,
"A message that you sent contained a header line that was excessively\n"
"long and could not be handled by the mail transmission software. The\n"
"message has not been delivered to any recipients.\n");
break;
case ERRMESS_TOOBIG:
- fprintf(f, "Subject: Mail failure - message too big\n\n");
- fprintf(f,
+ fprintf(fp, "Subject: Mail failure - message too big\n\n");
+ fprintf(fp,
"A message that you sent was longer than the maximum size allowed on this\n"
"system. It was not delivered to any recipients.\n");
break;
case ERRMESS_TOOMANYRECIP:
- fprintf(f, "Subject: Mail failure - too many recipients\n\n");
- fprintf(f,
+ fprintf(fp, "Subject: Mail failure - too many recipients\n\n");
+ fprintf(fp,
"A message that you sent contained more recipients than allowed on this\n"
"system. It was not delivered to any recipients.\n");
break;
case ERRMESS_LOCAL_SCAN:
case ERRMESS_LOCAL_ACL:
- fprintf(f, "Subject: Mail failure - rejected by local scanning code\n\n");
- fprintf(f,
+ fprintf(fp, "Subject: Mail failure - rejected by local scanning code\n\n");
+ fprintf(fp,
"A message that you sent was rejected by the local scanning code that\n"
"checks incoming messages on this system.");
if (eblock->text1)
- fprintf(f, " The following error was given:\n\n %s", eblock->text1);
- fprintf(f, "\n");
+ fprintf(fp, " The following error was given:\n\n %s", eblock->text1);
+ fprintf(fp, "\n");
break;
#ifdef EXPERIMENTAL_DMARC
case ERRMESS_DMARC_FORENSIC:
bounce_return_message = TRUE;
bounce_return_body = FALSE;
- fprintf(f,
+ fprintf(fp,
"Subject: DMARC Forensic Report for %s from IP %s\n\n",
((eblock == NULL) ? US"Unknown" : eblock->text2),
sender_host_address);
- fprintf(f,
+ fprintf(fp,
"A message claiming to be from you has failed the published DMARC\n"
"policy for your domain.\n\n");
while (eblock != NULL)
{
- fprintf(f, " %s: %s\n", eblock->text1, eblock->text2);
+ fprintf(fp, " %s: %s\n", eblock->text1, eblock->text2);
count++;
eblock = eblock->next;
}
#endif
default:
- fprintf(f, "Subject: Mail failure\n\n");
- fprintf(f,
+ fprintf(fp, "Subject: Mail failure\n\n");
+ fprintf(fp,
"A message that you sent has caused the error routine to be entered with\n"
"an unknown error number (%d).\n", ident);
break;
{
if (bounce_return_body)
{
- fprintf(f, "\n"
+ fprintf(fp, "\n"
"------ This is a copy of your message, including all the headers.");
if (size_limit == 0 || size_limit > thismessage_size_limit)
size_limit = thismessage_size_limit;
k = US"K";
x >>= 10;
}
- fprintf(f, "\n"
+ fprintf(fp, "\n"
"------ No more than %d%s characters of the body are included.\n\n",
x, k);
}
- else fprintf(f, " ------\n\n");
+ else fprintf(fp, " ------\n\n");
}
else
{
- fprintf(f, "\n"
+ fprintf(fp, "\n"
"------ This is a copy of the headers that were received before the "
"error\n was detected.\n\n");
}
while (headers)
{
- if (headers->text != NULL) fprintf(f, "%s", CS headers->text);
+ if (headers->text != NULL) fprintf(fp, "%s", CS headers->text);
headers = headers->next;
}
if (ident != ERRMESS_VLONGHEADER && ident != ERRMESS_VLONGHDRLINE)
- fputc('\n', f);
+ fputc('\n', fp);
/* After early detection of an error, the message file may be STDIN,
in which case we might have to terminate on a line containing just "."
if (bounce_return_body && message_file)
{
- BOOL enddot = dot_ends && message_file == stdin;
+ BOOL enddot = f.dot_ends && message_file == stdin;
uschar * buf = store_get(bounce_return_linesize_limit+2);
- if (firstline) fprintf(f, "%s", CS firstline);
+ if (firstline) fprintf(fp, "%s", CS firstline);
while (fgets(CS buf, bounce_return_linesize_limit+2, message_file))
{
if (enddot && *buf == '.' && buf[1] == '\n')
{
- fputc('.', f);
+ fputc('.', fp);
break;
}
if (size_limit > 0 && len > size_limit - written)
{
buf[size_limit - written] = '\0';
- fputs(CS buf, f);
+ fputs(CS buf, fp);
break;
}
- fputs(CS buf, f);
+ fputs(CS buf, fp);
}
}
#ifdef EXPERIMENTAL_DMARC
/*XXX limit line length here? */
/* This doesn't print newlines, disable until can parse and fix
* output to be legible. */
- fprintf(f, "%s", expand_string(US"$message_body"));
+ fprintf(fp, "%s", expand_string(US"$message_body"));
}
#endif
}
/* Close the file, which should send an EOF to the child process
that is receiving the message. Wait for it to finish, without a timeout. */
-(void)fclose(f);
+(void)fclose(fp);
status = child_close(pid, 0); /* Waits for child to close */
if (status != 0)
{
/* Find the sender from a From line if permitted and possible */
-if (check_sender && message_file && trusted_caller &&
+if (check_sender && message_file && f.trusted_caller &&
Ufgets(big_buffer, BIG_BUFFER_SIZE, message_file) != NULL)
{
uschar *new_sender = NULL;
/* If viable sender address, send a message */
-if (sender_address && sender_address[0] && !local_error_message)
+if (sender_address && sender_address[0] && !f.local_error_message)
return moan_send_message(sender_address, ident, eblock, headers,
message_file, firstline);
end of string will produce a null local_part and therefore fail. We don't
need to keep updating t, as the phrase isn't to be kept. */
- while (*s != '<' && (!parse_allow_group || *s != ':'))
+ while (*s != '<' && (!f.parse_allow_group || *s != ':'))
{
s = read_local_part(s, t, errorptr, FALSE);
if (*errorptr)
if (*s == ':')
{
- parse_found_group = TRUE;
- parse_allow_group = FALSE;
+ f.parse_found_group = TRUE;
+ f.parse_allow_group = FALSE;
s++;
goto RESTART;
}
PARSE_SUCCEEDED:
if (*s != 0)
{
- if (parse_found_group && *s == ';')
+ if (f.parse_found_group && *s == ';')
{
- parse_found_group = FALSE;
- parse_allow_group = TRUE;
+ f.parse_found_group = FALSE;
+ f.parse_allow_group = TRUE;
}
else
{
this. We must, however, keep the flags correct. */
PARSE_FAILED:
-if (parse_found_group && *s == ';')
+if (f.parse_found_group && *s == ';')
{
- parse_found_group = FALSE;
- parse_allow_group = TRUE;
+ f.parse_found_group = FALSE;
+ f.parse_allow_group = TRUE;
}
return NULL;
}
printf("Testing parse_extract_address with group syntax\n");
-parse_allow_group = TRUE;
+f.parse_allow_group = TRUE;
while (Ufgets(buffer, sizeof(buffer), stdin) != NULL)
{
uschar *out;
ST(0) = sv_newmortal();
if (str != NULL)
sv_setpv(ST(0), CCS str);
- else if (!expand_string_forcedfail)
+ else if (!f.expand_string_forcedfail)
croak("syntax error in Exim::expand_string argument: %s",
expand_string_message);
}
void
queue_run(uschar *start_id, uschar *stop_id, BOOL recurse)
{
-BOOL force_delivery = queue_run_force || deliver_selectstring != NULL ||
+BOOL force_delivery = f.queue_run_force || deliver_selectstring != NULL ||
deliver_selectstring_sender != NULL;
const pcre *selectstring_regex = NULL;
const pcre *selectstring_regex_sender = NULL;
queue_domains = NULL;
queue_smtp_domains = NULL;
-queue_smtp = queue_2stage;
+f.queue_smtp = f.queue_2stage;
queue_run_pid = getpid();
-queue_running = TRUE;
+f.queue_running = TRUE;
/* Log the true start of a queue run, and fancy options */
uschar extras[8];
uschar *p = extras;
- if (queue_2stage) *p++ = 'q';
- if (queue_run_first_delivery) *p++ = 'i';
- if (queue_run_force) *p++ = 'f';
- if (deliver_force_thaw) *p++ = 'f';
- if (queue_run_local) *p++ = 'l';
+ if (f.queue_2stage) *p++ = 'q';
+ if (f.queue_run_first_delivery) *p++ = 'i';
+ if (f.queue_run_force) *p++ = 'f';
+ if (f.deliver_force_thaw) *p++ = 'f';
+ if (f.queue_run_local) *p++ = 'l';
*p = 0;
p = big_buffer;
p += sprintf(CS p, " -q%s", extras);
if (deliver_selectstring)
- p += sprintf(CS p, " -R%s %s", deliver_selectstring_regex? "r" : "",
+ p += sprintf(CS p, " -R%s %s", f.deliver_selectstring_regex? "r" : "",
deliver_selectstring);
if (deliver_selectstring_sender)
- p += sprintf(CS p, " -S%s %s", deliver_selectstring_sender_regex? "r" : "",
+ p += sprintf(CS p, " -S%s %s", f.deliver_selectstring_sender_regex? "r" : "",
deliver_selectstring_sender);
log_detail = string_copy(big_buffer);
/* If deliver_selectstring is a regex, compile it. */
-if (deliver_selectstring && deliver_selectstring_regex)
+if (deliver_selectstring && f.deliver_selectstring_regex)
selectstring_regex = regex_must_compile(deliver_selectstring, TRUE, FALSE);
-if (deliver_selectstring_sender && deliver_selectstring_sender_regex)
+if (deliver_selectstring_sender && f.deliver_selectstring_sender_regex)
selectstring_regex_sender =
regex_must_compile(deliver_selectstring_sender, TRUE, FALSE);
i <= (queue_run_in_order ? -1 : subcount);
i++)
{
- queue_filename *f;
+ queue_filename * fq;
void *reset_point1 = store_get(0);
DEBUG(D_queue_run)
debug_printf("queue running subdirectory '%c'\n", subdirs[i]);
}
- for (f = queue_get_spool_list(i, subdirs, &subcount, !queue_run_in_order);
- f;
- f = f->next)
+ for (fq = queue_get_spool_list(i, subdirs, &subcount, !queue_run_in_order);
+ fq;
+ fq = fq->next)
{
pid_t pid;
int status;
/* Unless deliveries are forced, if deliver_queue_load_max is non-negative,
check that the load average is low enough to permit deliveries. */
- if (!queue_run_force && deliver_queue_load_max >= 0)
+ if (!f.queue_run_force && deliver_queue_load_max >= 0)
if ((load_average = os_getloadavg()) > deliver_queue_load_max)
{
log_write(L_queue_run, LOG_MAIN, "Abandon queue run: %s (load %.2f, max %.2f)",
/* Skip this message unless it's within the ID limits */
- if (stop_id && Ustrncmp(f->text, stop_id, MESSAGE_ID_LENGTH) > 0)
+ if (stop_id && Ustrncmp(fq->text, stop_id, MESSAGE_ID_LENGTH) > 0)
continue;
- if (start_id && Ustrncmp(f->text, start_id, MESSAGE_ID_LENGTH) < 0)
+ if (start_id && Ustrncmp(fq->text, start_id, MESSAGE_ID_LENGTH) < 0)
continue;
/* Check that the message still exists */
- message_subdir[0] = f->dir_uschar;
- if (Ustat(spool_fname(US"input", message_subdir, f->text, US""), &statbuf) < 0)
+ message_subdir[0] = fq->dir_uschar;
+ if (Ustat(spool_fname(US"input", message_subdir, fq->text, US""), &statbuf) < 0)
continue;
/* There are some tests that require the reading of the header file. Ensure
message when many are not going to be delivered. */
if (deliver_selectstring || deliver_selectstring_sender ||
- queue_run_first_delivery)
+ f.queue_run_first_delivery)
{
BOOL wanted = TRUE;
- BOOL orig_dont_deliver = dont_deliver;
+ BOOL orig_dont_deliver = f.dont_deliver;
void *reset_point2 = store_get(0);
/* Restore the original setting of dont_deliver after reading the header,
follow. If the message is chosen for delivery, the header is read again
in the deliver_message() function, in a subprocess. */
- if (spool_read_header(f->text, FALSE, TRUE) != spool_read_OK) continue;
- dont_deliver = orig_dont_deliver;
+ if (spool_read_header(fq->text, FALSE, TRUE) != spool_read_OK) continue;
+ f.dont_deliver = orig_dont_deliver;
/* Now decide if we want to deliver this message. As we have read the
header file, we might as well do the freeze test now, and save forking
another process. */
- if (deliver_freeze && !deliver_force_thaw)
+ if (f.deliver_freeze && !f.deliver_force_thaw)
{
log_write(L_skip_delivery, LOG_MAIN, "Message is frozen");
wanted = FALSE;
/* Check first_delivery in the case when there are no message logs. */
- else if (queue_run_first_delivery && !deliver_firsttime)
+ else if (f.queue_run_first_delivery && !f.deliver_firsttime)
{
- DEBUG(D_queue_run) debug_printf("%s: not first delivery\n", f->text);
+ DEBUG(D_queue_run) debug_printf("%s: not first delivery\n", fq->text);
wanted = FALSE;
}
/* Sender matching */
else if ( deliver_selectstring_sender
- && !(deliver_selectstring_sender_regex
+ && !(f.deliver_selectstring_sender_regex
? (pcre_exec(selectstring_regex_sender, NULL,
CS sender_address, Ustrlen(sender_address), 0, PCRE_EOPT,
NULL, 0) >= 0)
) )
{
DEBUG(D_queue_run) debug_printf("%s: sender address did not match %s\n",
- f->text, deliver_selectstring_sender);
+ fq->text, deliver_selectstring_sender);
wanted = FALSE;
}
for (i = 0; i < recipients_count; i++)
{
uschar *address = recipients_list[i].address;
- if ( (deliver_selectstring_regex
+ if ( (f.deliver_selectstring_regex
? (pcre_exec(selectstring_regex, NULL, CS address,
Ustrlen(address), 0, PCRE_EOPT, NULL, 0) >= 0)
: (strstric(address, deliver_selectstring, FALSE) != NULL)
{
DEBUG(D_queue_run)
debug_printf("%s: no recipient address matched %s\n",
- f->text, deliver_selectstring);
+ fq->text, deliver_selectstring);
wanted = FALSE;
}
}
/* Now deliver the message; get the id by cutting the -H off the file
name. The return of the process is zero if a delivery was attempted. */
- set_process_info("running queue: %s", f->text);
- f->text[SPOOL_NAME_LENGTH-2] = 0;
+ set_process_info("running queue: %s", fq->text);
+ fq->text[SPOOL_NAME_LENGTH-2] = 0;
if ((pid = fork()) == 0)
{
int rc;
- if (running_in_test_harness) millisleep(100);
+ if (f.running_in_test_harness) millisleep(100);
(void)close(pfd[pipe_read]);
- rc = deliver_message(f->text, force_delivery, FALSE);
+ rc = deliver_message(fq->text, force_delivery, FALSE);
_exit(rc == DELIVER_NOT_ATTEMPTED);
}
if (pid < 0)
then wait for the first level process to terminate. */
(void)close(pfd[pipe_write]);
- set_process_info("running queue: waiting for %s (%d)", f->text, pid);
+ set_process_info("running queue: waiting for %s (%d)", fq->text, pid);
while (wait(&status) != pid);
/* A zero return means a delivery was attempted; turn off the force flag
for any subsequent calls unless queue_force is set. */
- if ((status & 0xffff) == 0) force_delivery = queue_run_force;
+ if ((status & 0xffff) == 0) force_delivery = f.queue_run_force;
/* If the process crashed, tell somebody */
else if ((status & 0x00ff) != 0)
log_write(0, LOG_MAIN|LOG_PANIC,
"queue run: process %d crashed with signal %d while delivering %s",
- (int)pid, status & 0x00ff, f->text);
+ (int)pid, status & 0x00ff, fq->text);
/* Before continuing, wait till the pipe gets closed at the far end. This
tells us that any children created by the delivery to re-use any SMTP
/* If we are in the test harness, and this is not the first of a 2-stage
queue run, update fudged queue times. */
- if (running_in_test_harness && !queue_2stage)
+ if (f.running_in_test_harness && !f.queue_2stage)
{
uschar *fqtnext = Ustrchr(fudged_queue_times, '/');
if (fqtnext != NULL) fudged_queue_times = fqtnext + 1;
/* If queue_2stage is true, we do it all again, with the 2stage flag
turned off. */
-if (queue_2stage)
+if (f.queue_2stage)
{
- queue_2stage = FALSE;
+ f.queue_2stage = FALSE;
queue_run(start_id, stop_id, TRUE);
}
int subcount;
int now = (int)time(NULL);
void *reset_point;
-queue_filename *f = NULL;
+queue_filename * qf = NULL;
uschar subdirs[64];
/* If given a list of messages, build a chain containing their ids. */
sprintf(CS next->text, "%s-H", list[i]);
next->dir_uschar = '*';
next->next = NULL;
- if (i == 0) f = next; else last->next = next;
+ if (i == 0) qf = next; else last->next = next;
last = next;
}
}
/* Otherwise get a list of the entire queue, in order if necessary. */
else
- f = queue_get_spool_list(
+ qf = queue_get_spool_list(
-1, /* entire queue */
subdirs, /* for holding sub list */
&subcount, /* for subcount */
each time. */
for (reset_point = store_get(0);
- f;
- spool_clear_header_globals(), store_reset(reset_point), f = f->next
+ qf;
+ spool_clear_header_globals(), store_reset(reset_point), qf = qf->next
)
{
int rc, save_errno;
BOOL env_read;
message_size = 0;
- message_subdir[0] = f->dir_uschar;
- rc = spool_read_header(f->text, FALSE, count <= 0);
+ message_subdir[0] = qf->dir_uschar;
+ rc = spool_read_header(qf->text, FALSE, count <= 0);
if (rc == spool_read_notopen && errno == ENOENT && count <= 0)
continue;
save_errno = errno;
int ptr;
FILE *jread;
struct stat statbuf;
- uschar * fname = spool_fname(US"input", message_subdir, f->text, US"");
+ uschar * fname = spool_fname(US"input", message_subdir, qf->text, US"");
ptr = Ustrlen(fname)-1;
fname[ptr] = 'D';
}
fprintf(stdout, "%s ", string_format_size(size, big_buffer));
- for (i = 0; i < 16; i++) fputc(f->text[i], stdout);
+ for (i = 0; i < 16; i++) fputc(qf->text[i], stdout);
if (env_read && sender_address)
{
printf(" <%s>", sender_address);
- if (sender_set_untrusted) printf(" (%s)", originator_login);
+ if (f.sender_set_untrusted) printf(" (%s)", originator_login);
}
if (rc != spool_read_OK)
if (save_errno == ERRNO_SPOOLFORMAT)
{
struct stat statbuf;
- uschar * fname = spool_fname(US"input", message_subdir, f->text, US"");
+ uschar * fname = spool_fname(US"input", message_subdir, qf->text, US"");
if (Ustat(fname, &statbuf) == 0)
printf("*** spool format error: size=" OFF_T_FMT " ***",
}
}
- if (deliver_freeze) printf(" *** frozen ***");
+ if (f.deliver_freeze) printf(" *** frozen ***");
printf("\n");
int fd, i, rc;
uschar *subdirectory, *suffix;
- if (!admin_user)
+ if (!f.admin_user)
{
printf("Permission denied\n");
return FALSE;
{
yield = FALSE;
printf("Spool data file for %s does not exist\n", id);
- if (action != MSG_REMOVE || !admin_user) return FALSE;
+ if (action != MSG_REMOVE || !f.admin_user) return FALSE;
printf("Continuing, to ensure all files removed\n");
}
else
printf("Spool read error for %s: %s\n", spoolname, strerror(errno));
else
printf("Spool format error for %s\n", spoolname);
- if (action != MSG_REMOVE || !admin_user)
+ if (action != MSG_REMOVE || !f.admin_user)
{
(void)close(deliver_datafile);
deliver_datafile = -1;
mess about, but the original sender is permitted to remove a message. That's
why we leave this check until after the headers are read. */
-if (!admin_user && (action != MSG_REMOVE || real_uid != originator_uid))
+if (!f.admin_user && (action != MSG_REMOVE || real_uid != originator_uid))
{
printf("Permission denied\n");
(void)close(deliver_datafile);
case MSG_FREEZE:
- if (deliver_freeze)
+ if (f.deliver_freeze)
{
yield = FALSE;
printf("is already frozen\n");
}
else
{
- deliver_freeze = TRUE;
- deliver_manual_thaw = FALSE;
+ f.deliver_freeze = TRUE;
+ f.deliver_manual_thaw = FALSE;
deliver_frozen_at = time(NULL);
if (spool_write_header(id, SW_MODIFYING, &errmsg) >= 0)
{
case MSG_THAW:
- if (!deliver_freeze)
+ if (!f.deliver_freeze)
{
yield = FALSE;
printf("is not frozen\n");
}
else
{
- deliver_freeze = FALSE;
- deliver_manual_thaw = TRUE;
+ f.deliver_freeze = FALSE;
+ f.deliver_manual_thaw = TRUE;
if (spool_write_header(id, SW_MODIFYING, &errmsg) >= 0)
{
printf("is no longer frozen\n");
void
queue_check_only(void)
{
-BOOL *set;
int sep = 0;
struct stat statbuf;
const uschar *s;
-uschar *ss, *name;
+uschar *ss;
uschar buffer[1024];
if (queue_only_file == NULL) return;
{
if (Ustrncmp(ss, "smtp", 4) == 0)
{
- name = US"queue_smtp";
- set = &queue_smtp;
ss += 4;
+ if (Ustat(ss, &statbuf) == 0)
+ {
+ f.queue_smtp = TRUE;
+ DEBUG(D_receive) debug_printf("queue_smtp set because %s exists\n", ss);
+ }
}
else
{
- name = US"queue_only";
- set = &queue_only;
- }
-
- if (Ustat(ss, &statbuf) == 0)
- {
- *set = TRUE;
- DEBUG(D_receive) debug_printf("%s set because %s exists\n", name, ss);
+ if (Ustat(ss, &statbuf) == 0)
+ {
+ queue_only = TRUE;
+ DEBUG(D_receive) debug_printf("queue_only set because %s exists\n", ss);
+ }
}
}
}
}
else data = rdata->string;
-*filtertype = system_filtering? FILTER_EXIM : rda_is_filter(data);
+*filtertype = f.system_filtering ? FILTER_EXIM : rda_is_filter(data);
/* Filter interpretation is done by a general function that is also called from
the filter testing option (-bf). There are two versions: one for Exim filtering
data = expand_string(rdata->string);
if (data == NULL)
{
- if (expand_string_forcedfail) return FF_NOTDELIVERED;
+ if (f.expand_string_forcedfail) return FF_NOTDELIVERED;
*error = string_sprintf("failed to expand \"%s\": %s", rdata->string,
expand_string_message);
return FF_ERROR;
original header lines that were removed, and then any header lines that were
added but not subsequently removed. */
- if (system_filtering)
+ if (f.system_filtering)
{
int i = 0;
header_line *h;
/* If this is a system filter, read the identify of any original header lines
that were removed, and then read data for any new ones that were added. */
-if (system_filtering)
+if (f.system_filtering)
{
int hn = 0;
header_line *h = header_list;
/* Non-admin callers cannot see options that have been flagged secure by the
"hide" prefix. */
-if (!admin_user && ol->type & opt_secure)
+if (!f.admin_user && ol->type & opt_secure)
{
if (no_labels)
printf("%s\n", hidden);
if (Ustrcmp(name, "config") == 0)
{
- print_config(admin_user, no_labels);
+ print_config(f.admin_user, no_labels);
return TRUE;
}
{
/* People store passwords in macros and they were previously not available
for printing. So we have an admin_users restriction. */
- if (!admin_user)
+ if (!f.admin_user)
{
fprintf(stderr, "exim: permission denied\n");
return FALSE;
/* Check the status of the file we have opened, if we have retained root
privileges and the file isn't /dev/null (which *should* be 0666). */
-if (trusted_config && Ustrcmp(filename, US"/dev/null"))
+if (f.trusted_config && Ustrcmp(filename, US"/dev/null"))
{
if (fstat(fileno(config_file), &statbuf) != 0)
log_write(0, LOG_MAIN|LOG_PANIC_DIE, "failed to stat configuration file %s",
readconf_save_config(const uschar *s)
{
save_config_line(string_sprintf("# Exim Configuration (%s)",
- running_in_test_harness ? US"X" : s));
+ f.running_in_test_harness ? US"X" : s));
}
static void
receive_check_set_sender(uschar *newsender)
{
uschar *qnewsender;
-if (trusted_caller) return TRUE;
+if (f.trusted_caller) return TRUE;
if (!newsender || !untrusted_set_sender) return FALSE;
qnewsender = Ustrchr(newsender, '@')
? newsender : string_sprintf("%s@%s", newsender, qualify_domain_sender);
/* Handle the case when only EOF terminates the message */
-if (!dot_ends)
+if (!f.dot_ends)
{
register int last_ch = '\n';
DEBUG(D_receive) debug_printf("CHUNKING: %s\n",
fout ? "writing spoolfile in wire format" : "flushing input");
-spool_file_wireformat = TRUE;
+f.spool_file_wireformat = TRUE;
for (;;)
{
string_sprintf(" I=[%s]:%d", interface_address, interface_port));
}
}
-if (tcp_in_fastopen && !tcp_in_fastopen_logged)
+if (f.tcp_in_fastopen && !f.tcp_in_fastopen_logged)
{
g = string_catn(g, US" TFO", 4);
- tcp_in_fastopen_logged = TRUE;
+ f.tcp_in_fastopen_logged = TRUE;
}
if (sender_ident)
g = string_append(g, 2, US" U=", sender_ident);
if (received_protocol)
g = string_append(g, 2, US" P=", received_protocol);
-if (LOGGING(pipelining) && smtp_in_pipelining_advertised)
- g = string_catn(g, US" L-", smtp_in_pipelining_used ? 2 : 3);
+if (LOGGING(pipelining) && f.smtp_in_pipelining_advertised)
+ g = string_catn(g, US" L-", f.smtp_in_pipelining_used ? 2 : 3);
return g;
}
#ifndef DISABLE_DKIM
/* Call into DKIM to set up the context. In CHUNKING mode
we clear the dot-stuffing flag */
-if (smtp_input && !smtp_batched_input && !dkim_disable_verify)
+if (smtp_input && !smtp_batched_input && !f.dkim_disable_verify)
dkim_exim_verify_init(chunking_state <= CHUNKING_OFFERED);
#endif
prevent further reading), and break out of the loop, having freed the
empty header, and set next = NULL to indicate no data line. */
- if (ptr == 0 && ch == '.' && dot_ends)
+ if (ptr == 0 && ch == '.' && f.dot_ends)
{
ch = (receive_getc)(GETC_BUFFER_UNLIMITED);
if (ch == '\r')
log_write(0, LOG_MAIN, "ridiculously long message header received from "
"%s (more than %d characters): message abandoned",
- sender_host_unknown? sender_ident : sender_fullhost, header_maxsize);
+ f.sender_host_unknown ? sender_ident : sender_fullhost, header_maxsize);
if (smtp_input)
{
&& regex_match_and_setup(regex_From, next->text, 0, -1)
)
{
- if (!sender_address_forced)
+ if (!f.sender_address_forced)
{
uschar *uucp_sender = expand_string(uucp_from_sender);
if (!uucp_sender)
{
sender_address = newsender;
- if (trusted_caller || filter_test != FTEST_NONE)
+ if (f.trusted_caller || filter_test != FTEST_NONE)
{
authenticated_sender = NULL;
originator_name = US"";
- sender_local = FALSE;
+ f.sender_local = FALSE;
}
if (filter_test != FTEST_NONE)
{
log_write(0, LOG_MAIN, "overlong message header line received from "
"%s (more than %d characters): message abandoned",
- sender_host_unknown? sender_ident : sender_fullhost,
+ f.sender_host_unknown ? sender_ident : sender_fullhost,
header_line_maxsize);
if (smtp_input)
set.) */
case htype_sender:
- h->type = !active_local_sender_retain
- && ( sender_local && !trusted_caller && !suppress_local_fixups
- || submission_mode
+ h->type = !f.active_local_sender_retain
+ && ( f.sender_local && !f.trusted_caller && !f.suppress_local_fixups
+ || f.submission_mode
)
&& (!resents_exist || is_resent)
? htype_old : htype_sender;
uschar *s = Ustrchr(h->text, ':') + 1;
while (isspace(*s)) s++;
- parse_allow_group = TRUE; /* Allow address group syntax */
+ f.parse_allow_group = TRUE; /* Allow address group syntax */
while (*s != 0)
{
while (isspace(*s)) s++;
} /* Next address */
- parse_allow_group = FALSE; /* Reset group syntax flags */
- parse_found_group = FALSE;
+ f.parse_allow_group = FALSE; /* Reset group syntax flags */
+ f.parse_found_group = FALSE;
/* If this was the bcc: header, mark it "old", which means it
will be kept on the spool, but not transmitted as part of the
any illegal characters therein. */
if ( !msgid_header
- && ((!sender_host_address && !suppress_local_fixups) || submission_mode))
+ && ((!sender_host_address && !f.suppress_local_fixups) || f.submission_mode))
{
uschar *p;
uschar *id_text = US"";
uschar *new_id_domain = expand_string(message_id_domain);
if (!new_id_domain)
{
- if (!expand_string_forcedfail)
+ if (!f.expand_string_forcedfail)
log_write(0, LOG_MAIN|LOG_PANIC,
"expansion of \"%s\" (message_id_header_domain) "
"failed: %s", message_id_domain, expand_string_message);
uschar *new_id_text = expand_string(message_id_text);
if (!new_id_text)
{
- if (!expand_string_forcedfail)
+ if (!f.expand_string_forcedfail)
log_write(0, LOG_MAIN|LOG_PANIC,
"expansion of \"%s\" (message_id_header_text) "
"failed: %s", message_id_text, expand_string_message);
From:) but we still want to ensure a valid Sender: if it is required. */
if ( !from_header
- && ((!sender_host_address && !suppress_local_fixups) || submission_mode))
+ && ((!sender_host_address && !f.suppress_local_fixups) || f.submission_mode))
{
uschar *oname = US"";
if (!sender_host_address)
{
- if (!trusted_caller || sender_name_forced ||
- (!smtp_input && !sender_address_forced))
+ if (!f.trusted_caller || f.sender_name_forced ||
+ (!smtp_input && !f.sender_address_forced))
oname = originator_name;
}
resent_prefix, oname, *oname ? " <" : "");
fromend = *oname ? US">" : US"";
- if (sender_local || local_error_message)
+ if (f.sender_local || f.local_error_message)
header_add(htype_from, "%s%s@%s%s\n", fromstart,
local_part_quote(originator_login), qualify_domain_sender,
fromend);
- else if (submission_mode && authenticated_id)
+ else if (f.submission_mode && authenticated_id)
{
if (!submission_domain)
header_add(htype_from, "%s%s@%s%s\n", fromstart,
parse_extract_address fails, and a Sender: header is inserted, as required. */
if ( from_header
- && ( active_local_from_check
- && ( sender_local && !trusted_caller && !suppress_local_fixups
- || submission_mode && authenticated_id
+ && ( f.active_local_from_check
+ && ( f.sender_local && !f.trusted_caller && !f.suppress_local_fixups
+ || f.submission_mode && authenticated_id
) ) )
{
BOOL make_sender = TRUE;
&start, &end, &domain, FALSE);
uschar *generated_sender_address;
- generated_sender_address = submission_mode
+ generated_sender_address = f.submission_mode
? !submission_domain
? string_sprintf("%s@%s",
local_part_quote(authenticated_id), qualify_domain_sender)
appropriate rewriting rules. */
if (make_sender)
- if (submission_mode && !submission_name)
+ if (f.submission_mode && !submission_name)
header_add(htype_sender, "%sSender: %s\n", resent_prefix,
generated_sender_address);
else
header_add(htype_sender, "%sSender: %s <%s>\n",
resent_prefix,
- submission_mode? submission_name : originator_name,
+ f.submission_mode ? submission_name : originator_name,
generated_sender_address);
/* Ensure that a non-null envelope sender address corresponds to the
submission mode sender address. */
- if (submission_mode && *sender_address)
+ if (f.submission_mode && *sender_address)
{
if (!sender_address_unrewritten)
sender_address_unrewritten = sender_address;
*/
if ( !date_header_exists
- && ((!sender_host_address && !suppress_local_fixups) || submission_mode))
+ && ((!sender_host_address && !f.suppress_local_fixups) || f.submission_mode))
header_add_at_position(!resents_exist, NULL, FALSE, htype_other,
"%sDate: %s\n", resent_prefix, tod_stamp(tod_full));
deliver_datafile = data_fd;
user_msg = NULL;
-enable_dollar_recipients = TRUE;
+f.enable_dollar_recipients = TRUE;
if (recipients_count == 0)
- blackholed_by = recipients_discarded ? US"MAIL ACL" : US"RCPT ACL";
+ blackholed_by = f.recipients_discarded ? US"MAIL ACL" : US"RCPT ACL";
else
{
{
#ifndef DISABLE_DKIM
- if (!dkim_disable_verify)
+ if (!f.dkim_disable_verify)
{
/* Finish verification */
dkim_exim_verify_finish();
if (acl_not_smtp)
{
uschar *user_msg, *log_msg;
- authentication_local = TRUE;
+ f.authentication_local = TRUE;
rc = acl_check(ACL_WHERE_NOTSMTP, NULL, acl_not_smtp, &user_msg, &log_msg);
if (rc == DISCARD)
{
/* The applicable ACLs have been run */
- if (deliver_freeze) frozen_by = US"ACL"; /* for later logging */
- if (queue_only_policy) queued_by = US"ACL";
+ if (f.deliver_freeze) frozen_by = US"ACL"; /* for later logging */
+ if (f.queue_only_policy) queued_by = US"ACL";
}
#ifdef WITH_CONTENT_SCAN
alarm(0);
os_non_restarting_signal(SIGALRM, sigalrm_handler);
- enable_dollar_recipients = FALSE;
+ f.enable_dollar_recipients = FALSE;
store_pool = POOL_MAIN; /* In case changed */
DEBUG(D_receive) debug_printf("local_scan() returned %d %s\n", rc,
if (rc == LOCAL_SCAN_ACCEPT_FREEZE)
{
- if (!deliver_freeze) /* ACL might have already frozen */
+ if (!f.deliver_freeze) /* ACL might have already frozen */
{
- deliver_freeze = TRUE;
+ f.deliver_freeze = TRUE;
deliver_frozen_at = time(NULL);
frozen_by = US"local_scan()";
}
}
else if (rc == LOCAL_SCAN_ACCEPT_QUEUE)
{
- if (!queue_only_policy) /* ACL might have already queued */
+ if (!f.queue_only_policy) /* ACL might have already queued */
{
- queue_only_policy = TRUE;
+ f.queue_only_policy = TRUE;
queued_by = US"local_scan()";
}
rc = LOCAL_SCAN_ACCEPT;
/* Ensure the first time flag is set in the newly-received message. */
-deliver_firsttime = TRUE;
+f.deliver_firsttime = TRUE;
#ifdef EXPERIMENTAL_BRIGHTMAIL
if (bmi_run == 1)
if (mua_wrapper)
{
- deliver_freeze = FALSE;
- queue_only_policy = FALSE;
+ f.deliver_freeze = FALSE;
+ f.queue_only_policy = FALSE;
}
/* Keep the data file open until we have written the header file, in order to
{
uschar *now = tod_stamp(tod_log);
fprintf(message_log, "%s Received from %s\n", now, g->s+3);
- if (deliver_freeze) fprintf(message_log, "%s frozen by %s\n", now,
+ if (f.deliver_freeze) fprintf(message_log, "%s frozen by %s\n", now,
frozen_by);
- if (queue_only_policy) fprintf(message_log,
+ if (f.queue_only_policy) fprintf(message_log,
"%s no immediate delivery: queued%s%s by %s\n", now,
*queue_name ? " in " : "", *queue_name ? CS queue_name : "",
queued_by);
arrival, and outputting an SMTP response. While writing to the log, set a flag
to cause a call to receive_bomb_out() if the log cannot be opened. */
-receive_call_bombout = TRUE;
+f.receive_call_bombout = TRUE;
/* Before sending an SMTP response in a TCP/IP session, we check to see if the
connection has gone away. This can only be done if there is no unconsumed input
connection will vanish between the time of this test and the sending of the
response, but the chance of this happening should be small. */
-if (smtp_input && sender_host_address && !sender_host_notsocket &&
+if (smtp_input && sender_host_address && !f.sender_host_notsocket &&
!receive_smtp_buffered())
{
struct timeval tv;
/* Log any control actions taken by an ACL or local_scan(). */
- if (deliver_freeze) log_write(0, LOG_MAIN, "frozen by %s", frozen_by);
- if (queue_only_policy) log_write(L_delay_delivery, LOG_MAIN,
+ if (f.deliver_freeze) log_write(0, LOG_MAIN, "frozen by %s", frozen_by);
+ if (f.queue_only_policy) log_write(L_delay_delivery, LOG_MAIN,
"no immediate delivery: queued%s%s by %s",
*queue_name ? " in " : "", *queue_name ? CS queue_name : "",
queued_by);
}
-receive_call_bombout = FALSE;
+f.receive_call_bombout = FALSE;
store_reset(g); /* The store for the main log message can be reused */
/* If the message is frozen, and freeze_tell is set, do the telling. */
-if (deliver_freeze && freeze_tell && freeze_tell[0])
+if (f.deliver_freeze && freeze_tell && freeze_tell[0])
moan_tell_someone(freeze_tell, NULL, US"Message frozen on arrival",
"Message %s was frozen on arrival by %s.\nThe sender is <%s>.\n",
message_id, frozen_by, sender_address);
/* We have not reached the next try time. Check for the ultimate address
timeout if the host has not expired. */
- if (now < host_retry_record->next_try && !deliver_force)
+ if (now < host_retry_record->next_try && !f.deliver_force)
{
if (!host_retry_record->expired &&
retry_ultimate_address_timeout(host_key, domain,
if (message_retry_record)
{
*retry_message_key = message_key;
- if (now < message_retry_record->next_try && !deliver_force)
+ if (now < message_retry_record->next_try && !f.deliver_force)
{
if (!retry_ultimate_address_timeout(host_key, domain,
message_retry_record, now))
uschar *key = expand_string(rule->key);
if (key == NULL)
{
- if (!expand_string_forcedfail)
+ if (!f.expand_string_forcedfail)
log_write(0, LOG_MAIN|LOG_PANIC, "failed to expand \"%s\" while "
"checking for SMTP rewriting: %s", rule->key, expand_string_message);
continue;
if (new == NULL)
{
- if (expand_string_forcedfail)
+ if (f.expand_string_forcedfail)
{ if ((rule->flags & rewrite_quit) != 0) break; else continue; }
expand_string_message = expand_hide_passwords(expand_string_message);
DEBUG(D_rewrite)
debug_printf("rewrite_one_header: type=%c:\n %s", h->type, h->text);
-parse_allow_group = TRUE; /* Allow group syntax */
+f.parse_allow_group = TRUE; /* Allow group syntax */
/* Loop for multiple addresses in the header. We have to go through them all
in case any need qualifying, even if there's no rewriting. Pathological headers
/* Can only qualify if permitted; if not, no rewrite. */
- if (changed && ((is_recipient && !allow_unqualified_recipient) ||
- (!is_recipient && !allow_unqualified_sender)))
+ if (changed && ((is_recipient && !f.allow_unqualified_recipient) ||
+ (!is_recipient && !f.allow_unqualified_sender)))
{
store_reset(loop_reset_point);
continue;
}
}
-parse_allow_group = FALSE; /* Reset group flags */
-parse_found_group = FALSE;
+f.parse_allow_group = FALSE; /* Reset group flags */
+f.parse_found_group = FALSE;
/* If a rewrite happened and "replace" is true, put the new header into the
chain following the old one, and mark the old one as replaced. */
if (!ss)
{
- if (expand_string_forcedfail) continue;
+ if (f.expand_string_forcedfail) continue;
*perror = string_sprintf("failed to expand \"%s\" for require_files: %s",
check, expand_string_message);
goto RETURN_DEFER;
sender_data = NULL;
local_user_gid = (gid_t)(-1);
local_user_uid = (uid_t)(-1);
-search_find_defer = FALSE;
+f.search_find_defer = FALSE;
/* Skip this router if not verifying and it has verify_only set */
/* Skip this router if testing an address (-bt) and address_test is not set */
-if (address_test_mode && !r->address_test)
+if (f.address_test_mode && !r->address_test)
{
DEBUG(D_route) debug_printf("%s router skipped: address_test is unset\n",
r->name);
uschar *router_home = expand_string(r->router_home_directory);
if (!router_home)
{
- if (!expand_string_forcedfail)
+ if (!f.expand_string_forcedfail)
{
*perror = string_sprintf("failed to expand \"%s\" for "
"router_home_directory: %s", r->router_home_directory,
DEBUG(D_route) debug_printf("checking \"condition\" \"%.80s\"...\n", r->condition);
if (!expand_check_condition(r->condition, r->name, US"router"))
{
- if (search_find_defer)
+ if (f.search_find_defer)
{
*perror = US"condition check lookup defer";
DEBUG(D_route) debug_printf("%s\n", *perror);
/* There are some weird cases where logging is disabled */
- disable_logging = r->disable_logging;
+ f.disable_logging = r->disable_logging;
/* Record the last router to handle the address, and set the default
next router. */
deliver_address_data = expand_string(r->address_data);
if (!deliver_address_data)
{
- if (expand_string_forcedfail)
+ if (f.expand_string_forcedfail)
{
DEBUG(D_route) debug_printf("forced failure in expansion of \"%s\" "
"(address_data): decline action taken\n", r->address_data);
uschar *expmessage = expand_string(addr->router->cannot_route_message);
if (!expmessage)
{
- if (!expand_string_forcedfail)
+ if (!f.expand_string_forcedfail)
log_write(0, LOG_MAIN|LOG_PANIC, "failed to expand "
"cannot_route_message in %s router: %s", addr->router->name,
expand_string_message);
if (!newaddress)
{
- if (expand_string_forcedfail) continue;
+ if (f.expand_string_forcedfail) continue;
addr->basic_errno = ERRNO_EXPANDFAIL;
addr->message = string_sprintf("translate_ip_address expansion "
"failed: %s", expand_string_message);
deliver_set_expansions(NULL);
router_name = NULL;
-disable_logging = FALSE;
+f.disable_logging = FALSE;
return yield;
}
if (ob->check_srv)
{
if ( !(srv_service = expand_string(ob->check_srv))
- && !expand_string_forcedfail)
+ && !f.expand_string_forcedfail)
{
addr->message = string_sprintf("%s router: failed to expand \"%s\": %s",
rblock->name, ob->check_srv, expand_string_message);
if ( ob->ipv4_only
&& expand_check_condition(ob->ipv4_only, rblock->name, US"router"))
flags = flags & ~HOST_FIND_BY_AAAA | HOST_FIND_IPV4_ONLY;
- else if (search_find_defer)
+ else if (f.search_find_defer)
return DEFER;
if ( ob->ipv4_prefer
&& expand_check_condition(ob->ipv4_prefer, rblock->name, US"router"))
flags |= HOST_FIND_IPV4_FIRST;
- else if (search_find_defer)
+ else if (f.search_find_defer)
return DEFER;
/* Set up the rest of the initial host item. Others may get chained on if
/* If there's a syntax error, do not continue with any widening, and note
the error. */
- if (host_find_failed_syntax)
+ if (f.host_find_failed_syntax)
{
addr->message = string_sprintf("mail domain \"%s\" is syntactically "
"invalid", h.name);
if (newhostlist == NULL)
{
- if (expand_string_forcedfail) return DECLINE;
+ if (f.expand_string_forcedfail) return DECLINE;
addr->message = string_sprintf("%s router: failed to expand \"%s\": %s",
rblock->name, hostlist, expand_string_message);
return DEFER;
/* Don't do the "one_time" thing for the first pass of a 2-stage queue run. */
- if (ob->one_time && !queue_2stage)
+ if (ob->one_time && !f.queue_2stage)
{
for (parent = addr; parent->parent; parent = parent->parent) ;
next->onetime_parent = parent->address;
/* When verifying and testing addresses, the "logwrite" command in filters
must be bypassed. */
-if (verify == v_none && !address_test_mode) options |= RDO_REALLOG;
+if (verify == v_none && !f.address_test_mode) options |= RDO_REALLOG;
/* Sort out the fixed or dynamic uid/gid. This uid is used (a) for reading the
file (and interpreting a filter) and (b) for running the transports for
high so that their completion does not mark the original address done. */
case FF_FREEZE:
- if (!deliver_manual_thaw)
+ if (!f.deliver_manual_thaw)
{
if ((xrc = sort_errors_and_headers(rblock, addr, verify, &addr_prop))
!= OK) return xrc;
if (!moan_skipped_syntax_errors(
rblock->name, /* For message content */
eblock, /* Ditto */
- (verify != v_none || address_test_mode)?
+ (verify != v_none || f.address_test_mode)?
NULL : ob->syntax_errors_to, /* Who to mail */
generated != NULL, /* True if not all failed */
ob->syntax_errors_text)) /* Custom message */
if (frc == FF_DELIVERED)
{
- if (generated == NULL && verify == v_none && !address_test_mode)
+ if (generated == NULL && verify == v_none && !f.address_test_mode)
{
log_write(0, LOG_MAIN, "=> %s <%s> R=%s", discarded, addr->address,
rblock->name);
if (newh != NULL)
{
h = newh;
- header_rewritten = TRUE;
+ f.header_rewritten = TRUE;
}
}
}
{
uschar *yield = expand_string(s);
if (yield != NULL) return yield;
-if (expand_string_forcedfail)
+if (f.expand_string_forcedfail)
{
DEBUG(D_route) debug_printf("forced failure for expansion of \"%s\"\n", s);
*prc = DECLINE;
if (s == NULL)
{
- if (expand_string_forcedfail)
+ if (f.expand_string_forcedfail)
{
DEBUG(D_route)
debug_printf("forced expansion failure - ignoring errors_to\n");
}
else
{
- BOOL save_address_test_mode = address_test_mode;
+ BOOL save_address_test_mode = f.address_test_mode;
int save1 = 0;
int i;
const uschar ***p;
for (i = 0, p = address_expansions; *p != NULL;)
address_expansions_save[i++] = **p++;
- address_test_mode = FALSE;
+ f.address_test_mode = FALSE;
/* NOTE: the address is verified as a recipient, not a sender. This is
perhaps confusing. It isn't immediately obvious what to do: we want to have
DEBUG(D_route|D_verify)
debug_printf("------ End verifying errors address %s ------\n", s);
- address_test_mode = save_address_test_mode;
+ f.address_test_mode = save_address_test_mode;
for (i = 0, p = address_expansions; *p != NULL;)
**p++ = address_expansions_save[i++];
while ((s = string_nextinlist(&list, &sep, NULL, 0)))
if (!(s = expand_string(s)))
{
- if (!expand_string_forcedfail)
+ if (!f.expand_string_forcedfail)
{
addr->message = string_sprintf(
"%s router failed to expand add_headers item \"%s\": %s",
while ((s = string_nextinlist(&list, &sep, NULL, 0)))
if (!(s = expand_string(s)))
{
- if (!expand_string_forcedfail)
+ if (!f.expand_string_forcedfail)
{
addr->message = string_sprintf(
"%s router failed to expand remove_headers item \"%s\": %s",
addr->message =
string_sprintf("lookup of host \"%s\" failed in %s router%s",
h->name, rblock->name,
- host_find_failed_syntax? ": syntax error in name" : "");
+ f.host_find_failed_syntax? ": syntax error in name" : "");
if (hff_code == hff_defer) return DEFER;
if (hff_code == hff_fail) return FAIL;
the callers don't have to test for NULL, set an empty string. */
search_error_message = US"";
-search_find_defer = FALSE;
+f.search_find_defer = FALSE;
DEBUG(D_lookup) debug_printf("internal_search_find: file=\"%s\"\n "
"type=%s key=\"%s\"\n", filename,
if (lookup_list[search_type]->find(c->handle, filename, keystring, keylength,
&data, &search_error_message, &do_cache) == DEFER)
- search_find_defer = TRUE;
+ f.search_find_defer = TRUE;
/* A record that has been found is now in data, which is either NULL
or points to a bit of dynamic store. Cache the result of the lookup if
{
if (data)
debug_printf("lookup yielded: %s\n", data);
- else if (search_find_defer)
+ else if (f.search_find_defer)
debug_printf("lookup deferred: %s\n", search_error_message);
else debug_printf("lookup failed\n");
}
entry but could have been partial, flag to set up variables. */
yield = internal_search_find(handle, filename, keystring);
-if (search_find_defer) return NULL;
+if (f.search_find_defer) return NULL;
if (yield != NULL) { if (partial >= 0) set_null_wild = TRUE; }
/* Not matched a complete entry; handle partial lookups, but only if the full
Ustrcpy(keystring2 + affixlen, keystring);
DEBUG(D_lookup) debug_printf("trying partial match %s\n", keystring2);
yield = internal_search_find(handle, filename, keystring2);
- if (search_find_defer) return NULL;
+ if (f.search_find_defer) return NULL;
}
/* The key in its entirety did not match a wild entry; try chopping off
DEBUG(D_lookup) debug_printf("trying partial match %s\n", keystring3);
yield = internal_search_find(handle, filename, keystring3);
- if (search_find_defer) return NULL;
+ if (f.search_find_defer) return NULL;
if (yield != NULL)
{
/* First variable is the wild part; second is the fixed part. Take care
DEBUG(D_lookup) debug_printf("trying default match %s\n", atat);
yield = internal_search_find(handle, filename, atat);
*atat = savechar;
- if (search_find_defer) return NULL;
+ if (f.search_find_defer) return NULL;
if (yield != NULL && expand_setup != NULL && *expand_setup >= 0)
{
filter->errmsg=CUS "header string expansion failed";
return -1;
}
- parse_allow_group = TRUE;
+ f.parse_allow_group = TRUE;
while (*header_value && !*cond)
{
uschar *error;
if (saveend == 0) break;
header_value = end_addr + 1;
}
- parse_allow_group = FALSE;
- parse_found_group = FALSE;
+ f.parse_allow_group = FALSE;
+ f.parse_found_group = FALSE;
}
}
return 1;
static BOOL
check_sync(void)
{
-if (!smtp_enforce_sync || !sender_host_address || sender_host_notsocket)
+if (!smtp_enforce_sync || !sender_host_address || f.sender_host_notsocket)
return TRUE;
return wouldblock_reading();
pipeline_response(void)
{
if ( !smtp_enforce_sync || !sender_host_address
- || sender_host_notsocket || !smtp_in_pipelining_advertised)
+ || f.sender_host_notsocket || !f.smtp_in_pipelining_advertised)
return FALSE;
if (wouldblock_reading()) return FALSE;
-smtp_in_pipelining_used = TRUE;
+f.smtp_in_pipelining_used = TRUE;
return TRUE;
}
/* Unless PIPELINING was offered, there should be no next command
until after we ack that chunk */
- if (!smtp_in_pipelining_advertised && !check_sync())
+ if (!f.smtp_in_pipelining_advertised && !check_sync())
{
unsigned n = smtp_inend - smtp_inptr;
if (n > 32) n = 32;
}
else
{
- proxy_session_failed = TRUE;
+ f.proxy_session_failed = TRUE;
DEBUG(D_receive)
debug_printf("Failure to extract proxied host, only QUIT allowed\n");
}
{
#ifdef SUPPORT_PROXY
/* Only allow QUIT command if Proxy Protocol parsing failed */
- if (proxy_session && proxy_session_failed && p->cmd != QUIT_CMD)
+ if (proxy_session && f.proxy_session_failed && p->cmd != QUIT_CMD)
continue;
#endif
if ( p->len
check_sync && /* Local flag set */
smtp_enforce_sync && /* Global flag set */
sender_host_address != NULL && /* Not local input */
- !sender_host_notsocket) /* Really is a socket */
+ !f.sender_host_notsocket) /* Really is a socket */
return BADSYN_CMD;
/* The variables $smtp_command and $smtp_command_argument point into the
#ifdef SUPPORT_PROXY
/* Only allow QUIT command if Proxy Protocol parsing failed */
-if (proxy_session && proxy_session_failed)
+if (proxy_session && f.proxy_session_failed)
return PROXY_FAIL_IGNORE_CMD;
#endif
&& check_sync /* Local flag set */
&& smtp_enforce_sync /* Global flag set */
&& sender_host_address /* Not local input */
- && !sender_host_notsocket) /* Really is a socket */
+ && !f.sender_host_notsocket) /* Really is a socket */
return BADSYN_CMD;
return OTHER_CMD;
if (host_checking)
return string_sprintf("SMTP connection from %s", hostname);
-if (sender_host_unknown || sender_host_notsocket)
+if (f.sender_host_unknown || f.sender_host_notsocket)
return string_sprintf("SMTP connection from %s", sender_ident);
-if (is_inetd)
+if (f.is_inetd)
return string_sprintf("SMTP connection from %s (via inetd)", hostname);
if (LOGGING(incoming_interface) && interface_address != NULL)
if (!(s = string_from_gstring(g))) s = US"";
log_write(0, LOG_MAIN, "no MAIL in %sSMTP connection from %s D=%s%s",
- tcp_in_fastopen ? US"TFO " : US"",
+ f.tcp_in_fastopen ? US"TFO " : US"",
host_and_ident(FALSE), string_timesince(&smtp_connection_start), s);
}
message_size = -1;
acl_added_headers = NULL;
acl_removed_headers = NULL;
-queue_only_policy = FALSE;
+f.queue_only_policy = FALSE;
rcpt_smtp_response = NULL;
rcpt_smtp_response_same = TRUE;
rcpt_in_progress = FALSE;
-deliver_freeze = FALSE; /* Can be set by ACL */
+f.deliver_freeze = FALSE; /* Can be set by ACL */
freeze_tell = freeze_tell_config; /* Can be set by ACL */
fake_response = OK; /* Can be set by ACL */
#ifdef WITH_CONTENT_SCAN
-no_mbox_unspool = FALSE; /* Can be set by ACL */
+f.no_mbox_unspool = FALSE; /* Can be set by ACL */
#endif
-submission_mode = FALSE; /* Can be set by ACL */
-suppress_local_fixups = suppress_local_fixups_default; /* Can be set by ACL */
-active_local_from_check = local_from_check; /* Can be set by ACL */
-active_local_sender_retain = local_sender_retain; /* Can be set by ACL */
+f.submission_mode = FALSE; /* Can be set by ACL */
+f.suppress_local_fixups = f.suppress_local_fixups_default; /* Can be set by ACL */
+f.active_local_from_check = local_from_check; /* Can be set by ACL */
+f.active_local_sender_retain = local_sender_retain; /* Can be set by ACL */
sending_ip_address = NULL;
return_path = sender_address = NULL;
sender_data = NULL; /* Can be set by ACL */
dkim_cur_signer = dkim_signers =
dkim_signing_domain = dkim_signing_selector = dkim_signatures = NULL;
dkim_cur_signer = dkim_signers = dkim_signing_domain = dkim_signing_selector = NULL;
-dkim_disable_verify = FALSE;
+f.dkim_disable_verify = FALSE;
dkim_collect_input = 0;
dkim_verify_overall = dkim_verify_status = dkim_verify_reason = NULL;
dkim_key_length = 0;
dkim_verify_signers = US"$dkim_signers";
#endif
#ifdef EXPERIMENTAL_DMARC
-dmarc_has_been_checked = dmarc_disable_verify = dmarc_enable_forensic = FALSE;
+f.dmarc_has_been_checked = f.dmarc_disable_verify = f.dmarc_enable_forensic = FALSE;
dmarc_domain_policy = dmarc_status = dmarc_status_text =
dmarc_used_domain = NULL;
#endif
if ( !sender_domain
&& sender_address[0] != 0 && sender_address[0] != '@')
- if (allow_unqualified_sender)
+ if (f.allow_unqualified_sender)
{
sender_address = rewrite_address_qualify(sender_address, FALSE);
DEBUG(D_receive) debug_printf("unqualified address %s accepted "
add it to the list of recipients. */
if (!recipient_domain)
- if (allow_unqualified_recipient)
+ if (f.allow_unqualified_recipient)
{
DEBUG(D_receive) debug_printf("unqualified address %s accepted\n",
recipient);
)
{
DEBUG(D_receive) debug_printf("TCP_FASTOPEN mode connection (state TCP_SYN_RECV)\n");
- tcp_in_fastopen = TRUE;
+ f.tcp_in_fastopen = TRUE;
}
# endif
}
synprot_error_count = unknown_command_count = nonmail_command_count = 0;
smtp_delay_mail = smtp_rlm_base;
auth_advertised = FALSE;
-smtp_in_pipelining_advertised = smtp_in_pipelining_used = FALSE;
-pipelining_enable = TRUE;
+f.smtp_in_pipelining_advertised = f.smtp_in_pipelining_used = FALSE;
+f.pipelining_enable = TRUE;
sync_cmd_limit = NON_SYNC_CMD_NON_PIPELINING;
smtp_exit_function_called = FALSE; /* For avoiding loop in not-quit exit */
/* If receiving by -bs from a trusted user, or testing with -bh, we allow
authentication settings from -oMaa to remain in force. */
-if (!host_checking && !sender_host_notsocket)
+if (!host_checking && !f.sender_host_notsocket)
sender_host_auth_pubname = sender_host_authenticated = NULL;
authenticated_by = NULL;
If smtp_accept_max and smtp_accept_reserve are set, keep some connections in
reserve for certain hosts and/or networks. */
-if (!sender_host_unknown)
+if (!f.sender_host_unknown)
{
int rc;
BOOL reserved_host = FALSE;
#define OPTSTYLE 3
#endif
- if (!host_checking && !sender_host_notsocket)
+ if (!host_checking && !f.sender_host_notsocket)
{
#if OPTSTYLE == 1
EXIM_SOCKLEN_T optlen = sizeof(struct ip_options) + MAX_IPOPTLEN;
setting is an attempt to get rid of some hanging connections that stick in
read() when the remote end (usually a dialup) goes away. */
- if (smtp_accept_keepalive && !sender_host_notsocket)
+ if (smtp_accept_keepalive && !f.sender_host_notsocket)
ip_keepalive(fileno(smtp_out), sender_host_address, FALSE);
/* If the current host matches host_lookup, set the name by doing a
addresses in the headers. For a site that permits no qualification, this
won't take long, however. */
- allow_unqualified_sender =
+ f.allow_unqualified_sender =
verify_check_host(&sender_unqualified_hosts) == OK;
- allow_unqualified_recipient =
+ f.allow_unqualified_recipient =
verify_check_host(&recipient_unqualified_hosts) == OK;
/* Determine whether HELO/EHLO is required for this host. The requirement
#ifdef SUPPORT_PROXY
proxy_session = FALSE;
-proxy_session_failed = FALSE;
+f.proxy_session_failed = FALSE;
if (check_proxy_protocol_host())
setup_proxy_protocol_host();
#endif
int esclen = 0;
uschar *esc = US"";
-if (!final && no_multiline_responses) return;
+if (!final && f.no_multiline_responses) return;
if (codelen > 4)
{
smtp_printf("%.3s%c%.*s%s\r\n", !final, code, final ? ' ':'-', esclen, esc, msg);
return;
}
- else if (nl[1] == 0 || no_multiline_responses)
+ else if (nl[1] == 0 || f.no_multiline_responses)
{
smtp_printf("%.3s%c%.*s%.*s\r\n", !final, code, final ? ' ':'-', esclen, esc,
(int)(nl - msg), msg);
be re-implemented in a tidier fashion. */
else
- if (acl_temp_details && user_msg)
+ if (f.acl_temp_details && user_msg)
{
if ( smtp_return_error_details
&& sender_verified_failed
else if (sender_host_address == NULL)
{
HDEBUG(D_receive) debug_printf("no client IP address: assume success\n");
- helo_verified = TRUE;
+ f.helo_verified = TRUE;
}
/* Deal with the more common case when there is a sending IP address */
else if (sender_helo_name[0] == '[')
{
- helo_verified = Ustrncmp(sender_helo_name+1, sender_host_address,
+ f.helo_verified = Ustrncmp(sender_helo_name+1, sender_host_address,
Ustrlen(sender_host_address)) == 0;
#if HAVE_IPV6
- if (!helo_verified)
+ if (!f.helo_verified)
{
if (strncmpic(sender_host_address, US"::ffff:", 7) == 0)
- helo_verified = Ustrncmp(sender_helo_name + 1,
+ f.helo_verified = Ustrncmp(sender_helo_name + 1,
sender_host_address + 7, Ustrlen(sender_host_address) - 7) == 0;
}
#endif
HDEBUG(D_receive)
- { if (helo_verified) debug_printf("matched host address\n"); }
+ { if (f.helo_verified) debug_printf("matched host address\n"); }
}
/* Do a reverse lookup if one hasn't already given a positive or negative
/* If a host name is known, check it and all its aliases. */
if (sender_host_name)
- if ((helo_verified = strcmpic(sender_host_name, sender_helo_name) == 0))
+ if ((f.helo_verified = strcmpic(sender_host_name, sender_helo_name) == 0))
{
sender_helo_dnssec = sender_host_dnssec;
HDEBUG(D_receive) debug_printf("matched host name\n");
{
uschar **aliases = sender_host_aliases;
while (*aliases)
- if ((helo_verified = strcmpic(*aliases++, sender_helo_name) == 0))
+ if ((f.helo_verified = strcmpic(*aliases++, sender_helo_name) == 0))
{
sender_helo_dnssec = sender_host_dnssec;
break;
}
- HDEBUG(D_receive) if (helo_verified)
+ HDEBUG(D_receive) if (f.helo_verified)
debug_printf("matched alias %s\n", *(--aliases));
}
/* Final attempt: try a forward lookup of the helo name */
- if (!helo_verified)
+ if (!f.helo_verified)
{
int rc;
host_item h;
for (hh = &h; hh; hh = hh->next)
if (Ustrcmp(hh->address, sender_host_address) == 0)
{
- helo_verified = TRUE;
+ f.helo_verified = TRUE;
if (h.dnssec == DS_YES) sender_helo_dnssec = TRUE;
HDEBUG(D_receive)
{
}
}
-if (!helo_verified) helo_verify_failed = TRUE; /* We've tried ... */
+if (!f.helo_verified) f.helo_verify_failed = TRUE; /* We've tried ... */
return yield;
}
qualify_recipient(uschar ** recipient, uschar * smtp_cmd_data, uschar * tag)
{
int rd;
-if (allow_unqualified_recipient || strcmpic(*recipient, US"postmaster") == 0)
+if (f.allow_unqualified_recipient || strcmpic(*recipient, US"postmaster") == 0)
{
DEBUG(D_receive) debug_printf("unqualified address %s accepted\n",
*recipient);
smtp_reset(reset_point);
message_ended = END_NOTSTARTED;
-chunking_state = chunking_offered ? CHUNKING_OFFERED : CHUNKING_NOT_OFFERED;
+chunking_state = f.chunking_offered ? CHUNKING_OFFERED : CHUNKING_NOT_OFFERED;
cmd_list[CMD_LIST_RSET].is_mail_cmd = TRUE;
cmd_list[CMD_LIST_HELO].is_mail_cmd = TRUE;
authentication_failed = TRUE;
cmd_list[CMD_LIST_AUTH].is_mail_cmd = FALSE;
- if (!auth_advertised && !allow_auth_unadvertised)
+ if (!auth_advertised && !f.allow_auth_unadvertised)
{
done = synprot_error(L_smtp_protocol_error, 503, NULL,
US"AUTH command used when not advertised");
for (au = auths; au; au = au->next)
if (strcmpic(s, au->public_name) == 0 && au->server &&
- (au->advertised || allow_auth_unadvertised))
+ (au->advertised || f.allow_auth_unadvertised))
break;
if (au)
is set, ensure that the HELO name matches the actual host. If helo_verify
is set, do the same check, but softly. */
- if (!sender_host_unknown)
+ if (!f.sender_host_unknown)
{
- BOOL old_helo_verified = helo_verified;
+ BOOL old_helo_verified = f.helo_verified;
uschar *p = smtp_cmd_data;
while (*p != 0 && !isspace(*p)) { *p = tolower(*p); p++; }
now obsolescent, since the verification can now be requested selectively
at ACL time. */
- helo_verified = helo_verify_failed = sender_helo_dnssec = FALSE;
+ f.helo_verified = f.helo_verify_failed = sender_helo_dnssec = FALSE;
if (helo_required || helo_verify)
{
BOOL tempfail = !smtp_verify_helo();
- if (!helo_verified)
+ if (!f.helo_verified)
{
if (helo_required)
{
log_write(0, LOG_MAIN|LOG_REJECT, "%srejected \"%s %s\" from %s",
tempfail? "temporarily " : "",
hello, sender_helo_name, host_and_ident(FALSE));
- helo_verified = old_helo_verified;
+ f.helo_verified = old_helo_verified;
break; /* End of HELO/EHLO processing */
}
HDEBUG(D_all) debug_printf("%s verification failed but host is in "
that the entire reply is sent in one write(). */
auth_advertised = FALSE;
- smtp_in_pipelining_advertised = FALSE;
+ f.smtp_in_pipelining_advertised = FALSE;
#ifdef SUPPORT_TLS
tls_advertised = FALSE;
# ifdef EXPERIMENTAL_REQUIRETLS
/* Exim is quite happy with pipelining, so let the other end know that
it is safe to use it, unless advertising is disabled. */
- if (pipelining_enable &&
+ if (f.pipelining_enable &&
verify_check_host(&pipelining_advertise_hosts) == OK)
{
g = string_catn(g, smtp_code, 3);
g = string_catn(g, US"-PIPELINING\r\n", 13);
sync_cmd_limit = NON_SYNC_CMD_PIPELINING;
- smtp_in_pipelining_advertised = TRUE;
+ f.smtp_in_pipelining_advertised = TRUE;
}
{
g = string_catn(g, smtp_code, 3);
g = string_catn(g, US"-CHUNKING\r\n", 11);
- chunking_offered = TRUE;
+ f.chunking_offered = TRUE;
chunking_state = CHUNKING_OFFERED;
}
of the SMTP connection. */
if (!sender_domain && *sender_address)
- if (allow_unqualified_sender)
+ if (f.allow_unqualified_sender)
{
sender_domain = Ustrlen(sender_address) + 1;
sender_address = rewrite_address_qualify(sender_address, FALSE);
if (acl_smtp_mail)
{
rc = acl_check(ACL_WHERE_MAIL, NULL, acl_smtp_mail, &user_msg, &log_msg);
- if (rc == OK && !smtp_in_pipelining_advertised && !check_sync())
+ if (rc == OK && !f.smtp_in_pipelining_advertised && !check_sync())
goto SYNC_FAILURE;
}
else
smtp_user_msg(US"250", user_msg);
}
smtp_delay_rcpt = smtp_rlr_base;
- recipients_discarded = (rc == DISCARD);
+ f.recipients_discarded = (rc == DISCARD);
was_rej_mail = FALSE;
}
else
if (sender_address == NULL)
{
- if (smtp_in_pipelining_advertised && last_was_rej_mail)
+ if (f.smtp_in_pipelining_advertised && last_was_rej_mail)
{
smtp_printf("503 sender not yet given\r\n", FALSE);
was_rej_mail = TRUE;
there may be a delay in this, re-check for a synchronization error
afterwards, unless pipelining was advertised. */
- if (recipients_discarded)
+ if (f.recipients_discarded)
rc = DISCARD;
else
if ( (rc = acl_check(ACL_WHERE_RCPT, recipient, acl_smtp_rcpt, &user_msg,
&log_msg)) == OK
- && !smtp_in_pipelining_advertised && !check_sync())
+ && !f.smtp_in_pipelining_advertised && !check_sync())
goto SYNC_FAILURE;
/* The ACL was happy */
log_write(0, LOG_MAIN|LOG_REJECT, "%s F=<%s> RCPT %s: "
"discarded by %s ACL%s%s", host_and_ident(TRUE),
sender_address_unrewritten? sender_address_unrewritten : sender_address,
- smtp_cmd_argument, recipients_discarded? "MAIL" : "RCPT",
+ smtp_cmd_argument, f.recipients_discarded? "MAIL" : "RCPT",
log_msg ? US": " : US"", log_msg ? log_msg : US"");
}
receive_getc = bdat_getc;
receive_ungetc = bdat_ungetc;
- dot_ends = FALSE;
+ f.dot_ends = FALSE;
goto DATA_BDAT;
}
case DATA_CMD:
HAD(SCH_DATA);
- dot_ends = TRUE;
+ f.dot_ends = TRUE;
DATA_BDAT: /* Common code for DATA and BDAT */
if (!discarded && recipients_count <= 0)
rcpt_smtp_response[len-2] = 0;
smtp_respond(code, 3, FALSE, rcpt_smtp_response);
}
- if (smtp_in_pipelining_advertised && last_was_rcpt)
+ if (f.smtp_in_pipelining_advertised && last_was_rcpt)
smtp_printf("503 Valid RCPT command must precede %s\r\n", FALSE,
smtp_names[smtp_connection_had[smtp_ch_index-1]]);
else
else
{
uschar * acl = acl_smtp_predata ? acl_smtp_predata : US"accept";
- enable_dollar_recipients = TRUE;
+ f.enable_dollar_recipients = TRUE;
rc = acl_check(ACL_WHERE_PREDATA, NULL, acl, &user_msg,
&log_msg);
- enable_dollar_recipients = FALSE;
+ f.enable_dollar_recipients = FALSE;
if (rc == OK && !check_sync())
goto SYNC_FAILURE;
done = smtp_handle_acl_fail(ACL_WHERE_EXPN, rc, user_msg, log_msg);
else
{
- BOOL save_log_testing_mode = log_testing_mode;
- address_test_mode = log_testing_mode = TRUE;
+ BOOL save_log_testing_mode = f.log_testing_mode;
+ f.address_test_mode = f.log_testing_mode = TRUE;
(void) verify_address(deliver_make_addr(smtp_cmd_data, FALSE),
smtp_out, vopt_is_recipient | vopt_qualify | vopt_expn, -1, -1, -1,
NULL, NULL, NULL);
- address_test_mode = FALSE;
- log_testing_mode = save_log_testing_mode; /* true for -bh */
+ f.address_test_mode = FALSE;
+ f.log_testing_mode = save_log_testing_mode; /* true for -bh */
}
break;
if ((rc = tls_server_start(tls_require_ciphers, &s)) == OK)
{
if (!tls_remember_esmtp)
- helo_seen = esmtp = auth_advertised = smtp_in_pipelining_advertised = FALSE;
+ helo_seen = esmtp = auth_advertised = f.smtp_in_pipelining_advertised = FALSE;
cmd_list[CMD_LIST_EHLO].is_mail_cmd = TRUE;
cmd_list[CMD_LIST_AUTH].is_mail_cmd = TRUE;
cmd_list[CMD_LIST_TLS_AUTH].is_mail_cmd = TRUE;
if (sender_address || recipients_count > 0)
log_write(L_lost_incoming_connection, LOG_MAIN,
"unexpected %s while reading SMTP command from %s%s%s D=%s",
- sender_host_unknown ? "EOF" : "disconnection",
- tcp_in_fastopen && !tcp_in_fastopen_logged ? US"TFO " : US"",
+ f.sender_host_unknown ? "EOF" : "disconnection",
+ f.tcp_in_fastopen && !f.tcp_in_fastopen_logged ? US"TFO " : US"",
host_and_ident(FALSE), smtp_read_error,
string_timesince(&smtp_connection_start)
);
else
log_write(L_smtp_connection, LOG_MAIN, "%s %slost%s D=%s",
smtp_get_connection_info(),
- tcp_in_fastopen && !tcp_in_fastopen_logged ? US"TFO " : US"",
+ f.tcp_in_fastopen && !f.tcp_in_fastopen_logged ? US"TFO " : US"",
smtp_read_error,
string_timesince(&smtp_connection_start)
);
log_write(0, LOG_MAIN|LOG_REJECT, "SMTP protocol synchronization error "
"(next input sent too soon: pipelining was%s advertised): "
"rejected \"%s\" %s next input=\"%s\"",
- smtp_in_pipelining_advertised ? "" : " not",
+ f.smtp_in_pipelining_advertised ? "" : " not",
smtp_cmd_buffer, host_and_ident(TRUE),
string_printing(smtp_inptr));
smtp_notquit_exit(US"synchronization-error", US"554",
if (!(expint = expand_string(istring)))
{
- if (expand_string_forcedfail) return TRUE;
+ if (f.expand_string_forcedfail) return TRUE;
addr->transport_return = PANIC;
addr->message = string_sprintf("failed to expand \"interface\" "
"option for %s: %s", msg, expand_string_message);
if (errno == ENOENT)
{
if (i == 0) continue;
- if (!queue_running)
+ if (!f.queue_running)
log_write(0, LOG_MAIN, "Spool%s%s file %s-D not found",
*queue_name ? US" Q=" : US"",
*queue_name ? queue_name : US"",
acl_var_c = acl_var_m = NULL;
authenticated_id = NULL;
authenticated_sender = NULL;
-allow_unqualified_recipient = FALSE;
-allow_unqualified_sender = FALSE;
+f.allow_unqualified_recipient = FALSE;
+f.allow_unqualified_sender = FALSE;
body_linecount = 0;
body_zerocount = 0;
-deliver_firsttime = FALSE;
-deliver_freeze = FALSE;
+f.deliver_firsttime = FALSE;
+f.deliver_freeze = FALSE;
deliver_frozen_at = 0;
-deliver_manual_thaw = FALSE;
-/* dont_deliver must NOT be reset */
+f.deliver_manual_thaw = FALSE;
+/* f.dont_deliver must NOT be reset */
header_list = header_last = NULL;
host_lookup_deferred = FALSE;
host_lookup_failed = FALSE;
interface_address = NULL;
interface_port = 0;
-local_error_message = FALSE;
+f.local_error_message = FALSE;
#ifdef HAVE_LOCAL_SCAN
local_scan_data = NULL;
#endif
sender_host_port = 0;
sender_host_authenticated = NULL;
sender_ident = NULL;
-sender_local = FALSE;
-sender_set_untrusted = FALSE;
+f.sender_local = FALSE;
+f.sender_set_untrusted = FALSE;
smtp_active_hostname = primary_hostname;
#ifndef COMPILE_UTILITY
-spool_file_wireformat = FALSE;
+f.spool_file_wireformat = FALSE;
#endif
tree_nonrecipients = NULL;
#ifndef DISABLE_DKIM
dkim_signers = NULL;
-dkim_disable_verify = FALSE;
+f.dkim_disable_verify = FALSE;
dkim_collect_input = 0;
#endif
int
spool_read_header(uschar *name, BOOL read_headers, BOOL subdir_set)
{
-FILE *f = NULL;
+FILE * fp = NULL;
int n;
int rcount = 0;
long int uid, gid;
if (!subdir_set)
message_subdir[0] = split_spool_directory == (n == 0) ? name[5] : 0;
- if ((f = Ufopen(spool_fname(US"input", message_subdir, name, US""), "rb")))
+ if ((fp = Ufopen(spool_fname(US"input", message_subdir, name, US""), "rb")))
break;
if (n != 0 || subdir_set || errno != ENOENT)
return spool_read_notopen;
/* The first line of a spool file contains the message id followed by -H (i.e.
the file name), in order to make the file self-identifying. */
-if (Ufgets(big_buffer, big_buffer_size, f) == NULL) goto SPOOL_READ_ERROR;
+if (Ufgets(big_buffer, big_buffer_size, fp) == NULL) goto SPOOL_READ_ERROR;
if (Ustrlen(big_buffer) != MESSAGE_ID_LENGTH + 3 ||
Ustrncmp(big_buffer, name, MESSAGE_ID_LENGTH + 2) != 0)
goto SPOOL_FORMAT_ERROR;
sender, enclosed in <>. The third contains the time the message was received,
and the number of warning messages for delivery delays that have been sent. */
-if (Ufgets(big_buffer, big_buffer_size, f) == NULL) goto SPOOL_READ_ERROR;
+if (Ufgets(big_buffer, big_buffer_size, fp) == NULL) goto SPOOL_READ_ERROR;
p = big_buffer + Ustrlen(big_buffer);
while (p > big_buffer && isspace(p[-1])) p--;
originator_gid = (gid_t)gid;
/* envelope from */
-if (Ufgets(big_buffer, big_buffer_size, f) == NULL) goto SPOOL_READ_ERROR;
+if (Ufgets(big_buffer, big_buffer_size, fp) == NULL) goto SPOOL_READ_ERROR;
n = Ustrlen(big_buffer);
if (n < 3 || big_buffer[0] != '<' || big_buffer[n-2] != '>')
goto SPOOL_FORMAT_ERROR;
sender_address[n-3] = 0;
/* time */
-if (Ufgets(big_buffer, big_buffer_size, f) == NULL) goto SPOOL_READ_ERROR;
+if (Ufgets(big_buffer, big_buffer_size, fp) == NULL) goto SPOOL_READ_ERROR;
if (sscanf(CS big_buffer, TIME_T_FMT " %d", &received_time.tv_sec, &warning_count) != 2)
goto SPOOL_FORMAT_ERROR;
received_time.tv_usec = 0;
for (;;)
{
int len;
- if (Ufgets(big_buffer, big_buffer_size, f) == NULL) goto SPOOL_READ_ERROR;
+ if (Ufgets(big_buffer, big_buffer_size, fp) == NULL) goto SPOOL_READ_ERROR;
if (big_buffer[0] != '-') break;
while ( (len = Ustrlen(big_buffer)) == big_buffer_size-1
&& big_buffer[len-1] != '\n'
buf = store_get_perm(big_buffer_size *= 2);
memcpy(buf, big_buffer, --len);
big_buffer = buf;
- if (Ufgets(big_buffer+len, big_buffer_size-len, f) == NULL)
+ if (Ufgets(big_buffer+len, big_buffer_size-len, fp) == NULL)
goto SPOOL_READ_ERROR;
}
big_buffer[len-1] = 0;
if (sscanf(CS endptr, " %d", &count) != 1) goto SPOOL_FORMAT_ERROR;
node = acl_var_create(name);
node->data.ptr = store_get(count + 1);
- if (fread(node->data.ptr, 1, count+1, f) < count) goto SPOOL_READ_ERROR;
+ if (fread(node->data.ptr, 1, count+1, fp) < count) goto SPOOL_READ_ERROR;
((uschar*)node->data.ptr)[count] = 0;
}
else if (Ustrcmp(p, "llow_unqualified_recipient") == 0)
- allow_unqualified_recipient = TRUE;
+ f.allow_unqualified_recipient = TRUE;
else if (Ustrcmp(p, "llow_unqualified_sender") == 0)
- allow_unqualified_sender = TRUE;
+ f.allow_unqualified_sender = TRUE;
else if (Ustrncmp(p, "uth_id", 6) == 0)
authenticated_id = string_copy(big_buffer + 9);
node->data.ptr = store_get(count + 1);
/* We sanity-checked the count, so disable the Coverity error */
/* coverity[tainted_data] */
- if (fread(node->data.ptr, 1, count+1, f) < count) goto SPOOL_READ_ERROR;
+ if (fread(node->data.ptr, 1, count+1, fp) < count) goto SPOOL_READ_ERROR;
(US node->data.ptr)[count] = '\0';
}
break;
case 'd':
if (Ustrcmp(p, "eliver_firsttime") == 0)
- deliver_firsttime = TRUE;
+ f.deliver_firsttime = TRUE;
/* Check if the dsn flags have been set in the header file */
else if (Ustrncmp(p, "sn_ret", 6) == 0)
dsn_ret= atoi(CS big_buffer + 8);
case 'f':
if (Ustrncmp(p, "rozen", 5) == 0)
{
- deliver_freeze = TRUE;
+ f.deliver_freeze = TRUE;
if (sscanf(CS big_buffer+7, TIME_T_FMT, &deliver_frozen_at) != 1)
goto SPOOL_READ_ERROR;
}
case 'l':
if (Ustrcmp(p, "ocal") == 0)
- sender_local = TRUE;
+ f.sender_local = TRUE;
else if (Ustrcmp(big_buffer, "-localerror") == 0)
- local_error_message = TRUE;
+ f.local_error_message = TRUE;
#ifdef HAVE_LOCAL_SCAN
else if (Ustrncmp(p, "ocal_scan ", 10) == 0)
local_scan_data = string_copy(big_buffer + 12);
break;
case 'm':
- if (Ustrcmp(p, "anual_thaw") == 0) deliver_manual_thaw = TRUE;
+ if (Ustrcmp(p, "anual_thaw") == 0) f.deliver_manual_thaw = TRUE;
else if (Ustrncmp(p, "ax_received_linelength", 22) == 0)
max_received_linelength = Uatoi(big_buffer + 24);
break;
case 'N':
- if (*p == 0) dont_deliver = TRUE; /* -N */
+ if (*p == 0) f.dont_deliver = TRUE; /* -N */
break;
case 'r':
case 's':
if (Ustrncmp(p, "ender_set_untrusted", 19) == 0)
- sender_set_untrusted = TRUE;
+ f.sender_set_untrusted = TRUE;
#ifdef WITH_CONTENT_SCAN
else if (Ustrncmp(p, "pam_bar ", 8) == 0)
spam_bar = string_copy(big_buffer + 10);
#endif
#ifndef COMPILE_UTILITY
else if (Ustrncmp(p, "pool_file_wireformat", 20) == 0)
- spool_file_wireformat = TRUE;
+ f.spool_file_wireformat = TRUE;
#endif
#if defined(SUPPORT_I18N) && !defined(COMPILE_UTILITY)
else if (Ustrncmp(p, "mtputf8", 7) == 0)
#ifndef COMPILE_UTILITY
DEBUG(D_deliver)
- debug_printf("sender_local=%d ident=%s\n", sender_local,
+ debug_printf("sender_local=%d ident=%s\n", f.sender_local,
(sender_ident == NULL)? US"unset" : sender_ident);
#endif /* COMPILE_UTILITY */
containing "XX", indicating no tree. */
if (Ustrncmp(big_buffer, "XX\n", 3) != 0 &&
- !read_nonrecipients_tree(&tree_nonrecipients, f, big_buffer, big_buffer_size))
+ !read_nonrecipients_tree(&tree_nonrecipients, fp, big_buffer, big_buffer_size))
goto SPOOL_FORMAT_ERROR;
#ifndef COMPILE_UTILITY
buffer. It contains the count of recipients which follow on separate lines.
Apply an arbitrary sanity check.*/
-if (Ufgets(big_buffer, big_buffer_size, f) == NULL) goto SPOOL_READ_ERROR;
+if (Ufgets(big_buffer, big_buffer_size, fp) == NULL) goto SPOOL_READ_ERROR;
if (sscanf(CS big_buffer, "%d", &rcount) != 1 || rcount > 16384)
goto SPOOL_FORMAT_ERROR;
uschar *errors_to = NULL;
uschar *p;
- if (Ufgets(big_buffer, big_buffer_size, f) == NULL) goto SPOOL_READ_ERROR;
+ if (Ufgets(big_buffer, big_buffer_size, fp) == NULL) goto SPOOL_READ_ERROR;
nn = Ustrlen(big_buffer);
if (nn < 2) goto SPOOL_FORMAT_ERROR;
list if requested to do so. */
inheader = TRUE;
-if (Ufgets(big_buffer, big_buffer_size, f) == NULL) goto SPOOL_READ_ERROR;
+if (Ufgets(big_buffer, big_buffer_size, fp) == NULL) goto SPOOL_READ_ERROR;
if (big_buffer[0] != '\n') goto SPOOL_FORMAT_ERROR;
-while ((n = fgetc(f)) != EOF)
+while ((n = fgetc(fp)) != EOF)
{
header_line *h;
uschar flag[4];
int i;
if (!isdigit(n)) goto SPOOL_FORMAT_ERROR;
- if(ungetc(n, f) == EOF || fscanf(f, "%d%c ", &n, flag) == EOF)
+ if(ungetc(n, fp) == EOF || fscanf(fp, "%d%c ", &n, flag) == EOF)
goto SPOOL_READ_ERROR;
if (flag[0] != '*') message_size += n; /* Omit non-transmitted headers */
for (i = 0; i < n; i++)
{
- int c = fgetc(f);
+ int c = fgetc(fp);
if (c == 0 || c == EOF) goto SPOOL_FORMAT_ERROR;
if (c == '\n' && h->type != htype_old) message_linecount++;
h->text[i] = c;
else for (i = 0; i < n; i++)
{
- int c = fgetc(f);
+ int c = fgetc(fp);
if (c == 0 || c == EOF) goto SPOOL_FORMAT_ERROR;
}
}
message_linecount += body_linecount;
-fclose(f);
+fclose(fp);
return spool_read_OK;
DEBUG(D_any) debug_printf("Error while reading spool file %s\n", name);
#endif /* COMPILE_UTILITY */
- fclose(f);
+ fclose(fp);
errno = n;
return inheader? spool_read_hdrerror : spool_read_enverror;
}
DEBUG(D_any) debug_printf("Format error in spool file %s\n", name);
#endif /* COMPILE_UTILITY */
-fclose(f);
+fclose(fp);
errno = ERRNO_SPOOLFORMAT;
return inheader? spool_read_hdrerror : spool_read_enverror;
}
{
uschar * s;
- if (!spool_file_wireformat || source_file_override)
+ if (!f.spool_file_wireformat || source_file_override)
j = fread(buffer, 1, sizeof(buffer), l_data_file);
else /* needs CRLF -> NL */
if ((s = US fgets(CS buffer, sizeof(buffer), l_data_file)))
spam_ok = 0;
malware_ok = 0;
-if (spool_mbox_ok && !no_mbox_unspool)
+if (spool_mbox_ok && !f.no_mbox_unspool)
{
uschar *mbox_path;
uschar *file_path;
int fd;
int i;
int size_correction;
-FILE *f;
+FILE * fp;
header_line *h;
struct stat statbuf;
uschar * tname;
if ((fd = spool_open_temp(tname)) < 0)
return spool_write_error(where, errmsg, US"open", NULL, NULL);
-f = fdopen(fd, "wb");
+fp = fdopen(fd, "wb");
DEBUG(D_receive|D_deliver) debug_printf("Writing spool header file: %s\n", tname);
/* We now have an open file to which the header data is to be written. Start
address is enclosed in <> because it might be the null address. Then write the
received time and the number of warning messages that have been sent. */
-fprintf(f, "%s-H\n", message_id);
-fprintf(f, "%.63s %ld %ld\n", originator_login, (long int)originator_uid,
+fprintf(fp, "%s-H\n", message_id);
+fprintf(fp, "%.63s %ld %ld\n", originator_login, (long int)originator_uid,
(long int)originator_gid);
-fprintf(f, "<%s>\n", sender_address);
-fprintf(f, "%d %d\n", (int)received_time.tv_sec, warning_count);
+fprintf(fp, "<%s>\n", sender_address);
+fprintf(fp, "%d %d\n", (int)received_time.tv_sec, warning_count);
-fprintf(f, "-received_time_usec .%06d\n", (int)received_time.tv_usec);
+fprintf(fp, "-received_time_usec .%06d\n", (int)received_time.tv_usec);
/* If there is information about a sending host, remember it. The HELO
data can be set for local SMTP as well as remote. */
if (sender_helo_name)
- fprintf(f, "-helo_name %s\n", sender_helo_name);
+ fprintf(fp, "-helo_name %s\n", sender_helo_name);
if (sender_host_address)
{
- fprintf(f, "-host_address %s.%d\n", sender_host_address, sender_host_port);
+ fprintf(fp, "-host_address %s.%d\n", sender_host_address, sender_host_port);
if (sender_host_name)
- fprintf(f, "-host_name %s\n", sender_host_name);
+ fprintf(fp, "-host_name %s\n", sender_host_name);
if (sender_host_authenticated)
- fprintf(f, "-host_auth %s\n", sender_host_authenticated);
+ fprintf(fp, "-host_auth %s\n", sender_host_authenticated);
}
/* Also about the interface a message came in on */
if (interface_address)
- fprintf(f, "-interface_address %s.%d\n", interface_address, interface_port);
+ fprintf(fp, "-interface_address %s.%d\n", interface_address, interface_port);
if (smtp_active_hostname != primary_hostname)
- fprintf(f, "-active_hostname %s\n", smtp_active_hostname);
+ fprintf(fp, "-active_hostname %s\n", smtp_active_hostname);
/* Likewise for any ident information; for local messages this is
likely to be the same as originator_login, but will be different if
the originator was root, forcing a different ident. */
-if (sender_ident) fprintf(f, "-ident %s\n", sender_ident);
+if (sender_ident) fprintf(fp, "-ident %s\n", sender_ident);
/* Ditto for the received protocol */
if (received_protocol)
- fprintf(f, "-received_protocol %s\n", received_protocol);
+ fprintf(fp, "-received_protocol %s\n", received_protocol);
/* Preserve any ACL variables that are set. */
-tree_walk(acl_var_c, &acl_var_write, f);
-tree_walk(acl_var_m, &acl_var_write, f);
+tree_walk(acl_var_c, &acl_var_write, fp);
+tree_walk(acl_var_m, &acl_var_write, fp);
/* Now any other data that needs to be remembered. */
-if (spool_file_wireformat)
- fprintf(f, "-spool_file_wireformat\n");
+if (f.spool_file_wireformat)
+ fprintf(fp, "-spool_file_wireformat\n");
else
- fprintf(f, "-body_linecount %d\n", body_linecount);
-fprintf(f, "-max_received_linelength %d\n", max_received_linelength);
+ fprintf(fp, "-body_linecount %d\n", body_linecount);
+fprintf(fp, "-max_received_linelength %d\n", max_received_linelength);
-if (body_zerocount > 0) fprintf(f, "-body_zerocount %d\n", body_zerocount);
+if (body_zerocount > 0) fprintf(fp, "-body_zerocount %d\n", body_zerocount);
if (authenticated_id)
- fprintf(f, "-auth_id %s\n", authenticated_id);
+ fprintf(fp, "-auth_id %s\n", authenticated_id);
if (authenticated_sender)
- fprintf(f, "-auth_sender %s\n", authenticated_sender);
-
-if (allow_unqualified_recipient) fprintf(f, "-allow_unqualified_recipient\n");
-if (allow_unqualified_sender) fprintf(f, "-allow_unqualified_sender\n");
-if (deliver_firsttime) fprintf(f, "-deliver_firsttime\n");
-if (deliver_freeze) fprintf(f, "-frozen " TIME_T_FMT "\n", deliver_frozen_at);
-if (dont_deliver) fprintf(f, "-N\n");
-if (host_lookup_deferred) fprintf(f, "-host_lookup_deferred\n");
-if (host_lookup_failed) fprintf(f, "-host_lookup_failed\n");
-if (sender_local) fprintf(f, "-local\n");
-if (local_error_message) fprintf(f, "-localerror\n");
+ fprintf(fp, "-auth_sender %s\n", authenticated_sender);
+
+if (f.allow_unqualified_recipient) fprintf(fp, "-allow_unqualified_recipient\n");
+if (f.allow_unqualified_sender) fprintf(fp, "-allow_unqualified_sender\n");
+if (f.deliver_firsttime) fprintf(fp, "-deliver_firsttime\n");
+if (f.deliver_freeze) fprintf(fp, "-frozen " TIME_T_FMT "\n", deliver_frozen_at);
+if (f.dont_deliver) fprintf(fp, "-N\n");
+if (host_lookup_deferred) fprintf(fp, "-host_lookup_deferred\n");
+if (host_lookup_failed) fprintf(fp, "-host_lookup_failed\n");
+if (f.sender_local) fprintf(fp, "-local\n");
+if (f.local_error_message) fprintf(fp, "-localerror\n");
#ifdef HAVE_LOCAL_SCAN
-if (local_scan_data) fprintf(f, "-local_scan %s\n", local_scan_data);
+if (local_scan_data) fprintf(fp, "-local_scan %s\n", local_scan_data);
#endif
#ifdef WITH_CONTENT_SCAN
-if (spam_bar) fprintf(f,"-spam_bar %s\n", spam_bar);
-if (spam_score) fprintf(f,"-spam_score %s\n", spam_score);
-if (spam_score_int) fprintf(f,"-spam_score_int %s\n", spam_score_int);
+if (spam_bar) fprintf(fp,"-spam_bar %s\n", spam_bar);
+if (spam_score) fprintf(fp,"-spam_score %s\n", spam_score);
+if (spam_score_int) fprintf(fp,"-spam_score_int %s\n", spam_score_int);
#endif
-if (deliver_manual_thaw) fprintf(f, "-manual_thaw\n");
-if (sender_set_untrusted) fprintf(f, "-sender_set_untrusted\n");
+if (f.deliver_manual_thaw) fprintf(fp, "-manual_thaw\n");
+if (f.sender_set_untrusted) fprintf(fp, "-sender_set_untrusted\n");
#ifdef EXPERIMENTAL_BRIGHTMAIL
-if (bmi_verdicts) fprintf(f, "-bmi_verdicts %s\n", bmi_verdicts);
+if (bmi_verdicts) fprintf(fp, "-bmi_verdicts %s\n", bmi_verdicts);
#endif
#ifdef SUPPORT_TLS
-if (tls_in.certificate_verified) fprintf(f, "-tls_certificate_verified\n");
-if (tls_in.cipher) fprintf(f, "-tls_cipher %s\n", tls_in.cipher);
+if (tls_in.certificate_verified) fprintf(fp, "-tls_certificate_verified\n");
+if (tls_in.cipher) fprintf(fp, "-tls_cipher %s\n", tls_in.cipher);
if (tls_in.peercert)
{
(void) tls_export_cert(big_buffer, big_buffer_size, tls_in.peercert);
- fprintf(f, "-tls_peercert %s\n", CS big_buffer);
+ fprintf(fp, "-tls_peercert %s\n", CS big_buffer);
}
-if (tls_in.peerdn) fprintf(f, "-tls_peerdn %s\n", string_printing(tls_in.peerdn));
-if (tls_in.sni) fprintf(f, "-tls_sni %s\n", string_printing(tls_in.sni));
+if (tls_in.peerdn) fprintf(fp, "-tls_peerdn %s\n", string_printing(tls_in.peerdn));
+if (tls_in.sni) fprintf(fp, "-tls_sni %s\n", string_printing(tls_in.sni));
if (tls_in.ourcert)
{
(void) tls_export_cert(big_buffer, big_buffer_size, tls_in.ourcert);
- fprintf(f, "-tls_ourcert %s\n", CS big_buffer);
+ fprintf(fp, "-tls_ourcert %s\n", CS big_buffer);
}
-if (tls_in.ocsp) fprintf(f, "-tls_ocsp %d\n", tls_in.ocsp);
+if (tls_in.ocsp) fprintf(fp, "-tls_ocsp %d\n", tls_in.ocsp);
# ifdef EXPERIMENTAL_REQUIRETLS
-if (tls_requiretls) fprintf(f, "-tls_requiretls 0x%x\n", tls_requiretls);
+if (tls_requiretls) fprintf(fp, "-tls_requiretls 0x%x\n", tls_requiretls);
# endif
#endif
#ifdef SUPPORT_I18N
if (message_smtputf8)
{
- fprintf(f, "-smtputf8\n");
+ fprintf(fp, "-smtputf8\n");
if (message_utf8_downconvert)
- fprintf(f, "-utf8_%sdowncvt\n", message_utf8_downconvert < 0 ? "opt" : "");
+ fprintf(fp, "-utf8_%sdowncvt\n", message_utf8_downconvert < 0 ? "opt" : "");
}
#endif
/* Write the dsn flags to the spool header file */
DEBUG(D_deliver) debug_printf("DSN: Write SPOOL :-dsn_envid %s\n", dsn_envid);
-if (dsn_envid) fprintf(f, "-dsn_envid %s\n", dsn_envid);
+if (dsn_envid) fprintf(fp, "-dsn_envid %s\n", dsn_envid);
DEBUG(D_deliver) debug_printf("DSN: Write SPOOL :-dsn_ret %d\n", dsn_ret);
-if (dsn_ret) fprintf(f, "-dsn_ret %d\n", dsn_ret);
+if (dsn_ret) fprintf(fp, "-dsn_ret %d\n", dsn_ret);
/* To complete the envelope, write out the tree of non-recipients, followed by
the list of recipients. These won't be disjoint the first time, when no
checking has been done. If a recipient is a "one-time" alias, it is followed by
a space and its parent address number (pno). */
-tree_write(tree_nonrecipients, f);
-fprintf(f, "%d\n", recipients_count);
+tree_write(tree_nonrecipients, fp);
+fprintf(fp, "%d\n", recipients_count);
for (i = 0; i < recipients_count; i++)
{
recipient_item *r = recipients_list + i;
DEBUG(D_deliver) debug_printf("DSN: Flags :%d\n", r->dsn_flags);
if (r->pno < 0 && r->errors_to == NULL && r->dsn_flags == 0)
- fprintf(f, "%s\n", r->address);
+ fprintf(fp, "%s\n", r->address);
else
{
uschar * errors_to = r->errors_to ? r->errors_to : US"";
adding new values upfront and add flag 0x02 */
uschar * orcpt = r->orcpt ? r->orcpt : US"";
- fprintf(f, "%s %s %d,%d %s %d,%d#3\n", r->address, orcpt, Ustrlen(orcpt),
+ fprintf(fp, "%s %s %d,%d %s %d,%d#3\n", r->address, orcpt, Ustrlen(orcpt),
r->dsn_flags, errors_to, Ustrlen(errors_to), r->pno);
}
/* Put a blank line before the headers */
-fprintf(f, "\n");
+fprintf(fp, "\n");
/* Save the size of the file so far so we can subtract it from the final length
to get the actual size of the headers. */
-fflush(f);
+fflush(fp);
if (fstat(fd, &statbuf))
- return spool_write_error(where, errmsg, US"fstat", tname, f);
+ return spool_write_error(where, errmsg, US"fstat", tname, fp);
size_correction = statbuf.st_size;
/* Finally, write out the message's headers. To make it easier to read them
for (h = header_list; h; h = h->next)
{
- fprintf(f, "%03d%c %s", h->slen, h->type, h->text);
+ fprintf(fp, "%03d%c %s", h->slen, h->type, h->text);
size_correction += 5;
if (h->type == '*') size_correction += h->slen;
}
/* Flush and check for any errors while writing */
-if (fflush(f) != 0 || ferror(f))
- return spool_write_error(where, errmsg, US"write", tname, f);
+if (fflush(fp) != 0 || ferror(fp))
+ return spool_write_error(where, errmsg, US"write", tname, fp);
/* Force the file's contents to be written to disk. Note that fflush()
just pushes it out of C, and fclose() doesn't guarantee to do the write
either. That's just the way Unix works... */
-if (EXIMfsync(fileno(f)) < 0)
- return spool_write_error(where, errmsg, US"sync", tname, f);
+if (EXIMfsync(fileno(fp)) < 0)
+ return spool_write_error(where, errmsg, US"sync", tname, fp);
/* Get the size of the file, and close it. */
if (fstat(fd, &statbuf) != 0)
return spool_write_error(where, errmsg, US"fstat", tname, NULL);
-if (fclose(f) != 0)
+if (fclose(fp) != 0)
return spool_write_error(where, errmsg, US"close", tname, NULL);
/* Rename the file to its correct name, thereby replacing any previous
#else
DEBUG(D_memory)
{
- if (running_in_test_harness)
+ if (f.running_in_test_harness)
debug_printf("---%d Get %5d\n", store_pool, size);
else
debug_printf("---%d Get %6p %5d %-14s %4d\n", store_pool,
#else
DEBUG(D_memory)
{
- if (running_in_test_harness)
+ if (f.running_in_test_harness)
debug_printf("---%d Ext %5d\n", store_pool, newsize);
else
debug_printf("---%d Ext %6p %5d %-14s %4d\n", store_pool, ptr, newsize,
if (debug_store)
{
assert_no_variables(ptr, newlength, filename, linenumber);
- if (running_in_test_harness)
+ if (f.running_in_test_harness)
{
(void) VALGRIND_MAKE_MEM_DEFINED(ptr, newlength);
memset(ptr, 0xF0, newlength);
#else
DEBUG(D_memory)
{
- if (running_in_test_harness)
+ if (f.running_in_test_harness)
debug_printf("---%d Rst ** %d\n", store_pool, pool_malloc);
else
debug_printf("---%d Rst %6p ** %-14s %4d %d\n", store_pool, ptr,
linenumber = linenumber;
#else
DEBUG(D_memory)
- if (running_in_test_harness)
+ if (f.running_in_test_harness)
debug_printf("-Release %d\n", pool_malloc);
else
debug_printf("-Release %6p %-20s %4d %d\n", (void *)bb, filename,
linenumber, pool_malloc);
- if (running_in_test_harness)
+ if (f.running_in_test_harness)
memset(bb, 0xF0, bb->length+ALIGNED_SIZEOF_STOREBLOCK);
#endif /* COMPILE_UTILITY */
/* If running in test harness, spend time making sure all the new store
is not filled with zeros so as to catch problems. */
-if (running_in_test_harness)
+if (f.running_in_test_harness)
{
memset(yield, 0xF0, (size_t)size);
DEBUG(D_memory) debug_printf("--Malloc %5d %d %d\n", size, pool_malloc,
#else
DEBUG(D_memory)
{
- if (running_in_test_harness)
+ if (f.running_in_test_harness)
debug_printf("----Free\n");
else
debug_printf("----Free %6p %-20s %4d\n", block, filename, linenumber);
return;
bad:
- if (running_in_test_harness)
+ if (f.running_in_test_harness)
{
extern char ** environ;
uschar ** p;
if (!s)
*result = NULL;
else if ( !(*result = expand_string(US s)) /* need to clean up const more */
- && !expand_string_forcedfail
+ && !f.expand_string_forcedfail
)
{
*errstr = US"Internal error";
return string_sprintf("%u", (unsigned)t);
cp = store_get(len);
-if (timestamps_utc)
+if (f.timestamps_utc)
{
uschar * tz = to_tz(US"GMT0");
len = strftime(CS cp, len, "%b %e %T %Y %Z", gmtime(&t));
else
{
- if (!timestamps_utc) /* decoded string in local TZ */
+ if (!f.timestamps_utc) /* decoded string in local TZ */
{ /* shift to local TZ */
restore_tz(tz);
mod_tz = FALSE;
/* Convert to local time or UTC */
-t = timestamps_utc ? gmtime(&now.tv_sec) : localtime(&now.tv_sec);
+t = f.timestamps_utc ? gmtime(&now.tv_sec) : localtime(&now.tv_sec);
switch(type)
{
struct tm local;
memcpy(&local, t, sizeof(struct tm));
- if (timestamps_utc)
+ if (f.timestamps_utc)
diff_hour = diff_min = 0;
else
{
if ( *ptr == '\r' && ptr[1] == '\n'
&& !(tctx->options & topt_use_crlf)
- && spool_file_wireformat
+ && f.spool_file_wireformat
)
ptr++;
/* Insert CR before NL if required */
- if (tctx->options & topt_use_crlf && !spool_file_wireformat)
+ if (tctx->options & topt_use_crlf && !f.spool_file_wireformat)
*chunk_ptr++ = '\r';
*chunk_ptr++ = '\n';
transport_newlines++;
int len;
if (i == 0)
- if (!(s = expand_string(s)) && !expand_string_forcedfail)
+ if (!(s = expand_string(s)) && !f.expand_string_forcedfail)
{
errno = ERRNO_CHHEADER_FAIL;
return FALSE;
}
}
}
- else if (!expand_string_forcedfail)
+ else if (!f.expand_string_forcedfail)
{ errno = ERRNO_CHHEADER_FAIL; return FALSE; }
}
if (!(tctx->options & topt_no_headers))
{
- BOOL save_wireformat = spool_file_wireformat;
- spool_file_wireformat = FALSE;
+ BOOL save_wireformat = f.spool_file_wireformat;
+ f.spool_file_wireformat = FALSE;
/* Add return-path: if requested. */
if (!transport_headers_send(tctx, &write_chunk))
{
bad:
- spool_file_wireformat = save_wireformat;
+ f.spool_file_wireformat = save_wireformat;
return FALSE;
}
- spool_file_wireformat = save_wireformat;
+ f.spool_file_wireformat = save_wireformat;
}
/* When doing RFC3030 CHUNKING output, work out how much data would be in a
if (size_limit > 0 && fsize > size_limit)
fsize = size_limit;
size = hsize + fsize;
- if (tctx->options & topt_use_crlf && !spool_file_wireformat)
+ if (tctx->options & topt_use_crlf && !f.spool_file_wireformat)
size += body_linecount; /* account for CRLF-expansion */
/* With topt_use_bdat we never do dot-stuffing; no need to
dkim signing, when we had CHUNKING input. */
#ifdef OS_SENDFILE
-if ( spool_file_wireformat
+if ( f.spool_file_wireformat
&& !(tctx->options & (topt_no_body | topt_end_dot))
&& !nl_check_length
&& tls_out.active.sock != tctx->u.fd
DEBUG(D_transport)
if (!(tctx->options & topt_no_body))
debug_printf("cannot use sendfile for body: %s\n",
- !spool_file_wireformat ? "spoolfile not wireformat"
+ !f.spool_file_wireformat ? "spoolfile not wireformat"
: tctx->options & topt_end_dot ? "terminating dot wanted"
: nl_check_length ? "dot- or From-stuffing wanted"
: "TLS output wanted");
/* Finished with the check string, and spool-format consideration */
nl_check_length = nl_escape_length = 0;
-spool_file_wireformat = FALSE;
+f.spool_file_wireformat = FALSE;
/* If requested, add a terminating "." line (SMTP output). */
transport_write_message(transport_ctx * tctx, int size_limit)
{
BOOL last_filter_was_NL = TRUE;
-BOOL save_spool_file_wireformat = spool_file_wireformat;
+BOOL save_spool_file_wireformat = f.spool_file_wireformat;
int rc, len, yield, fd_read, fd_write, save_errno;
int pfd[2] = {-1, -1};
pid_t filter_pid, write_pid;
-transport_filter_timed_out = FALSE;
+f.transport_filter_timed_out = FALSE;
/* If there is no filter command set up, call the internal function that does
the actual work, passing it the incoming fd, and return its result. */
/* When testing, let the subprocess get going */
-if (running_in_test_harness) millisleep(250);
+if (f.running_in_test_harness) millisleep(250);
DEBUG(D_transport)
debug_printf("process %d writing to transport filter\n", (int)write_pid);
variable is TRUE). The output should always be unix-format as we converted
any wireformat source on writing input to the filter. */
-spool_file_wireformat = FALSE;
+f.spool_file_wireformat = FALSE;
chunk_ptr = deliver_out_buffer;
for (;;)
if (sigalrm_seen)
{
errno = ETIMEDOUT;
- transport_filter_timed_out = TRUE;
+ f.transport_filter_timed_out = TRUE;
goto TIDY_UP;
}
sure. Also apply a paranoia timeout. */
TIDY_UP:
-spool_file_wireformat = save_spool_file_wireformat;
+f.spool_file_wireformat = save_spool_file_wireformat;
save_errno = errno;
(void)close(fd_read);
if (yield)
{
nl_check_length = nl_escape_length = 0;
- spool_file_wireformat = FALSE;
+ f.spool_file_wireformat = FALSE;
if ( tctx->options & topt_end_dot
&& ( last_filter_was_NL
? !write_chunk(tctx, US".\n", 2)
argv = CUSS child_exec_exim(CEE_RETURN_ARGV, TRUE, &i, FALSE, 0);
-if (smtp_authenticated) argv[i++] = US"-MCA";
+if (f.smtp_authenticated) argv[i++] = US"-MCA";
if (smtp_peer_options & OPTION_CHUNKING) argv[i++] = US"-MCK";
if (smtp_peer_options & OPTION_DSN) argv[i++] = US"-MCD";
if (smtp_peer_options & OPTION_PIPE) argv[i++] = US"-MCP";
DEBUG(D_transport) debug_printf("transport_pass_socket succeeded (final-pid %d)\n", pid);
_exit(EXIT_SUCCESS);
}
- if (running_in_test_harness) sleep(1);
+ if (f.running_in_test_harness) sleep(1);
transport_do_pass_socket(transport_name, hostname, hostaddress,
id, socket_fd);
else
{
const uschar *expanded_arg;
- enable_dollar_recipients = allow_dollar_recipients;
+ f.enable_dollar_recipients = allow_dollar_recipients;
expanded_arg = expand_cstring(argv[i]);
- enable_dollar_recipients = FALSE;
+ f.enable_dollar_recipients = FALSE;
if (expanded_arg == NULL)
{
{
*errmsg = string_sprintf("Expansion of \"%s\" in %s transport failed: "
"%s", q, tblock->name, expand_string_message);
- return search_find_defer ? DEFER : FAIL;
+ return f.search_find_defer ? DEFER : FAIL;
}
d = Ustrtod(s, &rest);
/* If the -N option is set, can't do any more. */
-if (dont_deliver)
+if (f.dont_deliver)
{
DEBUG(D_transport)
debug_printf("*** delivery by %s transport bypassed by -N option\n",
$message_size is accurately known. */
if (nametag != NULL && expand_string(nametag) == NULL &&
- !expand_string_forcedfail)
+ !f.expand_string_forcedfail)
{
addr->transport_return = PANIC;
addr->message = string_sprintf("Expansion of \"%s\" (maildir_tag "
uschar *s = expand_string(ob->mailstore_prefix);
if (s == NULL)
{
- if (!expand_string_forcedfail)
+ if (!f.expand_string_forcedfail)
{
addr->transport_return = PANIC;
addr->message = string_sprintf("Expansion of \"%s\" (mailstore "
uschar *s = expand_string(ob->mailstore_suffix);
if (s == NULL)
{
- if (!expand_string_forcedfail)
+ if (!f.expand_string_forcedfail)
{
addr->transport_return = PANIC;
addr->message = string_sprintf("Expansion of \"%s\" (mailstore "
}
else /* Want a repeatable time when in test harness */
{
- addr->more_errno = running_in_test_harness ? 10 :
+ addr->more_errno = f.running_in_test_harness ? 10 :
(int)time(NULL) - statbuf.st_mtime;
}
DEBUG(D_transport)
header_line *h;
time_t now = time(NULL);
time_t once_repeat_sec = 0;
-FILE *f;
+FILE *fp;
FILE *ff = NULL;
autoreply_transport_options_block *ob =
/* If the -N option is set, can't do any more. */
-if (dont_deliver)
+if (f.dont_deliver)
{
DEBUG(D_transport)
debug_printf("*** delivery by %s transport bypassed by -N option\n",
as the -t option is used. The "headers" stuff *must* be last in case there
are newlines in it which might, if placed earlier, screw up other headers. */
-f = fdopen(fd, "wb");
+fp = fdopen(fd, "wb");
-if (from) fprintf(f, "From: %s\n", from);
-if (reply_to) fprintf(f, "Reply-To: %s\n", reply_to);
-if (to) fprintf(f, "To: %s\n", to);
-if (cc) fprintf(f, "Cc: %s\n", cc);
-if (bcc) fprintf(f, "Bcc: %s\n", bcc);
-if (subject) fprintf(f, "Subject: %s\n", subject);
+if (from) fprintf(fp, "From: %s\n", from);
+if (reply_to) fprintf(fp, "Reply-To: %s\n", reply_to);
+if (to) fprintf(fp, "To: %s\n", to);
+if (cc) fprintf(fp, "Cc: %s\n", cc);
+if (bcc) fprintf(fp, "Bcc: %s\n", bcc);
+if (subject) fprintf(fp, "Subject: %s\n", subject);
/* Generate In-Reply-To from the message_id header; there should
always be one, but code defensively. */
{
message_id = Ustrchr(h->text, ':') + 1;
while (isspace(*message_id)) message_id++;
- fprintf(f, "In-Reply-To: %s", message_id);
+ fprintf(fp, "In-Reply-To: %s", message_id);
}
/* Generate a References header if there is at least one of Message-ID:,
if (h || message_id)
{
- fprintf(f, "References:");
+ fprintf(fp, "References:");
if (h)
{
uschar *s, *id, *error;
int i;
s = Ustrchr(h->text, ':') + 1;
- parse_allow_group = FALSE;
+ f.parse_allow_group = FALSE;
while (*s != 0 && (s = parse_message_id(s, &id, &error)) != NULL)
{
if (reference_count == nelem(referenced_ids))
}
else referenced_ids[reference_count++] = id;
}
- for (i = 0; i < reference_count; ++i) fprintf(f, " %s", referenced_ids[i]);
+ for (i = 0; i < reference_count; ++i) fprintf(fp, " %s", referenced_ids[i]);
}
/* The message id will have a newline on the end of it. */
- if (message_id) fprintf(f, " %s", message_id);
- else fprintf(f, "\n");
+ if (message_id) fprintf(fp, " %s", message_id);
+ else fprintf(fp, "\n");
}
/* Add an Auto-Submitted: header */
-fprintf(f, "Auto-Submitted: auto-replied\n");
+fprintf(fp, "Auto-Submitted: auto-replied\n");
/* Add any specially requested headers */
-if (headers) fprintf(f, "%s\n", headers);
-fprintf(f, "\n");
+if (headers) fprintf(fp, "%s\n", headers);
+fprintf(fp, "\n");
if (text)
{
- fprintf(f, "%s", CS text);
- if (text[Ustrlen(text)-1] != '\n') fprintf(f, "\n");
+ fprintf(fp, "%s", CS text);
+ if (text[Ustrlen(text)-1] != '\n') fprintf(fp, "\n");
}
if (ff)
debug_printf("error while expanding line from file:\n %s\n %s\n",
big_buffer, expand_string_message);
}
- fprintf(f, "%s", s ? CS s : CS big_buffer);
+ fprintf(fp, "%s", s ? CS s : CS big_buffer);
}
- else fprintf(f, "%s", CS big_buffer);
+ else fprintf(fp, "%s", CS big_buffer);
}
(void) fclose(ff);
}
:
US"------ This is a copy of the message, including all the headers.\n";
transport_ctx tctx = {
- .u = {.fd = fileno(f)},
+ .u = {.fd = fileno(fp)},
.tblock = tblock,
.addr = addr,
.check_string = NULL,
DELIVER_IN_BUFFER_SIZE;
if (fstat(deliver_datafile, &statbuf) == 0 && statbuf.st_size > max)
{
- fprintf(f, "\n%s"
+ fprintf(fp, "\n%s"
"------ The body of the message is " OFF_T_FMT " characters long; only the first\n"
"------ %d or so are included here.\n\n", rubric, statbuf.st_size,
(max/1000)*1000);
}
- else fprintf(f, "\n%s\n", rubric);
+ else fprintf(fp, "\n%s\n", rubric);
}
- else fprintf(f, "\n%s\n", rubric);
+ else fprintf(fp, "\n%s\n", rubric);
- fflush(f);
+ fflush(fp);
transport_count = 0;
transport_write_message(&tctx, bounce_return_size_limit);
}
/* End the message and wait for the child process to end; no timeout. */
-(void)fclose(f);
+(void)fclose(fp);
rc = child_close(pid, 0);
/* Update the "sent to" log whatever the yield. This errs on the side of
return FALSE;
/* If the -N option is set, can't do any more. Presume all has gone well. */
- if (dont_deliver)
+ if (f.dont_deliver)
goto MINUS_N;
/* As this is a local transport, we are already running with the required
}
/* If the -N option is set, can't do any more. Presume all has gone well. */
- if (dont_deliver)
+ if (f.dont_deliver)
goto MINUS_N;
sockun.sun_family = AF_UNIX;
/* Allow $recipients in the expansion iff it comes from a system filter */
- enable_dollar_recipients = addr && addr->parent &&
+ f.enable_dollar_recipients = addr && addr->parent &&
Ustrcmp(addr->parent->address, "system-filter") == 0;
if (p != NULL && (
else
argv[2] = expand_string(cmd);
- enable_dollar_recipients = FALSE;
+ f.enable_dollar_recipients = FALSE;
if (!argv[2])
{
- addr->transport_return = search_find_defer ? DEFER : expand_fail;
+ addr->transport_return = f.search_find_defer ? DEFER : expand_fail;
addr->message = string_sprintf("Expansion of command \"%s\" "
"in %s transport failed: %s",
cmd, tname, expand_string_message);
if (addr->host_list != NULL)
envp[envcount++] = string_sprintf("HOST=%s", addr->host_list->name);
-if (timestamps_utc) envp[envcount++] = US"TZ=UTC";
+if (f.timestamps_utc) envp[envcount++] = US"TZ=UTC";
else if (timezone_string != NULL && timezone_string[0] != 0)
envp[envcount++] = string_sprintf("TZ=%s", timezone_string);
/* If the -N option is set, can't do any more. */
-if (dont_deliver)
+if (f.dont_deliver)
{
DEBUG(D_transport)
debug_printf("*** delivery by %s transport bypassed by -N option",
ignore all writing errors. (When in the test harness, we do do a short sleep so
any debugging output is likely to be in the same order.) */
-if (running_in_test_harness) millisleep(500);
+if (f.running_in_test_harness) millisleep(500);
DEBUG(D_transport) debug_printf("Writing message to pipe\n");
uschar *prefix = expand_string(ob->message_prefix);
if (prefix == NULL)
{
- addr->transport_return = search_find_defer? DEFER : PANIC;
+ addr->transport_return = f.search_find_defer? DEFER : PANIC;
addr->message = string_sprintf("Expansion of \"%s\" (prefix for %s "
"transport) failed: %s", ob->message_prefix, tblock->name,
expand_string_message);
uschar *suffix = expand_string(ob->message_suffix);
if (!suffix)
{
- addr->transport_return = search_find_defer? DEFER : PANIC;
+ addr->transport_return = f.search_find_defer? DEFER : PANIC;
addr->message = string_sprintf("Expansion of \"%s\" (suffix for %s "
"transport) failed: %s", ob->message_suffix, tblock->name,
expand_string_message);
if (errno == ETIMEDOUT)
{
addr->message = string_sprintf("%stimeout while writing to pipe",
- transport_filter_timed_out? "transport filter " : "");
+ f.transport_filter_timed_out ? "transport filter " : "");
addr->transport_return = ob->timeout_defer? DEFER : FAIL;
timeout = 1;
}
This prevents the transport_filter timeout message from getting overwritten
by the exit error which is not the cause of the problem. */
- else if (transport_filter_timed_out)
+ else if (f.transport_filter_timed_out)
{
killpg(pid, SIGKILL);
kill(outpid, SIGKILL);
}
can_link = (dstatbuf.st_dev == sstatbuf.st_dev);
-if (dont_deliver)
+if (f.dont_deliver)
{
DEBUG(D_transport)
debug_printf("*** delivery by %s transport bypassed by -N option\n",
int require_auth;
uschar *fail_reason = US"server did not advertise AUTH support";
-smtp_authenticated = FALSE;
+f.smtp_authenticated = FALSE;
client_authenticator = client_authenticated_id = client_authenticated_sender = NULL;
require_auth = verify_check_given_host(&ob->hosts_require_auth, host);
If one is found, attempt to authenticate by calling its client function.
*/
- for (au = auths; !smtp_authenticated && au; au = au->next)
+ for (au = auths; !f.smtp_authenticated && au; au = au->next)
{
uschar *p = names;
if (!au->client ||
switch(rc)
{
case OK:
- smtp_authenticated = TRUE; /* stops the outer loop */
+ f.smtp_authenticated = TRUE; /* stops the outer loop */
client_authenticator = au->name;
if (au->set_client_id != NULL)
client_authenticated_id = expand_string(au->set_client_id);
/* If we haven't authenticated, but are required to, give up. */
-if (require_auth == OK && !smtp_authenticated)
+if (require_auth == OK && !f.smtp_authenticated)
{
set_errno_nohost(addrlist, ERRNO_AUTHFAIL,
string_sprintf("authentication required but %s", fail_reason), DEFER,
addrlist chain of potential addresses to deliver
ob transport options
-Globals smtp_authenticated
+Globals f.smtp_authenticated
client_authenticated_sender
Return True on error, otherwise buffer has (possibly empty) terminated string
*/
uschar *local_authenticated_sender = authenticated_sender;
#ifdef notdef
- debug_printf("smtp_mail_auth_str: as<%s> os<%s> SA<%s>\n", authenticated_sender, ob->authenticated_sender, smtp_authenticated?"Y":"N");
+ debug_printf("smtp_mail_auth_str: as<%s> os<%s> SA<%s>\n", authenticated_sender, ob->authenticated_sender, f.smtp_authenticated?"Y":"N");
#endif
if (ob->authenticated_sender != NULL)
uschar *new = expand_string(ob->authenticated_sender);
if (new == NULL)
{
- if (!expand_string_forcedfail)
+ if (!f.expand_string_forcedfail)
{
uschar *message = string_sprintf("failed to expand "
"authenticated_sender: %s", expand_string_message);
/* Add the authenticated sender address if present */
-if ((smtp_authenticated || ob->authenticated_sender_force) &&
+if ((f.smtp_authenticated || ob->authenticated_sender_force) &&
local_authenticated_sender != NULL)
{
string_format(buffer, bufsize, " AUTH=%s",
BOOL no_flush;
uschar * rcpt_addr;
- if (tcp_out_fastopen && !tcp_out_fastopen_logged)
+ if (tcp_out_fastopen && !f.tcp_out_fastopen_logged)
{
setflag(addr, af_tcp_fastopen_conn);
if (tcp_out_fastopen > 1) setflag(addr, af_tcp_fastopen);
}
} /* Loop for next address */
-tcp_out_fastopen_logged = TRUE;
+f.tcp_out_fastopen_logged = TRUE;
sx->next_addr = addr;
return 0;
}
_exit(rc < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
}
-if (running_in_test_harness) millisleep(100); /* let parent debug out */
+if (f.running_in_test_harness) millisleep(100); /* let parent debug out */
set_process_info("proxying TLS connection for continued transport");
FD_ZERO(&rfds);
FD_SET(tls_out.active.sock, &rfds);
}
done:
- if (running_in_test_harness) millisleep(100); /* let logging complete */
+ if (f.running_in_test_harness) millisleep(100); /* let logging complete */
exim_exit(0, US"TLS proxy");
}
#endif
{
if (!(sx.ob->dkim.arc_signspec = s = expand_string(s)))
{
- if (!expand_string_forcedfail)
+ if (!f.expand_string_forcedfail)
{
message = US"failed to expand arc_sign";
sx.ok = FALSE;
DEBUG(D_transport)
debug_printf("ok=%d send_quit=%d send_rset=%d continue_more=%d "
"yield=%d first_address is %sNULL\n", sx.ok, sx.send_quit,
- sx.send_rset, continue_more, yield, sx.first_addr ? "not " : "");
+ sx.send_rset, f.continue_more, yield, sx.first_addr ? "not " : "");
if (sx.completed_addr && sx.ok && sx.send_quit)
{
t_compare.current_sender_address = sender_address;
if ( sx.first_addr != NULL
- || continue_more
+ || f.continue_more
|| (
#ifdef SUPPORT_TLS
( tls_out.active.sock < 0 && !continue_proxy_cipher
#ifdef SUPPORT_TLS
if (tls_out.active.sock >= 0)
- if ( continue_more
+ if ( f.continue_more
|| verify_check_given_host(&sx.ob->hosts_noproxy_tls, host) == OK)
{
/* Before passing the socket on, or returning to caller with it still
&& smtp_read_response(&sx.inblock, sx.buffer, sizeof(sx.buffer),
'2', sx.ob->command_timeout);
- if (sx.ok && continue_more)
+ if (sx.ok && f.continue_more)
return yield; /* More addresses for another run */
}
else
}
else
#endif
- if (continue_more)
+ if (f.continue_more)
return yield; /* More addresses for another run */
/* If the socket is successfully passed, we mustn't send QUIT (or
int pid = fork();
if (pid == 0) /* child; fork again to disconnect totally */
{
- if (running_in_test_harness) millisleep(100); /* let parent debug out */
+ if (f.running_in_test_harness) millisleep(100); /* let parent debug out */
/* does not return */
smtp_proxy_tls(sx.cctx.tls_ctx, sx.buffer, sizeof(sx.buffer), pfd,
sx.ob->command_timeout);
{
addrlist->message = string_sprintf("failed to expand list of hosts "
"\"%s\" in %s transport: %s", s, tblock->name, expand_string_message);
- addrlist->transport_return = search_find_defer ? DEFER : PANIC;
+ addrlist->transport_return = f.search_find_defer ? DEFER : PANIC;
return FALSE; /* Only top address has status */
}
DEBUG(D_transport) debug_printf("expanded list of hosts \"%s\" to "
were not in it. We don't want to hold up all SMTP deliveries! Except when
doing a two-stage queue run, don't do this if forcing. */
- if ((!deliver_force || queue_2stage) && (queue_smtp ||
+ if ((!f.deliver_force || f.queue_2stage) && (f.queue_smtp ||
match_isinlist(addrlist->domain,
(const uschar **)&queue_smtp_domains, 0,
&domainlist_anchor, NULL, MCL_DOMAIN, TRUE, NULL) == OK))
/* This is not for real; don't do the delivery. If there are
any remaining hosts, list them. */
- if (dont_deliver)
+ if (f.dont_deliver)
{
host_item *host2;
set_errno_nohost(addrlist, 0, NULL, OK, FALSE);
setflag(addr, af_retry_skipped);
}
- if (queue_smtp) /* no deliveries attempted */
+ if (f.queue_smtp) /* no deliveries attempted */
{
addr->transport_return = DEFER;
addr->basic_errno = 0;
and cause the client to time out. So in this case we forgo the PIPELINING
optimization. */
- if (smtp_out && !disable_callout_flush) mac_smtp_fflush();
+ if (smtp_out && !f.disable_callout_flush) mac_smtp_fflush();
clearflag(addr, af_verify_pmfail); /* postmaster callout flag */
clearflag(addr, af_verify_nsfail); /* null sender callout flag */
*/
int
-verify_address(address_item *vaddr, FILE *f, int options, int callout,
- int callout_overall, int callout_connect, uschar *se_mailfrom,
+verify_address(address_item * vaddr, FILE * fp, int options, int callout,
+ int callout_overall, int callout_connect, uschar * se_mailfrom,
uschar *pm_mailfrom, BOOL *routed)
{
BOOL allok = TRUE;
-BOOL full_info = (f == NULL)? FALSE : (debug_selector != 0);
+BOOL full_info = fp ? debug_selector != 0 : FALSE;
BOOL expn = (options & vopt_expn) != 0;
BOOL success_on_redirect = (options & vopt_success_on_redirect) != 0;
int i;
int yield = OK;
int verify_type = expn? v_expn :
- address_test_mode? v_none :
+ f.address_test_mode? v_none :
options & vopt_is_recipient? v_recipient : v_sender;
address_item *addr_list;
address_item *addr_new = NULL;
{
if (!(options & vopt_qualify))
{
- if (f)
- respond_printf(f, "%sA domain is required for \"%s\"%s\n",
+ if (fp)
+ respond_printf(fp, "%sA domain is required for \"%s\"%s\n",
ko_prefix, address, cr);
*failure_ptr = US"qualify";
return FAIL;
DEBUG(D_verify)
{
debug_printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
- debug_printf("%s %s\n", address_test_mode? "Testing" : "Verifying", address);
+ debug_printf("%s %s\n", f.address_test_mode? "Testing" : "Verifying", address);
}
/* Rewrite and report on it. Clear the domain and local part caches - these
{
for (i = 0; i < (MAX_NAMED_LIST * 2)/32; i++) vaddr->localpart_cache[i] = 0;
for (i = 0; i < (MAX_NAMED_LIST * 2)/32; i++) vaddr->domain_cache[i] = 0;
- if (f && !expn) fprintf(f, "Address rewritten as: %s\n", address);
+ if (fp && !expn) fprintf(fp, "Address rewritten as: %s\n", address);
}
}
if (testflag(addr, af_pfr))
{
allok = FALSE;
- if (f)
+ if (fp)
{
BOOL allow;
if (addr->address[0] == '>')
{
allow = testflag(addr, af_allow_reply);
- fprintf(f, "%s -> mail %s", addr->parent->address, addr->address + 1);
+ fprintf(fp, "%s -> mail %s", addr->parent->address, addr->address + 1);
}
else
{
allow = addr->address[0] == '|'
? testflag(addr, af_allow_pipe) : testflag(addr, af_allow_file);
- fprintf(f, "%s -> %s", addr->parent->address, addr->address);
+ fprintf(fp, "%s -> %s", addr->parent->address, addr->address);
}
if (addr->basic_errno == ERRNO_BADTRANSPORT)
- fprintf(f, "\n*** Error in setting up pipe, file, or autoreply:\n"
+ fprintf(fp, "\n*** Error in setting up pipe, file, or autoreply:\n"
"%s\n", addr->message);
else if (allow)
- fprintf(f, "\n transport = %s\n", addr->transport->name);
+ fprintf(fp, "\n transport = %s\n", addr->transport->name);
else
- fprintf(f, " *** forbidden ***\n");
+ fprintf(fp, " *** forbidden ***\n");
}
continue;
}
if (host_list)
{
HDEBUG(D_verify) debug_printf("Attempting full verification using callout\n");
- if (host_checking && !host_checking_callout)
+ if (host_checking && !f.host_checking_callout)
{
HDEBUG(D_verify)
debug_printf("... callout omitted by default when host testing\n"
if (rc == FAIL)
{
allok = FALSE;
- if (f)
+ if (fp)
{
address_item *p = addr->parent;
- respond_printf(f, "%s%s %s", ko_prefix,
+ respond_printf(fp, "%s%s %s", ko_prefix,
full_info ? addr->address : address,
- address_test_mode ? "is undeliverable" : "failed to verify");
- if (!expn && admin_user)
+ f.address_test_mode ? "is undeliverable" : "failed to verify");
+ if (!expn && f.admin_user)
{
if (addr->basic_errno > 0)
- respond_printf(f, ": %s", strerror(addr->basic_errno));
+ respond_printf(fp, ": %s", strerror(addr->basic_errno));
if (addr->message)
- respond_printf(f, ": %s", addr->message);
+ respond_printf(fp, ": %s", addr->message);
}
/* Show parents iff doing full info */
if (full_info) while (p)
{
- respond_printf(f, "%s\n <-- %s", cr, p->address);
+ respond_printf(fp, "%s\n <-- %s", cr, p->address);
p = p->parent;
}
- respond_printf(f, "%s\n", cr);
+ respond_printf(fp, "%s\n", cr);
}
cancel_cutthrough_connection(TRUE, US"routing hard fail");
else if (rc == DEFER)
{
allok = FALSE;
- if (f)
+ if (fp)
{
address_item *p = addr->parent;
- respond_printf(f, "%s%s cannot be resolved at this time", ko_prefix,
+ respond_printf(fp, "%s%s cannot be resolved at this time", ko_prefix,
full_info? addr->address : address);
- if (!expn && admin_user)
+ if (!expn && f.admin_user)
{
if (addr->basic_errno > 0)
- respond_printf(f, ": %s", strerror(addr->basic_errno));
+ respond_printf(fp, ": %s", strerror(addr->basic_errno));
if (addr->message)
- respond_printf(f, ": %s", addr->message);
+ respond_printf(fp, ": %s", addr->message);
else if (addr->basic_errno <= 0)
- respond_printf(f, ": unknown error");
+ respond_printf(fp, ": unknown error");
}
/* Show parents iff doing full info */
if (full_info) while (p)
{
- respond_printf(f, "%s\n <-- %s", cr, p->address);
+ respond_printf(fp, "%s\n <-- %s", cr, p->address);
p = p->parent;
}
- respond_printf(f, "%s\n", cr);
+ respond_printf(fp, "%s\n", cr);
}
cancel_cutthrough_connection(TRUE, US"routing soft fail");
if (!addr_new)
if (!addr_local && !addr_remote)
- respond_printf(f, "250 mail to <%s> is discarded\r\n", address);
+ respond_printf(fp, "250 mail to <%s> is discarded\r\n", address);
else
- respond_printf(f, "250 <%s>\r\n", address);
+ respond_printf(fp, "250 <%s>\r\n", address);
else do
{
address_item *addr2 = addr_new;
addr_new = addr2->next;
if (!addr_new) ok_prefix = US"250 ";
- respond_printf(f, "%s<%s>\r\n", ok_prefix, addr2->address);
+ respond_printf(fp, "%s<%s>\r\n", ok_prefix, addr2->address);
} while (addr_new);
yield = OK;
goto out;
) )
)
{
- if (f) fprintf(f, "%s %s\n",
- address, address_test_mode ? "is deliverable" : "verified");
+ if (fp) fprintf(fp, "%s %s\n",
+ address, f.address_test_mode ? "is deliverable" : "verified");
/* If we have carried on to verify a child address, we want the value
of $address_data to be that of the child */
} /* Loop for generated addresses */
/* Display the full results of the successful routing, including any generated
-addresses. Control gets here only when full_info is set, which requires f not
+addresses. Control gets here only when full_info is set, which requires fp not
to be NULL, and this occurs only when a top-level verify is called with the
debugging switch on.
if (allok && !addr_local && !addr_remote)
{
- fprintf(f, "mail to %s is discarded\n", address);
+ fprintf(fp, "mail to %s is discarded\n", address);
goto out;
}
addr_list = addr->next;
- fprintf(f, "%s", CS addr->address);
+ fprintf(fp, "%s", CS addr->address);
#ifdef EXPERIMENTAL_SRS
if(addr->prop.srs_sender)
- fprintf(f, " [srs = %s]", addr->prop.srs_sender);
+ fprintf(fp, " [srs = %s]", addr->prop.srs_sender);
#endif
/* If the address is a duplicate, show something about it. */
{
tree_node *tnode;
if ((tnode = tree_search(tree_duplicates, addr->unique)))
- fprintf(f, " [duplicate, would not be delivered]");
+ fprintf(fp, " [duplicate, would not be delivered]");
else tree_add_duplicate(addr->unique, addr);
}
/* Now show its parents */
for (p = addr->parent; p; p = p->parent)
- fprintf(f, "\n <-- %s", p->address);
- fprintf(f, "\n ");
+ fprintf(fp, "\n <-- %s", p->address);
+ fprintf(fp, "\n ");
/* Show router, and transport */
- fprintf(f, "router = %s, transport = %s\n",
+ fprintf(fp, "router = %s, transport = %s\n",
addr->router->name, tp ? tp->name : US"unset");
/* Show any hosts that are set up by a router unless the transport
}
for (h = addr->host_list; h; h = h->next)
{
- fprintf(f, " host %-*s ", maxlen, h->name);
+ fprintf(fp, " host %-*s ", maxlen, h->name);
if (h->address)
- fprintf(f, "[%s%-*c", h->address, maxaddlen+1 - Ustrlen(h->address), ']');
+ fprintf(fp, "[%s%-*c", h->address, maxaddlen+1 - Ustrlen(h->address), ']');
else if (tp->info->local)
- fprintf(f, " %-*s ", maxaddlen, ""); /* Omit [unknown] for local */
+ fprintf(fp, " %-*s ", maxaddlen, ""); /* Omit [unknown] for local */
else
- fprintf(f, "[%s%-*c", "unknown", maxaddlen+1 - 7, ']');
+ fprintf(fp, "[%s%-*c", "unknown", maxaddlen+1 - 7, ']');
- if (h->mx >= 0) fprintf(f, " MX=%d", h->mx);
- if (h->port != PORT_NONE) fprintf(f, " port=%d", h->port);
- if (running_in_test_harness && h->dnssec == DS_YES) fputs(" AD", f);
- if (h->status == hstatus_unusable) fputs(" ** unusable **", f);
- fputc('\n', f);
+ if (h->mx >= 0) fprintf(fp, " MX=%d", h->mx);
+ if (h->port != PORT_NONE) fprintf(fp, " port=%d", h->port);
+ if (f.running_in_test_harness && h->dnssec == DS_YES) fputs(" AD", fp);
+ if (h->status == hstatus_unusable) fputs(" ** unusable **", fp);
+ fputc('\n', fp);
}
}
}
/* Loop for multiple addresses in the header, enabling group syntax. Note
that we have to reset this after the header has been scanned. */
- parse_allow_group = TRUE;
+ f.parse_allow_group = TRUE;
while (*s)
{
{
if (h->type == htype_from || h->type == htype_sender)
{
- if (!allow_unqualified_sender) recipient = NULL;
+ if (!f.allow_unqualified_sender) recipient = NULL;
}
else
{
- if (!allow_unqualified_recipient) recipient = NULL;
+ if (!f.allow_unqualified_recipient) recipient = NULL;
}
if (recipient == NULL) errmess = US"unqualified address not permitted";
}
while (isspace(*s)) s++;
} /* Next address */
- parse_allow_group = FALSE;
- parse_found_group = FALSE;
+ f.parse_allow_group = FALSE;
+ f.parse_found_group = FALSE;
} /* Next header unless yield has been set FALSE */
return yield;
/* Loop for multiple addresses in the header, enabling group syntax. Note
that we have to reset this after the header has been scanned. */
- parse_allow_group = TRUE;
+ f.parse_allow_group = TRUE;
while (*s != 0)
{
while (isspace(*s)) s++;
} /* Next address */
- parse_allow_group = FALSE;
- parse_found_group = FALSE;
+ f.parse_allow_group = FALSE;
+ f.parse_found_group = FALSE;
} /* Next header (if found is false) */
if (!found) return FAIL;
/* Scan the addresses in the header, enabling group syntax. Note that we
have to reset this after the header has been scanned. */
- parse_allow_group = TRUE;
+ f.parse_allow_group = TRUE;
while (*s != 0)
{
s = ss;
} /* Next address */
- parse_allow_group = FALSE;
- parse_found_group = FALSE;
+ f.parse_allow_group = FALSE;
+ f.parse_found_group = FALSE;
} /* Next header, unless done */
} /* Next header type unless done */
log_write(0, LOG_MAIN|LOG_PANIC_DIE, "%s", search_error_message);
result = search_find(handle, filename, key, -1, NULL, 0, 0, NULL);
- if (valueptr != NULL) *valueptr = result;
- return (result != NULL)? OK : search_find_defer? DEFER: FAIL;
+ if (valueptr) *valueptr = result;
+ return result ? OK : f.search_find_defer ? DEFER: FAIL;
}
/* The pattern is not an IP address or network reference of any kind. That is,