[exim-cvs] Use single-bit fields for global flags

Top Page
Delete this message
Reply to this message
Author: Exim Git Commits Mailing List
Date:  
To: exim-cvs
Subject: [exim-cvs] Use single-bit fields for global flags
Gitweb: https://git.exim.org/exim.git/commitdiff/8768d5483a5894400ae1f70cda1beb44ed9b087c
Commit:     8768d5483a5894400ae1f70cda1beb44ed9b087c
Parent:     3fc73bdc7aa8ac2b2b290033f602bdb947ae8049
Author:     Jeremy Harris <jgh146exb@???>
AuthorDate: Wed Aug 22 20:46:11 2018 +0100
Committer:  Jeremy Harris <jgh146exb@???>
CommitDate: Wed Aug 22 21:59:45 2018 +0100


    Use single-bit fields for global flags
---
 doc/doc-txt/ChangeLog                   |   6 +
 src/exim_monitor/em_globals.c           |   5 +-
 src/exim_monitor/em_menu.c              |   2 +-
 src/exim_monitor/em_queue.c             |   6 +-
 src/src/acl.c                           |  80 +++---
 src/src/auths/check_serv_cond.c         |   2 +-
 src/src/auths/cram_md5.c                |   6 +-
 src/src/auths/gsasl_exim.c              |   2 +-
 src/src/auths/plaintext.c               |   2 +-
 src/src/auths/spa.c                     |   8 +-
 src/src/child.c                         |  10 +-
 src/src/daemon.c                        |  56 ++--
 src/src/debug.c                         |   2 +-
 src/src/deliver.c                       | 232 ++++++++---------
 src/src/dkim.c                          |   6 +-
 src/src/dkim_transport.c                |   8 +-
 src/src/dmarc.c                         |  28 +-
 src/src/dns.c                           |   6 +-
 src/src/exim.c                          | 442 ++++++++++++++++----------------
 src/src/expand.c                        |  62 ++---
 src/src/filter.c                        |  20 +-
 src/src/filtertest.c                    |  10 +-
 src/src/globals.c                       | 374 +++++++++++++++------------
 src/src/globals.h                       | 198 ++++++++------
 src/src/host.c                          |  18 +-
 src/src/ip.c                            |   6 +-
 src/src/log.c                           |  12 +-
 src/src/macros.h                        |   2 +-
 src/src/malware.c                       |   2 +-
 src/src/match.c                         |  11 +-
 src/src/moan.c                          | 108 ++++----
 src/src/parse.c                         |  20 +-
 src/src/perl.c                          |   2 +-
 src/src/queue.c                         | 151 ++++++-----
 src/src/rda.c                           |   8 +-
 src/src/readconf.c                      |  10 +-
 src/src/receive.c                       | 116 ++++-----
 src/src/retry.c                         |   4 +-
 src/src/rewrite.c                       |  14 +-
 src/src/route.c                         |  20 +-
 src/src/routers/dnslookup.c             |   8 +-
 src/src/routers/manualroute.c           |   2 +-
 src/src/routers/redirect.c              |  10 +-
 src/src/routers/rf_change_domain.c      |   2 +-
 src/src/routers/rf_expand_data.c        |   2 +-
 src/src/routers/rf_get_errors_address.c |   8 +-
 src/src/routers/rf_get_munge_headers.c  |   4 +-
 src/src/routers/rf_lookup_hostlist.c    |   2 +-
 src/src/search.c                        |  14 +-
 src/src/sieve.c                         |   6 +-
 src/src/smtp_in.c                       | 162 ++++++------
 src/src/smtp_out.c                      |   2 +-
 src/src/spool_in.c                      |  88 +++----
 src/src/spool_mbox.c                    |   4 +-
 src/src/spool_out.c                     | 132 +++++-----
 src/src/store.c                         |  16 +-
 src/src/tls-openssl.c                   |   2 +-
 src/src/tls.c                           |   2 +-
 src/src/tlscert-gnu.c                   |   2 +-
 src/src/tlscert-openssl.c               |   2 +-
 src/src/tod.c                           |   4 +-
 src/src/transport.c                     |  46 ++--
 src/src/transports/appendfile.c         |  12 +-
 src/src/transports/autoreply.c          |  56 ++--
 src/src/transports/lmtp.c               |   4 +-
 src/src/transports/pipe.c               |  20 +-
 src/src/transports/queuefile.c          |   2 +-
 src/src/transports/smtp.c               |  46 ++--
 src/src/verify.c                        | 134 +++++-----
 69 files changed, 1478 insertions(+), 1393 deletions(-)


diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog
index 583603f..333ae73 100644
--- a/doc/doc-txt/ChangeLog
+++ b/doc/doc-txt/ChangeLog
@@ -98,6 +98,12 @@ PP/03 Make ${utf8clean:} expansion operator detect incomplete final character.

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
 -----------------
diff --git a/src/exim_monitor/em_globals.c b/src/exim_monitor/em_globals.c
index 6ed57ef..0a4f92e 100644
--- a/src/exim_monitor/em_globals.c
+++ b/src/exim_monitor/em_globals.c
@@ -148,6 +148,10 @@ BOOL    dont_deliver           = FALSE;
 int     dsn_ret                = 0;
 uschar *dsn_envid              = NULL;


+struct global_flags f = {
+ .sender_local        = FALSE,
+};
+
 #ifdef WITH_CONTENT_SCAN
 int     fake_response          = OK;
 #endif
@@ -205,7 +209,6 @@ uschar *sender_host_authenticated = NULL;
 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;


diff --git a/src/exim_monitor/em_menu.c b/src/exim_monitor/em_menu.c
index 8e638f0..31ce1a3 100644
--- a/src/exim_monitor/em_menu.c
+++ b/src/exim_monitor/em_menu.c
@@ -680,7 +680,7 @@ if (spool_read_header(buffer, TRUE, FALSE) != spool_read_OK)

 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);
   }


diff --git a/src/exim_monitor/em_queue.c b/src/exim_monitor/em_queue.c
index fabec40..c8d9a40 100644
--- a/src/exim_monitor/em_queue.c
+++ b/src/exim_monitor/em_queue.c
@@ -234,7 +234,7 @@ if (rc != spool_read_OK)
     }
   else
     {
-    deliver_freeze = FALSE;
+    f.deliver_freeze = FALSE;
     sender_address = msg;
     recipients_count = 0;
     }
@@ -242,9 +242,9 @@ if (rc != spool_read_OK)


/* 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)
     {
diff --git a/src/src/acl.c b/src/src/acl.c
index 4f335df..d4d370f 100644
--- a/src/src/acl.c
+++ b/src/src/acl.c
@@ -1674,8 +1674,8 @@ switch(vp->value)
     /* 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
@@ -1907,7 +1907,7 @@ if (verify_header_sender)
       {
       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;
       }
     }
   }
@@ -2060,7 +2060,7 @@ else
     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;
@@ -2902,10 +2902,10 @@ for (; cb; cb = cb->next)
     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 */
@@ -3027,7 +3027,7 @@ for (; cb; cb = cb->next)
       switch(control_type)
     {
     case CONTROL_AUTH_UNADVERTISED:
-    allow_auth_unadvertised = TRUE;
+    f.allow_auth_unadvertised = TRUE;
     break;


     #ifdef EXPERIMENTAL_BRIGHTMAIL
@@ -3038,22 +3038,22 @@ for (; cb; cb = cb->next)


     #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


@@ -3118,24 +3118,24 @@ for (; cb; cb = cb->next)

     #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:
@@ -3157,7 +3157,7 @@ for (; cb; cb = cb->next)
     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)
@@ -3174,7 +3174,7 @@ for (; cb; cb = cb->next)
     break;


     case CONTROL_QUEUE_ONLY:
-    queue_only_policy = TRUE;
+    f.queue_only_policy = TRUE;
     cancel_cutthrough_connection(TRUE, US"queueing forced");
     break;


@@ -3185,14 +3185,14 @@ for (; cb; cb = cb->next)
 #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)
         {
@@ -3257,7 +3257,7 @@ for (; cb; cb = cb->next)
     break;


     case CONTROL_SUPPRESS_LOCAL_FIXUPS:
-    suppress_local_fixups = TRUE;
+    f.suppress_local_fixups = TRUE;
     break;


     case CONTROL_CUTTHROUGH_DELIVERY:
@@ -3274,9 +3274,9 @@ for (; cb; cb = cb->next)
       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";
@@ -3404,7 +3404,7 @@ for (; cb; cb = cb->next)


         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)
@@ -3456,9 +3456,9 @@ for (; cb; cb = cb->next)

     #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),
@@ -3772,7 +3772,7 @@ if ((BIT(rc) & msgcond[verb]) != 0)
     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);
       }
@@ -3785,7 +3785,7 @@ if ((BIT(rc) & msgcond[verb]) != 0)
     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);
       }
@@ -3973,7 +3973,7 @@ if (acl_level == 0)
   {
   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;
@@ -4075,7 +4075,7 @@ while (acl != NULL)
     && (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]);

@@ -4097,12 +4097,10 @@ while (acl != NULL)
       {
       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;


@@ -4158,7 +4156,7 @@ while (acl != NULL)
       {
       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;
@@ -4291,10 +4289,10 @@ for (i = 0; i < 9; i++) acl_arg[i] = sav_arg[i];
 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;
}


@@ -4425,7 +4423,7 @@ switch (where)
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
@@ -4441,7 +4439,7 @@ switch (where)
       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
       {
diff --git a/src/src/auths/check_serv_cond.c b/src/src/auths/check_serv_cond.c
index 96c4b56..dc299f1 100644
--- a/src/src/auths/check_serv_cond.c
+++ b/src/src/auths/check_serv_cond.c
@@ -102,7 +102,7 @@ again later. */


if (cond == NULL)
{
- if (expand_string_forcedfail) return FAIL;
+ if (f.expand_string_forcedfail) return FAIL;
auth_defer_msg = expand_string_message;
return DEFER;
}
diff --git a/src/src/auths/cram_md5.c b/src/src/auths/cram_md5.c
index 06c153a..b9607b1 100644
--- a/src/src/auths/cram_md5.c
+++ b/src/src/auths/cram_md5.c
@@ -175,7 +175,7 @@ int i, rc, len;
/* 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@???>";

/* No data should have been sent with the AUTH command */
@@ -212,7 +212,7 @@ the given name. */

if (secret == NULL)
{
- if (expand_string_forcedfail) return FAIL;
+ if (f.expand_string_forcedfail) return FAIL;
auth_defer_msg = expand_string_message;
return DEFER;
}
@@ -278,7 +278,7 @@ or ERROR, as appropriate. */

 if (!secret || !name)
   {
-  if (expand_string_forcedfail)
+  if (f.expand_string_forcedfail)
     {
     *buffer = 0;           /* No message */
     return CANCELLED;
diff --git a/src/src/auths/gsasl_exim.c b/src/src/auths/gsasl_exim.c
index 5d8769f..6611de3 100644
--- a/src/src/auths/gsasl_exim.c
+++ b/src/src/auths/gsasl_exim.c
@@ -554,7 +554,7 @@ server_callback(Gsasl *ctx, Gsasl_session *sctx, Gsasl_property prop, auth_insta


       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;
diff --git a/src/src/auths/plaintext.c b/src/src/auths/plaintext.c
index 21581b6..bdd0569 100644
--- a/src/src/auths/plaintext.c
+++ b/src/src/auths/plaintext.c
@@ -204,7 +204,7 @@ while ((s = string_nextinlist(&text, &sep, big_buffer, big_buffer_size)))
       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;
diff --git a/src/src/auths/spa.c b/src/src/auths/spa.c
index 1ef41b5..50a4fea 100644
--- a/src/src/auths/spa.c
+++ b/src/src/auths/spa.c
@@ -224,7 +224,7 @@ debug_print_string(ablock->server_debug_string);    /* customized debug */
 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");
@@ -289,7 +289,7 @@ char *username, *password;


 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);
@@ -298,7 +298,7 @@ if (!(username = CS expand_string(ob->spa_username)))


 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);
@@ -309,7 +309,7 @@ if (ob->spa_domain)
   {
   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);
diff --git a/src/src/child.c b/src/src/child.c
index ad625ae..fb333d3 100644
--- a/src/src/child.c
+++ b/src/src/child.c
@@ -94,7 +94,7 @@ if (clmacro_count > 0)
   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;
@@ -117,9 +117,9 @@ if (!minimal)
     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)
@@ -249,7 +249,7 @@ if (pid == 0)
   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,
diff --git a/src/src/daemon.c b/src/src/daemon.c
index a382a73..6678789 100644
--- a/src/src/daemon.c
+++ b/src/src/daemon.c
@@ -259,7 +259,7 @@ if (smtp_accept_max_per_host != NULL)
   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);
     }
