Use single-bit fields for global flags
authorJeremy Harris <jgh146exb@wizmail.org>
Wed, 22 Aug 2018 19:46:11 +0000 (20:46 +0100)
committerJeremy Harris <jgh146exb@wizmail.org>
Wed, 22 Aug 2018 20:59:45 +0000 (21:59 +0100)
69 files changed:
doc/doc-txt/ChangeLog
src/exim_monitor/em_globals.c
src/exim_monitor/em_menu.c
src/exim_monitor/em_queue.c
src/src/acl.c
src/src/auths/check_serv_cond.c
src/src/auths/cram_md5.c
src/src/auths/gsasl_exim.c
src/src/auths/plaintext.c
src/src/auths/spa.c
src/src/child.c
src/src/daemon.c
src/src/debug.c
src/src/deliver.c
src/src/dkim.c
src/src/dkim_transport.c
src/src/dmarc.c
src/src/dns.c
src/src/exim.c
src/src/expand.c
src/src/filter.c
src/src/filtertest.c
src/src/globals.c
src/src/globals.h
src/src/host.c
src/src/ip.c
src/src/log.c
src/src/macros.h
src/src/malware.c
src/src/match.c
src/src/moan.c
src/src/parse.c
src/src/perl.c
src/src/queue.c
src/src/rda.c
src/src/readconf.c
src/src/receive.c
src/src/retry.c
src/src/rewrite.c
src/src/route.c
src/src/routers/dnslookup.c
src/src/routers/manualroute.c
src/src/routers/redirect.c
src/src/routers/rf_change_domain.c
src/src/routers/rf_expand_data.c
src/src/routers/rf_get_errors_address.c
src/src/routers/rf_get_munge_headers.c
src/src/routers/rf_lookup_hostlist.c
src/src/search.c
src/src/sieve.c
src/src/smtp_in.c
src/src/smtp_out.c
src/src/spool_in.c
src/src/spool_mbox.c
src/src/spool_out.c
src/src/store.c
src/src/tls-openssl.c
src/src/tls.c
src/src/tlscert-gnu.c
src/src/tlscert-openssl.c
src/src/tod.c
src/src/transport.c
src/src/transports/appendfile.c
src/src/transports/autoreply.c
src/src/transports/lmtp.c
src/src/transports/pipe.c
src/src/transports/queuefile.c
src/src/transports/smtp.c
src/src/verify.c

index 583603f..333ae73 100644 (file)
@@ -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
 -----------------
index 6ed57ef..0a4f92e 100644 (file)
@@ -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;
 
index 8e638f0..31ce1a3 100644 (file)
@@ -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);
   }
 
index fabec40..c8d9a40 100644 (file)
@@ -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)
     {
index 4f335df..d4d370f 100644 (file)
@@ -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
          {
index 96c4b56..dc299f1 100644 (file)
@@ -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;
   }
index 06c153a..b9607b1 100644 (file)
@@ -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@postoffice.reston.mci.net>";
 
 /* 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;
index 5d8769f..6611de3 100644 (file)
@@ -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;
index 21581b6..bdd0569 100644 (file)
@@ -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;
index 1ef41b5..50a4fea 100644 (file)
@@ -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);
index ad625ae..fb333d3 100644 (file)
@@ -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,
index a382a73..6678789 100644 (file)
@@ -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;
index a5cc251..35eb77c 100644 (file)
@@ -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));
index 3a39572..e316505 100644 (file)
@@ -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);
index 29ec29a..4d1822e 100644 (file)
@@ -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)
index db3db91..8ce18c8 100644 (file)
@@ -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)))
index 956c16b..a7e08c5 100644 (file)
@@ -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)
index cb17666..1da7feb 100644 (file)
@@ -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));
 
index 1410359..9a1cf8b 100644 (file)
@@ -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);
index 1508dcf..b3e918e 100644 (file)
@@ -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");
     }
   }
index 4d67f98..a16416c 100644 (file)
@@ -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");
index 7245608..f3d3acc 100644 (file)
@@ -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
   {
index ee1db4b..d834373 100644 (file)
@@ -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 */
index 5b234e2..bdf0360 100644 (file)
@@ -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 */
index 7118221..0da9933 100644 (file)
@@ -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)
     {
index d9184ef..633e0c2 100644 (file)
@@ -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;
index 6d8fdd2..2832f4e 100644 (file)
@@ -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
index 5c2b0a4..fd53de8 100644 (file)
@@ -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
index 49456de..4b28760 100644 (file)
@@ -2226,7 +2226,7 @@ sender_address = US"malware-sender@example.net";
 return_path = US"";
 recipients_list = NULL;
 receive_add_recipient(US"malware-victim@example.net", -1);
-enable_dollar_recipients = TRUE;
+f.enable_dollar_recipients = TRUE;
 
 ret = malware_internal(US"*", eml_filename, 0);
 
index 3539aaa..0c0f3e8 100644 (file)
@@ -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);
index 4e86484..c89f5c2 100644 (file)
@@ -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);
 
index 9e53120..46f9751 100644 (file)
@@ -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;
index 5239f3d..58643f0 100644 (file)
@@ -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);
 }
index 3ae2a70..9f9e409 100644 (file)
@@ -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);
+      }
     }
   }
 }
index 2d8bda8..ee7c1fe 100644 (file)
@@ -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;
index 875e032..1f0e41d 100644 (file)
@@ -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
index 7e5aac1..f7124a6 100644 (file)
@@ -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);
index fd4cbc2..a040c33 100644 (file)
@@ -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))
index 172f868..2196bfa 100644 (file)
@@ -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. */
index f50a86e..c69bdcb 100644 (file)
@@ -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;
 }
 
index a3b0d35..d6d7d06 100644 (file)
@@ -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);
index fded7af..af44706 100644 (file)
@@ -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;
index 944fb67..938db36 100644 (file)
@@ -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);
index d37220d..9f50957 100644 (file)
@@ -76,7 +76,7 @@ if (rewrite)
     if (newh != NULL)
       {
       h = newh;
-      header_rewritten = TRUE;
+      f.header_rewritten = TRUE;
       }
     }
   }
index cf5b9cb..6a8ad17 100644 (file)
@@ -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;
index 752cc95..858c806 100644 (file)
@@ -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++];
 
index f45e6eb..7f81e65 100644 (file)
@@ -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",
index acf976f..0527566 100644 (file)
@@ -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;
index 8f46c7e..e5beaf3 100644 (file)
@@ -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)
       {
index cf90819..f5329da 100644 (file)
@@ -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;
index 8405945..4267bc5 100644 (file)
@@ -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");
     }
@@