@@ -387,7 +387,7 @@ if (pid == 0)
     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,
@@ -441,7 +441,7 @@ if (pid == 0)
   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;
@@ -453,7 +453,7 @@ if (pid == 0)
/* 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
@@ -565,9 +565,9 @@ if (pid == 0)

       {
       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;
       }


@@ -629,7 +629,7 @@ if (pid == 0)
     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;


@@ -927,7 +927,7 @@ debugging lines get the pid added. */

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));
@@ -966,7 +966,7 @@ if (inetd_wait_mode)
}


-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
@@ -1048,7 +1048,7 @@ The preparation code decodes options and sets up the relevant data. We do this
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;
@@ -1270,7 +1270,7 @@ if (daemon_listen && !inetd_wait_mode)

} /* 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
@@ -1310,7 +1310,7 @@ Then disconnect from the controlling terminal, Most modern Unixes seem to have
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. */
@@ -1321,7 +1321,7 @@ if (background_daemon || inetd_wait_mode)
   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
@@ -1342,7 +1342,7 @@ if (background_daemon)
/* 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;
@@ -1420,7 +1420,7 @@ if (daemon_listen && !inetd_wait_mode)
     listen() stage instead. */


 #ifdef TCP_FASTOPEN
-    tcp_fastopen_ok = TRUE;
+    f.tcp_fastopen_ok = TRUE;
 #endif
     for(;;)
       {
@@ -1463,7 +1463,7 @@ if (daemon_listen && !inetd_wait_mode)
             &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


@@ -1525,7 +1525,7 @@ automatically. Consequently, Exim 4 writes a pid file only

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;

@@ -1591,7 +1591,7 @@ sigalrm_seen = (queue_interval > 0);
/* 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;

@@ -1609,7 +1609,7 @@ if (inetd_wait_mode)
sigalrm_seen = 1;
}

-else if (daemon_listen)
+else if (f.daemon_listen)
   {
   int i, j;
   int smtp_ports = 0;
@@ -1812,7 +1812,7 @@ for (;;)
           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 */


@@ -1837,11 +1837,11 @@ for (;;)
             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;
@@ -1851,13 +1851,13 @@ for (;;)


             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;
               }
@@ -1915,7 +1915,7 @@ for (;;)
   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;
diff --git a/src/src/debug.c b/src/src/debug.c
index a5cc251..35eb77c 100644
--- a/src/src/debug.c
+++ b/src/src/debug.c
@@ -188,7 +188,7 @@ if (debug_ptr == debug_buffer)


     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));
diff --git a/src/src/deliver.c b/src/src/deliver.c
index 3a39572..e316505 100644
--- a/src/src/deliver.c
+++ b/src/src/deliver.c
@@ -1358,7 +1358,7 @@ if (addr->message)
 /* 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.
@@ -1478,7 +1478,7 @@ if (driver_type == EXIM_DTYPE_TRANSPORT)
     {
     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";
   }
@@ -1488,7 +1488,7 @@ else if (driver_type == EXIM_DTYPE_ROUTER)
     {
     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";
   }
@@ -1662,7 +1662,7 @@ else if (result == DEFER || result == PANIC)


   if (addr->special_action == SPECIAL_FREEZE)
     {
-    deliver_freeze = TRUE;
+    f.deliver_freeze = TRUE;
     deliver_frozen_at = time(NULL);
     update_spool = TRUE;
     }
@@ -1670,7 +1670,7 @@ else if (result == DEFER || result == PANIC)
   /* 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);
   }


@@ -1703,10 +1703,10 @@ else
     {
     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;


@@ -1731,7 +1731,7 @@ else

/* Ensure logging is turned on again in all cases */

-disable_logging = FALSE;
+f.disable_logging = FALSE;
}


@@ -2157,7 +2157,7 @@ if (tp->return_path)
   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",
@@ -2556,7 +2556,7 @@ if (!shadowing)
       /* 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);
@@ -2716,7 +2716,7 @@ while (addr_local)
   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;


@@ -2734,7 +2734,7 @@ while (addr_local)
   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");
@@ -2752,7 +2752,7 @@ while (addr_local)


/* 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
@@ -2939,7 +2939,7 @@ while (addr_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)
@@ -4261,7 +4261,7 @@ for (delivery_count = 0; addr_remote; delivery_count++)


   if (!(tp = addr->transport))
     {
-    disable_logging = FALSE;  /* Jic */
+    f.disable_logging = FALSE;  /* Jic */
     panicmsg = US"No transport set by router";
     goto panic_continue;
     }
@@ -4456,7 +4456,7 @@ for (delivery_count = 0; addr_remote; delivery_count++)
     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);
@@ -4507,7 +4507,7 @@ for (delivery_count = 0; addr_remote; delivery_count++)
   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;
@@ -4582,12 +4582,12 @@ for (delivery_count = 0; addr_remote; delivery_count++)
     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; }
       }
     }


@@ -4677,7 +4677,7 @@ all pipes, so I do not see a reason to use non-blocking IO here
     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 */


@@ -4692,7 +4692,7 @@ all pipes, so I do not see a reason to use non-blocking IO here
     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
@@ -5046,7 +5046,7 @@ all pipes, so I do not see a reason to use non-blocking IO here
   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;

@@ -5570,7 +5570,7 @@ it is obtained from a command line (the -M or -q options), and otherwise it is
known to be a valid message id. */

Ustrcpy(message_id, id);
-deliver_force = forced;
+f.deliver_force = forced;
return_count = 0;
message_size = 0;

@@ -5718,7 +5718,7 @@ Otherwise it might be needed again. */
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
@@ -5761,8 +5761,8 @@ if (deliver_freeze)
       || 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);
@@ -5776,7 +5776,7 @@ if (deliver_freeze)


     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");
@@ -5784,7 +5784,7 @@ if (deliver_freeze)


/* We get here if any of the rules for unfreezing have triggered. */

- deliver_freeze = FALSE;
+ f.deliver_freeze = FALSE;
update_spool = TRUE;
}

@@ -5859,8 +5859,8 @@ else if (system_filter && process_recipients != RECIP_FAIL_TIMEOUT)
     }


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. */

@@ -5908,8 +5908,8 @@ else if (system_filter && process_recipients != RECIP_FAIL_TIMEOUT)
/* 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
@@ -5932,9 +5932,9 @@ else if (system_filter && process_recipients != RECIP_FAIL_TIMEOUT)
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",
@@ -6309,7 +6309,7 @@ deliver_out_buffer = store_malloc(DELIVER_OUT_BUFFER_SIZE);
  . 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;
@@ -6655,7 +6655,7 @@ while (addr_new)           /* Loop until all addresses dealt with */
     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
@@ -6699,7 +6699,7 @@ while (addr_new)           /* Loop until all addresses dealt with */
   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)
@@ -6993,14 +6993,14 @@ remember them for all subsequent deliveries. This can be delayed till later if
 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;
   }



@@ -7080,13 +7080,13 @@ if (addr_local)
   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;
@@ -7138,7 +7138,7 @@ if (addr_remote)
     if (remote_sort_domains) sort_remote_deliveries();
     do_remote_deliveries(TRUE);
     }
-  disable_logging = FALSE;
+  f.disable_logging = FALSE;
   }



@@ -7217,7 +7217,7 @@ retry cutoff time has expired for all alternative destinations. Bypass the
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 */
@@ -7397,9 +7397,9 @@ while (addr_failed)
/* 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);
@@ -7481,8 +7481,8 @@ while (addr_failed)
       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;
@@ -7520,10 +7520,10 @@ while (addr_failed)
         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  ",
@@ -7531,20 +7531,20 @@ while (addr_failed)
       ? 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);
@@ -7560,46 +7560,46 @@ while (addr_failed)
       /* 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
@@ -7610,12 +7610,12 @@ wording. */
       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. */


@@ -7636,7 +7636,7 @@ wording. */
           }
         }


-      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. */
@@ -7655,9 +7655,9 @@ wording. */
         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" : "");


@@ -7668,24 +7668,24 @@ wording. */

           /* 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);
@@ -7697,19 +7697,19 @@ wording. */
           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);
@@ -7719,22 +7719,22 @@ wording. */
         /* 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;
@@ -7742,19 +7742,19 @@ wording. */
         {
         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
@@ -7775,7 +7775,7 @@ wording. */
          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;
@@ -7813,44 +7813,44 @@ wording. */
       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
@@ -7867,7 +7867,7 @@ wording. */
         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);
@@ -7896,7 +7896,7 @@ wording. */
     }
   }


-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 */

@@ -7954,7 +7954,7 @@ if (!addr_defer)
     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);
@@ -8072,7 +8072,7 @@ else if (addr_defer != (address_item *)(+1))
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
@@ -8094,7 +8094,7 @@ else if (addr_defer != (address_item *)(+1))
     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)
@@ -8325,9 +8325,9 @@ else if (addr_defer != (address_item *)(+1))
   /* 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;
     }


@@ -8338,9 +8338,9 @@ else if (addr_defer != (address_item *)(+1))
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: ");
@@ -8381,9 +8381,9 @@ else if (addr_defer != (address_item *)(+1))


   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);
   }
@@ -8418,7 +8418,7 @@ if (remove_journal)
   /* 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
   }
@@ -8450,7 +8450,7 @@ deliver_init(void)
 #ifdef EXIM_TFO_PROBE
 tfo_probe();
 #else
-tcp_fastopen_ok = TRUE;
+f.tcp_fastopen_ok = TRUE;
 #endif



@@ -8501,17 +8501,17 @@ deliver_get_sender_address (uschar * id)
 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;

@@ -8573,7 +8573,7 @@ if (cutthrough.cctx.sock >= 0 && cutthrough.callout_hold_only)

     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);
diff --git a/src/src/dkim.c b/src/src/dkim.c
index 29ec29a..4d1822e 100644
--- a/src/src/dkim.c
+++ b/src/src/dkim.c
@@ -306,7 +306,7 @@ if (dkim_collect_error)
   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;
   }


@@ -381,7 +381,7 @@ dkim_verify_status = US"none";
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 */
@@ -453,7 +453,7 @@ switch (what)
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)
diff --git a/src/src/dkim_transport.c b/src/src/dkim_transport.c
index db3db91..8ce18c8 100644
--- a/src/src/dkim_transport.c
+++ b/src/src/dkim_transport.c
@@ -124,7 +124,7 @@ dkt_direct(transport_ctx * tctx, struct ob_dkim * dkim,
{
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;
@@ -157,7 +157,7 @@ arc_sign_init();
/* 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)))
@@ -186,7 +186,7 @@ having already been done - but we have to say we want CRLF output format, and
 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
@@ -196,7 +196,7 @@ if (  (  dkim_signature
    )
   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)))
diff --git a/src/src/dmarc.c b/src/src/dmarc.c
index 956c16b..a7e08c5 100644
--- a/src/src/dmarc.c
+++ b/src/src/dmarc.c
@@ -91,13 +91,13 @@ dmarc_status       = US"none";
 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);
@@ -148,7 +148,7 @@ int
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;
}
@@ -164,7 +164,7 @@ error_block *eblock = NULL;
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
@@ -195,8 +195,8 @@ 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;
@@ -226,7 +226,7 @@ BOOL has_dmarc_record = TRUE;
 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.
@@ -247,7 +247,7 @@ else if (!dmarc_abort)
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,
@@ -487,7 +487,7 @@ if (!dmarc_abort && !sender_host_authenticated)
/* 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;
@@ -558,8 +558,8 @@ history_buffer = string_sprintf(
 /* 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);
@@ -584,7 +584,7 @@ return DMARC_HIST_OK;
 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)
@@ -596,7 +596,7 @@ uschar *
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"";
}

@@ -604,7 +604,7 @@ 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)
diff --git a/src/src/dns.c b/src/src/dns.c
index cb17666..1da7feb 100644
--- a/src/src/dns.c
+++ b/src/src/dns.c
@@ -693,7 +693,7 @@ if ((previous = tree_search(tree_dns_fails, node_name)))
     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;
@@ -738,7 +738,7 @@ if (check_dns_names_pattern[0] != 0 && type != T_PTR && type != T_TXT)
     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;
     }
   }
@@ -761,7 +761,7 @@ if ((type == T_A || type == T_AAAA) && string_is_ip_address(name, NULL) != 0)
 (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));

diff --git a/src/src/exim.c b/src/src/exim.c
index 1410359..9a1cf8b 100644
--- a/src/src/exim.c
+++ b/src/src/exim.c
@@ -420,7 +420,7 @@ if (exim_tvcmp(&now_tv, then_tv) <= 0)

   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,
@@ -563,7 +563,7 @@ else
   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;
@@ -793,193 +793,193 @@ Returns:    nothing
 */


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. */
@@ -989,9 +989,9 @@ DEBUG(D_any) do {

 /* 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
@@ -999,29 +999,29 @@ DEBUG(D_any) do {
 # 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
@@ -1031,7 +1031,7 @@ show_db_version(f);
 #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) "",
@@ -1042,17 +1042,17 @@ show_db_version(f);
   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);
@@ -1633,9 +1633,9 @@ OS_INIT
/* 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
@@ -1799,7 +1799,7 @@ message has been sent). */
 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;
   }
@@ -1921,7 +1921,7 @@ for (i = 1; i < argc; i++)
     {
     switchchar = arg[3];
     argrest += 2;
-    queue_2stage = TRUE;
+    f.queue_2stage = TRUE;
     }


/* Make -r synonymous with -f, since it is a documented alias */
@@ -1992,8 +1992,8 @@ for (i = 1; i < argc; i++)

     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; }
       }


@@ -2065,8 +2065,8 @@ for (i = 1; i < argc; i++)
       {
       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;
       }


@@ -2123,8 +2123,8 @@ for (i = 1; i < argc; i++)

     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
@@ -2223,18 +2223,18 @@ for (i = 1; i < argc; i++)
     /* -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;
       }


@@ -2247,16 +2247,16 @@ for (i = 1; i < argc; i++)
       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);
@@ -2310,7 +2310,7 @@ for (i = 1; i < argc; i++)
             && real_uid != config_uid
             #endif
             )
-          trusted_config = FALSE;
+          f.trusted_config = FALSE;
         else
           {
           FILE *trust_list = Ufopen(TRUSTED_CONFIG_LIST, "rb");
@@ -2332,7 +2332,7 @@ for (i = 1; i < argc; i++)
                    ) ||                            /* or */
                 (statbuf.st_mode & 2) != 0)        /* world writeable */
               {
-              trusted_config = FALSE;
+              f.trusted_config = FALSE;
               fclose(trust_list);
               }
         else
@@ -2364,7 +2364,7 @@ for (i = 1; i < argc; i++)
                 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++)
@@ -2374,7 +2374,7 @@ for (i = 1; i < argc; i++)
                     }
                   if (i == nr_configs)
                     {
-                    trusted_config = FALSE;
+                    f.trusted_config = FALSE;
                     break;
                     }
                   }
@@ -2383,24 +2383,24 @@ for (i = 1; i < argc; i++)
               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;


@@ -2482,7 +2482,7 @@ for (i = 1; i < argc; i++)
       debug_file = NULL;
       if (*argrest == 'd')
         {
-        debug_daemon = TRUE;
+        f.debug_daemon = TRUE;
         argrest++;
         }
       if (*argrest != 0)
@@ -2501,7 +2501,7 @@ for (i = 1; i < argc; i++)
     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;


@@ -2538,7 +2538,7 @@ for (i = 1; i < argc; i++)
         { badarg = TRUE; break; }
       }
     originator_name = argrest;
-    sender_name_forced = TRUE;
+    f.sender_name_forced = TRUE;
     break;



@@ -2592,7 +2592,7 @@ for (i = 1; i < argc; i++)
           return EXIT_FAILURE;
           }
         }
-      sender_address_forced = TRUE;
+      f.sender_address_forced = TRUE;
       }
     break;


@@ -2623,7 +2623,7 @@ for (i = 1; i < argc; i++)
     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;



@@ -2714,7 +2714,7 @@ for (i = 1; i < argc; i++)
       return EXIT_FAILURE;
       }


-      if (running_in_test_harness) millisleep(500);
+      if (f.running_in_test_harness) millisleep(500);
       break;
       }


@@ -2726,7 +2726,7 @@ for (i = 1; i < argc; i++)
     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 */
@@ -2823,7 +2823,7 @@ for (i = 1; i < argc; i++)
     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)
       {
@@ -2933,7 +2933,7 @@ for (i = 1; i < argc; i++)
     case 'N':
     if (*argrest == 0)
       {
-      dont_deliver = TRUE;
+      f.dont_deliver = TRUE;
       debug_selector |= D_v;
       debug_file = stderr;
       }
@@ -3011,7 +3011,7 @@ for (i = 1; i < argc; i++)


     else if (Ustrcmp(argrest, "db") == 0)
       {
-      synchronous_delivery = FALSE;
+      f.synchronous_delivery = FALSE;
       arg_queue_only = FALSE;
       queue_only_set = TRUE;
       }
@@ -3022,7 +3022,7 @@ for (i = 1; i < argc; i++)


     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;
       }
@@ -3031,7 +3031,7 @@ for (i = 1; i < argc; i++)


     else if (Ustrcmp(argrest, "dq") == 0)
       {
-      synchronous_delivery = FALSE;
+      f.synchronous_delivery = FALSE;
       arg_queue_only = TRUE;
       queue_only_set = TRUE;
       }
@@ -3041,7 +3041,7 @@ for (i = 1; i < argc; i++)


     else if (Ustrcmp(argrest, "dqs") == 0)
       {
-      queue_smtp = TRUE;
+      f.queue_smtp = TRUE;
       arg_queue_only = FALSE;
       queue_only_set = TRUE;
       }
@@ -3055,7 +3055,7 @@ for (i = 1; i < argc; i++)


     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. */
@@ -3098,7 +3098,7 @@ for (i = 1; i < argc; i++)
             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);
@@ -3246,7 +3246,7 @@ for (i = 1; i < argc; i++)


     if (*argrest == 'q')
       {
-      queue_2stage = TRUE;
+      f.queue_2stage = TRUE;
       argrest++;
       }


@@ -3254,7 +3254,7 @@ for (i = 1; i < argc; i++)

     if (*argrest == 'i')
       {
-      queue_run_first_delivery = TRUE;
+      f.queue_run_first_delivery = TRUE;
       argrest++;
       }


@@ -3263,10 +3263,10 @@ for (i = 1; i < argc; i++)

     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++;
         }
       }
@@ -3275,7 +3275,7 @@ for (i = 1; i < argc; i++)


     if (*argrest == 'l')
       {
-      queue_run_local = TRUE;
+      f.queue_run_local = TRUE;
       argrest++;
       }


@@ -3333,9 +3333,9 @@ for (i = 1; i < argc; 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_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]);
           }
       }
@@ -3378,9 +3378,9 @@ for (i = 1; i < argc; 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]);
           }
       }
@@ -3405,7 +3405,7 @@ for (i = 1; i < argc; 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;
@@ -3422,7 +3422,7 @@ for (i = 1; i < argc; i++)
     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) */
@@ -3522,26 +3522,26 @@ if (usage_wanted) exim_usage(called_as);
 /* 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 &&
@@ -3550,11 +3550,11 @@ if ((
     ) ||
     (
     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)
     ) ||
     (
@@ -3582,8 +3582,8 @@ if (debug_selector != 0)
   {
   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",
@@ -3719,10 +3719,10 @@ values (such as the path name). If running in the test harness, pretend that
 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   */
@@ -3743,7 +3743,7 @@ if ((                                            /* EITHER */
   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,
@@ -3790,7 +3790,7 @@ This needs to happen before we read the main configuration. */
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
@@ -3839,17 +3839,17 @@ since some actions can be performed by non-admin users. Instead, set admin_user
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,
@@ -3858,29 +3858,29 @@ are permitted to specify sender_addresses with -f on the command line, and
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);
}
@@ -3923,7 +3923,7 @@ if (sender_address != NULL)

 if (cmdline_syslog_name != NULL)
   {
-  if (admin_user)
+  if (f.admin_user)
     {
     syslog_processname = cmdline_syslog_name;
     log_file_path = string_copy(CUS"syslog");
@@ -3965,7 +3965,7 @@ if (Ustrlen(syslog_processname) > 32)
     "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;
@@ -4007,7 +4007,7 @@ this. We have to make a new environment if TZ is wrong, but don't bother if
 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");
@@ -4060,14 +4060,14 @@ Exim user", but it hasn't, because either the -D option set macros, or the
       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
@@ -4097,7 +4097,7 @@ Don't attempt it if logging is disabled, or if listing variables or if
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;
@@ -4198,8 +4198,8 @@ if (bi_option)
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
@@ -4209,14 +4209,14 @@ passwords, etc. in lookup queries). Only an admin user may request a queue
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);
@@ -4231,9 +4231,9 @@ regression testing. */


 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;
@@ -4244,7 +4244,7 @@ real, but are permitted when checking things (-be, -bv, -bt, -bh, -bf, -bF).
 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;
@@ -4267,9 +4267,9 @@ else
 /* 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
@@ -4304,7 +4304,7 @@ if (smtp_input)


       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 "
@@ -4327,7 +4327,7 @@ root. There will be further calls later for each message received. */
 #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();
@@ -4359,7 +4359,7 @@ to the state Exim usually runs in. */


 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  */
@@ -4367,7 +4367,7 @@ if (!unprivileged &&                      /* originally had root AND */
         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");


@@ -4462,7 +4462,7 @@ if (msg_action_arg > 0 && msg_action != MSG_DELIVER && msg_action != MSG_LOAD)
}

/* 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. */

@@ -4658,13 +4658,13 @@ message. */

 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;
@@ -4691,7 +4691,7 @@ if (msg_action_arg > 0 && msg_action != MSG_LOAD)
 /* 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 ",
@@ -4728,7 +4728,7 @@ for (i = 0;;)


     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, '&');
@@ -4793,7 +4793,7 @@ for (i = 0;;)
 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)
     {
@@ -4828,7 +4828,7 @@ returns. We leave this till here so that the originator_ fields are available
 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)
     {
@@ -4852,7 +4852,7 @@ originator_* variables set. */


 if (test_rewrite_arg >= 0)
   {
-  really_exim = FALSE;
+  f.really_exim = FALSE;
   if (test_rewrite_arg >= argc)
     {
     printf("-brw needs an address argument\n");
@@ -4867,9 +4867,9 @@ unless a trusted caller supplies a sender address with -f, or is passing in the
 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
@@ -4902,14 +4902,14 @@ if ((!smtp_input && sender_address == NULL) ||
        !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
@@ -4928,7 +4928,7 @@ predicated upon the sender. If no arguments are given, read addresses from
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;
@@ -4988,7 +4988,7 @@ if (expansion_test)
   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);
@@ -5026,11 +5026,11 @@ if (expansion_test)


/* 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 */

@@ -5080,7 +5080,7 @@ if (raw_active_hostname != NULL)
   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);
@@ -5103,7 +5103,7 @@ if (host_checking)
   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);
     }
@@ -5121,8 +5121,8 @@ if (host_checking)
   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"
@@ -5206,11 +5206,11 @@ to override any SMTP queueing. */


 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 */
@@ -5233,7 +5233,7 @@ if (!smtp_input) error_handling = arg_error_handling;
 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 */
@@ -5253,13 +5253,13 @@ if (sender_host_address && !sender_fullhost)
   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,
@@ -5275,7 +5275,7 @@ batch/HELO/EHLO/AUTH/TLS. */

 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);
   }
@@ -5372,7 +5372,7 @@ this is logically inconsistent. In other words, it doesn't like the paranoia.
 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;
@@ -5427,10 +5427,10 @@ while (more)
       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 */
@@ -5467,8 +5467,8 @@ while (more)


     /* 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 */


@@ -5521,7 +5521,7 @@ while (more)
       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";
@@ -5575,10 +5575,10 @@ while (more)
     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,
@@ -5710,7 +5710,7 @@ while (more)
   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
@@ -5735,7 +5735,7 @@ while (more)
       }
     }


-  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
@@ -5787,7 +5787,7 @@ while (more)
       /* 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);
diff --git a/src/src/expand.c b/src/src/expand.c
index 1508dcf..b3e918e 100644
--- a/src/src/expand.c
+++ b/src/src/expand.c
@@ -927,7 +927,7 @@ int rc;
 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;
@@ -1662,7 +1662,7 @@ if this was a non-smtp message.
 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);
@@ -1707,7 +1707,7 @@ uschar * s;
 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++)
   {
@@ -1799,7 +1799,7 @@ val = vp->value;
 switch (vp->type)
   {
   case vtype_filter_int:
-    if (!filter_running) return NULL;
+    if (!f.filter_running) return NULL;
     /* Fall through */
     /* VVVVVVVVVVVV */
   case vtype_int:
@@ -2276,7 +2276,7 @@ switch(cond_type)
   /* 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;


@@ -2431,7 +2431,7 @@ switch(cond_type)
       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]);
@@ -3258,8 +3258,8 @@ want this string. Set skipping in the call in the fail case (this will always
 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 '}'";
@@ -3288,8 +3288,8 @@ while (isspace(*s)) s++;
 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 '{'";
@@ -3324,7 +3324,7 @@ else if (*s != '}')
     }
       expand_string_message =
         string_sprintf("\"%s\" failed and \"fail\" requested", type);
-      expand_string_forcedfail = TRUE;
+      f.expand_string_forcedfail = TRUE;
       goto FAILED;
       }
     }
@@ -3931,7 +3931,7 @@ DEBUG(D_expand)
     : "considering",
     string);


-expand_string_forcedfail = FALSE;
+f.expand_string_forcedfail = FALSE;
expand_string_message = US"";

 while (*s != 0)
@@ -4158,7 +4158,7 @@ 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]);
@@ -4456,7 +4456,7 @@ while (*s != 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",
@@ -4565,7 +4565,7 @@ while (*s != 0)
           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;
         }
@@ -4573,7 +4573,7 @@ while (*s != 0)
       /* 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;
       }
@@ -4823,7 +4823,7 @@ while (*s != 0)
       int fd;
       int timeout = 5;
       int save_ptr = yield->ptr;
-      FILE *f;
+      FILE * fp;
       uschar * arg;
       uschar * sub_arg[4];
       uschar * server_name = NULL;
@@ -4999,7 +4999,7 @@ while (*s != 0)
 #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 */


@@ -5027,20 +5027,20 @@ while (*s != 0)
     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
@@ -5051,7 +5051,7 @@ while (*s != 0)
       }
     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. */
@@ -6318,7 +6318,7 @@ while (*s != 0)
       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);
@@ -6936,7 +6936,7 @@ while (*s != 0)
               "missing in expanding ${addresses:%s}", --sub);
             goto EXPAND_FAILED;
             }
-        parse_allow_group = TRUE;
+        f.parse_allow_group = TRUE;


         for (;;)
           {
@@ -6985,7 +6985,7 @@ while (*s != 0)
         separator. */


         if (yield->ptr != save_ptr) yield->ptr--;
-        parse_allow_group = FALSE;
+        f.parse_allow_group = FALSE;
         continue;
         }


@@ -7704,9 +7704,9 @@ DEBUG(D_expand)
     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;
@@ -7731,7 +7731,7 @@ if (Ustrpbrk(string, "$\\") != NULL)
   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);
@@ -7924,7 +7924,7 @@ if (svalue == NULL) { *rvalue = bvalue; return OK; }
 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;
@@ -8181,9 +8181,9 @@ while (fgets(buffer, sizeof(buffer), stdin) != NULL)
     }
   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");
     }
   }
diff --git a/src/src/filter.c b/src/src/filter.c
index 4d67f98..a16416c 100644
--- a/src/src/filter.c
+++ b/src/src/filter.c
@@ -950,7 +950,7 @@ switch (command)
         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",
@@ -1452,7 +1452,7 @@ switch (c->type)
   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:
@@ -1471,14 +1471,14 @@ switch (c->type)
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 */
@@ -1494,7 +1494,7 @@ switch (c->type)
     }


   yield = FALSE;
-  parse_allow_group = TRUE;     /* Allow group syntax */
+  f.parse_allow_group = TRUE;     /* Allow group syntax */


   while (*pp != 0)
     {
@@ -1526,8 +1526,8 @@ switch (c->type)
     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;
@@ -1774,7 +1774,7 @@ while (commands != NULL)

     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)
@@ -2521,7 +2521,7 @@ while filtering, and zero the variables. */


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.
@@ -2590,7 +2590,7 @@ before returning. Reset the header decoding charset. */

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");
diff --git a/src/src/filtertest.c b/src/src/filtertest.c
index 7245608..f3d3acc 100644
--- a/src/src/filtertest.c
+++ b/src/src/filtertest.c
@@ -47,7 +47,7 @@ header_size = message_size;

 if (!dot_ended && !feof(stdin))
   {
-  if (!dot_ends)
+  if (!f.dot_ends)
     {
     while ((ch = getc(stdin)) != EOF)
       {
@@ -259,13 +259,13 @@ testing a system filter that is going to be followed by a user filter test. */


 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
   {
diff --git a/src/src/globals.c b/src/src/globals.c
index ee1db4b..d834373 100644
--- a/src/src/globals.c
+++ b/src/src/globals.c
@@ -228,7 +228,218 @@ const uschar **address_expansions[ADDRESS_EXPANSIONS_COUNT] = {


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;
@@ -268,7 +479,6 @@ uschar *acl_smtp_rcpt          = 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;
@@ -327,9 +537,6 @@ uschar *acl_wherecodes[]       = { US"550",     /* RCPT */
                    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;


@@ -416,17 +623,9 @@ address_item address_defaults = {

 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;
@@ -439,8 +638,6 @@ const uschar *arc_state_reason    = 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    = {
@@ -467,12 +664,10 @@ uschar *auth_defer_user_msg    = US"";
 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";
@@ -499,9 +694,7 @@ int     body_zerocount         = 0;
 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;


@@ -514,14 +707,12 @@ uschar *callout_random_local_part = US"$primary_hostname-$tod_epoch-testing";
 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;


@@ -530,8 +721,6 @@ uschar *client_authenticated_id = 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;
@@ -555,7 +744,6 @@ int     connection_max_messages= -1;
 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;


@@ -569,20 +757,17 @@ cut_t   cutthrough = {
   .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[]         = {
@@ -625,7 +810,6 @@ bit_table debug_options[]      = { /* must be in alphabetical order */
 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 {"
@@ -633,17 +817,12 @@ uschar *delay_warning_condition=
             "{ 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;
@@ -657,27 +836,15 @@ uschar *deliver_localpart_orig = 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;
@@ -689,7 +856,6 @@ uschar *dkim_verify_status     = 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;
@@ -697,13 +863,10 @@ uschar *dmarc_status            = 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;
@@ -720,13 +883,8 @@ uschar *dnslist_text           = NULL;
 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;
@@ -741,19 +899,15 @@ const uschar *event_name         = NULL;    /* event name variable */



 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;
@@ -762,7 +916,6 @@ uschar *fake_response_text     = US"Your message has been rejected but is "
                                    "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;
@@ -808,23 +961,15 @@ header_name header_names[] = {


 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;
@@ -836,14 +981,11 @@ uschar *hosts_treat_as_local   = NULL;
 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;
@@ -854,8 +996,6 @@ int     keep_malformed         = 4*24*60*60;    /* 4 days */


 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;


@@ -869,7 +1009,6 @@ uschar *local_interfaces       = US"0.0.0.0";
 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);


@@ -970,8 +1109,6 @@ int     log_reject_target      = 0;
 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;
@@ -987,7 +1124,6 @@ int     max_username_length    = 0;
 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;
@@ -999,11 +1135,9 @@ struct timeval message_id_tv   = { 0, 0 };
 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 };
@@ -1029,13 +1163,7 @@ int     mime_is_rfc822         = 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;
@@ -1048,20 +1176,14 @@ uid_t   originator_uid;
 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"";
@@ -1069,8 +1191,6 @@ uschar *proxy_external_address = 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;
@@ -1080,26 +1200,14 @@ uschar *prvscheck_result       = 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;
@@ -1116,8 +1224,6 @@ int     rcpt_fail_count        = 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;
@@ -1151,11 +1257,9 @@ uschar *recipient_data         = NULL;
 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;
@@ -1179,11 +1283,9 @@ int     retry_interval_max     = 24*60*60;
 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;


@@ -1271,7 +1373,6 @@ router_instance  router_defaults = {
 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
@@ -1286,49 +1387,38 @@ uschar *running_status         = US">>>running<<<" "\0EXTRA";
 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"*";
@@ -1338,12 +1428,9 @@ int     smtp_accept_queue      = 0;
 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;
@@ -1352,16 +1439,11 @@ uschar  smtp_connection_had[SMTP_HBUFF_SIZE];
 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;
@@ -1372,7 +1454,6 @@ uschar *smtp_read_error        = US"";
 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;
@@ -1400,16 +1481,12 @@ uschar *spf_guess              = US"v=spf1 a/24 mx/24 ptr ?all";
 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;
@@ -1422,26 +1499,14 @@ uschar *srs_orig_sender        = 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;
@@ -1450,25 +1515,16 @@ uschar *system_filter_pipe_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;

@@ -1534,7 +1590,6 @@ uschar *transport_name          = 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;
@@ -1542,8 +1597,6 @@ tree_node  *tree_duplicates    = 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;
@@ -1589,7 +1642,6 @@ uschar *warn_message_file      = NULL;
 int     warning_count          = 0;
 uschar *warnmsg_delay          = NULL;
 uschar *warnmsg_recipients     = NULL;
-BOOL    write_rejectlog        = TRUE;



/* End of globals.c */
diff --git a/src/src/globals.h b/src/src/globals.h
index 5b234e2..bdf0360 100644
--- a/src/src/globals.h
+++ b/src/src/globals.h
@@ -159,6 +159,118 @@ one module. */

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 */
@@ -198,29 +310,21 @@ extern uschar *acl_smtp_quit;          /* ACL run for QUIT */
 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 */
@@ -233,7 +337,6 @@ extern uschar *authenticated_fail_id;  /* ID that failed authentication */
 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 */
@@ -243,11 +346,10 @@ extern uschar *auth_defer_user_msg;    /* Error message for user */
 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 */
@@ -287,7 +389,6 @@ extern int     check_spool_space;      /* Minimum for message acceptance */
 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 */
@@ -296,7 +397,6 @@ extern int     clmacro_count;          /* Number of command line macros */
 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 */
@@ -308,7 +408,6 @@ extern uid_t   config_uid;             /* Additional 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 */


@@ -331,7 +430,6 @@ typedef struct {
 } 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 */
@@ -344,7 +442,6 @@ extern uschar *dccifd_address;         /* address of the dccifd daemon */
 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 */
@@ -362,9 +459,6 @@ extern uschar *deliver_domain_data;    /* From domain lookup */
 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 */
@@ -379,27 +473,19 @@ extern uschar *deliver_localpart_orig; /* The original local part for delivery *
 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 */
@@ -411,7 +497,6 @@ extern uschar *dkim_verify_status;     /* result for this signature */
 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 */
@@ -419,8 +504,6 @@ extern uschar *dmarc_status;           /* Expansion variable, one word value */
 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 */
@@ -442,15 +525,12 @@ extern uschar *dnslist_text;           /* DNS (black) list text message */
 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 */
@@ -476,14 +556,12 @@ extern int     expand_forbid;          /* RDO flags for forbidding things */
 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 */
@@ -508,18 +586,13 @@ extern int     header_maxsize;         /* Max total length for header */
 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 */
@@ -537,10 +610,8 @@ extern uschar *hosts_treat_as_local;   /* For routing */
 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 */
@@ -550,7 +621,6 @@ extern int     keep_malformed;         /* Time to keep malformed messages */


 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 */
@@ -576,7 +646,6 @@ extern int     log_reject_target;      /* Target log for ACL rejections */
 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 */
@@ -643,9 +712,7 @@ extern BOOL    mua_wrapper;            /* TRUE when Exim is wrapping an MUA */


 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;
@@ -665,12 +732,9 @@ extern uid_t   originator_uid;         /* Uid of ditto */
 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 */
@@ -690,7 +754,6 @@ extern int     proxy_external_port;    /* Port on remote interface of proxy */
 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 */
@@ -699,13 +762,8 @@ extern uschar *prvscheck_result;       /* 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 */
@@ -716,10 +774,8 @@ extern int     queue_only_load;        /* Max load before auto-queue */
 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 */
@@ -735,8 +791,6 @@ extern int     rcpt_fail_count;        /* Those that got 5xx */
 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 */
@@ -749,7 +803,6 @@ extern struct timeval received_time_taken; /* Interval the message took to be re
 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 */
@@ -788,17 +841,14 @@ extern router_info routers_available[];/* Vector of available routers */
 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 */
@@ -809,16 +859,11 @@ extern uschar **sender_host_aliases;   /* Points to list of alias names */
 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 */
@@ -839,7 +884,6 @@ extern int     smtp_accept_queue;      /* Queue after so many connections */
 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 */
@@ -854,8 +898,6 @@ extern BOOL    smtp_enforce_sync;      /* Enforce sync rules */
 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 */
@@ -903,7 +945,6 @@ extern uschar *spf_smtp_comment;       /* spf comment to include in SMTP reply *
 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 */
@@ -927,11 +968,7 @@ extern int     string_datestamp_type;  /* After insertion by string_format */
 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 */
@@ -948,29 +985,22 @@ extern gid_t   system_filter_gid;      /* Gid for running system filter */
 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 */
@@ -983,8 +1013,6 @@ extern tree_node *tree_duplicates;     /* Tree of duplicate addresses */
 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 */
diff --git a/src/src/host.c b/src/src/host.c
index 7118221..0da9933 100644
--- a/src/src/host.c
+++ b/src/src/host.c
@@ -84,7 +84,7 @@ if (limit < 1)
   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);
@@ -1674,7 +1674,7 @@ HDEBUG(D_host_lookup)
 /* 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)
@@ -1798,7 +1798,7 @@ NB host_lookup_msg must be in permanent store.  */


 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)";
@@ -2011,7 +2011,7 @@ lookups here (except when testing standalone). */
 /* 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 */

@@ -2033,7 +2033,7 @@ for (i = 1; i <= times;
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
     {
@@ -2046,7 +2046,7 @@ for (i = 1; i <= times;
     }


   #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
     {
@@ -2171,7 +2171,7 @@ if (host->address == NULL)


   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;
   }
@@ -2592,7 +2592,7 @@ if (fully_qualified_name != NULL) *fully_qualified_name = host->name;
 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
@@ -3268,7 +3268,7 @@ while (Ufgets(buffer, 256, stdin) != NULL)
   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)
     {
diff --git a/src/src/ip.c b/src/src/ip.c
index d9184ef..633e0c2 100644
--- a/src/src/ip.c
+++ b/src/src/ip.c
@@ -173,7 +173,7 @@ int sock, backlog = 5;
 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
 }
@@ -256,7 +256,7 @@ This is a Linux implementation.  It might be useable on FreeBSD; I have
 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)
@@ -313,7 +313,7 @@ alarm(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;
diff --git a/src/src/log.c b/src/src/log.c
index 6d8fdd2..2832f4e 100644
--- a/src/src/log.c
+++ b/src/src/log.c
@@ -157,7 +157,7 @@ if (!syslog_timestamp)
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);
@@ -189,7 +189,7 @@ for (pass = 0; pass < 2; pass++)

     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
@@ -241,7 +241,7 @@ if (s1)
   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);
 }
@@ -895,7 +895,7 @@ if (!(flags & (LOG_MAIN|LOG_PANIC|LOG_REJECT)))


/* 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;
@@ -918,7 +918,7 @@ if (LOGGING(pid))
   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);
@@ -961,7 +961,7 @@ length = ptr - log_buffer;
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
diff --git a/src/src/macros.h b/src/src/macros.h
index 5c2b0a4..fd53de8 100644
--- a/src/src/macros.h
+++ b/src/src/macros.h
@@ -24,7 +24,7 @@ a string as a text string. This is sometimes useful for debugging output. */
 /* 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
diff --git a/src/src/malware.c b/src/src/malware.c
index 49456de..4b28760 100644
--- a/src/src/malware.c
+++ b/src/src/malware.c
@@ -2226,7 +2226,7 @@ sender_address = US"malware-sender@???";
return_path = US"";
recipients_list = NULL;
receive_add_recipient(US"malware-victim@???", -1);
-enable_dollar_recipients = TRUE;
+f.enable_dollar_recipients = TRUE;

ret = malware_internal(US"*", eml_filename, 0);

diff --git a/src/src/match.c b/src/src/match.c
index 3539aaa..0c0f3e8 100644
--- a/src/src/match.c
+++ b/src/src/match.c
@@ -297,14 +297,13 @@ else if (!mac_islookup(search_type, lookup_querystyle))
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;
@@ -494,7 +493,7 @@ else

   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);
diff --git a/src/src/moan.c b/src/src/moan.c
index 4e86484..c89f5c2 100644
--- a/src/src/moan.c
+++ b/src/src/moan.c
@@ -70,7 +70,7 @@ int fd;
 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 */
@@ -85,48 +85,48 @@ else DEBUG(D_any) debug_printf("Child process %d for sending message\n", pid);

/* 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" :


@@ -135,8 +135,8 @@ switch(ident)
     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"
@@ -144,75 +144,75 @@ switch(ident)
     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;
       }
@@ -220,8 +220,8 @@ switch(ident)
 #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;
@@ -235,7 +235,7 @@ if (bounce_return_message)
   {
   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;
@@ -248,15 +248,15 @@ if (bounce_return_message)
         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");
     }
@@ -266,12 +266,12 @@ if (bounce_return_message)


   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 "."
@@ -279,10 +279,10 @@ if (bounce_return_message)

   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))
       {
@@ -290,7 +290,7 @@ if (bounce_return_message)


       if (enddot && *buf == '.' && buf[1] == '\n')
     {
-    fputc('.', f);
+    fputc('.', fp);
     break;
     }


@@ -304,11 +304,11 @@ if (bounce_return_message)
       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
@@ -318,14 +318,14 @@ if (bounce_return_message)
     /*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)
{
@@ -382,7 +382,7 @@ if (message_reference)

/* 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;
@@ -394,7 +394,7 @@ if (check_sender && message_file && trusted_caller &&


/* 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);


diff --git a/src/src/parse.c b/src/src/parse.c
index 9e53120..46f9751 100644
--- a/src/src/parse.c
+++ b/src/src/parse.c
@@ -658,7 +658,7 @@ if (*s != '@' && *s != '<')
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)
@@ -670,8 +670,8 @@ if (*s != '@' && *s != '<')


   if (*s == ':')
     {
-    parse_found_group = TRUE;
-    parse_allow_group = FALSE;
+    f.parse_found_group = TRUE;
+    f.parse_allow_group = FALSE;
     s++;
     goto RESTART;
     }
@@ -790,10 +790,10 @@ move it back past white space if necessary. */
 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
     {
@@ -824,10 +824,10 @@ We might have an empty address in a group - the caller can choose to ignore
 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;
}
@@ -2149,7 +2149,7 @@ allow_utf8_domains = FALSE;

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;
diff --git a/src/src/perl.c b/src/src/perl.c
index 5239f3d..58643f0 100644
--- a/src/src/perl.c
+++ b/src/src/perl.c
@@ -62,7 +62,7 @@ XS(xs_expand_string)
   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);
 }
diff --git a/src/src/queue.c b/src/src/queue.c
index 3ae2a70..9f9e409 100644
--- a/src/src/queue.c
+++ b/src/src/queue.c
@@ -373,7 +373,7 @@ Returns:     nothing
 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;
@@ -390,10 +390,10 @@ on TCP/IP channels have queue_run_pid set, but not queue_running. */


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 */

@@ -402,11 +402,11 @@ if (!recurse)
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;
@@ -416,11 +416,11 @@ if (!recurse)
     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);
@@ -433,10 +433,10 @@ if (!recurse)

/* 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);


@@ -459,7 +459,7 @@ for (i = queue_run_in_order ? -1 : 0;
      i <= (queue_run_in_order ? -1 : subcount);
      i++)
   {
-  queue_filename *f;
+  queue_filename * fq;
   void *reset_point1 = store_get(0);


   DEBUG(D_queue_run)
@@ -472,9 +472,9 @@ for (i = queue_run_in_order ? -1 : 0;
       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;
@@ -485,7 +485,7 @@ for (i = queue_run_in_order ? -1 : 0;
     /* 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)",
@@ -502,15 +502,15 @@ for (i = queue_run_in_order ? -1 : 0;


     /* 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
@@ -520,10 +520,10 @@ for (i = queue_run_in_order ? -1 : 0;
     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,
@@ -531,14 +531,14 @@ for (i = queue_run_in_order ? -1 : 0;
       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;
@@ -546,9 +546,9 @@ for (i = queue_run_in_order ? -1 : 0;


       /* 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;
         }


@@ -559,7 +559,7 @@ for (i = queue_run_in_order ? -1 : 0;
       /* 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)
@@ -568,7 +568,7 @@ for (i = queue_run_in_order ? -1 : 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;
         }


@@ -580,7 +580,7 @@ for (i = queue_run_in_order ? -1 : 0;
         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)
@@ -594,7 +594,7 @@ for (i = queue_run_in_order ? -1 : 0;
           {
           DEBUG(D_queue_run)
             debug_printf("%s: no recipient address matched %s\n",
-              f->text, deliver_selectstring);
+              fq->text, deliver_selectstring);
           wanted = FALSE;
           }
         }
@@ -642,14 +642,14 @@ for (i = queue_run_in_order ? -1 : 0;
     /* 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)
@@ -660,20 +660,20 @@ for (i = queue_run_in_order ? -1 : 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
@@ -690,7 +690,7 @@ for (i = queue_run_in_order ? -1 : 0;
     /* 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;
@@ -720,9 +720,9 @@ for (i = queue_run_in_order ? -1 : 0;
 /* 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);
}

@@ -820,7 +820,7 @@ int i;
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. */
@@ -835,7 +835,7 @@ if (count > 0)
     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;
     }
   }
@@ -843,7 +843,7 @@ if (count > 0)
 /* 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 */
@@ -855,8 +855,8 @@ if (option >= 8) option -= 8;
 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;
@@ -864,8 +864,8 @@ for (reset_point = store_get(0);
   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;
@@ -877,7 +877,7 @@ for (reset_point = store_get(0);
     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';
@@ -912,12 +912,12 @@ for (reset_point = store_get(0);
     }


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)
@@ -926,7 +926,7 @@ for (reset_point = store_get(0);
     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 " ***",
@@ -941,7 +941,7 @@ for (reset_point = store_get(0);
       }
     }


- if (deliver_freeze) printf(" *** frozen ***");
+ if (f.deliver_freeze) printf(" *** frozen ***");

printf("\n");

@@ -1008,7 +1008,7 @@ if (action >= MSG_SHOW_BODY)
int fd, i, rc;
uschar *subdirectory, *suffix;

-  if (!admin_user)
+  if (!f.admin_user)
     {
     printf("Permission denied\n");
     return FALSE;
@@ -1070,7 +1070,7 @@ if ((deliver_datafile = spool_open_datafile(id)) < 0)
     {
     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
@@ -1095,7 +1095,7 @@ if (spool_read_header(spoolname, TRUE, FALSE) != spool_read_OK)
     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;
@@ -1109,7 +1109,7 @@ message. Only admin users may freeze/thaw, add/cancel recipients, or otherwise
 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);
@@ -1141,15 +1141,15 @@ switch(action)


   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)
       {
@@ -1166,15 +1166,15 @@ switch(action)



   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");
@@ -1407,11 +1407,10 @@ Returns:    nothing
 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;
@@ -1421,20 +1420,20 @@ while ((ss = string_nextinlist(&s, &sep, buffer, sizeof(buffer))) != NULL)
   {
   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);
+      }
     }
   }
 }
diff --git a/src/src/rda.c b/src/src/rda.c
index 2d8bda8..ee7c1fe 100644
--- a/src/src/rda.c
+++ b/src/src/rda.c
@@ -358,7 +358,7 @@ if (rdata->isfile)
   }
 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
@@ -566,7 +566,7 @@ DEBUG(D_route) debug_printf("rda_interpret (%s): %s\n",
 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;
@@ -672,7 +672,7 @@ if ((pid = fork()) == 0)
   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;
@@ -825,7 +825,7 @@ if (eblockp)
 /* 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;
diff --git a/src/src/readconf.c b/src/src/readconf.c
index 875e032..1f0e41d 100644
--- a/src/src/readconf.c
+++ b/src/src/readconf.c
@@ -2423,7 +2423,7 @@ if (!ol)
/* 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);
@@ -2782,7 +2782,7 @@ if (!type)


   if (Ustrcmp(name, "config") == 0)
     {
-    print_config(admin_user, no_labels);
+    print_config(f.admin_user, no_labels);
     return TRUE;
     }


@@ -2883,7 +2883,7 @@ else if (Ustrcmp(type, "macro") == 0)
   {
   /* 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;
@@ -3290,7 +3290,7 @@ if (Uchdir("/") < 0)
 /* 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",
@@ -4416,7 +4416,7 @@ void
 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
diff --git a/src/src/receive.c b/src/src/receive.c
index 7e5aac1..f7124a6 100644
--- a/src/src/receive.c
+++ b/src/src/receive.c
@@ -109,7 +109,7 @@ BOOL
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);
@@ -619,7 +619,7 @@ register int linelength = 0;

/* Handle the case when only EOF terminates the message */

-if (!dot_ends)
+if (!f.dot_ends)
{
register int last_ch = '\n';

@@ -1023,7 +1023,7 @@ int ch;

 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 (;;)
   {
@@ -1311,17 +1311,17 @@ if (sender_fullhost)
       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;
 }


@@ -1730,7 +1730,7 @@ message_linecount = body_linecount = body_zerocount =
#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

@@ -1862,7 +1862,7 @@ for (;;)
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')
@@ -1935,7 +1935,7 @@ for (;;)


     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)
       {
@@ -2059,7 +2059,7 @@ for (;;)
      && 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)
@@ -2081,11 +2081,11 @@ for (;;)
             {
             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)
@@ -2156,7 +2156,7 @@ for (;;)
       {
       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)
@@ -2383,9 +2383,9 @@ for (h = header_list->next; h; h = h->next)
     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;
@@ -2471,7 +2471,7 @@ if (extract_recip)
       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)
         {
@@ -2551,8 +2551,8 @@ if (extract_recip)
         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
@@ -2660,7 +2660,7 @@ messages. This can be user-configured if required, but we had better flatten
 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"";
@@ -2673,7 +2673,7 @@ if (  !msgid_header
     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);
@@ -2694,7 +2694,7 @@ if (  !msgid_header
     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);
@@ -2746,7 +2746,7 @@ untrusted user to set anything in the envelope (which might then get info
 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"";

@@ -2757,8 +2757,8 @@ if ( !from_header

   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;
     }


@@ -2777,12 +2777,12 @@ if (  !from_header
       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,
@@ -2829,9 +2829,9 @@ here. If the From: header contains more than one address, then the call to
 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;
@@ -2842,7 +2842,7 @@ if (  from_header
       &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)
@@ -2880,19 +2880,19 @@ if (  from_header
   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;
@@ -2957,7 +2957,7 @@ As per Message-Id, we prepend if resending, else append.
 */


 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));


@@ -3333,10 +3333,10 @@ $message_body_end can be extracted if needed. Allow $recipients in expansions.
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
   {
@@ -3346,7 +3346,7 @@ else
     {


 #ifndef DISABLE_DKIM
-    if (!dkim_disable_verify)
+    if (!f.dkim_disable_verify)
       {
       /* Finish verification */
       dkim_exim_verify_finish();
@@ -3575,7 +3575,7 @@ else
     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)
         {
@@ -3619,8 +3619,8 @@ else


/* 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
@@ -3662,7 +3662,7 @@ if (sigsetjmp(local_scan_env, 1) == 0)
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,
@@ -3704,9 +3704,9 @@ if (local_scan_data)

 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()";
     }
@@ -3714,9 +3714,9 @@ if (rc == LOCAL_SCAN_ACCEPT_FREEZE)
   }
 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;
@@ -3823,7 +3823,7 @@ signal(SIGINT, SIG_IGN);


/* 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)
@@ -3847,8 +3847,8 @@ memcpy(received_header->text + received_header->slen - tslen - 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
@@ -4093,9 +4093,9 @@ if (message_logs && !blackholed_by)
       {
       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);
@@ -4108,7 +4108,7 @@ if (message_logs && !blackholed_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
@@ -4128,7 +4128,7 @@ Of course, since TCP/IP is asynchronous, there is always a chance that the
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;
@@ -4222,19 +4222,19 @@ if(!smtp_reply)


/* 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);
diff --git a/src/src/retry.c b/src/src/retry.c
index fd4cbc2..a040c33 100644
--- a/src/src/retry.c
+++ b/src/src/retry.c
@@ -217,7 +217,7 @@ if (host_retry_record)
   /* 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,
@@ -245,7 +245,7 @@ unless the ultimate address timeout has been reached. */
 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))
diff --git a/src/src/rewrite.c b/src/src/rewrite.c
index 172f868..2196bfa 100644
--- a/src/src/rewrite.c
+++ b/src/src/rewrite.c
@@ -142,7 +142,7 @@ for (rule = rewrite_rules;
     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;
@@ -203,7 +203,7 @@ for (rule = rewrite_rules;


   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);
@@ -465,7 +465,7 @@ while (isspace(*s)) s++;
 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
@@ -544,8 +544,8 @@ while (*s != 0)

     /* 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;
@@ -673,8 +673,8 @@ while (*s != 0)
     }
   }


-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. */
diff --git a/src/src/route.c b/src/src/route.c
index f50a86e..c69bdcb 100644
--- a/src/src/route.c
+++ b/src/src/route.c
@@ -606,7 +606,7 @@ while ((check = string_nextinlist(&listptr, &sep, buffer, sizeof(buffer))))

   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;
@@ -854,7 +854,7 @@ deliver_localpart_data = NULL;
 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 */

@@ -866,7 +866,7 @@ if ((verify == v_none || verify == v_expn) && r->verify_only)

/* 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);
@@ -958,7 +958,7 @@ if (r->router_home_directory)
   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,
@@ -1003,7 +1003,7 @@ if (r->condition)
   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);
@@ -1474,7 +1474,7 @@ for (r = addr->start_router ? addr->start_router : routers; r; r = nextr)


/* 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. */
@@ -1620,7 +1620,7 @@ for (r = addr->start_router ? addr->start_router : routers; r; r = nextr)
     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);
@@ -1766,7 +1766,7 @@ if (!r)
       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);
@@ -1835,7 +1835,7 @@ if (r->translate_ip_address)


     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);
@@ -1923,7 +1923,7 @@ if (yield == DEFER && addr->message)


deliver_set_expansions(NULL);
router_name = NULL;
-disable_logging = FALSE;
+f.disable_logging = FALSE;
return yield;
}

diff --git a/src/src/routers/dnslookup.c b/src/src/routers/dnslookup.c
index a3b0d35..d6d7d06 100644
--- a/src/src/routers/dnslookup.c
+++ b/src/src/routers/dnslookup.c
@@ -183,7 +183,7 @@ DEBUG(D_route)
 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);
@@ -266,12 +266,12 @@ for (;;)
   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
@@ -399,7 +399,7 @@ for (;;)
/* 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);
diff --git a/src/src/routers/manualroute.c b/src/src/routers/manualroute.c
index fded7af..af44706 100644
--- a/src/src/routers/manualroute.c
+++ b/src/src/routers/manualroute.c
@@ -319,7 +319,7 @@ configuration problem. */


 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;
diff --git a/src/src/routers/redirect.c b/src/src/routers/redirect.c
index 944fb67..938db36 100644
--- a/src/src/routers/redirect.c
+++ b/src/src/routers/redirect.c
@@ -359,7 +359,7 @@ while (generated)


/* 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;
@@ -577,7 +577,7 @@ addr_prop.utf8_downcvt_maybe = addr->prop.utf8_downcvt_maybe;
 /* 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
@@ -786,7 +786,7 @@ switch (frc)
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;
@@ -855,7 +855,7 @@ if (eblock != NULL)
   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 */
@@ -887,7 +887,7 @@ generated anything. Log what happened to this address, and return DISCARD. */


 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);
diff --git a/src/src/routers/rf_change_domain.c b/src/src/routers/rf_change_domain.c
index d37220d..9f50957 100644
--- a/src/src/routers/rf_change_domain.c
+++ b/src/src/routers/rf_change_domain.c
@@ -76,7 +76,7 @@ if (rewrite)
     if (newh != NULL)
       {
       h = newh;
-      header_rewritten = TRUE;
+      f.header_rewritten = TRUE;
       }
     }
   }
diff --git a/src/src/routers/rf_expand_data.c b/src/src/routers/rf_expand_data.c
index cf5b9cb..6a8ad17 100644
--- a/src/src/routers/rf_expand_data.c
+++ b/src/src/routers/rf_expand_data.c
@@ -31,7 +31,7 @@ rf_expand_data(address_item *addr, uschar *s, int *prc)
 {
 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;
diff --git a/src/src/routers/rf_get_errors_address.c b/src/src/routers/rf_get_errors_address.c
index 752cc95..858c806 100644
--- a/src/src/routers/rf_get_errors_address.c
+++ b/src/src/routers/rf_get_errors_address.c
@@ -45,7 +45,7 @@ s = expand_string(rblock->errors_to);


 if (s == NULL)
   {
-  if (expand_string_forcedfail)
+  if (f.expand_string_forcedfail)
     {
     DEBUG(D_route)
       debug_printf("forced expansion failure - ignoring errors_to\n");
@@ -81,7 +81,7 @@ if (verify != v_none)
   }
 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;
@@ -96,7 +96,7 @@ else


   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
@@ -118,7 +118,7 @@ else
   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++];


diff --git a/src/src/routers/rf_get_munge_headers.c b/src/src/routers/rf_get_munge_headers.c
index f45e6eb..7f81e65 100644
--- a/src/src/routers/rf_get_munge_headers.c
+++ b/src/src/routers/rf_get_munge_headers.c
@@ -44,7 +44,7 @@ if (rblock->extra_headers)
   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",
@@ -99,7 +99,7 @@ if (rblock->remove_headers)
   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",
diff --git a/src/src/routers/rf_lookup_hostlist.c b/src/src/routers/rf_lookup_hostlist.c
index acf976f..0527566 100644
--- a/src/src/routers/rf_lookup_hostlist.c
+++ b/src/src/routers/rf_lookup_hostlist.c
@@ -197,7 +197,7 @@ for (prev = NULL, h = addr->host_list; h; h = next_h)
     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;
diff --git a/src/src/search.c b/src/src/search.c
index 8f46c7e..e5beaf3 100644
--- a/src/src/search.c
+++ b/src/src/search.c
@@ -475,7 +475,7 @@ int old_pool = store_pool;
 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,
@@ -521,7 +521,7 @@ else

   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
@@ -564,7 +564,7 @@ DEBUG(D_lookup)
   {
   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");
   }
@@ -669,7 +669,7 @@ DEBUG(D_lookup)
 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
@@ -692,7 +692,7 @@ else if (partial >= 0)
     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
@@ -730,7 +730,7 @@ else if (partial >= 0)

       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
@@ -772,7 +772,7 @@ if (yield == NULL && (starflags & SEARCH_STARAT) != 0)
     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)
       {
diff --git a/src/src/sieve.c b/src/src/sieve.c
index cf90819..f5329da 100644
--- a/src/src/sieve.c
+++ b/src/src/sieve.c
@@ -2137,7 +2137,7 @@ if (parse_identifier(filter,CUS "address"))
         filter->errmsg=CUS "header string expansion failed";
         return -1;
         }
-      parse_allow_group = TRUE;
+      f.parse_allow_group = TRUE;
       while (*header_value && !*cond)
         {
         uschar *error;
@@ -2183,8 +2183,8 @@ if (parse_identifier(filter,CUS "address"))
         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;
diff --git a/src/src/smtp_in.c b/src/src/smtp_in.c
index 8405945..4267bc5 100644
--- a/src/src/smtp_in.c
+++ b/src/src/smtp_in.c
@@ -374,7 +374,7 @@ return FALSE;
 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();
@@ -388,11 +388,11 @@ static BOOL
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;
}

@@ -623,7 +623,7 @@ for(;;)
/* 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;
@@ -1520,7 +1520,7 @@ bad:
     }
   else
     {
-    proxy_session_failed = TRUE;
+    f.proxy_session_failed = TRUE;
     DEBUG(D_receive)
       debug_printf("Failure to extract proxied host, only QUIT allowed\n");
     }
@@ -1606,7 +1606,7 @@ for (p = cmd_list; p < cmd_list_end; p++)
   {
 #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
@@ -1621,7 +1621,7 @@ for (p = cmd_list; p < cmd_list_end; p++)
         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
@@ -1660,7 +1660,7 @@ for (p = cmd_list; p < cmd_list_end; p++)


#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

@@ -1670,7 +1670,7 @@ if (  smtp_inptr < smtp_inend        /* Outstanding input */
    && 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;
@@ -1747,10 +1747,10 @@ const uschar * hostname = sender_fullhost
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)
@@ -1835,7 +1835,7 @@ for (i = 0; i < smtp_ch_index; i++)
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);
}

@@ -2015,20 +2015,20 @@ message_linecount = 0;
 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 */
@@ -2056,14 +2056,14 @@ spf_result_guessed = FALSE;
 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
@@ -2226,7 +2226,7 @@ while (done <= 0)


       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 "
@@ -2282,7 +2282,7 @@ while (done <= 0)
       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);
@@ -2388,7 +2388,7 @@ if (  getsockopt(fileno(smtp_out), IPPROTO_TCP, TCP_INFO, &tinfo, &len) == 0
    )
   {
   DEBUG(D_receive) debug_printf("TCP_FASTOPEN mode connection (state TCP_SYN_RECV)\n");
-  tcp_in_fastopen = TRUE;
+  f.tcp_in_fastopen = TRUE;
   }
 # endif
 }
@@ -2430,15 +2430,15 @@ count_nonmail = TRUE_UNSET;
 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;

@@ -2528,7 +2528,7 @@ the flag sender_host_notsocket is used to suppress it.
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;
@@ -2572,7 +2572,7 @@ if (!sender_host_unknown)
     #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;
@@ -2719,7 +2719,7 @@ if (!sender_host_unknown)
   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
@@ -2850,10 +2850,10 @@ if (!sender_host_unknown)
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
@@ -2878,7 +2878,7 @@ if (smtp_batched_input) return TRUE;

#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
@@ -3083,7 +3083,7 @@ smtp_respond(uschar* code, int codelen, BOOL final, uschar *msg)
int esclen = 0;
uschar *esc = US"";

-if (!final && no_multiline_responses) return;
+if (!final && f.no_multiline_responses) return;

 if (codelen > 4)
   {
@@ -3119,7 +3119,7 @@ for (;;)
     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);
@@ -3349,7 +3349,7 @@ interactions between temp_details and return_error_details. One day it should
 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
@@ -3519,27 +3519,27 @@ if (sender_helo_name == NULL)
 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
@@ -3554,7 +3554,7 @@ else
/* 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");
@@ -3563,19 +3563,19 @@ else
       {
       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;
@@ -3597,7 +3597,7 @@ else
       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)
         {
@@ -3610,7 +3610,7 @@ else
     }
   }


-if (!helo_verified) helo_verify_failed = TRUE; /* We've tried ... */
+if (!f.helo_verified) f.helo_verify_failed = TRUE; /* We've tried ... */
return yield;
}

@@ -3757,7 +3757,7 @@ static int
 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);
@@ -3859,7 +3859,7 @@ for the host). Note: we do NOT reset AUTH at this point. */
 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;
@@ -3962,7 +3962,7 @@ while (done <= 0)
       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");
@@ -4021,7 +4021,7 @@ while (done <= 0)


       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)
@@ -4100,9 +4100,9 @@ while (done <= 0)
       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++; }
@@ -4131,11 +4131,11 @@ while (done <= 0)
     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)
           {
@@ -4144,7 +4144,7 @@ while (done <= 0)
           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 "
@@ -4183,7 +4183,7 @@ while (done <= 0)
       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
@@ -4303,13 +4303,13 @@ while (done <= 0)
     /* 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;
       }



@@ -4371,7 +4371,7 @@ while (done <= 0)
       {
       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;
       }


@@ -4843,7 +4843,7 @@ while (done <= 0)
       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);
@@ -4871,7 +4871,7 @@ while (done <= 0)
       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
@@ -4898,7 +4898,7 @@ while (done <= 0)
       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
@@ -4926,7 +4926,7 @@ while (done <= 0)


       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;
@@ -5114,12 +5114,12 @@ while (done <= 0)
       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 */
@@ -5156,7 +5156,7 @@ while (done <= 0)
     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"");
     }


@@ -5226,14 +5226,14 @@ while (done <= 0)
       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)
@@ -5249,7 +5249,7 @@ while (done <= 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
@@ -5284,10 +5284,10 @@ while (done <= 0)
     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;


@@ -5377,13 +5377,13 @@ while (done <= 0)
     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;


@@ -5459,7 +5459,7 @@ while (done <= 0)
       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;
@@ -5604,8 +5604,8 @@ while (done <= 0)
       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)
       );
@@ -5613,7 +5613,7 @@ while (done <= 0)
       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)
       );
@@ -5808,7 +5808,7 @@ while (done <= 0)
       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",
diff --git a/src/src/smtp_out.c b/src/src/smtp_out.c
index 70aaef3..31e9a36 100644
--- a/src/src/smtp_out.c
+++ b/src/src/smtp_out.c
@@ -45,7 +45,7 @@ if (!istring) return TRUE;


 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);
diff --git a/src/src/spool_in.c b/src/src/spool_in.c
index 0b3490b..2d34977 100644
--- a/src/src/spool_in.c
+++ b/src/src/spool_in.c
@@ -75,7 +75,7 @@ for (i = 0; i < 2; i++)
   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"",
@@ -224,21 +224,21 @@ spool_clear_header_globals(void)
 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
@@ -255,11 +255,11 @@ sender_host_name = NULL;
 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;


@@ -270,7 +270,7 @@ bmi_verdicts = NULL;

#ifndef DISABLE_DKIM
dkim_signers = NULL;
-dkim_disable_verify = FALSE;
+f.dkim_disable_verify = FALSE;
dkim_collect_input = 0;
#endif

@@ -340,7 +340,7 @@ Returns:        spool_read_OK        success
 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;
@@ -362,7 +362,7 @@ for (n = 0; n < 2; n++)
   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;
@@ -377,7 +377,7 @@ DEBUG(D_deliver) debug_printf("reading spool file %s\n", name);
 /* 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;
@@ -389,7 +389,7 @@ negative uids and gids. The second contains the mail address of the message's
 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--;
@@ -410,7 +410,7 @@ originator_uid = (uid_t)uid;
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;
@@ -420,7 +420,7 @@ Ustrncpy(sender_address, big_buffer+1, n-3);
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;
@@ -450,7 +450,7 @@ p = big_buffer + 2;
 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'
@@ -461,7 +461,7 @@ for (;;)
     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;
@@ -488,14 +488,14 @@ for (;;)
       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);
@@ -529,7 +529,7 @@ for (;;)
       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;
@@ -547,7 +547,7 @@ for (;;)


     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);
@@ -558,7 +558,7 @@ for (;;)
     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;
       }
@@ -599,9 +599,9 @@ for (;;)


     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);
@@ -609,13 +609,13 @@ for (;;)
     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':
@@ -631,7 +631,7 @@ for (;;)


     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);
@@ -642,7 +642,7 @@ for (;;)
 #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)
@@ -701,7 +701,7 @@ host_build_sender_fullhost();


 #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 */


@@ -709,7 +709,7 @@ DEBUG(D_deliver)
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
@@ -724,7 +724,7 @@ DEBUG(D_deliver)
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;

@@ -748,7 +748,7 @@ for (recipients_count = 0; recipients_count < rcount; recipients_count++)
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;

@@ -888,17 +888,17 @@ always, in order to check on the format of the file, but only create a header
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 */


@@ -918,7 +918,7 @@ while ((n = fgetc(f)) != EOF)

     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;
@@ -930,7 +930,7 @@ while ((n = fgetc(f)) != EOF)


   else for (i = 0; i < n; i++)
     {
-    int c = fgetc(f);
+    int c = fgetc(fp);
     if (c == 0 || c == EOF) goto SPOOL_FORMAT_ERROR;
     }
   }
@@ -946,7 +946,7 @@ DEBUG(D_deliver) debug_printf("body_linecount=%d message_linecount=%d\n",


message_linecount += body_linecount;

-fclose(f);
+fclose(fp);
return spool_read_OK;


@@ -963,7 +963,7 @@ if (errno != 0)
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;
}
@@ -974,7 +974,7 @@ SPOOL_FORMAT_ERROR:
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;
 }
diff --git a/src/src/spool_mbox.c b/src/src/spool_mbox.c
index 05f90a8..2447daf 100644
--- a/src/src/spool_mbox.c
+++ b/src/src/spool_mbox.c
@@ -147,7 +147,7 @@ if (!spool_mbox_ok)
     {
     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)))
@@ -209,7 +209,7 @@ unspool_mbox(void)
 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;
diff --git a/src/src/spool_out.c b/src/src/spool_out.c
index 52f079c..d558952 100644
--- a/src/src/spool_out.c
+++ b/src/src/spool_out.c
@@ -130,7 +130,7 @@ spool_write_header(uschar *id, int where, uschar **errmsg)
int fd;
int i;
int size_correction;
-FILE *f;
+FILE * fp;
header_line *h;
struct stat statbuf;
uschar * tname;
@@ -141,7 +141,7 @@ tname = spool_fname(US"input", message_subdir,

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
@@ -150,136 +150,136 @@ identity of the submitting user, followed by the sender's address. The sender's
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;
@@ -287,7 +287,7 @@ for (i = 0; i < recipients_count; 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"";
@@ -295,7 +295,7 @@ for (i = 0; i < recipients_count; i++)
     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);
     }


@@ -306,14 +306,14 @@ for (i = 0; i < recipients_count; i++)

/* 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
@@ -326,28 +326,28 @@ size. */

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
diff --git a/src/src/store.c b/src/src/store.c
index 4e1a63e..b527991 100644
--- a/src/src/store.c
+++ b/src/src/store.c
@@ -194,7 +194,7 @@ linenumber = linenumber;
 #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,
@@ -286,7 +286,7 @@ linenumber = linenumber;
 #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,
@@ -357,7 +357,7 @@ newlength = bc + b->length - CS ptr;
 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);
@@ -411,7 +411,7 @@ linenumber = linenumber;
 #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,
@@ -462,13 +462,13 @@ for (b = chainbase[store_pool]; b; b = b->next)
     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 */


@@ -558,7 +558,7 @@ linenumber = linenumber;
/* 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,
@@ -598,7 +598,7 @@ linenumber = linenumber;
 #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);
diff --git a/src/src/tls-openssl.c b/src/src/tls-openssl.c
index 9e1fc91..53a967a 100644
--- a/src/src/tls-openssl.c
+++ b/src/src/tls-openssl.c
@@ -960,7 +960,7 @@ supply_response:
 return;


 bad:
-  if (running_in_test_harness)
+  if (f.running_in_test_harness)
     {
     extern char ** environ;
     uschar ** p;
diff --git a/src/src/tls.c b/src/src/tls.c
index f816620..b0b15f8 100644
--- a/src/src/tls.c
+++ b/src/src/tls.c
@@ -69,7 +69,7 @@ expand_check(const uschar *s, const uschar *name, uschar **result, uschar ** err
 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";
diff --git a/src/src/tlscert-gnu.c b/src/src/tlscert-gnu.c
index d34ceed..a923da1 100644
--- a/src/src/tlscert-gnu.c
+++ b/src/src/tlscert-gnu.c
@@ -113,7 +113,7 @@ if (mod && Ustrcmp(mod, "int") == 0)
   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));
diff --git a/src/src/tlscert-openssl.c b/src/src/tlscert-openssl.c
index f218322..7e0128e 100644
--- a/src/src/tlscert-openssl.c
+++ b/src/src/tlscert-openssl.c
@@ -156,7 +156,7 @@ else

     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;
diff --git a/src/src/tod.c b/src/src/tod.c
index c363845..b0d3ac9 100644
--- a/src/src/tod.c
+++ b/src/src/tod.c
@@ -84,7 +84,7 @@ if (type == tod_log) type = log_timezone ? tod_log_zone : tod_log_bare;


/* 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)
   {
@@ -148,7 +148,7 @@ switch(type)
       struct tm local;
       memcpy(&local, t, sizeof(struct tm));


-      if (timestamps_utc)
+      if (f.timestamps_utc)
     diff_hour = diff_min = 0;
       else
     {
diff --git a/src/src/transport.c b/src/src/transport.c
index d5ff738..5c72e2e 100644
--- a/src/src/transport.c
+++ b/src/src/transport.c
@@ -495,7 +495,7 @@ for (ptr = start; ptr < end; ptr++)


   if (  *ptr == '\r' && ptr[1] == '\n'
      && !(tctx->options & topt_use_crlf)
-     && spool_file_wireformat
+     && f.spool_file_wireformat
      )
     ptr++;


@@ -505,7 +505,7 @@ for (ptr = start; ptr < end; 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++;
@@ -723,7 +723,7 @@ for (h = header_list; h; h = h->next) if (h->type != htype_old)
     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;
@@ -829,7 +829,7 @@ if (tblock && (list = CUS tblock->add_headers))
       }
     }
       }
-    else if (!expand_string_forcedfail)
+    else if (!f.expand_string_forcedfail)
       { errno = ERRNO_CHHEADER_FAIL; return FALSE; }
   }


@@ -934,8 +934,8 @@ so temporarily hide the global that adjusts for its format. */

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. */

@@ -992,11 +992,11 @@ if (!(tctx->options & topt_no_headers))
   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
@@ -1025,7 +1025,7 @@ if (tctx->options & topt_use_bdat)
     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
@@ -1072,7 +1072,7 @@ This should get used for CHUNKING output and also for writing the -K file for
 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
@@ -1106,7 +1106,7 @@ DEBUG(D_transport) debug_printf("cannot use sendfile for body: no support\n");
 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");
@@ -1135,7 +1135,7 @@ if (!(tctx->options & topt_no_body))
 /* 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). */

@@ -1172,12 +1172,12 @@ BOOL
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. */
@@ -1277,7 +1277,7 @@ if (write_pid < 0)

/* 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);
@@ -1294,7 +1294,7 @@ no data is returned, that counts as "ended with NL" (default setting of the
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 (;;)
@@ -1306,7 +1306,7 @@ for (;;)
   if (sigalrm_seen)
     {
     errno = ETIMEDOUT;
-    transport_filter_timed_out = TRUE;
+    f.transport_filter_timed_out = TRUE;
     goto TIDY_UP;
     }


@@ -1334,7 +1334,7 @@ there has been an error, kill the processes before waiting for them, just to be
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);
@@ -1402,7 +1402,7 @@ filter was not NL, insert a NL to make the SMTP protocol work. */
 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)
@@ -1870,7 +1870,7 @@ but we have a number of extras that may be added. */


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";
@@ -1956,7 +1956,7 @@ if ((pid = fork()) == 0)
     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);
@@ -2247,9 +2247,9 @@ if (expand_arguments)
     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)
         {
diff --git a/src/src/transports/appendfile.c b/src/src/transports/appendfile.c
index 321dbc9..b762b66 100644
--- a/src/src/transports/appendfile.c
+++ b/src/src/transports/appendfile.c
@@ -310,7 +310,7 @@ for (i = 0; i < 5; i++)
       {
       *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);
@@ -1435,7 +1435,7 @@ DEBUG(D_transport)


/* 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",
@@ -2551,7 +2551,7 @@ else
     $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 "
@@ -2688,7 +2688,7 @@ else
       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 "
@@ -2717,7 +2717,7 @@ else
       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 "
@@ -3080,7 +3080,7 @@ if (yield != OK)
         }
       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)
diff --git a/src/src/transports/autoreply.c b/src/src/transports/autoreply.c
index c3ed169..bc38168 100644
--- a/src/src/transports/autoreply.c
+++ b/src/src/transports/autoreply.c
@@ -290,7 +290,7 @@ uschar *message_id = NULL;
 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 =
@@ -403,7 +403,7 @@ if (ob->never_mail)

/* 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",
@@ -577,14 +577,14 @@ if (pid < 0)
 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. */
@@ -596,7 +596,7 @@ if (h)
{
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:,
@@ -618,7 +618,7 @@ the position inside the thread, up to a maximum of 12 altogether. */

 if (h || message_id)
   {
-  fprintf(f, "References:");
+  fprintf(fp, "References:");
   if (h)
     {
     uschar *s, *id, *error;
@@ -627,7 +627,7 @@ if (h || message_id)
     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))
@@ -638,28 +638,28 @@ if (h || message_id)
         }
       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)
@@ -675,9 +675,9 @@ 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);
   }
@@ -694,7 +694,7 @@ if (return_message)
     :
     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,
@@ -714,23 +714,23 @@ if (return_message)
       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
diff --git a/src/src/transports/lmtp.c b/src/src/transports/lmtp.c
index e4c1a75..89c41d3 100644
--- a/src/src/transports/lmtp.c
+++ b/src/src/transports/lmtp.c
@@ -490,7 +490,7 @@ if (ob->cmd)
     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
@@ -528,7 +528,7 @@ else
     }


   /* 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;
diff --git a/src/src/transports/pipe.c b/src/src/transports/pipe.c
index 5470c72..b94c223 100644
--- a/src/src/transports/pipe.c
+++ b/src/src/transports/pipe.c
@@ -481,7 +481,7 @@ if (expand_arguments)

/* 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 && (
@@ -509,11 +509,11 @@ if (expand_arguments)
   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);
@@ -679,7 +679,7 @@ envp[envcount++] = US"SHELL=/bin/sh";
 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);

@@ -714,7 +714,7 @@ envp[envcount] = NULL;

/* 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",
@@ -814,7 +814,7 @@ bit here to let the sub-process get going, but it may still not complete. So we
 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");

@@ -837,7 +837,7 @@ if (ob->message_prefix != NULL)
   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);
@@ -881,7 +881,7 @@ if (ob->message_suffix)
   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);
@@ -920,7 +920,7 @@ if (!written_ok)
   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;
     }
@@ -986,7 +986,7 @@ if ((rc = child_close(pid, timeout)) != 0)
   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);
diff --git a/src/src/transports/queuefile.c b/src/src/transports/queuefile.c
index 652f275..cde6e53 100644
--- a/src/src/transports/queuefile.c
+++ b/src/src/transports/queuefile.c
@@ -232,7 +232,7 @@ if (  (s = dstdir,    fstat(ddfd, &dstatbuf) < 0)
   }
 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",
diff --git a/src/src/transports/smtp.c b/src/src/transports/smtp.c
index bca8c49..87bac10 100644
--- a/src/src/transports/smtp.c
+++ b/src/src/transports/smtp.c
@@ -1024,7 +1024,7 @@ smtp_auth(uschar *buffer, unsigned bufsize, address_item *addrlist, host_item *h
 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);

@@ -1054,7 +1054,7 @@ if (is_esmtp && regex_match_and_setup(regex_AUTH, buffer, 0, -1))
     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 ||
@@ -1104,7 +1104,7 @@ if (is_esmtp && regex_match_and_setup(regex_AUTH, buffer, 0, -1))
     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);
@@ -1152,7 +1152,7 @@ if (is_esmtp && regex_match_and_setup(regex_AUTH, buffer, 0, -1))


/* 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,
@@ -1171,7 +1171,7 @@ Arguments
   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
 */
@@ -1183,7 +1183,7 @@ smtp_mail_auth_str(uschar *buffer, unsigned bufsize, address_item *addrlist,
 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)
@@ -1191,7 +1191,7 @@ 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);
@@ -1204,7 +1204,7 @@ if (ob->authenticated_sender != NULL)


/* 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",
@@ -2662,7 +2662,7 @@ for (addr = sx->first_addr, address_count = 0;
   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);
@@ -2721,7 +2721,7 @@ for (addr = sx->first_addr, address_count = 0;
     }
   }      /* Loop for next address */


-tcp_out_fastopen_logged = TRUE;
+f.tcp_out_fastopen_logged = TRUE;
sx->next_addr = addr;
return 0;
}
@@ -2761,7 +2761,7 @@ if ((rc = fork()))
_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);
@@ -2835,7 +2835,7 @@ for (fd_bits = 3; fd_bits; )
}

 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
@@ -3127,7 +3127,7 @@ else
       {
       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;
@@ -3571,7 +3571,7 @@ hosts_nopass_tls. */
 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)
{
@@ -3582,7 +3582,7 @@ 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
@@ -3639,7 +3639,7 @@ if (sx.completed_addr && sx.ok && sx.send_quit)


 #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
@@ -3657,7 +3657,7 @@ if (sx.completed_addr && sx.ok && sx.send_quit)
         && 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
@@ -3677,7 +3677,7 @@ if (sx.completed_addr && sx.ok && sx.send_quit)
       }
       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
@@ -3702,7 +3702,7 @@ propagate it from the initial
       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);
@@ -4000,7 +4000,7 @@ if (!hostlist || (ob->hosts_override && ob->hosts))
         {
         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 "
@@ -4288,7 +4288,7 @@ retry_non_continued:
     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))
@@ -4452,7 +4452,7 @@ retry_non_continued:
     /* 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);
@@ -4823,7 +4823,7 @@ for (addr = addrlist; addr; addr = addr->next)
       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;
diff --git a/src/src/verify.c b/src/src/verify.c
index c92ef65..7d46c35 100644
--- a/src/src/verify.c
+++ b/src/src/verify.c
@@ -601,7 +601,7 @@ else
   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 */
@@ -1642,18 +1642,18 @@ Returns:           OK      address verified
 */


 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;
@@ -1688,8 +1688,8 @@ if (parse_find_at(address) == 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;
@@ -1700,7 +1700,7 @@ if (parse_find_at(address) == NULL)
 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
@@ -1715,7 +1715,7 @@ if (global_rewrite_rules)
     {
     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);
     }
   }


@@ -1781,29 +1781,29 @@ while (addr_new)
   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;
     }
@@ -1935,7 +1935,7 @@ while (addr_new)
       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"
@@ -1976,29 +1976,29 @@ while (addr_new)
   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");


@@ -2015,29 +2015,29 @@ while (addr_new)
   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");


@@ -2058,16 +2058,16 @@ while (addr_new)

     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;
@@ -2101,8 +2101,8 @@ while (addr_new)
       )  )
        )
       {
-      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 */
@@ -2121,7 +2121,7 @@ while (addr_new)
   }     /* 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.

@@ -2131,7 +2131,7 @@ discarded, usually because of the use of :blackhole: in an alias file. */

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;
}

@@ -2144,10 +2144,10 @@ for (addr_list = addr_local, i = 0; i < 2; addr_list = addr_remote, i++)

     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. */
@@ -2156,19 +2156,19 @@ for (addr_list = addr_local, i = 0; i < 2; addr_list = addr_remote, i++)
       {
       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
@@ -2188,20 +2188,20 @@ for (addr_list = addr_local, i = 0; i < 2; addr_list = addr_remote, i++)
         }
       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);
         }
       }
     }
@@ -2257,7 +2257,7 @@ for (h = header_list; h && yield == OK; h = h->next)
   /* 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)
     {
@@ -2280,11 +2280,11 @@ for (h = header_list; h && yield == OK; h = h->next)
       {
       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";
       }
@@ -2334,8 +2334,8 @@ for (h = header_list; h && yield == OK; h = h->next)
     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;
@@ -2417,7 +2417,7 @@ for (i = 0; i < recipients_count; i++)
     /* 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)
       {
@@ -2452,8 +2452,8 @@ for (i = 0; i < recipients_count; i++)
       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;
@@ -2554,7 +2554,7 @@ for (i = 0; i < 3 && !done; i++)
     /* 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)
       {
@@ -2672,8 +2672,8 @@ for (i = 0; i < 3 && !done; i++)
       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 */


@@ -3031,8 +3031,8 @@ if (iplookup)
     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,